summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/9p-handle.c24
-rw-r--r--hw/9pfs/9p-local.c36
-rw-r--r--hw/9pfs/9p-proxy.c26
-rw-r--r--hw/9pfs/9p-proxy.h5
-rw-r--r--hw/9pfs/9p-synth.c219
-rw-r--r--hw/9pfs/9p-synth.h5
-rw-r--r--hw/9pfs/9p-xattr.h5
-rw-r--r--hw/9pfs/9p.c214
-rw-r--r--hw/9pfs/9p.h30
-rw-r--r--hw/9pfs/codir.c13
-rw-r--r--hw/9pfs/cofile.c3
-rw-r--r--hw/9pfs/cofs.c3
-rw-r--r--hw/9pfs/coth.c5
-rw-r--r--hw/9pfs/coth.h11
-rw-r--r--hw/9pfs/coxattr.c3
-rw-r--r--hw/9pfs/trace-events47
-rw-r--r--hw/9pfs/virtio-9p-device.c16
-rw-r--r--hw/9pfs/virtio-9p.h4
-rw-r--r--hw/acpi/Makefile.objs4
-rw-r--r--hw/acpi/acpi_interface.c9
-rw-r--r--hw/acpi/aml-build.c98
-rw-r--r--hw/acpi/bios-linker-loader.c180
-rw-r--r--hw/acpi/core.c16
-rw-r--r--hw/acpi/cpu.c561
-rw-r--r--hw/acpi/cpu_hotplug.c267
-rw-r--r--hw/acpi/cpu_hotplug_acpi_table.c136
-rw-r--r--hw/acpi/ich9.c103
-rw-r--r--hw/acpi/ipmi.c105
-rw-r--r--hw/acpi/memory_hotplug.c12
-rw-r--r--hw/acpi/nvdimm.c442
-rw-r--r--hw/acpi/pcihp.c10
-rw-r--r--hw/acpi/piix4.c93
-rw-r--r--hw/acpi/trace-events32
-rw-r--r--hw/alpha/alpha_sys.h5
-rw-r--r--hw/alpha/pci.c1
-rw-r--r--hw/alpha/trace-events4
-rw-r--r--hw/alpha/typhoon.c2
-rw-r--r--hw/arm/Makefile.objs1
-rw-r--r--hw/arm/armv7m.c11
-rw-r--r--hw/arm/ast2400.c76
-rw-r--r--hw/arm/bcm2835_peripherals.c16
-rw-r--r--hw/arm/boot.c43
-rw-r--r--hw/arm/collie.c1
-rw-r--r--hw/arm/digic.c2
-rw-r--r--hw/arm/fsl-imx25.c11
-rw-r--r--hw/arm/fsl-imx31.c11
-rw-r--r--hw/arm/fsl-imx6.c466
-rw-r--r--hw/arm/highbank.c15
-rw-r--r--hw/arm/integratorcp.c37
-rw-r--r--hw/arm/musicpal.c2
-rw-r--r--hw/arm/nseries.c8
-rw-r--r--hw/arm/palmetto-bmc.c34
-rw-r--r--hw/arm/pxa2xx.c38
-rw-r--r--hw/arm/pxa2xx_gpio.c2
-rw-r--r--hw/arm/pxa2xx_pic.c7
-rw-r--r--hw/arm/realview.c11
-rw-r--r--hw/arm/sabrelite.c127
-rw-r--r--hw/arm/spitz.c35
-rw-r--r--hw/arm/stellaris.c55
-rw-r--r--hw/arm/stm32f205_soc.c2
-rw-r--r--hw/arm/strongarm.c67
-rw-r--r--hw/arm/strongarm.h5
-rw-r--r--hw/arm/tosa.c5
-rw-r--r--hw/arm/trace-events4
-rw-r--r--hw/arm/versatilepb.c24
-rw-r--r--hw/arm/vexpress.c9
-rw-r--r--hw/arm/virt-acpi-build.c110
-rw-r--r--hw/arm/virt.c183
-rw-r--r--hw/arm/xilinx_zynq.c19
-rw-r--r--hw/arm/xlnx-ep108.c18
-rw-r--r--hw/arm/xlnx-zynqmp.c154
-rw-r--r--hw/arm/z2.c6
-rw-r--r--hw/audio/cs4231.c12
-rw-r--r--hw/audio/fmopl.h4
-rw-r--r--hw/audio/gus.c2
-rw-r--r--hw/audio/gusemu.h2
-rw-r--r--hw/audio/gustate.h2
-rw-r--r--hw/audio/intel-hda.c66
-rw-r--r--hw/audio/lm4549.h2
-rw-r--r--hw/audio/milkymist-ac97.c28
-rw-r--r--hw/audio/pcspk.c11
-rw-r--r--hw/audio/pl041.c1
-rw-r--r--hw/audio/pl041.h2
-rw-r--r--hw/audio/trace-events19
-rw-r--r--hw/block/block.c28
-rw-r--r--hw/block/dataplane/virtio-blk.c146
-rw-r--r--hw/block/dataplane/virtio-blk.h2
-rw-r--r--hw/block/fdc.c25
-rw-r--r--hw/block/hd-geometry.c3
-rw-r--r--hw/block/m25p80.c490
-rw-r--r--hw/block/nand.c36
-rw-r--r--hw/block/nvme.c76
-rw-r--r--hw/block/onenand.c41
-rw-r--r--hw/block/pflash_cfi01.c14
-rw-r--r--hw/block/pflash_cfi02.c13
-rw-r--r--hw/block/tc58128.c2
-rw-r--r--hw/block/trace-events17
-rw-r--r--hw/block/virtio-blk.c116
-rw-r--r--hw/block/xen_blkif.h173
-rw-r--r--hw/block/xen_disk.c20
-rw-r--r--hw/bt/hci-csr.c68
-rw-r--r--hw/bt/hci.c10
-rw-r--r--hw/bt/l2cap.c13
-rw-r--r--hw/bt/sdp.c1
-rw-r--r--hw/char/bcm2835_aux.c1
-rw-r--r--hw/char/cadence_uart.c33
-rw-r--r--hw/char/digic-uart.c11
-rw-r--r--hw/char/escc.c38
-rw-r--r--hw/char/etraxfs_ser.c27
-rw-r--r--hw/char/imx_serial.c1
-rw-r--r--hw/char/ipoctal232.c2
-rw-r--r--hw/char/lm32_juart.c17
-rw-r--r--hw/char/lm32_uart.c28
-rw-r--r--hw/char/milkymist-uart.c12
-rw-r--r--hw/char/pl011.c12
-rw-r--r--hw/char/sclpconsole-lm.c14
-rw-r--r--hw/char/sclpconsole.c14
-rw-r--r--hw/char/serial.c67
-rw-r--r--hw/char/stm32f2xx_usart.c16
-rw-r--r--hw/char/trace-events49
-rw-r--r--hw/char/virtio-console.c25
-rw-r--r--hw/char/virtio-serial-bus.c62
-rw-r--r--hw/char/xen_console.c1
-rw-r--r--hw/char/xilinx_uartlite.c10
-rw-r--r--hw/core/Makefile.objs4
-rw-r--r--hw/core/bus.c251
-rw-r--r--hw/core/hotplug.c11
-rw-r--r--hw/core/loader.c6
-rw-r--r--hw/core/machine.c70
-rw-r--r--hw/core/nmi.c19
-rw-r--r--hw/core/ptimer.c83
-rw-r--r--hw/core/qdev-properties-system.c75
-rw-r--r--hw/core/qdev-properties.c42
-rw-r--r--hw/core/qdev.c278
-rw-r--r--hw/core/register.c287
-rw-r--r--hw/core/sysbus.c4
-rw-r--r--hw/core/uboot_image.h6
-rw-r--r--hw/cpu/Makefile.objs1
-rw-r--r--hw/cpu/a9mpcore.c1
-rw-r--r--hw/cpu/core.c88
-rw-r--r--hw/cris/axis_dev88.c4
-rw-r--r--hw/cris/boot.h4
-rw-r--r--hw/display/Makefile.objs2
-rw-r--r--hw/display/ads7846.c5
-rw-r--r--hw/display/bcm2835_fb.c1
-rw-r--r--hw/display/blizzard.c120
-rw-r--r--hw/display/blizzard_template.h146
-rw-r--r--hw/display/cg3.c2
-rw-r--r--hw/display/dpcd.c173
-rw-r--r--hw/display/exynos4210_fimd.c19
-rw-r--r--hw/display/jazz_led.c18
-rw-r--r--hw/display/milkymist-tmu2.c27
-rw-r--r--hw/display/milkymist-vgafb.c18
-rw-r--r--hw/display/omap_lcd_template.h10
-rw-r--r--hw/display/omap_lcdc.c48
-rw-r--r--hw/display/pl110.c1
-rw-r--r--hw/display/qxl.c127
-rw-r--r--hw/display/qxl.h9
-rw-r--r--hw/display/ssd0323.c5
-rw-r--r--hw/display/tc6393xb.c1
-rw-r--r--hw/display/trace-events122
-rw-r--r--hw/display/vga.c4
-rw-r--r--hw/display/vga.h6
-rw-r--r--hw/display/vga_int.h5
-rw-r--r--hw/display/virtio-gpu-3d.c14
-rw-r--r--hw/display/virtio-gpu-pci.c4
-rw-r--r--hw/display/virtio-gpu.c251
-rw-r--r--hw/display/virtio-vga.c24
-rw-r--r--hw/display/xenfb.c5
-rw-r--r--hw/display/xlnx_dp.c1338
-rw-r--r--hw/dma/Makefile.objs2
-rw-r--r--hw/dma/bcm2835_dma.c1
-rw-r--r--hw/dma/pl080.c1
-rw-r--r--hw/dma/pl330.c1
-rw-r--r--hw/dma/pxa2xx_dma.c38
-rw-r--r--hw/dma/rc4030.c1
-rw-r--r--hw/dma/trace-events32
-rw-r--r--hw/dma/xlnx-zynq-devcfg.c400
-rw-r--r--hw/dma/xlnx_dpdma.c786
-rw-r--r--hw/gpio/gpio_key.c1
-rw-r--r--hw/gpio/imx_gpio.c1
-rw-r--r--hw/gpio/omap_gpio.c61
-rw-r--r--hw/gpio/pl061.c25
-rw-r--r--hw/gpio/zaurus.c14
-rw-r--r--hw/i2c/Makefile.objs2
-rw-r--r--hw/i2c/aspeed_i2c.c440
-rw-r--r--hw/i2c/bitbang_i2c.c14
-rw-r--r--hw/i2c/core.c165
-rw-r--r--hw/i2c/exynos4210_i2c.c13
-rw-r--r--hw/i2c/i2c-ddc.c308
-rw-r--r--hw/i2c/imx_i2c.c1
-rw-r--r--hw/i2c/omap_i2c.c42
-rw-r--r--hw/i2c/smbus_ich9.c1
-rw-r--r--hw/i2c/versatile_i2c.c20
-rw-r--r--hw/i386/Makefile.objs2
-rw-r--r--hw/i386/acpi-build.c559
-rw-r--r--hw/i386/intel_iommu.c461
-rw-r--r--hw/i386/intel_iommu_internal.h50
-rw-r--r--hw/i386/kvm/apic.c11
-rw-r--r--hw/i386/kvm/clock.c1
-rw-r--r--hw/i386/kvm/i8254.c2
-rw-r--r--hw/i386/kvm/pci-assign.c29
-rw-r--r--hw/i386/kvmvapic.c8
-rw-r--r--hw/i386/pc.c458
-rw-r--r--hw/i386/pc_piix.c126
-rw-r--r--hw/i386/pc_q35.c50
-rw-r--r--hw/i386/trace-events15
-rw-r--r--hw/i386/x86-iommu.c128
-rw-r--r--hw/ide/ahci.c20
-rw-r--r--hw/ide/ahci.h405
-rw-r--r--hw/ide/atapi.c19
-rw-r--r--hw/ide/cmd646.c10
-rw-r--r--hw/ide/core.c68
-rw-r--r--hw/ide/ich.c21
-rw-r--r--hw/ide/internal.h635
-rw-r--r--hw/ide/isa.c8
-rw-r--r--hw/ide/macio.c66
-rw-r--r--hw/ide/microdrive.c8
-rw-r--r--hw/ide/mmio.c2
-rw-r--r--hw/ide/pci.c10
-rw-r--r--hw/ide/pci.h76
-rw-r--r--hw/ide/piix.c10
-rw-r--r--hw/ide/qdev.c10
-rw-r--r--hw/ide/via.c10
-rw-r--r--hw/input/hid.c3
-rw-r--r--hw/input/pckbd.c21
-rw-r--r--hw/input/pl050.c1
-rw-r--r--hw/input/trace-events31
-rw-r--r--hw/input/virtio-input.c40
-rw-r--r--hw/intc/Makefile.objs6
-rw-r--r--hw/intc/allwinner-a10-pic.c1
-rw-r--r--hw/intc/apic.c28
-rw-r--r--hw/intc/apic_common.c35
-rw-r--r--hw/intc/arm_gic.c81
-rw-r--r--hw/intc/arm_gic_kvm.c2
-rw-r--r--hw/intc/arm_gicv2m.c2
-rw-r--r--hw/intc/arm_gicv3.c400
-rw-r--r--hw/intc/arm_gicv3_common.c225
-rw-r--r--hw/intc/arm_gicv3_cpuif.c1348
-rw-r--r--hw/intc/arm_gicv3_dist.c880
-rw-r--r--hw/intc/arm_gicv3_kvm.c8
-rw-r--r--hw/intc/arm_gicv3_redist.c567
-rw-r--r--hw/intc/armv7m_nvic.c10
-rw-r--r--hw/intc/aspeed_vic.c2
-rw-r--r--hw/intc/bcm2835_ic.c1
-rw-r--r--hw/intc/bcm2836_control.c1
-rw-r--r--hw/intc/etraxfs_pic.c13
-rw-r--r--hw/intc/exynos4210_combiner.c14
-rw-r--r--hw/intc/exynos4210_gic.c39
-rw-r--r--hw/intc/gic_internal.h2
-rw-r--r--hw/intc/gicv3_internal.h331
-rw-r--r--hw/intc/grlib_irqmp.c27
-rw-r--r--hw/intc/i8259.c1
-rw-r--r--hw/intc/imx_avic.c16
-rw-r--r--hw/intc/ioapic.c203
-rw-r--r--hw/intc/lm32_pic.c12
-rw-r--r--hw/intc/mips_gic.c460
-rw-r--r--hw/intc/omap_intc.c64
-rw-r--r--hw/intc/openpic.c1
-rw-r--r--hw/intc/openpic_kvm.c2
-rw-r--r--hw/intc/pl190.c14
-rw-r--r--hw/intc/s390_flic.c8
-rw-r--r--hw/intc/s390_flic_kvm.c33
-rw-r--r--hw/intc/slavio_intctl.c14
-rw-r--r--hw/intc/trace-events123
-rw-r--r--hw/intc/xics.c556
-rw-r--r--hw/intc/xics_kvm.c72
-rw-r--r--hw/intc/xics_spapr.c434
-rw-r--r--hw/ipack/ipack.c2
-rw-r--r--hw/ipack/tpci200.c2
-rw-r--r--hw/ipmi/ipmi.c34
-rw-r--r--hw/ipmi/ipmi_bmc_extern.c2
-rw-r--r--hw/ipmi/isa_ipmi_bt.c57
-rw-r--r--hw/ipmi/isa_ipmi_kcs.c56
-rw-r--r--hw/isa/isa-bus.c7
-rw-r--r--hw/isa/lpc_ich9.c129
-rw-r--r--hw/isa/trace-events9
-rw-r--r--hw/lm32/lm32.h21
-rw-r--r--hw/lm32/lm32_boards.c9
-rw-r--r--hw/lm32/milkymist-hw.h14
-rw-r--r--hw/lm32/milkymist.c8
-rw-r--r--hw/mem/nvdimm.c133
-rw-r--r--hw/mem/pc-dimm.c40
-rw-r--r--hw/microblaze/boot.h6
-rw-r--r--hw/microblaze/petalogix_ml605_mmu.c9
-rw-r--r--hw/microblaze/petalogix_s3adsp1800_mmu.c5
-rw-r--r--hw/mips/cps.c34
-rw-r--r--hw/mips/cputimer.c4
-rw-r--r--hw/mips/gt64xxx_pci.c2
-rw-r--r--hw/mips/mips_fulong2e.c4
-rw-r--r--hw/mips/mips_int.c3
-rw-r--r--hw/mips/mips_jazz.c4
-rw-r--r--hw/mips/mips_malta.c11
-rw-r--r--hw/mips/mips_mipssim.c4
-rw-r--r--hw/mips/mips_r4k.c4
-rw-r--r--hw/misc/Makefile.objs3
-rw-r--r--hw/misc/arm11scu.c1
-rw-r--r--hw/misc/arm_integrator_debug.c1
-rw-r--r--hw/misc/arm_l2x0.c12
-rw-r--r--hw/misc/arm_sysctl.c1
-rw-r--r--hw/misc/aspeed_scu.c282
-rw-r--r--hw/misc/auxbus.c292
-rw-r--r--hw/misc/bcm2835_mbox.c1
-rw-r--r--hw/misc/bcm2835_property.c34
-rw-r--r--hw/misc/exynos4210_pmu.c11
-rw-r--r--hw/misc/hyperv_testdev.c2
-rw-r--r--hw/misc/imx25_ccm.c1
-rw-r--r--hw/misc/imx31_ccm.c1
-rw-r--r--hw/misc/imx6_ccm.c7
-rw-r--r--hw/misc/imx6_src.c265
-rw-r--r--hw/misc/imx_ccm.c1
-rw-r--r--hw/misc/ivshmem.c25
-rw-r--r--hw/misc/macio/cuda.c1
-rw-r--r--hw/misc/macio/mac_dbdma.c135
-rw-r--r--hw/misc/max111x.c12
-rw-r--r--hw/misc/milkymist-hpdmc.c2
-rw-r--r--hw/misc/milkymist-pfpu.c2
-rw-r--r--hw/misc/mips_cmgcr.c88
-rw-r--r--hw/misc/mips_cpc.c7
-rw-r--r--hw/misc/mips_itu.c3
-rw-r--r--hw/misc/mst_fpga.c13
-rw-r--r--hw/misc/pc-testdev.c3
-rw-r--r--hw/misc/pci-testdev.c1
-rw-r--r--hw/misc/stm32f2xx_syscfg.c1
-rw-r--r--hw/misc/trace-events55
-rw-r--r--hw/misc/vmport.c1
-rw-r--r--hw/misc/zynq-xadc.c1
-rw-r--r--hw/misc/zynq_slcr.c1
-rw-r--r--hw/net/Makefile.objs6
-rw-r--r--hw/net/allwinner_emac.c3
-rw-r--r--hw/net/cadence_gem.c15
-rw-r--r--hw/net/dp8393x.c2
-rw-r--r--hw/net/e1000.c437
-rw-r--r--hw/net/e1000_regs.h356
-rw-r--r--hw/net/e1000e.c711
-rw-r--r--hw/net/e1000e_core.c3483
-rw-r--r--hw/net/e1000e_core.h146
-rw-r--r--hw/net/e1000x_common.c267
-rw-r--r--hw/net/e1000x_common.h213
-rw-r--r--hw/net/eepro100.c10
-rw-r--r--hw/net/etraxfs_eth.c2
-rw-r--r--hw/net/fsl_etsec/etsec.c3
-rw-r--r--hw/net/fsl_etsec/etsec.h7
-rw-r--r--hw/net/fsl_etsec/registers.h6
-rw-r--r--hw/net/fsl_etsec/rings.c2
-rw-r--r--hw/net/imx_fec.c1010
-rw-r--r--hw/net/lan9118.c3
-rw-r--r--hw/net/lance.c2
-rw-r--r--hw/net/mcf_fec.c2
-rw-r--r--hw/net/milkymist-minimac2.c2
-rw-r--r--hw/net/mipsnet.c10
-rw-r--r--hw/net/ne2000-isa.c6
-rw-r--r--hw/net/ne2000.c2
-rw-r--r--hw/net/ne2000.h2
-rw-r--r--hw/net/net_rx_pkt.c600
-rw-r--r--hw/net/net_rx_pkt.h363
-rw-r--r--hw/net/net_tx_pkt.h190
-rw-r--r--hw/net/opencores_eth.c46
-rw-r--r--hw/net/pcnet-pci.c2
-rw-r--r--hw/net/pcnet.h2
-rw-r--r--hw/net/rocker/rocker.h6
-rw-r--r--hw/net/rocker/rocker_desc.h5
-rw-r--r--hw/net/rocker/rocker_fp.c2
-rw-r--r--hw/net/rocker/rocker_fp.h6
-rw-r--r--hw/net/rocker/rocker_hw.h6
-rw-r--r--hw/net/rocker/rocker_of_dpa.c5
-rw-r--r--hw/net/rocker/rocker_of_dpa.h6
-rw-r--r--hw/net/rocker/rocker_tlv.h10
-rw-r--r--hw/net/rocker/rocker_world.h6
-rw-r--r--hw/net/rtl8139.c56
-rw-r--r--hw/net/smc91c111.c2
-rw-r--r--hw/net/spapr_llan.c56
-rw-r--r--hw/net/stellaris_enet.c2
-rw-r--r--hw/net/trace-events272
-rw-r--r--hw/net/vhost_net.c85
-rw-r--r--hw/net/virtio-net.c114
-rw-r--r--hw/net/vmware_utils.h55
-rw-r--r--hw/net/vmxnet3.c395
-rw-r--r--hw/net/vmxnet3.h4
-rw-r--r--hw/net/vmxnet_debug.h9
-rw-r--r--hw/net/vmxnet_rx_pkt.c187
-rw-r--r--hw/net/vmxnet_rx_pkt.h174
-rw-r--r--hw/net/vmxnet_tx_pkt.c (renamed from hw/net/net_tx_pkt.c)362
-rw-r--r--hw/net/vmxnet_tx_pkt.h146
-rw-r--r--hw/net/xen_nic.c3
-rw-r--r--hw/net/xgmac.c2
-rw-r--r--hw/net/xilinx_axienet.c2
-rw-r--r--hw/net/xilinx_ethlite.c6
-rw-r--r--hw/nvram/fw_cfg.c28
-rw-r--r--hw/nvram/spapr_nvram.c25
-rw-r--r--hw/nvram/trace-events10
-rw-r--r--hw/pci-bridge/dec.h4
-rw-r--r--hw/pci-bridge/ioh3420.c23
-rw-r--r--hw/pci-bridge/pci_bridge_dev.c35
-rw-r--r--hw/pci-bridge/pci_expander_bridge.c56
-rw-r--r--hw/pci-bridge/xio3130_downstream.c21
-rw-r--r--hw/pci-bridge/xio3130_upstream.c19
-rw-r--r--hw/pci-bridge/xio3130_upstream.h2
-rw-r--r--hw/pci-host/apb.c21
-rw-r--r--hw/pci-host/grackle.c2
-rw-r--r--hw/pci-host/piix.c32
-rw-r--r--hw/pci-host/prep.c1
-rw-r--r--hw/pci-host/q35.c92
-rw-r--r--hw/pci-host/uninorth.c5
-rw-r--r--hw/pci-host/versatile.c2
-rw-r--r--hw/pci/msi.c27
-rw-r--r--hw/pci/msix.c2
-rw-r--r--hw/pci/pci.c171
-rw-r--r--hw/pci/pcie.c95
-rw-r--r--hw/pci/pcie_aer.c1
-rw-r--r--hw/pci/trace-events9
-rw-r--r--hw/ppc/Makefile.objs2
-rw-r--r--hw/ppc/e500.c2
-rw-r--r--hw/ppc/e500.h2
-rw-r--r--hw/ppc/e500plat.c1
-rw-r--r--hw/ppc/mac.h7
-rw-r--r--hw/ppc/mac_newworld.c1
-rw-r--r--hw/ppc/mac_oldworld.c2
-rw-r--r--hw/ppc/ppc.c65
-rw-r--r--hw/ppc/ppc405.h6
-rw-r--r--hw/ppc/ppc4xx_devs.c1
-rw-r--r--hw/ppc/ppce500_spin.c9
-rw-r--r--hw/ppc/prep.c3
-rw-r--r--hw/ppc/spapr.c373
-rw-r--r--hw/ppc/spapr_cpu_core.c432
-rw-r--r--hw/ppc/spapr_drc.c25
-rw-r--r--hw/ppc/spapr_events.c11
-rw-r--r--hw/ppc/spapr_hcall.c90
-rw-r--r--hw/ppc/spapr_iommu.c211
-rw-r--r--hw/ppc/spapr_pci.c123
-rw-r--r--hw/ppc/spapr_pci_vfio.c7
-rw-r--r--hw/ppc/spapr_rtas.c26
-rw-r--r--hw/ppc/spapr_rtas_ddw.c295
-rw-r--r--hw/ppc/spapr_vio.c18
-rw-r--r--hw/ppc/trace-events43
-rw-r--r--hw/ppc/virtex_ml507.c1
-rw-r--r--hw/s390x/Makefile.objs2
-rw-r--r--hw/s390x/ccw-device.c27
-rw-r--r--hw/s390x/ccw-device.h43
-rw-r--r--hw/s390x/css-bridge.c148
-rw-r--r--hw/s390x/css.c278
-rw-r--r--hw/s390x/css.h126
-rw-r--r--hw/s390x/ipl.c91
-rw-r--r--hw/s390x/ipl.h97
-rw-r--r--hw/s390x/s390-pci-bus.c608
-rw-r--r--hw/s390x/s390-pci-bus.h98
-rw-r--r--hw/s390x/s390-pci-inst.c349
-rw-r--r--hw/s390x/s390-pci-inst.h20
-rw-r--r--hw/s390x/s390-skeys.c27
-rw-r--r--hw/s390x/s390-virtio-ccw.c65
-rw-r--r--hw/s390x/s390-virtio.h2
-rw-r--r--hw/s390x/sclp.c4
-rw-r--r--hw/s390x/sclpquiesce.c2
-rw-r--r--hw/s390x/trace-events15
-rw-r--r--hw/s390x/virtio-ccw.c457
-rw-r--r--hw/s390x/virtio-ccw.h39
-rw-r--r--hw/scsi/esp.c5
-rw-r--r--hw/scsi/megasas.c70
-rw-r--r--hw/scsi/mfi.h6
-rw-r--r--hw/scsi/mptsas.c38
-rw-r--r--hw/scsi/mptsas.h3
-rw-r--r--hw/scsi/scsi-bus.c41
-rw-r--r--hw/scsi/scsi-disk.c468
-rw-r--r--hw/scsi/scsi-generic.c21
-rw-r--r--hw/scsi/trace-events204
-rw-r--r--hw/scsi/vhost-scsi.c6
-rw-r--r--hw/scsi/virtio-scsi-dataplane.c15
-rw-r--r--hw/scsi/virtio-scsi.c110
-rw-r--r--hw/scsi/vmw_pvscsi.c17
-rw-r--r--hw/sd/milkymist-memcard.c2
-rw-r--r--hw/sd/pl181.c27
-rw-r--r--hw/sd/sd.c52
-rw-r--r--hw/sd/sdhci.c1
-rw-r--r--hw/sd/ssi-sd.c9
-rw-r--r--hw/sd/trace-events5
-rw-r--r--hw/sh4/sh7750.c1
-rw-r--r--hw/sh4/sh7750_regnames.h6
-rw-r--r--hw/sh4/sh7750_regs.h4
-rw-r--r--hw/sh4/sh_pci.c4
-rw-r--r--hw/smbios/Makefile.objs1
-rw-r--r--hw/smbios/smbios.c72
-rw-r--r--hw/smbios/smbios_build.h87
-rw-r--r--hw/smbios/smbios_type_38.c117
-rw-r--r--hw/sparc/leon3.c6
-rw-r--r--hw/sparc/sun4m.c2
-rw-r--r--hw/sparc/trace-events11
-rw-r--r--hw/ssi/Makefile.objs2
-rw-r--r--hw/ssi/aspeed_smc.c469
-rw-r--r--hw/ssi/imx_spi.c455
-rw-r--r--hw/ssi/pl022.c1
-rw-r--r--hw/ssi/ssi.c6
-rw-r--r--hw/timer/Makefile.objs1
-rw-r--r--hw/timer/allwinner-a10-pit.c1
-rw-r--r--hw/timer/arm_timer.c1
-rw-r--r--hw/timer/aspeed_timer.c139
-rw-r--r--hw/timer/digic-timer.c1
-rw-r--r--hw/timer/imx_epit.c1
-rw-r--r--hw/timer/imx_gpt.c70
-rw-r--r--hw/timer/lm32_timer.c19
-rw-r--r--hw/timer/mc146818rtc.c11
-rw-r--r--hw/timer/milkymist-sysctl.c23
-rw-r--r--hw/timer/mips_gictimer.c142
-rw-r--r--hw/timer/omap_gptimer.c4
-rw-r--r--hw/timer/pl031.c1
-rw-r--r--hw/timer/stm32f2xx_timer.c1
-rw-r--r--hw/timer/trace-events51
-rw-r--r--hw/tpm/tpm_util.h7
-rw-r--r--hw/usb/Makefile.objs4
-rw-r--r--hw/usb/bus.c58
-rw-r--r--hw/usb/desc.c1
-rw-r--r--hw/usb/dev-mtp.c4
-rw-r--r--hw/usb/dev-network.c67
-rw-r--r--hw/usb/dev-storage.c52
-rw-r--r--hw/usb/dev-uas.c5
-rw-r--r--hw/usb/hcd-ehci.c31
-rw-r--r--hw/usb/hcd-ehci.h5
-rw-r--r--hw/usb/hcd-ohci.c2
-rw-r--r--hw/usb/hcd-xhci.c42
-rw-r--r--hw/usb/host-libusb.c79
-rw-r--r--hw/usb/redirect.c12
-rw-r--r--hw/usb/trace-events268
-rw-r--r--hw/usb/xen-usb.c1107
-rw-r--r--hw/vfio/Makefile.objs1
-rw-r--r--hw/vfio/common.c328
-rw-r--r--hw/vfio/pci-quirks.c643
-rw-r--r--hw/vfio/pci.c273
-rw-r--r--hw/vfio/pci.h8
-rw-r--r--hw/vfio/platform.c2
-rw-r--r--hw/vfio/spapr.c209
-rw-r--r--hw/vfio/trace-events125
-rw-r--r--hw/virtio/trace-events16
-rw-r--r--hw/virtio/vhost-backend.c13
-rw-r--r--hw/virtio/vhost-user.c124
-rw-r--r--hw/virtio/vhost.c213
-rw-r--r--hw/virtio/virtio-balloon.c38
-rw-r--r--hw/virtio/virtio-bus.c126
-rw-r--r--hw/virtio/virtio-mmio.c177
-rw-r--r--hw/virtio/virtio-pci.c172
-rw-r--r--hw/virtio/virtio-pci.h21
-rw-r--r--hw/virtio/virtio-rng.c20
-rw-r--r--hw/virtio/virtio.c79
-rw-r--r--hw/watchdog/watchdog.c2
-rw-r--r--hw/watchdog/wdt_diag288.c1
-rw-r--r--hw/xen/xen-host-pci-device.h2
-rw-r--r--hw/xen/xen_backend.c173
-rw-r--r--hw/xen/xen_devconfig.c52
-rw-r--r--hw/xen/xen_pt.h2
-rw-r--r--hw/xen/xen_pt_config_init.c5
-rw-r--r--hw/xen/xen_pt_msi.c1
-rw-r--r--hw/xenpv/xen_domainbuild.h2
-rw-r--r--hw/xenpv/xen_machine_pv.c4
-rw-r--r--hw/xtensa/bootparam.h4
-rw-r--r--hw/xtensa/pic_cpu.c5
-rw-r--r--hw/xtensa/xtfpga.c2
554 files changed, 9437 insertions, 36439 deletions
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 3d77594f9..894041488 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -112,7 +112,7 @@ static int handle_close(FsContext *ctx, V9fsFidOpenState *fs)
static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return closedir(fs->dir.stream);
+ return closedir(fs->dir);
}
static int handle_open(FsContext *ctx, V9fsPath *fs_path,
@@ -132,8 +132,8 @@ static int handle_opendir(FsContext *ctx,
if (ret < 0) {
return -1;
}
- fs->dir.stream = fdopendir(ret);
- if (!fs->dir.stream) {
+ fs->dir = fdopendir(ret);
+ if (!fs->dir) {
return -1;
}
return 0;
@@ -141,22 +141,24 @@ static int handle_opendir(FsContext *ctx,
static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
{
- rewinddir(fs->dir.stream);
+ rewinddir(fs->dir);
}
static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return telldir(fs->dir.stream);
+ return telldir(fs->dir);
}
-static struct dirent *handle_readdir(FsContext *ctx, V9fsFidOpenState *fs)
+static int handle_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
+ struct dirent *entry,
+ struct dirent **result)
{
- return readdir(fs->dir.stream);
+ return readdir_r(fs->dir, entry, result);
}
static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
{
- seekdir(fs->dir.stream, off);
+ seekdir(fs->dir, off);
}
static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs,
@@ -260,7 +262,7 @@ static int handle_fstat(FsContext *fs_ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
+ fd = dirfd(fs->dir);
} else {
fd = fs->fd;
}
@@ -407,7 +409,7 @@ static int handle_fsync(FsContext *ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
+ fd = dirfd(fs->dir);
} else {
fd = fs->fd;
}
@@ -679,7 +681,7 @@ FileOperations handle_ops = {
.opendir = handle_opendir,
.rewinddir = handle_rewinddir,
.telldir = handle_telldir,
- .readdir = handle_readdir,
+ .readdir_r = handle_readdir_r,
.seekdir = handle_seekdir,
.preadv = handle_preadv,
.pwritev = handle_pwritev,
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 3f271fcbd..16f45f485 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -348,7 +348,7 @@ static int local_close(FsContext *ctx, V9fsFidOpenState *fs)
static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return closedir(fs->dir.stream);
+ return closedir(fs->dir);
}
static int local_open(FsContext *ctx, V9fsPath *fs_path,
@@ -370,9 +370,9 @@ static int local_opendir(FsContext *ctx,
char *path = fs_path->data;
buffer = rpath(ctx, path);
- fs->dir.stream = opendir(buffer);
+ fs->dir = opendir(buffer);
g_free(buffer);
- if (!fs->dir.stream) {
+ if (!fs->dir) {
return -1;
}
return 0;
@@ -380,40 +380,38 @@ static int local_opendir(FsContext *ctx,
static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
{
- rewinddir(fs->dir.stream);
+ rewinddir(fs->dir);
}
static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return telldir(fs->dir.stream);
+ return telldir(fs->dir);
}
-static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs)
+static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
+ struct dirent *entry,
+ struct dirent **result)
{
- struct dirent *entry;
+ int ret;
again:
- entry = readdir(fs->dir.stream);
- if (!entry) {
- return NULL;
- }
-
+ ret = readdir_r(fs->dir, entry, result);
if (ctx->export_flags & V9FS_SM_MAPPED) {
entry->d_type = DT_UNKNOWN;
} else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- if (!strcmp(entry->d_name, VIRTFS_META_DIR)) {
+ if (!ret && *result != NULL &&
+ !strcmp(entry->d_name, VIRTFS_META_DIR)) {
/* skp the meta data directory */
goto again;
}
entry->d_type = DT_UNKNOWN;
}
-
- return entry;
+ return ret;
}
static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
{
- seekdir(fs->dir.stream, off);
+ seekdir(fs->dir, off);
}
static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs,
@@ -612,7 +610,7 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
int err, fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
+ fd = dirfd(fs->dir);
} else {
fd = fs->fd;
}
@@ -1000,7 +998,7 @@ static int local_fsync(FsContext *ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
+ fd = dirfd(fs->dir);
} else {
fd = fs->fd;
}
@@ -1256,7 +1254,7 @@ FileOperations local_ops = {
.opendir = local_opendir,
.rewinddir = local_rewinddir,
.telldir = local_telldir,
- .readdir = local_readdir,
+ .readdir_r = local_readdir_r,
.seekdir = local_seekdir,
.preadv = local_preadv,
.pwritev = local_pwritev,
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index f265501ea..00a4eb2a7 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -633,7 +633,7 @@ static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return closedir(fs->dir.stream);
+ return closedir(fs->dir);
}
static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
@@ -652,14 +652,14 @@ static int proxy_opendir(FsContext *ctx,
{
int serrno, fd;
- fs->dir.stream = NULL;
+ fs->dir = NULL;
fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, O_DIRECTORY);
if (fd < 0) {
errno = -fd;
return -1;
}
- fs->dir.stream = fdopendir(fd);
- if (!fs->dir.stream) {
+ fs->dir = fdopendir(fd);
+ if (!fs->dir) {
serrno = errno;
close(fd);
errno = serrno;
@@ -670,22 +670,24 @@ static int proxy_opendir(FsContext *ctx,
static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
{
- rewinddir(fs->dir.stream);
+ rewinddir(fs->dir);
}
static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return telldir(fs->dir.stream);
+ return telldir(fs->dir);
}
-static struct dirent *proxy_readdir(FsContext *ctx, V9fsFidOpenState *fs)
+static int proxy_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
+ struct dirent *entry,
+ struct dirent **result)
{
- return readdir(fs->dir.stream);
+ return readdir_r(fs->dir, entry, result);
}
static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
{
- seekdir(fs->dir.stream, off);
+ seekdir(fs->dir, off);
}
static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
@@ -789,7 +791,7 @@ static int proxy_fstat(FsContext *fs_ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
+ fd = dirfd(fs->dir);
} else {
fd = fs->fd;
}
@@ -934,7 +936,7 @@ static int proxy_fsync(FsContext *ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
+ fd = dirfd(fs->dir);
} else {
fd = fs->fd;
}
@@ -1190,7 +1192,7 @@ FileOperations proxy_ops = {
.opendir = proxy_opendir,
.rewinddir = proxy_rewinddir,
.telldir = proxy_telldir,
- .readdir = proxy_readdir,
+ .readdir_r = proxy_readdir_r,
.seekdir = proxy_seekdir,
.preadv = proxy_preadv,
.pwritev = proxy_pwritev,
diff --git a/hw/9pfs/9p-proxy.h b/hw/9pfs/9p-proxy.h
index b84301d00..ba9ca203d 100644
--- a/hw/9pfs/9p-proxy.h
+++ b/hw/9pfs/9p-proxy.h
@@ -9,9 +9,8 @@
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/
-
-#ifndef QEMU_9P_PROXY_H
-#define QEMU_9P_PROXY_H
+#ifndef _QEMU_9P_PROXY_H
+#define _QEMU_9P_PROXY_H
#define PROXY_MAX_IO_SZ (64 * 1024)
#define V9FS_FD_VALID INT_MAX
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 4b6d4e6a3..f1475dfd6 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -1,5 +1,5 @@
/*
- * 9p synthetic file system support
+ * Virtio 9p synthetic file system support
*
* Copyright IBM, Corp. 2011
*
@@ -13,7 +13,9 @@
*/
#include "qemu/osdep.h"
+#include "hw/virtio/virtio.h"
#include "9p.h"
+#include "9p-xattr.h"
#include "fsdev/qemu-fsdev.h"
#include "9p-synth.h"
#include "qemu/rcu.h"
@@ -21,19 +23,19 @@
#include "qemu/cutils.h"
/* Root node for synth file system */
-static V9fsSynthNode synth_root = {
+static V9fsSynthNode v9fs_synth_root = {
.name = "/",
.actual_attr = {
.mode = 0555 | S_IFDIR,
.nlink = 1,
},
- .attr = &synth_root.actual_attr,
+ .attr = &v9fs_synth_root.actual_attr,
};
-static QemuMutex synth_mutex;
-static int synth_node_count;
+static QemuMutex v9fs_synth_mutex;
+static int v9fs_synth_node_count;
/* set to 1 when the synth fs is ready */
-static int synth_fs;
+static int v9fs_synth_fs;
static V9fsSynthNode *v9fs_add_dir_node(V9fsSynthNode *parent, int mode,
const char *name,
@@ -69,16 +71,16 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
int ret;
V9fsSynthNode *node, *tmp;
- if (!synth_fs) {
+ if (!v9fs_synth_fs) {
return EAGAIN;
}
if (!name || (strlen(name) >= NAME_MAX)) {
return EINVAL;
}
if (!parent) {
- parent = &synth_root;
+ parent = &v9fs_synth_root;
}
- qemu_mutex_lock(&synth_mutex);
+ qemu_mutex_lock(&v9fs_synth_mutex);
QLIST_FOREACH(tmp, &parent->child, sibling) {
if (!strcmp(tmp->name, name)) {
ret = EEXIST;
@@ -86,7 +88,7 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
}
}
/* Add the name */
- node = v9fs_add_dir_node(parent, mode, name, NULL, synth_node_count++);
+ node = v9fs_add_dir_node(parent, mode, name, NULL, v9fs_synth_node_count++);
v9fs_add_dir_node(node, parent->attr->mode, "..",
parent->attr, parent->attr->inode);
v9fs_add_dir_node(node, node->attr->mode, ".",
@@ -94,7 +96,7 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
*result = node;
ret = 0;
err_out:
- qemu_mutex_unlock(&synth_mutex);
+ qemu_mutex_unlock(&v9fs_synth_mutex);
return ret;
}
@@ -105,17 +107,17 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
int ret;
V9fsSynthNode *node, *tmp;
- if (!synth_fs) {
+ if (!v9fs_synth_fs) {
return EAGAIN;
}
if (!name || (strlen(name) >= NAME_MAX)) {
return EINVAL;
}
if (!parent) {
- parent = &synth_root;
+ parent = &v9fs_synth_root;
}
- qemu_mutex_lock(&synth_mutex);
+ qemu_mutex_lock(&v9fs_synth_mutex);
QLIST_FOREACH(tmp, &parent->child, sibling) {
if (!strcmp(tmp->name, name)) {
ret = EEXIST;
@@ -126,7 +128,7 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
mode = ((mode & 0777) | S_IFREG);
node = g_malloc0(sizeof(V9fsSynthNode));
node->attr = &node->actual_attr;
- node->attr->inode = synth_node_count++;
+ node->attr->inode = v9fs_synth_node_count++;
node->attr->nlink = 1;
node->attr->read = read;
node->attr->write = write;
@@ -136,11 +138,11 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
QLIST_INSERT_HEAD_RCU(&parent->child, node, sibling);
ret = 0;
err_out:
- qemu_mutex_unlock(&synth_mutex);
+ qemu_mutex_unlock(&v9fs_synth_mutex);
return ret;
}
-static void synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
+static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
{
stbuf->st_dev = 0;
stbuf->st_ino = node->attr->inode;
@@ -157,24 +159,24 @@ static void synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
stbuf->st_ctime = 0;
}
-static int synth_lstat(FsContext *fs_ctx,
+static int v9fs_synth_lstat(FsContext *fs_ctx,
V9fsPath *fs_path, struct stat *stbuf)
{
V9fsSynthNode *node = *(V9fsSynthNode **)fs_path->data;
- synth_fill_statbuf(node, stbuf);
+ v9fs_synth_fill_statbuf(node, stbuf);
return 0;
}
-static int synth_fstat(FsContext *fs_ctx, int fid_type,
+static int v9fs_synth_fstat(FsContext *fs_ctx, int fid_type,
V9fsFidOpenState *fs, struct stat *stbuf)
{
V9fsSynthOpenState *synth_open = fs->private;
- synth_fill_statbuf(synth_open->node, stbuf);
+ v9fs_synth_fill_statbuf(synth_open->node, stbuf);
return 0;
}
-static int synth_opendir(FsContext *ctx,
+static int v9fs_synth_opendir(FsContext *ctx,
V9fsPath *fs_path, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open;
@@ -187,7 +189,7 @@ static int synth_opendir(FsContext *ctx,
return 0;
}
-static int synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
+static int v9fs_synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open = fs->private;
V9fsSynthNode *node = synth_open->node;
@@ -198,24 +200,24 @@ static int synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
return 0;
}
-static off_t synth_telldir(FsContext *ctx, V9fsFidOpenState *fs)
+static off_t v9fs_synth_telldir(FsContext *ctx, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open = fs->private;
return synth_open->offset;
}
-static void synth_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
+static void v9fs_synth_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
{
V9fsSynthOpenState *synth_open = fs->private;
synth_open->offset = off;
}
-static void synth_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
+static void v9fs_synth_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
{
- synth_seekdir(ctx, fs, 0);
+ v9fs_synth_seekdir(ctx, fs, 0);
}
-static void synth_direntry(V9fsSynthNode *node,
+static void v9fs_synth_direntry(V9fsSynthNode *node,
struct dirent *entry, off_t off)
{
strcpy(entry->d_name, node->name);
@@ -223,8 +225,8 @@ static void synth_direntry(V9fsSynthNode *node,
entry->d_off = off + 1;
}
-static struct dirent *synth_get_dentry(V9fsSynthNode *dir,
- struct dirent *entry, off_t off)
+static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent *entry,
+ struct dirent **result, off_t off)
{
int i = 0;
V9fsSynthNode *node;
@@ -240,25 +242,28 @@ static struct dirent *synth_get_dentry(V9fsSynthNode *dir,
rcu_read_unlock();
if (!node) {
/* end of directory */
- return NULL;
+ *result = NULL;
+ return 0;
}
- synth_direntry(node, entry, off);
- return entry;
+ v9fs_synth_direntry(node, entry, off);
+ *result = entry;
+ return 0;
}
-static struct dirent *synth_readdir(FsContext *ctx, V9fsFidOpenState *fs)
+static int v9fs_synth_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
+ struct dirent *entry, struct dirent **result)
{
- struct dirent *entry;
+ int ret;
V9fsSynthOpenState *synth_open = fs->private;
V9fsSynthNode *node = synth_open->node;
- entry = synth_get_dentry(node, &synth_open->dent, synth_open->offset);
- if (entry) {
+ ret = v9fs_synth_get_dentry(node, entry, result, synth_open->offset);
+ if (!ret && *result != NULL) {
synth_open->offset++;
}
- return entry;
+ return ret;
}
-static int synth_open(FsContext *ctx, V9fsPath *fs_path,
+static int v9fs_synth_open(FsContext *ctx, V9fsPath *fs_path,
int flags, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open;
@@ -271,7 +276,7 @@ static int synth_open(FsContext *ctx, V9fsPath *fs_path,
return 0;
}
-static int synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
+static int v9fs_synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, int flags,
FsCred *credp, V9fsFidOpenState *fs)
{
@@ -279,7 +284,7 @@ static int synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
return -1;
}
-static int synth_close(FsContext *ctx, V9fsFidOpenState *fs)
+static int v9fs_synth_close(FsContext *ctx, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open = fs->private;
V9fsSynthNode *node = synth_open->node;
@@ -290,7 +295,7 @@ static int synth_close(FsContext *ctx, V9fsFidOpenState *fs)
return 0;
}
-static ssize_t synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
+static ssize_t v9fs_synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
const struct iovec *iov,
int iovcnt, off_t offset)
{
@@ -314,7 +319,7 @@ static ssize_t synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
return count;
}
-static ssize_t synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
+static ssize_t v9fs_synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
const struct iovec *iov,
int iovcnt, off_t offset)
{
@@ -338,112 +343,112 @@ static ssize_t synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
return count;
}
-static int synth_truncate(FsContext *ctx, V9fsPath *path, off_t offset)
+static int v9fs_synth_truncate(FsContext *ctx, V9fsPath *path, off_t offset)
{
errno = ENOSYS;
return -1;
}
-static int synth_chmod(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
+static int v9fs_synth_chmod(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static int synth_mknod(FsContext *fs_ctx, V9fsPath *path,
+static int v9fs_synth_mknod(FsContext *fs_ctx, V9fsPath *path,
const char *buf, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static int synth_mkdir(FsContext *fs_ctx, V9fsPath *path,
+static int v9fs_synth_mkdir(FsContext *fs_ctx, V9fsPath *path,
const char *buf, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static ssize_t synth_readlink(FsContext *fs_ctx, V9fsPath *path,
+static ssize_t v9fs_synth_readlink(FsContext *fs_ctx, V9fsPath *path,
char *buf, size_t bufsz)
{
errno = ENOSYS;
return -1;
}
-static int synth_symlink(FsContext *fs_ctx, const char *oldpath,
+static int v9fs_synth_symlink(FsContext *fs_ctx, const char *oldpath,
V9fsPath *newpath, const char *buf, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static int synth_link(FsContext *fs_ctx, V9fsPath *oldpath,
+static int v9fs_synth_link(FsContext *fs_ctx, V9fsPath *oldpath,
V9fsPath *newpath, const char *buf)
{
errno = EPERM;
return -1;
}
-static int synth_rename(FsContext *ctx, const char *oldpath,
+static int v9fs_synth_rename(FsContext *ctx, const char *oldpath,
const char *newpath)
{
errno = EPERM;
return -1;
}
-static int synth_chown(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
+static int v9fs_synth_chown(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static int synth_utimensat(FsContext *fs_ctx, V9fsPath *path,
+static int v9fs_synth_utimensat(FsContext *fs_ctx, V9fsPath *path,
const struct timespec *buf)
{
errno = EPERM;
return 0;
}
-static int synth_remove(FsContext *ctx, const char *path)
+static int v9fs_synth_remove(FsContext *ctx, const char *path)
{
errno = EPERM;
return -1;
}
-static int synth_fsync(FsContext *ctx, int fid_type,
+static int v9fs_synth_fsync(FsContext *ctx, int fid_type,
V9fsFidOpenState *fs, int datasync)
{
errno = ENOSYS;
return 0;
}
-static int synth_statfs(FsContext *s, V9fsPath *fs_path,
+static int v9fs_synth_statfs(FsContext *s, V9fsPath *fs_path,
struct statfs *stbuf)
{
stbuf->f_type = 0xABCD;
stbuf->f_bsize = 512;
stbuf->f_blocks = 0;
- stbuf->f_files = synth_node_count;
+ stbuf->f_files = v9fs_synth_node_count;
stbuf->f_namelen = NAME_MAX;
return 0;
}
-static ssize_t synth_lgetxattr(FsContext *ctx, V9fsPath *path,
+static ssize_t v9fs_synth_lgetxattr(FsContext *ctx, V9fsPath *path,
const char *name, void *value, size_t size)
{
errno = ENOTSUP;
return -1;
}
-static ssize_t synth_llistxattr(FsContext *ctx, V9fsPath *path,
+static ssize_t v9fs_synth_llistxattr(FsContext *ctx, V9fsPath *path,
void *value, size_t size)
{
errno = ENOTSUP;
return -1;
}
-static int synth_lsetxattr(FsContext *ctx, V9fsPath *path,
+static int v9fs_synth_lsetxattr(FsContext *ctx, V9fsPath *path,
const char *name, void *value,
size_t size, int flags)
{
@@ -451,14 +456,14 @@ static int synth_lsetxattr(FsContext *ctx, V9fsPath *path,
return -1;
}
-static int synth_lremovexattr(FsContext *ctx,
+static int v9fs_synth_lremovexattr(FsContext *ctx,
V9fsPath *path, const char *name)
{
errno = ENOTSUP;
return -1;
}
-static int synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
+static int v9fs_synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
const char *name, V9fsPath *target)
{
V9fsSynthNode *node;
@@ -471,7 +476,7 @@ static int synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
}
if (!dir_path) {
- dir_node = &synth_root;
+ dir_node = &v9fs_synth_root;
} else {
dir_node = *(V9fsSynthNode **)dir_path->data;
}
@@ -500,7 +505,7 @@ out:
return 0;
}
-static int synth_renameat(FsContext *ctx, V9fsPath *olddir,
+static int v9fs_synth_renameat(FsContext *ctx, V9fsPath *olddir,
const char *old_name, V9fsPath *newdir,
const char *new_name)
{
@@ -508,62 +513,62 @@ static int synth_renameat(FsContext *ctx, V9fsPath *olddir,
return -1;
}
-static int synth_unlinkat(FsContext *ctx, V9fsPath *dir,
+static int v9fs_synth_unlinkat(FsContext *ctx, V9fsPath *dir,
const char *name, int flags)
{
errno = EPERM;
return -1;
}
-static int synth_init(FsContext *ctx)
+static int v9fs_synth_init(FsContext *ctx)
{
- QLIST_INIT(&synth_root.child);
- qemu_mutex_init(&synth_mutex);
+ QLIST_INIT(&v9fs_synth_root.child);
+ qemu_mutex_init(&v9fs_synth_mutex);
/* Add "." and ".." entries for root */
- v9fs_add_dir_node(&synth_root, synth_root.attr->mode,
- "..", synth_root.attr, synth_root.attr->inode);
- v9fs_add_dir_node(&synth_root, synth_root.attr->mode,
- ".", synth_root.attr, synth_root.attr->inode);
+ v9fs_add_dir_node(&v9fs_synth_root, v9fs_synth_root.attr->mode,
+ "..", v9fs_synth_root.attr, v9fs_synth_root.attr->inode);
+ v9fs_add_dir_node(&v9fs_synth_root, v9fs_synth_root.attr->mode,
+ ".", v9fs_synth_root.attr, v9fs_synth_root.attr->inode);
/* Mark the subsystem is ready for use */
- synth_fs = 1;
+ v9fs_synth_fs = 1;
return 0;
}
FileOperations synth_ops = {
- .init = synth_init,
- .lstat = synth_lstat,
- .readlink = synth_readlink,
- .close = synth_close,
- .closedir = synth_closedir,
- .open = synth_open,
- .opendir = synth_opendir,
- .rewinddir = synth_rewinddir,
- .telldir = synth_telldir,
- .readdir = synth_readdir,
- .seekdir = synth_seekdir,
- .preadv = synth_preadv,
- .pwritev = synth_pwritev,
- .chmod = synth_chmod,
- .mknod = synth_mknod,
- .mkdir = synth_mkdir,
- .fstat = synth_fstat,
- .open2 = synth_open2,
- .symlink = synth_symlink,
- .link = synth_link,
- .truncate = synth_truncate,
- .rename = synth_rename,
- .chown = synth_chown,
- .utimensat = synth_utimensat,
- .remove = synth_remove,
- .fsync = synth_fsync,
- .statfs = synth_statfs,
- .lgetxattr = synth_lgetxattr,
- .llistxattr = synth_llistxattr,
- .lsetxattr = synth_lsetxattr,
- .lremovexattr = synth_lremovexattr,
- .name_to_path = synth_name_to_path,
- .renameat = synth_renameat,
- .unlinkat = synth_unlinkat,
+ .init = v9fs_synth_init,
+ .lstat = v9fs_synth_lstat,
+ .readlink = v9fs_synth_readlink,
+ .close = v9fs_synth_close,
+ .closedir = v9fs_synth_closedir,
+ .open = v9fs_synth_open,
+ .opendir = v9fs_synth_opendir,
+ .rewinddir = v9fs_synth_rewinddir,
+ .telldir = v9fs_synth_telldir,
+ .readdir_r = v9fs_synth_readdir_r,
+ .seekdir = v9fs_synth_seekdir,
+ .preadv = v9fs_synth_preadv,
+ .pwritev = v9fs_synth_pwritev,
+ .chmod = v9fs_synth_chmod,
+ .mknod = v9fs_synth_mknod,
+ .mkdir = v9fs_synth_mkdir,
+ .fstat = v9fs_synth_fstat,
+ .open2 = v9fs_synth_open2,
+ .symlink = v9fs_synth_symlink,
+ .link = v9fs_synth_link,
+ .truncate = v9fs_synth_truncate,
+ .rename = v9fs_synth_rename,
+ .chown = v9fs_synth_chown,
+ .utimensat = v9fs_synth_utimensat,
+ .remove = v9fs_synth_remove,
+ .fsync = v9fs_synth_fsync,
+ .statfs = v9fs_synth_statfs,
+ .lgetxattr = v9fs_synth_lgetxattr,
+ .llistxattr = v9fs_synth_llistxattr,
+ .lsetxattr = v9fs_synth_lsetxattr,
+ .lremovexattr = v9fs_synth_lremovexattr,
+ .name_to_path = v9fs_synth_name_to_path,
+ .renameat = v9fs_synth_renameat,
+ .unlinkat = v9fs_synth_unlinkat,
};
diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h
index 6bcb44ace..82962512a 100644
--- a/hw/9pfs/9p-synth.h
+++ b/hw/9pfs/9p-synth.h
@@ -10,9 +10,9 @@
* the COPYING file in the top-level directory.
*
*/
+#ifndef HW_9PFS_SYNTH_H
+#define HW_9PFS_SYNTH_H 1
-#ifndef QEMU_9P_SYNTH_H
-#define QEMU_9P_SYNTH_H
typedef struct V9fsSynthNode V9fsSynthNode;
typedef ssize_t (*v9fs_synth_read)(void *buf, int len, off_t offset,
@@ -40,7 +40,6 @@ struct V9fsSynthNode {
typedef struct V9fsSynthOpenState {
off_t offset;
V9fsSynthNode *node;
- struct dirent dent;
} V9fsSynthOpenState;
extern int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
diff --git a/hw/9pfs/9p-xattr.h b/hw/9pfs/9p-xattr.h
index a853ea641..4d39a2026 100644
--- a/hw/9pfs/9p-xattr.h
+++ b/hw/9pfs/9p-xattr.h
@@ -10,9 +10,8 @@
* the COPYING file in the top-level directory.
*
*/
-
-#ifndef QEMU_9P_XATTR_H
-#define QEMU_9P_XATTR_H
+#ifndef _QEMU_9P_XATTR_H
+#define _QEMU_9P_XATTR_H
#include "qemu/xattr.h"
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index dfe293d11..f5e30125f 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -13,6 +13,7 @@
#include "qemu/osdep.h"
#include "hw/virtio/virtio.h"
+#include "hw/i386/pc.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/iov.h"
@@ -231,7 +232,7 @@ static int v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f)
} while (err == -EINTR && !pdu->cancelled);
}
} else if (f->fid_type == P9_FID_DIR) {
- if (f->fs.dir.stream == NULL) {
+ if (f->fs.dir == NULL) {
do {
err = v9fs_co_opendir(pdu, f);
} while (err == -EINTR && !pdu->cancelled);
@@ -300,9 +301,6 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
f->next = s->fid_list;
s->fid_list = f;
- v9fs_readdir_init(&f->fs.dir);
- v9fs_readdir_init(&f->fs_reclaim.dir);
-
return f;
}
@@ -348,7 +346,7 @@ static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
retval = v9fs_co_close(pdu, &fidp->fs);
}
} else if (fidp->fid_type == P9_FID_DIR) {
- if (fidp->fs.dir.stream != NULL) {
+ if (fidp->fs.dir != NULL) {
retval = v9fs_co_closedir(pdu, &fidp->fs);
}
} else if (fidp->fid_type == P9_FID_XATTR) {
@@ -446,7 +444,7 @@ void v9fs_reclaim_fd(V9fsPDU *pdu)
reclaim_count++;
}
} else if (f->fid_type == P9_FID_DIR) {
- if (f->fs.dir.stream != NULL) {
+ if (f->fs.dir != NULL) {
/*
* Up the reference count so that
* a clunk request won't free this fid
@@ -454,8 +452,8 @@ void v9fs_reclaim_fd(V9fsPDU *pdu)
f->ref++;
f->rclm_lst = reclaim_list;
reclaim_list = f;
- f->fs_reclaim.dir.stream = f->fs.dir.stream;
- f->fs.dir.stream = NULL;
+ f->fs_reclaim.dir = f->fs.dir;
+ f->fs.dir = NULL;
reclaim_count++;
}
}
@@ -1010,7 +1008,6 @@ static void v9fs_attach(void *opaque)
goto out;
}
err += offset;
- memcpy(&s->root_qid, &qid, sizeof(qid));
trace_v9fs_attach_return(pdu->tag, pdu->id,
qid.type, qid.version, qid.path);
/*
@@ -1257,19 +1254,6 @@ static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids)
return offset;
}
-static bool name_is_illegal(const char *name)
-{
- return !*name || strchr(name, '/') != NULL;
-}
-
-static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2)
-{
- return
- qid1->type != qid2->type ||
- qid1->version != qid2->version ||
- qid1->path != qid2->path;
-}
-
static void v9fs_walk(void *opaque)
{
int name_idx;
@@ -1285,7 +1269,6 @@ static void v9fs_walk(void *opaque)
V9fsFidState *newfidp = NULL;
V9fsPDU *pdu = opaque;
V9fsState *s = pdu->s;
- V9fsQID qid;
err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames);
if (err < 0) {
@@ -1304,10 +1287,6 @@ static void v9fs_walk(void *opaque)
if (err < 0) {
goto out_nofid;
}
- if (name_is_illegal(wnames[i].data)) {
- err = -ENOENT;
- goto out_nofid;
- }
offset += err;
}
} else if (nwnames > P9_MAXWELEM) {
@@ -1319,12 +1298,6 @@ static void v9fs_walk(void *opaque)
err = -ENOENT;
goto out_nofid;
}
-
- err = fid_to_qid(pdu, fidp, &qid);
- if (err < 0) {
- goto out;
- }
-
v9fs_path_init(&dpath);
v9fs_path_init(&path);
/*
@@ -1334,22 +1307,16 @@ static void v9fs_walk(void *opaque)
v9fs_path_copy(&dpath, &fidp->path);
v9fs_path_copy(&path, &fidp->path);
for (name_idx = 0; name_idx < nwnames; name_idx++) {
- if (not_same_qid(&pdu->s->root_qid, &qid) ||
- strcmp("..", wnames[name_idx].data)) {
- err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data,
- &path);
- if (err < 0) {
- goto out;
- }
-
- err = v9fs_co_lstat(pdu, &path, &stbuf);
- if (err < 0) {
- goto out;
- }
- stat_to_qid(&stbuf, &qid);
- v9fs_path_copy(&dpath, &path);
+ err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, &path);
+ if (err < 0) {
+ goto out;
}
- memcpy(&qids[name_idx], &qid, sizeof(qid));
+ err = v9fs_co_lstat(pdu, &path, &stbuf);
+ if (err < 0) {
+ goto out;
+ }
+ stat_to_qid(&stbuf, &qids[name_idx]);
+ v9fs_path_copy(&dpath, &path);
}
if (fid == newfid) {
BUG_ON(fidp->fid_type != P9_FID_NONE);
@@ -1514,16 +1481,6 @@ static void v9fs_lcreate(void *opaque)
}
trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
- goto out_nofid;
- }
-
fidp = get_fid(pdu, dfid);
if (fidp == NULL) {
err = -ENOENT;
@@ -1668,7 +1625,7 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
int32_t count = 0;
struct stat stbuf;
off_t saved_dir_pos;
- struct dirent *dent;
+ struct dirent *dent, *result;
/* save the directory position */
saved_dir_pos = v9fs_co_telldir(pdu, fidp);
@@ -1676,37 +1633,34 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
return saved_dir_pos;
}
+ dent = g_malloc(sizeof(struct dirent));
+
while (1) {
v9fs_path_init(&path);
-
- v9fs_readdir_lock(&fidp->fs.dir);
-
- err = v9fs_co_readdir(pdu, fidp, &dent);
- if (err || !dent) {
+ err = v9fs_co_readdir_r(pdu, fidp, dent, &result);
+ if (err || !result) {
break;
}
err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path);
if (err < 0) {
- break;
+ goto out;
}
err = v9fs_co_lstat(pdu, &path, &stbuf);
if (err < 0) {
- break;
+ goto out;
}
err = stat_to_v9stat(pdu, &path, &stbuf, &v9stat);
if (err < 0) {
- break;
+ goto out;
}
/* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
-
- v9fs_readdir_unlock(&fidp->fs.dir);
-
if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) {
/* Ran out of buffer. Set dir back to old position and return */
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
v9fs_stat_free(&v9stat);
v9fs_path_free(&path);
+ g_free(dent);
return count;
}
count += len;
@@ -1714,9 +1668,8 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
v9fs_path_free(&path);
saved_dir_pos = dent->d_off;
}
-
- v9fs_readdir_unlock(&fidp->fs.dir);
-
+out:
+ g_free(dent);
v9fs_path_free(&path);
if (err < 0) {
return err;
@@ -1852,7 +1805,7 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
int len, err = 0;
int32_t count = 0;
off_t saved_dir_pos;
- struct dirent *dent;
+ struct dirent *dent, *result;
/* save the directory position */
saved_dir_pos = v9fs_co_telldir(pdu, fidp);
@@ -1860,21 +1813,20 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
return saved_dir_pos;
}
- while (1) {
- v9fs_readdir_lock(&fidp->fs.dir);
+ dent = g_malloc(sizeof(struct dirent));
- err = v9fs_co_readdir(pdu, fidp, &dent);
- if (err || !dent) {
+ while (1) {
+ err = v9fs_co_readdir_r(pdu, fidp, dent, &result);
+ if (err || !result) {
break;
}
v9fs_string_init(&name);
v9fs_string_sprintf(&name, "%s", dent->d_name);
if ((count + v9fs_readdir_data_size(&name)) > max_count) {
- v9fs_readdir_unlock(&fidp->fs.dir);
-
/* Ran out of buffer. Set dir back to old position and return */
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
v9fs_string_free(&name);
+ g_free(dent);
return count;
}
/*
@@ -1892,21 +1844,17 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
len = pdu_marshal(pdu, 11 + count, "Qqbs",
&qid, dent->d_off,
dent->d_type, &name);
-
- v9fs_readdir_unlock(&fidp->fs.dir);
-
if (len < 0) {
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
v9fs_string_free(&name);
+ g_free(dent);
return len;
}
count += len;
v9fs_string_free(&name);
saved_dir_pos = dent->d_off;
}
-
- v9fs_readdir_unlock(&fidp->fs.dir);
-
+ g_free(dent);
if (err < 0) {
return err;
}
@@ -1936,7 +1884,7 @@ static void v9fs_readdir(void *opaque)
retval = -EINVAL;
goto out_nofid;
}
- if (!fidp->fs.dir.stream) {
+ if (!fidp->fs.dir) {
retval = -EINVAL;
goto out;
}
@@ -2118,16 +2066,6 @@ static void v9fs_create(void *opaque)
}
trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
- goto out_nofid;
- }
-
fidp = get_fid(pdu, fid);
if (fidp == NULL) {
err = -EINVAL;
@@ -2293,16 +2231,6 @@ static void v9fs_symlink(void *opaque)
}
trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
- goto out_nofid;
- }
-
dfidp = get_fid(pdu, dfid);
if (dfidp == NULL) {
err = -EINVAL;
@@ -2377,16 +2305,6 @@ static void v9fs_link(void *opaque)
}
trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
- goto out_nofid;
- }
-
dfidp = get_fid(pdu, dfid);
if (dfidp == NULL) {
err = -ENOENT;
@@ -2469,22 +2387,6 @@ static void v9fs_unlinkat(void *opaque)
if (err < 0) {
goto out_nofid;
}
-
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data)) {
- err = -EINVAL;
- goto out_nofid;
- }
-
- if (!strcmp("..", name.data)) {
- err = -ENOTEMPTY;
- goto out_nofid;
- }
-
dfidp = get_fid(pdu, dfid);
if (dfidp == NULL) {
err = -EINVAL;
@@ -2591,17 +2493,6 @@ static void v9fs_rename(void *opaque)
if (err < 0) {
goto out_nofid;
}
-
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EISDIR;
- goto out_nofid;
- }
-
fidp = get_fid(pdu, fid);
if (fidp == NULL) {
err = -ENOENT;
@@ -2714,17 +2605,6 @@ static void v9fs_renameat(void *opaque)
goto out_err;
}
- if (name_is_illegal(old_name.data) || name_is_illegal(new_name.data)) {
- err = -ENOENT;
- goto out_err;
- }
-
- if (!strcmp(".", old_name.data) || !strcmp("..", old_name.data) ||
- !strcmp(".", new_name.data) || !strcmp("..", new_name.data)) {
- err = -EISDIR;
- goto out_err;
- }
-
v9fs_path_write_lock(s);
err = v9fs_complete_renameat(pdu, olddirfid,
&old_name, newdirfid, &new_name);
@@ -2935,16 +2815,6 @@ static void v9fs_mknod(void *opaque)
}
trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
- goto out_nofid;
- }
-
fidp = get_fid(pdu, fid);
if (fidp == NULL) {
err = -ENOENT;
@@ -3096,16 +2966,6 @@ static void v9fs_mkdir(void *opaque)
}
trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
- goto out_nofid;
- }
-
fidp = get_fid(pdu, fid);
if (fidp == NULL) {
err = -ENOENT;
@@ -3407,8 +3267,8 @@ void pdu_submit(V9fsPDU *pdu)
if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) {
handler = v9fs_fs_ro;
}
- co = qemu_coroutine_create(handler, pdu);
- qemu_coroutine_enter(co);
+ co = qemu_coroutine_create(handler);
+ qemu_coroutine_enter(co, pdu);
}
/* Returns 0 on success, 1 on failure. */
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index a38603398..1a19418a8 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -1,9 +1,12 @@
-#ifndef QEMU_9P_H
-#define QEMU_9P_H
+#ifndef _QEMU_9P_H
+#define _QEMU_9P_H
#include <dirent.h>
#include <utime.h>
#include <sys/resource.h>
+#include <glib.h>
+#include "standard-headers/linux/virtio_9p.h"
+#include "hw/virtio/virtio.h"
#include "fsdev/file-op-9p.h"
#include "fsdev/9p-iov-marshal.h"
#include "qemu/thread.h"
@@ -166,33 +169,13 @@ typedef struct V9fsXattr
int flags;
} V9fsXattr;
-typedef struct V9fsDir {
- DIR *stream;
- QemuMutex readdir_mutex;
-} V9fsDir;
-
-static inline void v9fs_readdir_lock(V9fsDir *dir)
-{
- qemu_mutex_lock(&dir->readdir_mutex);
-}
-
-static inline void v9fs_readdir_unlock(V9fsDir *dir)
-{
- qemu_mutex_unlock(&dir->readdir_mutex);
-}
-
-static inline void v9fs_readdir_init(V9fsDir *dir)
-{
- qemu_mutex_init(&dir->readdir_mutex);
-}
-
/*
* Filled by fs driver on open and other
* calls.
*/
union V9fsFidOpenState {
int fd;
- V9fsDir dir;
+ DIR *dir;
V9fsXattr xattr;
/*
* private pointer for fs drivers, that
@@ -236,7 +219,6 @@ typedef struct V9fsState
int32_t root_fid;
Error *migration_blocker;
V9fsConf fsconf;
- V9fsQID root_qid;
} V9fsState;
/* 9p2000.L open flags */
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index d91f9ad6e..91df7f7a7 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -1,5 +1,6 @@
+
/*
- * 9p backend
+ * Virtio 9p backend
*
* Copyright IBM, Corp. 2011
*
@@ -17,7 +18,8 @@
#include "qemu/coroutine.h"
#include "coth.h"
-int v9fs_co_readdir(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent **dent)
+int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent,
+ struct dirent **result)
{
int err;
V9fsState *s = pdu->s;
@@ -27,14 +29,11 @@ int v9fs_co_readdir(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent **dent)
}
v9fs_co_run_in_worker(
{
- struct dirent *entry;
-
errno = 0;
- entry = s->ops->readdir(&s->ctx, &fidp->fs);
- if (!entry && errno) {
+ err = s->ops->readdir_r(&s->ctx, &fidp->fs, dent, result);
+ if (!*result && errno) {
err = -errno;
} else {
- *dent = entry;
err = 0;
}
});
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index 10343c0a9..293483e0c 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -1,5 +1,6 @@
+
/*
- * 9p backend
+ * Virtio 9p backend
*
* Copyright IBM, Corp. 2011
*
diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 70f584fcb..18c81cb3d 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -1,5 +1,6 @@
+
/*
- * 9p backend
+ * Virtio 9p backend
*
* Copyright IBM, Corp. 2011
*
diff --git a/hw/9pfs/coth.c b/hw/9pfs/coth.c
index 89018de6b..464293ef2 100644
--- a/hw/9pfs/coth.c
+++ b/hw/9pfs/coth.c
@@ -16,20 +16,21 @@
#include "qemu-common.h"
#include "block/thread-pool.h"
#include "qemu/coroutine.h"
+#include "qemu/main-loop.h"
#include "coth.h"
/* Called from QEMU I/O thread. */
static void coroutine_enter_cb(void *opaque, int ret)
{
Coroutine *co = opaque;
- qemu_coroutine_enter(co);
+ qemu_coroutine_enter(co, NULL);
}
/* Called from worker thread. */
static int coroutine_enter_func(void *arg)
{
Coroutine *co = arg;
- qemu_coroutine_enter(co);
+ qemu_coroutine_enter(co, NULL);
return 0;
}
diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h
index 3c7424e42..209fc6a9a 100644
--- a/hw/9pfs/coth.h
+++ b/hw/9pfs/coth.h
@@ -12,13 +12,12 @@
*
*/
-#ifndef QEMU_9P_COTH_H
-#define QEMU_9P_COTH_H
+#ifndef _QEMU_9P_COTH_H
+#define _QEMU_9P_COTH_H
#include "qemu/thread.h"
#include "qemu/coroutine.h"
-#include "qemu/main-loop.h"
-#include "9p.h"
+#include "virtio-9p.h"
/*
* we want to use bottom half because we want to make sure the below
@@ -48,8 +47,10 @@
} while (0)
extern void co_run_in_worker_bh(void *);
+extern int v9fs_init_worker_threads(void);
extern int v9fs_co_readlink(V9fsPDU *, V9fsPath *, V9fsString *);
-extern int v9fs_co_readdir(V9fsPDU *, V9fsFidState *, struct dirent **);
+extern int v9fs_co_readdir_r(V9fsPDU *, V9fsFidState *,
+ struct dirent *, struct dirent **result);
extern off_t v9fs_co_telldir(V9fsPDU *, V9fsFidState *);
extern void v9fs_co_seekdir(V9fsPDU *, V9fsFidState *, off_t);
extern void v9fs_co_rewinddir(V9fsPDU *, V9fsFidState *);
diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c
index 133c4ead3..6ad96ea9f 100644
--- a/hw/9pfs/coxattr.c
+++ b/hw/9pfs/coxattr.c
@@ -1,5 +1,6 @@
+
/*
- * 9p backend
+ * Virtio 9p backend
*
* Copyright IBM, Corp. 2011
*
diff --git a/hw/9pfs/trace-events b/hw/9pfs/trace-events
deleted file mode 100644
index 48d3d8abe..000000000
--- a/hw/9pfs/trace-events
+++ /dev/null
@@ -1,47 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/9pfs/virtio-9p.c
-v9fs_rerror(uint16_t tag, uint8_t id, int err) "tag %d id %d err %d"
-v9fs_version(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
-v9fs_version_return(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
-v9fs_attach(uint16_t tag, uint8_t id, int32_t fid, int32_t afid, char* uname, char* aname) "tag %u id %u fid %d afid %d uname %s aname %s"
-v9fs_attach_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d type %d version %d path %"PRId64
-v9fs_stat(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
-v9fs_stat_return(uint16_t tag, uint8_t id, int32_t mode, int32_t atime, int32_t mtime, int64_t length) "tag %d id %d stat={mode %d atime %d mtime %d length %"PRId64"}"
-v9fs_getattr(uint16_t tag, uint8_t id, int32_t fid, uint64_t request_mask) "tag %d id %d fid %d request_mask %"PRIu64
-v9fs_getattr_return(uint16_t tag, uint8_t id, uint64_t result_mask, uint32_t mode, uint32_t uid, uint32_t gid) "tag %d id %d getattr={result_mask %"PRId64" mode %u uid %u gid %u}"
-v9fs_walk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, uint16_t nwnames) "tag %d id %d fid %d newfid %d nwnames %d"
-v9fs_walk_return(uint16_t tag, uint8_t id, uint16_t nwnames, void* qids) "tag %d id %d nwnames %d qids %p"
-v9fs_open(uint16_t tag, uint8_t id, int32_t fid, int32_t mode) "tag %d id %d fid %d mode %d"
-v9fs_open_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
-v9fs_lcreate(uint16_t tag, uint8_t id, int32_t dfid, int32_t flags, int32_t mode, uint32_t gid) "tag %d id %d dfid %d flags %d mode %d gid %u"
-v9fs_lcreate_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int32_t iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
-v9fs_fsync(uint16_t tag, uint8_t id, int32_t fid, int datasync) "tag %d id %d fid %d datasync %d"
-v9fs_clunk(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
-v9fs_read(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t max_count) "tag %d id %d fid %d off %"PRIu64" max_count %u"
-v9fs_read_return(uint16_t tag, uint8_t id, int32_t count, ssize_t err) "tag %d id %d count %d err %zd"
-v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, uint64_t offset, uint32_t max_count) "tag %d id %d fid %d offset %"PRIu64" max_count %u"
-v9fs_readdir_return(uint16_t tag, uint8_t id, uint32_t count, ssize_t retval) "tag %d id %d count %u retval %zd"
-v9fs_write(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t count, int cnt) "tag %d id %d fid %d off %"PRIu64" count %u cnt %d"
-v9fs_write_return(uint16_t tag, uint8_t id, int32_t total, ssize_t err) "tag %d id %d total %d err %zd"
-v9fs_create(uint16_t tag, uint8_t id, int32_t fid, char* name, int32_t perm, int8_t mode) "tag %d id %d fid %d name %s perm %d mode %d"
-v9fs_create_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
-v9fs_symlink(uint16_t tag, uint8_t id, int32_t fid, char* name, char* symname, uint32_t gid) "tag %d id %d fid %d name %s symname %s gid %u"
-v9fs_symlink_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d qid={type %d version %d path %"PRId64"}"
-v9fs_flush(uint16_t tag, uint8_t id, int16_t flush_tag) "tag %d id %d flush_tag %d"
-v9fs_link(uint16_t tag, uint8_t id, int32_t dfid, int32_t oldfid, char* name) "tag %d id %d dfid %d oldfid %d name %s"
-v9fs_remove(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
-v9fs_wstat(uint16_t tag, uint8_t id, int32_t fid, int32_t mode, int32_t atime, int32_t mtime) "tag %u id %u fid %d stat={mode %d atime %d mtime %d}"
-v9fs_mknod(uint16_t tag, uint8_t id, int32_t fid, int mode, int major, int minor) "tag %d id %d fid %d mode %d major %d minor %d"
-v9fs_mknod_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d qid={type %d version %d path %"PRId64"}"
-v9fs_lock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length) "tag %d id %d fid %d type %d start %"PRIu64" length %"PRIu64
-v9fs_lock_return(uint16_t tag, uint8_t id, int8_t status) "tag %d id %d status %d"
-v9fs_getlock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length)"tag %d id %d fid %d type %d start %"PRIu64" length %"PRIu64
-v9fs_getlock_return(uint16_t tag, uint8_t id, uint8_t type, uint64_t start, uint64_t length, uint32_t proc_id) "tag %d id %d type %d start %"PRIu64" length %"PRIu64" proc_id %u"
-v9fs_mkdir(uint16_t tag, uint8_t id, int32_t fid, char* name, int mode, uint32_t gid) "tag %u id %u fid %d name %s mode %d gid %u"
-v9fs_mkdir_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int err) "tag %u id %u qid={type %d version %d path %"PRId64"} err %d"
-v9fs_xattrwalk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, char* name) "tag %d id %d fid %d newfid %d name %s"
-v9fs_xattrwalk_return(uint16_t tag, uint8_t id, int64_t size) "tag %d id %d size %"PRId64
-v9fs_xattrcreate(uint16_t tag, uint8_t id, int32_t fid, char* name, int64_t size, int flags) "tag %d id %d fid %d name %s size %"PRId64" flags %d"
-v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
-v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) "tag %d id %d name %s"
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 009b43f6d..a38850ee8 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -13,9 +13,11 @@
#include "qemu/osdep.h"
#include "hw/virtio/virtio.h"
+#include "hw/i386/pc.h"
#include "qemu/sockets.h"
#include "virtio-9p.h"
#include "fsdev/qemu-fsdev.h"
+#include "9p-xattr.h"
#include "coth.h"
#include "hw/virtio/virtio-access.h"
#include "qemu/iov.h"
@@ -97,9 +99,14 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
g_free(cfg);
}
-static int virtio_9p_load(QEMUFile *f, void *opaque, size_t size)
+static void virtio_9p_save(QEMUFile *f, void *opaque)
{
- return virtio_load(VIRTIO_DEVICE(opaque), f, 1);
+ virtio_save(VIRTIO_DEVICE(opaque), f);
+}
+
+static int virtio_9p_load(QEMUFile *f, void *opaque, int version_id)
+{
+ return virtio_load(VIRTIO_DEVICE(opaque), f, version_id);
}
static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
@@ -115,6 +122,7 @@ static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag);
virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size);
v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
+ register_savevm(dev, "virtio-9p", -1, 1, virtio_9p_save, virtio_9p_load, v);
out:
return;
@@ -127,6 +135,7 @@ static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp)
V9fsState *s = &v->state;
virtio_cleanup(vdev);
+ unregister_savevm(dev, "virtio-9p", v);
v9fs_device_unrealize_common(s, errp);
}
@@ -168,8 +177,6 @@ void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
/* virtio-9p device */
-VMSTATE_VIRTIO_DEVICE(9p, 1, virtio_9p_load, virtio_vmstate_save);
-
static Property virtio_9p_properties[] = {
DEFINE_PROP_STRING("mount_tag", V9fsVirtioState, state.fsconf.tag),
DEFINE_PROP_STRING("fsdev", V9fsVirtioState, state.fsconf.fsdev_id),
@@ -182,7 +189,6 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->props = virtio_9p_properties;
- dc->vmsd = &vmstate_virtio_9p;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->realize = virtio_9p_device_realize;
vdc->unrealize = virtio_9p_device_unrealize;
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 7586b792d..7f6d88553 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -1,5 +1,5 @@
-#ifndef QEMU_VIRTIO_9P_H
-#define QEMU_VIRTIO_9P_H
+#ifndef _QEMU_VIRTIO_9P_H
+#define _QEMU_VIRTIO_9P_H
#include "standard-headers/linux/virtio_9p.h"
#include "hw/virtio/virtio.h"
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 4b7da6639..faee86c5c 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -1,10 +1,8 @@
common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o
common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o
-common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
+common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o cpu_hotplug_acpi_table.o
common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o memory_hotplug_acpi_table.o
-common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
common-obj-$(CONFIG_ACPI) += acpi_interface.o
common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
common-obj-$(CONFIG_ACPI) += aml-build.o
-common-obj-$(call land,$(CONFIG_ACPI),$(CONFIG_IPMI)) += ipmi.o
diff --git a/hw/acpi/acpi_interface.c b/hw/acpi/acpi_interface.c
index 6583917b8..d82131326 100644
--- a/hw/acpi/acpi_interface.c
+++ b/hw/acpi/acpi_interface.c
@@ -2,15 +2,6 @@
#include "hw/acpi/acpi_dev_interface.h"
#include "qemu/module.h"
-void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event)
-{
- AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(dev);
- if (adevc->send_event) {
- AcpiDeviceIf *adev = ACPI_DEVICE_IF(dev);
- adevc->send_event(adev, event);
- }
-}
-
static void register_types(void)
{
static const TypeInfo acpi_dev_if_info = {
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index db3e914fb..ab89ca638 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -24,6 +24,7 @@
#include "hw/acpi/aml-build.h"
#include "qemu/bswap.h"
#include "qemu/bitops.h"
+#include "hw/acpi/bios-linker-loader.h"
static GArray *build_alloc_array(void)
{
@@ -324,9 +325,12 @@ static void aml_free(gpointer data, gpointer user_data)
Aml *init_aml_allocator(void)
{
+ Aml *var;
+
assert(!alloc_list);
alloc_list = g_ptr_array_new();
- return aml_alloc();
+ var = aml_alloc();
+ return var;
}
void free_aml_allocator(void)
@@ -402,15 +406,6 @@ Aml *aml_return(Aml *val)
return var;
}
-/* ACPI 1.0b: 16.2.6.3 Debug Objects Encoding: DebugObj */
-Aml *aml_debug(void)
-{
- Aml *var = aml_alloc();
- build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
- build_append_byte(var->buf, 0x31); /* DebugOp */
- return var;
-}
-
/*
* ACPI 1.0b: 16.2.3 Data Objects Encoding:
* encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp
@@ -448,10 +443,12 @@ Aml *aml_name_decl(const char *name, Aml *val)
/* ACPI 1.0b: 16.2.6.1 Arg Objects Encoding */
Aml *aml_arg(int pos)
{
+ Aml *var;
uint8_t op = 0x68 /* ARG0 op */ + pos;
assert(pos <= 6);
- return aml_opcode(op);
+ var = aml_opcode(op);
+ return var;
}
/* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToInteger */
@@ -660,20 +657,6 @@ Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4)
return var;
}
-/* helper to call method with 5 arguments */
-Aml *aml_call5(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
- Aml *arg5)
-{
- Aml *var = aml_alloc();
- build_append_namestring(var->buf, "%s", method);
- aml_append(var, arg1);
- aml_append(var, arg2);
- aml_append(var, arg3);
- aml_append(var, arg4);
- aml_append(var, arg5);
- return var;
-}
-
/*
* ACPI 5.0: 6.4.3.8.1 GPIO Connection Descriptor
* Type 1, Large Item Name 0xC
@@ -1091,10 +1074,12 @@ Aml *aml_string(const char *name_format, ...)
/* ACPI 1.0b: 16.2.6.2 Local Objects Encoding */
Aml *aml_local(int num)
{
+ Aml *var;
uint8_t op = 0x60 /* Local0Op */ + num;
assert(num <= 7);
- return aml_opcode(op);
+ var = aml_opcode(op);
+ return var;
}
/* ACPI 2.0a: 17.2.2 Data Objects Encoding: DefVarPackage */
@@ -1422,14 +1407,6 @@ Aml *aml_unicode(const char *str)
return var;
}
-/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefRefOf */
-Aml *aml_refof(Aml *arg)
-{
- Aml *var = aml_opcode(0x71 /* RefOfOp */);
- aml_append(var, arg);
- return var;
-}
-
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDerefOf */
Aml *aml_derefof(Aml *arg)
{
@@ -1495,21 +1472,11 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
target);
}
-/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefObjectType */
-Aml *aml_object_type(Aml *object)
-{
- Aml *var = aml_opcode(0x8E /* ObjectTypeOp */);
- aml_append(var, object);
- return var;
-}
-
void
-build_header(BIOSLinker *linker, GArray *table_data,
+build_header(GArray *linker, GArray *table_data,
AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
const char *oem_id, const char *oem_table_id)
{
- unsigned tbl_offset = (char *)h - table_data->data;
- unsigned checksum_offset = (char *)&h->checksum - table_data->data;
memcpy(&h->signature, sig, 4);
h->length = cpu_to_le32(len);
h->revision = rev;
@@ -1530,9 +1497,10 @@ build_header(BIOSLinker *linker, GArray *table_data,
h->oem_revision = cpu_to_le32(1);
memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
h->asl_compiler_revision = cpu_to_le32(1);
+ h->checksum = 0;
/* Checksum to be filled in by Guest linker */
bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
- tbl_offset, len, checksum_offset);
+ table_data, h, len, &h->checksum);
}
void *acpi_data_push(GArray *table_data, unsigned size)
@@ -1550,7 +1518,7 @@ unsigned acpi_data_len(GArray *table)
void acpi_add_table(GArray *table_offsets, GArray *table_data)
{
- uint32_t offset = table_data->len;
+ uint32_t offset = cpu_to_le32(table_data->len);
g_array_append_val(table_offsets, offset);
}
@@ -1564,7 +1532,8 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
{
- bios_linker_loader_cleanup(tables->linker);
+ void *linker_data = bios_linker_loader_cleanup(tables->linker);
+ g_free(linker_data);
g_array_free(tables->rsdp, true);
g_array_free(tables->table_data, true);
g_array_free(tables->tcpalog, mfre);
@@ -1572,38 +1541,25 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
/* Build rsdt table */
void
-build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
+build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets,
const char *oem_id, const char *oem_table_id)
{
- int i;
- unsigned rsdt_entries_offset;
AcpiRsdtDescriptorRev1 *rsdt;
- const unsigned table_data_len = (sizeof(uint32_t) * table_offsets->len);
- const unsigned rsdt_entry_size = sizeof(rsdt->table_offset_entry[0]);
- const size_t rsdt_len = sizeof(*rsdt) + table_data_len;
+ size_t rsdt_len;
+ int i;
+ const int table_data_len = (sizeof(uint32_t) * table_offsets->len);
+ rsdt_len = sizeof(*rsdt) + table_data_len;
rsdt = acpi_data_push(table_data, rsdt_len);
- rsdt_entries_offset = (char *)rsdt->table_offset_entry - table_data->data;
+ memcpy(rsdt->table_offset_entry, table_offsets->data, table_data_len);
for (i = 0; i < table_offsets->len; ++i) {
- uint32_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
- uint32_t rsdt_entry_offset = rsdt_entries_offset + rsdt_entry_size * i;
-
/* rsdt->table_offset_entry to be filled by Guest linker */
bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, rsdt_entry_size,
- ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
+ ACPI_BUILD_TABLE_FILE,
+ ACPI_BUILD_TABLE_FILE,
+ table_data, &rsdt->table_offset_entry[i],
+ sizeof(uint32_t));
}
build_header(linker, table_data,
(void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id);
}
-
-void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
- uint64_t len, int node, MemoryAffinityFlags flags)
-{
- numamem->type = ACPI_SRAT_MEMORY;
- numamem->length = sizeof(*numamem);
- numamem->proximity = cpu_to_le32(node);
- numamem->flags = cpu_to_le32(flags);
- numamem->base_addr = cpu_to_le64(base);
- numamem->range_length = cpu_to_le64(len);
-}
diff --git a/hw/acpi/bios-linker-loader.c b/hw/acpi/bios-linker-loader.c
index d963ebe24..5153ab151 100644
--- a/hw/acpi/bios-linker-loader.c
+++ b/hw/acpi/bios-linker-loader.c
@@ -96,170 +96,134 @@ enum {
};
/*
- * BiosLinkerFileEntry:
- *
- * An internal type used for book-keeping file entries
- */
-typedef struct BiosLinkerFileEntry {
- char *name; /* file name */
- GArray *blob; /* data accosiated with @name */
-} BiosLinkerFileEntry;
-
-/*
- * bios_linker_loader_init: allocate a new linker object instance.
+ * bios_linker_loader_init: allocate a new linker file blob array.
*
* After initialization, linker commands can be added, and will
- * be stored in the linker.cmd_blob array.
+ * be stored in the array.
*/
-BIOSLinker *bios_linker_loader_init(void)
+GArray *bios_linker_loader_init(void)
{
- BIOSLinker *linker = g_new(BIOSLinker, 1);
-
- linker->cmd_blob = g_array_new(false, true /* clear */, 1);
- linker->file_list = g_array_new(false, true /* clear */,
- sizeof(BiosLinkerFileEntry));
- return linker;
+ return g_array_new(false, true /* clear */, 1);
}
-/* Free linker wrapper */
-void bios_linker_loader_cleanup(BIOSLinker *linker)
+/* Free linker wrapper and return the linker array. */
+void *bios_linker_loader_cleanup(GArray *linker)
{
- int i;
- BiosLinkerFileEntry *entry;
-
- g_array_free(linker->cmd_blob, true);
-
- for (i = 0; i < linker->file_list->len; i++) {
- entry = &g_array_index(linker->file_list, BiosLinkerFileEntry, i);
- g_free(entry->name);
- }
- g_array_free(linker->file_list, true);
- g_free(linker);
-}
-
-static const BiosLinkerFileEntry *
-bios_linker_find_file(const BIOSLinker *linker, const char *name)
-{
- int i;
- BiosLinkerFileEntry *entry;
-
- for (i = 0; i < linker->file_list->len; i++) {
- entry = &g_array_index(linker->file_list, BiosLinkerFileEntry, i);
- if (!strcmp(entry->name, name)) {
- return entry;
- }
- }
- return NULL;
+ return g_array_free(linker, false);
}
/*
* bios_linker_loader_alloc: ask guest to load file into guest memory.
*
- * @linker: linker object instance
- * @file_name: name of the file blob to be loaded
- * @file_blob: pointer to blob corresponding to @file_name
+ * @linker: linker file blob array
+ * @file: file to be loaded
* @alloc_align: required minimal alignment in bytes. Must be a power of 2.
* @alloc_fseg: request allocation in FSEG zone (useful for the RSDP ACPI table)
*
* Note: this command must precede any other linker command using this file.
*/
-void bios_linker_loader_alloc(BIOSLinker *linker,
- const char *file_name,
- GArray *file_blob,
+void bios_linker_loader_alloc(GArray *linker,
+ const char *file,
uint32_t alloc_align,
bool alloc_fseg)
{
BiosLinkerLoaderEntry entry;
- BiosLinkerFileEntry file = { g_strdup(file_name), file_blob};
assert(!(alloc_align & (alloc_align - 1)));
- assert(!bios_linker_find_file(linker, file_name));
- g_array_append_val(linker->file_list, file);
-
memset(&entry, 0, sizeof entry);
- strncpy(entry.alloc.file, file_name, sizeof entry.alloc.file - 1);
+ strncpy(entry.alloc.file, file, sizeof entry.alloc.file - 1);
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ALLOCATE);
entry.alloc.align = cpu_to_le32(alloc_align);
entry.alloc.zone = alloc_fseg ? BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG :
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH;
/* Alloc entries must come first, so prepend them */
- g_array_prepend_vals(linker->cmd_blob, &entry, sizeof entry);
+ g_array_prepend_vals(linker, &entry, sizeof entry);
}
/*
- * bios_linker_loader_add_checksum: ask guest to add checksum of ACPI
- * table in the specified file at the specified offset.
+ * bios_linker_loader_add_checksum: ask guest to add checksum of file data
+ * into (same) file at the specified pointer.
*
* Checksum calculation simply sums -X for each byte X in the range
* using 8-bit math (i.e. ACPI checksum).
*
- * @linker: linker object instance
+ * @linker: linker file blob array
* @file: file that includes the checksum to be calculated
* and the data to be checksummed
- * @start_offset, @size: range of data in the file to checksum,
- * relative to the start of file blob
- * @checksum_offset: location of the checksum to be patched within file blob,
- * relative to the start of file blob
+ * @table: @file blob contents
+ * @start, @size: range of data to checksum
+ * @checksum: location of the checksum to be patched within file blob
+ *
+ * Notes:
+ * - checksum byte initial value must have been pushed into @table
+ * and reside at address @checksum.
+ * - @size bytes must have been pushed into @table and reside at address
+ * @start.
+ * - Guest calculates checksum of specified range of data, result is added to
+ * initial value at @checksum into copy of @file in Guest memory.
+ * - Range might include the checksum itself.
+ * - To avoid confusion, caller must always put 0x0 at @checksum.
+ * - @file must be loaded into Guest memory using bios_linker_loader_alloc
*/
-void bios_linker_loader_add_checksum(BIOSLinker *linker, const char *file_name,
- unsigned start_offset, unsigned size,
- unsigned checksum_offset)
+void bios_linker_loader_add_checksum(GArray *linker, const char *file,
+ GArray *table,
+ void *start, unsigned size,
+ uint8_t *checksum)
{
BiosLinkerLoaderEntry entry;
- const BiosLinkerFileEntry *file = bios_linker_find_file(linker, file_name);
+ ptrdiff_t checksum_offset = (gchar *)checksum - table->data;
+ ptrdiff_t start_offset = (gchar *)start - table->data;
- assert(file);
- assert(start_offset < file->blob->len);
- assert(start_offset + size <= file->blob->len);
- assert(checksum_offset >= start_offset);
- assert(checksum_offset + 1 <= start_offset + size);
+ assert(checksum_offset >= 0);
+ assert(start_offset >= 0);
+ assert(checksum_offset + 1 <= table->len);
+ assert(start_offset + size <= table->len);
+ assert(*checksum == 0x0);
- *(file->blob->data + checksum_offset) = 0;
memset(&entry, 0, sizeof entry);
- strncpy(entry.cksum.file, file_name, sizeof entry.cksum.file - 1);
+ strncpy(entry.cksum.file, file, sizeof entry.cksum.file - 1);
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM);
entry.cksum.offset = cpu_to_le32(checksum_offset);
entry.cksum.start = cpu_to_le32(start_offset);
entry.cksum.length = cpu_to_le32(size);
- g_array_append_vals(linker->cmd_blob, &entry, sizeof entry);
+ g_array_append_vals(linker, &entry, sizeof entry);
}
/*
- * bios_linker_loader_add_pointer: ask guest to patch address in
- * destination file with a pointer to source file
+ * bios_linker_loader_add_pointer: ask guest to add address of source file
+ * into destination file at the specified pointer.
*
- * @linker: linker object instance
+ * @linker: linker file blob array
* @dest_file: destination file that must be changed
- * @dst_patched_offset: location within destination file blob to be patched
- * with the pointer to @src_file+@src_offset (i.e. source
- * blob allocated in guest memory + @src_offset), in bytes
- * @dst_patched_offset_size: size of the pointer to be patched
- * at @dst_patched_offset in @dest_file blob, in bytes
* @src_file: source file who's address must be taken
- * @src_offset: location within source file blob to which
- * @dest_file+@dst_patched_offset will point to after
- * firmware's executed ADD_POINTER command
+ * @table: @dest_file blob contents array
+ * @pointer: location of the pointer to be patched within destination file blob
+ * @pointer_size: size of pointer to be patched, in bytes
+ *
+ * Notes:
+ * - @pointer_size bytes must have been pushed into @table
+ * and reside at address @pointer.
+ * - Guest address is added to initial value at @pointer
+ * into copy of @dest_file in Guest memory.
+ * e.g. to get start of src_file in guest memory, put 0x0 there
+ * to get address of a field at offset 0x10 in src_file, put 0x10 there
+ * - Both @dest_file and @src_file must be
+ * loaded into Guest memory using bios_linker_loader_alloc
*/
-void bios_linker_loader_add_pointer(BIOSLinker *linker,
+void bios_linker_loader_add_pointer(GArray *linker,
const char *dest_file,
- uint32_t dst_patched_offset,
- uint8_t dst_patched_size,
const char *src_file,
- uint32_t src_offset)
+ GArray *table, void *pointer,
+ uint8_t pointer_size)
{
- uint64_t le_src_offset;
BiosLinkerLoaderEntry entry;
- const BiosLinkerFileEntry *dst_file =
- bios_linker_find_file(linker, dest_file);
- const BiosLinkerFileEntry *source_file =
- bios_linker_find_file(linker, src_file);
+ ptrdiff_t offset = (gchar *)pointer - table->data;
- assert(dst_patched_offset < dst_file->blob->len);
- assert(dst_patched_offset + dst_patched_size <= dst_file->blob->len);
- assert(src_offset < source_file->blob->len);
+ assert(offset >= 0);
+ assert(offset + pointer_size <= table->len);
memset(&entry, 0, sizeof entry);
strncpy(entry.pointer.dest_file, dest_file,
@@ -267,14 +231,10 @@ void bios_linker_loader_add_pointer(BIOSLinker *linker,
strncpy(entry.pointer.src_file, src_file,
sizeof entry.pointer.src_file - 1);
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER);
- entry.pointer.offset = cpu_to_le32(dst_patched_offset);
- entry.pointer.size = dst_patched_size;
- assert(dst_patched_size == 1 || dst_patched_size == 2 ||
- dst_patched_size == 4 || dst_patched_size == 8);
-
- le_src_offset = cpu_to_le64(src_offset);
- memcpy(dst_file->blob->data + dst_patched_offset,
- &le_src_offset, dst_patched_size);
+ entry.pointer.offset = cpu_to_le32(offset);
+ entry.pointer.size = pointer_size;
+ assert(pointer_size == 1 || pointer_size == 2 ||
+ pointer_size == 4 || pointer_size == 8);
- g_array_append_vals(linker->cmd_blob, &entry, sizeof entry);
+ g_array_append_vals(linker, &entry, sizeof entry);
}
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index e890a5d67..6a2f45214 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -239,11 +239,11 @@ void acpi_table_add(const QemuOpts *opts, Error **errp)
char unsigned *blob = NULL;
{
- Visitor *v;
+ OptsVisitor *ov;
- v = opts_visitor_new(opts);
- visit_type_AcpiTableOptions(v, NULL, &hdrs, &err);
- visit_free(v);
+ ov = opts_visitor_new(opts);
+ visit_type_AcpiTableOptions(opts_get_visitor(ov), NULL, &hdrs, &err);
+ opts_visitor_cleanup(ov);
}
if (err) {
@@ -491,12 +491,6 @@ void acpi_pm_tmr_update(ACPIREGS *ar, bool enable)
}
}
-static inline int64_t acpi_pm_tmr_get_clock(void)
-{
- return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY,
- NANOSECONDS_PER_SECOND);
-}
-
void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar)
{
int64_t d = acpi_pm_tmr_get_clock();
@@ -698,7 +692,7 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
}
void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq,
- AcpiEventStatusBits status)
+ AcpiGPEStatusBits status)
{
ar->gpe.sts[0] |= status;
acpi_update_sci(ar, irq);
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
deleted file mode 100644
index c13b65c2c..000000000
--- a/hw/acpi/cpu.c
+++ /dev/null
@@ -1,561 +0,0 @@
-#include "qemu/osdep.h"
-#include "hw/boards.h"
-#include "hw/acpi/cpu.h"
-#include "qapi/error.h"
-#include "qapi-event.h"
-#include "trace.h"
-
-#define ACPI_CPU_HOTPLUG_REG_LEN 12
-#define ACPI_CPU_SELECTOR_OFFSET_WR 0
-#define ACPI_CPU_FLAGS_OFFSET_RW 4
-#define ACPI_CPU_CMD_OFFSET_WR 5
-#define ACPI_CPU_CMD_DATA_OFFSET_RW 8
-
-enum {
- CPHP_GET_NEXT_CPU_WITH_EVENT_CMD = 0,
- CPHP_OST_EVENT_CMD = 1,
- CPHP_OST_STATUS_CMD = 2,
- CPHP_CMD_MAX
-};
-
-static ACPIOSTInfo *acpi_cpu_device_status(int idx, AcpiCpuStatus *cdev)
-{
- ACPIOSTInfo *info = g_new0(ACPIOSTInfo, 1);
-
- info->slot_type = ACPI_SLOT_TYPE_CPU;
- info->slot = g_strdup_printf("%d", idx);
- info->source = cdev->ost_event;
- info->status = cdev->ost_status;
- if (cdev->cpu) {
- DeviceState *dev = DEVICE(cdev->cpu);
- if (dev->id) {
- info->device = g_strdup(dev->id);
- info->has_device = true;
- }
- }
- return info;
-}
-
-void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list)
-{
- int i;
-
- for (i = 0; i < cpu_st->dev_count; i++) {
- ACPIOSTInfoList *elem = g_new0(ACPIOSTInfoList, 1);
- elem->value = acpi_cpu_device_status(i, &cpu_st->devs[i]);
- elem->next = NULL;
- **list = elem;
- *list = &elem->next;
- }
-}
-
-static uint64_t cpu_hotplug_rd(void *opaque, hwaddr addr, unsigned size)
-{
- uint64_t val = 0;
- CPUHotplugState *cpu_st = opaque;
- AcpiCpuStatus *cdev;
-
- if (cpu_st->selector >= cpu_st->dev_count) {
- return val;
- }
-
- cdev = &cpu_st->devs[cpu_st->selector];
- switch (addr) {
- case ACPI_CPU_FLAGS_OFFSET_RW: /* pack and return is_* fields */
- val |= cdev->cpu ? 1 : 0;
- val |= cdev->is_inserting ? 2 : 0;
- val |= cdev->is_removing ? 4 : 0;
- trace_cpuhp_acpi_read_flags(cpu_st->selector, val);
- break;
- case ACPI_CPU_CMD_DATA_OFFSET_RW:
- switch (cpu_st->command) {
- case CPHP_GET_NEXT_CPU_WITH_EVENT_CMD:
- val = cpu_st->selector;
- break;
- default:
- break;
- }
- trace_cpuhp_acpi_read_cmd_data(cpu_st->selector, val);
- break;
- default:
- break;
- }
- return val;
-}
-
-static void cpu_hotplug_wr(void *opaque, hwaddr addr, uint64_t data,
- unsigned int size)
-{
- CPUHotplugState *cpu_st = opaque;
- AcpiCpuStatus *cdev;
- ACPIOSTInfo *info;
-
- assert(cpu_st->dev_count);
-
- if (addr) {
- if (cpu_st->selector >= cpu_st->dev_count) {
- trace_cpuhp_acpi_invalid_idx_selected(cpu_st->selector);
- return;
- }
- }
-
- switch (addr) {
- case ACPI_CPU_SELECTOR_OFFSET_WR: /* current CPU selector */
- cpu_st->selector = data;
- trace_cpuhp_acpi_write_idx(cpu_st->selector);
- break;
- case ACPI_CPU_FLAGS_OFFSET_RW: /* set is_* fields */
- cdev = &cpu_st->devs[cpu_st->selector];
- if (data & 2) { /* clear insert event */
- cdev->is_inserting = false;
- trace_cpuhp_acpi_clear_inserting_evt(cpu_st->selector);
- } else if (data & 4) { /* clear remove event */
- cdev->is_removing = false;
- trace_cpuhp_acpi_clear_remove_evt(cpu_st->selector);
- } else if (data & 8) {
- DeviceState *dev = NULL;
- HotplugHandler *hotplug_ctrl = NULL;
-
- if (!cdev->cpu) {
- trace_cpuhp_acpi_ejecting_invalid_cpu(cpu_st->selector);
- break;
- }
-
- trace_cpuhp_acpi_ejecting_cpu(cpu_st->selector);
- dev = DEVICE(cdev->cpu);
- hotplug_ctrl = qdev_get_hotplug_handler(dev);
- hotplug_handler_unplug(hotplug_ctrl, dev, NULL);
- }
- break;
- case ACPI_CPU_CMD_OFFSET_WR:
- trace_cpuhp_acpi_write_cmd(cpu_st->selector, data);
- if (data < CPHP_CMD_MAX) {
- cpu_st->command = data;
- if (cpu_st->command == CPHP_GET_NEXT_CPU_WITH_EVENT_CMD) {
- uint32_t iter = cpu_st->selector;
-
- do {
- cdev = &cpu_st->devs[iter];
- if (cdev->is_inserting || cdev->is_removing) {
- cpu_st->selector = iter;
- trace_cpuhp_acpi_cpu_has_events(cpu_st->selector,
- cdev->is_inserting, cdev->is_removing);
- break;
- }
- iter = iter + 1 < cpu_st->dev_count ? iter + 1 : 0;
- } while (iter != cpu_st->selector);
- }
- }
- break;
- case ACPI_CPU_CMD_DATA_OFFSET_RW:
- switch (cpu_st->command) {
- case CPHP_OST_EVENT_CMD: {
- cdev = &cpu_st->devs[cpu_st->selector];
- cdev->ost_event = data;
- trace_cpuhp_acpi_write_ost_ev(cpu_st->selector, cdev->ost_event);
- break;
- }
- case CPHP_OST_STATUS_CMD: {
- cdev = &cpu_st->devs[cpu_st->selector];
- cdev->ost_status = data;
- info = acpi_cpu_device_status(cpu_st->selector, cdev);
- qapi_event_send_acpi_device_ost(info, &error_abort);
- qapi_free_ACPIOSTInfo(info);
- trace_cpuhp_acpi_write_ost_status(cpu_st->selector,
- cdev->ost_status);
- break;
- }
- default:
- break;
- }
- break;
- default:
- break;
- }
-}
-
-static const MemoryRegionOps cpu_hotplug_ops = {
- .read = cpu_hotplug_rd,
- .write = cpu_hotplug_wr,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 4,
- },
-};
-
-void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
- CPUHotplugState *state, hwaddr base_addr)
-{
- MachineState *machine = MACHINE(qdev_get_machine());
- MachineClass *mc = MACHINE_GET_CLASS(machine);
- CPUArchIdList *id_list;
- int i;
-
- assert(mc->possible_cpu_arch_ids);
- id_list = mc->possible_cpu_arch_ids(machine);
- state->dev_count = id_list->len;
- state->devs = g_new0(typeof(*state->devs), state->dev_count);
- for (i = 0; i < id_list->len; i++) {
- state->devs[i].cpu = id_list->cpus[i].cpu;
- state->devs[i].arch_id = id_list->cpus[i].arch_id;
- }
- g_free(id_list);
- memory_region_init_io(&state->ctrl_reg, owner, &cpu_hotplug_ops, state,
- "acpi-mem-hotplug", ACPI_CPU_HOTPLUG_REG_LEN);
- memory_region_add_subregion(as, base_addr, &state->ctrl_reg);
-}
-
-static AcpiCpuStatus *get_cpu_status(CPUHotplugState *cpu_st, DeviceState *dev)
-{
- CPUClass *k = CPU_GET_CLASS(dev);
- uint64_t cpu_arch_id = k->get_arch_id(CPU(dev));
- int i;
-
- for (i = 0; i < cpu_st->dev_count; i++) {
- if (cpu_arch_id == cpu_st->devs[i].arch_id) {
- return &cpu_st->devs[i];
- }
- }
- return NULL;
-}
-
-void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
- CPUHotplugState *cpu_st, DeviceState *dev, Error **errp)
-{
- AcpiCpuStatus *cdev;
-
- cdev = get_cpu_status(cpu_st, dev);
- if (!cdev) {
- return;
- }
-
- cdev->cpu = CPU(dev);
- if (dev->hotplugged) {
- cdev->is_inserting = true;
- acpi_send_event(DEVICE(hotplug_dev), ACPI_CPU_HOTPLUG_STATUS);
- }
-}
-
-void acpi_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
- CPUHotplugState *cpu_st,
- DeviceState *dev, Error **errp)
-{
- AcpiCpuStatus *cdev;
-
- cdev = get_cpu_status(cpu_st, dev);
- if (!cdev) {
- return;
- }
-
- cdev->is_removing = true;
- acpi_send_event(DEVICE(hotplug_dev), ACPI_CPU_HOTPLUG_STATUS);
-}
-
-void acpi_cpu_unplug_cb(CPUHotplugState *cpu_st,
- DeviceState *dev, Error **errp)
-{
- AcpiCpuStatus *cdev;
-
- cdev = get_cpu_status(cpu_st, dev);
- if (!cdev) {
- return;
- }
-
- cdev->cpu = NULL;
-}
-
-static const VMStateDescription vmstate_cpuhp_sts = {
- .name = "CPU hotplug device state",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .fields = (VMStateField[]) {
- VMSTATE_BOOL(is_inserting, AcpiCpuStatus),
- VMSTATE_BOOL(is_removing, AcpiCpuStatus),
- VMSTATE_UINT32(ost_event, AcpiCpuStatus),
- VMSTATE_UINT32(ost_status, AcpiCpuStatus),
- VMSTATE_END_OF_LIST()
- }
-};
-
-const VMStateDescription vmstate_cpu_hotplug = {
- .name = "CPU hotplug state",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(selector, CPUHotplugState),
- VMSTATE_UINT8(command, CPUHotplugState),
- VMSTATE_STRUCT_VARRAY_POINTER_UINT32(devs, CPUHotplugState, dev_count,
- vmstate_cpuhp_sts, AcpiCpuStatus),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define CPU_NAME_FMT "C%.03X"
-#define CPUHP_RES_DEVICE "PRES"
-#define CPU_LOCK "CPLK"
-#define CPU_STS_METHOD "CSTA"
-#define CPU_SCAN_METHOD "CSCN"
-#define CPU_NOTIFY_METHOD "CTFY"
-#define CPU_EJECT_METHOD "CEJ0"
-#define CPU_OST_METHOD "COST"
-
-#define CPU_ENABLED "CPEN"
-#define CPU_SELECTOR "CSEL"
-#define CPU_COMMAND "CCMD"
-#define CPU_DATA "CDAT"
-#define CPU_INSERT_EVENT "CINS"
-#define CPU_REMOVE_EVENT "CRMV"
-#define CPU_EJECT_EVENT "CEJ0"
-
-void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
- hwaddr io_base,
- const char *res_root,
- const char *event_handler_method)
-{
- Aml *ifctx;
- Aml *field;
- Aml *method;
- Aml *cpu_ctrl_dev;
- Aml *cpus_dev;
- Aml *zero = aml_int(0);
- Aml *one = aml_int(1);
- Aml *sb_scope = aml_scope("_SB");
- MachineClass *mc = MACHINE_GET_CLASS(machine);
- CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
- char *cphp_res_path = g_strdup_printf("%s." CPUHP_RES_DEVICE, res_root);
- Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, NULL);
- AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
- AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
-
- cpu_ctrl_dev = aml_device("%s", cphp_res_path);
- {
- Aml *crs;
-
- aml_append(cpu_ctrl_dev,
- aml_name_decl("_HID", aml_eisaid("PNP0A06")));
- aml_append(cpu_ctrl_dev,
- aml_name_decl("_UID", aml_string("CPU Hotplug resources")));
- aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0));
-
- crs = aml_resource_template();
- aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1,
- ACPI_CPU_HOTPLUG_REG_LEN));
- aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs));
-
- /* declare CPU hotplug MMIO region with related access fields */
- aml_append(cpu_ctrl_dev,
- aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base),
- ACPI_CPU_HOTPLUG_REG_LEN));
-
- field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK,
- AML_WRITE_AS_ZEROS);
- aml_append(field, aml_reserved_field(ACPI_CPU_FLAGS_OFFSET_RW * 8));
- /* 1 if enabled, read only */
- aml_append(field, aml_named_field(CPU_ENABLED, 1));
- /* (read) 1 if has a insert event. (write) 1 to clear event */
- aml_append(field, aml_named_field(CPU_INSERT_EVENT, 1));
- /* (read) 1 if has a remove event. (write) 1 to clear event */
- aml_append(field, aml_named_field(CPU_REMOVE_EVENT, 1));
- /* initiates device eject, write only */
- aml_append(field, aml_named_field(CPU_EJECT_EVENT, 1));
- aml_append(field, aml_reserved_field(4));
- aml_append(field, aml_named_field(CPU_COMMAND, 8));
- aml_append(cpu_ctrl_dev, field);
-
- field = aml_field("PRST", AML_DWORD_ACC, AML_NOLOCK, AML_PRESERVE);
- /* CPU selector, write only */
- aml_append(field, aml_named_field(CPU_SELECTOR, 32));
- /* flags + cmd + 2byte align */
- aml_append(field, aml_reserved_field(4 * 8));
- aml_append(field, aml_named_field(CPU_DATA, 32));
- aml_append(cpu_ctrl_dev, field);
-
- if (opts.has_legacy_cphp) {
- method = aml_method("_INI", 0, AML_SERIALIZED);
- /* switch off legacy CPU hotplug HW and use new one,
- * on reboot system is in new mode and writing 0
- * in CPU_SELECTOR selects BSP, which is NOP at
- * the time _INI is called */
- aml_append(method, aml_store(zero, aml_name(CPU_SELECTOR)));
- aml_append(cpu_ctrl_dev, method);
- }
- }
- aml_append(sb_scope, cpu_ctrl_dev);
-
- cpus_dev = aml_device("\\_SB.CPUS");
- {
- int i;
- Aml *ctrl_lock = aml_name("%s.%s", cphp_res_path, CPU_LOCK);
- Aml *cpu_selector = aml_name("%s.%s", cphp_res_path, CPU_SELECTOR);
- Aml *is_enabled = aml_name("%s.%s", cphp_res_path, CPU_ENABLED);
- Aml *cpu_cmd = aml_name("%s.%s", cphp_res_path, CPU_COMMAND);
- Aml *cpu_data = aml_name("%s.%s", cphp_res_path, CPU_DATA);
- Aml *ins_evt = aml_name("%s.%s", cphp_res_path, CPU_INSERT_EVENT);
- Aml *rm_evt = aml_name("%s.%s", cphp_res_path, CPU_REMOVE_EVENT);
- Aml *ej_evt = aml_name("%s.%s", cphp_res_path, CPU_EJECT_EVENT);
-
- aml_append(cpus_dev, aml_name_decl("_HID", aml_string("ACPI0010")));
- aml_append(cpus_dev, aml_name_decl("_CID", aml_eisaid("PNP0A05")));
-
- method = aml_method(CPU_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
- for (i = 0; i < arch_ids->len; i++) {
- Aml *cpu = aml_name(CPU_NAME_FMT, i);
- Aml *uid = aml_arg(0);
- Aml *event = aml_arg(1);
-
- ifctx = aml_if(aml_equal(uid, aml_int(i)));
- {
- aml_append(ifctx, aml_notify(cpu, event));
- }
- aml_append(method, ifctx);
- }
- aml_append(cpus_dev, method);
-
- method = aml_method(CPU_STS_METHOD, 1, AML_SERIALIZED);
- {
- Aml *idx = aml_arg(0);
- Aml *sta = aml_local(0);
-
- aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
- aml_append(method, aml_store(idx, cpu_selector));
- aml_append(method, aml_store(zero, sta));
- ifctx = aml_if(aml_equal(is_enabled, one));
- {
- aml_append(ifctx, aml_store(aml_int(0xF), sta));
- }
- aml_append(method, ifctx);
- aml_append(method, aml_release(ctrl_lock));
- aml_append(method, aml_return(sta));
- }
- aml_append(cpus_dev, method);
-
- method = aml_method(CPU_EJECT_METHOD, 1, AML_SERIALIZED);
- {
- Aml *idx = aml_arg(0);
-
- aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
- aml_append(method, aml_store(idx, cpu_selector));
- aml_append(method, aml_store(one, ej_evt));
- aml_append(method, aml_release(ctrl_lock));
- }
- aml_append(cpus_dev, method);
-
- method = aml_method(CPU_SCAN_METHOD, 0, AML_SERIALIZED);
- {
- Aml *else_ctx;
- Aml *while_ctx;
- Aml *has_event = aml_local(0);
- Aml *dev_chk = aml_int(1);
- Aml *eject_req = aml_int(3);
- Aml *next_cpu_cmd = aml_int(CPHP_GET_NEXT_CPU_WITH_EVENT_CMD);
-
- aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
- aml_append(method, aml_store(one, has_event));
- while_ctx = aml_while(aml_equal(has_event, one));
- {
- /* clear loop exit condition, ins_evt/rm_evt checks
- * will set it to 1 while next_cpu_cmd returns a CPU
- * with events */
- aml_append(while_ctx, aml_store(zero, has_event));
- aml_append(while_ctx, aml_store(next_cpu_cmd, cpu_cmd));
- ifctx = aml_if(aml_equal(ins_evt, one));
- {
- aml_append(ifctx,
- aml_call2(CPU_NOTIFY_METHOD, cpu_data, dev_chk));
- aml_append(ifctx, aml_store(one, ins_evt));
- aml_append(ifctx, aml_store(one, has_event));
- }
- aml_append(while_ctx, ifctx);
- else_ctx = aml_else();
- ifctx = aml_if(aml_equal(rm_evt, one));
- {
- aml_append(ifctx,
- aml_call2(CPU_NOTIFY_METHOD, cpu_data, eject_req));
- aml_append(ifctx, aml_store(one, rm_evt));
- aml_append(ifctx, aml_store(one, has_event));
- }
- aml_append(else_ctx, ifctx);
- aml_append(while_ctx, else_ctx);
- }
- aml_append(method, while_ctx);
- aml_append(method, aml_release(ctrl_lock));
- }
- aml_append(cpus_dev, method);
-
- method = aml_method(CPU_OST_METHOD, 4, AML_SERIALIZED);
- {
- Aml *uid = aml_arg(0);
- Aml *ev_cmd = aml_int(CPHP_OST_EVENT_CMD);
- Aml *st_cmd = aml_int(CPHP_OST_STATUS_CMD);
-
- aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
- aml_append(method, aml_store(uid, cpu_selector));
- aml_append(method, aml_store(ev_cmd, cpu_cmd));
- aml_append(method, aml_store(aml_arg(1), cpu_data));
- aml_append(method, aml_store(st_cmd, cpu_cmd));
- aml_append(method, aml_store(aml_arg(2), cpu_data));
- aml_append(method, aml_release(ctrl_lock));
- }
- aml_append(cpus_dev, method);
-
- /* build Processor object for each processor */
- for (i = 0; i < arch_ids->len; i++) {
- Aml *dev;
- Aml *uid = aml_int(i);
- GArray *madt_buf = g_array_new(0, 1, 1);
- int arch_id = arch_ids->cpus[i].arch_id;
-
- if (opts.apci_1_compatible && arch_id < 255) {
- dev = aml_processor(i, 0, 0, CPU_NAME_FMT, i);
- } else {
- dev = aml_device(CPU_NAME_FMT, i);
- aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
- aml_append(dev, aml_name_decl("_UID", uid));
- }
-
- method = aml_method("_STA", 0, AML_SERIALIZED);
- aml_append(method, aml_return(aml_call1(CPU_STS_METHOD, uid)));
- aml_append(dev, method);
-
- /* build _MAT object */
- assert(adevc && adevc->madt_cpu);
- adevc->madt_cpu(adev, i, arch_ids, madt_buf);
- switch (madt_buf->data[0]) {
- case ACPI_APIC_PROCESSOR: {
- AcpiMadtProcessorApic *apic = (void *)madt_buf->data;
- apic->flags = cpu_to_le32(1);
- break;
- }
- default:
- assert(0);
- }
- aml_append(dev, aml_name_decl("_MAT",
- aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data)));
- g_array_free(madt_buf, true);
-
- method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
- aml_append(method, aml_call1(CPU_EJECT_METHOD, uid));
- aml_append(dev, method);
-
- method = aml_method("_OST", 3, AML_SERIALIZED);
- aml_append(method,
- aml_call4(CPU_OST_METHOD, uid, aml_arg(0),
- aml_arg(1), aml_arg(2))
- );
- aml_append(dev, method);
- aml_append(cpus_dev, dev);
- }
- }
- aml_append(sb_scope, cpus_dev);
- aml_append(table, sb_scope);
-
- method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
- aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
- aml_append(table, method);
-
- g_free(cphp_res_path);
- g_free(arch_ids);
-}
diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
index e19d90206..4d86743fd 100644
--- a/hw/acpi/cpu_hotplug.c
+++ b/hw/acpi/cpu_hotplug.c
@@ -14,14 +14,6 @@
#include "hw/acpi/cpu_hotplug.h"
#include "qapi/error.h"
#include "qom/cpu.h"
-#include "hw/i386/pc.h"
-
-#define CPU_EJECT_METHOD "CPEJ"
-#define CPU_MAT_METHOD "CPMA"
-#define CPU_ON_BITMAP "CPON"
-#define CPU_STATUS_METHOD "CPST"
-#define CPU_STATUS_MAP "PRS"
-#define CPU_SCAN_METHOD "PRSC"
static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
{
@@ -34,15 +26,7 @@ static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
unsigned int size)
{
- /* firmware never used to write in CPU present bitmap so use
- this fact as means to switch QEMU into modern CPU hotplug
- mode by writing 0 at the beginning of legacy CPU bitmap
- */
- if (addr == 0 && data == 0) {
- AcpiCpuHotplug *cpus = opaque;
- object_property_set_bool(cpus->device, false, "cpu-hotplug-legacy",
- &error_abort);
- }
+ /* TODO: implement VCPU removal on guest signal that CPU can be removed */
}
static const MemoryRegionOps AcpiCpuHotplug_ops = {
@@ -70,18 +54,19 @@ static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu,
g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
}
-void legacy_acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
- AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
+void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
+ AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
{
acpi_set_cpu_present_bit(g, CPU(dev), errp);
if (*errp != NULL) {
return;
}
- acpi_send_event(DEVICE(hotplug_dev), ACPI_CPU_HOTPLUG_STATUS);
+
+ acpi_send_gpe_event(ar, irq, ACPI_CPU_HOTPLUG_STATUS);
}
-void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
- AcpiCpuHotplug *gpe_cpu, uint16_t base)
+void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
+ AcpiCpuHotplug *gpe_cpu, uint16_t base)
{
CPUState *cpu;
@@ -91,242 +76,4 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
memory_region_init_io(&gpe_cpu->io, owner, &AcpiCpuHotplug_ops,
gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
memory_region_add_subregion(parent, base, &gpe_cpu->io);
- gpe_cpu->device = owner;
-}
-
-void acpi_switch_to_modern_cphp(AcpiCpuHotplug *gpe_cpu,
- CPUHotplugState *cpuhp_state,
- uint16_t io_port)
-{
- MemoryRegion *parent = pci_address_space_io(PCI_DEVICE(gpe_cpu->device));
-
- memory_region_del_subregion(parent, &gpe_cpu->io);
- cpu_hotplug_hw_init(parent, gpe_cpu->device, cpuhp_state, io_port);
-}
-
-void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
- uint16_t io_base)
-{
- Aml *dev;
- Aml *crs;
- Aml *pkg;
- Aml *field;
- Aml *method;
- Aml *if_ctx;
- Aml *else_ctx;
- int i, apic_idx;
- Aml *sb_scope = aml_scope("_SB");
- uint8_t madt_tmpl[8] = {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0};
- Aml *cpu_id = aml_arg(1);
- Aml *apic_id = aml_arg(0);
- Aml *cpu_on = aml_local(0);
- Aml *madt = aml_local(1);
- Aml *cpus_map = aml_name(CPU_ON_BITMAP);
- Aml *zero = aml_int(0);
- Aml *one = aml_int(1);
- MachineClass *mc = MACHINE_GET_CLASS(machine);
- CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
- PCMachineState *pcms = PC_MACHINE(machine);
-
- /*
- * _MAT method - creates an madt apic buffer
- * apic_id = Arg0 = Local APIC ID
- * cpu_id = Arg1 = Processor ID
- * cpu_on = Local0 = CPON flag for this cpu
- * madt = Local1 = Buffer (in madt apic form) to return
- */
- method = aml_method(CPU_MAT_METHOD, 2, AML_NOTSERIALIZED);
- aml_append(method,
- aml_store(aml_derefof(aml_index(cpus_map, apic_id)), cpu_on));
- aml_append(method,
- aml_store(aml_buffer(sizeof(madt_tmpl), madt_tmpl), madt));
- /* Update the processor id, lapic id, and enable/disable status */
- aml_append(method, aml_store(cpu_id, aml_index(madt, aml_int(2))));
- aml_append(method, aml_store(apic_id, aml_index(madt, aml_int(3))));
- aml_append(method, aml_store(cpu_on, aml_index(madt, aml_int(4))));
- aml_append(method, aml_return(madt));
- aml_append(sb_scope, method);
-
- /*
- * _STA method - return ON status of cpu
- * apic_id = Arg0 = Local APIC ID
- * cpu_on = Local0 = CPON flag for this cpu
- */
- method = aml_method(CPU_STATUS_METHOD, 1, AML_NOTSERIALIZED);
- aml_append(method,
- aml_store(aml_derefof(aml_index(cpus_map, apic_id)), cpu_on));
- if_ctx = aml_if(cpu_on);
- {
- aml_append(if_ctx, aml_return(aml_int(0xF)));
- }
- aml_append(method, if_ctx);
- else_ctx = aml_else();
- {
- aml_append(else_ctx, aml_return(zero));
- }
- aml_append(method, else_ctx);
- aml_append(sb_scope, method);
-
- method = aml_method(CPU_EJECT_METHOD, 2, AML_NOTSERIALIZED);
- aml_append(method, aml_sleep(200));
- aml_append(sb_scope, method);
-
- method = aml_method(CPU_SCAN_METHOD, 0, AML_NOTSERIALIZED);
- {
- Aml *while_ctx, *if_ctx2, *else_ctx2;
- Aml *bus_check_evt = aml_int(1);
- Aml *remove_evt = aml_int(3);
- Aml *status_map = aml_local(5); /* Local5 = active cpu bitmap */
- Aml *byte = aml_local(2); /* Local2 = last read byte from bitmap */
- Aml *idx = aml_local(0); /* Processor ID / APIC ID iterator */
- Aml *is_cpu_on = aml_local(1); /* Local1 = CPON flag for cpu */
- Aml *status = aml_local(3); /* Local3 = active state for cpu */
-
- aml_append(method, aml_store(aml_name(CPU_STATUS_MAP), status_map));
- aml_append(method, aml_store(zero, byte));
- aml_append(method, aml_store(zero, idx));
-
- /* While (idx < SizeOf(CPON)) */
- while_ctx = aml_while(aml_lless(idx, aml_sizeof(cpus_map)));
- aml_append(while_ctx,
- aml_store(aml_derefof(aml_index(cpus_map, idx)), is_cpu_on));
-
- if_ctx = aml_if(aml_and(idx, aml_int(0x07), NULL));
- {
- /* Shift down previously read bitmap byte */
- aml_append(if_ctx, aml_shiftright(byte, one, byte));
- }
- aml_append(while_ctx, if_ctx);
-
- else_ctx = aml_else();
- {
- /* Read next byte from cpu bitmap */
- aml_append(else_ctx, aml_store(aml_derefof(aml_index(status_map,
- aml_shiftright(idx, aml_int(3), NULL))), byte));
- }
- aml_append(while_ctx, else_ctx);
-
- aml_append(while_ctx, aml_store(aml_and(byte, one, NULL), status));
- if_ctx = aml_if(aml_lnot(aml_equal(is_cpu_on, status)));
- {
- /* State change - update CPON with new state */
- aml_append(if_ctx, aml_store(status, aml_index(cpus_map, idx)));
- if_ctx2 = aml_if(aml_equal(status, one));
- {
- aml_append(if_ctx2,
- aml_call2(AML_NOTIFY_METHOD, idx, bus_check_evt));
- }
- aml_append(if_ctx, if_ctx2);
- else_ctx2 = aml_else();
- {
- aml_append(else_ctx2,
- aml_call2(AML_NOTIFY_METHOD, idx, remove_evt));
- }
- }
- aml_append(if_ctx, else_ctx2);
- aml_append(while_ctx, if_ctx);
-
- aml_append(while_ctx, aml_increment(idx)); /* go to next cpu */
- aml_append(method, while_ctx);
- }
- aml_append(sb_scope, method);
-
- /* The current AML generator can cover the APIC ID range [0..255],
- * inclusive, for VCPU hotplug. */
- QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
- g_assert(pcms->apic_id_limit <= ACPI_CPU_HOTPLUG_ID_LIMIT);
-
- /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
- dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
- aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06")));
- aml_append(dev,
- aml_name_decl("_UID", aml_string("CPU Hotplug resources"))
- );
- /* device present, functioning, decoding, not shown in UI */
- aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
- crs = aml_resource_template();
- aml_append(crs,
- aml_io(AML_DECODE16, io_base, io_base, 1, ACPI_GPE_PROC_LEN)
- );
- aml_append(dev, aml_name_decl("_CRS", crs));
- aml_append(sb_scope, dev);
- /* declare CPU hotplug MMIO region and PRS field to access it */
- aml_append(sb_scope, aml_operation_region(
- "PRST", AML_SYSTEM_IO, aml_int(io_base), ACPI_GPE_PROC_LEN));
- field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
- aml_append(field, aml_named_field("PRS", 256));
- aml_append(sb_scope, field);
-
- /* build Processor object for each processor */
- for (i = 0; i < apic_ids->len; i++) {
- int apic_id = apic_ids->cpus[i].arch_id;
-
- assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT);
-
- dev = aml_processor(i, 0, 0, "CP%.02X", apic_id);
-
- method = aml_method("_MAT", 0, AML_NOTSERIALIZED);
- aml_append(method,
- aml_return(aml_call2(CPU_MAT_METHOD, aml_int(apic_id), aml_int(i))
- ));
- aml_append(dev, method);
-
- method = aml_method("_STA", 0, AML_NOTSERIALIZED);
- aml_append(method,
- aml_return(aml_call1(CPU_STATUS_METHOD, aml_int(apic_id))));
- aml_append(dev, method);
-
- method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
- aml_append(method,
- aml_return(aml_call2(CPU_EJECT_METHOD, aml_int(apic_id),
- aml_arg(0)))
- );
- aml_append(dev, method);
-
- aml_append(sb_scope, dev);
- }
-
- /* build this code:
- * Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
- */
- /* Arg0 = APIC ID */
- method = aml_method(AML_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
- for (i = 0; i < apic_ids->len; i++) {
- int apic_id = apic_ids->cpus[i].arch_id;
-
- if_ctx = aml_if(aml_equal(aml_arg(0), aml_int(apic_id)));
- aml_append(if_ctx,
- aml_notify(aml_name("CP%.02X", apic_id), aml_arg(1))
- );
- aml_append(method, if_ctx);
- }
- aml_append(sb_scope, method);
-
- /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
- *
- * Note: The ability to create variable-sized packages was first
- * introduced in ACPI 2.0. ACPI 1.0 only allowed fixed-size packages
- * ith up to 255 elements. Windows guests up to win2k8 fail when
- * VarPackageOp is used.
- */
- pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) :
- aml_varpackage(pcms->apic_id_limit);
-
- for (i = 0, apic_idx = 0; i < apic_ids->len; i++) {
- int apic_id = apic_ids->cpus[i].arch_id;
-
- for (; apic_idx < apic_id; apic_idx++) {
- aml_append(pkg, aml_int(0));
- }
- aml_append(pkg, aml_int(apic_ids->cpus[i].cpu ? 1 : 0));
- apic_idx = apic_id + 1;
- }
- aml_append(sb_scope, aml_name_decl(CPU_ON_BITMAP, pkg));
- g_free(apic_ids);
-
- aml_append(ctx, sb_scope);
-
- method = aml_method("\\_GPE._E02", 0, AML_NOTSERIALIZED);
- aml_append(method, aml_call0("\\_SB." CPU_SCAN_METHOD));
- aml_append(ctx, method);
}
diff --git a/hw/acpi/cpu_hotplug_acpi_table.c b/hw/acpi/cpu_hotplug_acpi_table.c
new file mode 100644
index 000000000..97bb1092a
--- /dev/null
+++ b/hw/acpi/cpu_hotplug_acpi_table.c
@@ -0,0 +1,136 @@
+/*
+ * 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/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/cpu_hotplug.h"
+
+void build_cpu_hotplug_aml(Aml *ctx)
+{
+ Aml *method;
+ Aml *if_ctx;
+ Aml *else_ctx;
+ Aml *sb_scope = aml_scope("_SB");
+ uint8_t madt_tmpl[8] = {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0};
+ Aml *cpu_id = aml_arg(0);
+ Aml *cpu_on = aml_local(0);
+ Aml *madt = aml_local(1);
+ Aml *cpus_map = aml_name(CPU_ON_BITMAP);
+ Aml *zero = aml_int(0);
+ Aml *one = aml_int(1);
+
+ /*
+ * _MAT method - creates an madt apic buffer
+ * cpu_id = Arg0 = Processor ID = Local APIC ID
+ * cpu_on = Local0 = CPON flag for this cpu
+ * madt = Local1 = Buffer (in madt apic form) to return
+ */
+ method = aml_method(CPU_MAT_METHOD, 1, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_store(aml_derefof(aml_index(cpus_map, cpu_id)), cpu_on));
+ aml_append(method,
+ aml_store(aml_buffer(sizeof(madt_tmpl), madt_tmpl), madt));
+ /* Update the processor id, lapic id, and enable/disable status */
+ aml_append(method, aml_store(cpu_id, aml_index(madt, aml_int(2))));
+ aml_append(method, aml_store(cpu_id, aml_index(madt, aml_int(3))));
+ aml_append(method, aml_store(cpu_on, aml_index(madt, aml_int(4))));
+ aml_append(method, aml_return(madt));
+ aml_append(sb_scope, method);
+
+ /*
+ * _STA method - return ON status of cpu
+ * cpu_id = Arg0 = Processor ID = Local APIC ID
+ * cpu_on = Local0 = CPON flag for this cpu
+ */
+ method = aml_method(CPU_STATUS_METHOD, 1, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_store(aml_derefof(aml_index(cpus_map, cpu_id)), cpu_on));
+ if_ctx = aml_if(cpu_on);
+ {
+ aml_append(if_ctx, aml_return(aml_int(0xF)));
+ }
+ aml_append(method, if_ctx);
+ else_ctx = aml_else();
+ {
+ aml_append(else_ctx, aml_return(zero));
+ }
+ aml_append(method, else_ctx);
+ aml_append(sb_scope, method);
+
+ method = aml_method(CPU_EJECT_METHOD, 2, AML_NOTSERIALIZED);
+ aml_append(method, aml_sleep(200));
+ aml_append(sb_scope, method);
+
+ method = aml_method(CPU_SCAN_METHOD, 0, AML_NOTSERIALIZED);
+ {
+ Aml *while_ctx, *if_ctx2, *else_ctx2;
+ Aml *bus_check_evt = aml_int(1);
+ Aml *remove_evt = aml_int(3);
+ Aml *status_map = aml_local(5); /* Local5 = active cpu bitmap */
+ Aml *byte = aml_local(2); /* Local2 = last read byte from bitmap */
+ Aml *idx = aml_local(0); /* Processor ID / APIC ID iterator */
+ Aml *is_cpu_on = aml_local(1); /* Local1 = CPON flag for cpu */
+ Aml *status = aml_local(3); /* Local3 = active state for cpu */
+
+ aml_append(method, aml_store(aml_name(CPU_STATUS_MAP), status_map));
+ aml_append(method, aml_store(zero, byte));
+ aml_append(method, aml_store(zero, idx));
+
+ /* While (idx < SizeOf(CPON)) */
+ while_ctx = aml_while(aml_lless(idx, aml_sizeof(cpus_map)));
+ aml_append(while_ctx,
+ aml_store(aml_derefof(aml_index(cpus_map, idx)), is_cpu_on));
+
+ if_ctx = aml_if(aml_and(idx, aml_int(0x07), NULL));
+ {
+ /* Shift down previously read bitmap byte */
+ aml_append(if_ctx, aml_shiftright(byte, one, byte));
+ }
+ aml_append(while_ctx, if_ctx);
+
+ else_ctx = aml_else();
+ {
+ /* Read next byte from cpu bitmap */
+ aml_append(else_ctx, aml_store(aml_derefof(aml_index(status_map,
+ aml_shiftright(idx, aml_int(3), NULL))), byte));
+ }
+ aml_append(while_ctx, else_ctx);
+
+ aml_append(while_ctx, aml_store(aml_and(byte, one, NULL), status));
+ if_ctx = aml_if(aml_lnot(aml_equal(is_cpu_on, status)));
+ {
+ /* State change - update CPON with new state */
+ aml_append(if_ctx, aml_store(status, aml_index(cpus_map, idx)));
+ if_ctx2 = aml_if(aml_equal(status, one));
+ {
+ aml_append(if_ctx2,
+ aml_call2(AML_NOTIFY_METHOD, idx, bus_check_evt));
+ }
+ aml_append(if_ctx, if_ctx2);
+ else_ctx2 = aml_else();
+ {
+ aml_append(else_ctx2,
+ aml_call2(AML_NOTIFY_METHOD, idx, remove_evt));
+ }
+ }
+ aml_append(if_ctx, else_ctx2);
+ aml_append(while_ctx, if_ctx);
+
+ aml_append(while_ctx, aml_increment(idx)); /* go to next cpu */
+ aml_append(method, while_ctx);
+ }
+ aml_append(sb_scope, method);
+
+ aml_append(ctx, sb_scope);
+}
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index e5a3c18e5..27e978f5f 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -189,33 +189,6 @@ static const VMStateDescription vmstate_tco_io_state = {
}
};
-static bool vmstate_test_use_cpuhp(void *opaque)
-{
- ICH9LPCPMRegs *s = opaque;
- return !s->cpu_hotplug_legacy;
-}
-
-static int vmstate_cpuhp_pre_load(void *opaque)
-{
- ICH9LPCPMRegs *s = opaque;
- Object *obj = OBJECT(s->gpe_cpu.device);
- object_property_set_bool(obj, false, "cpu-hotplug-legacy", &error_abort);
- return 0;
-}
-
-static const VMStateDescription vmstate_cpuhp_state = {
- .name = "ich9_pm/cpuhp",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .needed = vmstate_test_use_cpuhp,
- .pre_load = vmstate_cpuhp_pre_load,
- .fields = (VMStateField[]) {
- VMSTATE_CPU_HOTPLUG(cpuhp_state, ICH9LPCPMRegs),
- VMSTATE_END_OF_LIST()
- }
-};
-
const VMStateDescription vmstate_ich9_pm = {
.name = "ich9_pm",
.version_id = 1,
@@ -236,7 +209,6 @@ const VMStateDescription vmstate_ich9_pm = {
.subsections = (const VMStateDescription*[]) {
&vmstate_memhp_state,
&vmstate_tco_io_state,
- &vmstate_cpuhp_state,
NULL
}
};
@@ -301,8 +273,8 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
pm->powerdown_notifier.notify = pm_powerdown_req;
qemu_register_powerdown_notifier(&pm->powerdown_notifier);
- legacy_acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci),
- OBJECT(lpc_pci), &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
+ acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
+ &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
if (pm->acpi_memory_hotplug.is_enabled) {
acpi_memory_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
@@ -334,26 +306,6 @@ static void ich9_pm_set_memory_hotplug_support(Object *obj, bool value,
s->pm.acpi_memory_hotplug.is_enabled = value;
}
-static bool ich9_pm_get_cpu_hotplug_legacy(Object *obj, Error **errp)
-{
- ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
-
- return s->pm.cpu_hotplug_legacy;
-}
-
-static void ich9_pm_set_cpu_hotplug_legacy(Object *obj, bool value,
- Error **errp)
-{
- ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
-
- assert(!value);
- if (s->pm.cpu_hotplug_legacy && value == false) {
- acpi_switch_to_modern_cphp(&s->pm.gpe_cpu, &s->pm.cpuhp_state,
- ICH9_CPU_HOTPLUG_IO_BASE);
- }
- s->pm.cpu_hotplug_legacy = value;
-}
-
static void ich9_pm_get_disable_s3(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -445,7 +397,6 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
{
static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
pm->acpi_memory_hotplug.is_enabled = true;
- pm->cpu_hotplug_legacy = true;
pm->disable_s3 = 0;
pm->disable_s4 = 0;
pm->s4_val = 2;
@@ -461,10 +412,6 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
ich9_pm_get_memory_hotplug_support,
ich9_pm_set_memory_hotplug_support,
NULL);
- object_property_add_bool(obj, "cpu-hotplug-legacy",
- ich9_pm_get_cpu_hotplug_legacy,
- ich9_pm_set_cpu_hotplug_legacy,
- NULL);
object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8",
ich9_pm_get_disable_s3,
ich9_pm_set_disable_s3,
@@ -483,58 +430,39 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
NULL);
}
-void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
+void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp)
{
- ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
-
- if (lpc->pm.acpi_memory_hotplug.is_enabled &&
+ if (pm->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_plug_cb(hotplug_dev, &lpc->pm.acpi_memory_hotplug,
+ acpi_memory_plug_cb(&pm->acpi_regs, pm->irq, &pm->acpi_memory_hotplug,
dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
- if (lpc->pm.cpu_hotplug_legacy) {
- legacy_acpi_cpu_plug_cb(hotplug_dev, &lpc->pm.gpe_cpu, dev, errp);
- } else {
- acpi_cpu_plug_cb(hotplug_dev, &lpc->pm.cpuhp_state, dev, errp);
- }
+ acpi_cpu_plug_cb(&pm->acpi_regs, pm->irq, &pm->gpe_cpu, dev, errp);
} else {
error_setg(errp, "acpi: device plug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
-void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
+void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
+ Error **errp)
{
- ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
-
- if (lpc->pm.acpi_memory_hotplug.is_enabled &&
+ if (pm->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_unplug_request_cb(hotplug_dev,
- &lpc->pm.acpi_memory_hotplug, dev,
- errp);
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) &&
- !lpc->pm.cpu_hotplug_legacy) {
- acpi_cpu_unplug_request_cb(hotplug_dev, &lpc->pm.cpuhp_state,
- dev, errp);
+ acpi_memory_unplug_request_cb(&pm->acpi_regs, pm->irq,
+ &pm->acpi_memory_hotplug, dev, errp);
} else {
error_setg(errp, "acpi: device unplug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
-void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
Error **errp)
{
- ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
-
- if (lpc->pm.acpi_memory_hotplug.is_enabled &&
+ if (pm->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_unplug_cb(&lpc->pm.acpi_memory_hotplug, dev, errp);
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) &&
- !lpc->pm.cpu_hotplug_legacy) {
- acpi_cpu_unplug_cb(&lpc->pm.cpuhp_state, dev, errp);
+ acpi_memory_unplug_cb(&pm->acpi_memory_hotplug, dev, errp);
} else {
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -546,7 +474,4 @@ void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
ICH9LPCState *s = ICH9_LPC_DEVICE(adev);
acpi_memory_ospm_status(&s->pm.acpi_memory_hotplug, list);
- if (!s->pm.cpu_hotplug_legacy) {
- acpi_cpu_ospm_status(&s->pm.cpuhp_state, list);
- }
}
diff --git a/hw/acpi/ipmi.c b/hw/acpi/ipmi.c
deleted file mode 100644
index 7e74ce446..000000000
--- a/hw/acpi/ipmi.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * IPMI ACPI firmware handling
- *
- * Copyright (c) 2015,2016 Corey Minyard, MontaVista Software, 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.
- */
-
-#include "qemu/osdep.h"
-#include "hw/ipmi/ipmi.h"
-#include "hw/acpi/aml-build.h"
-#include "hw/acpi/acpi.h"
-#include "hw/acpi/ipmi.h"
-
-static Aml *aml_ipmi_crs(IPMIFwInfo *info)
-{
- Aml *crs = aml_resource_template();
-
- /*
- * The base address is fixed and cannot change. That may be different
- * if someone does PCI, but we aren't there yet.
- */
- switch (info->memspace) {
- case IPMI_MEMSPACE_IO:
- aml_append(crs, aml_io(AML_DECODE16, info->base_address,
- info->base_address + info->register_length - 1,
- info->register_spacing, info->register_length));
- break;
- case IPMI_MEMSPACE_MEM32:
- aml_append(crs,
- aml_dword_memory(AML_POS_DECODE,
- AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE,
- 0xffffffff,
- info->base_address,
- info->base_address + info->register_length - 1,
- info->register_spacing, info->register_length));
- break;
- case IPMI_MEMSPACE_MEM64:
- aml_append(crs,
- aml_qword_memory(AML_POS_DECODE,
- AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE,
- 0xffffffffffffffffULL,
- info->base_address,
- info->base_address + info->register_length - 1,
- info->register_spacing, info->register_length));
- break;
- case IPMI_MEMSPACE_SMBUS:
- aml_append(crs, aml_return(aml_int(info->base_address)));
- break;
- default:
- abort();
- }
-
- if (info->interrupt_number) {
- aml_append(crs, aml_irq_no_flags(info->interrupt_number));
- }
-
- return crs;
-}
-
-static Aml *aml_ipmi_device(IPMIFwInfo *info)
-{
- Aml *dev;
- uint16_t version = ((info->ipmi_spec_major_revision << 8)
- | (info->ipmi_spec_minor_revision << 4));
-
- assert(info->ipmi_spec_minor_revision <= 15);
-
- dev = aml_device("MI%d", info->uuid);
- aml_append(dev, aml_name_decl("_HID", aml_eisaid("IPI0001")));
- aml_append(dev, aml_name_decl("_STR", aml_string("ipmi_%s",
- info->interface_name)));
- aml_append(dev, aml_name_decl("_UID", aml_int(info->uuid)));
- aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(info)));
- aml_append(dev, aml_name_decl("_IFT", aml_int(info->interface_type)));
- aml_append(dev, aml_name_decl("_SRV", aml_int(version)));
-
- return dev;
-}
-
-void build_acpi_ipmi_devices(Aml *scope, BusState *bus)
-{
-
- BusChild *kid;
-
- QTAILQ_FOREACH(kid, &bus->children, sibling) {
- IPMIInterface *ii;
- IPMIInterfaceClass *iic;
- IPMIFwInfo info;
- Object *obj = object_dynamic_cast(OBJECT(kid->child),
- TYPE_IPMI_INTERFACE);
-
- if (!obj) {
- continue;
- }
-
- ii = IPMI_INTERFACE(obj);
- iic = IPMI_INTERFACE_GET_CLASS(obj);
- iic->get_fwinfo(ii, &info);
- aml_append(scope, aml_ipmi_device(&info));
- }
-}
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index ec4e64b36..f65a3a21e 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -228,7 +228,7 @@ acpi_memory_slot_status(MemHotplugState *mem_st,
return &mem_st->devs[slot];
}
-void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
+void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
MemStatus *mdev;
@@ -247,11 +247,13 @@ void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
mdev->is_enabled = true;
if (dev->hotplugged) {
mdev->is_inserting = true;
- acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
+
+ /* do ACPI magic */
+ acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
}
}
-void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
+void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
@@ -263,7 +265,9 @@ void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
}
mdev->is_removing = true;
- acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
+
+ /* Do ACPI magic */
+ acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
}
void acpi_memory_unplug_cb(MemHotplugState *mem_st,
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index e486128aa..9531340e5 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -216,26 +216,6 @@ static uint32_t nvdimm_slot_to_dcr_index(int slot)
return nvdimm_slot_to_spa_index(slot) + 1;
}
-static NVDIMMDevice *nvdimm_get_device_by_handle(uint32_t handle)
-{
- NVDIMMDevice *nvdimm = NULL;
- GSList *list, *device_list = nvdimm_get_plugged_device_list();
-
- for (list = device_list; list; list = list->next) {
- NVDIMMDevice *nvd = list->data;
- int slot = object_property_get_int(OBJECT(nvd), PC_DIMM_SLOT_PROP,
- NULL);
-
- if (nvdimm_slot_to_handle(slot) == handle) {
- nvdimm = nvd;
- break;
- }
- }
-
- g_slist_free(device_list);
- return nvdimm;
-}
-
/* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure */
static void
nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
@@ -373,7 +353,7 @@ static GArray *nvdimm_build_device_structure(GSList *device_list)
}
static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
- GArray *table_data, BIOSLinker *linker)
+ GArray *table_data, GArray *linker)
{
GArray *structures = nvdimm_build_device_structure(device_list);
unsigned int header;
@@ -398,19 +378,17 @@ struct NvdimmDsmIn {
uint32_t function;
/* the remaining size in the page is used by arg3. */
union {
- uint8_t arg3[4084];
+ uint8_t arg3[0];
};
} QEMU_PACKED;
typedef struct NvdimmDsmIn NvdimmDsmIn;
-QEMU_BUILD_BUG_ON(sizeof(NvdimmDsmIn) != 4096);
struct NvdimmDsmOut {
/* the size of buffer filled by QEMU. */
uint32_t len;
- uint8_t data[4092];
+ uint8_t data[0];
} QEMU_PACKED;
typedef struct NvdimmDsmOut NvdimmDsmOut;
-QEMU_BUILD_BUG_ON(sizeof(NvdimmDsmOut) != 4096);
struct NvdimmDsmFunc0Out {
/* the size of buffer filled by QEMU. */
@@ -426,282 +404,6 @@ struct NvdimmDsmFuncNoPayloadOut {
} QEMU_PACKED;
typedef struct NvdimmDsmFuncNoPayloadOut NvdimmDsmFuncNoPayloadOut;
-struct NvdimmFuncGetLabelSizeOut {
- /* the size of buffer filled by QEMU. */
- uint32_t len;
- uint32_t func_ret_status; /* return status code. */
- uint32_t label_size; /* the size of label data area. */
- /*
- * Maximum size of the namespace label data length supported by
- * the platform in Get/Set Namespace Label Data functions.
- */
- uint32_t max_xfer;
-} QEMU_PACKED;
-typedef struct NvdimmFuncGetLabelSizeOut NvdimmFuncGetLabelSizeOut;
-QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelSizeOut) > 4096);
-
-struct NvdimmFuncGetLabelDataIn {
- uint32_t offset; /* the offset in the namespace label data area. */
- uint32_t length; /* the size of data is to be read via the function. */
-} QEMU_PACKED;
-typedef struct NvdimmFuncGetLabelDataIn NvdimmFuncGetLabelDataIn;
-QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataIn) +
- offsetof(NvdimmDsmIn, arg3) > 4096);
-
-struct NvdimmFuncGetLabelDataOut {
- /* the size of buffer filled by QEMU. */
- uint32_t len;
- uint32_t func_ret_status; /* return status code. */
- uint8_t out_buf[0]; /* the data got via Get Namesapce Label function. */
-} QEMU_PACKED;
-typedef struct NvdimmFuncGetLabelDataOut NvdimmFuncGetLabelDataOut;
-QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataOut) > 4096);
-
-struct NvdimmFuncSetLabelDataIn {
- uint32_t offset; /* the offset in the namespace label data area. */
- uint32_t length; /* the size of data is to be written via the function. */
- uint8_t in_buf[0]; /* the data written to label data area. */
-} QEMU_PACKED;
-typedef struct NvdimmFuncSetLabelDataIn NvdimmFuncSetLabelDataIn;
-QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncSetLabelDataIn) +
- offsetof(NvdimmDsmIn, arg3) > 4096);
-
-static void
-nvdimm_dsm_function0(uint32_t supported_func, hwaddr dsm_mem_addr)
-{
- NvdimmDsmFunc0Out func0 = {
- .len = cpu_to_le32(sizeof(func0)),
- .supported_func = cpu_to_le32(supported_func),
- };
- cpu_physical_memory_write(dsm_mem_addr, &func0, sizeof(func0));
-}
-
-static void
-nvdimm_dsm_no_payload(uint32_t func_ret_status, hwaddr dsm_mem_addr)
-{
- NvdimmDsmFuncNoPayloadOut out = {
- .len = cpu_to_le32(sizeof(out)),
- .func_ret_status = cpu_to_le32(func_ret_status),
- };
- cpu_physical_memory_write(dsm_mem_addr, &out, sizeof(out));
-}
-
-static void nvdimm_dsm_root(NvdimmDsmIn *in, hwaddr dsm_mem_addr)
-{
- /*
- * function 0 is called to inquire which functions are supported by
- * OSPM
- */
- if (!in->function) {
- nvdimm_dsm_function0(0 /* No function supported other than
- function 0 */, dsm_mem_addr);
- return;
- }
-
- /* No function except function 0 is supported yet. */
- nvdimm_dsm_no_payload(1 /* Not Supported */, dsm_mem_addr);
-}
-
-/*
- * the max transfer size is the max size transferred by both a
- * 'Get Namespace Label Data' function and a 'Set Namespace Label Data'
- * function.
- */
-static uint32_t nvdimm_get_max_xfer_label_size(void)
-{
- uint32_t max_get_size, max_set_size, dsm_memory_size = 4096;
-
- /*
- * the max data ACPI can read one time which is transferred by
- * the response of 'Get Namespace Label Data' function.
- */
- max_get_size = dsm_memory_size - sizeof(NvdimmFuncGetLabelDataOut);
-
- /*
- * the max data ACPI can write one time which is transferred by
- * 'Set Namespace Label Data' function.
- */
- max_set_size = dsm_memory_size - offsetof(NvdimmDsmIn, arg3) -
- sizeof(NvdimmFuncSetLabelDataIn);
-
- return MIN(max_get_size, max_set_size);
-}
-
-/*
- * DSM Spec Rev1 4.4 Get Namespace Label Size (Function Index 4).
- *
- * It gets the size of Namespace Label data area and the max data size
- * that Get/Set Namespace Label Data functions can transfer.
- */
-static void nvdimm_dsm_label_size(NVDIMMDevice *nvdimm, hwaddr dsm_mem_addr)
-{
- NvdimmFuncGetLabelSizeOut label_size_out = {
- .len = cpu_to_le32(sizeof(label_size_out)),
- };
- uint32_t label_size, mxfer;
-
- label_size = nvdimm->label_size;
- mxfer = nvdimm_get_max_xfer_label_size();
-
- nvdimm_debug("label_size %#x, max_xfer %#x.\n", label_size, mxfer);
-
- label_size_out.func_ret_status = cpu_to_le32(0 /* Success */);
- label_size_out.label_size = cpu_to_le32(label_size);
- label_size_out.max_xfer = cpu_to_le32(mxfer);
-
- cpu_physical_memory_write(dsm_mem_addr, &label_size_out,
- sizeof(label_size_out));
-}
-
-static uint32_t nvdimm_rw_label_data_check(NVDIMMDevice *nvdimm,
- uint32_t offset, uint32_t length)
-{
- uint32_t ret = 3 /* Invalid Input Parameters */;
-
- if (offset + length < offset) {
- nvdimm_debug("offset %#x + length %#x is overflow.\n", offset,
- length);
- return ret;
- }
-
- if (nvdimm->label_size < offset + length) {
- nvdimm_debug("position %#x is beyond label data (len = %" PRIx64 ").\n",
- offset + length, nvdimm->label_size);
- return ret;
- }
-
- if (length > nvdimm_get_max_xfer_label_size()) {
- nvdimm_debug("length (%#x) is larger than max_xfer (%#x).\n",
- length, nvdimm_get_max_xfer_label_size());
- return ret;
- }
-
- return 0 /* Success */;
-}
-
-/*
- * DSM Spec Rev1 4.5 Get Namespace Label Data (Function Index 5).
- */
-static void nvdimm_dsm_get_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in,
- hwaddr dsm_mem_addr)
-{
- NVDIMMClass *nvc = NVDIMM_GET_CLASS(nvdimm);
- NvdimmFuncGetLabelDataIn *get_label_data;
- NvdimmFuncGetLabelDataOut *get_label_data_out;
- uint32_t status;
- int size;
-
- get_label_data = (NvdimmFuncGetLabelDataIn *)in->arg3;
- le32_to_cpus(&get_label_data->offset);
- le32_to_cpus(&get_label_data->length);
-
- nvdimm_debug("Read Label Data: offset %#x length %#x.\n",
- get_label_data->offset, get_label_data->length);
-
- status = nvdimm_rw_label_data_check(nvdimm, get_label_data->offset,
- get_label_data->length);
- if (status != 0 /* Success */) {
- nvdimm_dsm_no_payload(status, dsm_mem_addr);
- return;
- }
-
- size = sizeof(*get_label_data_out) + get_label_data->length;
- assert(size <= 4096);
- get_label_data_out = g_malloc(size);
-
- get_label_data_out->len = cpu_to_le32(size);
- get_label_data_out->func_ret_status = cpu_to_le32(0 /* Success */);
- nvc->read_label_data(nvdimm, get_label_data_out->out_buf,
- get_label_data->length, get_label_data->offset);
-
- cpu_physical_memory_write(dsm_mem_addr, get_label_data_out, size);
- g_free(get_label_data_out);
-}
-
-/*
- * DSM Spec Rev1 4.6 Set Namespace Label Data (Function Index 6).
- */
-static void nvdimm_dsm_set_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in,
- hwaddr dsm_mem_addr)
-{
- NVDIMMClass *nvc = NVDIMM_GET_CLASS(nvdimm);
- NvdimmFuncSetLabelDataIn *set_label_data;
- uint32_t status;
-
- set_label_data = (NvdimmFuncSetLabelDataIn *)in->arg3;
-
- le32_to_cpus(&set_label_data->offset);
- le32_to_cpus(&set_label_data->length);
-
- nvdimm_debug("Write Label Data: offset %#x length %#x.\n",
- set_label_data->offset, set_label_data->length);
-
- status = nvdimm_rw_label_data_check(nvdimm, set_label_data->offset,
- set_label_data->length);
- if (status != 0 /* Success */) {
- nvdimm_dsm_no_payload(status, dsm_mem_addr);
- return;
- }
-
- assert(sizeof(*in) + sizeof(*set_label_data) + set_label_data->length <=
- 4096);
-
- nvc->write_label_data(nvdimm, set_label_data->in_buf,
- set_label_data->length, set_label_data->offset);
- nvdimm_dsm_no_payload(0 /* Success */, dsm_mem_addr);
-}
-
-static void nvdimm_dsm_device(NvdimmDsmIn *in, hwaddr dsm_mem_addr)
-{
- NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(in->handle);
-
- /* See the comments in nvdimm_dsm_root(). */
- if (!in->function) {
- uint32_t supported_func = 0;
-
- if (nvdimm && nvdimm->label_size) {
- supported_func |= 0x1 /* Bit 0 indicates whether there is
- support for any functions other
- than function 0. */ |
- 1 << 4 /* Get Namespace Label Size */ |
- 1 << 5 /* Get Namespace Label Data */ |
- 1 << 6 /* Set Namespace Label Data */;
- }
- nvdimm_dsm_function0(supported_func, dsm_mem_addr);
- return;
- }
-
- if (!nvdimm) {
- nvdimm_dsm_no_payload(2 /* Non-Existing Memory Device */,
- dsm_mem_addr);
- return;
- }
-
- /* Encode DSM function according to DSM Spec Rev1. */
- switch (in->function) {
- case 4 /* Get Namespace Label Size */:
- if (nvdimm->label_size) {
- nvdimm_dsm_label_size(nvdimm, dsm_mem_addr);
- return;
- }
- break;
- case 5 /* Get Namespace Label Data */:
- if (nvdimm->label_size) {
- nvdimm_dsm_get_label_data(nvdimm, in, dsm_mem_addr);
- return;
- }
- break;
- case 0x6 /* Set Namespace Label Data */:
- if (nvdimm->label_size) {
- nvdimm_dsm_set_label_data(nvdimm, in, dsm_mem_addr);
- return;
- }
- break;
- }
-
- nvdimm_dsm_no_payload(1 /* Not Supported */, dsm_mem_addr);
-}
-
static uint64_t
nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
{
@@ -722,8 +424,8 @@ nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
* can change its content while we are doing DSM emulation. Avoid
* this by copying DSM memory to QEMU local memory.
*/
- in = g_new(NvdimmDsmIn, 1);
- cpu_physical_memory_read(dsm_mem_addr, in, sizeof(*in));
+ in = g_malloc(TARGET_PAGE_SIZE);
+ cpu_physical_memory_read(dsm_mem_addr, in, TARGET_PAGE_SIZE);
le32_to_cpus(&in->revision);
le32_to_cpus(&in->function);
@@ -732,22 +434,26 @@ nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
nvdimm_debug("Revision %#x Handler %#x Function %#x.\n", in->revision,
in->handle, in->function);
- if (in->revision != 0x1 /* Currently we only support DSM Spec Rev1. */) {
- nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
- in->revision, 0x1);
- nvdimm_dsm_no_payload(1 /* Not Supported */, dsm_mem_addr);
- goto exit;
- }
-
- /* Handle 0 is reserved for NVDIMM Root Device. */
- if (!in->handle) {
- nvdimm_dsm_root(in, dsm_mem_addr);
- goto exit;
+ /*
+ * function 0 is called to inquire which functions are supported by
+ * OSPM
+ */
+ if (in->function == 0) {
+ NvdimmDsmFunc0Out func0 = {
+ .len = cpu_to_le32(sizeof(func0)),
+ /* No function supported other than function 0 */
+ .supported_func = cpu_to_le32(0),
+ };
+ cpu_physical_memory_write(dsm_mem_addr, &func0, sizeof func0);
+ } else {
+ /* No function except function 0 is supported yet. */
+ NvdimmDsmFuncNoPayloadOut out = {
+ .len = cpu_to_le32(sizeof(out)),
+ .func_ret_status = cpu_to_le32(1) /* Not Supported */,
+ };
+ cpu_physical_memory_write(dsm_mem_addr, &out, sizeof(out));
}
- nvdimm_dsm_device(in, dsm_mem_addr);
-
-exit:
g_free(in);
}
@@ -769,7 +475,7 @@ void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io,
memory_region_add_subregion(io, NVDIMM_ACPI_IO_BASE, &state->io_mr);
state->dsm_mem = g_array_new(false, true /* clear */, 1);
- acpi_data_push(state->dsm_mem, sizeof(NvdimmDsmIn));
+ acpi_data_push(state->dsm_mem, TARGET_PAGE_SIZE);
fw_cfg_add_file(fw_cfg, NVDIMM_DSM_MEM_FILE, state->dsm_mem->data,
state->dsm_mem->len);
}
@@ -779,39 +485,18 @@ void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io,
static void nvdimm_build_common_dsm(Aml *dev)
{
- Aml *method, *ifctx, *function, *handle, *uuid, *dsm_mem, *result_size;
- Aml *elsectx, *unsupport, *unpatched, *expected_uuid, *uuid_invalid;
- Aml *pckg, *pckg_index, *pckg_buf;
+ Aml *method, *ifctx, *function, *dsm_mem, *unpatched, *result_size;
uint8_t byte_list[1];
- method = aml_method(NVDIMM_COMMON_DSM, 5, AML_SERIALIZED);
- uuid = aml_arg(0);
+ method = aml_method(NVDIMM_COMMON_DSM, 4, AML_SERIALIZED);
function = aml_arg(2);
- handle = aml_arg(4);
dsm_mem = aml_name(NVDIMM_ACPI_MEM_ADDR);
/*
* do not support any method if DSM memory address has not been
* patched.
*/
- unpatched = aml_equal(dsm_mem, aml_int(0x0));
-
- expected_uuid = aml_local(0);
-
- ifctx = aml_if(aml_equal(handle, aml_int(0x0)));
- aml_append(ifctx, aml_store(
- aml_touuid("2F10E7A4-9E91-11E4-89D3-123B93F75CBA")
- /* UUID for NVDIMM Root Device */, expected_uuid));
- aml_append(method, ifctx);
- elsectx = aml_else();
- aml_append(elsectx, aml_store(
- aml_touuid("4309AC30-0D11-11E4-9191-0800200C9A66")
- /* UUID for NVDIMM Devices */, expected_uuid));
- aml_append(method, elsectx);
-
- uuid_invalid = aml_lnot(aml_equal(uuid, expected_uuid));
-
- unsupport = aml_if(aml_or(unpatched, uuid_invalid, NULL));
+ unpatched = aml_if(aml_equal(dsm_mem, aml_int(0x0)));
/*
* function 0 is called to inquire what functions are supported by
@@ -820,42 +505,24 @@ static void nvdimm_build_common_dsm(Aml *dev)
ifctx = aml_if(aml_equal(function, aml_int(0)));
byte_list[0] = 0 /* No function Supported */;
aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
- aml_append(unsupport, ifctx);
+ aml_append(unpatched, ifctx);
/* No function is supported yet. */
byte_list[0] = 1 /* Not Supported */;
- aml_append(unsupport, aml_return(aml_buffer(1, byte_list)));
- aml_append(method, unsupport);
+ aml_append(unpatched, aml_return(aml_buffer(1, byte_list)));
+ aml_append(method, unpatched);
/*
* The HDLE indicates the DSM function is issued from which device,
- * it reserves 0 for root device and is the handle for NVDIMM devices.
- * See the comments in nvdimm_slot_to_handle().
+ * it is not used at this time as no function is supported yet.
+ * Currently we make it always be 0 for all the devices and will set
+ * the appropriate value once real function is implemented.
*/
- aml_append(method, aml_store(handle, aml_name("HDLE")));
+ aml_append(method, aml_store(aml_int(0x0), aml_name("HDLE")));
aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
/*
- * The fourth parameter (Arg3) of _DSM is a package which contains
- * a buffer, the layout of the buffer is specified by UUID (Arg0),
- * Revision ID (Arg1) and Function Index (Arg2) which are documented
- * in the DSM Spec.
- */
- pckg = aml_arg(3);
- ifctx = aml_if(aml_and(aml_equal(aml_object_type(pckg),
- aml_int(4 /* Package */)) /* It is a Package? */,
- aml_equal(aml_sizeof(pckg), aml_int(1)) /* 1 element? */,
- NULL));
-
- pckg_index = aml_local(2);
- pckg_buf = aml_local(3);
- aml_append(ifctx, aml_store(aml_index(pckg, aml_int(0)), pckg_index));
- aml_append(ifctx, aml_store(aml_derefof(pckg_index), pckg_buf));
- aml_append(ifctx, aml_store(pckg_buf, aml_name("ARG3")));
- aml_append(method, ifctx);
-
- /*
* tell QEMU about the real address of DSM memory, then QEMU
* gets the control and fills the result in DSM memory.
*/
@@ -873,14 +540,13 @@ static void nvdimm_build_common_dsm(Aml *dev)
aml_append(dev, method);
}
-static void nvdimm_build_device_dsm(Aml *dev, uint32_t handle)
+static void nvdimm_build_device_dsm(Aml *dev)
{
Aml *method;
method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
- aml_append(method, aml_return(aml_call5(NVDIMM_COMMON_DSM, aml_arg(0),
- aml_arg(1), aml_arg(2), aml_arg(3),
- aml_int(handle))));
+ aml_append(method, aml_return(aml_call4(NVDIMM_COMMON_DSM, aml_arg(0),
+ aml_arg(1), aml_arg(2), aml_arg(3))));
aml_append(dev, method);
}
@@ -905,14 +571,13 @@ static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
*/
aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
- nvdimm_build_device_dsm(nvdimm_dev, handle);
+ nvdimm_build_device_dsm(nvdimm_dev);
aml_append(root_dev, nvdimm_dev);
}
}
static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
- GArray *table_data, BIOSLinker *linker,
- GArray *dsm_dma_arrea)
+ GArray *table_data, GArray *linker)
{
Aml *ssdt, *sb_scope, *dev, *field;
int mem_addr_offset, nvdimm_ssdt;
@@ -943,7 +608,7 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
aml_append(dev, aml_operation_region("NPIO", AML_SYSTEM_IO,
aml_int(NVDIMM_ACPI_IO_BASE), NVDIMM_ACPI_IO_LEN));
aml_append(dev, aml_operation_region("NRAM", AML_SYSTEM_MEMORY,
- aml_name(NVDIMM_ACPI_MEM_ADDR), sizeof(NvdimmDsmIn)));
+ aml_name(NVDIMM_ACPI_MEM_ADDR), TARGET_PAGE_SIZE));
/*
* DSM notifier:
@@ -977,7 +642,8 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
aml_append(field, aml_named_field("FUNC",
sizeof(typeof_field(NvdimmDsmIn, function)) * BITS_PER_BYTE));
aml_append(field, aml_named_field("ARG3",
- (sizeof(NvdimmDsmIn) - offsetof(NvdimmDsmIn, arg3)) * BITS_PER_BYTE));
+ (TARGET_PAGE_SIZE - offsetof(NvdimmDsmIn, arg3)) *
+ BITS_PER_BYTE));
aml_append(dev, field);
/*
@@ -993,13 +659,12 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
aml_append(field, aml_named_field("RLEN",
sizeof(typeof_field(NvdimmDsmOut, len)) * BITS_PER_BYTE));
aml_append(field, aml_named_field("ODAT",
- (sizeof(NvdimmDsmOut) - offsetof(NvdimmDsmOut, data)) * BITS_PER_BYTE));
+ (TARGET_PAGE_SIZE - offsetof(NvdimmDsmOut, data)) *
+ BITS_PER_BYTE));
aml_append(dev, field);
nvdimm_build_common_dsm(dev);
-
- /* 0 is reserved for root device. */
- nvdimm_build_device_dsm(dev, 0);
+ nvdimm_build_device_dsm(dev);
nvdimm_build_nvdimm_devices(device_list, dev);
@@ -1013,12 +678,12 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
mem_addr_offset = build_append_named_dword(table_data,
NVDIMM_ACPI_MEM_ADDR);
- bios_linker_loader_alloc(linker,
- NVDIMM_DSM_MEM_FILE, dsm_dma_arrea,
- sizeof(NvdimmDsmIn), false /* high memory */);
- bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t),
- NVDIMM_DSM_MEM_FILE, 0);
+ bios_linker_loader_alloc(linker, NVDIMM_DSM_MEM_FILE, TARGET_PAGE_SIZE,
+ false /* high memory */);
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+ NVDIMM_DSM_MEM_FILE, table_data,
+ table_data->data + mem_addr_offset,
+ sizeof(uint32_t));
build_header(linker, table_data,
(void *)(table_data->data + nvdimm_ssdt),
"SSDT", table_data->len - nvdimm_ssdt, 1, NULL, "NVDIMM");
@@ -1026,7 +691,7 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
}
void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
- BIOSLinker *linker, GArray *dsm_dma_arrea)
+ GArray *linker)
{
GSList *device_list;
@@ -1036,7 +701,6 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
return;
}
nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
- nvdimm_build_ssdt(device_list, table_offsets, table_data, linker,
- dsm_dma_arrea);
+ nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
g_slist_free(device_list);
}
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index d957d1e30..71f4c4e14 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -182,7 +182,7 @@ void acpi_pcihp_reset(AcpiPciHpState *s)
acpi_pcihp_update(s);
}
-void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
+void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(dev);
@@ -202,10 +202,11 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
}
s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
- acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
+
+ acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
}
-void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
+void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(dev);
@@ -218,7 +219,8 @@ void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
}
s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
- acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
+
+ acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
}
static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 2adc246b0..16abdf162 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -34,13 +34,11 @@
#include "hw/acpi/piix4.h"
#include "hw/acpi/pcihp.h"
#include "hw/acpi/cpu_hotplug.h"
-#include "hw/acpi/cpu.h"
#include "hw/hotplug.h"
#include "hw/mem/pc-dimm.h"
#include "hw/acpi/memory_hotplug.h"
#include "hw/acpi/acpi_dev_interface.h"
#include "hw/xen/xen.h"
-#include "qom/cpu.h"
//#define DEBUG
@@ -87,9 +85,7 @@ typedef struct PIIX4PMState {
uint8_t disable_s4;
uint8_t s4_val;
- bool cpu_hotplug_legacy;
AcpiCpuHotplug gpe_cpu;
- CPUHotplugState cpuhp_state;
MemHotplugState acpi_memory_hotplug;
} PIIX4PMState;
@@ -276,32 +272,6 @@ static const VMStateDescription vmstate_memhp_state = {
}
};
-static bool vmstate_test_use_cpuhp(void *opaque)
-{
- PIIX4PMState *s = opaque;
- return !s->cpu_hotplug_legacy;
-}
-
-static int vmstate_cpuhp_pre_load(void *opaque)
-{
- Object *obj = OBJECT(opaque);
- object_property_set_bool(obj, false, "cpu-hotplug-legacy", &error_abort);
- return 0;
-}
-
-static const VMStateDescription vmstate_cpuhp_state = {
- .name = "piix4_pm/cpuhp",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .needed = vmstate_test_use_cpuhp,
- .pre_load = vmstate_cpuhp_pre_load,
- .fields = (VMStateField[]) {
- VMSTATE_CPU_HOTPLUG(cpuhp_state, PIIX4PMState),
- VMSTATE_END_OF_LIST()
- }
-};
-
/* qemu-kvm 1.2 uses version 3 but advertised as 2
* To support incoming qemu-kvm 1.2 migration, change version_id
* and minimum_version_id to 2 below (which breaks migration from
@@ -336,7 +306,6 @@ static const VMStateDescription vmstate_acpi = {
},
.subsections = (const VMStateDescription*[]) {
&vmstate_memhp_state,
- &vmstate_cpuhp_state,
NULL
}
};
@@ -378,15 +347,12 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
if (s->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_plug_cb(hotplug_dev, &s->acpi_memory_hotplug, dev, errp);
+ acpi_memory_plug_cb(&s->ar, s->irq, &s->acpi_memory_hotplug, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
- acpi_pcihp_device_plug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev, errp);
+ acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
+ errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
- if (s->cpu_hotplug_legacy) {
- legacy_acpi_cpu_plug_cb(hotplug_dev, &s->gpe_cpu, dev, errp);
- } else {
- acpi_cpu_plug_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
- }
+ acpi_cpu_plug_cb(&s->ar, s->irq, &s->gpe_cpu, dev, errp);
} else {
error_setg(errp, "acpi: device plug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -400,14 +366,11 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
if (s->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_unplug_request_cb(hotplug_dev, &s->acpi_memory_hotplug,
+ acpi_memory_unplug_request_cb(&s->ar, s->irq, &s->acpi_memory_hotplug,
dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
- acpi_pcihp_device_unplug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev,
+ acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
errp);
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) &&
- !s->cpu_hotplug_legacy) {
- acpi_cpu_unplug_request_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
} else {
error_setg(errp, "acpi: device unplug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -422,9 +385,6 @@ static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
if (s->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
acpi_memory_unplug_cb(&s->acpi_memory_hotplug, dev, errp);
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) &&
- !s->cpu_hotplug_legacy) {
- acpi_cpu_unplug_cb(&s->cpuhp_state, dev, errp);
} else {
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -600,26 +560,6 @@ static const MemoryRegionOps piix4_gpe_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-
-static bool piix4_get_cpu_hotplug_legacy(Object *obj, Error **errp)
-{
- PIIX4PMState *s = PIIX4_PM(obj);
-
- return s->cpu_hotplug_legacy;
-}
-
-static void piix4_set_cpu_hotplug_legacy(Object *obj, bool value, Error **errp)
-{
- PIIX4PMState *s = PIIX4_PM(obj);
-
- assert(!value);
- if (s->cpu_hotplug_legacy && value == false) {
- acpi_switch_to_modern_cphp(&s->gpe_cpu, &s->cpuhp_state,
- PIIX4_CPU_HOTPLUG_IO_BASE);
- }
- s->cpu_hotplug_legacy = value;
-}
-
static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
PCIBus *bus, PIIX4PMState *s)
{
@@ -630,13 +570,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent,
s->use_acpi_pci_hotplug);
- s->cpu_hotplug_legacy = true;
- object_property_add_bool(OBJECT(s), "cpu-hotplug-legacy",
- piix4_get_cpu_hotplug_legacy,
- piix4_set_cpu_hotplug_legacy,
- NULL);
- legacy_acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
- PIIX4_CPU_HOTPLUG_IO_BASE);
+ acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
+ PIIX4_CPU_HOTPLUG_IO_BASE);
if (s->acpi_memory_hotplug.is_enabled) {
acpi_memory_hotplug_init(parent, OBJECT(s), &s->acpi_memory_hotplug);
@@ -648,16 +583,6 @@ static void piix4_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
PIIX4PMState *s = PIIX4_PM(adev);
acpi_memory_ospm_status(&s->acpi_memory_hotplug, list);
- if (!s->cpu_hotplug_legacy) {
- acpi_cpu_ospm_status(&s->cpuhp_state, list);
- }
-}
-
-static void piix4_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
-{
- PIIX4PMState *s = PIIX4_PM(adev);
-
- acpi_send_gpe_event(&s->ar, s->irq, ev);
}
static Property piix4_pm_properties[] = {
@@ -698,8 +623,6 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
hc->unplug_request = piix4_device_unplug_request_cb;
hc->unplug = piix4_device_unplug_cb;
adevc->ospm_status = piix4_ospm_status;
- adevc->send_event = piix4_send_gpe;
- adevc->madt_cpu = pc_madt_cpu_entry;
}
static const TypeInfo piix4_pm_info = {
diff --git a/hw/acpi/trace-events b/hw/acpi/trace-events
deleted file mode 100644
index c379607a3..000000000
--- a/hw/acpi/trace-events
+++ /dev/null
@@ -1,32 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/acpi/memory_hotplug.c
-mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
-mhp_acpi_ejecting_invalid_slot(uint32_t slot) "0x%"PRIx32
-mhp_acpi_read_addr_lo(uint32_t slot, uint32_t addr) "slot[0x%"PRIx32"] addr lo: 0x%"PRIx32
-mhp_acpi_read_addr_hi(uint32_t slot, uint32_t addr) "slot[0x%"PRIx32"] addr hi: 0x%"PRIx32
-mhp_acpi_read_size_lo(uint32_t slot, uint32_t size) "slot[0x%"PRIx32"] size lo: 0x%"PRIx32
-mhp_acpi_read_size_hi(uint32_t slot, uint32_t size) "slot[0x%"PRIx32"] size hi: 0x%"PRIx32
-mhp_acpi_read_pxm(uint32_t slot, uint32_t pxm) "slot[0x%"PRIx32"] proximity: 0x%"PRIx32
-mhp_acpi_read_flags(uint32_t slot, uint32_t flags) "slot[0x%"PRIx32"] flags: 0x%"PRIx32
-mhp_acpi_write_slot(uint32_t slot) "set active slot: 0x%"PRIx32
-mhp_acpi_write_ost_ev(uint32_t slot, uint32_t ev) "slot[0x%"PRIx32"] OST EVENT: 0x%"PRIx32
-mhp_acpi_write_ost_status(uint32_t slot, uint32_t st) "slot[0x%"PRIx32"] OST STATUS: 0x%"PRIx32
-mhp_acpi_clear_insert_evt(uint32_t slot) "slot[0x%"PRIx32"] clear insert event"
-mhp_acpi_clear_remove_evt(uint32_t slot) "slot[0x%"PRIx32"] clear remove event"
-mhp_acpi_pc_dimm_deleted(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm deleted"
-mhp_acpi_pc_dimm_delete_failed(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm delete failed"
-
-# hw/acpi/cpu.c
-cpuhp_acpi_invalid_idx_selected(uint32_t idx) "0x%"PRIx32
-cpuhp_acpi_read_flags(uint32_t idx, uint8_t flags) "idx[0x%"PRIx32"] flags: 0x%"PRIx8
-cpuhp_acpi_write_idx(uint32_t idx) "set active cpu idx: 0x%"PRIx32
-cpuhp_acpi_write_cmd(uint32_t idx, uint8_t cmd) "idx[0x%"PRIx32"] cmd: 0x%"PRIx8
-cpuhp_acpi_read_cmd_data(uint32_t idx, uint32_t data) "idx[0x%"PRIx32"] data: 0x%"PRIx32
-cpuhp_acpi_cpu_has_events(uint32_t idx, bool ins, bool rm) "idx[0x%"PRIx32"] inserting: %d, removing: %d"
-cpuhp_acpi_clear_inserting_evt(uint32_t idx) "idx[0x%"PRIx32"]"
-cpuhp_acpi_clear_remove_evt(uint32_t idx) "idx[0x%"PRIx32"]"
-cpuhp_acpi_ejecting_invalid_cpu(uint32_t idx) "0x%"PRIx32
-cpuhp_acpi_ejecting_cpu(uint32_t idx) "0x%"PRIx32
-cpuhp_acpi_write_ost_ev(uint32_t slot, uint32_t ev) "idx[0x%"PRIx32"] OST EVENT: 0x%"PRIx32
-cpuhp_acpi_write_ost_status(uint32_t slot, uint32_t st) "idx[0x%"PRIx32"] OST STATUS: 0x%"PRIx32
diff --git a/hw/alpha/alpha_sys.h b/hw/alpha/alpha_sys.h
index ed911f22a..e11025b4b 100644
--- a/hw/alpha/alpha_sys.h
+++ b/hw/alpha/alpha_sys.h
@@ -1,9 +1,8 @@
/* Alpha cores and system support chips. */
-#ifndef HW_ALPHA_SYS_H
-#define HW_ALPHA_SYS_H
+#ifndef HW_ALPHA_H
+#define HW_ALPHA_H 1
-#include "target-alpha/cpu-qom.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "hw/ide.h"
diff --git a/hw/alpha/pci.c b/hw/alpha/pci.c
index 8dde637bf..5baa0eaf1 100644
--- a/hw/alpha/pci.c
+++ b/hw/alpha/pci.c
@@ -8,6 +8,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
+#include "cpu.h"
#include "alpha_sys.h"
#include "qemu/log.h"
#include "sysemu/sysemu.h"
diff --git a/hw/alpha/trace-events b/hw/alpha/trace-events
deleted file mode 100644
index e44ff01a0..000000000
--- a/hw/alpha/trace-events
+++ /dev/null
@@ -1,4 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/alpha/pci.c
-alpha_pci_iack_write(void) ""
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index 883db13f9..97721b535 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -824,6 +824,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
int i;
dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE);
+ qdev_init_nofail(dev);
s = TYPHOON_PCI_HOST_BRIDGE(dev);
phb = PCI_HOST_BRIDGE(dev);
@@ -888,7 +889,6 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
&s->pchip.reg_mem, &s->pchip.reg_io,
0, 64, TYPE_PCI_BUS);
phb->bus = b;
- qdev_init_nofail(dev);
/* Host memory as seen from the PCI side, via the IOMMU. */
memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 12764ef2b..954c9fe15 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -16,5 +16,4 @@ obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
-obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 49d30782c..bb2a22d96 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -132,14 +132,14 @@ typedef struct {
uint32_t base;
} BitBandState;
-static void bitband_init(Object *obj)
+static int bitband_init(SysBusDevice *dev)
{
- BitBandState *s = BITBAND(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ BitBandState *s = BITBAND(dev);
- memory_region_init_io(&s->iomem, obj, &bitband_ops, &s->base,
+ memory_region_init_io(&s->iomem, OBJECT(s), &bitband_ops, &s->base,
"bitband", 0x02000000);
sysbus_init_mmio(dev, &s->iomem);
+ return 0;
}
static void armv7m_bitband_init(void)
@@ -244,7 +244,9 @@ static Property bitband_properties[] = {
static void bitband_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = bitband_init;
dc->props = bitband_properties;
}
@@ -252,7 +254,6 @@ static const TypeInfo bitband_info = {
.name = TYPE_BITBAND,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(BitBandState),
- .instance_init = bitband_init,
.class_init = bitband_class_init,
};
diff --git a/hw/arm/ast2400.c b/hw/arm/ast2400.c
index 326fdb36e..03f993863 100644
--- a/hw/arm/ast2400.c
+++ b/hw/arm/ast2400.c
@@ -17,22 +17,12 @@
#include "exec/address-spaces.h"
#include "hw/arm/ast2400.h"
#include "hw/char/serial.h"
-#include "qemu/log.h"
-#include "hw/i2c/aspeed_i2c.h"
#define AST2400_UART_5_BASE 0x00184000
#define AST2400_IOMEM_SIZE 0x00200000
#define AST2400_IOMEM_BASE 0x1E600000
-#define AST2400_SMC_BASE AST2400_IOMEM_BASE /* Legacy SMC */
-#define AST2400_FMC_BASE 0X1E620000
-#define AST2400_SPI_BASE 0X1E630000
#define AST2400_VIC_BASE 0x1E6C0000
-#define AST2400_SCU_BASE 0x1E6E2000
#define AST2400_TIMER_BASE 0x1E782000
-#define AST2400_I2C_BASE 0x1E78A000
-
-#define AST2400_FMC_FLASH_BASE 0x20000000
-#define AST2400_SPI_FLASH_BASE 0x30000000
static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
@@ -75,35 +65,13 @@ static void ast2400_init(Object *obj)
object_initialize(&s->timerctrl, sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
object_property_add_child(obj, "timerctrl", OBJECT(&s->timerctrl), NULL);
qdev_set_parent_bus(DEVICE(&s->timerctrl), sysbus_get_default());
-
- object_initialize(&s->i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
- object_property_add_child(obj, "i2c", OBJECT(&s->i2c), NULL);
- qdev_set_parent_bus(DEVICE(&s->i2c), sysbus_get_default());
-
- object_initialize(&s->scu, sizeof(s->scu), TYPE_ASPEED_SCU);
- object_property_add_child(obj, "scu", OBJECT(&s->scu), NULL);
- qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
- qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
- AST2400_A0_SILICON_REV);
- object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
- "hw-strap1", &error_abort);
- object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
- "hw-strap2", &error_abort);
-
- object_initialize(&s->smc, sizeof(s->smc), "aspeed.smc.fmc");
- object_property_add_child(obj, "smc", OBJECT(&s->smc), NULL);
- qdev_set_parent_bus(DEVICE(&s->smc), sysbus_get_default());
-
- object_initialize(&s->spi, sizeof(s->spi), "aspeed.smc.spi");
- object_property_add_child(obj, "spi", OBJECT(&s->spi), NULL);
- qdev_set_parent_bus(DEVICE(&s->spi), sysbus_get_default());
}
static void ast2400_realize(DeviceState *dev, Error **errp)
{
int i;
AST2400State *s = AST2400(dev);
- Error *err = NULL, *local_err = NULL;
+ Error *err = NULL;
/* IO space */
memory_region_init_io(&s->iomem, NULL, &ast2400_io_ops, NULL,
@@ -135,54 +103,12 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
}
- /* SCU */
- object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, AST2400_SCU_BASE);
-
/* UART - attach an 8250 to the IO space as our UART5 */
if (serial_hds[0]) {
qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]);
serial_mm_init(&s->iomem, AST2400_UART_5_BASE, 2,
uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
}
-
- /* I2C */
- object_property_set_bool(OBJECT(&s->i2c), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, AST2400_I2C_BASE);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
- qdev_get_gpio_in(DEVICE(&s->vic), 12));
-
- /* SMC */
- object_property_set_int(OBJECT(&s->smc), 1, "num-cs", &err);
- object_property_set_bool(OBJECT(&s->smc), true, "realized", &local_err);
- error_propagate(&err, local_err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, AST2400_FMC_BASE);
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, AST2400_FMC_FLASH_BASE);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->smc), 0,
- qdev_get_gpio_in(DEVICE(&s->vic), 19));
-
- /* SPI */
- object_property_set_int(OBJECT(&s->spi), 1, "num-cs", &err);
- object_property_set_bool(OBJECT(&s->spi), true, "realized", &local_err);
- error_propagate(&err, local_err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, AST2400_SPI_BASE);
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, AST2400_SPI_FLASH_BASE);
}
static void ast2400_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 2e641a398..234d51843 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -14,7 +14,6 @@
#include "hw/misc/bcm2835_mbox_defs.h"
#include "hw/arm/raspi_platform.h"
#include "sysemu/char.h"
-#include "sysemu/sysemu.h"
/* Peripheral base address on the VC (GPU) system bus */
#define BCM2835_VC_PERI_BASE 0x7e000000
@@ -107,6 +106,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
MemoryRegion *ram;
Error *err = NULL;
uint32_t ram_size, vcram_size;
+ CharDriverState *chr;
int n;
obj = object_property_get_link(OBJECT(dev), "ram", &err);
@@ -147,7 +147,6 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
/* UART0 */
- qdev_prop_set_chr(DEVICE(s->uart0), "chardev", serial_hds[0]);
object_property_set_bool(OBJECT(s->uart0), true, "realized", &err);
if (err) {
error_propagate(errp, err);
@@ -159,8 +158,17 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(s->uart0, 0,
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
INTERRUPT_UART));
+
/* AUX / UART1 */
- qdev_prop_set_chr(DEVICE(&s->aux), "chardev", serial_hds[1]);
+ /* TODO: don't call qemu_char_get_next_serial() here, instead set
+ * chardev properties for each uart at the board level, once pl011
+ * (uart0) has been updated to avoid qemu_char_get_next_serial()
+ */
+ chr = qemu_char_get_next_serial();
+ if (chr == NULL) {
+ chr = qemu_chr_new("bcm2835.uart1", "null", NULL);
+ }
+ qdev_prop_set_chr(DEVICE(&s->aux), "chardev", chr);
object_property_set_bool(OBJECT(&s->aux), true, "realized", &err);
if (err) {
@@ -284,6 +292,8 @@ static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = bcm2835_peripherals_realize;
+ /* Reason: realize() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo bcm2835_peripherals_type_info = {
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 1b913a43c..587694557 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -14,7 +14,6 @@
#include "hw/arm/linux-boot-if.h"
#include "sysemu/kvm.h"
#include "sysemu/sysemu.h"
-#include "sysemu/numa.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "elf.h"
@@ -406,9 +405,6 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
void *fdt = NULL;
int size, rc;
uint32_t acells, scells;
- char *nodename;
- unsigned int i;
- hwaddr mem_base, mem_len;
if (binfo->dtb_filename) {
char *filename;
@@ -460,39 +456,12 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
goto fail;
}
- if (nb_numa_nodes > 0) {
- /*
- * Turn the /memory node created before into a NOP node, then create
- * /memory@addr nodes for all numa nodes respectively.
- */
- qemu_fdt_nop_node(fdt, "/memory");
- mem_base = binfo->loader_start;
- for (i = 0; i < nb_numa_nodes; i++) {
- mem_len = numa_info[i].node_mem;
- nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
- qemu_fdt_add_subnode(fdt, nodename);
- qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
- rc = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
- acells, mem_base,
- scells, mem_len);
- if (rc < 0) {
- fprintf(stderr, "couldn't set %s/reg for node %d\n", nodename,
- i);
- goto fail;
- }
-
- qemu_fdt_setprop_cell(fdt, nodename, "numa-node-id", i);
- mem_base += mem_len;
- g_free(nodename);
- }
- } else {
- rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg",
- acells, binfo->loader_start,
- scells, binfo->ram_size);
- if (rc < 0) {
- fprintf(stderr, "couldn't set /memory/reg\n");
- goto fail;
- }
+ rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg",
+ acells, binfo->loader_start,
+ scells, binfo->ram_size);
+ if (rc < 0) {
+ fprintf(stderr, "couldn't set /memory/reg\n");
+ goto fail;
}
if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
index 2e6953128..8bb308a42 100644
--- a/hw/arm/collie.c
+++ b/hw/arm/collie.c
@@ -18,7 +18,6 @@
#include "hw/block/flash.h"
#include "sysemu/block-backend.h"
#include "exec/address-spaces.h"
-#include "qom/cpu.h"
static struct arm_boot_info collie_binfo = {
.loader_start = SA_SDCS0,
diff --git a/hw/arm/digic.c b/hw/arm/digic.c
index d60ea395f..e0f973032 100644
--- a/hw/arm/digic.c
+++ b/hw/arm/digic.c
@@ -23,7 +23,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/arm/digic.h"
-#include "sysemu/sysemu.h"
#define DIGIC4_TIMER_BASE(n) (0xc0210000 + (n) * 0x100)
@@ -85,7 +84,6 @@ static void digic_realize(DeviceState *dev, Error **errp)
sysbus_mmio_map(sbd, 0, DIGIC4_TIMER_BASE(i));
}
- qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hds[0]);
object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
index b4e358db6..2f878b935 100644
--- a/hw/arm/fsl-imx25.c
+++ b/hw/arm/fsl-imx25.c
@@ -51,7 +51,7 @@ static void fsl_imx25_init(Object *obj)
}
for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
- object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX25_GPT);
+ object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX_GPT);
qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus_get_default());
}
@@ -191,7 +191,6 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
}
qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
-
object_property_set_bool(OBJECT(&s->fec), true, "realized", &err);
if (err) {
error_propagate(errp, err);
@@ -249,16 +248,16 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
}
/* initialize 2 x 16 KB ROM */
- memory_region_init_rom(&s->rom[0], NULL,
- "imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
+ memory_region_init_rom_device(&s->rom[0], NULL, NULL, NULL,
+ "imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
if (err) {
error_propagate(errp, err);
return;
}
memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM0_ADDR,
&s->rom[0]);
- memory_region_init_rom(&s->rom[1], NULL,
- "imx25.rom1", FSL_IMX25_ROM1_SIZE, &err);
+ memory_region_init_rom_device(&s->rom[1], NULL, NULL, NULL,
+ "imx25.rom1", FSL_IMX25_ROM1_SIZE, &err);
if (err) {
error_propagate(errp, err);
return;
diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c
index fe204ace6..31a3a8791 100644
--- a/hw/arm/fsl-imx31.c
+++ b/hw/arm/fsl-imx31.c
@@ -47,7 +47,7 @@ static void fsl_imx31_init(Object *obj)
qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
}
- object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX31_GPT);
+ object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX_GPT);
qdev_set_parent_bus(DEVICE(&s->gpt), sysbus_get_default());
for (i = 0; i < FSL_IMX31_NUM_EPITS; i++) {
@@ -219,8 +219,9 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
}
/* On a real system, the first 16k is a `secure boot rom' */
- memory_region_init_rom(&s->secure_rom, NULL, "imx31.secure_rom",
- FSL_IMX31_SECURE_ROM_SIZE, &err);
+ memory_region_init_rom_device(&s->secure_rom, NULL, NULL, NULL,
+ "imx31.secure_rom",
+ FSL_IMX31_SECURE_ROM_SIZE, &err);
if (err) {
error_propagate(errp, err);
return;
@@ -229,8 +230,8 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
&s->secure_rom);
/* There is also a 16k ROM */
- memory_region_init_rom(&s->rom, NULL, "imx31.rom",
- FSL_IMX31_ROM_SIZE, &err);
+ memory_region_init_rom_device(&s->rom, NULL, NULL, NULL, "imx31.rom",
+ FSL_IMX31_ROM_SIZE, &err);
if (err) {
error_propagate(errp, err);
return;
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
deleted file mode 100644
index 6a1bf263a..000000000
--- a/hw/arm/fsl-imx6.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
- *
- * i.MX6 SOC emulation.
- *
- * Based on hw/arm/fsl-imx31.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 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/>.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu-common.h"
-#include "hw/arm/fsl-imx6.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/char.h"
-#include "qemu/error-report.h"
-
-#define NAME_SIZE 20
-
-static void fsl_imx6_init(Object *obj)
-{
- FslIMX6State *s = FSL_IMX6(obj);
- char name[NAME_SIZE];
- int i;
-
- if (smp_cpus > FSL_IMX6_NUM_CPUS) {
- error_report("%s: Only %d CPUs are supported (%d requested)",
- TYPE_FSL_IMX6, FSL_IMX6_NUM_CPUS, smp_cpus);
- exit(1);
- }
-
- for (i = 0; i < smp_cpus; i++) {
- object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
- "cortex-a9-" TYPE_ARM_CPU);
- snprintf(name, NAME_SIZE, "cpu%d", i);
- object_property_add_child(obj, name, OBJECT(&s->cpu[i]), NULL);
- }
-
- object_initialize(&s->a9mpcore, sizeof(s->a9mpcore), TYPE_A9MPCORE_PRIV);
- qdev_set_parent_bus(DEVICE(&s->a9mpcore), sysbus_get_default());
- object_property_add_child(obj, "a9mpcore", OBJECT(&s->a9mpcore), NULL);
-
- object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX6_CCM);
- qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
- object_property_add_child(obj, "ccm", OBJECT(&s->ccm), NULL);
-
- object_initialize(&s->src, sizeof(s->src), TYPE_IMX6_SRC);
- qdev_set_parent_bus(DEVICE(&s->src), sysbus_get_default());
- object_property_add_child(obj, "src", OBJECT(&s->src), NULL);
-
- for (i = 0; i < FSL_IMX6_NUM_UARTS; i++) {
- object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL);
- qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
- snprintf(name, NAME_SIZE, "uart%d", i + 1);
- object_property_add_child(obj, name, OBJECT(&s->uart[i]), NULL);
- }
-
- object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX6_GPT);
- qdev_set_parent_bus(DEVICE(&s->gpt), sysbus_get_default());
- object_property_add_child(obj, "gpt", OBJECT(&s->gpt), NULL);
-
- for (i = 0; i < FSL_IMX6_NUM_EPITS; i++) {
- object_initialize(&s->epit[i], sizeof(s->epit[i]), TYPE_IMX_EPIT);
- qdev_set_parent_bus(DEVICE(&s->epit[i]), sysbus_get_default());
- snprintf(name, NAME_SIZE, "epit%d", i + 1);
- object_property_add_child(obj, name, OBJECT(&s->epit[i]), NULL);
- }
-
- for (i = 0; i < FSL_IMX6_NUM_I2CS; i++) {
- object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C);
- qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default());
- snprintf(name, NAME_SIZE, "i2c%d", i + 1);
- object_property_add_child(obj, name, OBJECT(&s->i2c[i]), NULL);
- }
-
- for (i = 0; i < FSL_IMX6_NUM_GPIOS; i++) {
- object_initialize(&s->gpio[i], sizeof(s->gpio[i]), TYPE_IMX_GPIO);
- qdev_set_parent_bus(DEVICE(&s->gpio[i]), sysbus_get_default());
- snprintf(name, NAME_SIZE, "gpio%d", i + 1);
- object_property_add_child(obj, name, OBJECT(&s->gpio[i]), NULL);
- }
-
- for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) {
- object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_SYSBUS_SDHCI);
- qdev_set_parent_bus(DEVICE(&s->esdhc[i]), sysbus_get_default());
- snprintf(name, NAME_SIZE, "sdhc%d", i + 1);
- object_property_add_child(obj, name, OBJECT(&s->esdhc[i]), NULL);
- }
-
- for (i = 0; i < FSL_IMX6_NUM_ECSPIS; i++) {
- object_initialize(&s->spi[i], sizeof(s->spi[i]), TYPE_IMX_SPI);
- qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
- snprintf(name, NAME_SIZE, "spi%d", i + 1);
- object_property_add_child(obj, name, OBJECT(&s->spi[i]), NULL);
- }
-
- object_initialize(&s->eth, sizeof(s->eth), TYPE_IMX_ENET);
- qdev_set_parent_bus(DEVICE(&s->eth), sysbus_get_default());
- object_property_add_child(obj, "eth", OBJECT(&s->eth), NULL);
-}
-
-static void fsl_imx6_realize(DeviceState *dev, Error **errp)
-{
- FslIMX6State *s = FSL_IMX6(dev);
- uint16_t i;
- Error *err = NULL;
-
- for (i = 0; i < smp_cpus; i++) {
-
- /* On uniprocessor, the CBAR is set to 0 */
- if (smp_cpus > 1) {
- object_property_set_int(OBJECT(&s->cpu[i]), FSL_IMX6_A9MPCORE_ADDR,
- "reset-cbar", &error_abort);
- }
-
- /* All CPU but CPU 0 start in power off mode */
- if (i) {
- object_property_set_bool(OBJECT(&s->cpu[i]), true,
- "start-powered-off", &error_abort);
- }
-
- object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- }
-
- object_property_set_int(OBJECT(&s->a9mpcore), smp_cpus, "num-cpu",
- &error_abort);
-
- object_property_set_int(OBJECT(&s->a9mpcore),
- FSL_IMX6_MAX_IRQ + GIC_INTERNAL, "num-irq",
- &error_abort);
-
- object_property_set_bool(OBJECT(&s->a9mpcore), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, FSL_IMX6_A9MPCORE_ADDR);
-
- for (i = 0; i < smp_cpus; i++) {
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i,
- qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + smp_cpus,
- qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
- }
-
- object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX6_CCM_ADDR);
-
- object_property_set_bool(OBJECT(&s->src), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX6_SRC_ADDR);
-
- /* Initialize all UARTs */
- for (i = 0; i < FSL_IMX6_NUM_UARTS; i++) {
- static const struct {
- hwaddr addr;
- unsigned int irq;
- } serial_table[FSL_IMX6_NUM_UARTS] = {
- { FSL_IMX6_UART1_ADDR, FSL_IMX6_UART1_IRQ },
- { FSL_IMX6_UART2_ADDR, FSL_IMX6_UART2_IRQ },
- { FSL_IMX6_UART3_ADDR, FSL_IMX6_UART3_IRQ },
- { FSL_IMX6_UART4_ADDR, FSL_IMX6_UART4_IRQ },
- { FSL_IMX6_UART5_ADDR, FSL_IMX6_UART5_IRQ },
- };
-
- if (i < MAX_SERIAL_PORTS) {
- CharDriverState *chr;
-
- chr = serial_hds[i];
-
- if (!chr) {
- char *label = g_strdup_printf("imx6.uart%d", i + 1);
- chr = qemu_chr_new(label, "null", NULL);
- g_free(label);
- serial_hds[i] = chr;
- }
-
- qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
- }
-
- object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
-
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- serial_table[i].irq));
- }
-
- s->gpt.ccm = IMX_CCM(&s->ccm);
-
- object_property_set_bool(OBJECT(&s->gpt), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
-
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt), 0, FSL_IMX6_GPT_ADDR);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt), 0,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- FSL_IMX6_GPT_IRQ));
-
- /* Initialize all EPIT timers */
- for (i = 0; i < FSL_IMX6_NUM_EPITS; i++) {
- static const struct {
- hwaddr addr;
- unsigned int irq;
- } epit_table[FSL_IMX6_NUM_EPITS] = {
- { FSL_IMX6_EPIT1_ADDR, FSL_IMX6_EPIT1_IRQ },
- { FSL_IMX6_EPIT2_ADDR, FSL_IMX6_EPIT2_IRQ },
- };
-
- s->epit[i].ccm = IMX_CCM(&s->ccm);
-
- object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
-
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- epit_table[i].irq));
- }
-
- /* Initialize all I2C */
- for (i = 0; i < FSL_IMX6_NUM_I2CS; i++) {
- static const struct {
- hwaddr addr;
- unsigned int irq;
- } i2c_table[FSL_IMX6_NUM_I2CS] = {
- { FSL_IMX6_I2C1_ADDR, FSL_IMX6_I2C1_IRQ },
- { FSL_IMX6_I2C2_ADDR, FSL_IMX6_I2C2_IRQ },
- { FSL_IMX6_I2C3_ADDR, FSL_IMX6_I2C3_IRQ }
- };
-
- object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
-
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- i2c_table[i].irq));
- }
-
- /* Initialize all GPIOs */
- for (i = 0; i < FSL_IMX6_NUM_GPIOS; i++) {
- static const struct {
- hwaddr addr;
- unsigned int irq_low;
- unsigned int irq_high;
- } gpio_table[FSL_IMX6_NUM_GPIOS] = {
- {
- FSL_IMX6_GPIO1_ADDR,
- FSL_IMX6_GPIO1_LOW_IRQ,
- FSL_IMX6_GPIO1_HIGH_IRQ
- },
- {
- FSL_IMX6_GPIO2_ADDR,
- FSL_IMX6_GPIO2_LOW_IRQ,
- FSL_IMX6_GPIO2_HIGH_IRQ
- },
- {
- FSL_IMX6_GPIO3_ADDR,
- FSL_IMX6_GPIO3_LOW_IRQ,
- FSL_IMX6_GPIO3_HIGH_IRQ
- },
- {
- FSL_IMX6_GPIO4_ADDR,
- FSL_IMX6_GPIO4_LOW_IRQ,
- FSL_IMX6_GPIO4_HIGH_IRQ
- },
- {
- FSL_IMX6_GPIO5_ADDR,
- FSL_IMX6_GPIO5_LOW_IRQ,
- FSL_IMX6_GPIO5_HIGH_IRQ
- },
- {
- FSL_IMX6_GPIO6_ADDR,
- FSL_IMX6_GPIO6_LOW_IRQ,
- FSL_IMX6_GPIO6_HIGH_IRQ
- },
- {
- FSL_IMX6_GPIO7_ADDR,
- FSL_IMX6_GPIO7_LOW_IRQ,
- FSL_IMX6_GPIO7_HIGH_IRQ
- },
- };
-
- object_property_set_bool(OBJECT(&s->gpio[i]), true, "has-edge-sel",
- &error_abort);
- object_property_set_bool(OBJECT(&s->gpio[i]), true, "has-upper-pin-irq",
- &error_abort);
- object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
-
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- gpio_table[i].irq_low));
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- gpio_table[i].irq_high));
- }
-
- /* Initialize all SDHC */
- for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) {
- static const struct {
- hwaddr addr;
- unsigned int irq;
- } esdhc_table[FSL_IMX6_NUM_ESDHCS] = {
- { FSL_IMX6_uSDHC1_ADDR, FSL_IMX6_uSDHC1_IRQ },
- { FSL_IMX6_uSDHC2_ADDR, FSL_IMX6_uSDHC2_IRQ },
- { FSL_IMX6_uSDHC3_ADDR, FSL_IMX6_uSDHC3_IRQ },
- { FSL_IMX6_uSDHC4_ADDR, FSL_IMX6_uSDHC4_IRQ },
- };
-
- object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->esdhc[i]), 0,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- esdhc_table[i].irq));
- }
-
- /* Initialize all ECSPI */
- for (i = 0; i < FSL_IMX6_NUM_ECSPIS; i++) {
- static const struct {
- hwaddr addr;
- unsigned int irq;
- } spi_table[FSL_IMX6_NUM_ECSPIS] = {
- { FSL_IMX6_eCSPI1_ADDR, FSL_IMX6_ECSPI1_IRQ },
- { FSL_IMX6_eCSPI2_ADDR, FSL_IMX6_ECSPI2_IRQ },
- { FSL_IMX6_eCSPI3_ADDR, FSL_IMX6_ECSPI3_IRQ },
- { FSL_IMX6_eCSPI4_ADDR, FSL_IMX6_ECSPI4_IRQ },
- { FSL_IMX6_eCSPI5_ADDR, FSL_IMX6_ECSPI5_IRQ },
- };
-
- /* Initialize the SPI */
- object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
-
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- spi_table[i].irq));
- }
-
- object_property_set_bool(OBJECT(&s->eth), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth), 0, FSL_IMX6_ENET_ADDR);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth), 0,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- FSL_IMX6_ENET_MAC_IRQ));
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth), 1,
- qdev_get_gpio_in(DEVICE(&s->a9mpcore),
- FSL_IMX6_ENET_MAC_1588_IRQ));
-
- /* ROM memory */
- memory_region_init_rom(&s->rom, NULL, "imx6.rom",
- FSL_IMX6_ROM_SIZE, &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- memory_region_add_subregion(get_system_memory(), FSL_IMX6_ROM_ADDR,
- &s->rom);
-
- /* CAAM memory */
- memory_region_init_rom(&s->caam, NULL, "imx6.caam",
- FSL_IMX6_CAAM_MEM_SIZE, &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- memory_region_add_subregion(get_system_memory(), FSL_IMX6_CAAM_MEM_ADDR,
- &s->caam);
-
- /* OCRAM memory */
- memory_region_init_ram(&s->ocram, NULL, "imx6.ocram", FSL_IMX6_OCRAM_SIZE,
- &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- memory_region_add_subregion(get_system_memory(), FSL_IMX6_OCRAM_ADDR,
- &s->ocram);
- vmstate_register_ram_global(&s->ocram);
-
- /* internal OCRAM (256 KB) is aliased over 1 MB */
- memory_region_init_alias(&s->ocram_alias, NULL, "imx6.ocram_alias",
- &s->ocram, 0, FSL_IMX6_OCRAM_ALIAS_SIZE);
- memory_region_add_subregion(get_system_memory(), FSL_IMX6_OCRAM_ALIAS_ADDR,
- &s->ocram_alias);
-}
-
-static void fsl_imx6_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- dc->realize = fsl_imx6_realize;
-
- /*
- * Reason: creates an ARM CPU, thus use after free(), see
- * arm_cpu_class_init()
- */
- dc->cannot_destroy_with_object_finalize_yet = true;
- dc->desc = "i.MX6 SOC";
-}
-
-static const TypeInfo fsl_imx6_type_info = {
- .name = TYPE_FSL_IMX6,
- .parent = TYPE_DEVICE,
- .instance_size = sizeof(FslIMX6State),
- .instance_init = fsl_imx6_init,
- .class_init = fsl_imx6_class_init,
-};
-
-static void fsl_imx6_register_types(void)
-{
- type_register_static(&fsl_imx6_type_info);
-}
-
-type_init(fsl_imx6_register_types)
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index 80e5fd458..d9930c0d3 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -30,7 +30,6 @@
#include "sysemu/block-backend.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
-#include "hw/char/pl011.h"
#define SMP_BOOT_ADDR 0x100
#define SMP_BOOT_REG 0x40
@@ -169,20 +168,23 @@ static void highbank_regs_reset(DeviceState *dev)
s->regs[0x43] = 0x05F40121;
}
-static void highbank_regs_init(Object *obj)
+static int highbank_regs_init(SysBusDevice *dev)
{
- HighbankRegsState *s = HIGHBANK_REGISTERS(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ HighbankRegsState *s = HIGHBANK_REGISTERS(dev);
- memory_region_init_io(&s->iomem, obj, &hb_mem_ops, s->regs,
+ memory_region_init_io(&s->iomem, OBJECT(s), &hb_mem_ops, s->regs,
"highbank_regs", 0x1000);
sysbus_init_mmio(dev, &s->iomem);
+
+ return 0;
}
static void highbank_regs_class_init(ObjectClass *klass, void *data)
{
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
+ sbc->init = highbank_regs_init;
dc->desc = "Calxeda Highbank registers";
dc->vmsd = &vmstate_highbank_regs;
dc->reset = highbank_regs_reset;
@@ -192,7 +194,6 @@ static const TypeInfo highbank_regs_info = {
.name = TYPE_HIGHBANK_REGISTERS,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(HighbankRegsState),
- .instance_init = highbank_regs_init,
.class_init = highbank_regs_class_init,
};
@@ -327,7 +328,7 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, 0xfff34000);
sysbus_connect_irq(busdev, 0, pic[18]);
- pl011_create(0xfff36000, pic[20], serial_hds[0]);
+ sysbus_create_simple("pl011", 0xfff36000, pic[20]);
dev = qdev_create(NULL, "highbank-regs");
qdev_init_nofail(dev);
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 96dc15002..e31bca6e7 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -20,7 +20,6 @@
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"
#include "qemu/error-report.h"
-#include "hw/char/pl011.h"
#define TYPE_INTEGRATOR_CM "integrator_core"
#define INTEGRATOR_CM(obj) \
@@ -243,10 +242,9 @@ static const MemoryRegionOps integratorcm_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void integratorcm_init(Object *obj)
+static int integratorcm_init(SysBusDevice *dev)
{
- IntegratorCMState *s = INTEGRATOR_CM(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ IntegratorCMState *s = INTEGRATOR_CM(dev);
s->cm_osc = 0x01000048;
/* ??? What should the high bits of this value be? */
@@ -271,16 +269,17 @@ static void integratorcm_init(Object *obj)
s->cm_init = 0x00000112;
s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
1000);
- memory_region_init_ram(&s->flash, obj, "integrator.flash", 0x100000,
+ memory_region_init_ram(&s->flash, OBJECT(s), "integrator.flash", 0x100000,
&error_fatal);
vmstate_register_ram_global(&s->flash);
- memory_region_init_io(&s->iomem, obj, &integratorcm_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &integratorcm_ops, s,
"integratorcm", 0x00800000);
sysbus_init_mmio(dev, &s->iomem);
integratorcm_do_remap(s);
/* ??? Save/restore. */
+ return 0;
}
/* Integrator/CP hardware emulation. */
@@ -395,18 +394,18 @@ static const MemoryRegionOps icp_pic_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void icp_pic_init(Object *obj)
+static int icp_pic_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- icp_pic_state *s = INTEGRATOR_PIC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ icp_pic_state *s = INTEGRATOR_PIC(dev);
qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
sysbus_init_irq(sbd, &s->parent_irq);
sysbus_init_irq(sbd, &s->parent_fiq);
- memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &icp_pic_ops, s,
"icp-pic", 0x00800000);
sysbus_init_mmio(sbd, &s->iomem);
+ return 0;
}
/* CP control registers. */
@@ -589,8 +588,8 @@ static void integratorcp_init(MachineState *machine)
sysbus_create_varargs("integrator_pit", 0x13000000,
pic[5], pic[6], pic[7], NULL);
sysbus_create_simple("pl031", 0x15000000, pic[8]);
- pl011_create(0x16000000, pic[1], serial_hds[0]);
- pl011_create(0x17000000, pic[2], serial_hds[1]);
+ sysbus_create_simple("pl011", 0x16000000, pic[1]);
+ sysbus_create_simple("pl011", 0x17000000, pic[2]);
icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000,
qdev_get_gpio_in(sic, 3));
sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
@@ -631,7 +630,9 @@ static Property core_properties[] = {
static void core_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = integratorcm_init;
dc->props = core_properties;
}
@@ -639,15 +640,21 @@ static const TypeInfo core_info = {
.name = TYPE_INTEGRATOR_CM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IntegratorCMState),
- .instance_init = integratorcm_init,
.class_init = core_class_init,
};
+static void icp_pic_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = icp_pic_init;
+}
+
static const TypeInfo icp_pic_info = {
.name = TYPE_INTEGRATOR_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(icp_pic_state),
- .instance_init = icp_pic_init,
+ .class_init = icp_pic_class_init,
};
static const TypeInfo icp_ctrl_regs_info = {
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index cc50ace13..7a4cc07dd 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -378,7 +378,7 @@ static void eth_cleanup(NetClientState *nc)
}
static NetClientInfo net_mv88w8618_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = eth_receive,
.cleanup = eth_cleanup,
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index fea911e3e..538250555 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -20,9 +20,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "cpu.h"
#include "qemu/cutils.h"
-#include "qemu/bswap.h"
#include "sysemu/sysemu.h"
#include "hw/arm/omap.h"
#include "hw/arm/arm.h"
@@ -37,7 +35,6 @@
#include "hw/loader.h"
#include "sysemu/block-backend.h"
#include "hw/sysbus.h"
-#include "qemu/log.h"
#include "exec/address-spaces.h"
/* Nokia N8x0 support */
@@ -1351,7 +1348,7 @@ static void n8x0_init(MachineState *machine,
n8x0_dss_setup(s);
n8x0_cbus_setup(s);
n8x0_uart_setup(s);
- if (machine_usb(machine)) {
+ if (usb_enabled()) {
n8x0_usb_setup(s);
}
@@ -1367,7 +1364,7 @@ static void n8x0_init(MachineState *machine,
if (option_rom[0].name &&
(machine->boot_order[0] == 'n' || !machine->kernel_filename)) {
- uint8_t *nolo_tags = g_new(uint8_t, 0x10000);
+ uint8_t nolo_tags[0x10000];
/* No, wait, better start at the ROM. */
s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
@@ -1386,7 +1383,6 @@ static void n8x0_init(MachineState *machine,
n800_setup_nolo_tags(nolo_tags);
cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
- g_free(nolo_tags);
}
}
diff --git a/hw/arm/palmetto-bmc.c b/hw/arm/palmetto-bmc.c
index 54e29a865..89ebd92b9 100644
--- a/hw/arm/palmetto-bmc.c
+++ b/hw/arm/palmetto-bmc.c
@@ -17,9 +17,6 @@
#include "hw/arm/arm.h"
#include "hw/arm/ast2400.h"
#include "hw/boards.h"
-#include "qemu/log.h"
-#include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
static struct arm_boot_info palmetto_bmc_binfo = {
.loader_start = AST2400_SDRAM_BASE,
@@ -32,32 +29,6 @@ typedef struct PalmettoBMCState {
MemoryRegion ram;
} PalmettoBMCState;
-static void palmetto_bmc_init_flashes(AspeedSMCState *s, const char *flashtype,
- Error **errp)
-{
- int i ;
-
- for (i = 0; i < s->num_cs; ++i) {
- AspeedSMCFlash *fl = &s->flashes[i];
- DriveInfo *dinfo = drive_get_next(IF_MTD);
- qemu_irq cs_line;
-
- /*
- * FIXME: check that we are not using a flash module exceeding
- * the controller segment size
- */
- fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
- if (dinfo) {
- qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
- errp);
- }
- qdev_init_nofail(fl->flash);
-
- cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
- sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
- }
-}
-
static void palmetto_bmc_init(MachineState *machine)
{
PalmettoBMCState *bmc;
@@ -72,14 +43,9 @@ static void palmetto_bmc_init(MachineState *machine)
&bmc->ram);
object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
&error_abort);
- object_property_set_int(OBJECT(&bmc->soc), 0x120CE416, "hw-strap1",
- &error_abort);
object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
&error_abort);
- palmetto_bmc_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
- palmetto_bmc_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
-
palmetto_bmc_binfo.kernel_filename = machine->kernel_filename;
palmetto_bmc_binfo.initrd_filename = machine->initrd_filename;
palmetto_bmc_binfo.kernel_cmdline = machine->kernel_cmdline;
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index cb5570468..1a8c36033 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1107,10 +1107,9 @@ static const MemoryRegionOps pxa2xx_rtc_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void pxa2xx_rtc_init(Object *obj)
+static int pxa2xx_rtc_init(SysBusDevice *dev)
{
- PXA2xxRTCState *s = PXA2XX_RTC(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ PXA2xxRTCState *s = PXA2XX_RTC(dev);
struct tm tm;
int wom;
@@ -1139,9 +1138,11 @@ static void pxa2xx_rtc_init(Object *obj)
sysbus_init_irq(dev, &s->rtc_irq);
- memory_region_init_io(&s->iomem, obj, &pxa2xx_rtc_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_rtc_ops, s,
"pxa2xx-rtc", 0x10000);
sysbus_init_mmio(dev, &s->iomem);
+
+ return 0;
}
static void pxa2xx_rtc_pre_save(void *opaque)
@@ -1194,7 +1195,9 @@ static const VMStateDescription vmstate_pxa2xx_rtc_regs = {
static void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = pxa2xx_rtc_init;
dc->desc = "PXA2xx RTC Controller";
dc->vmsd = &vmstate_pxa2xx_rtc_regs;
}
@@ -1203,7 +1206,6 @@ static const TypeInfo pxa2xx_rtc_sysbus_info = {
.name = TYPE_PXA2XX_RTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxRTCState),
- .instance_init = pxa2xx_rtc_init,
.class_init = pxa2xx_rtc_sysbus_class_init,
};
@@ -1499,18 +1501,19 @@ PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
return s;
}
-static void pxa2xx_i2c_initfn(Object *obj)
+static int pxa2xx_i2c_initfn(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- PXA2xxI2CState *s = PXA2XX_I2C(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ PXA2xxI2CState *s = PXA2XX_I2C(dev);
s->bus = i2c_init_bus(dev, "i2c");
- memory_region_init_io(&s->iomem, obj, &pxa2xx_i2c_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_i2c_ops, s,
"pxa2xx-i2c", s->region_size);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
+
+ return 0;
}
I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s)
@@ -1527,7 +1530,9 @@ static Property pxa2xx_i2c_properties[] = {
static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = pxa2xx_i2c_initfn;
dc->desc = "PXA2xx I2C Bus Controller";
dc->vmsd = &vmstate_pxa2xx_i2c;
dc->props = pxa2xx_i2c_properties;
@@ -1537,7 +1542,6 @@ static const TypeInfo pxa2xx_i2c_info = {
.name = TYPE_PXA2XX_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxI2CState),
- .instance_init = pxa2xx_i2c_initfn,
.class_init = pxa2xx_i2c_class_init,
};
@@ -2165,8 +2169,10 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
}
- sysbus_create_simple("sysbus-ohci", 0x4c000000,
- qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
+ if (usb_enabled()) {
+ sysbus_create_simple("sysbus-ohci", 0x4c000000,
+ qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
+ }
s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
@@ -2296,8 +2302,10 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
}
- sysbus_create_simple("sysbus-ohci", 0x4c000000,
- qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
+ if (usb_enabled()) {
+ sysbus_create_simple("sysbus-ohci", 0x4c000000,
+ qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
+ }
s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index 576a8eb91..67e7e7094 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -8,11 +8,9 @@
*/
#include "qemu/osdep.h"
-#include "cpu.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "hw/arm/pxa.h"
-#include "qemu/log.h"
#define PXA2XX_GPIO_BANKS 4
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index b516ced8c..7e51532cd 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -310,10 +310,17 @@ static VMStateDescription vmstate_pxa2xx_pic_regs = {
},
};
+static int pxa2xx_pic_initfn(SysBusDevice *dev)
+{
+ return 0;
+}
+
static void pxa2xx_pic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = pxa2xx_pic_initfn;
dc->desc = "PXA2xx PIC";
dc->vmsd = &vmstate_pxa2xx_pic_regs;
}
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index 8eafccaf1..3222b360e 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -23,7 +23,6 @@
#include "sysemu/block-backend.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
-#include "hw/char/pl011.h"
#define SMP_BOOT_ADDR 0xe0000000
#define SMP_BOOTREG_ADDR 0x10000030
@@ -203,10 +202,10 @@ static void realview_init(MachineState *machine,
sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]);
- pl011_create(0x10009000, pic[12], serial_hds[0]);
- pl011_create(0x1000a000, pic[13], serial_hds[1]);
- pl011_create(0x1000b000, pic[14], serial_hds[2]);
- pl011_create(0x1000c000, pic[15], serial_hds[3]);
+ sysbus_create_simple("pl011", 0x10009000, pic[12]);
+ sysbus_create_simple("pl011", 0x1000a000, pic[13]);
+ sysbus_create_simple("pl011", 0x1000b000, pic[14]);
+ sysbus_create_simple("pl011", 0x1000c000, pic[15]);
/* DMA controller is optional, apparently. */
sysbus_create_simple("pl081", 0x10030000, pic[24]);
@@ -254,7 +253,7 @@ static void realview_init(MachineState *machine,
sysbus_connect_irq(busdev, 2, pic[50]);
sysbus_connect_irq(busdev, 3, pic[51]);
pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
- if (machine_usb(machine)) {
+ if (usb_enabled()) {
pci_create_simple(pci_bus, -1, "pci-ohci");
}
n = drive_get_max_bus(IF_SCSI);
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
deleted file mode 100644
index 4e7ac8cc4..000000000
--- a/hw/arm/sabrelite.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * SABRELITE Board System emulation.
- *
- * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
- *
- * This code is licensed under the GPL, version 2 or later.
- * See the file `COPYING' in the top level directory.
- *
- * It (partially) emulates a sabrelite board, with a Freescale
- * i.MX6 SoC
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu-common.h"
-#include "hw/arm/fsl-imx6.h"
-#include "hw/boards.h"
-#include "sysemu/sysemu.h"
-#include "qemu/error-report.h"
-#include "sysemu/qtest.h"
-
-typedef struct IMX6Sabrelite {
- FslIMX6State soc;
- MemoryRegion ram;
-} IMX6Sabrelite;
-
-static struct arm_boot_info sabrelite_binfo = {
- /* DDR memory start */
- .loader_start = FSL_IMX6_MMDC_ADDR,
- /* No board ID, we boot from DT tree */
- .board_id = -1,
-};
-
-/* No need to do any particular setup for secondary boot */
-static void sabrelite_write_secondary(ARMCPU *cpu,
- const struct arm_boot_info *info)
-{
-}
-
-/* Secondary cores are reset through SRC device */
-static void sabrelite_reset_secondary(ARMCPU *cpu,
- const struct arm_boot_info *info)
-{
-}
-
-static void sabrelite_init(MachineState *machine)
-{
- IMX6Sabrelite *s = g_new0(IMX6Sabrelite, 1);
- Error *err = NULL;
-
- /* Check the amount of memory is compatible with the SOC */
- if (machine->ram_size > FSL_IMX6_MMDC_SIZE) {
- error_report("RAM size " RAM_ADDR_FMT " above max supported (%08x)",
- machine->ram_size, FSL_IMX6_MMDC_SIZE);
- exit(1);
- }
-
- object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX6);
- object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
- &error_abort);
-
- object_property_set_bool(OBJECT(&s->soc), true, "realized", &err);
- if (err != NULL) {
- error_report("%s", error_get_pretty(err));
- exit(1);
- }
-
- memory_region_allocate_system_memory(&s->ram, NULL, "sabrelite.ram",
- machine->ram_size);
- memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR,
- &s->ram);
-
- {
- /*
- * TODO: Ideally we would expose the chip select and spi bus on the
- * SoC object using alias properties; then we would not need to
- * directly access the underlying spi device object.
- */
- /* Add the sst25vf016b NOR FLASH memory to first SPI */
- Object *spi_dev;
-
- spi_dev = object_resolve_path_component(OBJECT(&s->soc), "spi1");
- if (spi_dev) {
- SSIBus *spi_bus;
-
- spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(spi_dev), "spi");
- if (spi_bus) {
- DeviceState *flash_dev;
- qemu_irq cs_line;
- DriveInfo *dinfo = drive_get_next(IF_MTD);
-
- flash_dev = ssi_create_slave_no_init(spi_bus, "sst25vf016b");
- if (dinfo) {
- qdev_prop_set_drive(flash_dev, "drive",
- blk_by_legacy_dinfo(dinfo),
- &error_fatal);
- }
- qdev_init_nofail(flash_dev);
-
- cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
- sysbus_connect_irq(SYS_BUS_DEVICE(spi_dev), 1, cs_line);
- }
- }
- }
-
- sabrelite_binfo.ram_size = machine->ram_size;
- sabrelite_binfo.kernel_filename = machine->kernel_filename;
- sabrelite_binfo.kernel_cmdline = machine->kernel_cmdline;
- sabrelite_binfo.initrd_filename = machine->initrd_filename;
- sabrelite_binfo.nb_cpus = smp_cpus;
- sabrelite_binfo.secure_boot = true;
- sabrelite_binfo.write_secondary_boot = sabrelite_write_secondary;
- sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary;
-
- if (!qtest_enabled()) {
- arm_load_kernel(&s->soc.cpu[0], &sabrelite_binfo);
- }
-}
-
-static void sabrelite_machine_init(MachineClass *mc)
-{
- mc->desc = "Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)";
- mc->init = sabrelite_init;
- mc->max_cpus = FSL_IMX6_NUM_CPUS;
-}
-
-DEFINE_MACHINE("sabrelite", sabrelite_machine_init)
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 41cc2eeeb..bf61d63b5 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -164,10 +164,9 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE);
}
-static void sl_nand_init(Object *obj)
+static int sl_nand_init(SysBusDevice *dev)
{
- SLNANDState *s = SL_NAND(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ SLNANDState *s = SL_NAND(dev);
DriveInfo *nand;
s->ctl = 0;
@@ -176,8 +175,10 @@ static void sl_nand_init(Object *obj)
s->nand = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL,
s->manf_id, s->chip_id);
- memory_region_init_io(&s->iomem, obj, &sl_ops, s, "sl", 0x40);
+ memory_region_init_io(&s->iomem, OBJECT(s), &sl_ops, s, "sl", 0x40);
sysbus_init_mmio(dev, &s->iomem);
+
+ return 0;
}
/* Spitz Keyboard */
@@ -500,10 +501,10 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
}
-static void spitz_keyboard_init(Object *obj)
+static int spitz_keyboard_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- SpitzKeyboardState *s = SPITZ_KEYBOARD(obj);
+ DeviceState *dev = DEVICE(sbd);
+ SpitzKeyboardState *s = SPITZ_KEYBOARD(dev);
int i, j;
for (i = 0; i < 0x80; i ++)
@@ -518,6 +519,8 @@ static void spitz_keyboard_init(Object *obj)
s->kbdtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, spitz_keyboard_tick, s);
qdev_init_gpio_in(dev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
qdev_init_gpio_out(dev, s->sense, SPITZ_KEY_SENSE_NUM);
+
+ return 0;
}
/* LCD backlight controller */
@@ -598,13 +601,15 @@ static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
return 0;
}
-static void spitz_lcdtg_realize(SSISlave *dev, Error **errp)
+static int spitz_lcdtg_init(SSISlave *dev)
{
SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
spitz_lcdtg = s;
s->bl_power = 0;
s->bl_intensity = 0x20;
+
+ return 0;
}
/* SSP devices */
@@ -664,7 +669,7 @@ static void spitz_adc_temp_on(void *opaque, int line, int level)
max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
}
-static void corgi_ssp_realize(SSISlave *d, Error **errp)
+static int corgi_ssp_init(SSISlave *d)
{
DeviceState *dev = DEVICE(d);
CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, d);
@@ -673,6 +678,8 @@ static void corgi_ssp_realize(SSISlave *d, Error **errp)
s->bus[0] = ssi_create_bus(dev, "ssi0");
s->bus[1] = ssi_create_bus(dev, "ssi1");
s->bus[2] = ssi_create_bus(dev, "ssi2");
+
+ return 0;
}
static void spitz_ssp_attach(PXA2xxState *cpu)
@@ -1058,7 +1065,9 @@ static Property sl_nand_properties[] = {
static void sl_nand_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = sl_nand_init;
dc->vmsd = &vmstate_sl_nand_info;
dc->props = sl_nand_properties;
/* Reason: init() method uses drive_get() */
@@ -1069,7 +1078,6 @@ static const TypeInfo sl_nand_info = {
.name = TYPE_SL_NAND,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SLNANDState),
- .instance_init = sl_nand_init,
.class_init = sl_nand_class_init,
};
@@ -1089,7 +1097,9 @@ static VMStateDescription vmstate_spitz_kbd = {
static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = spitz_keyboard_init;
dc->vmsd = &vmstate_spitz_kbd;
}
@@ -1097,7 +1107,6 @@ static const TypeInfo spitz_keyboard_info = {
.name = TYPE_SPITZ_KEYBOARD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SpitzKeyboardState),
- .instance_init = spitz_keyboard_init,
.class_init = spitz_keyboard_class_init,
};
@@ -1117,7 +1126,7 @@ static void corgi_ssp_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
- k->realize = corgi_ssp_realize;
+ k->init = corgi_ssp_init;
k->transfer = corgi_ssp_transfer;
dc->vmsd = &vmstate_corgi_ssp_regs;
}
@@ -1146,7 +1155,7 @@ static void spitz_lcdtg_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
- k->realize = spitz_lcdtg_realize;
+ k->init = spitz_lcdtg_init;
k->transfer = spitz_lcdtg_transfer;
dc->vmsd = &vmstate_spitz_lcdtg_regs;
}
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index 794a3ada7..c1766f856 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -17,10 +17,8 @@
#include "hw/i2c/i2c.h"
#include "net/net.h"
#include "hw/boards.h"
-#include "qemu/log.h"
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"
-#include "hw/char/pl011.h"
#define GPIO_A 0
#define GPIO_B 1
@@ -318,22 +316,23 @@ static const VMStateDescription vmstate_stellaris_gptm = {
}
};
-static void stellaris_gptm_init(Object *obj)
+static int stellaris_gptm_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- gptm_state *s = STELLARIS_GPTM(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ gptm_state *s = STELLARIS_GPTM(dev);
sysbus_init_irq(sbd, &s->irq);
qdev_init_gpio_out(dev, &s->trigger, 1);
- memory_region_init_io(&s->iomem, obj, &gptm_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &gptm_ops, s,
"gptm", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
s->opaque[0] = s->opaque[1] = s;
s->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[0]);
s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]);
+ vmstate_register(dev, -1, &vmstate_stellaris_gptm, s);
+ return 0;
}
@@ -874,22 +873,23 @@ static const VMStateDescription vmstate_stellaris_i2c = {
}
};
-static void stellaris_i2c_init(Object *obj)
+static int stellaris_i2c_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- stellaris_i2c_state *s = STELLARIS_I2C(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ stellaris_i2c_state *s = STELLARIS_I2C(dev);
I2CBus *bus;
sysbus_init_irq(sbd, &s->irq);
bus = i2c_init_bus(dev, "i2c");
s->bus = bus;
- memory_region_init_io(&s->iomem, obj, &stellaris_i2c_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_i2c_ops, s,
"i2c", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
/* ??? For now we only implement the master interface. */
stellaris_i2c_reset(s);
+ vmstate_register(dev, -1, &vmstate_stellaris_i2c, s);
+ return 0;
}
/* Analogue to Digital Converter. This is only partially implemented,
@@ -1160,22 +1160,23 @@ static const VMStateDescription vmstate_stellaris_adc = {
}
};
-static void stellaris_adc_init(Object *obj)
+static int stellaris_adc_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- stellaris_adc_state *s = STELLARIS_ADC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ stellaris_adc_state *s = STELLARIS_ADC(dev);
int n;
for (n = 0; n < 4; n++) {
sysbus_init_irq(sbd, &s->irq[n]);
}
- memory_region_init_io(&s->iomem, obj, &stellaris_adc_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_adc_ops, s,
"adc", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
stellaris_adc_reset(s);
qdev_init_gpio_in(dev, stellaris_adc_trigger, 1);
+ vmstate_register(dev, -1, &vmstate_stellaris_adc, s);
+ return 0;
}
static
@@ -1304,9 +1305,8 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
for (i = 0; i < 4; i++) {
if (board->dc2 & (1 << i)) {
- pl011_luminary_create(0x4000c000 + i * 0x1000,
- qdev_get_gpio_in(nvic, uart_irq[i]),
- serial_hds[i]);
+ sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000,
+ qdev_get_gpio_in(nvic, uart_irq[i]));
}
}
if (board->dc2 & (1 << 4)) {
@@ -1425,46 +1425,43 @@ type_init(stellaris_machine_init)
static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
{
- DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
- dc->vmsd = &vmstate_stellaris_i2c;
+ sdc->init = stellaris_i2c_init;
}
static const TypeInfo stellaris_i2c_info = {
.name = TYPE_STELLARIS_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(stellaris_i2c_state),
- .instance_init = stellaris_i2c_init,
.class_init = stellaris_i2c_class_init,
};
static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
{
- DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
- dc->vmsd = &vmstate_stellaris_gptm;
+ sdc->init = stellaris_gptm_init;
}
static const TypeInfo stellaris_gptm_info = {
.name = TYPE_STELLARIS_GPTM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(gptm_state),
- .instance_init = stellaris_gptm_init,
.class_init = stellaris_gptm_class_init,
};
static void stellaris_adc_class_init(ObjectClass *klass, void *data)
{
- DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
- dc->vmsd = &vmstate_stellaris_adc;
+ sdc->init = stellaris_adc_init;
}
static const TypeInfo stellaris_adc_info = {
.name = TYPE_STELLARIS_ADC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(stellaris_adc_state),
- .instance_init = stellaris_adc_init,
.class_init = stellaris_adc_class_init,
};
diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
index de26b8caf..a5ea1e237 100644
--- a/hw/arm/stm32f205_soc.c
+++ b/hw/arm/stm32f205_soc.c
@@ -25,6 +25,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
+#include "cpu.h"
#include "hw/arm/arm.h"
#include "exec/address-spaces.h"
#include "hw/arm/stm32f205_soc.h"
@@ -107,7 +108,6 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
/* Attach UART (uses USART registers) and USART controllers */
for (i = 0; i < STM_NUM_USARTS; i++) {
usartdev = DEVICE(&(s->usart[i]));
- qdev_prop_set_chr(usartdev, "chardev", i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL);
object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index f1b2c6c96..1eeb1ab39 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -38,7 +38,6 @@
#include "sysemu/sysemu.h"
#include "hw/ssi/ssi.h"
#include "qemu/cutils.h"
-#include "qemu/log.h"
//#define DEBUG
@@ -180,18 +179,19 @@ static const MemoryRegionOps strongarm_pic_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void strongarm_pic_initfn(Object *obj)
+static int strongarm_pic_initfn(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- StrongARMPICState *s = STRONGARM_PIC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ StrongARMPICState *s = STRONGARM_PIC(dev);
qdev_init_gpio_in(dev, strongarm_pic_set_irq, SA_PIC_SRCS);
- memory_region_init_io(&s->iomem, obj, &strongarm_pic_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_pic_ops, s,
"pic", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
sysbus_init_irq(sbd, &s->fiq);
+
+ return 0;
}
static int strongarm_pic_post_load(void *opaque, int version_id)
@@ -217,7 +217,9 @@ static VMStateDescription vmstate_strongarm_pic_regs = {
static void strongarm_pic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = strongarm_pic_initfn;
dc->desc = "StrongARM PIC";
dc->vmsd = &vmstate_strongarm_pic_regs;
}
@@ -226,7 +228,6 @@ static const TypeInfo strongarm_pic_info = {
.name = TYPE_STRONGARM_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMPICState),
- .instance_init = strongarm_pic_initfn,
.class_init = strongarm_pic_class_init,
};
@@ -380,10 +381,9 @@ static const MemoryRegionOps strongarm_rtc_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void strongarm_rtc_init(Object *obj)
+static int strongarm_rtc_init(SysBusDevice *dev)
{
- StrongARMRTCState *s = STRONGARM_RTC(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ StrongARMRTCState *s = STRONGARM_RTC(dev);
struct tm tm;
s->rttr = 0x0;
@@ -400,9 +400,11 @@ static void strongarm_rtc_init(Object *obj)
sysbus_init_irq(dev, &s->rtc_irq);
sysbus_init_irq(dev, &s->rtc_hz_irq);
- memory_region_init_io(&s->iomem, obj, &strongarm_rtc_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_rtc_ops, s,
"rtc", 0x10000);
sysbus_init_mmio(dev, &s->iomem);
+
+ return 0;
}
static void strongarm_rtc_pre_save(void *opaque)
@@ -441,7 +443,9 @@ static const VMStateDescription vmstate_strongarm_rtc_regs = {
static void strongarm_rtc_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = strongarm_rtc_init;
dc->desc = "StrongARM RTC Controller";
dc->vmsd = &vmstate_strongarm_rtc_regs;
}
@@ -450,7 +454,6 @@ static const TypeInfo strongarm_rtc_sysbus_info = {
.name = TYPE_STRONGARM_RTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMRTCState),
- .instance_init = strongarm_rtc_init,
.class_init = strongarm_rtc_sysbus_class_init,
};
@@ -643,17 +646,16 @@ static DeviceState *strongarm_gpio_init(hwaddr base,
return dev;
}
-static void strongarm_gpio_initfn(Object *obj)
+static int strongarm_gpio_initfn(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- StrongARMGPIOInfo *s = STRONGARM_GPIO(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ StrongARMGPIOInfo *s = STRONGARM_GPIO(dev);
int i;
qdev_init_gpio_in(dev, strongarm_gpio_set, 28);
qdev_init_gpio_out(dev, s->handler, 28);
- memory_region_init_io(&s->iomem, obj, &strongarm_gpio_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_gpio_ops, s,
"gpio", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
@@ -661,6 +663,8 @@ static void strongarm_gpio_initfn(Object *obj)
sysbus_init_irq(sbd, &s->irqs[i]);
}
sysbus_init_irq(sbd, &s->irqX);
+
+ return 0;
}
static const VMStateDescription vmstate_strongarm_gpio_regs = {
@@ -683,7 +687,9 @@ static const VMStateDescription vmstate_strongarm_gpio_regs = {
static void strongarm_gpio_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = strongarm_gpio_initfn;
dc->desc = "StrongARM GPIO controller";
dc->vmsd = &vmstate_strongarm_gpio_regs;
}
@@ -692,7 +698,6 @@ static const TypeInfo strongarm_gpio_info = {
.name = TYPE_STRONGARM_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMGPIOInfo),
- .instance_init = strongarm_gpio_initfn,
.class_init = strongarm_gpio_class_init,
};
@@ -819,19 +824,20 @@ static const MemoryRegionOps strongarm_ppc_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void strongarm_ppc_init(Object *obj)
+static int strongarm_ppc_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- StrongARMPPCInfo *s = STRONGARM_PPC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ StrongARMPPCInfo *s = STRONGARM_PPC(dev);
qdev_init_gpio_in(dev, strongarm_ppc_set, 22);
qdev_init_gpio_out(dev, s->handler, 22);
- memory_region_init_io(&s->iomem, obj, &strongarm_ppc_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_ppc_ops, s,
"ppc", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
+
+ return 0;
}
static const VMStateDescription vmstate_strongarm_ppc_regs = {
@@ -853,7 +859,9 @@ static const VMStateDescription vmstate_strongarm_ppc_regs = {
static void strongarm_ppc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = strongarm_ppc_init;
dc->desc = "StrongARM PPC controller";
dc->vmsd = &vmstate_strongarm_ppc_regs;
}
@@ -862,7 +870,6 @@ static const TypeInfo strongarm_ppc_info = {
.name = TYPE_STRONGARM_PPC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMPPCInfo),
- .instance_init = strongarm_ppc_init,
.class_init = strongarm_ppc_class_init,
};
@@ -1224,12 +1231,11 @@ static const MemoryRegionOps strongarm_uart_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void strongarm_uart_init(Object *obj)
+static int strongarm_uart_init(SysBusDevice *dev)
{
- StrongARMUARTState *s = STRONGARM_UART(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ StrongARMUARTState *s = STRONGARM_UART(dev);
- memory_region_init_io(&s->iomem, obj, &strongarm_uart_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_uart_ops, s,
"uart", 0x10000);
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
@@ -1244,6 +1250,8 @@ static void strongarm_uart_init(Object *obj)
strongarm_uart_event,
s);
}
+
+ return 0;
}
static void strongarm_uart_reset(DeviceState *dev)
@@ -1313,7 +1321,9 @@ static Property strongarm_uart_properties[] = {
static void strongarm_uart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = strongarm_uart_init;
dc->desc = "StrongARM UART controller";
dc->reset = strongarm_uart_reset;
dc->vmsd = &vmstate_strongarm_uart_regs;
@@ -1324,7 +1334,6 @@ static const TypeInfo strongarm_uart_info = {
.name = TYPE_STRONGARM_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMUARTState),
- .instance_init = strongarm_uart_init,
.class_init = strongarm_uart_class_init,
};
diff --git a/hw/arm/strongarm.h b/hw/arm/strongarm.h
index 1470eac4f..2893f9444 100644
--- a/hw/arm/strongarm.h
+++ b/hw/arm/strongarm.h
@@ -1,8 +1,7 @@
-#ifndef STRONGARM_H
-#define STRONGARM_H
+#ifndef _STRONGARM_H
+#define _STRONGARM_H
#include "exec/memory.h"
-#include "target-arm/cpu-qom.h"
#define SA_CS0 0x00000000
#define SA_CS1 0x08000000
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
index 2db66508b..4e9494f94 100644
--- a/hw/arm/tosa.c
+++ b/hw/arm/tosa.c
@@ -127,9 +127,10 @@ static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
return 0;
}
-static void tosa_ssp_realize(SSISlave *dev, Error **errp)
+static int tosa_ssp_init(SSISlave *dev)
{
/* Nothing to do. */
+ return 0;
}
#define TYPE_TOSA_DAC "tosa_dac"
@@ -282,7 +283,7 @@ static void tosa_ssp_class_init(ObjectClass *klass, void *data)
{
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
- k->realize = tosa_ssp_realize;
+ k->init = tosa_ssp_init;
k->transfer = tosa_ssp_tansfer;
}
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
deleted file mode 100644
index d5f33a2a0..000000000
--- a/hw/arm/trace-events
+++ /dev/null
@@ -1,4 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/arm/virt-acpi-build.c
-virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out."
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 8ae5392bc..e5a80c2d2 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -23,7 +23,6 @@
#include "exec/address-spaces.h"
#include "hw/block/flash.h"
#include "qemu/error-report.h"
-#include "hw/char/pl011.h"
#define VERSATILE_FLASH_ADDR 0x34000000
#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
@@ -154,11 +153,10 @@ static const MemoryRegionOps vpb_sic_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void vpb_sic_init(Object *obj)
+static int vpb_sic_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- vpb_sic_state *s = VERSATILE_PB_SIC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ vpb_sic_state *s = VERSATILE_PB_SIC(dev);
int i;
qdev_init_gpio_in(dev, vpb_sic_set_irq, 32);
@@ -166,9 +164,10 @@ static void vpb_sic_init(Object *obj)
sysbus_init_irq(sbd, &s->parent[i]);
}
s->irq = 31;
- memory_region_init_io(&s->iomem, obj, &vpb_sic_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &vpb_sic_ops, s,
"vpb-sic", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
+ return 0;
}
/* Board init. */
@@ -276,7 +275,7 @@ static void versatile_init(MachineState *machine, int board_id)
pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL);
}
}
- if (machine_usb(machine)) {
+ if (usb_enabled()) {
pci_create_simple(pci_bus, -1, "pci-ohci");
}
n = drive_get_max_bus(IF_SCSI);
@@ -285,10 +284,10 @@ static void versatile_init(MachineState *machine, int board_id)
n--;
}
- pl011_create(0x101f1000, pic[12], serial_hds[0]);
- pl011_create(0x101f2000, pic[13], serial_hds[1]);
- pl011_create(0x101f3000, pic[14], serial_hds[2]);
- pl011_create(0x10009000, sic[6], serial_hds[3]);
+ sysbus_create_simple("pl011", 0x101f1000, pic[12]);
+ sysbus_create_simple("pl011", 0x101f2000, pic[13]);
+ sysbus_create_simple("pl011", 0x101f3000, pic[14]);
+ sysbus_create_simple("pl011", 0x10009000, sic[6]);
sysbus_create_simple("pl080", 0x10130000, pic[17]);
sysbus_create_simple("sp804", 0x101e2000, pic[4]);
@@ -428,7 +427,9 @@ type_init(versatile_machine_init)
static void vpb_sic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = vpb_sic_init;
dc->vmsd = &vmstate_vpb_sic;
}
@@ -436,7 +437,6 @@ static const TypeInfo vpb_sic_info = {
.name = TYPE_VERSATILE_PB_SIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(vpb_sic_state),
- .instance_init = vpb_sic_init,
.class_init = vpb_sic_class_init,
};
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 58760f40c..70b3e701e 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -39,7 +39,6 @@
#include "sysemu/device_tree.h"
#include "qemu/error-report.h"
#include <libfdt.h>
-#include "hw/char/pl011.h"
#define VEXPRESS_BOARD_ID 0x8e0
#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
@@ -632,10 +631,10 @@ static void vexpress_common_init(MachineState *machine)
sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]);
sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]);
- pl011_create(map[VE_UART0], pic[5], serial_hds[0]);
- pl011_create(map[VE_UART1], pic[6], serial_hds[1]);
- pl011_create(map[VE_UART2], pic[7], serial_hds[2]);
- pl011_create(map[VE_UART3], pic[8], serial_hds[3]);
+ sysbus_create_simple("pl011", map[VE_UART0], pic[5]);
+ sysbus_create_simple("pl011", map[VE_UART1], pic[6]);
+ sysbus_create_simple("pl011", map[VE_UART2], pic[7]);
+ sysbus_create_simple("pl011", map[VE_UART3], pic[8]);
sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 28fc59c66..f51fe396c 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -43,7 +43,6 @@
#include "hw/acpi/aml-build.h"
#include "hw/pci/pcie_host.h"
#include "hw/pci/pci.h"
-#include "sysemu/numa.h"
#define ARM_SPI_BASE 32
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
@@ -231,8 +230,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
aml_append(rbuf,
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000,
- base_mmio_high,
- base_mmio_high + size_mmio_high - 1, 0x0000,
+ base_mmio_high, base_mmio_high, 0x0000,
size_mmio_high));
}
@@ -354,14 +352,11 @@ static void acpi_dsdt_add_power_button(Aml *scope)
/* RSDP */
static GArray *
-build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
+build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
{
AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
- unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
- unsigned rsdt_pa_offset =
- (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
- bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
+ bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 16,
true /* fseg memory */);
memcpy(&rsdp->signature, "RSD PTR ", sizeof(rsdp->signature));
@@ -369,21 +364,24 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
rsdp->length = cpu_to_le32(sizeof(*rsdp));
rsdp->revision = 0x02;
+ /* Point to RSDT */
+ rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
/* Address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
- ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
-
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
+ ACPI_BUILD_TABLE_FILE,
+ rsdp_table, &rsdp->rsdt_physical_address,
+ sizeof rsdp->rsdt_physical_address);
+ rsdp->checksum = 0;
/* Checksum to be filled by Guest linker */
bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
- (char *)rsdp - rsdp_table->data, sizeof *rsdp,
- (char *)&rsdp->checksum - rsdp_table->data);
+ rsdp_table, rsdp, sizeof *rsdp,
+ &rsdp->checksum);
return rsdp_table;
}
static void
-build_spcr(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
+build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
{
AcpiSerialPortConsoleRedirection *spcr;
const MemMapEntry *uart_memmap = &guest_info->memmap[VIRT_UART];
@@ -416,52 +414,7 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
}
static void
-build_srat(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
-{
- AcpiSystemResourceAffinityTable *srat;
- AcpiSratProcessorGiccAffinity *core;
- AcpiSratMemoryAffinity *numamem;
- int i, j, srat_start;
- uint64_t mem_base;
- uint32_t *cpu_node = g_malloc0(guest_info->smp_cpus * sizeof(uint32_t));
-
- for (i = 0; i < guest_info->smp_cpus; i++) {
- for (j = 0; j < nb_numa_nodes; j++) {
- if (test_bit(i, numa_info[j].node_cpu)) {
- cpu_node[i] = j;
- break;
- }
- }
- }
-
- srat_start = table_data->len;
- srat = acpi_data_push(table_data, sizeof(*srat));
- srat->reserved1 = cpu_to_le32(1);
-
- for (i = 0; i < guest_info->smp_cpus; ++i) {
- core = acpi_data_push(table_data, sizeof(*core));
- core->type = ACPI_SRAT_PROCESSOR_GICC;
- core->length = sizeof(*core);
- core->proximity = cpu_to_le32(cpu_node[i]);
- core->acpi_processor_uid = cpu_to_le32(i);
- core->flags = cpu_to_le32(1);
- }
- g_free(cpu_node);
-
- mem_base = guest_info->memmap[VIRT_MEM].base;
- for (i = 0; i < nb_numa_nodes; ++i) {
- numamem = acpi_data_push(table_data, sizeof(*numamem));
- build_srat_memory(numamem, mem_base, numa_info[i].node_mem, i,
- MEM_AFFINITY_ENABLED);
- mem_base += numa_info[i].node_mem;
- }
-
- build_header(linker, table_data, (void *)srat, "SRAT",
- table_data->len - srat_start, 3, NULL, NULL);
-}
-
-static void
-build_mcfg(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
+build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
{
AcpiTableMcfg *mcfg;
const MemMapEntry *memmap = guest_info->memmap;
@@ -481,7 +434,7 @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
/* GTDT */
static void
-build_gtdt(GArray *table_data, BIOSLinker *linker)
+build_gtdt(GArray *table_data, GArray *linker)
{
int gtdt_start = table_data->len;
AcpiGenericTimerTable *gtdt;
@@ -507,7 +460,7 @@ build_gtdt(GArray *table_data, BIOSLinker *linker)
/* MADT */
static void
-build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
+build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
{
int madt_start = table_data->len;
const MemMapEntry *memmap = guest_info->memmap;
@@ -523,7 +476,6 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR;
gicd->length = sizeof(*gicd);
gicd->base_address = memmap[VIRT_GIC_DIST].base;
- gicd->version = guest_info->gic_version;
for (i = 0; i < guest_info->smp_cpus; i++) {
AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data,
@@ -539,10 +491,6 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
gicc->arm_mpidr = armcpu->mp_affinity;
gicc->uid = i;
gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED);
-
- if (armcpu->has_pmu) {
- gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
- }
}
if (guest_info->gic_version == 3) {
@@ -571,10 +519,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
/* FADT */
static void
-build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset)
+build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
{
AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
- unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data;
/* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */
fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI);
@@ -584,10 +531,12 @@ build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset)
/* ACPI v5.1 (fadt->revision.fadt->minor_revision) */
fadt->minor_revision = 0x1;
+ fadt->dsdt = cpu_to_le32(dsdt);
/* DSDT address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt),
- ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset);
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+ ACPI_BUILD_TABLE_FILE,
+ table_data, &fadt->dsdt,
+ sizeof fadt->dsdt);
build_header(linker, table_data,
(void *)fadt, "FACP", sizeof(*fadt), 5, NULL, NULL);
@@ -595,7 +544,7 @@ build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset)
/* DSDT */
static void
-build_dsdt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
+build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
{
Aml *scope, *dsdt;
const MemMapEntry *memmap = guest_info->memmap;
@@ -655,8 +604,7 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
table_offsets = g_array_new(false, true /* clear */,
sizeof(uint32_t));
- bios_linker_loader_alloc(tables->linker,
- ACPI_BUILD_TABLE_FILE, tables_blob,
+ bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE,
64, false /* high memory */);
/*
@@ -690,11 +638,6 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables_blob);
build_spcr(tables_blob, tables->linker, guest_info);
- if (nb_numa_nodes > 0) {
- acpi_add_table(table_offsets, tables_blob);
- build_srat(tables_blob, tables->linker, guest_info);
- }
-
/* RSDT is pointed to by RSDP */
rsdt = tables_blob->len;
build_rsdt(tables_blob, tables->linker, table_offsets, NULL, NULL);
@@ -735,7 +678,7 @@ static void virt_acpi_build_update(void *build_opaque)
acpi_ram_update(build_state->table_mr, tables.table_data);
acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
- acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob);
+ acpi_ram_update(build_state->linker_mr, tables.linker);
acpi_build_tables_cleanup(&tables, true);
@@ -793,8 +736,7 @@ void virt_acpi_setup(VirtGuestInfo *guest_info)
assert(build_state->table_mr != NULL);
build_state->linker_mr =
- acpi_add_rom_blob(build_state, tables.linker->cmd_blob,
- "etc/table-loader", 0);
+ acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index a193b5a95..a535285e4 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -38,11 +38,9 @@
#include "net/net.h"
#include "sysemu/block-backend.h"
#include "sysemu/device_tree.h"
-#include "sysemu/numa.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "hw/boards.h"
-#include "hw/compat.h"
#include "hw/loader.h"
#include "exec/address-spaces.h"
#include "qemu/bitops.h"
@@ -52,8 +50,7 @@
#include "hw/arm/sysbus-fdt.h"
#include "hw/platform-bus.h"
#include "hw/arm/fdt.h"
-#include "hw/intc/arm_gic.h"
-#include "hw/intc/arm_gicv3_common.h"
+#include "hw/intc/arm_gic_common.h"
#include "kvm_arm.h"
#include "hw/smbios/smbios.h"
#include "qapi/visitor.h"
@@ -83,7 +80,6 @@ typedef struct VirtBoardInfo {
typedef struct {
MachineClass parent;
VirtBoardInfo *daughterboard;
- bool disallow_affinity_adjustment;
} VirtMachineClass;
typedef struct {
@@ -101,36 +97,6 @@ typedef struct {
#define VIRT_MACHINE_CLASS(klass) \
OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE)
-
-#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
- static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
- void *data) \
- { \
- MachineClass *mc = MACHINE_CLASS(oc); \
- virt_machine_##major##_##minor##_options(mc); \
- mc->desc = "QEMU " # major "." # minor " ARM Virtual Machine"; \
- if (latest) { \
- mc->alias = "virt"; \
- } \
- } \
- static const TypeInfo machvirt_##major##_##minor##_info = { \
- .name = MACHINE_TYPE_NAME("virt-" # major "." # minor), \
- .parent = TYPE_VIRT_MACHINE, \
- .instance_init = virt_##major##_##minor##_instance_init, \
- .class_init = virt_##major##_##minor##_class_init, \
- }; \
- static void machvirt_machine_##major##_##minor##_init(void) \
- { \
- type_register_static(&machvirt_##major##_##minor##_info); \
- } \
- type_init(machvirt_machine_##major##_##minor##_init);
-
-#define DEFINE_VIRT_MACHINE_AS_LATEST(major, minor) \
- DEFINE_VIRT_MACHINE_LATEST(major, minor, true)
-#define DEFINE_VIRT_MACHINE(major, minor) \
- DEFINE_VIRT_MACHINE_LATEST(major, minor, false)
-
-
/* RAM limit in GB. Since VIRT_MEM starts at the 1GB mark, this means
* RAM can go up to the 256GB mark, leaving 256GB of the physical
* address space unallocated and free for future use between 256G and 512G.
@@ -363,7 +329,6 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
{
int cpu;
int addr_cells = 1;
- unsigned int i;
/*
* From Documentation/devicetree/bindings/arm/cpus.txt
@@ -413,12 +378,6 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
armcpu->mp_affinity);
}
- for (i = 0; i < nb_numa_nodes; i++) {
- if (test_bit(cpu, numa_info[i].node_cpu)) {
- qemu_fdt_setprop_cell(vbi->fdt, nodename, "numa-node-id", i);
- }
- }
-
g_free(nodename);
}
}
@@ -469,37 +428,6 @@ static void fdt_add_gic_node(VirtBoardInfo *vbi, int type)
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle);
}
-static void fdt_add_pmu_nodes(const VirtBoardInfo *vbi, int gictype)
-{
- CPUState *cpu;
- ARMCPU *armcpu;
- uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
-
- CPU_FOREACH(cpu) {
- armcpu = ARM_CPU(cpu);
- if (!armcpu->has_pmu ||
- !kvm_arm_pmu_create(cpu, PPI(VIRTUAL_PMU_IRQ))) {
- return;
- }
- }
-
- if (gictype == 2) {
- irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
- GIC_FDT_IRQ_PPI_CPU_WIDTH,
- (1 << vbi->smp_cpus) - 1);
- }
-
- armcpu = ARM_CPU(qemu_get_cpu(0));
- qemu_fdt_add_subnode(vbi->fdt, "/pmu");
- if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
- const char compat[] = "arm,armv8-pmuv3";
- qemu_fdt_setprop(vbi->fdt, "/pmu", "compatible",
- compat, sizeof(compat));
- qemu_fdt_setprop_cells(vbi->fdt, "/pmu", "interrupts",
- GIC_FDT_IRQ_TYPE_PPI, VIRTUAL_PMU_IRQ, irqflags);
- }
-}
-
static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
{
int i;
@@ -589,7 +517,7 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, bool secure)
}
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart,
- MemoryRegion *mem, CharDriverState *chr)
+ MemoryRegion *mem)
{
char *nodename;
hwaddr base = vbi->memmap[uart].base;
@@ -600,7 +528,6 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart,
DeviceState *dev = qdev_create(NULL, "pl011");
SysBusDevice *s = SYS_BUS_DEVICE(dev);
- qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
memory_region_add_subregion(mem, base,
sysbus_mmio_get_region(s, 0));
@@ -1023,7 +950,6 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
qemu_fdt_setprop_cell(vbi->fdt, nodename, "#size-cells", 2);
qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0,
nr_pcie_buses - 1);
- qemu_fdt_setprop(vbi->fdt, nodename, "dma-coherent", NULL, 0);
if (vbi->v2m_phandle) {
qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent",
@@ -1167,7 +1093,6 @@ void virt_guest_info_machine_done(Notifier *notifier, void *data)
static void machvirt_init(MachineState *machine)
{
VirtMachineState *vms = VIRT_MACHINE(machine);
- VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine);
qemu_irq pic[NUM_IRQS];
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *secure_sysmem = NULL;
@@ -1179,12 +1104,7 @@ static void machvirt_init(MachineState *machine)
VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
VirtGuestInfo *guest_info = &guest_info_state->info;
char **cpustr;
- ObjectClass *oc;
- const char *typename;
- CPUClass *cc;
- Error *err = NULL;
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
- uint8_t clustersz;
if (!cpu_model) {
cpu_model = "cortex-a15";
@@ -1230,10 +1150,8 @@ static void machvirt_init(MachineState *machine)
*/
if (gic_version == 3) {
virt_max_cpus = vbi->memmap[VIRT_GIC_REDIST].size / 0x20000;
- clustersz = GICV3_TARGETLIST_BITS;
} else {
virt_max_cpus = GIC_NCPU;
- clustersz = GIC_TARGETLIST_BITS;
}
if (max_cpus > virt_max_cpus) {
@@ -1269,37 +1187,25 @@ static void machvirt_init(MachineState *machine)
create_fdt(vbi);
- oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
- if (!oc) {
- error_report("Unable to find CPU definition");
- exit(1);
- }
- typename = object_class_get_name(oc);
-
- /* convert -smp CPU options specified by the user into global props */
- cc = CPU_CLASS(oc);
- cc->parse_features(typename, cpustr[1], &err);
- g_strfreev(cpustr);
- if (err) {
- error_report_err(err);
- exit(1);
- }
-
for (n = 0; n < smp_cpus; n++) {
- Object *cpuobj = object_new(typename);
- if (!vmc->disallow_affinity_adjustment) {
- /* Adjust MPIDR like 64-bit KVM hosts, which incorporate the
- * GIC's target-list limitations. 32-bit KVM hosts currently
- * always create clusters of 4 CPUs, but that is expected to
- * change when they gain support for gicv3. When KVM is enabled
- * it will override the changes we make here, therefore our
- * purposes are to make TCG consistent (with 64-bit KVM hosts)
- * and to improve SGI efficiency.
- */
- uint8_t aff1 = n / clustersz;
- uint8_t aff0 = n % clustersz;
- object_property_set_int(cpuobj, (aff1 << ARM_AFF1_SHIFT) | aff0,
- "mp-affinity", NULL);
+ ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
+ CPUClass *cc = CPU_CLASS(oc);
+ Object *cpuobj;
+ Error *err = NULL;
+ char *cpuopts = g_strdup(cpustr[1]);
+
+ if (!oc) {
+ error_report("Unable to find CPU definition");
+ exit(1);
+ }
+ cpuobj = object_new(object_class_get_name(oc));
+
+ /* Handle any CPU options specified by the user */
+ cc->parse_features(CPU(cpuobj), cpuopts, &err);
+ g_free(cpuopts);
+ if (err) {
+ error_report_err(err);
+ exit(1);
}
if (!vms->secure) {
@@ -1331,6 +1237,7 @@ static void machvirt_init(MachineState *machine)
object_property_set_bool(cpuobj, true, "realized", NULL);
}
+ g_strfreev(cpustr);
fdt_add_timer_nodes(vbi, gic_version);
fdt_add_cpu_nodes(vbi);
fdt_add_psci_node(vbi);
@@ -1343,13 +1250,11 @@ static void machvirt_init(MachineState *machine)
create_gic(vbi, pic, gic_version, vms->secure);
- fdt_add_pmu_nodes(vbi, gic_version);
-
- create_uart(vbi, pic, VIRT_UART, sysmem, serial_hds[0]);
+ create_uart(vbi, pic, VIRT_UART, sysmem);
if (vms->secure) {
create_secure_ram(vbi, secure_sysmem);
- create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]);
+ create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem);
}
create_rtc(vbi, pic);
@@ -1473,13 +1378,7 @@ static const TypeInfo virt_machine_info = {
.class_init = virt_machine_class_init,
};
-static void machvirt_machine_init(void)
-{
- type_register_static(&virt_machine_info);
-}
-type_init(machvirt_machine_init);
-
-static void virt_2_7_instance_init(Object *obj)
+static void virt_2_6_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -1512,25 +1411,29 @@ static void virt_2_7_instance_init(Object *obj)
"Valid values are 2, 3 and host", NULL);
}
-static void virt_machine_2_7_options(MachineClass *mc)
+static void virt_2_6_class_init(ObjectClass *oc, void *data)
{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ static GlobalProperty compat_props[] = {
+ { /* end of list */ }
+ };
+
+ mc->desc = "QEMU 2.6 ARM Virtual Machine";
+ mc->alias = "virt";
+ mc->compat_props = compat_props;
}
-DEFINE_VIRT_MACHINE_AS_LATEST(2, 7)
-#define VIRT_COMPAT_2_6 \
- HW_COMPAT_2_6
+static const TypeInfo machvirt_info = {
+ .name = MACHINE_TYPE_NAME("virt-2.6"),
+ .parent = TYPE_VIRT_MACHINE,
+ .instance_init = virt_2_6_instance_init,
+ .class_init = virt_2_6_class_init,
+};
-static void virt_2_6_instance_init(Object *obj)
+static void machvirt_machine_init(void)
{
- virt_2_7_instance_init(obj);
+ type_register_static(&virt_machine_info);
+ type_register_static(&machvirt_info);
}
-static void virt_machine_2_6_options(MachineClass *mc)
-{
- VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
-
- virt_machine_2_7_options(mc);
- SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_6);
- vmc->disallow_affinity_adjustment = true;
-}
-DEFINE_VIRT_MACHINE(2, 6)
+type_init(machvirt_machine_init);
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 7dac20d67..98b17c9ae 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -32,7 +32,6 @@
#include "hw/ssi/ssi.h"
#include "qemu/error-report.h"
#include "hw/sd/sd.h"
-#include "hw/char/cadence_uart.h"
#define NUM_SPI_FLASHES 4
#define NUM_QSPI_FLASHES 2
@@ -138,13 +137,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
for (j = 0; j < num_ss; ++j) {
- DriveInfo *dinfo = drive_get_next(IF_MTD);
- flash_dev = ssi_create_slave_no_init(spi, "n25q128");
- if (dinfo) {
- qdev_prop_set_drive(flash_dev, "drive",
- blk_by_legacy_dinfo(dinfo), &error_fatal);
- }
- qdev_init_nofail(flash_dev);
+ flash_dev = ssi_create_slave(spi, "n25q128");
cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
@@ -242,8 +235,8 @@ static void zynq_init(MachineState *machine)
sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
- cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hds[0]);
- cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hds[1]);
+ sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
+ sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
sysbus_create_varargs("cadence_ttc", 0xF8001000,
pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
@@ -300,12 +293,6 @@ static void zynq_init(MachineState *machine)
sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]);
}
- dev = qdev_create(NULL, "xlnx.ps7-dev-cfg");
- qdev_init_nofail(dev);
- busdev = SYS_BUS_DEVICE(dev);
- sysbus_connect_irq(busdev, 0, pic[40 - IRQ_OFFSET]);
- sysbus_mmio_map(busdev, 0, 0xF8007000);
-
zynq_binfo.ram_size = ram_size;
zynq_binfo.kernel_filename = kernel_filename;
zynq_binfo.kernel_cmdline = kernel_cmdline;
diff --git a/hw/arm/xlnx-ep108.c b/hw/arm/xlnx-ep108.c
index 4ec590a25..5f480182b 100644
--- a/hw/arm/xlnx-ep108.c
+++ b/hw/arm/xlnx-ep108.c
@@ -23,7 +23,6 @@
#include "hw/boards.h"
#include "qemu/error-report.h"
#include "exec/address-spaces.h"
-#include "qemu/log.h"
typedef struct XlnxEP108 {
XlnxZynqMPState soc;
@@ -88,19 +87,12 @@ static void xlnx_ep108_init(MachineState *machine)
SSIBus *spi_bus;
DeviceState *flash_dev;
qemu_irq cs_line;
- DriveInfo *dinfo = drive_get_next(IF_MTD);
gchar *bus_name = g_strdup_printf("spi%d", i);
spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(&s->soc), bus_name);
g_free(bus_name);
- flash_dev = ssi_create_slave_no_init(spi_bus, "sst25wf080");
- if (dinfo) {
- qdev_prop_set_drive(flash_dev, "drive", blk_by_legacy_dinfo(dinfo),
- &error_fatal);
- }
- qdev_init_nofail(flash_dev);
-
+ flash_dev = ssi_create_slave(spi_bus, "sst25wf080");
cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.spi[i]), 1, cs_line);
@@ -121,11 +113,3 @@ static void xlnx_ep108_machine_init(MachineClass *mc)
}
DEFINE_MACHINE("xlnx-ep108", xlnx_ep108_machine_init)
-
-static void xlnx_zcu102_machine_init(MachineClass *mc)
-{
- mc->desc = "Xilinx ZynqMP ZCU102 board";
- mc->init = xlnx_ep108_init;
-}
-
-DEFINE_MACHINE("xlnx-zcu102", xlnx_zcu102_machine_init)
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 23c719986..4d504da64 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -22,8 +22,6 @@
#include "hw/arm/xlnx-zynqmp.h"
#include "hw/intc/arm_gic_common.h"
#include "exec/address-spaces.h"
-#include "sysemu/kvm.h"
-#include "kvm_arm.h"
#define GIC_NUM_SPI_INTR 160
@@ -38,12 +36,6 @@
#define SATA_ADDR 0xFD0C0000
#define SATA_NUM_PORTS 2
-#define DP_ADDR 0xfd4a0000
-#define DP_IRQ 113
-
-#define DPDMA_ADDR 0xfd4c0000
-#define DPDMA_IRQ 116
-
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
0xFF0B0000, 0xFF0C0000, 0xFF0D0000, 0xFF0E0000,
};
@@ -91,41 +83,6 @@ static inline int arm_gic_ppi_index(int cpu_nr, int ppi_index)
return GIC_NUM_SPI_INTR + cpu_nr * GIC_INTERNAL + ppi_index;
}
-static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
- Error **errp)
-{
- Error *err = NULL;
- int i;
-
- for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
- char *name;
-
- object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
- "cortex-r5-" TYPE_ARM_CPU);
- object_property_add_child(OBJECT(s), "rpu-cpu[*]",
- OBJECT(&s->rpu_cpu[i]), &error_abort);
-
- name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
- if (strcmp(name, boot_cpu)) {
- /* Secondary CPUs start in PSCI powered-down state */
- object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
- "start-powered-off", &error_abort);
- } else {
- s->boot_cpu_ptr = &s->rpu_cpu[i];
- }
- g_free(name);
-
- object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
- &error_abort);
- object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
- &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- }
-}
-
static void xlnx_zynqmp_init(Object *obj)
{
XlnxZynqMPState *s = XLNX_ZYNQMP(obj);
@@ -138,12 +95,19 @@ static void xlnx_zynqmp_init(Object *obj)
&error_abort);
}
+ for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+ object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
+ "cortex-r5-" TYPE_ARM_CPU);
+ object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]),
+ &error_abort);
+ }
+
object_property_add_link(obj, "ddr-ram", TYPE_MEMORY_REGION,
(Object **)&s->ddr_ram,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
- object_initialize(&s->gic, sizeof(s->gic), gic_class_name());
+ object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
for (i = 0; i < XLNX_ZYNQMP_NUM_GEMS; i++) {
@@ -171,12 +135,6 @@ static void xlnx_zynqmp_init(Object *obj)
TYPE_XILINX_SPIPS);
qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
}
-
- object_initialize(&s->dp, sizeof(s->dp), TYPE_XLNX_DP);
- qdev_set_parent_bus(DEVICE(&s->dp), sysbus_get_default());
-
- object_initialize(&s->dpdma, sizeof(s->dpdma), TYPE_XLNX_DPDMA);
- qdev_set_parent_bus(DEVICE(&s->dpdma), sysbus_get_default());
}
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -238,42 +196,11 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32);
qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS);
-
- /* Realize APUs before realizing the GIC. KVM requires this. */
- for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
- char *name;
-
- object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC,
- "psci-conduit", &error_abort);
-
- name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i]));
- if (strcmp(name, boot_cpu)) {
- /* Secondary CPUs start in PSCI powered-down state */
- object_property_set_bool(OBJECT(&s->apu_cpu[i]), true,
- "start-powered-off", &error_abort);
- } else {
- s->boot_cpu_ptr = &s->apu_cpu[i];
- }
- g_free(name);
-
- object_property_set_bool(OBJECT(&s->apu_cpu[i]),
- s->secure, "has_el3", NULL);
- object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
- "reset-cbar", &error_abort);
- object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
- &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- }
-
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
-
assert(ARRAY_SIZE(xlnx_zynqmp_gic_regions) == XLNX_ZYNQMP_GIC_REGIONS);
for (i = 0; i < XLNX_ZYNQMP_GIC_REGIONS; i++) {
SysBusDevice *gic = SYS_BUS_DEVICE(&s->gic);
@@ -296,6 +223,29 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
qemu_irq irq;
+ char *name;
+
+ object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC,
+ "psci-conduit", &error_abort);
+
+ name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i]));
+ if (strcmp(name, boot_cpu)) {
+ /* Secondary CPUs start in PSCI powered-down state */
+ object_property_set_bool(OBJECT(&s->apu_cpu[i]), true,
+ "start-powered-off", &error_abort);
+ } else {
+ s->boot_cpu_ptr = &s->apu_cpu[i];
+ }
+ g_free(name);
+
+ object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
+ "reset-cbar", &error_abort);
+ object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
+ &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
@@ -308,8 +258,23 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
}
- if (s->has_rpu) {
- xlnx_zynqmp_create_rpu(s, boot_cpu, &err);
+ for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+ char *name;
+
+ name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
+ if (strcmp(name, boot_cpu)) {
+ /* Secondary CPUs start in PSCI powered-down state */
+ object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
+ "start-powered-off", &error_abort);
+ } else {
+ s->boot_cpu_ptr = &s->rpu_cpu[i];
+ }
+ g_free(name);
+
+ object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
+ &error_abort);
+ object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
+ &err);
if (err) {
error_propagate(errp, err);
return;
@@ -343,7 +308,6 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
}
for (i = 0; i < XLNX_ZYNQMP_NUM_UARTS; i++) {
- qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hds[i]);
object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
@@ -400,32 +364,12 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
object_property_add_alias(OBJECT(s), bus_name,
OBJECT(&s->spi[i]), "spi0",
&error_abort);
- g_free(bus_name);
- }
-
- object_property_set_bool(OBJECT(&s->dp), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->dp), 0, DP_ADDR);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->dp), 0, gic_spi[DP_IRQ]);
-
- object_property_set_bool(OBJECT(&s->dpdma), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
+ g_free(bus_name);
}
- object_property_set_link(OBJECT(&s->dp), OBJECT(&s->dpdma), "dpdma",
- &error_abort);
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->dpdma), 0, DPDMA_ADDR);
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->dpdma), 0, gic_spi[DPDMA_IRQ]);
}
static Property xlnx_zynqmp_props[] = {
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
- DEFINE_PROP_BOOL("secure", XlnxZynqMPState, secure, false),
- DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 68a92f318..aea895a50 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -151,12 +151,14 @@ static void z2_lcd_cs(void *opaque, int line, int level)
z2_lcd->selected = !level;
}
-static void zipit_lcd_realize(SSISlave *dev, Error **errp)
+static int zipit_lcd_init(SSISlave *dev)
{
ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
z->selected = 0;
z->enabled = 0;
z->pos = 0;
+
+ return 0;
}
static VMStateDescription vmstate_zipit_lcd_state = {
@@ -179,7 +181,7 @@ static void zipit_lcd_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
- k->realize = zipit_lcd_realize;
+ k->init = zipit_lcd_init;
k->transfer = zipit_lcd_transfer;
dc->vmsd = &vmstate_zipit_lcd_state;
}
diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c
index 30690f96a..caf97c169 100644
--- a/hw/audio/cs4231.c
+++ b/hw/audio/cs4231.c
@@ -145,15 +145,16 @@ static const VMStateDescription vmstate_cs4231 = {
}
};
-static void cs4231_init(Object *obj)
+static int cs4231_init1(SysBusDevice *dev)
{
- CSState *s = CS4231(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ CSState *s = CS4231(dev);
- memory_region_init_io(&s->iomem, obj, &cs_mem_ops, s, "cs4321",
+ memory_region_init_io(&s->iomem, OBJECT(s), &cs_mem_ops, s, "cs4321",
CS_SIZE);
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
+
+ return 0;
}
static Property cs4231_properties[] = {
@@ -163,7 +164,9 @@ static Property cs4231_properties[] = {
static void cs4231_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = cs4231_init1;
dc->reset = cs_reset;
dc->vmsd = &vmstate_cs4231;
dc->props = cs4231_properties;
@@ -173,7 +176,6 @@ static const TypeInfo cs4231_info = {
.name = TYPE_CS4231,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CSState),
- .instance_init = cs4231_init,
.class_init = cs4231_class_init,
};
diff --git a/hw/audio/fmopl.h b/hw/audio/fmopl.h
index fdda7f9f5..24ba5f480 100644
--- a/hw/audio/fmopl.h
+++ b/hw/audio/fmopl.h
@@ -1,5 +1,5 @@
-#ifndef FMOPL_H
-#define FMOPL_H
+#ifndef __FMOPL_H_
+#define __FMOPL_H_
/* --- select emulation chips --- */
#define BUILD_YM3812 (HAS_YM3812)
diff --git a/hw/audio/gus.c b/hw/audio/gus.c
index 6c0264677..9dd6947be 100644
--- a/hw/audio/gus.c
+++ b/hw/audio/gus.c
@@ -144,7 +144,7 @@ static void GUS_callback (void *opaque, int free)
s->left = samples;
reset:
- gus_irqgen (&s->emu, (uint64_t)net * 1000000 / s->freq);
+ gus_irqgen (&s->emu, muldiv64 (net, 1000000, s->freq));
}
int GUS_irqrequest (GUSEmuState *emu, int hwirq, int n)
diff --git a/hw/audio/gusemu.h b/hw/audio/gusemu.h
index 9aec7bf8e..b7f075126 100644
--- a/hw/audio/gusemu.h
+++ b/hw/audio/gusemu.h
@@ -101,4 +101,4 @@ void gus_irqgen(GUSEmuState *state, unsigned int elapsed_time);
/* lower values won´t provide any benefit at all, higher values can cause audible timing delays */
/* note: masked timers are also calculated by this function, thus it might be needed even without any IRQs in use! */
-#endif /* GUSEMU_H */
+#endif /* gusemu.h */
diff --git a/hw/audio/gustate.h b/hw/audio/gustate.h
index d16297110..ece903abb 100644
--- a/hw/audio/gustate.h
+++ b/hw/audio/gustate.h
@@ -129,4 +129,4 @@
#define gusdataend (VSRegsEnd+4)
-#endif /* GUSTATE_H */
+#endif /* gustate.h */
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index cd95340cd..d372d4ab9 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -26,7 +26,6 @@
#include "intel-hda.h"
#include "intel-hda-defs.h"
#include "sysemu/dma.h"
-#include "qapi/error.h"
/* --------------------------------------------------------------------- */
/* hda bus */
@@ -51,28 +50,25 @@ void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, size_t bus_size,
bus->xfer = xfer;
}
-static void hda_codec_dev_realize(DeviceState *qdev, Error **errp)
+static int hda_codec_dev_init(DeviceState *qdev)
{
- HDACodecBus *bus = HDA_BUS(qdev->parent_bus);
- HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev);
+ HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, qdev->parent_bus);
+ HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
if (dev->cad == -1) {
dev->cad = bus->next_cad;
}
if (dev->cad >= 15) {
- error_setg(errp, "HDA audio codec address is full");
- return;
+ return -1;
}
bus->next_cad = dev->cad + 1;
- if (cdc->init(dev) != 0) {
- error_setg(errp, "HDA audio init failed");
- }
+ return cdc->init(dev);
}
static int hda_codec_dev_exit(DeviceState *qdev)
{
- HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev);
+ HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
if (cdc->exit) {
@@ -88,7 +84,7 @@ HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
DeviceState *qdev = kid->child;
- cdev = HDA_CODEC_DEVICE(qdev);
+ cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
if (cdev->cad == cad) {
return cdev;
}
@@ -98,14 +94,14 @@ HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
void hda_codec_response(HDACodecDevice *dev, bool solicited, uint32_t response)
{
- HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus);
+ HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
bus->response(dev, solicited, response);
}
bool hda_codec_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
uint8_t *buf, uint32_t len)
{
- HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus);
+ HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
return bus->xfer(dev, stnr, output, buf, len);
}
@@ -191,7 +187,7 @@ struct IntelHDAState {
/* properties */
uint32_t debug;
- OnOffAuto msi;
+ uint32_t msi;
bool old_msi_addr;
};
@@ -219,7 +215,10 @@ static void intel_hda_reset(DeviceState *dev);
static hwaddr intel_hda_addr(uint32_t lbase, uint32_t ubase)
{
- return ((uint64_t)ubase << 32) | lbase;
+ hwaddr addr;
+
+ addr = ((uint64_t)ubase << 32) | lbase;
+ return addr;
}
static void intel_hda_update_int_sts(IntelHDAState *d)
@@ -256,7 +255,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d)
static void intel_hda_update_irq(IntelHDAState *d)
{
- bool msi = msi_enabled(&d->pci);
+ int msi = d->msi && msi_enabled(&d->pci);
int level;
intel_hda_update_int_sts(d);
@@ -338,7 +337,7 @@ static void intel_hda_corb_run(IntelHDAState *d)
static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t response)
{
- HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus);
+ HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
IntelHDAState *d = container_of(bus, IntelHDAState, codecs);
hwaddr addr;
uint32_t wp, ex;
@@ -387,7 +386,7 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res
static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
uint8_t *buf, uint32_t len)
{
- HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus);
+ HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
IntelHDAState *d = container_of(bus, IntelHDAState, codecs);
hwaddr addr;
uint32_t s, copy, left;
@@ -494,7 +493,7 @@ static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool runn
DeviceState *qdev = kid->child;
HDACodecDeviceClass *cdc;
- cdev = HDA_CODEC_DEVICE(qdev);
+ cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
cdc = HDA_CODEC_DEVICE_GET_CLASS(cdev);
if (cdc->stream) {
cdc->stream(cdev, stream, running, output);
@@ -1121,7 +1120,7 @@ static void intel_hda_reset(DeviceState *dev)
/* reset codecs */
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
DeviceState *qdev = kid->child;
- cdev = HDA_CODEC_DEVICE(qdev);
+ cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
device_reset(DEVICE(cdev));
d->state_sts |= (1 << cdev->cad);
}
@@ -1132,8 +1131,6 @@ static void intel_hda_realize(PCIDevice *pci, Error **errp)
{
IntelHDAState *d = INTEL_HDA(pci);
uint8_t *conf = d->pci.config;
- Error *err = NULL;
- int ret;
d->name = object_get_typename(OBJECT(d));
@@ -1142,27 +1139,12 @@ static void intel_hda_realize(PCIDevice *pci, Error **errp)
/* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
conf[0x40] = 0x01;
- if (d->msi != ON_OFF_AUTO_OFF) {
- ret = msi_init(&d->pci, d->old_msi_addr ? 0x50 : 0x60,
- 1, true, false, &err);
- /* Any error other than -ENOTSUP(board's MSI support is broken)
- * is a programming error */
- assert(!ret || ret == -ENOTSUP);
- if (ret && d->msi == ON_OFF_AUTO_ON) {
- /* Can't satisfy user's explicit msi=on request, fail */
- error_append_hint(&err, "You have to use msi=auto (default) or "
- "msi=off with this machine type.\n");
- error_propagate(errp, err);
- return;
- }
- assert(!err || d->msi == ON_OFF_AUTO_AUTO);
- /* With msi=auto, we fall back to MSI off silently */
- error_free(err);
- }
-
memory_region_init_io(&d->mmio, OBJECT(d), &intel_hda_mmio_ops, d,
"intel-hda", 0x4000);
pci_register_bar(&d->pci, 0, 0, &d->mmio);
+ if (d->msi) {
+ msi_init(&d->pci, d->old_msi_addr ? 0x50 : 0x60, 1, true, false);
+ }
hda_codec_bus_init(DEVICE(pci), &d->codecs, sizeof(d->codecs),
intel_hda_response, intel_hda_xfer);
@@ -1252,7 +1234,7 @@ static const VMStateDescription vmstate_intel_hda = {
static Property intel_hda_properties[] = {
DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
- DEFINE_PROP_ON_OFF_AUTO("msi", IntelHDAState, msi, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
DEFINE_PROP_BOOL("old_msi_addr", IntelHDAState, old_msi_addr, false),
DEFINE_PROP_END_OF_LIST(),
};
@@ -1316,7 +1298,7 @@ static const TypeInfo intel_hda_info_ich9 = {
static void hda_codec_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
- k->realize = hda_codec_dev_realize;
+ k->init = hda_codec_dev_init;
k->exit = hda_codec_dev_exit;
set_bit(DEVICE_CATEGORY_SOUND, k->categories);
k->bus_type = TYPE_HDA_BUS;
diff --git a/hw/audio/lm4549.h b/hw/audio/lm4549.h
index 74c3ee893..812a7a444 100644
--- a/hw/audio/lm4549.h
+++ b/hw/audio/lm4549.h
@@ -40,4 +40,4 @@ uint32_t lm4549_read(lm4549_state *s, hwaddr offset);
void lm4549_write(lm4549_state *s, hwaddr offset, uint32_t value);
uint32_t lm4549_write_samples(lm4549_state *s, uint32_t left, uint32_t right);
-#endif /* HW_LM4549_H */
+#endif /* #ifndef HW_LM4549_H */
diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c
index bc8db71ae..6a3b53674 100644
--- a/hw/audio/milkymist-ac97.c
+++ b/hw/audio/milkymist-ac97.c
@@ -18,7 +18,7 @@
*
*
* Specification available at:
- * http://milkymist.walle.cc/socdoc/ac97.pdf
+ * http://www.milkymist.org/socdoc/ac97.pdf
*/
#include "qemu/osdep.h"
@@ -284,26 +284,16 @@ static int ac97_post_load(void *opaque, int version_id)
return 0;
}
-static void milkymist_ac97_init(Object *obj)
+static int milkymist_ac97_init(SysBusDevice *dev)
{
- MilkymistAC97State *s = MILKYMIST_AC97(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ MilkymistAC97State *s = MILKYMIST_AC97(dev);
+ struct audsettings as;
sysbus_init_irq(dev, &s->crrequest_irq);
sysbus_init_irq(dev, &s->crreply_irq);
sysbus_init_irq(dev, &s->dmar_irq);
sysbus_init_irq(dev, &s->dmaw_irq);
- memory_region_init_io(&s->regs_region, obj, &ac97_mmio_ops, s,
- "milkymist-ac97", R_MAX * 4);
- sysbus_init_mmio(dev, &s->regs_region);
-}
-
-static void milkymist_ac97_realize(DeviceState *dev, Error **errp)
-{
- MilkymistAC97State *s = MILKYMIST_AC97(dev);
- struct audsettings as;
-
AUD_register_card("Milkymist AC'97", &s->card);
as.freq = 48000;
@@ -315,6 +305,12 @@ static void milkymist_ac97_realize(DeviceState *dev, Error **errp)
"mm_ac97.in", s, ac97_in_cb, &as);
s->voice_out = AUD_open_out(&s->card, s->voice_out,
"mm_ac97.out", s, ac97_out_cb, &as);
+
+ memory_region_init_io(&s->regs_region, OBJECT(s), &ac97_mmio_ops, s,
+ "milkymist-ac97", R_MAX * 4);
+ sysbus_init_mmio(dev, &s->regs_region);
+
+ return 0;
}
static const VMStateDescription vmstate_milkymist_ac97 = {
@@ -331,8 +327,9 @@ static const VMStateDescription vmstate_milkymist_ac97 = {
static void milkymist_ac97_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- dc->realize = milkymist_ac97_realize;
+ k->init = milkymist_ac97_init;
dc->reset = milkymist_ac97_reset;
dc->vmsd = &vmstate_milkymist_ac97;
}
@@ -341,7 +338,6 @@ static const TypeInfo milkymist_ac97_info = {
.name = TYPE_MILKYMIST_AC97,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistAC97State),
- .instance_init = milkymist_ac97_init,
.class_init = milkymist_ac97_class_init,
};
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index 42a6f4885..f9afc8eda 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -31,12 +31,11 @@
#include "qemu/timer.h"
#include "hw/timer/i8254.h"
#include "hw/audio/pcspk.h"
-#include "qapi/error.h"
#define PCSPK_BUF_LEN 1792
#define PCSPK_SAMPLE_RATE 32000
#define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
-#define PCSPK_MIN_COUNT DIV_ROUND_UP(PIT_FREQ, PCSPK_MAX_FREQ)
+#define PCSPK_MIN_COUNT ((PIT_FREQ + PCSPK_MAX_FREQ - 1) / PCSPK_MAX_FREQ)
#define PC_SPEAKER(obj) OBJECT_CHECK(PCSpkState, (obj), TYPE_PC_SPEAKER)
@@ -170,11 +169,6 @@ static void pcspk_initfn(Object *obj)
PCSpkState *s = PC_SPEAKER(obj);
memory_region_init_io(&s->ioport, OBJECT(s), &pcspk_io_ops, s, "pcspk", 1);
-
- object_property_add_link(obj, "pit", TYPE_PIT_COMMON,
- (Object **)&s->pit,
- qdev_prop_allow_set_link_before_realize,
- 0, &error_abort);
}
static void pcspk_realizefn(DeviceState *dev, Error **errp)
@@ -189,6 +183,7 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp)
static Property pcspk_properties[] = {
DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1),
+ DEFINE_PROP_PTR("pit", PCSpkState, pit),
DEFINE_PROP_END_OF_LIST(),
};
@@ -199,7 +194,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
dc->realize = pcspk_realizefn;
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->props = pcspk_properties;
- /* Reason: realize sets global pcspk_state */
+ /* Reason: pointer property "pit", realize sets global pcspk_state */
dc->cannot_instantiate_with_device_add_yet = true;
}
diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c
index 6e9c10401..4717bc9b9 100644
--- a/hw/audio/pl041.c
+++ b/hw/audio/pl041.c
@@ -22,7 +22,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
-#include "qemu/log.h"
#include "pl041.h"
#include "lm4549.h"
diff --git a/hw/audio/pl041.h b/hw/audio/pl041.h
index 515db4756..427ab6d6f 100644
--- a/hw/audio/pl041.h
+++ b/hw/audio/pl041.h
@@ -132,4 +132,4 @@ enum {
#define RXTOFEC3 (1 << 11)
#define RXTOFEC4 (1 << 12)
-#endif /* HW_PL041_H */
+#endif /* #ifndef HW_PL041_H */
diff --git a/hw/audio/trace-events b/hw/audio/trace-events
deleted file mode 100644
index 3210386e8..000000000
--- a/hw/audio/trace-events
+++ /dev/null
@@ -1,19 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/audio/cs4231.c
-cs4231_mem_readl_dreg(uint32_t reg, uint32_t ret) "read dreg %d: 0x%02x"
-cs4231_mem_readl_reg(uint32_t reg, uint32_t ret) "read reg %d: 0x%08x"
-cs4231_mem_writel_reg(uint32_t reg, uint32_t old, uint32_t val) "write reg %d: 0x%08x -> 0x%08x"
-cs4231_mem_writel_dreg(uint32_t reg, uint32_t old, uint32_t val) "write dreg %d: 0x%02x -> 0x%02x"
-
-# hw/audio/milkymist-ac97.c
-milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request"
-milkymist_ac97_pulse_irq_crreply(void) "Pulse IRQ CR reply"
-milkymist_ac97_pulse_irq_dmaw(void) "Pulse IRQ DMA write"
-milkymist_ac97_pulse_irq_dmar(void) "Pulse IRQ DMA read"
-milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining %u"
-milkymist_ac97_in_cb_transferred(int transferred) "transferred %d"
-milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u"
-milkymist_ac97_out_cb_transferred(int transferred) "transferred %d"
diff --git a/hw/block/block.c b/hw/block/block.c
index 8dc9d84a3..97a59d4fa 100644
--- a/hw/block/block.c
+++ b/hw/block/block.c
@@ -51,34 +51,6 @@ void blkconf_blocksizes(BlockConf *conf)
}
}
-void blkconf_apply_backend_options(BlockConf *conf)
-{
- BlockBackend *blk = conf->blk;
- BlockdevOnError rerror, werror;
- bool wce;
-
- switch (conf->wce) {
- case ON_OFF_AUTO_ON: wce = true; break;
- case ON_OFF_AUTO_OFF: wce = false; break;
- case ON_OFF_AUTO_AUTO: wce = blk_enable_write_cache(blk); break;
- default:
- abort();
- }
-
- rerror = conf->rerror;
- if (rerror == BLOCKDEV_ON_ERROR_AUTO) {
- rerror = blk_get_on_error(blk, true);
- }
-
- werror = conf->werror;
- if (werror == BLOCKDEV_ON_ERROR_AUTO) {
- werror = blk_get_on_error(blk, false);
- }
-
- blk_set_enable_write_cache(blk, wce);
- blk_set_on_error(blk, rerror, werror);
-}
-
void blkconf_geometry(BlockConf *conf, int *ptrans,
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
Error **errp)
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 704a76360..3cb97c9a2 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -31,9 +31,13 @@ struct VirtIOBlockDataPlane {
bool stopping;
VirtIOBlkConf *conf;
+
VirtIODevice *vdev;
+ VirtQueue *vq; /* virtqueue vring */
+ EventNotifier *guest_notifier; /* irq */
QEMUBH *bh; /* bh for guest notification */
- unsigned long *batch_notify_vqs;
+
+ Notifier insert_notifier, remove_notifier;
/* Note that these EventNotifiers are assigned by value. This is
* fine as long as you do not call event_notifier_cleanup on them
@@ -42,41 +46,76 @@ struct VirtIOBlockDataPlane {
*/
IOThread *iothread;
AioContext *ctx;
+
+ /* Operation blocker on BDS */
+ Error *blocker;
};
/* Raise an interrupt to signal guest, if necessary */
-void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s, VirtQueue *vq)
+void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s)
{
- set_bit(virtio_get_queue_index(vq), s->batch_notify_vqs);
qemu_bh_schedule(s->bh);
}
static void notify_guest_bh(void *opaque)
{
VirtIOBlockDataPlane *s = opaque;
- unsigned nvqs = s->conf->num_queues;
- unsigned long bitmap[BITS_TO_LONGS(nvqs)];
- unsigned j;
-
- memcpy(bitmap, s->batch_notify_vqs, sizeof(bitmap));
- memset(s->batch_notify_vqs, 0, sizeof(bitmap));
- for (j = 0; j < nvqs; j += BITS_PER_LONG) {
- unsigned long bits = bitmap[j];
+ if (!virtio_should_notify(s->vdev, s->vq)) {
+ return;
+ }
- while (bits != 0) {
- unsigned i = j + ctzl(bits);
- VirtQueue *vq = virtio_get_queue(s->vdev, i);
+ event_notifier_set(s->guest_notifier);
+}
- if (virtio_should_notify(s->vdev, vq)) {
- event_notifier_set(virtio_queue_get_guest_notifier(vq));
- }
+static void data_plane_set_up_op_blockers(VirtIOBlockDataPlane *s)
+{
+ assert(!s->blocker);
+ error_setg(&s->blocker, "block device is in use by data plane");
+ blk_op_block_all(s->conf->conf.blk, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_SOURCE, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_TARGET, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
+ s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT,
+ s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
+ s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_MIRROR_SOURCE, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_STREAM, s->blocker);
+ blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_REPLACE, s->blocker);
+}
- bits &= bits - 1; /* clear right-most bit */
- }
+static void data_plane_remove_op_blockers(VirtIOBlockDataPlane *s)
+{
+ if (s->blocker) {
+ blk_op_unblock_all(s->conf->conf.blk, s->blocker);
+ error_free(s->blocker);
+ s->blocker = NULL;
}
}
+static void data_plane_blk_insert_notifier(Notifier *n, void *data)
+{
+ VirtIOBlockDataPlane *s = container_of(n, VirtIOBlockDataPlane,
+ insert_notifier);
+ assert(s->conf->conf.blk == data);
+ data_plane_set_up_op_blockers(s);
+}
+
+static void data_plane_blk_remove_notifier(Notifier *n, void *data)
+{
+ VirtIOBlockDataPlane *s = container_of(n, VirtIOBlockDataPlane,
+ remove_notifier);
+ assert(s->conf->conf.blk == data);
+ data_plane_remove_op_blockers(s);
+}
+
/* Context: QEMU global mutex held */
void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
VirtIOBlockDataPlane **dataplane,
@@ -93,7 +132,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
}
/* Don't try if transport does not support notifiers. */
- if (!k->set_guest_notifiers || !k->ioeventfd_started) {
+ if (!k->set_guest_notifiers || !k->set_host_notifier) {
error_setg(errp,
"device is incompatible with dataplane "
"(transport does not support notifiers)");
@@ -112,11 +151,19 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
s->vdev = vdev;
s->conf = conf;
- s->iothread = conf->iothread;
- object_ref(OBJECT(s->iothread));
+ if (conf->iothread) {
+ s->iothread = conf->iothread;
+ object_ref(OBJECT(s->iothread));
+ }
s->ctx = iothread_get_aio_context(s->iothread);
s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
- s->batch_notify_vqs = bitmap_new(conf->num_queues);
+
+ s->insert_notifier.notify = data_plane_blk_insert_notifier;
+ s->remove_notifier.notify = data_plane_blk_remove_notifier;
+ blk_add_insert_bs_notifier(conf->conf.blk, &s->insert_notifier);
+ blk_add_remove_bs_notifier(conf->conf.blk, &s->remove_notifier);
+
+ data_plane_set_up_op_blockers(s);
*dataplane = s;
}
@@ -129,7 +176,9 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
}
virtio_blk_data_plane_stop(s);
- g_free(s->batch_notify_vqs);
+ data_plane_remove_op_blockers(s);
+ notifier_remove(&s->insert_notifier);
+ notifier_remove(&s->remove_notifier);
qemu_bh_delete(s->bh);
object_unref(OBJECT(s->iothread));
g_free(s);
@@ -152,8 +201,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
- unsigned i;
- unsigned nvqs = s->conf->num_queues;
int r;
if (vblk->dataplane_started || s->starting) {
@@ -161,25 +208,22 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
}
s->starting = true;
+ s->vq = virtio_get_queue(s->vdev, 0);
/* Set up guest notifier (irq) */
- r = k->set_guest_notifiers(qbus->parent, nvqs, true);
+ r = k->set_guest_notifiers(qbus->parent, 1, true);
if (r != 0) {
fprintf(stderr, "virtio-blk failed to set guest notifier (%d), "
"ensure -enable-kvm is set\n", r);
goto fail_guest_notifiers;
}
+ s->guest_notifier = virtio_queue_get_guest_notifier(s->vq);
/* Set up virtqueue notify */
- for (i = 0; i < nvqs; i++) {
- r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, true);
- if (r != 0) {
- fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r);
- while (i--) {
- virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
- }
- goto fail_guest_notifiers;
- }
+ r = k->set_host_notifier(qbus->parent, 0, true);
+ if (r != 0) {
+ fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r);
+ goto fail_host_notifier;
}
s->starting = false;
@@ -189,23 +233,17 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
blk_set_aio_context(s->conf->conf.blk, s->ctx);
/* Kick right away to begin processing requests already in vring */
- for (i = 0; i < nvqs; i++) {
- VirtQueue *vq = virtio_get_queue(s->vdev, i);
-
- event_notifier_set(virtio_queue_get_host_notifier(vq));
- }
+ event_notifier_set(virtio_queue_get_host_notifier(s->vq));
/* Get this show started by hooking up our callbacks */
aio_context_acquire(s->ctx);
- for (i = 0; i < nvqs; i++) {
- VirtQueue *vq = virtio_get_queue(s->vdev, i);
-
- virtio_queue_aio_set_host_notifier_handler(vq, s->ctx,
- virtio_blk_data_plane_handle_output);
- }
+ virtio_queue_aio_set_host_notifier_handler(s->vq, s->ctx,
+ virtio_blk_data_plane_handle_output);
aio_context_release(s->ctx);
return;
+ fail_host_notifier:
+ k->set_guest_notifiers(qbus->parent, 1, false);
fail_guest_notifiers:
vblk->dataplane_disabled = true;
s->starting = false;
@@ -218,8 +256,6 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
- unsigned i;
- unsigned nvqs = s->conf->num_queues;
if (!vblk->dataplane_started || s->stopping) {
return;
@@ -237,23 +273,17 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
aio_context_acquire(s->ctx);
/* Stop notifications for new requests from guest */
- for (i = 0; i < nvqs; i++) {
- VirtQueue *vq = virtio_get_queue(s->vdev, i);
-
- virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, NULL);
- }
+ virtio_queue_aio_set_host_notifier_handler(s->vq, s->ctx, NULL);
/* Drain and switch bs back to the QEMU main loop */
blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context());
aio_context_release(s->ctx);
- for (i = 0; i < nvqs; i++) {
- virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
- }
+ k->set_host_notifier(qbus->parent, 0, false);
/* Clean up guest notifier (irq) */
- k->set_guest_notifiers(qbus->parent, nvqs, false);
+ k->set_guest_notifiers(qbus->parent, 1, false);
vblk->dataplane_started = false;
s->stopping = false;
diff --git a/hw/block/dataplane/virtio-blk.h b/hw/block/dataplane/virtio-blk.h
index b1f0b95b3..0714c11a2 100644
--- a/hw/block/dataplane/virtio-blk.h
+++ b/hw/block/dataplane/virtio-blk.h
@@ -26,6 +26,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s);
void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s);
void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s);
void virtio_blk_data_plane_drain(VirtIOBlockDataPlane *s);
-void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s, VirtQueue *vq);
+void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s);
#endif /* HW_DATAPLANE_VIRTIO_BLK_H */
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index f73af7db4..372227569 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -223,13 +223,6 @@ static int fd_sector(FDrive *drv)
NUM_SIDES(drv));
}
-/* Returns current position, in bytes, for given drive */
-static int fd_offset(FDrive *drv)
-{
- g_assert(fd_sector(drv) < INT_MAX >> BDRV_SECTOR_BITS);
- return fd_sector(drv) << BDRV_SECTOR_BITS;
-}
-
/* Seek to a new position:
* returns 0 if already on right track
* returns 1 if track changed
@@ -1636,8 +1629,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
if (fdctrl->data_dir != FD_DIR_WRITE ||
len < FD_SECTOR_LEN || rel_pos != 0) {
/* READ & SCAN commands and realign to a sector for WRITE */
- if (blk_pread(cur_drv->blk, fd_offset(cur_drv),
- fdctrl->fifo, BDRV_SECTOR_SIZE) < 0) {
+ if (blk_read(cur_drv->blk, fd_sector(cur_drv),
+ fdctrl->fifo, 1) < 0) {
FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
fd_sector(cur_drv));
/* Sure, image size is too small... */
@@ -1664,8 +1657,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
k->read_memory(fdctrl->dma, nchan, fdctrl->fifo + rel_pos,
fdctrl->data_pos, len);
- if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv),
- fdctrl->fifo, BDRV_SECTOR_SIZE, 0) < 0) {
+ if (blk_write(cur_drv->blk, fd_sector(cur_drv),
+ fdctrl->fifo, 1) < 0) {
FLOPPY_DPRINTF("error writing sector %d\n",
fd_sector(cur_drv));
fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
@@ -1748,8 +1741,7 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
fd_sector(cur_drv));
return 0;
}
- if (blk_pread(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo,
- BDRV_SECTOR_SIZE)
+ if (blk_read(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1)
< 0) {
FLOPPY_DPRINTF("error getting sector %d\n",
fd_sector(cur_drv));
@@ -1828,8 +1820,7 @@ static void fdctrl_format_sector(FDCtrl *fdctrl)
}
memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
if (cur_drv->blk == NULL ||
- blk_pwrite(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo,
- BDRV_SECTOR_SIZE, 0) < 0) {
+ blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
FLOPPY_DPRINTF("error formatting sector %d\n", fd_sector(cur_drv));
fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
} else {
@@ -2252,8 +2243,8 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
if (pos == FD_SECTOR_LEN - 1 ||
fdctrl->data_pos == fdctrl->data_len) {
cur_drv = get_cur_drv(fdctrl);
- if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo,
- BDRV_SECTOR_SIZE, 0) < 0) {
+ if (blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1)
+ < 0) {
FLOPPY_DPRINTF("error writing sector %d\n",
fd_sector(cur_drv));
break;
diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c
index 57ad5012a..6d02192db 100644
--- a/hw/block/hd-geometry.c
+++ b/hw/block/hd-geometry.c
@@ -32,7 +32,6 @@
#include "qemu/osdep.h"
#include "sysemu/block-backend.h"
-#include "qemu/bswap.h"
#include "hw/block/block.h"
#include "trace.h"
@@ -67,7 +66,7 @@ static int guess_disk_lchs(BlockBackend *blk,
* but also in async I/O mode. So the I/O throttling function has to
* be disabled temporarily here, not permanently.
*/
- if (blk_pread_unthrottled(blk, 0, buf, BDRV_SECTOR_SIZE) < 0) {
+ if (blk_read_unthrottled(blk, 0, buf, 1) < 0) {
return -1;
}
/* test msdos magic */
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 9828ee61d..906b71257 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -27,8 +27,6 @@
#include "sysemu/blockdev.h"
#include "hw/ssi/ssi.h"
#include "qemu/bitops.h"
-#include "qemu/log.h"
-#include "qapi/error.h"
#ifndef M25P80_ERR_DEBUG
#define M25P80_ERR_DEBUG 0
@@ -54,17 +52,12 @@
/* 16 MiB max in 3 byte address mode */
#define MAX_3BYTES_SIZE 0x1000000
-#define SPI_NOR_MAX_ID_LEN 6
-
typedef struct FlashPartInfo {
const char *part_name;
- /*
- * This array stores the ID bytes.
- * The first three bytes are the JEDIC ID.
- * JEDEC ID zero means "no ID" (mostly older chips).
- */
- uint8_t id[SPI_NOR_MAX_ID_LEN];
- uint8_t id_len;
+ /* jedec code. (jedec >> 16) & 0xff is the 1st byte, >> 8 the 2nd etc */
+ uint32_t jedec;
+ /* extended jedec code */
+ uint16_t ext_jedec;
/* there is confusion between manufacturers as to what a sector is. In this
* device model, a "sector" is the size that is erased by the ERASE_SECTOR
* command (opcode 0xd8).
@@ -76,33 +69,11 @@ typedef struct FlashPartInfo {
} FlashPartInfo;
/* adapted from linux */
-/* Used when the "_ext_id" is two bytes at most */
-#define INFO(_part_name, _jedec_id, _ext_id, _sector_size, _n_sectors, _flags)\
- .part_name = _part_name,\
- .id = {\
- ((_jedec_id) >> 16) & 0xff,\
- ((_jedec_id) >> 8) & 0xff,\
- (_jedec_id) & 0xff,\
- ((_ext_id) >> 8) & 0xff,\
- (_ext_id) & 0xff,\
- },\
- .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),\
- .sector_size = (_sector_size),\
- .n_sectors = (_n_sectors),\
- .page_size = 256,\
- .flags = (_flags),
-
-#define INFO6(_part_name, _jedec_id, _ext_id, _sector_size, _n_sectors, _flags)\
- .part_name = _part_name,\
- .id = {\
- ((_jedec_id) >> 16) & 0xff,\
- ((_jedec_id) >> 8) & 0xff,\
- (_jedec_id) & 0xff,\
- ((_ext_id) >> 16) & 0xff,\
- ((_ext_id) >> 8) & 0xff,\
- (_ext_id) & 0xff,\
- },\
- .id_len = 6,\
+
+#define INFO(_part_name, _jedec, _ext_jedec, _sector_size, _n_sectors, _flags)\
+ .part_name = (_part_name),\
+ .jedec = (_jedec),\
+ .ext_jedec = (_ext_jedec),\
.sector_size = (_sector_size),\
.n_sectors = (_n_sectors),\
.page_size = 256,\
@@ -130,27 +101,12 @@ typedef struct FlashPartInfo {
#define EVCFG_QUAD_IO_ENABLED (1 << 7)
#define NVCFG_4BYTE_ADDR_MASK (1 << 0)
#define NVCFG_LOWER_SEGMENT_MASK (1 << 1)
+#define CFG_UPPER_128MB_SEG_ENABLED 0x3
/* Numonyx (Micron) Flag Status Register macros */
#define FSR_4BYTE_ADDR_MODE_ENABLED 0x1
#define FSR_FLASH_READY (1 << 7)
-/* Spansion configuration registers macros. */
-#define SPANSION_QUAD_CFG_POS 0
-#define SPANSION_QUAD_CFG_LEN 1
-#define SPANSION_DUMMY_CLK_POS 0
-#define SPANSION_DUMMY_CLK_LEN 4
-#define SPANSION_ADDR_LEN_POS 7
-#define SPANSION_ADDR_LEN_LEN 1
-
-/*
- * Spansion read mode command length in bytes,
- * the mode is currently not supported.
-*/
-
-#define SPANSION_CONTINUOUS_READ_MODE_CMD_LEN 1
-#define WINBOND_CONTINUOUS_READ_MODE_CMD_LEN 1
-
static const FlashPartInfo known_devices[] = {
/* Atmel -- some are (confusingly) marketed as "DataFlash" */
{ INFO("at25fs010", 0x1f6601, 0, 32 << 10, 4, ER_4K) },
@@ -201,8 +157,6 @@ static const FlashPartInfo known_devices[] = {
{ INFO("mx25l12855e", 0xc22618, 0, 64 << 10, 256, 0) },
{ INFO("mx25l25635e", 0xc22019, 0, 64 << 10, 512, 0) },
{ INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) },
- { INFO("mx66u51235f", 0xc2253a, 0, 64 << 10, 1024, ER_4K | ER_32K) },
- { INFO("mx66u1g45g", 0xc2253b, 0, 64 << 10, 2048, ER_4K | ER_32K) },
/* Micron */
{ INFO("n25q032a11", 0x20bb16, 0, 64 << 10, 64, ER_4K) },
@@ -213,11 +167,6 @@ static const FlashPartInfo known_devices[] = {
{ INFO("n25q128a13", 0x20ba18, 0, 64 << 10, 256, ER_4K) },
{ INFO("n25q256a11", 0x20bb19, 0, 64 << 10, 512, ER_4K) },
{ INFO("n25q256a13", 0x20ba19, 0, 64 << 10, 512, ER_4K) },
- { INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) },
- { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, ER_4K) },
- { INFO("n25q512a", 0x20ba20, 0, 64 << 10, 1024, ER_4K) },
- { INFO("mt25ql01g", 0x20ba21, 0, 64 << 10, 2048, ER_4K) },
- { INFO("mt25qu01g", 0x20bb21, 0, 64 << 10, 2048, ER_4K) },
/* Spansion -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
@@ -226,8 +175,8 @@ static const FlashPartInfo known_devices[] = {
{ INFO("s25sl064p", 0x010216, 0x4d00, 64 << 10, 128, ER_4K) },
{ INFO("s25fl256s0", 0x010219, 0x4d00, 256 << 10, 128, 0) },
{ INFO("s25fl256s1", 0x010219, 0x4d01, 64 << 10, 512, 0) },
- { INFO6("s25fl512s", 0x010220, 0x4d0080, 256 << 10, 256, 0) },
- { INFO6("s70fl01gs", 0x010221, 0x4d0080, 256 << 10, 512, 0) },
+ { INFO("s25fl512s", 0x010220, 0x4d00, 256 << 10, 256, 0) },
+ { INFO("s70fl01gs", 0x010221, 0x4d00, 256 << 10, 256, 0) },
{ INFO("s25sl12800", 0x012018, 0x0300, 256 << 10, 64, 0) },
{ INFO("s25sl12801", 0x012018, 0x0301, 64 << 10, 256, 0) },
{ INFO("s25fl129p0", 0x012018, 0x4d00, 256 << 10, 64, 0) },
@@ -240,10 +189,6 @@ static const FlashPartInfo known_devices[] = {
{ INFO("s25fl016k", 0xef4015, 0, 64 << 10, 32, ER_4K | ER_32K) },
{ INFO("s25fl064k", 0xef4017, 0, 64 << 10, 128, ER_4K | ER_32K) },
- /* Spansion -- boot sectors support */
- { INFO6("s25fs512s", 0x010220, 0x4d0081, 256 << 10, 256, 0) },
- { INFO6("s70fs01gs", 0x010221, 0x4d0081, 256 << 10, 512, 0) },
-
/* SST -- large erase sizes are "overlays", "sectors" are 4<< 10 */
{ INFO("sst25vf040b", 0xbf258d, 0, 64 << 10, 8, ER_4K) },
{ INFO("sst25vf080b", 0xbf258e, 0, 64 << 10, 16, ER_4K) },
@@ -294,6 +239,10 @@ static const FlashPartInfo known_devices[] = {
{ INFO("w25q80", 0xef5014, 0, 64 << 10, 16, ER_4K) },
{ INFO("w25q80bl", 0xef4014, 0, 64 << 10, 16, ER_4K) },
{ INFO("w25q256", 0xef4019, 0, 64 << 10, 512, ER_4K) },
+
+ { INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) },
+ { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, ER_4K) },
+ { INFO("n25q512a", 0x20ba20, 0, 64 << 10, 1024, ER_4K) },
};
typedef enum {
@@ -305,7 +254,6 @@ typedef enum {
JEDEC_READ = 0x9f,
BULK_ERASE = 0xc7,
READ_FSR = 0x70,
- RDCR = 0x15,
READ = 0x03,
READ4 = 0x13,
@@ -322,14 +270,12 @@ typedef enum {
PP = 0x02,
PP4 = 0x12,
- PP4_4 = 0x3e,
DPP = 0xa2,
QPP = 0x32,
ERASE_4K = 0x20,
ERASE4_4K = 0x21,
ERASE_32K = 0x52,
- ERASE4_32K = 0x5c,
ERASE_SECTOR = 0xd8,
ERASE4_SECTOR = 0xdc,
@@ -342,13 +288,6 @@ typedef enum {
RESET_ENABLE = 0x66,
RESET_MEMORY = 0x99,
- /*
- * Micron: 0x35 - enable QPI
- * Spansion: 0x35 - read control register
- */
- RDCR_EQIO = 0x35,
- RSTQIO = 0xf5,
-
RNVCR = 0xB5,
WNVCR = 0xB1,
@@ -364,18 +303,9 @@ typedef enum {
STATE_PAGE_PROGRAM,
STATE_READ,
STATE_COLLECTING_DATA,
- STATE_COLLECTING_VAR_LEN_DATA,
STATE_READING_DATA,
} CMDState;
-typedef enum {
- MAN_SPANSION,
- MAN_MACRONIX,
- MAN_NUMONYX,
- MAN_WINBOND,
- MAN_GENERIC,
-} Manufacturer;
-
typedef struct Flash {
SSISlave parent_obj;
@@ -391,24 +321,13 @@ typedef struct Flash {
uint32_t pos;
uint8_t needed_bytes;
uint8_t cmd_in_progress;
- uint32_t cur_addr;
+ uint64_t cur_addr;
uint32_t nonvolatile_cfg;
- /* Configuration register for Macronix */
uint32_t volatile_cfg;
uint32_t enh_volatile_cfg;
- /* Spansion cfg registers. */
- uint8_t spansion_cr1nv;
- uint8_t spansion_cr2nv;
- uint8_t spansion_cr3nv;
- uint8_t spansion_cr4nv;
- uint8_t spansion_cr1v;
- uint8_t spansion_cr2v;
- uint8_t spansion_cr3v;
- uint8_t spansion_cr4v;
bool write_enable;
bool four_bytes_address_mode;
bool reset_enable;
- bool quad_enable;
uint8_t ear;
int64_t dirty_page;
@@ -430,29 +349,8 @@ typedef struct M25P80Class {
#define M25P80_GET_CLASS(obj) \
OBJECT_GET_CLASS(M25P80Class, (obj), TYPE_M25P80)
-static inline Manufacturer get_man(Flash *s)
-{
- switch (s->pi->id[0]) {
- case 0x20:
- return MAN_NUMONYX;
- case 0xEF:
- return MAN_WINBOND;
- case 0x01:
- return MAN_SPANSION;
- case 0xC2:
- return MAN_MACRONIX;
- default:
- return MAN_GENERIC;
- }
-}
-
static void blk_sync_complete(void *opaque, int ret)
{
- QEMUIOVector *iov = opaque;
-
- qemu_iovec_destroy(iov);
- g_free(iov);
-
/* do nothing. Masters do not directly interact with the backing store,
* only the working copy so no mutexing required.
*/
@@ -460,33 +358,39 @@ static void blk_sync_complete(void *opaque, int ret)
static void flash_sync_page(Flash *s, int page)
{
- QEMUIOVector *iov;
+ int blk_sector, nb_sectors;
+ QEMUIOVector iov;
if (!s->blk || blk_is_read_only(s->blk)) {
return;
}
- iov = g_new(QEMUIOVector, 1);
- qemu_iovec_init(iov, 1);
- qemu_iovec_add(iov, s->storage + page * s->pi->page_size,
- s->pi->page_size);
- blk_aio_pwritev(s->blk, page * s->pi->page_size, iov, 0,
- blk_sync_complete, iov);
+ blk_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE;
+ nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE);
+ qemu_iovec_init(&iov, 1);
+ qemu_iovec_add(&iov, s->storage + blk_sector * BDRV_SECTOR_SIZE,
+ nb_sectors * BDRV_SECTOR_SIZE);
+ blk_aio_writev(s->blk, blk_sector, &iov, nb_sectors, blk_sync_complete,
+ NULL);
}
static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
{
- QEMUIOVector *iov;
+ int64_t start, end, nb_sectors;
+ QEMUIOVector iov;
if (!s->blk || blk_is_read_only(s->blk)) {
return;
}
assert(!(len % BDRV_SECTOR_SIZE));
- iov = g_new(QEMUIOVector, 1);
- qemu_iovec_init(iov, 1);
- qemu_iovec_add(iov, s->storage + off, len);
- blk_aio_pwritev(s->blk, off, iov, 0, blk_sync_complete, iov);
+ start = off / BDRV_SECTOR_SIZE;
+ end = (off + len) / BDRV_SECTOR_SIZE;
+ nb_sectors = end - start;
+ qemu_iovec_init(&iov, 1);
+ qemu_iovec_add(&iov, s->storage + (start * BDRV_SECTOR_SIZE),
+ nb_sectors * BDRV_SECTOR_SIZE);
+ blk_aio_writev(s->blk, start, &iov, nb_sectors, blk_sync_complete, NULL);
}
static void flash_erase(Flash *s, int offset, FlashCMD cmd)
@@ -501,7 +405,6 @@ static void flash_erase(Flash *s, int offset, FlashCMD cmd)
capa_to_assert = ER_4K;
break;
case ERASE_32K:
- case ERASE4_32K:
len = 32 << 10;
capa_to_assert = ER_32K;
break;
@@ -539,9 +442,9 @@ static inline void flash_sync_dirty(Flash *s, int64_t newpage)
}
static inline
-void flash_write8(Flash *s, uint32_t addr, uint8_t data)
+void flash_write8(Flash *s, uint64_t addr, uint8_t data)
{
- uint32_t page = addr / s->pi->page_size;
+ int64_t page = addr / s->pi->page_size;
uint8_t prev = s->storage[s->cur_addr];
if (!s->write_enable) {
@@ -549,7 +452,7 @@ void flash_write8(Flash *s, uint32_t addr, uint8_t data)
}
if ((prev ^ data) & data) {
- DB_PRINT_L(1, "programming zero to one! addr=%" PRIx32 " %" PRIx8
+ DB_PRINT_L(1, "programming zero to one! addr=%" PRIx64 " %" PRIx8
" -> %" PRIx8 "\n", addr, prev, data);
}
@@ -572,11 +475,9 @@ static inline int get_addr_length(Flash *s)
switch (s->cmd_in_progress) {
case PP4:
- case PP4_4:
case READ4:
case QIOR4:
case ERASE4_4K:
- case ERASE4_32K:
case ERASE4_SECTOR:
case FAST_READ4:
case DOR4:
@@ -590,16 +491,18 @@ static inline int get_addr_length(Flash *s)
static void complete_collecting_data(Flash *s)
{
- int i, n;
+ int i;
+
+ s->cur_addr = 0;
- n = get_addr_length(s);
- s->cur_addr = (n == 3 ? s->ear : 0);
- for (i = 0; i < n; ++i) {
+ for (i = 0; i < get_addr_length(s); ++i) {
s->cur_addr <<= 8;
s->cur_addr |= s->data[i];
}
- s->cur_addr &= s->size - 1;
+ if (get_addr_length(s) == 3) {
+ s->cur_addr += (s->ear & 0x3) * MAX_3BYTES_SIZE;
+ }
s->state = STATE_IDLE;
@@ -608,7 +511,6 @@ static void complete_collecting_data(Flash *s)
case QPP:
case PP:
case PP4:
- case PP4_4:
s->state = STATE_PAGE_PROGRAM;
break;
case READ:
@@ -628,25 +530,11 @@ static void complete_collecting_data(Flash *s)
case ERASE_4K:
case ERASE4_4K:
case ERASE_32K:
- case ERASE4_32K:
case ERASE_SECTOR:
case ERASE4_SECTOR:
flash_erase(s, s->cur_addr, s->cmd_in_progress);
break;
case WRSR:
- switch (get_man(s)) {
- case MAN_SPANSION:
- s->quad_enable = !!(s->data[1] & 0x02);
- break;
- case MAN_MACRONIX:
- s->quad_enable = extract32(s->data[0], 6, 1);
- if (s->len > 1) {
- s->four_bytes_address_mode = extract32(s->data[1], 5, 1);
- }
- break;
- default:
- break;
- }
if (s->write_enable) {
s->write_enable = false;
}
@@ -680,10 +568,8 @@ static void reset_memory(Flash *s)
s->state = STATE_IDLE;
s->write_enable = false;
s->reset_enable = false;
- s->quad_enable = false;
- switch (get_man(s)) {
- case MAN_NUMONYX:
+ if (((s->pi->jedec >> 16) & 0xFF) == JEDEC_NUMONYX) {
s->volatile_cfg = 0;
s->volatile_cfg |= VCFG_DUMMY;
s->volatile_cfg |= VCFG_WRAP_SEQUENTIAL;
@@ -713,148 +599,16 @@ static void reset_memory(Flash *s)
s->four_bytes_address_mode = true;
}
if (!(s->nonvolatile_cfg & NVCFG_LOWER_SEGMENT_MASK)) {
- s->ear = s->size / MAX_3BYTES_SIZE - 1;
+ s->ear = CFG_UPPER_128MB_SEG_ENABLED;
}
- break;
- case MAN_MACRONIX:
- s->volatile_cfg = 0x7;
- break;
- case MAN_SPANSION:
- s->spansion_cr1v = s->spansion_cr1nv;
- s->spansion_cr2v = s->spansion_cr2nv;
- s->spansion_cr3v = s->spansion_cr3nv;
- s->spansion_cr4v = s->spansion_cr4nv;
- s->quad_enable = extract32(s->spansion_cr1v,
- SPANSION_QUAD_CFG_POS,
- SPANSION_QUAD_CFG_LEN
- );
- s->four_bytes_address_mode = extract32(s->spansion_cr2v,
- SPANSION_ADDR_LEN_POS,
- SPANSION_ADDR_LEN_LEN
- );
- break;
- default:
- break;
}
DB_PRINT_L(0, "Reset done.\n");
}
-static void decode_fast_read_cmd(Flash *s)
-{
- s->needed_bytes = get_addr_length(s);
- switch (get_man(s)) {
- /* Dummy cycles - modeled with bytes writes instead of bits */
- case MAN_WINBOND:
- s->needed_bytes += 8;
- break;
- case MAN_NUMONYX:
- s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
- break;
- case MAN_MACRONIX:
- if (extract32(s->volatile_cfg, 6, 2) == 1) {
- s->needed_bytes += 6;
- } else {
- s->needed_bytes += 8;
- }
- break;
- case MAN_SPANSION:
- s->needed_bytes += extract32(s->spansion_cr2v,
- SPANSION_DUMMY_CLK_POS,
- SPANSION_DUMMY_CLK_LEN
- );
- break;
- default:
- break;
- }
- s->pos = 0;
- s->len = 0;
- s->state = STATE_COLLECTING_DATA;
-}
-
-static void decode_dio_read_cmd(Flash *s)
-{
- s->needed_bytes = get_addr_length(s);
- /* Dummy cycles modeled with bytes writes instead of bits */
- switch (get_man(s)) {
- case MAN_WINBOND:
- s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
- break;
- case MAN_SPANSION:
- s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
- s->needed_bytes += extract32(s->spansion_cr2v,
- SPANSION_DUMMY_CLK_POS,
- SPANSION_DUMMY_CLK_LEN
- );
- break;
- case MAN_NUMONYX:
- s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
- break;
- case MAN_MACRONIX:
- switch (extract32(s->volatile_cfg, 6, 2)) {
- case 1:
- s->needed_bytes += 6;
- break;
- case 2:
- s->needed_bytes += 8;
- break;
- default:
- s->needed_bytes += 4;
- break;
- }
- break;
- default:
- break;
- }
- s->pos = 0;
- s->len = 0;
- s->state = STATE_COLLECTING_DATA;
-}
-
-static void decode_qio_read_cmd(Flash *s)
-{
- s->needed_bytes = get_addr_length(s);
- /* Dummy cycles modeled with bytes writes instead of bits */
- switch (get_man(s)) {
- case MAN_WINBOND:
- s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
- s->needed_bytes += 4;
- break;
- case MAN_SPANSION:
- s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
- s->needed_bytes += extract32(s->spansion_cr2v,
- SPANSION_DUMMY_CLK_POS,
- SPANSION_DUMMY_CLK_LEN
- );
- break;
- case MAN_NUMONYX:
- s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
- break;
- case MAN_MACRONIX:
- switch (extract32(s->volatile_cfg, 6, 2)) {
- case 1:
- s->needed_bytes += 4;
- break;
- case 2:
- s->needed_bytes += 8;
- break;
- default:
- s->needed_bytes += 6;
- break;
- }
- break;
- default:
- break;
- }
- s->pos = 0;
- s->len = 0;
- s->state = STATE_COLLECTING_DATA;
-}
-
static void decode_new_cmd(Flash *s, uint32_t value)
{
s->cmd_in_progress = value;
- int i;
DB_PRINT_L(0, "decoded new command:%x\n", value);
if (value != RESET_MEMORY) {
@@ -866,7 +620,6 @@ static void decode_new_cmd(Flash *s, uint32_t value)
case ERASE_4K:
case ERASE4_4K:
case ERASE_32K:
- case ERASE4_32K:
case ERASE_SECTOR:
case ERASE4_SECTOR:
case READ:
@@ -875,7 +628,6 @@ static void decode_new_cmd(Flash *s, uint32_t value)
case QPP:
case PP:
case PP4:
- case PP4_4:
s->needed_bytes = get_addr_length(s);
s->pos = 0;
s->len = 0;
@@ -888,35 +640,56 @@ static void decode_new_cmd(Flash *s, uint32_t value)
case DOR4:
case QOR:
case QOR4:
- decode_fast_read_cmd(s);
+ s->needed_bytes = get_addr_length(s);
+ if (((s->pi->jedec >> 16) & 0xFF) == JEDEC_NUMONYX) {
+ /* Dummy cycles modeled with bytes writes instead of bits */
+ s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
+ }
+ s->pos = 0;
+ s->len = 0;
+ s->state = STATE_COLLECTING_DATA;
break;
case DIOR:
case DIOR4:
- decode_dio_read_cmd(s);
+ switch ((s->pi->jedec >> 16) & 0xFF) {
+ case JEDEC_WINBOND:
+ case JEDEC_SPANSION:
+ s->needed_bytes = 4;
+ break;
+ default:
+ s->needed_bytes = get_addr_length(s);
+ /* Dummy cycles modeled with bytes writes instead of bits */
+ s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
+ }
+ s->pos = 0;
+ s->len = 0;
+ s->state = STATE_COLLECTING_DATA;
break;
case QIOR:
case QIOR4:
- decode_qio_read_cmd(s);
+ switch ((s->pi->jedec >> 16) & 0xFF) {
+ case JEDEC_WINBOND:
+ case JEDEC_SPANSION:
+ s->needed_bytes = 6;
+ break;
+ default:
+ s->needed_bytes = get_addr_length(s);
+ /* Dummy cycles modeled with bytes writes instead of bits */
+ s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
+ }
+ s->pos = 0;
+ s->len = 0;
+ s->state = STATE_COLLECTING_DATA;
break;
case WRSR:
if (s->write_enable) {
- switch (get_man(s)) {
- case MAN_SPANSION:
- s->needed_bytes = 2;
- s->state = STATE_COLLECTING_DATA;
- break;
- case MAN_MACRONIX:
- s->needed_bytes = 2;
- s->state = STATE_COLLECTING_VAR_LEN_DATA;
- break;
- default:
- s->needed_bytes = 1;
- s->state = STATE_COLLECTING_DATA;
- }
+ s->needed_bytes = 1;
s->pos = 0;
+ s->len = 0;
+ s->state = STATE_COLLECTING_DATA;
}
break;
@@ -929,9 +702,6 @@ static void decode_new_cmd(Flash *s, uint32_t value)
case RDSR:
s->data[0] = (!!s->write_enable) << 1;
- if (get_man(s) == MAN_MACRONIX) {
- s->data[0] |= (!!s->quad_enable) << 6;
- }
s->pos = 0;
s->len = 1;
s->state = STATE_READING_DATA;
@@ -949,20 +719,17 @@ static void decode_new_cmd(Flash *s, uint32_t value)
case JEDEC_READ:
DB_PRINT_L(0, "populated jedec code\n");
- for (i = 0; i < s->pi->id_len; i++) {
- s->data[i] = s->pi->id[i];
+ s->data[0] = (s->pi->jedec >> 16) & 0xff;
+ s->data[1] = (s->pi->jedec >> 8) & 0xff;
+ s->data[2] = s->pi->jedec & 0xff;
+ if (s->pi->ext_jedec) {
+ s->data[3] = (s->pi->ext_jedec >> 8) & 0xff;
+ s->data[4] = s->pi->ext_jedec & 0xff;
+ s->len = 5;
+ } else {
+ s->len = 3;
}
-
- s->len = s->pi->id_len;
- s->pos = 0;
- s->state = STATE_READING_DATA;
- break;
-
- case RDCR:
- s->data[0] = s->volatile_cfg & 0xFF;
- s->data[0] |= (!!s->four_bytes_address_mode) << 5;
s->pos = 0;
- s->len = 1;
s->state = STATE_READING_DATA;
break;
@@ -1005,7 +772,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
s->state = STATE_READING_DATA;
break;
case WNVCR:
- if (s->write_enable && get_man(s) == MAN_NUMONYX) {
+ if (s->write_enable) {
s->needed_bytes = 2;
s->pos = 0;
s->len = 0;
@@ -1048,24 +815,6 @@ static void decode_new_cmd(Flash *s, uint32_t value)
reset_memory(s);
}
break;
- case RDCR_EQIO:
- switch (get_man(s)) {
- case MAN_SPANSION:
- s->data[0] = (!!s->quad_enable) << 1;
- s->pos = 0;
- s->len = 1;
- s->state = STATE_READING_DATA;
- break;
- case MAN_MACRONIX:
- s->quad_enable = true;
- break;
- default:
- break;
- }
- break;
- case RSTQIO:
- s->quad_enable = false;
- break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Unknown cmd %x\n", value);
break;
@@ -1077,9 +826,6 @@ static int m25p80_cs(SSISlave *ss, bool select)
Flash *s = M25P80(ss);
if (select) {
- if (s->state == STATE_COLLECTING_VAR_LEN_DATA) {
- complete_collecting_data(s);
- }
s->len = 0;
s->pos = 0;
s->state = STATE_IDLE;
@@ -1099,21 +845,20 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
switch (s->state) {
case STATE_PAGE_PROGRAM:
- DB_PRINT_L(1, "page program cur_addr=%#" PRIx32 " data=%" PRIx8 "\n",
+ DB_PRINT_L(1, "page program cur_addr=%#" PRIx64 " data=%" PRIx8 "\n",
s->cur_addr, (uint8_t)tx);
flash_write8(s, s->cur_addr, (uint8_t)tx);
- s->cur_addr = (s->cur_addr + 1) & (s->size - 1);
+ s->cur_addr++;
break;
case STATE_READ:
r = s->storage[s->cur_addr];
- DB_PRINT_L(1, "READ 0x%" PRIx32 "=%" PRIx8 "\n", s->cur_addr,
+ DB_PRINT_L(1, "READ 0x%" PRIx64 "=%" PRIx8 "\n", s->cur_addr,
(uint8_t)r);
- s->cur_addr = (s->cur_addr + 1) & (s->size - 1);
+ s->cur_addr = (s->cur_addr + 1) % s->size;
break;
case STATE_COLLECTING_DATA:
- case STATE_COLLECTING_VAR_LEN_DATA:
s->data[s->len] = (uint8_t)tx;
s->len++;
@@ -1140,8 +885,9 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
return r;
}
-static void m25p80_realize(SSISlave *ss, Error **errp)
+static int m25p80_init(SSISlave *ss)
{
+ DriveInfo *dinfo;
Flash *s = M25P80(ss);
M25P80Class *mc = M25P80_GET_CLASS(s);
@@ -1150,19 +896,29 @@ static void m25p80_realize(SSISlave *ss, Error **errp)
s->size = s->pi->sector_size * s->pi->n_sectors;
s->dirty_page = -1;
- if (s->blk) {
+ /* FIXME use a qdev drive property instead of drive_get_next() */
+ dinfo = drive_get_next(IF_MTD);
+
+ if (dinfo) {
DB_PRINT_L(0, "Binding to IF_MTD drive\n");
+ s->blk = blk_by_legacy_dinfo(dinfo);
+ blk_attach_dev_nofail(s->blk, s);
+
s->storage = blk_blockalign(s->blk, s->size);
- if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
- error_setg(errp, "failed to read the initial flash content");
- return;
+ /* FIXME: Move to late init */
+ if (blk_read(s->blk, 0, s->storage,
+ DIV_ROUND_UP(s->size, BDRV_SECTOR_SIZE))) {
+ fprintf(stderr, "Failed to initialize SPI flash!\n");
+ return 1;
}
} else {
DB_PRINT_L(0, "No BDRV - binding to RAM\n");
s->storage = blk_blockalign(NULL, s->size);
memset(s->storage, 0xFF, s->size);
}
+
+ return 0;
}
static void m25p80_reset(DeviceState *d)
@@ -1178,19 +934,13 @@ static void m25p80_pre_save(void *opaque)
}
static Property m25p80_properties[] = {
- /* This is default value for Micron flash */
DEFINE_PROP_UINT32("nonvolatile-cfg", Flash, nonvolatile_cfg, 0x8FFF),
- DEFINE_PROP_UINT8("spansion-cr1nv", Flash, spansion_cr1nv, 0x0),
- DEFINE_PROP_UINT8("spansion-cr2nv", Flash, spansion_cr2nv, 0x8),
- DEFINE_PROP_UINT8("spansion-cr3nv", Flash, spansion_cr3nv, 0x2),
- DEFINE_PROP_UINT8("spansion-cr4nv", Flash, spansion_cr4nv, 0x10),
- DEFINE_PROP_DRIVE("drive", Flash, blk),
DEFINE_PROP_END_OF_LIST(),
};
static const VMStateDescription vmstate_m25p80 = {
.name = "xilinx_spi",
- .version_id = 3,
+ .version_id = 2,
.minimum_version_id = 1,
.pre_save = m25p80_pre_save,
.fields = (VMStateField[]) {
@@ -1200,8 +950,7 @@ static const VMStateDescription vmstate_m25p80 = {
VMSTATE_UINT32(pos, Flash),
VMSTATE_UINT8(needed_bytes, Flash),
VMSTATE_UINT8(cmd_in_progress, Flash),
- VMSTATE_UNUSED(4),
- VMSTATE_UINT32(cur_addr, Flash),
+ VMSTATE_UINT64(cur_addr, Flash),
VMSTATE_BOOL(write_enable, Flash),
VMSTATE_BOOL_V(reset_enable, Flash, 2),
VMSTATE_UINT8_V(ear, Flash, 2),
@@ -1209,11 +958,6 @@ static const VMStateDescription vmstate_m25p80 = {
VMSTATE_UINT32_V(nonvolatile_cfg, Flash, 2),
VMSTATE_UINT32_V(volatile_cfg, Flash, 2),
VMSTATE_UINT32_V(enh_volatile_cfg, Flash, 2),
- VMSTATE_BOOL_V(quad_enable, Flash, 3),
- VMSTATE_UINT8_V(spansion_cr1nv, Flash, 3),
- VMSTATE_UINT8_V(spansion_cr2nv, Flash, 3),
- VMSTATE_UINT8_V(spansion_cr3nv, Flash, 3),
- VMSTATE_UINT8_V(spansion_cr4nv, Flash, 3),
VMSTATE_END_OF_LIST()
}
};
@@ -1224,7 +968,7 @@ static void m25p80_class_init(ObjectClass *klass, void *data)
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
M25P80Class *mc = M25P80_CLASS(klass);
- k->realize = m25p80_realize;
+ k->init = m25p80_init;
k->transfer = m25p80_transfer8;
k->set_cs = m25p80_cs;
k->cs_polarity = SSI_CS_LOW;
diff --git a/hw/block/nand.c b/hw/block/nand.c
index c69e6755d..29c659681 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -663,8 +663,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
sector = SECTOR(s->addr);
off = (s->addr & PAGE_MASK) + s->offset;
soff = SECTOR_OFFSET(s->addr);
- if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
- PAGE_SECTORS << BDRV_SECTOR_BITS) < 0) {
+ if (blk_read(s->blk, sector, iobuf, PAGE_SECTORS) < 0) {
printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
return;
}
@@ -676,24 +675,21 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
}
- if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
- PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) {
+ if (blk_write(s->blk, sector, iobuf, PAGE_SECTORS) < 0) {
printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
}
} else {
off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
sector = off >> 9;
soff = off & 0x1ff;
- if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
- (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS) < 0) {
+ if (blk_read(s->blk, sector, iobuf, PAGE_SECTORS + 2) < 0) {
printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
return;
}
mem_and(iobuf + soff, s->io, s->iolen);
- if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
- (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) {
+ if (blk_write(s->blk, sector, iobuf, PAGE_SECTORS + 2) < 0) {
printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
}
}
@@ -720,20 +716,17 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
i = SECTOR(addr);
page = SECTOR(addr + (1 << (ADDR_SHIFT + s->erase_shift)));
for (; i < page; i ++)
- if (blk_pwrite(s->blk, i << BDRV_SECTOR_BITS, iobuf,
- BDRV_SECTOR_SIZE, 0) < 0) {
+ if (blk_write(s->blk, i, iobuf, 1) < 0) {
printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
}
} else {
addr = PAGE_START(addr);
page = addr >> 9;
- if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf,
- BDRV_SECTOR_SIZE) < 0) {
+ if (blk_read(s->blk, page, iobuf, 1) < 0) {
printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
}
memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
- if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf,
- BDRV_SECTOR_SIZE, 0) < 0) {
+ if (blk_write(s->blk, page, iobuf, 1) < 0) {
printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
}
@@ -741,20 +734,18 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
i = (addr & ~0x1ff) + 0x200;
for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
i < addr; i += 0x200) {
- if (blk_pwrite(s->blk, i, iobuf, BDRV_SECTOR_SIZE, 0) < 0) {
+ if (blk_write(s->blk, i >> 9, iobuf, 1) < 0) {
printf("%s: write error in sector %" PRIu64 "\n",
__func__, i >> 9);
}
}
page = i >> 9;
- if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf,
- BDRV_SECTOR_SIZE) < 0) {
+ if (blk_read(s->blk, page, iobuf, 1) < 0) {
printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
}
memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
- if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf,
- BDRV_SECTOR_SIZE, 0) < 0) {
+ if (blk_write(s->blk, page, iobuf, 1) < 0) {
printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
}
}
@@ -769,8 +760,7 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
if (s->blk) {
if (s->mem_oob) {
- if (blk_pread(s->blk, SECTOR(addr) << BDRV_SECTOR_BITS, s->io,
- PAGE_SECTORS << BDRV_SECTOR_BITS) < 0) {
+ if (blk_read(s->blk, SECTOR(addr), s->io, PAGE_SECTORS) < 0) {
printf("%s: read error in sector %" PRIu64 "\n",
__func__, SECTOR(addr));
}
@@ -779,8 +769,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
OOB_SIZE);
s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset;
} else {
- if (blk_pread(s->blk, PAGE_START(addr), s->io,
- (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS) < 0) {
+ if (blk_read(s->blk, PAGE_START(addr) >> 9,
+ s->io, (PAGE_SECTORS + 2)) < 0) {
printf("%s: read error in sector %" PRIu64 "\n",
__func__, PAGE_START(addr) >> 9);
}
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index cef3bb42f..173988ee8 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -21,10 +21,10 @@
*/
#include "qemu/osdep.h"
-#include "hw/block/block.h"
-#include "hw/hw.h"
-#include "hw/pci/msix.h"
-#include "hw/pci/pci.h"
+#include <hw/block/block.h>
+#include <hw/hw.h>
+#include <hw/pci/msix.h>
+#include <hw/pci/pci.h>
#include "sysemu/sysemu.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
@@ -239,7 +239,7 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
uint8_t lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas);
uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds;
uint64_t data_size = (uint64_t)nlb << data_shift;
- uint64_t data_offset = slba << data_shift;
+ uint64_t aio_slba = slba << (data_shift - BDRV_SECTOR_BITS);
int is_write = rw->opcode == NVME_CMD_WRITE ? 1 : 0;
enum BlockAcctType acct = is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ;
@@ -258,8 +258,8 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
req->has_sg = true;
dma_acct_start(n->conf.blk, &req->acct, &req->qsg, acct);
req->aiocb = is_write ?
- dma_blk_write(n->conf.blk, &req->qsg, data_offset, nvme_rw_cb, req) :
- dma_blk_read(n->conf.blk, &req->qsg, data_offset, nvme_rw_cb, req);
+ dma_blk_write(n->conf.blk, &req->qsg, aio_slba, nvme_rw_cb, req) :
+ dma_blk_read(n->conf.blk, &req->qsg, aio_slba, nvme_rw_cb, req);
return NVME_NO_COMPLETE;
}
@@ -469,22 +469,19 @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeCmd *cmd)
return NVME_SUCCESS;
}
-static uint16_t nvme_identify_ctrl(NvmeCtrl *n, NvmeIdentify *c)
-{
- uint64_t prp1 = le64_to_cpu(c->prp1);
- uint64_t prp2 = le64_to_cpu(c->prp2);
-
- return nvme_dma_read_prp(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl),
- prp1, prp2);
-}
-
-static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeIdentify *c)
+static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
{
NvmeNamespace *ns;
+ NvmeIdentify *c = (NvmeIdentify *)cmd;
+ uint32_t cns = le32_to_cpu(c->cns);
uint32_t nsid = le32_to_cpu(c->nsid);
uint64_t prp1 = le64_to_cpu(c->prp1);
uint64_t prp2 = le64_to_cpu(c->prp2);
+ if (cns) {
+ return nvme_dma_read_prp(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl),
+ prp1, prp2);
+ }
if (nsid == 0 || nsid > n->num_namespaces) {
return NVME_INVALID_NSID | NVME_DNR;
}
@@ -494,48 +491,6 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeIdentify *c)
prp1, prp2);
}
-static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeIdentify *c)
-{
- static const int data_len = 4096;
- uint32_t min_nsid = le32_to_cpu(c->nsid);
- uint64_t prp1 = le64_to_cpu(c->prp1);
- uint64_t prp2 = le64_to_cpu(c->prp2);
- uint32_t *list;
- uint16_t ret;
- int i, j = 0;
-
- list = g_malloc0(data_len);
- for (i = 0; i < n->num_namespaces; i++) {
- if (i < min_nsid) {
- continue;
- }
- list[j++] = cpu_to_le32(i + 1);
- if (j == data_len / sizeof(uint32_t)) {
- break;
- }
- }
- ret = nvme_dma_read_prp(n, (uint8_t *)list, data_len, prp1, prp2);
- g_free(list);
- return ret;
-}
-
-
-static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
-{
- NvmeIdentify *c = (NvmeIdentify *)cmd;
-
- switch (le32_to_cpu(c->cns)) {
- case 0x00:
- return nvme_identify_ns(n, c);
- case 0x01:
- return nvme_identify_ctrl(n, c);
- case 0x02:
- return nvme_identify_nslist(n, c);
- default:
- return NVME_INVALID_FIELD | NVME_DNR;
- }
-}
-
static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
{
uint32_t dw10 = le32_to_cpu(cmd->cdw10);
@@ -848,7 +803,6 @@ static int nvme_init(PCIDevice *pci_dev)
return -1;
}
blkconf_blocksizes(&n->conf);
- blkconf_apply_backend_options(&n->conf);
pci_conf = pci_dev->config;
pci_conf[PCI_INTERRUPT_PIN] = 1;
@@ -954,7 +908,7 @@ static void nvme_class_init(ObjectClass *oc, void *data)
pc->class_id = PCI_CLASS_STORAGE_EXPRESS;
pc->vendor_id = PCI_VENDOR_ID_INTEL;
pc->device_id = 0x5845;
- pc->revision = 2;
+ pc->revision = 1;
pc->is_express = 1;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
index 8d8422739..883f4b1fa 100644
--- a/hw/block/onenand.c
+++ b/hw/block/onenand.c
@@ -224,8 +224,7 @@ static void onenand_reset(OneNANDState *s, int cold)
/* Lock the whole flash */
memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
- if (s->blk_cur && blk_pread(s->blk_cur, 0, s->boot[0],
- 8 << BDRV_SECTOR_BITS) < 0) {
+ if (s->blk_cur && blk_read(s->blk_cur, 0, s->boot[0], 8) < 0) {
hw_error("%s: Loading the BootRAM failed.\n", __func__);
}
}
@@ -241,11 +240,8 @@ static void onenand_system_reset(DeviceState *dev)
static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
void *dest)
{
- assert(UINT32_MAX >> BDRV_SECTOR_BITS > sec);
- assert(UINT32_MAX >> BDRV_SECTOR_BITS > secn);
if (s->blk_cur) {
- return blk_pread(s->blk_cur, sec << BDRV_SECTOR_BITS, dest,
- secn << BDRV_SECTOR_BITS) < 0;
+ return blk_read(s->blk_cur, sec, dest, secn) < 0;
} else if (sec + secn > s->secs_cur) {
return 1;
}
@@ -261,22 +257,19 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
int result = 0;
if (secn > 0) {
- uint32_t size = secn << BDRV_SECTOR_BITS;
- uint32_t offset = sec << BDRV_SECTOR_BITS;
- assert(UINT32_MAX >> BDRV_SECTOR_BITS > sec);
- assert(UINT32_MAX >> BDRV_SECTOR_BITS > secn);
+ uint32_t size = (uint32_t)secn * 512;
const uint8_t *sp = (const uint8_t *)src;
uint8_t *dp = 0;
if (s->blk_cur) {
dp = g_malloc(size);
- if (!dp || blk_pread(s->blk_cur, offset, dp, size) < 0) {
+ if (!dp || blk_read(s->blk_cur, sec, dp, secn) < 0) {
result = 1;
}
} else {
if (sec + secn > s->secs_cur) {
result = 1;
} else {
- dp = (uint8_t *)s->current + offset;
+ dp = (uint8_t *)s->current + (sec << 9);
}
}
if (!result) {
@@ -285,7 +278,7 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
dp[i] &= sp[i];
}
if (s->blk_cur) {
- result = blk_pwrite(s->blk_cur, offset, dp, size, 0) < 0;
+ result = blk_write(s->blk_cur, sec, dp, secn) < 0;
}
}
if (dp && s->blk_cur) {
@@ -302,8 +295,7 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
uint8_t buf[512];
if (s->blk_cur) {
- uint32_t offset = (s->secs_cur + (sec >> 5)) << BDRV_SECTOR_BITS;
- if (blk_pread(s->blk_cur, offset, buf, BDRV_SECTOR_SIZE) < 0) {
+ if (blk_read(s->blk_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) {
return 1;
}
memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
@@ -312,7 +304,7 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
} else {
memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
}
-
+
return 0;
}
@@ -323,12 +315,10 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
if (secn > 0) {
const uint8_t *sp = (const uint8_t *)src;
uint8_t *dp = 0, *dpp = 0;
- uint32_t offset = (s->secs_cur + (sec >> 5)) << BDRV_SECTOR_BITS;
- assert(UINT32_MAX >> BDRV_SECTOR_BITS > s->secs_cur + (sec >> 5));
if (s->blk_cur) {
dp = g_malloc(512);
if (!dp
- || blk_pread(s->blk_cur, offset, dp, BDRV_SECTOR_SIZE) < 0) {
+ || blk_read(s->blk_cur, s->secs_cur + (sec >> 5), dp, 1) < 0) {
result = 1;
} else {
dpp = dp + ((sec & 31) << 4);
@@ -346,8 +336,8 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
dpp[i] &= sp[i];
}
if (s->blk_cur) {
- result = blk_pwrite(s->blk_cur, offset, dp,
- BDRV_SECTOR_SIZE, 0) < 0;
+ result = blk_write(s->blk_cur, s->secs_cur + (sec >> 5),
+ dp, 1) < 0;
}
}
g_free(dp);
@@ -365,17 +355,14 @@ static inline int onenand_erase(OneNANDState *s, int sec, int num)
for (; num > 0; num--, sec++) {
if (s->blk_cur) {
int erasesec = s->secs_cur + (sec >> 5);
- if (blk_pwrite(s->blk_cur, sec << BDRV_SECTOR_BITS, blankbuf,
- BDRV_SECTOR_SIZE, 0) < 0) {
+ if (blk_write(s->blk_cur, sec, blankbuf, 1) < 0) {
goto fail;
}
- if (blk_pread(s->blk_cur, erasesec << BDRV_SECTOR_BITS, tmpbuf,
- BDRV_SECTOR_SIZE) < 0) {
+ if (blk_read(s->blk_cur, erasesec, tmpbuf, 1) < 0) {
goto fail;
}
memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
- if (blk_pwrite(s->blk_cur, erasesec << BDRV_SECTOR_BITS, tmpbuf,
- BDRV_SECTOR_SIZE, 0) < 0) {
+ if (blk_write(s->blk_cur, erasesec, tmpbuf, 1) < 0) {
goto fail;
}
} else {
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 62d7a5661..106a77523 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -45,7 +45,6 @@
#include "qemu/bitops.h"
#include "exec/address-spaces.h"
#include "qemu/host-utils.h"
-#include "qemu/log.h"
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
@@ -65,6 +64,7 @@ do { \
#define DPRINTF(fmt, ...) do { } while (0)
#endif
+#define TYPE_CFI_PFLASH01 "cfi.pflash01"
#define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
#define PFLASH_BE 0
@@ -413,11 +413,11 @@ static void pflash_update(pflash_t *pfl, int offset,
int offset_end;
if (pfl->blk) {
offset_end = offset + size;
- /* widen to sector boundaries */
- offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
- offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE);
- blk_pwrite(pfl->blk, offset, pfl->storage + offset,
- offset_end - offset, 0);
+ /* round to sectors */
+ offset = offset >> 9;
+ offset_end = (offset_end + 511) >> 9;
+ blk_write(pfl->blk, offset, pfl->storage + (offset << 9),
+ offset_end - offset);
}
}
@@ -739,7 +739,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
if (pfl->blk) {
/* read the initial flash content */
- ret = blk_pread(pfl->blk, 0, pfl->storage, total_len);
+ ret = blk_read(pfl->blk, 0, pfl->storage, total_len >> 9);
if (ret < 0) {
vmstate_unregister_ram(&pfl->mem, DEVICE(pfl));
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 4f6105cc5..b13172c6e 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -57,6 +57,7 @@ do { \
#define PFLASH_LAZY_ROMD_THRESHOLD 42
+#define TYPE_CFI_PFLASH02 "cfi.pflash02"
#define CFI_PFLASH02(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH02)
struct pflash_t {
@@ -252,11 +253,11 @@ static void pflash_update(pflash_t *pfl, int offset,
int offset_end;
if (pfl->blk) {
offset_end = offset + size;
- /* widen to sector boundaries */
- offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
- offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE);
- blk_pwrite(pfl->blk, offset, pfl->storage + offset,
- offset_end - offset, 0);
+ /* round to sectors */
+ offset = offset >> 9;
+ offset_end = (offset_end + 511) >> 9;
+ blk_write(pfl->blk, offset, pfl->storage + (offset << 9),
+ offset_end - offset);
}
}
@@ -621,7 +622,7 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
pfl->chip_len = chip_len;
if (pfl->blk) {
/* read the initial flash content */
- ret = blk_pread(pfl->blk, 0, pfl->storage, chip_len);
+ ret = blk_read(pfl->blk, 0, pfl->storage, chip_len >> 9);
if (ret < 0) {
vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl));
error_setg(errp, "failed to read the initial flash content");
diff --git a/hw/block/tc58128.c b/hw/block/tc58128.c
index 1d9f7ee00..7909d5041 100644
--- a/hw/block/tc58128.c
+++ b/hw/block/tc58128.c
@@ -45,7 +45,7 @@ static void init_dev(tc58128_dev * dev, const char *filename)
}
} else {
/* Build first block with number of blocks */
- blocks = DIV_ROUND_UP(ret, 528 * 32);
+ blocks = (ret + 528 * 32 - 1) / (528 * 32);
dev->flash_contents[0] = blocks & 0xff;
dev->flash_contents[1] = (blocks >> 8) & 0xff;
dev->flash_contents[2] = (blocks >> 16) & 0xff;
diff --git a/hw/block/trace-events b/hw/block/trace-events
deleted file mode 100644
index d0dd94ff0..000000000
--- a/hw/block/trace-events
+++ /dev/null
@@ -1,17 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/block/virtio-blk.c
-virtio_blk_req_complete(void *req, int status) "req %p status %d"
-virtio_blk_rw_complete(void *req, int ret) "req %p ret %d"
-virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu"
-virtio_blk_handle_read(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu"
-virtio_blk_submit_multireq(void *mrb, int start, int num_reqs, uint64_t offset, size_t size, bool is_write) "mrb %p start %d num_reqs %d offset %"PRIu64" size %zu is_write %d"
-
-# hw/block/dataplane/virtio-blk.c
-virtio_blk_data_plane_start(void *s) "dataplane %p"
-virtio_blk_data_plane_stop(void *s) "dataplane %p"
-virtio_blk_data_plane_process_request(void *s, unsigned int out_num, unsigned int in_num, unsigned int head) "dataplane %p out_num %u in_num %u head %u"
-
-# hw/block/hd-geometry.c
-hd_geometry_lchs_guess(void *blk, int cyls, int heads, int secs) "blk %p LCHS %d %d %d"
-hd_geometry_guess(void *blk, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "blk %p CHS %u %u %u trans %d"
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 331d7667e..3f88f8cf5 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -29,11 +29,9 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
-void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq,
- VirtIOBlockReq *req)
+void virtio_blk_init_request(VirtIOBlock *s, VirtIOBlockReq *req)
{
req->dev = s;
- req->vq = vq;
req->qiov.size = 0;
req->in_len = 0;
req->next = NULL;
@@ -55,11 +53,11 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
trace_virtio_blk_req_complete(req, status);
stb_p(&req->in->status, status);
- virtqueue_push(req->vq, &req->elem, req->in_len);
+ virtqueue_push(s->vq, &req->elem, req->in_len);
if (s->dataplane_started && !s->dataplane_disabled) {
- virtio_blk_data_plane_notify(s->dataplane, req->vq);
+ virtio_blk_data_plane_notify(s->dataplane);
} else {
- virtio_notify(vdev, req->vq);
+ virtio_notify(vdev, s->vq);
}
}
@@ -189,12 +187,12 @@ out:
#endif
-static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s, VirtQueue *vq)
+static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
{
- VirtIOBlockReq *req = virtqueue_pop(vq, sizeof(VirtIOBlockReq));
+ VirtIOBlockReq *req = virtqueue_pop(s->vq, sizeof(VirtIOBlockReq));
if (req) {
- virtio_blk_init_request(s, vq, req);
+ virtio_blk_init_request(s, req);
}
return req;
}
@@ -324,6 +322,7 @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
{
QEMUIOVector *qiov = &mrb->reqs[start]->qiov;
int64_t sector_num = mrb->reqs[start]->sector_num;
+ int nb_sectors = mrb->reqs[start]->qiov.size / BDRV_SECTOR_SIZE;
bool is_write = mrb->is_write;
if (num_reqs > 1) {
@@ -332,7 +331,7 @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
int tmp_niov = qiov->niov;
/* mrb->reqs[start]->qiov was initialized from external so we can't
- * modify it here. We need to initialize it locally and then add the
+ * modifiy it here. We need to initialize it locally and then add the
* external iovecs. */
qemu_iovec_init(qiov, niov);
@@ -344,22 +343,23 @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
qemu_iovec_concat(qiov, &mrb->reqs[i]->qiov, 0,
mrb->reqs[i]->qiov.size);
mrb->reqs[i - 1]->mr_next = mrb->reqs[i];
+ nb_sectors += mrb->reqs[i]->qiov.size / BDRV_SECTOR_SIZE;
}
+ assert(nb_sectors == qiov->size / BDRV_SECTOR_SIZE);
- trace_virtio_blk_submit_multireq(mrb, start, num_reqs,
- sector_num << BDRV_SECTOR_BITS,
- qiov->size, is_write);
+ trace_virtio_blk_submit_multireq(mrb, start, num_reqs, sector_num,
+ nb_sectors, is_write);
block_acct_merge_done(blk_get_stats(blk),
is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ,
num_reqs - 1);
}
if (is_write) {
- blk_aio_pwritev(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0,
- virtio_blk_rw_complete, mrb->reqs[start]);
- } else {
- blk_aio_preadv(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0,
+ blk_aio_writev(blk, sector_num, qiov, nb_sectors,
virtio_blk_rw_complete, mrb->reqs[start]);
+ } else {
+ blk_aio_readv(blk, sector_num, qiov, nb_sectors,
+ virtio_blk_rw_complete, mrb->reqs[start]);
}
}
@@ -384,7 +384,7 @@ static int multireq_compare(const void *a, const void *b)
void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
{
int i = 0, start = 0, num_reqs = 0, niov = 0, nb_sectors = 0;
- uint32_t max_transfer;
+ int max_xfer_len = 0;
int64_t sector_num = 0;
if (mrb->num_reqs == 1) {
@@ -393,7 +393,8 @@ void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
return;
}
- max_transfer = blk_get_max_transfer(mrb->reqs[0]->dev->blk);
+ max_xfer_len = blk_get_max_transfer_length(mrb->reqs[0]->dev->blk);
+ max_xfer_len = MIN_NON_ZERO(max_xfer_len, BDRV_REQUEST_MAX_SECTORS);
qsort(mrb->reqs, mrb->num_reqs, sizeof(*mrb->reqs),
&multireq_compare);
@@ -409,9 +410,8 @@ void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
*/
if (sector_num + nb_sectors != req->sector_num ||
niov > blk_get_max_iov(blk) - req->qiov.niov ||
- req->qiov.size > max_transfer ||
- nb_sectors > (max_transfer -
- req->qiov.size) / BDRV_SECTOR_SIZE) {
+ req->qiov.size / BDRV_SECTOR_SIZE > max_xfer_len ||
+ nb_sectors > max_xfer_len - req->qiov.size / BDRV_SECTOR_SIZE) {
submit_requests(blk, mrb, start, num_reqs, niov);
num_reqs = 0;
}
@@ -585,7 +585,7 @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
blk_io_plug(s->blk);
- while ((req = virtio_blk_get_request(s, vq))) {
+ while ((req = virtio_blk_get_request(s))) {
virtio_blk_handle_request(req, &mrb);
}
@@ -654,20 +654,15 @@ static void virtio_blk_reset(VirtIODevice *vdev)
{
VirtIOBlock *s = VIRTIO_BLK(vdev);
AioContext *ctx;
- VirtIOBlockReq *req;
+ /*
+ * This should cancel pending requests, but can't do nicely until there
+ * are per-device request lists.
+ */
ctx = blk_get_aio_context(s->blk);
aio_context_acquire(ctx);
blk_drain(s->blk);
- /* We drop queued requests after blk_drain() because blk_drain() itself can
- * produce them. */
- while (s->rq) {
- req = s->rq;
- s->rq = req->next;
- virtio_blk_free_request(req);
- }
-
if (s->dataplane) {
virtio_blk_data_plane_stop(s->dataplane);
}
@@ -715,7 +710,6 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
blkcfg.physical_block_exp = get_physical_block_exp(conf);
blkcfg.alignment_offset = 0;
blkcfg.wce = blk_enable_write_cache(s->blk);
- virtio_stw_p(vdev, &blkcfg.num_queues, s->conf.num_queues);
memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
}
@@ -759,9 +753,6 @@ static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features,
if (blk_is_read_only(s->blk)) {
virtio_add_feature(&features, VIRTIO_BLK_F_RO);
}
- if (s->conf.num_queues > 1) {
- virtio_add_feature(&features, VIRTIO_BLK_F_MQ);
- }
return features;
}
@@ -803,9 +794,14 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
}
}
-static void virtio_blk_save(QEMUFile *f, void *opaque, size_t size)
+static void virtio_blk_save(QEMUFile *f, void *opaque)
{
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
+ VirtIOBlock *s = VIRTIO_BLK(vdev);
+
+ if (s->dataplane) {
+ virtio_blk_data_plane_stop(s->dataplane);
+ }
virtio_save(vdev, f);
}
@@ -817,23 +813,21 @@ static void virtio_blk_save_device(VirtIODevice *vdev, QEMUFile *f)
while (req) {
qemu_put_sbyte(f, 1);
-
- if (s->conf.num_queues > 1) {
- qemu_put_be32(f, virtio_get_queue_index(req->vq));
- }
-
qemu_put_virtqueue_element(f, &req->elem);
req = req->next;
}
qemu_put_sbyte(f, 0);
}
-static int virtio_blk_load(QEMUFile *f, void *opaque, size_t size)
+static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIOBlock *s = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(s);
- return virtio_load(vdev, f, 2);
+ if (version_id != 2)
+ return -EINVAL;
+
+ return virtio_load(vdev, f, version_id);
}
static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f,
@@ -842,22 +836,9 @@ static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f,
VirtIOBlock *s = VIRTIO_BLK(vdev);
while (qemu_get_sbyte(f)) {
- unsigned nvqs = s->conf.num_queues;
- unsigned vq_idx = 0;
VirtIOBlockReq *req;
-
- if (nvqs > 1) {
- vq_idx = qemu_get_be32(f);
-
- if (vq_idx >= nvqs) {
- error_report("Invalid virtqueue index in request list: %#x",
- vq_idx);
- return -EINVAL;
- }
- }
-
req = qemu_get_virtqueue_element(f, sizeof(VirtIOBlockReq));
- virtio_blk_init_request(s, virtio_get_queue(vdev, vq_idx), req);
+ virtio_blk_init_request(s, req);
req->next = s->rq;
s->rq = req;
}
@@ -882,7 +863,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
VirtIOBlock *s = VIRTIO_BLK(dev);
VirtIOBlkConf *conf = &s->conf;
Error *err = NULL;
- unsigned i;
+ static int virtio_blk_id;
if (!conf->conf.blk) {
error_setg(errp, "drive property not set");
@@ -892,13 +873,8 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
error_setg(errp, "Device needs media, but drive is empty");
return;
}
- if (!conf->num_queues) {
- error_setg(errp, "num-queues property must be larger than 0");
- return;
- }
blkconf_serial(&conf->conf, &conf->serial);
- blkconf_apply_backend_options(&conf->conf);
s->original_wce = blk_enable_write_cache(conf->conf.blk);
blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, &err);
if (err) {
@@ -914,9 +890,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
s->rq = NULL;
s->sector_mask = (s->conf.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1;
- for (i = 0; i < conf->num_queues; i++) {
- virtio_add_queue_aio(vdev, 128, virtio_blk_handle_output);
- }
+ s->vq = virtio_add_queue(vdev, 128, virtio_blk_handle_output);
virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err);
if (err != NULL) {
error_propagate(errp, err);
@@ -925,6 +899,8 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
}
s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
+ register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
+ virtio_blk_save, virtio_blk_load, s);
blk_set_dev_ops(s->blk, &virtio_block_ops, s);
blk_set_guest_block_size(s->blk, s->conf.conf.logical_block_size);
@@ -939,6 +915,7 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
virtio_blk_data_plane_destroy(s->dataplane);
s->dataplane = NULL;
qemu_del_vm_change_state_handler(s->change);
+ unregister_savevm(dev, "virtio-blk", s);
blockdev_mark_auto_del(s->blk);
virtio_cleanup(vdev);
}
@@ -956,11 +933,8 @@ static void virtio_blk_instance_init(Object *obj)
DEVICE(obj), NULL);
}
-VMSTATE_VIRTIO_DEVICE(blk, 2, virtio_blk_load, virtio_blk_save);
-
static Property virtio_blk_properties[] = {
DEFINE_BLOCK_PROPERTIES(VirtIOBlock, conf.conf),
- DEFINE_BLOCK_ERROR_PROPERTIES(VirtIOBlock, conf.conf),
DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, conf.conf),
DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial),
DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true),
@@ -969,7 +943,6 @@ static Property virtio_blk_properties[] = {
#endif
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
true),
- DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, 1),
DEFINE_PROP_END_OF_LIST(),
};
@@ -979,7 +952,6 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->props = virtio_blk_properties;
- dc->vmsd = &vmstate_virtio_blk;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->realize = virtio_blk_device_realize;
vdc->unrealize = virtio_blk_device_unrealize;
diff --git a/hw/block/xen_blkif.h b/hw/block/xen_blkif.h
index 3300b6fc0..c68487cb3 100644
--- a/hw/block/xen_blkif.h
+++ b/hw/block/xen_blkif.h
@@ -1,45 +1,35 @@
-#ifndef XEN_BLKIF_H
-#define XEN_BLKIF_H
+#ifndef __XEN_BLKIF_H__
+#define __XEN_BLKIF_H__
#include <xen/io/ring.h>
#include <xen/io/blkif.h>
#include <xen/io/protocols.h>
-/*
- * Not a real protocol. Used to generate ring structs which contain
+/* Not a real protocol. Used to generate ring structs which contain
* the elements common to all protocols only. This way we get a
* compiler-checkable way to use common struct elements, so we can
- * avoid using switch(protocol) in a number of places.
- */
+ * avoid using switch(protocol) in a number of places. */
struct blkif_common_request {
- char dummy;
+ char dummy;
};
struct blkif_common_response {
- char dummy;
+ char dummy;
};
/* i386 protocol version */
#pragma pack(push, 4)
struct blkif_x86_32_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];
-};
-struct blkif_x86_32_request_discard {
- uint8_t operation; /* BLKIF_OP_DISCARD */
- uint8_t flag; /* nr_segments in request struct */
- 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) */
- uint64_t nr_sectors; /* # of contiguous sectors to discard */
+ 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];
};
struct blkif_x86_32_response {
- uint64_t id; /* copied from request */
- uint8_t operation; /* copied from request */
- int16_t status; /* BLKIF_RSP_??? */
+ uint64_t id; /* copied from request */
+ uint8_t operation; /* copied from request */
+ int16_t status; /* BLKIF_RSP_??? */
};
typedef struct blkif_x86_32_request blkif_x86_32_request_t;
typedef struct blkif_x86_32_response blkif_x86_32_response_t;
@@ -47,100 +37,83 @@ typedef struct blkif_x86_32_response blkif_x86_32_response_t;
/* x86_64 protocol version */
struct blkif_x86_64_request {
- uint8_t operation; /* BLKIF_OP_??? */
- uint8_t nr_segments; /* number of segments */
- blkif_vdev_t handle; /* only for read/write requests */
- uint64_t __attribute__((__aligned__(8))) id;
- blkif_sector_t sector_number; /* start sector idx on disk (r/w only) */
- struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-};
-struct blkif_x86_64_request_discard {
- uint8_t operation; /* BLKIF_OP_DISCARD */
- uint8_t flag; /* nr_segments in request struct */
- blkif_vdev_t handle; /* only for read/write requests */
- uint64_t __attribute__((__aligned__(8))) id;
- blkif_sector_t sector_number; /* start sector idx on disk (r/w only) */
- uint64_t nr_sectors; /* # of contiguous sectors to discard */
+ uint8_t operation; /* BLKIF_OP_??? */
+ uint8_t nr_segments; /* number of segments */
+ blkif_vdev_t handle; /* only for read/write requests */
+ uint64_t __attribute__((__aligned__(8))) id;
+ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
+ struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
};
struct blkif_x86_64_response {
- uint64_t __attribute__((__aligned__(8))) id;
- uint8_t operation; /* copied from request */
- int16_t status; /* BLKIF_RSP_??? */
+ uint64_t __attribute__((__aligned__(8))) id;
+ uint8_t operation; /* copied from request */
+ int16_t status; /* BLKIF_RSP_??? */
};
typedef struct blkif_x86_64_request blkif_x86_64_request_t;
typedef struct blkif_x86_64_response blkif_x86_64_response_t;
-DEFINE_RING_TYPES(blkif_common, struct blkif_common_request,
- struct blkif_common_response);
-DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request,
- struct blkif_x86_32_response);
-DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request,
- struct blkif_x86_64_response);
+DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, struct blkif_common_response);
+DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, struct blkif_x86_32_response);
+DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, struct blkif_x86_64_response);
union blkif_back_rings {
- blkif_back_ring_t native;
- blkif_common_back_ring_t common;
- blkif_x86_32_back_ring_t x86_32_part;
- blkif_x86_64_back_ring_t x86_64_part;
+ blkif_back_ring_t native;
+ blkif_common_back_ring_t common;
+ blkif_x86_32_back_ring_t x86_32_part;
+ blkif_x86_64_back_ring_t x86_64_part;
};
typedef union blkif_back_rings blkif_back_rings_t;
enum blkif_protocol {
- BLKIF_PROTOCOL_NATIVE = 1,
- BLKIF_PROTOCOL_X86_32 = 2,
- BLKIF_PROTOCOL_X86_64 = 3,
+ BLKIF_PROTOCOL_NATIVE = 1,
+ BLKIF_PROTOCOL_X86_32 = 2,
+ BLKIF_PROTOCOL_X86_64 = 3,
};
-static inline void blkif_get_x86_32_req(blkif_request_t *dst,
- blkif_x86_32_request_t *src)
+static inline void blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src)
{
- int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+ int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
- dst->operation = src->operation;
- dst->nr_segments = src->nr_segments;
- dst->handle = src->handle;
- dst->id = src->id;
- dst->sector_number = src->sector_number;
- /* Prevent the compiler from using src->... instead. */
- barrier();
- if (dst->operation == BLKIF_OP_DISCARD) {
- struct blkif_x86_32_request_discard *s = (void *)src;
- struct blkif_request_discard *d = (void *)dst;
- d->nr_sectors = s->nr_sectors;
- return;
- }
- if (n > dst->nr_segments) {
- n = dst->nr_segments;
- }
- for (i = 0; i < n; i++) {
- dst->seg[i] = src->seg[i];
- }
+ dst->operation = src->operation;
+ dst->nr_segments = src->nr_segments;
+ dst->handle = src->handle;
+ dst->id = src->id;
+ dst->sector_number = src->sector_number;
+ if (src->operation == BLKIF_OP_DISCARD) {
+ struct blkif_request_discard *s = (void *)src;
+ struct blkif_request_discard *d = (void *)dst;
+ d->nr_sectors = s->nr_sectors;
+ return;
+ }
+ /* prevent the compiler from optimizing the code and using src->nr_segments instead */
+ barrier();
+ if (n > dst->nr_segments)
+ n = dst->nr_segments;
+ for (i = 0; i < n; i++)
+ dst->seg[i] = src->seg[i];
}
-static inline void blkif_get_x86_64_req(blkif_request_t *dst,
- blkif_x86_64_request_t *src)
+static inline void blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src)
{
- int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+ int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
- dst->operation = src->operation;
- dst->nr_segments = src->nr_segments;
- dst->handle = src->handle;
- dst->id = src->id;
- dst->sector_number = src->sector_number;
- /* Prevent the compiler from using src->... instead. */
- barrier();
- if (dst->operation == BLKIF_OP_DISCARD) {
- struct blkif_x86_64_request_discard *s = (void *)src;
- struct blkif_request_discard *d = (void *)dst;
- d->nr_sectors = s->nr_sectors;
- return;
- }
- if (n > dst->nr_segments) {
- n = dst->nr_segments;
- }
- for (i = 0; i < n; i++) {
- dst->seg[i] = src->seg[i];
- }
+ dst->operation = src->operation;
+ dst->nr_segments = src->nr_segments;
+ dst->handle = src->handle;
+ dst->id = src->id;
+ dst->sector_number = src->sector_number;
+ if (src->operation == BLKIF_OP_DISCARD) {
+ struct blkif_request_discard *s = (void *)src;
+ struct blkif_request_discard *d = (void *)dst;
+ d->nr_sectors = s->nr_sectors;
+ return;
+ }
+ /* prevent the compiler from optimizing the code and using src->nr_segments instead */
+ barrier();
+ if (n > dst->nr_segments)
+ n = dst->nr_segments;
+ for (i = 0; i < n; i++)
+ dst->seg[i] = src->seg[i];
}
-#endif /* XEN_BLKIF_H */
+#endif /* __XEN_BLKIF_H__ */
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 3b8ad33fc..d4ce380fe 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include <sys/ioctl.h>
+#include <sys/mman.h>
#include <sys/uio.h>
#include "hw/hw.h"
@@ -553,8 +554,9 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct,
ioreq->v.size, BLOCK_ACCT_READ);
ioreq->aio_inflight++;
- blk_aio_preadv(blkdev->blk, ioreq->start, &ioreq->v, 0,
- qemu_aio_complete, ioreq);
+ blk_aio_readv(blkdev->blk, ioreq->start / BLOCK_SIZE,
+ &ioreq->v, ioreq->v.size / BLOCK_SIZE,
+ qemu_aio_complete, ioreq);
break;
case BLKIF_OP_WRITE:
case BLKIF_OP_FLUSH_DISKCACHE:
@@ -567,17 +569,17 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
ioreq->req.operation == BLKIF_OP_WRITE ?
BLOCK_ACCT_WRITE : BLOCK_ACCT_FLUSH);
ioreq->aio_inflight++;
- blk_aio_pwritev(blkdev->blk, ioreq->start, &ioreq->v, 0,
- qemu_aio_complete, ioreq);
+ blk_aio_writev(blkdev->blk, ioreq->start / BLOCK_SIZE,
+ &ioreq->v, ioreq->v.size / BLOCK_SIZE,
+ qemu_aio_complete, ioreq);
break;
case BLKIF_OP_DISCARD:
{
struct blkif_request_discard *discard_req = (void *)&ioreq->req;
ioreq->aio_inflight++;
- blk_aio_pdiscard(blkdev->blk,
- discard_req->sector_number << BDRV_SECTOR_BITS,
- discard_req->nr_sectors << BDRV_SECTOR_BITS,
- qemu_aio_complete, ioreq);
+ blk_aio_discard(blkdev->blk,
+ discard_req->sector_number, discard_req->nr_sectors,
+ qemu_aio_complete, ioreq);
break;
}
default:
@@ -679,8 +681,6 @@ static int blk_get_request(struct XenBlkDev *blkdev, struct ioreq *ioreq, RING_I
RING_GET_REQUEST(&blkdev->rings.x86_64_part, rc));
break;
}
- /* Prevent the compiler from accessing the on-ring fields instead. */
- barrier();
return 0;
}
diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c
index d688372ca..2e970b656 100644
--- a/hw/bt/hci-csr.c
+++ b/hw/bt/hci-csr.c
@@ -22,7 +22,6 @@
#include "qemu-common.h"
#include "sysemu/char.h"
#include "qemu/timer.h"
-#include "qemu/bswap.h"
#include "hw/irq.h"
#include "sysemu/bt.h"
#include "hw/bt.h"
@@ -39,14 +38,9 @@ struct csrhci_s {
int out_size;
uint8_t outfifo[FIFO_LEN * 2];
uint8_t inpkt[FIFO_LEN];
- enum {
- CSR_HDR_LEN,
- CSR_DATA_LEN,
- CSR_DATA
- } in_state;
int in_len;
int in_hdr;
- int in_needed;
+ int in_data;
QEMUTimer *out_tm;
int64_t baud_delay;
@@ -301,60 +295,38 @@ static int csrhci_data_len(const uint8_t *pkt)
exit(-1);
}
-static void csrhci_ready_for_next_inpkt(struct csrhci_s *s)
-{
- s->in_state = CSR_HDR_LEN;
- s->in_len = 0;
- s->in_needed = 2;
- s->in_hdr = INT_MAX;
-}
-
static int csrhci_write(struct CharDriverState *chr,
const uint8_t *buf, int len)
{
struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
- int total = 0;
+ int plen = s->in_len;
if (!s->enable)
return 0;
- for (;;) {
- int cnt = MIN(len, s->in_needed - s->in_len);
- if (cnt) {
- memcpy(s->inpkt + s->in_len, buf, cnt);
- s->in_len += cnt;
- buf += cnt;
- len -= cnt;
- total += cnt;
- }
-
- if (s->in_len < s->in_needed) {
- break;
- }
+ s->in_len += len;
+ memcpy(s->inpkt + plen, buf, len);
- if (s->in_state == CSR_HDR_LEN) {
+ while (1) {
+ if (s->in_len >= 2 && plen < 2)
s->in_hdr = csrhci_header_len(s->inpkt) + 1;
- assert(s->in_hdr >= s->in_needed);
- s->in_needed = s->in_hdr;
- s->in_state = CSR_DATA_LEN;
- continue;
- }
- if (s->in_state == CSR_DATA_LEN) {
- s->in_needed += csrhci_data_len(s->inpkt);
- /* hci_acl_hdr could specify more than 4096 bytes, so assert. */
- assert(s->in_needed <= sizeof(s->inpkt));
- s->in_state = CSR_DATA;
- continue;
- }
+ if (s->in_len >= s->in_hdr && plen < s->in_hdr)
+ s->in_data = csrhci_data_len(s->inpkt) + s->in_hdr;
- if (s->in_state == CSR_DATA) {
+ if (s->in_len >= s->in_data) {
csrhci_in_packet(s, s->inpkt);
- csrhci_ready_for_next_inpkt(s);
- }
+
+ memmove(s->inpkt, s->inpkt + s->in_len, s->in_len - s->in_data);
+ s->in_len -= s->in_data;
+ s->in_hdr = INT_MAX;
+ s->in_data = INT_MAX;
+ plen = 0;
+ } else
+ break;
}
- return total;
+ return len;
}
static void csrhci_out_hci_packet_event(void *opaque,
@@ -416,9 +388,11 @@ static void csrhci_reset(struct csrhci_s *s)
{
s->out_len = 0;
s->out_size = FIFO_LEN;
- csrhci_ready_for_next_inpkt(s);
+ s->in_len = 0;
s->baud_delay = NANOSECONDS_PER_SECOND;
s->enable = 0;
+ s->in_hdr = INT_MAX;
+ s->in_data = INT_MAX;
s->modem_state = 0;
/* After a while... (but sooner than 10ms) */
diff --git a/hw/bt/hci.c b/hw/bt/hci.c
index 351123fab..7d5220509 100644
--- a/hw/bt/hci.c
+++ b/hw/bt/hci.c
@@ -426,7 +426,11 @@ static void bt_submit_raw_acl(struct bt_piconet_s *net, int length, uint8_t *dat
* be continuously allocated. We do it though, to preserve similar
* behaviour between hosts. Some things, like the BD_ADDR cannot be
* preserved though (for example if a real hci is used). */
-#define HNDL(raw) cpu_to_le16(raw)
+#ifdef HOST_WORDS_BIGENDIAN
+# define HNDL(raw) bswap16(raw)
+#else
+# define HNDL(raw) (raw)
+#endif
static const uint8_t bt_event_reserved_mask[8] = {
0xff, 0x9f, 0xfb, 0xff, 0x07, 0x18, 0x00, 0x00,
@@ -1500,8 +1504,8 @@ static void bt_submit_hci(struct HCIInfo *info,
return;
#define PARAM(cmd, param) (((cmd##_cp *) data)->param)
-#define PARAM16(cmd, param) lduw_le_p(&PARAM(cmd, param))
-#define PARAMHANDLE(cmd) PARAM16(cmd, handle)
+#define PARAM16(cmd, param) le16_to_cpup(&PARAM(cmd, param))
+#define PARAMHANDLE(cmd) HNDL(PARAM(cmd, handle))
#define LENGTH_CHECK(cmd) if (length < sizeof(cmd##_cp)) goto short_hci
/* Note: the supported commands bitmask in bt_hci_read_local_commands_rp
* needs to be updated every time a command is implemented here! */
diff --git a/hw/bt/l2cap.c b/hw/bt/l2cap.c
index e34204514..806525194 100644
--- a/hw/bt/l2cap.c
+++ b/hw/bt/l2cap.c
@@ -20,7 +20,6 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/timer.h"
-#include "qemu/bswap.h"
#include "hw/bt.h"
#define L2CAP_CID_MAX 0x100 /* Between 0x40 and 0x10000 */
@@ -526,9 +525,9 @@ static int l2cap_channel_config(struct l2cap_instance_s *l2cap,
}
/* MTU */
- val = lduw_le_p(opt->val);
+ val = le16_to_cpup((void *) opt->val);
if (val < ch->min_mtu) {
- stw_le_p(opt->val, ch->min_mtu);
+ cpu_to_le16w((void *) opt->val, ch->min_mtu);
result = L2CAP_CONF_UNACCEPT;
break;
}
@@ -543,7 +542,7 @@ static int l2cap_channel_config(struct l2cap_instance_s *l2cap,
}
/* Flush Timeout */
- val = lduw_le_p(opt->val);
+ val = le16_to_cpup((void *) opt->val);
if (val < 0x0001) {
opt->val[0] = 0xff;
opt->val[1] = 0xff;
@@ -987,7 +986,7 @@ static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid,
static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
const l2cap_hdr *hdr, int len)
{
- uint16_t fcs = lduw_le_p(hdr->data + len - 2);
+ uint16_t fcs = le16_to_cpup((void *) (hdr->data + len - 2));
if (len < 4)
goto len_error;
@@ -1002,7 +1001,7 @@ static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
/* TODO: Signal an error? */
return;
}
- l2cap_sframe_in(ch, lduw_le_p(hdr->data));
+ l2cap_sframe_in(ch, le16_to_cpup((void *) hdr->data));
return;
}
@@ -1022,7 +1021,7 @@ static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
if (len - 6 > ch->mps)
goto len_error;
- ch->len_total = lduw_le_p(hdr->data + 2);
+ ch->len_total = le16_to_cpup((void *) (hdr->data + 2));
if (len >= 6 + ch->len_total)
goto seg_error;
diff --git a/hw/bt/sdp.c b/hw/bt/sdp.c
index f67b3b89c..be26009b0 100644
--- a/hw/bt/sdp.c
+++ b/hw/bt/sdp.c
@@ -19,7 +19,6 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
-#include "qemu/host-utils.h"
#include "hw/bt.h"
struct bt_l2cap_sdp_state_s {
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c
index 319f1652f..0394d11a8 100644
--- a/hw/char/bcm2835_aux.c
+++ b/hw/char/bcm2835_aux.c
@@ -22,7 +22,6 @@
#include "qemu/osdep.h"
#include "hw/char/bcm2835_aux.h"
-#include "qemu/log.h"
#define AUX_IRQ 0x0
#define AUX_ENABLES 0x4
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index e3bc52f7d..797787823 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -17,10 +17,6 @@
*/
#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "sysemu/char.h"
-#include "qemu/timer.h"
-#include "qemu/log.h"
#include "hw/char/cadence_uart.h"
#ifdef CADENCE_UART_ERR_DEBUG
@@ -288,19 +284,13 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
}
ret = qemu_chr_fe_write(s->chr, s->tx_fifo, s->tx_count);
-
- if (ret >= 0) {
- s->tx_count -= ret;
- memmove(s->tx_fifo, s->tx_fifo + ret, s->tx_count);
- }
+ s->tx_count -= ret;
+ memmove(s->tx_fifo, s->tx_fifo + ret, s->tx_count);
if (s->tx_count) {
- guint r = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
- cadence_uart_xmit, s);
- if (!r) {
- s->tx_count = 0;
- return FALSE;
- }
+ int r = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
+ cadence_uart_xmit, s);
+ assert(r);
}
uart_update_status(s);
@@ -474,6 +464,9 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
fifo_trigger_update, s);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
+
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
uart_event, s);
@@ -520,11 +513,6 @@ static const VMStateDescription vmstate_cadence_uart = {
}
};
-static Property cadence_uart_properties[] = {
- DEFINE_PROP_CHR("chardev", CadenceUARTState, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void cadence_uart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -532,8 +520,9 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data)
dc->realize = cadence_uart_realize;
dc->vmsd = &vmstate_cadence_uart;
dc->reset = cadence_uart_reset;
- dc->props = cadence_uart_properties;
- }
+ /* Reason: realize() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
+}
static const TypeInfo cadence_uart_info = {
.name = TYPE_CADENCE_UART,
diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c
index c7604e676..d3bc533d7 100644
--- a/hw/char/digic-uart.c
+++ b/hw/char/digic-uart.c
@@ -30,7 +30,6 @@
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "sysemu/char.h"
-#include "qemu/log.h"
#include "hw/char/digic-uart.h"
@@ -145,6 +144,8 @@ static void digic_uart_realize(DeviceState *dev, Error **errp)
{
DigicUartState *s = DIGIC_UART(dev);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
@@ -170,11 +171,6 @@ static const VMStateDescription vmstate_digic_uart = {
}
};
-static Property digic_uart_properties[] = {
- DEFINE_PROP_CHR("chardev", DigicUartState, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void digic_uart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -182,7 +178,8 @@ static void digic_uart_class_init(ObjectClass *klass, void *data)
dc->realize = digic_uart_realize;
dc->reset = digic_uart_reset;
dc->vmsd = &vmstate_digic_uart;
- dc->props = digic_uart_properties;
+ /* Reason: realize() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo digic_uart_info = {
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 31a5f902f..7bf09a007 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -983,40 +983,28 @@ void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq,
sysbus_mmio_map(s, 0, base);
}
-static void escc_init1(Object *obj)
-{
- ESCCState *s = ESCC(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- unsigned int i;
-
- for (i = 0; i < 2; i++) {
- sysbus_init_irq(dev, &s->chn[i].irq);
- s->chn[i].chn = 1 - i;
- }
- s->chn[0].otherchn = &s->chn[1];
- s->chn[1].otherchn = &s->chn[0];
-
- sysbus_init_mmio(dev, &s->mmio);
-}
-
-static void escc_realize(DeviceState *dev, Error **errp)
+static int escc_init1(SysBusDevice *dev)
{
ESCCState *s = ESCC(dev);
unsigned int i;
s->chn[0].disabled = s->disabled;
s->chn[1].disabled = s->disabled;
-
- memory_region_init_io(&s->mmio, OBJECT(dev), &escc_mem_ops, s, "escc",
- ESCC_SIZE << s->it_shift);
-
for (i = 0; i < 2; i++) {
+ sysbus_init_irq(dev, &s->chn[i].irq);
+ s->chn[i].chn = 1 - i;
+ s->chn[i].clock = s->frequency / 2;
if (s->chn[i].chr) {
- s->chn[i].clock = s->frequency / 2;
qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event, &s->chn[i]);
}
}
+ s->chn[0].otherchn = &s->chn[1];
+ s->chn[1].otherchn = &s->chn[0];
+
+ memory_region_init_io(&s->mmio, OBJECT(s), &escc_mem_ops, s, "escc",
+ ESCC_SIZE << s->it_shift);
+ sysbus_init_mmio(dev, &s->mmio);
if (s->chn[0].type == mouse) {
qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
@@ -1026,6 +1014,8 @@ static void escc_realize(DeviceState *dev, Error **errp)
s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]),
&sunkbd_handler);
}
+
+ return 0;
}
static Property escc_properties[] = {
@@ -1042,9 +1032,10 @@ static Property escc_properties[] = {
static void escc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = escc_init1;
dc->reset = escc_reset;
- dc->realize = escc_realize;
dc->vmsd = &vmstate_escc;
dc->props = escc_properties;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
@@ -1054,7 +1045,6 @@ static const TypeInfo escc_info = {
.name = TYPE_ESCC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ESCCState),
- .instance_init = escc_init1,
.class_init = escc_class_init,
};
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index 04ca04fe2..146b387e7 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -159,11 +159,6 @@ static const MemoryRegionOps ser_ops = {
}
};
-static Property etraxfs_ser_properties[] = {
- DEFINE_PROP_CHR("chardev", ETRAXSerial, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void serial_receive(void *opaque, const uint8_t *buf, int size)
{
ETRAXSerial *s = opaque;
@@ -214,42 +209,40 @@ static void etraxfs_ser_reset(DeviceState *d)
}
-static void etraxfs_ser_init(Object *obj)
+static int etraxfs_ser_init(SysBusDevice *dev)
{
- ETRAXSerial *s = ETRAX_SERIAL(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ ETRAXSerial *s = ETRAX_SERIAL(dev);
sysbus_init_irq(dev, &s->irq);
- memory_region_init_io(&s->mmio, obj, &ser_ops, s,
+ memory_region_init_io(&s->mmio, OBJECT(s), &ser_ops, s,
"etraxfs-serial", R_MAX * 4);
sysbus_init_mmio(dev, &s->mmio);
-}
-
-static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
-{
- ETRAXSerial *s = ETRAX_SERIAL(dev);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr,
serial_can_receive, serial_receive,
serial_event, s);
}
+ return 0;
}
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = etraxfs_ser_init;
dc->reset = etraxfs_ser_reset;
- dc->props = etraxfs_ser_properties;
- dc->realize = etraxfs_ser_realize;
+ /* Reason: init() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo etraxfs_ser_info = {
.name = TYPE_ETRAX_FS_SERIAL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ETRAXSerial),
- .instance_init = etraxfs_ser_init,
.class_init = etraxfs_ser_class_init,
};
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 44856d671..6df74ac7c 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -22,7 +22,6 @@
#include "hw/char/imx_serial.h"
#include "sysemu/sysemu.h"
#include "sysemu/char.h"
-#include "qemu/log.h"
#ifndef DEBUG_IMX_UART
#define DEBUG_IMX_UART 0
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index 9ead32af6..bc0ae4980 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -2,7 +2,7 @@
* QEMU GE IP-Octal 232 IndustryPack emulation
*
* Copyright (C) 2012 Igalia, S.L.
- * Author: Alberto Garcia <berto@igalia.com>
+ * Author: Alberto Garcia <agarcia@igalia.com>
*
* This code is licensed under the GNU GPL v2 or (at your option) any
* later version.
diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
index 28c2cf702..5bf8acfe8 100644
--- a/hw/char/lm32_juart.c
+++ b/hw/char/lm32_juart.c
@@ -114,13 +114,17 @@ static void juart_reset(DeviceState *d)
s->jrx = 0;
}
-static void lm32_juart_realize(DeviceState *dev, Error **errp)
+static int lm32_juart_init(SysBusDevice *dev)
{
LM32JuartState *s = LM32_JUART(dev);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
}
+
+ return 0;
}
static const VMStateDescription vmstate_lm32_juart = {
@@ -134,19 +138,16 @@ static const VMStateDescription vmstate_lm32_juart = {
}
};
-static Property lm32_juart_properties[] = {
- DEFINE_PROP_CHR("chardev", LM32JuartState, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void lm32_juart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = lm32_juart_init;
dc->reset = juart_reset;
dc->vmsd = &vmstate_lm32_juart;
- dc->props = lm32_juart_properties;
- dc->realize = lm32_juart_realize;
+ /* Reason: init() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo lm32_juart_info = {
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index b5c760dda..036813d0f 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -249,25 +249,23 @@ static void uart_reset(DeviceState *d)
s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
}
-static void lm32_uart_init(Object *obj)
+static int lm32_uart_init(SysBusDevice *dev)
{
- LM32UartState *s = LM32_UART(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ LM32UartState *s = LM32_UART(dev);
sysbus_init_irq(dev, &s->irq);
- memory_region_init_io(&s->iomem, obj, &uart_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s,
"uart", R_MAX * 4);
sysbus_init_mmio(dev, &s->iomem);
-}
-
-static void lm32_uart_realize(DeviceState *dev, Error **errp)
-{
- LM32UartState *s = LM32_UART(dev);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
+
+ return 0;
}
static const VMStateDescription vmstate_lm32_uart = {
@@ -280,26 +278,22 @@ static const VMStateDescription vmstate_lm32_uart = {
}
};
-static Property lm32_uart_properties[] = {
- DEFINE_PROP_CHR("chardev", LM32UartState, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void lm32_uart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = lm32_uart_init;
dc->reset = uart_reset;
dc->vmsd = &vmstate_lm32_uart;
- dc->props = lm32_uart_properties;
- dc->realize = lm32_uart_realize;
+ /* Reason: init() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo lm32_uart_info = {
.name = TYPE_LM32_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LM32UartState),
- .instance_init = lm32_uart_init,
.class_init = lm32_uart_class_init,
};
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index baddb3764..03b36b223 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -18,7 +18,7 @@
*
*
* Specification available at:
- * http://milkymist.walle.cc/socdoc/uart.pdf
+ * http://www.milkymist.org/socdoc/uart.pdf
*/
#include "qemu/osdep.h"
@@ -200,6 +200,8 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp)
{
MilkymistUartState *s = MILKYMIST_UART(dev);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
@@ -227,11 +229,6 @@ static const VMStateDescription vmstate_milkymist_uart = {
}
};
-static Property milkymist_uart_properties[] = {
- DEFINE_PROP_CHR("chardev", MilkymistUartState, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void milkymist_uart_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -239,7 +236,8 @@ static void milkymist_uart_class_init(ObjectClass *klass, void *data)
dc->realize = milkymist_uart_realize;
dc->reset = milkymist_uart_reset;
dc->vmsd = &vmstate_milkymist_uart;
- dc->props = milkymist_uart_properties;
+ /* Reason: realize() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo milkymist_uart_info = {
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index c0fbf8a87..210c87b4c 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -10,7 +10,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "sysemu/char.h"
-#include "qemu/log.h"
#define TYPE_PL011 "pl011"
#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
@@ -274,11 +273,6 @@ static const VMStateDescription vmstate_pl011 = {
}
};
-static Property pl011_properties[] = {
- DEFINE_PROP_CHR("chardev", PL011State, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void pl011_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@@ -300,6 +294,9 @@ static void pl011_realize(DeviceState *dev, Error **errp)
{
PL011State *s = PL011(dev);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
+
if (s->chr) {
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
pl011_event, s);
@@ -312,7 +309,8 @@ static void pl011_class_init(ObjectClass *oc, void *data)
dc->realize = pl011_realize;
dc->vmsd = &vmstate_pl011;
- dc->props = pl011_properties;
+ /* Reason: realize() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo pl011_arm_info = {
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index a22ad8d01..7d4ff8120 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -44,10 +44,6 @@ typedef struct SCLPConsoleLM {
uint8_t buf[SIZE_CONSOLE_BUFFER];
} SCLPConsoleLM;
-#define TYPE_SCLPLM_CONSOLE "sclplmconsole"
-#define SCLPLM_CONSOLE(obj) \
- OBJECT_CHECK(SCLPConsoleLM, (obj), TYPE_SCLPLM_CONSOLE)
-
/*
* Character layer call-back functions
*
@@ -120,7 +116,7 @@ static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
{
int len;
- SCLPConsoleLM *cons = SCLPLM_CONSOLE(event);
+ SCLPConsoleLM *cons = DO_UPCAST(SCLPConsoleLM, event, event);
len = cons->length;
/* data need to fit into provided SCLP buffer */
@@ -194,7 +190,7 @@ static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len)
int ret = 0;
const uint8_t *buf_offset;
- SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
+ SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
if (!scon->chr) {
/* If there's no backend, we can just say we consumed all data. */
@@ -248,7 +244,7 @@ static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh)
int errors = 0;
MDBO *mdbo;
SclpMsg *data = (SclpMsg *) ebh;
- SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
+ SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
len = be16_to_cpu(data->mdb.header.length);
if (len < sizeof(data->mdb.header)) {
@@ -317,7 +313,7 @@ static int console_init(SCLPEvent *event)
{
static bool console_available;
- SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
+ SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
if (console_available) {
error_report("Multiple line-mode operator consoles are not supported");
@@ -340,7 +336,7 @@ static int console_exit(SCLPEvent *event)
static void console_reset(DeviceState *dev)
{
SCLPEvent *event = SCLP_EVENT(dev);
- SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
+ SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
event->event_pending = false;
scon->length = 0;
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index d22464826..45997ff4a 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -13,7 +13,7 @@
*/
#include "qemu/osdep.h"
-#include "hw/qdev.h"
+#include <hw/qdev.h>
#include "qemu/thread.h"
#include "qemu/error-report.h"
@@ -40,10 +40,6 @@ typedef struct SCLPConsole {
bool notify; /* qemu_notify_event() req'd if true */
} SCLPConsole;
-#define TYPE_SCLP_CONSOLE "sclpconsole"
-#define SCLP_CONSOLE(obj) \
- OBJECT_CHECK(SCLPConsole, (obj), TYPE_SCLP_CONSOLE)
-
/* character layer call-back functions */
/* Return number of bytes that fit into iov buffer */
@@ -99,7 +95,7 @@ static unsigned int receive_mask(void)
static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
int avail)
{
- SCLPConsole *cons = SCLP_CONSOLE(event);
+ SCLPConsole *cons = DO_UPCAST(SCLPConsole, event, event);
/* first byte is hex 0 saying an ascii string follows */
*buf++ = '\0';
@@ -161,7 +157,7 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
size_t len)
{
- SCLPConsole *scon = SCLP_CONSOLE(event);
+ SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
if (!scon->chr) {
/* If there's no backend, we can just say we consumed all data. */
@@ -218,7 +214,7 @@ static int console_init(SCLPEvent *event)
{
static bool console_available;
- SCLPConsole *scon = SCLP_CONSOLE(event);
+ SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
if (console_available) {
error_report("Multiple VT220 operator consoles are not supported");
@@ -236,7 +232,7 @@ static int console_init(SCLPEvent *event)
static void console_reset(DeviceState *dev)
{
SCLPEvent *event = SCLP_EVENT(dev);
- SCLPConsole *scon = SCLP_CONSOLE(event);
+ SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
event->event_pending = false;
scon->iov_sclp = 0;
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 3442f47d3..6d815b5c6 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -106,7 +106,6 @@ do {} while (0)
#endif
static void serial_receive1(void *opaque, const uint8_t *buf, int size);
-static void serial_xmit(SerialState *s);
static inline void recv_fifo_put(SerialState *s, uint8_t chr)
{
@@ -224,20 +223,13 @@ static void serial_update_msl(SerialState *s)
}
}
-static gboolean serial_watch_cb(GIOChannel *chan, GIOCondition cond,
- void *opaque)
+static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
{
SerialState *s = opaque;
- s->watch_tag = 0;
- serial_xmit(s);
- return FALSE;
-}
-static void serial_xmit(SerialState *s)
-{
do {
assert(!(s->lsr & UART_LSR_TEMT));
- if (s->tsr_retry == 0) {
+ if (s->tsr_retry <= 0) {
assert(!(s->lsr & UART_LSR_THRE));
if (s->fcr & UART_FCR_FE) {
@@ -259,17 +251,17 @@ static void serial_xmit(SerialState *s)
if (s->mcr & UART_MCR_LOOP) {
/* in loopback mode, say that we just received a char */
serial_receive1(s, &s->tsr, 1);
- } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1 &&
- s->tsr_retry < MAX_XMIT_RETRY) {
- assert(s->watch_tag == 0);
- s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
- serial_watch_cb, s);
- if (s->watch_tag > 0) {
+ } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
+ if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
+ qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
+ serial_xmit, s) > 0) {
s->tsr_retry++;
- return;
+ return FALSE;
}
+ s->tsr_retry = 0;
+ } else {
+ s->tsr_retry = 0;
}
- s->tsr_retry = 0;
/* Transmit another byte if it is already available. It is only
possible when FIFO is enabled and not empty. */
@@ -277,8 +269,11 @@ static void serial_xmit(SerialState *s)
s->last_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->lsr |= UART_LSR_TEMT;
+
+ return FALSE;
}
+
/* Setter for FCR.
is_load flag means, that value is set while loading VM state
and interrupt should not be invoked */
@@ -335,8 +330,8 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
s->lsr &= ~UART_LSR_THRE;
s->lsr &= ~UART_LSR_TEMT;
serial_update_irq(s);
- if (s->tsr_retry == 0) {
- serial_xmit(s);
+ if (s->tsr_retry <= 0) {
+ serial_xmit(NULL, G_IO_OUT, s);
}
}
break;
@@ -644,31 +639,6 @@ static int serial_post_load(void *opaque, int version_id)
if (s->thr_ipending == -1) {
s->thr_ipending = ((s->iir & UART_IIR_ID) == UART_IIR_THRI);
}
-
- if (s->tsr_retry > 0) {
- /* tsr_retry > 0 implies LSR.TEMT = 0 (transmitter not empty). */
- if (s->lsr & UART_LSR_TEMT) {
- error_report("inconsistent state in serial device "
- "(tsr empty, tsr_retry=%d", s->tsr_retry);
- return -1;
- }
-
- if (s->tsr_retry > MAX_XMIT_RETRY) {
- s->tsr_retry = MAX_XMIT_RETRY;
- }
-
- assert(s->watch_tag == 0);
- s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
- serial_watch_cb, s);
- } else {
- /* tsr_retry == 0 implies LSR.TEMT = 1 (transmitter empty). */
- if (!(s->lsr & UART_LSR_TEMT)) {
- error_report("inconsistent state in serial device "
- "(tsr not empty, tsr_retry=0");
- return -1;
- }
- }
-
s->last_break_enable = (s->lcr >> 6) & 1;
/* Initialize fcr via setter to perform essential side-effects */
serial_write_fcr(s, s->fcr_vmstate);
@@ -715,7 +685,7 @@ static const VMStateDescription vmstate_serial_tsr = {
.minimum_version_id = 1,
.needed = serial_tsr_needed,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(tsr_retry, SerialState),
+ VMSTATE_INT32(tsr_retry, SerialState),
VMSTATE_UINT8(thr, SerialState),
VMSTATE_UINT8(tsr, SerialState),
VMSTATE_END_OF_LIST()
@@ -845,11 +815,6 @@ static void serial_reset(void *opaque)
{
SerialState *s = opaque;
- if (s->watch_tag > 0) {
- g_source_remove(s->watch_tag);
- s->watch_tag = 0;
- }
-
s->rbr = 0;
s->ier = 0;
s->iir = UART_IIR_NO_INT;
diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
index 15657abda..a94d61ceb 100644
--- a/hw/char/stm32f2xx_usart.c
+++ b/hw/char/stm32f2xx_usart.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
#include "hw/char/stm32f2xx_usart.h"
-#include "qemu/log.h"
#ifndef STM_USART_ERR_DEBUG
#define STM_USART_ERR_DEBUG 0
@@ -190,11 +189,6 @@ static const MemoryRegionOps stm32f2xx_usart_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static Property stm32f2xx_usart_properties[] = {
- DEFINE_PROP_CHR("chardev", STM32F2XXUsartState, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void stm32f2xx_usart_init(Object *obj)
{
STM32F2XXUsartState *s = STM32F2XX_USART(obj);
@@ -204,11 +198,9 @@ static void stm32f2xx_usart_init(Object *obj)
memory_region_init_io(&s->mmio, obj, &stm32f2xx_usart_ops, s,
TYPE_STM32F2XX_USART, 0x2000);
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
-}
-static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp)
-{
- STM32F2XXUsartState *s = STM32F2XX_USART(dev);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
@@ -221,8 +213,8 @@ static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = stm32f2xx_usart_reset;
- dc->props = stm32f2xx_usart_properties;
- dc->realize = stm32f2xx_usart_realize;
+ /* Reason: instance_init() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo stm32f2xx_usart_info = {
diff --git a/hw/char/trace-events b/hw/char/trace-events
deleted file mode 100644
index d53577c99..000000000
--- a/hw/char/trace-events
+++ /dev/null
@@ -1,49 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/char/virtio-serial-bus.c
-virtio_serial_send_control_event(unsigned int port, uint16_t event, uint16_t value) "port %u, event %u, value %u"
-virtio_serial_throttle_port(unsigned int port, bool throttle) "port %u, throttle %d"
-virtio_serial_handle_control_message(uint16_t event, uint16_t value) "event %u, value %u"
-virtio_serial_handle_control_message_port(unsigned int port) "port %u"
-
-# hw/char/virtio-console.c
-virtio_console_flush_buf(unsigned int port, size_t len, ssize_t ret) "port %u, in_len %zu, out_len %zd"
-virtio_console_chr_read(unsigned int port, int size) "port %u, size %d"
-virtio_console_chr_event(unsigned int port, int event) "port %u, event %d"
-
-# hw/char/grlib_apbuart.c
-grlib_apbuart_event(int event) "event:%d"
-grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x"
-grlib_apbuart_readl_unknown(uint64_t addr) "addr 0x%"PRIx64
-
-# hw/char/lm32_juart.c
-lm32_juart_get_jtx(uint32_t value) "jtx 0x%08x"
-lm32_juart_set_jtx(uint32_t value) "jtx 0x%08x"
-lm32_juart_get_jrx(uint32_t value) "jrx 0x%08x"
-lm32_juart_set_jrx(uint32_t value) "jrx 0x%08x"
-
-# hw/char/lm32_uart.c
-lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
-lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
-lm32_uart_irq_state(int level) "irq state %d"
-
-# hw/char/milkymist-uart.c
-milkymist_uart_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_uart_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_uart_raise_irq(void) "Raise IRQ"
-milkymist_uart_lower_irq(void) "Lower IRQ"
-
-# hw/char/escc.c
-escc_put_queue(char channel, int b) "channel %c put: 0x%02x"
-escc_get_queue(char channel, int val) "channel %c get 0x%02x"
-escc_update_irq(int irq) "IRQ = %d"
-escc_update_parameters(char channel, int speed, int parity, int data_bits, int stop_bits) "channel %c: speed=%d parity=%c data=%d stop=%d"
-escc_mem_writeb_ctrl(char channel, uint32_t reg, uint32_t val) "Write channel %c, reg[%d] = %2.2x"
-escc_mem_writeb_data(char channel, uint32_t val) "Write channel %c, ch %d"
-escc_mem_readb_ctrl(char channel, uint32_t reg, uint8_t val) "Read channel %c, reg[%d] = %2.2x"
-escc_mem_readb_data(char channel, uint32_t ret) "Read channel %c, ch %d"
-escc_serial_receive_byte(char channel, int ch) "channel %c put ch %d"
-escc_sunkbd_event_in(int ch, const char *name, int down) "QKeyCode 0x%2.2x [%s], down %d"
-escc_sunkbd_event_out(int ch) "Translated keycode 0x%2.2x"
-escc_kbd_command(int val) "Command %d"
-escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x"
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 4f0e03d3b..2e36481a7 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -85,9 +85,8 @@ static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
{
VirtConsole *vcon = VIRTIO_CONSOLE(port);
DeviceState *dev = DEVICE(port);
- VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
- if (vcon->chr && !k->is_console) {
+ if (vcon->chr) {
qemu_chr_fe_set_open(vcon->chr, guest_connected);
}
@@ -157,25 +156,9 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
}
if (vcon->chr) {
- /*
- * For consoles we don't block guest data transfer just
- * because nothing is connected - we'll just let it go
- * whetherever the chardev wants - /dev/null probably.
- *
- * For serial ports we need 100% reliable data transfer
- * so we use the opened/closed signals from chardev to
- * trigger open/close of the device
- */
- if (k->is_console) {
- vcon->chr->explicit_fe_open = 0;
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
- NULL, vcon);
- virtio_serial_open(port);
- } else {
- vcon->chr->explicit_fe_open = 1;
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
- chr_event, vcon);
- }
+ vcon->chr->explicit_fe_open = 1;
+ qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
+ vcon);
}
}
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index db57a3854..6e5de6dec 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -594,6 +594,12 @@ static void vser_reset(VirtIODevice *vdev)
guest_reset(vser);
}
+static void virtio_serial_save(QEMUFile *f, void *opaque)
+{
+ /* The virtio device */
+ virtio_save(VIRTIO_DEVICE(opaque), f);
+}
+
static void virtio_serial_save_device(VirtIODevice *vdev, QEMUFile *f)
{
VirtIOSerial *s = VIRTIO_SERIAL(vdev);
@@ -679,7 +685,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
s->post_load = NULL;
}
-static int fetch_active_ports_list(QEMUFile *f,
+static int fetch_active_ports_list(QEMUFile *f, int version_id,
VirtIOSerial *s, uint32_t nr_active_ports)
{
uint32_t i;
@@ -696,7 +702,6 @@ static int fetch_active_ports_list(QEMUFile *f,
/* Items in struct VirtIOSerialPort */
for (i = 0; i < nr_active_ports; i++) {
VirtIOSerialPort *port;
- uint32_t elem_popped;
uint32_t id;
id = qemu_get_be32(f);
@@ -709,29 +714,37 @@ static int fetch_active_ports_list(QEMUFile *f,
s->post_load->connected[i].port = port;
s->post_load->connected[i].host_connected = qemu_get_byte(f);
- qemu_get_be32s(f, &elem_popped);
- if (elem_popped) {
- qemu_get_be32s(f, &port->iov_idx);
- qemu_get_be64s(f, &port->iov_offset);
+ if (version_id > 2) {
+ uint32_t elem_popped;
- port->elem =
- qemu_get_virtqueue_element(f, sizeof(VirtQueueElement));
+ qemu_get_be32s(f, &elem_popped);
+ if (elem_popped) {
+ qemu_get_be32s(f, &port->iov_idx);
+ qemu_get_be64s(f, &port->iov_offset);
- /*
- * Port was throttled on source machine. Let's
- * unthrottle it here so data starts flowing again.
- */
- virtio_serial_throttle_port(port, false);
+ port->elem =
+ qemu_get_virtqueue_element(f, sizeof(VirtQueueElement));
+
+ /*
+ * Port was throttled on source machine. Let's
+ * unthrottle it here so data starts flowing again.
+ */
+ virtio_serial_throttle_port(port, false);
+ }
}
}
timer_mod(s->post_load->timer, 1);
return 0;
}
-static int virtio_serial_load(QEMUFile *f, void *opaque, size_t size)
+static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
{
+ if (version_id > 3) {
+ return -EINVAL;
+ }
+
/* The virtio device */
- return virtio_load(VIRTIO_DEVICE(opaque), f, 3);
+ return virtio_load(VIRTIO_DEVICE(opaque), f, version_id);
}
static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f,
@@ -743,6 +756,10 @@ static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f,
int ret;
uint32_t tmp;
+ if (version_id < 2) {
+ return 0;
+ }
+
/* Unused */
qemu_get_be16s(f, (uint16_t *) &tmp);
qemu_get_be16s(f, (uint16_t *) &tmp);
@@ -764,7 +781,7 @@ static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f,
qemu_get_be32s(f, &nr_active_ports);
if (nr_active_ports) {
- ret = fetch_active_ports_list(f, s, nr_active_ports);
+ ret = fetch_active_ports_list(f, version_id, s, nr_active_ports);
if (ret) {
return ret;
}
@@ -1032,6 +1049,13 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
vser->post_load = NULL;
+ /*
+ * Register for the savevm section with the virtio-console name
+ * to preserve backward compat
+ */
+ register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save,
+ virtio_serial_load, vser);
+
QLIST_INSERT_HEAD(&vserdevices.devices, vser, next);
}
@@ -1062,6 +1086,8 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp)
QLIST_REMOVE(vser, next);
+ unregister_savevm(dev, "virtio-console", vser);
+
g_free(vser->ivqs);
g_free(vser->ovqs);
g_free(vser->ports_map);
@@ -1074,9 +1100,6 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp)
virtio_cleanup(vdev);
}
-/* Note: 'console' is used for backwards compatibility */
-VMSTATE_VIRTIO_DEVICE(console, 3, virtio_serial_load, virtio_vmstate_save);
-
static Property virtio_serial_properties[] = {
DEFINE_PROP_UINT32("max_ports", VirtIOSerial, serial.max_virtserial_ports,
31),
@@ -1092,7 +1115,6 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data)
QLIST_INIT(&vserdevices.devices);
dc->props = virtio_serial_properties;
- dc->vmsd = &vmstate_virtio_console;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
vdc->realize = virtio_serial_device_realize;
vdc->unrealize = virtio_serial_device_unrealize;
diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
index 83108b0bd..cbf1dccbb 100644
--- a/hw/char/xen_console.c
+++ b/hw/char/xen_console.c
@@ -22,6 +22,7 @@
#include "qemu/osdep.h"
#include <sys/select.h>
#include <termios.h>
+#include <sys/mman.h>
#include "hw/hw.h"
#include "sysemu/char.h"
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index 4847efb29..911af4a0d 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -172,11 +172,6 @@ static const MemoryRegionOps uart_ops = {
}
};
-static Property xilinx_uartlite_properties[] = {
- DEFINE_PROP_CHR("chardev", XilinxUARTLite, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void uart_rx(void *opaque, const uint8_t *buf, int size)
{
XilinxUARTLite *s = opaque;
@@ -211,6 +206,8 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
{
XilinxUARTLite *s = XILINX_UARTLITE(dev);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
if (s->chr)
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
@@ -232,7 +229,8 @@ static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
dc->reset = xilinx_uartlite_reset;
dc->realize = xilinx_uartlite_realize;
- dc->props = xilinx_uartlite_properties;
+ /* Reason: realize() method uses qemu_char_get_next_serial() */
+ dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo xilinx_uartlite_info = {
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index cfd484039..abb3560be 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -1,11 +1,10 @@
# core qdev-related obj files, also used by *-user:
common-obj-y += qdev.o qdev-properties.o
-common-obj-y += bus.o
common-obj-y += fw-path-provider.o
# irq.o needed for qdev GPIO handling:
common-obj-y += irq.o
common-obj-y += hotplug.o
-obj-y += nmi.o
+common-obj-y += nmi.o
common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
common-obj-$(CONFIG_XILINX_AXI) += stream.o
@@ -15,5 +14,4 @@ common-obj-$(CONFIG_SOFTMMU) += machine.o
common-obj-$(CONFIG_SOFTMMU) += null-machine.o
common-obj-$(CONFIG_SOFTMMU) += loader.o
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
-common-obj-$(CONFIG_SOFTMMU) += register.o
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
diff --git a/hw/core/bus.c b/hw/core/bus.c
deleted file mode 100644
index 3e3f8ac74..000000000
--- a/hw/core/bus.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Dynamic device configuration and creation -- buses.
- *
- * Copyright (c) 2009 CodeSourcery
- *
- * 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 "qemu-common.h"
-#include "hw/qdev.h"
-#include "qapi/error.h"
-
-static void qbus_set_hotplug_handler_internal(BusState *bus, Object *handler,
- Error **errp)
-{
-
- object_property_set_link(OBJECT(bus), OBJECT(handler),
- QDEV_HOTPLUG_HANDLER_PROPERTY, errp);
-}
-
-void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, Error **errp)
-{
- qbus_set_hotplug_handler_internal(bus, OBJECT(handler), errp);
-}
-
-void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp)
-{
- qbus_set_hotplug_handler_internal(bus, OBJECT(bus), errp);
-}
-
-int qbus_walk_children(BusState *bus,
- qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
- qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
- void *opaque)
-{
- BusChild *kid;
- int err;
-
- if (pre_busfn) {
- err = pre_busfn(bus, opaque);
- if (err) {
- return err;
- }
- }
-
- QTAILQ_FOREACH(kid, &bus->children, sibling) {
- err = qdev_walk_children(kid->child,
- pre_devfn, pre_busfn,
- post_devfn, post_busfn, opaque);
- if (err < 0) {
- return err;
- }
- }
-
- if (post_busfn) {
- err = post_busfn(bus, opaque);
- if (err) {
- return err;
- }
- }
-
- return 0;
-}
-
-static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
-{
- const char *typename = object_get_typename(OBJECT(bus));
- BusClass *bc;
- char *buf;
- int i, len, bus_id;
-
- bus->parent = parent;
-
- if (name) {
- bus->name = g_strdup(name);
- } else if (bus->parent && bus->parent->id) {
- /* parent device has id -> use it plus parent-bus-id for bus name */
- bus_id = bus->parent->num_child_bus;
-
- len = strlen(bus->parent->id) + 16;
- buf = g_malloc(len);
- snprintf(buf, len, "%s.%d", bus->parent->id, bus_id);
- bus->name = buf;
- } else {
- /* no id -> use lowercase bus type plus global bus-id for bus name */
- bc = BUS_GET_CLASS(bus);
- bus_id = bc->automatic_ids++;
-
- len = strlen(typename) + 16;
- buf = g_malloc(len);
- len = snprintf(buf, len, "%s.%d", typename, bus_id);
- for (i = 0; i < len; i++) {
- buf[i] = qemu_tolower(buf[i]);
- }
- bus->name = buf;
- }
-
- if (bus->parent) {
- QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
- bus->parent->num_child_bus++;
- object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
- object_unref(OBJECT(bus));
- } else if (bus != sysbus_get_default()) {
- /* TODO: once all bus devices are qdevified,
- only reset handler for main_system_bus should be registered here. */
- qemu_register_reset(qbus_reset_all_fn, bus);
- }
-}
-
-static void bus_unparent(Object *obj)
-{
- BusState *bus = BUS(obj);
- BusChild *kid;
-
- while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
- DeviceState *dev = kid->child;
- object_unparent(OBJECT(dev));
- }
- if (bus->parent) {
- QLIST_REMOVE(bus, sibling);
- bus->parent->num_child_bus--;
- bus->parent = NULL;
- } else {
- assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
- qemu_unregister_reset(qbus_reset_all_fn, bus);
- }
-}
-
-void qbus_create_inplace(void *bus, size_t size, const char *typename,
- DeviceState *parent, const char *name)
-{
- object_initialize(bus, size, typename);
- qbus_realize(bus, parent, name);
-}
-
-BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
-{
- BusState *bus;
-
- bus = BUS(object_new(typename));
- qbus_realize(bus, parent, name);
-
- return bus;
-}
-
-static bool bus_get_realized(Object *obj, Error **errp)
-{
- BusState *bus = BUS(obj);
-
- return bus->realized;
-}
-
-static void bus_set_realized(Object *obj, bool value, Error **errp)
-{
- BusState *bus = BUS(obj);
- BusClass *bc = BUS_GET_CLASS(bus);
- BusChild *kid;
- Error *local_err = NULL;
-
- if (value && !bus->realized) {
- if (bc->realize) {
- bc->realize(bus, &local_err);
- }
-
- /* TODO: recursive realization */
- } else if (!value && bus->realized) {
- QTAILQ_FOREACH(kid, &bus->children, sibling) {
- DeviceState *dev = kid->child;
- object_property_set_bool(OBJECT(dev), false, "realized",
- &local_err);
- if (local_err != NULL) {
- break;
- }
- }
- if (bc->unrealize && local_err == NULL) {
- bc->unrealize(bus, &local_err);
- }
- }
-
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- return;
- }
-
- bus->realized = value;
-}
-
-static void qbus_initfn(Object *obj)
-{
- BusState *bus = BUS(obj);
-
- QTAILQ_INIT(&bus->children);
- object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY,
- TYPE_HOTPLUG_HANDLER,
- (Object **)&bus->hotplug_handler,
- object_property_allow_set_link,
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
- NULL);
- object_property_add_bool(obj, "realized",
- bus_get_realized, bus_set_realized, NULL);
-}
-
-static char *default_bus_get_fw_dev_path(DeviceState *dev)
-{
- return g_strdup(object_get_typename(OBJECT(dev)));
-}
-
-static void bus_class_init(ObjectClass *class, void *data)
-{
- BusClass *bc = BUS_CLASS(class);
-
- class->unparent = bus_unparent;
- bc->get_fw_dev_path = default_bus_get_fw_dev_path;
-}
-
-static void qbus_finalize(Object *obj)
-{
- BusState *bus = BUS(obj);
-
- g_free((char *)bus->name);
-}
-
-static const TypeInfo bus_info = {
- .name = TYPE_BUS,
- .parent = TYPE_OBJECT,
- .instance_size = sizeof(BusState),
- .abstract = true,
- .class_size = sizeof(BusClass),
- .instance_init = qbus_initfn,
- .instance_finalize = qbus_finalize,
- .class_init = bus_class_init,
-};
-
-static void bus_register_types(void)
-{
- type_register_static(&bus_info);
-}
-
-type_init(bus_register_types)
diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c
index 17ac98668..645cfca1b 100644
--- a/hw/core/hotplug.c
+++ b/hw/core/hotplug.c
@@ -13,17 +13,6 @@
#include "hw/hotplug.h"
#include "qemu/module.h"
-void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
- DeviceState *plugged_dev,
- Error **errp)
-{
- HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
-
- if (hdc->pre_plug) {
- hdc->pre_plug(plug_handler, plugged_dev, errp);
- }
-}
-
void hotplug_handler_plug(HotplugHandler *plug_handler,
DeviceState *plugged_dev,
Error **errp)
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 53e0e4155..c0499571c 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -914,16 +914,10 @@ int rom_add_file(const char *file, const char *fw_dir,
err:
if (fd != -1)
close(fd);
-
g_free(rom->data);
g_free(rom->path);
g_free(rom->name);
- if (fw_dir) {
- g_free(rom->fw_dir);
- g_free(rom->fw_file);
- }
g_free(rom);
-
return -1;
}
diff --git a/hw/core/machine.c b/hw/core/machine.c
index e5a456f21..6dbbc85b9 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -65,9 +65,6 @@ static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
ms->kernel_irqchip_split = true;
break;
default:
- /* The value was checked in visit_type_OnOffSplit() above. If
- * we get here, then something is wrong in QEMU.
- */
abort();
}
}
@@ -260,47 +257,47 @@ static void machine_set_usb(Object *obj, bool value, Error **errp)
ms->usb_disabled = !value;
}
-static bool machine_get_graphics(Object *obj, Error **errp)
+static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
{
MachineState *ms = MACHINE(obj);
- return ms->enable_graphics;
+ return ms->igd_gfx_passthru;
}
-static void machine_set_graphics(Object *obj, bool value, Error **errp)
+static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
{
MachineState *ms = MACHINE(obj);
- ms->enable_graphics = value;
+ ms->igd_gfx_passthru = value;
}
-static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
+static char *machine_get_firmware(Object *obj, Error **errp)
{
MachineState *ms = MACHINE(obj);
- return ms->igd_gfx_passthru;
+ return g_strdup(ms->firmware);
}
-static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
+static void machine_set_firmware(Object *obj, const char *value, Error **errp)
{
MachineState *ms = MACHINE(obj);
- ms->igd_gfx_passthru = value;
+ g_free(ms->firmware);
+ ms->firmware = g_strdup(value);
}
-static char *machine_get_firmware(Object *obj, Error **errp)
+static bool machine_get_iommu(Object *obj, Error **errp)
{
MachineState *ms = MACHINE(obj);
- return g_strdup(ms->firmware);
+ return ms->iommu;
}
-static void machine_set_firmware(Object *obj, const char *value, Error **errp)
+static void machine_set_iommu(Object *obj, bool value, Error **errp)
{
MachineState *ms = MACHINE(obj);
- g_free(ms->firmware);
- ms->firmware = g_strdup(value);
+ ms->iommu = value;
}
static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
@@ -385,7 +382,6 @@ static void machine_initfn(Object *obj)
ms->kvm_shadow_mem = -1;
ms->dump_guest_core = true;
ms->mem_merge = true;
- ms->enable_graphics = true;
object_property_add_str(obj, "accel",
machine_get_accel, machine_set_accel, NULL);
@@ -464,12 +460,6 @@ static void machine_initfn(Object *obj)
object_property_set_description(obj, "usb",
"Set on/off to enable/disable usb",
NULL);
- object_property_add_bool(obj, "graphics",
- machine_get_graphics,
- machine_set_graphics, NULL);
- object_property_set_description(obj, "graphics",
- "Set on/off to enable/disable graphics emulation",
- NULL);
object_property_add_bool(obj, "igd-passthru",
machine_get_igd_gfx_passthru,
machine_set_igd_gfx_passthru, NULL);
@@ -482,6 +472,12 @@ static void machine_initfn(Object *obj)
object_property_set_description(obj, "firmware",
"Firmware image",
NULL);
+ object_property_add_bool(obj, "iommu",
+ machine_get_iommu,
+ machine_set_iommu, NULL);
+ object_property_set_description(obj, "iommu",
+ "Set on/off to enable/disable Intel IOMMU (VT-d)",
+ NULL);
object_property_add_bool(obj, "suppress-vmdesc",
machine_get_suppress_vmdesc,
machine_set_suppress_vmdesc, NULL);
@@ -554,33 +550,6 @@ bool machine_mem_merge(MachineState *machine)
return machine->mem_merge;
}
-static void machine_class_finalize(ObjectClass *klass, void *data)
-{
- MachineClass *mc = MACHINE_CLASS(klass);
-
- if (mc->compat_props) {
- g_array_free(mc->compat_props, true);
- }
-}
-
-void machine_register_compat_props(MachineState *machine)
-{
- MachineClass *mc = MACHINE_GET_CLASS(machine);
- int i;
- GlobalProperty *p;
-
- if (!mc->compat_props) {
- return;
- }
-
- for (i = 0; i < mc->compat_props->len; i++) {
- p = g_array_index(mc->compat_props, GlobalProperty *, i);
- /* Machine compat_props must never cause errors: */
- p->errp = &error_abort;
- qdev_prop_register_global(p);
- }
-}
-
static const TypeInfo machine_info = {
.name = TYPE_MACHINE,
.parent = TYPE_OBJECT,
@@ -588,7 +557,6 @@ static const TypeInfo machine_info = {
.class_size = sizeof(MachineClass),
.class_init = machine_class_init,
.class_base_init = machine_class_base_init,
- .class_finalize = machine_class_finalize,
.instance_size = sizeof(MachineState),
.instance_init = machine_initfn,
.instance_finalize = machine_finalize,
diff --git a/hw/core/nmi.c b/hw/core/nmi.c
index bfd0896da..e8bcc4177 100644
--- a/hw/core/nmi.c
+++ b/hw/core/nmi.c
@@ -73,6 +73,25 @@ void nmi_monitor_handle(int cpu_index, Error **errp)
}
}
+void inject_nmi(void)
+{
+#if defined(TARGET_I386)
+ CPUState *cs;
+
+ CPU_FOREACH(cs) {
+ X86CPU *cpu = X86_CPU(cs);
+
+ if (!cpu->apic_state) {
+ cpu_interrupt(cs, CPU_INTERRUPT_NMI);
+ } else {
+ apic_deliver_nmi(cpu->apic_state);
+ }
+ }
+#else
+ nmi_monitor_handle(0, NULL);
+#endif
+}
+
static const TypeInfo nmi_info = {
.name = TYPE_NMI,
.parent = TYPE_INTERFACE,
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
index 30829ee97..153c83513 100644
--- a/hw/core/ptimer.c
+++ b/hw/core/ptimer.c
@@ -35,9 +35,6 @@ static void ptimer_trigger(ptimer_state *s)
static void ptimer_reload(ptimer_state *s)
{
- uint32_t period_frac = s->period_frac;
- uint64_t period = s->period;
-
if (s->delta == 0) {
ptimer_trigger(s);
s->delta = s->limit;
@@ -48,24 +45,10 @@ static void ptimer_reload(ptimer_state *s)
return;
}
- /*
- * Artificially limit timeout rate to something
- * achievable under QEMU. Otherwise, QEMU spends all
- * its time generating timer interrupts, and there
- * is no forward progress.
- * About ten microseconds is the fastest that really works
- * on the current generation of host machines.
- */
-
- if (s->enabled == 1 && (s->delta * period < 10000) && !use_icount) {
- period = 10000 / s->delta;
- period_frac = 0;
- }
-
s->last_event = s->next_event;
- s->next_event = s->last_event + s->delta * period;
- if (period_frac) {
- s->next_event += ((int64_t)period_frac * s->delta) >> 32;
+ s->next_event = s->last_event + s->delta * s->period;
+ if (s->period_frac) {
+ s->next_event += ((int64_t)s->period_frac * s->delta) >> 32;
}
timer_mod(s->timer, s->next_event);
}
@@ -84,16 +67,14 @@ static void ptimer_tick(void *opaque)
uint64_t ptimer_get_count(ptimer_state *s)
{
+ int64_t now;
uint64_t counter;
if (s->enabled) {
- int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- int64_t next = s->next_event;
- bool expired = (now - next >= 0);
- bool oneshot = (s->enabled == 2);
-
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* Figure out the current counter value. */
- if (expired) {
+ if (now - s->next_event > 0
+ || s->period == 0) {
/* Prevent timer underflowing if it should already have
triggered. */
counter = 0;
@@ -102,13 +83,6 @@ uint64_t ptimer_get_count(ptimer_state *s)
uint64_t div;
int clz1, clz2;
int shift;
- uint32_t period_frac = s->period_frac;
- uint64_t period = s->period;
-
- if (!oneshot && (s->delta * period < 10000) && !use_icount) {
- period = 10000 / s->delta;
- period_frac = 0;
- }
/* We need to divide time by period, where time is stored in
rem (64-bit integer) and period is stored in period/period_frac
@@ -120,8 +94,8 @@ uint64_t ptimer_get_count(ptimer_state *s)
backwards.
*/
- rem = next - now;
- div = period;
+ rem = s->next_event - now;
+ div = s->period;
clz1 = clz64(rem);
clz2 = clz64(div);
@@ -130,13 +104,13 @@ uint64_t ptimer_get_count(ptimer_state *s)
rem <<= shift;
div <<= shift;
if (shift >= 32) {
- div |= ((uint64_t)period_frac << (shift - 32));
+ div |= ((uint64_t)s->period_frac << (shift - 32));
} else {
if (shift != 0)
- div |= (period_frac >> (32 - shift));
+ div |= (s->period_frac >> (32 - shift));
/* Look at remaining bits of period_frac and round div up if
necessary. */
- if ((uint32_t)(period_frac << shift))
+ if ((uint32_t)(s->period_frac << shift))
div += 1;
}
counter = rem / div;
@@ -158,17 +132,16 @@ void ptimer_set_count(ptimer_state *s, uint64_t count)
void ptimer_run(ptimer_state *s, int oneshot)
{
- bool was_disabled = !s->enabled;
-
- if (was_disabled && s->period == 0) {
+ if (s->enabled) {
+ return;
+ }
+ if (s->period == 0) {
fprintf(stderr, "Timer with period zero, disabling\n");
return;
}
s->enabled = oneshot ? 2 : 1;
- if (was_disabled) {
- s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- ptimer_reload(s);
- }
+ s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ ptimer_reload(s);
}
/* Pause a timer. Note that this may cause it to "lose" time, even if it
@@ -186,7 +159,6 @@ void ptimer_stop(ptimer_state *s)
/* Set counter increment interval in nanoseconds. */
void ptimer_set_period(ptimer_state *s, int64_t period)
{
- s->delta = ptimer_get_count(s);
s->period = period;
s->period_frac = 0;
if (s->enabled) {
@@ -198,7 +170,6 @@ void ptimer_set_period(ptimer_state *s, int64_t period)
/* Set counter frequency in Hz. */
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
{
- s->delta = ptimer_get_count(s);
s->period = 1000000000ll / freq;
s->period_frac = (1000000000ll << 32) / freq;
if (s->enabled) {
@@ -211,6 +182,19 @@ void ptimer_set_freq(ptimer_state *s, uint32_t freq)
count = limit. */
void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
{
+ /*
+ * Artificially limit timeout rate to something
+ * achievable under QEMU. Otherwise, QEMU spends all
+ * its time generating timer interrupts, and there
+ * is no forward progress.
+ * About ten microseconds is the fastest that really works
+ * on the current generation of host machines.
+ */
+
+ if (!use_icount && limit * s->period < 10000 && s->period) {
+ limit = 10000 / s->period;
+ }
+
s->limit = limit;
if (reload)
s->delta = limit;
@@ -220,11 +204,6 @@ void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
}
}
-uint64_t ptimer_get_limit(ptimer_state *s)
-{
- return s->limit;
-}
-
const VMStateDescription vmstate_ptimer = {
.name = "ptimer",
.version_id = 1,
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index e55afe6bf..891219ae0 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -1,5 +1,5 @@
/*
- * qdev property parsing
+ * qdev property parsing and global properties
* (parts specific for qemu-system-*)
*
* This file is based on code from hw/qdev-properties.c from
@@ -72,26 +72,17 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr,
const char *propname, Error **errp)
{
BlockBackend *blk;
- bool blk_created = false;
blk = blk_by_name(str);
if (!blk) {
- BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
- if (bs) {
- blk = blk_new();
- blk_insert_bs(blk, bs);
- blk_created = true;
- }
- }
- if (!blk) {
error_setg(errp, "Property '%s.%s' can't find value '%s'",
object_get_typename(OBJECT(dev)), propname, str);
- goto fail;
+ return;
}
if (blk_attach_dev(blk, dev) < 0) {
DriveInfo *dinfo = blk_legacy_dinfo(blk);
- if (dinfo && dinfo->type != IF_NONE) {
+ if (dinfo->type != IF_NONE) {
error_setg(errp, "Drive '%s' is already in use because "
"it has been automatically connected to another "
"device (did you need 'if=none' in the drive options?)",
@@ -100,16 +91,9 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr,
error_setg(errp, "Drive '%s' is already in use by another device",
str);
}
- goto fail;
+ return;
}
-
*ptr = blk;
-
-fail:
- if (blk_created) {
- /* If we need to keep a reference, blk_attach_dev() took it */
- blk_unref(blk);
- }
}
static void release_drive(Object *obj, const char *name, void *opaque)
@@ -119,23 +103,14 @@ static void release_drive(Object *obj, const char *name, void *opaque)
BlockBackend **ptr = qdev_get_prop_ptr(dev, prop);
if (*ptr) {
- blockdev_auto_del(*ptr);
blk_detach_dev(*ptr, dev);
+ blockdev_auto_del(*ptr);
}
}
static char *print_drive(void *ptr)
{
- const char *name;
-
- name = blk_name(ptr);
- if (!*name) {
- BlockDriverState *bs = blk_bs(ptr);
- if (bs) {
- name = bdrv_get_node_name(bs);
- }
- }
- return g_strdup(name);
+ return g_strdup(blk_name(ptr));
}
static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque,
@@ -152,7 +127,7 @@ static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque,
PropertyInfo qdev_prop_drive = {
.name = "str",
- .description = "Node name or ID of a block device to use as a backend",
+ .description = "ID of a drive to use as a backend",
.get = get_drive,
.set = set_drive,
.release = release_drive,
@@ -256,7 +231,7 @@ static void set_netdev(Object *obj, Visitor *v, const char *name,
}
queues = qemu_find_net_clients_except(str, peers,
- NET_CLIENT_DRIVER_NIC,
+ NET_CLIENT_OPTIONS_KIND_NIC,
MAX_QUEUE_NUM);
if (queues == 0) {
err = -ENOENT;
@@ -387,19 +362,8 @@ PropertyInfo qdev_prop_vlan = {
void qdev_prop_set_drive(DeviceState *dev, const char *name,
BlockBackend *value, Error **errp)
{
- const char *ref = "";
-
- if (value) {
- ref = blk_name(value);
- if (!*ref) {
- BlockDriverState *bs = blk_bs(value);
- if (bs) {
- ref = bdrv_get_node_name(bs);
- }
- }
- }
-
- object_property_set_str(OBJECT(dev), ref, name, errp);
+ object_property_set_str(OBJECT(dev), value ? blk_name(value) : "",
+ name, errp);
}
void qdev_prop_set_chr(DeviceState *dev, const char *name,
@@ -430,3 +394,22 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
}
nd->instantiated = 1;
}
+
+static int qdev_add_one_global(void *opaque, QemuOpts *opts, Error **errp)
+{
+ GlobalProperty *g;
+
+ g = g_malloc0(sizeof(*g));
+ g->driver = qemu_opt_get(opts, "driver");
+ g->property = qemu_opt_get(opts, "property");
+ g->value = qemu_opt_get(opts, "value");
+ g->user_provided = true;
+ qdev_prop_register_global(g);
+ return 0;
+}
+
+void qemu_add_globals(void)
+{
+ qemu_opts_foreach(qemu_find_opts("global"),
+ qdev_add_one_global, NULL, NULL);
+}
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 311af6da7..737d29c63 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -539,19 +539,6 @@ PropertyInfo qdev_prop_losttickpolicy = {
.set = set_enum,
};
-/* --- Block device error handling policy --- */
-
-QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
-
-PropertyInfo qdev_prop_blockdev_on_error = {
- .name = "BlockdevOnError",
- .description = "Error handling policy, "
- "report/ignore/enospc/stop/auto",
- .enum_table = BlockdevOnError_lookup,
- .get = get_enum,
- .set = set_enum,
-};
-
/* --- BIOS CHS translation */
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
@@ -1033,11 +1020,12 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
*ptr = value;
}
-static GList *global_props;
+static QTAILQ_HEAD(, GlobalProperty) global_props =
+ QTAILQ_HEAD_INITIALIZER(global_props);
void qdev_prop_register_global(GlobalProperty *prop)
{
- global_props = g_list_append(global_props, prop);
+ QTAILQ_INSERT_TAIL(&global_props, prop, next);
}
void qdev_prop_register_global_list(GlobalProperty *props)
@@ -1051,11 +1039,10 @@ void qdev_prop_register_global_list(GlobalProperty *props)
int qdev_prop_check_globals(void)
{
- GList *l;
+ GlobalProperty *prop;
int ret = 0;
- for (l = global_props; l; l = l->next) {
- GlobalProperty *prop = l->data;
+ QTAILQ_FOREACH(prop, &global_props, next) {
ObjectClass *oc;
DeviceClass *dc;
if (prop->used) {
@@ -1084,12 +1071,11 @@ int qdev_prop_check_globals(void)
}
static void qdev_prop_set_globals_for_type(DeviceState *dev,
- const char *typename)
+ const char *typename)
{
- GList *l;
+ GlobalProperty *prop;
- for (l = global_props; l; l = l->next) {
- GlobalProperty *prop = l->data;
+ QTAILQ_FOREACH(prop, &global_props, next) {
Error *err = NULL;
if (strcmp(typename, prop->driver) != 0) {
@@ -1098,14 +1084,10 @@ static void qdev_prop_set_globals_for_type(DeviceState *dev,
prop->used = true;
object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
if (err != NULL) {
- error_prepend(&err, "can't apply global %s.%s=%s: ",
- prop->driver, prop->property, prop->value);
- if (!dev->hotplugged && prop->errp) {
- error_propagate(prop->errp, err);
- } else {
- assert(prop->user_provided);
- error_reportf_err(err, "Warning: ");
- }
+ assert(prop->user_provided);
+ error_reportf_err(err, "Warning: global %s.%s=%s ignored: ",
+ prop->driver, prop->property, prop->value);
+ return;
}
}
}
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 57834423b..db41aa1f2 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -35,7 +35,6 @@
#include "qemu/error-report.h"
#include "hw/hotplug.h"
#include "hw/boards.h"
-#include "hw/sysbus.h"
#include "qapi-event.h"
int qdev_hotplug = 0;
@@ -59,6 +58,9 @@ const char *qdev_fw_name(DeviceState *dev)
return object_get_typename(OBJECT(dev));
}
+static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
+ Error **errp);
+
static void bus_remove_child(BusState *bus, DeviceState *child)
{
BusChild *kid;
@@ -107,6 +109,24 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
bus_add_child(bus, dev);
}
+static void qbus_set_hotplug_handler_internal(BusState *bus, Object *handler,
+ Error **errp)
+{
+
+ object_property_set_link(OBJECT(bus), OBJECT(handler),
+ QDEV_HOTPLUG_HANDLER_PROPERTY, errp);
+}
+
+void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, Error **errp)
+{
+ qbus_set_hotplug_handler_internal(bus, OBJECT(handler), errp);
+}
+
+void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp)
+{
+ qbus_set_hotplug_handler_internal(bus, OBJECT(bus), errp);
+}
+
/* Create a new device. This only initializes the device state
structure and allows properties to be set. The device still needs
to be realized. See qdev-core.h. */
@@ -141,12 +161,6 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
}
if (!bus) {
- /* Assert that the device really is a SysBusDevice before
- * we put it onto the sysbus. Non-sysbus devices which aren't
- * being put onto a bus should be created with object_new(TYPE_FOO),
- * not qdev_create(NULL, TYPE_FOO).
- */
- g_assert(object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE));
bus = sysbus_get_default();
}
@@ -354,14 +368,12 @@ void qdev_init_nofail(DeviceState *dev)
assert(!dev->realized);
- object_ref(OBJECT(dev));
object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err) {
error_reportf_err(err, "Initialization of device %s failed: ",
object_get_typename(OBJECT(dev)));
exit(1);
}
- object_unref(OBJECT(dev));
}
void qdev_machine_creation_done(void)
@@ -583,6 +595,40 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
return NULL;
}
+int qbus_walk_children(BusState *bus,
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
+ void *opaque)
+{
+ BusChild *kid;
+ int err;
+
+ if (pre_busfn) {
+ err = pre_busfn(bus, opaque);
+ if (err) {
+ return err;
+ }
+ }
+
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ err = qdev_walk_children(kid->child,
+ pre_devfn, pre_busfn,
+ post_devfn, post_busfn, opaque);
+ if (err < 0) {
+ return err;
+ }
+ }
+
+ if (post_busfn) {
+ err = post_busfn(bus, opaque);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
int qdev_walk_children(DeviceState *dev,
qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
@@ -639,6 +685,129 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
return NULL;
}
+static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
+{
+ const char *typename = object_get_typename(OBJECT(bus));
+ BusClass *bc;
+ char *buf;
+ int i, len, bus_id;
+
+ bus->parent = parent;
+
+ if (name) {
+ bus->name = g_strdup(name);
+ } else if (bus->parent && bus->parent->id) {
+ /* parent device has id -> use it plus parent-bus-id for bus name */
+ bus_id = bus->parent->num_child_bus;
+
+ len = strlen(bus->parent->id) + 16;
+ buf = g_malloc(len);
+ snprintf(buf, len, "%s.%d", bus->parent->id, bus_id);
+ bus->name = buf;
+ } else {
+ /* no id -> use lowercase bus type plus global bus-id for bus name */
+ bc = BUS_GET_CLASS(bus);
+ bus_id = bc->automatic_ids++;
+
+ len = strlen(typename) + 16;
+ buf = g_malloc(len);
+ len = snprintf(buf, len, "%s.%d", typename, bus_id);
+ for (i = 0; i < len; i++) {
+ buf[i] = qemu_tolower(buf[i]);
+ }
+ bus->name = buf;
+ }
+
+ if (bus->parent) {
+ QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
+ bus->parent->num_child_bus++;
+ object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
+ object_unref(OBJECT(bus));
+ } else if (bus != sysbus_get_default()) {
+ /* TODO: once all bus devices are qdevified,
+ only reset handler for main_system_bus should be registered here. */
+ qemu_register_reset(qbus_reset_all_fn, bus);
+ }
+}
+
+static void bus_unparent(Object *obj)
+{
+ BusState *bus = BUS(obj);
+ BusChild *kid;
+
+ while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
+ DeviceState *dev = kid->child;
+ object_unparent(OBJECT(dev));
+ }
+ if (bus->parent) {
+ QLIST_REMOVE(bus, sibling);
+ bus->parent->num_child_bus--;
+ bus->parent = NULL;
+ } else {
+ assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
+ qemu_unregister_reset(qbus_reset_all_fn, bus);
+ }
+}
+
+static bool bus_get_realized(Object *obj, Error **errp)
+{
+ BusState *bus = BUS(obj);
+
+ return bus->realized;
+}
+
+static void bus_set_realized(Object *obj, bool value, Error **errp)
+{
+ BusState *bus = BUS(obj);
+ BusClass *bc = BUS_GET_CLASS(bus);
+ BusChild *kid;
+ Error *local_err = NULL;
+
+ if (value && !bus->realized) {
+ if (bc->realize) {
+ bc->realize(bus, &local_err);
+ }
+
+ /* TODO: recursive realization */
+ } else if (!value && bus->realized) {
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+ object_property_set_bool(OBJECT(dev), false, "realized",
+ &local_err);
+ if (local_err != NULL) {
+ break;
+ }
+ }
+ if (bc->unrealize && local_err == NULL) {
+ bc->unrealize(bus, &local_err);
+ }
+ }
+
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ bus->realized = value;
+}
+
+void qbus_create_inplace(void *bus, size_t size, const char *typename,
+ DeviceState *parent, const char *name)
+{
+ object_initialize(bus, size, typename);
+ qbus_realize(bus, parent, name);
+}
+
+BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
+{
+ BusState *bus;
+
+ bus = BUS(object_new(typename));
+ qbus_realize(bus, parent, name);
+
+ return bus;
+}
+
static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
{
BusClass *bc = BUS_GET_CLASS(bus);
@@ -739,20 +908,13 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v,
}
/**
- * qdev_property_add_legacy:
- * @dev: Device to add the property to.
- * @prop: The qdev property definition.
- * @errp: location to store error information.
+ * @qdev_add_legacy_property - adds a legacy property
*
- * Add a legacy QOM property to @dev for qdev property @prop.
- * On error, store error in @errp.
+ * Do not use this is new code! Properties added through this interface will
+ * be given names and types in the "legacy" namespace.
*
- * Legacy properties are string versions of QOM properties. The format of
- * the string depends on the property type. Legacy properties are only
- * needed for "info qtree".
- *
- * Do not use this is new code! QOM Properties added through this interface
- * will be given names in the "legacy" namespace.
+ * Legacy properties are string versions of other OOM properties. The format
+ * of the string depends on the property type.
*/
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
Error **errp)
@@ -775,14 +937,10 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
}
/**
- * qdev_property_add_static:
- * @dev: Device to add the property to.
- * @prop: The qdev property definition.
- * @errp: location to store error information.
+ * @qdev_property_add_static - add a @Property to a device.
*
- * 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.
+ * Static properties access data in a struct. The actual type of the
+ * property and the field depends on the property type.
*/
void qdev_property_add_static(DeviceState *dev, Property *prop,
Error **errp)
@@ -887,8 +1045,6 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
HotplugHandler *hotplug_ctrl;
BusState *bus;
Error *local_err = NULL;
- bool unattached_parent = false;
- static int unattached_count;
if (dev->hotplugged && !dc->hotpluggable) {
error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
@@ -897,23 +1053,15 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
if (value && !dev->realized) {
if (!obj->parent) {
+ static int unattached_count;
gchar *name = g_strdup_printf("device[%d]", unattached_count++);
object_property_add_child(container_get(qdev_get_machine(),
"/unattached"),
name, obj, &error_abort);
- unattached_parent = true;
g_free(name);
}
- hotplug_ctrl = qdev_get_hotplug_handler(dev);
- if (hotplug_ctrl) {
- hotplug_handler_pre_plug(hotplug_ctrl, dev, &local_err);
- if (local_err != NULL) {
- goto fail;
- }
- }
-
if (dc->realize) {
dc->realize(dev, &local_err);
}
@@ -924,6 +1072,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
DEVICE_LISTENER_CALL(realize, Forward, dev);
+ hotplug_ctrl = qdev_get_hotplug_handler(dev);
if (hotplug_ctrl) {
hotplug_handler_plug(hotplug_ctrl, dev, &local_err);
}
@@ -991,10 +1140,6 @@ post_realize_fail:
fail:
error_propagate(errp, local_err);
- if (unattached_parent) {
- object_unparent(OBJECT(dev));
- unattached_count--;
- }
}
static bool device_get_hotpluggable(Object *obj, Error **errp)
@@ -1170,8 +1315,55 @@ static const TypeInfo device_type_info = {
.class_size = sizeof(DeviceClass),
};
+static void qbus_initfn(Object *obj)
+{
+ BusState *bus = BUS(obj);
+
+ QTAILQ_INIT(&bus->children);
+ object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY,
+ TYPE_HOTPLUG_HANDLER,
+ (Object **)&bus->hotplug_handler,
+ object_property_allow_set_link,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
+ NULL);
+ object_property_add_bool(obj, "realized",
+ bus_get_realized, bus_set_realized, NULL);
+}
+
+static char *default_bus_get_fw_dev_path(DeviceState *dev)
+{
+ return g_strdup(object_get_typename(OBJECT(dev)));
+}
+
+static void bus_class_init(ObjectClass *class, void *data)
+{
+ BusClass *bc = BUS_CLASS(class);
+
+ class->unparent = bus_unparent;
+ bc->get_fw_dev_path = default_bus_get_fw_dev_path;
+}
+
+static void qbus_finalize(Object *obj)
+{
+ BusState *bus = BUS(obj);
+
+ g_free((char *)bus->name);
+}
+
+static const TypeInfo bus_info = {
+ .name = TYPE_BUS,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(BusState),
+ .abstract = true,
+ .class_size = sizeof(BusClass),
+ .instance_init = qbus_initfn,
+ .instance_finalize = qbus_finalize,
+ .class_init = bus_class_init,
+};
+
static void qdev_register_types(void)
{
+ type_register_static(&bus_info);
type_register_static(&device_type_info);
}
diff --git a/hw/core/register.c b/hw/core/register.c
deleted file mode 100644
index 4bfbc508d..000000000
--- a/hw/core/register.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Register Definition API
- *
- * Copyright (c) 2016 Xilinx Inc.
- * Copyright (c) 2013 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.
- */
-
-#include "qemu/osdep.h"
-#include "hw/register.h"
-#include "hw/qdev.h"
-#include "qemu/log.h"
-
-static inline void register_write_val(RegisterInfo *reg, uint64_t val)
-{
- g_assert(reg->data);
-
- switch (reg->data_size) {
- case 1:
- *(uint8_t *)reg->data = val;
- break;
- case 2:
- *(uint16_t *)reg->data = val;
- break;
- case 4:
- *(uint32_t *)reg->data = val;
- break;
- case 8:
- *(uint64_t *)reg->data = val;
- break;
- default:
- g_assert_not_reached();
- }
-}
-
-static inline uint64_t register_read_val(RegisterInfo *reg)
-{
- switch (reg->data_size) {
- case 1:
- return *(uint8_t *)reg->data;
- case 2:
- return *(uint16_t *)reg->data;
- case 4:
- return *(uint32_t *)reg->data;
- case 8:
- return *(uint64_t *)reg->data;
- default:
- g_assert_not_reached();
- }
- return 0; /* unreachable */
-}
-
-void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
- const char *prefix, bool debug)
-{
- uint64_t old_val, new_val, test, no_w_mask;
- const RegisterAccessInfo *ac;
-
- assert(reg);
-
- ac = reg->access;
-
- if (!ac || !ac->name) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
- "(written value: %#" PRIx64 ")\n", prefix, val);
- return;
- }
-
- old_val = reg->data ? register_read_val(reg) : ac->reset;
-
- test = (old_val ^ val) & ac->rsvd;
- if (test) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit"
- "fields: %#" PRIx64 ")\n", prefix, test);
- }
-
- test = val & ac->unimp;
- if (test) {
- qemu_log_mask(LOG_UNIMP,
- "%s:%s writing %#" PRIx64 " to unimplemented bits:" \
- " %#" PRIx64 "",
- prefix, reg->access->name, val, ac->unimp);
- }
-
- /* Create the no write mask based on the read only, write to clear and
- * reserved bit masks.
- */
- no_w_mask = ac->ro | ac->w1c | ac->rsvd | ~we;
- new_val = (val & ~no_w_mask) | (old_val & no_w_mask);
- new_val &= ~(val & ac->w1c);
-
- if (ac->pre_write) {
- new_val = ac->pre_write(reg, new_val);
- }
-
- if (debug) {
- qemu_log("%s:%s: write of value %#" PRIx64 "\n", prefix, ac->name,
- new_val);
- }
-
- register_write_val(reg, new_val);
-
- if (ac->post_write) {
- ac->post_write(reg, new_val);
- }
-}
-
-uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
- bool debug)
-{
- uint64_t ret;
- const RegisterAccessInfo *ac;
-
- assert(reg);
-
- ac = reg->access;
- if (!ac || !ac->name) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: read from undefined device state\n",
- prefix);
- return 0;
- }
-
- ret = reg->data ? register_read_val(reg) : ac->reset;
-
- register_write_val(reg, ret & ~(ac->cor & re));
-
- /* Mask based on the read enable size */
- ret &= re;
-
- if (ac->post_read) {
- ret = ac->post_read(reg, ret);
- }
-
- if (debug) {
- qemu_log("%s:%s: read of value %#" PRIx64 "\n", prefix,
- ac->name, ret);
- }
-
- return ret;
-}
-
-void register_reset(RegisterInfo *reg)
-{
- g_assert(reg);
-
- if (!reg->data || !reg->access) {
- return;
- }
-
- register_write_val(reg, reg->access->reset);
-}
-
-void register_init(RegisterInfo *reg)
-{
- assert(reg);
-
- if (!reg->data || !reg->access) {
- return;
- }
-
- object_initialize((void *)reg, sizeof(*reg), TYPE_REGISTER);
-}
-
-void register_write_memory(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- RegisterInfoArray *reg_array = opaque;
- RegisterInfo *reg = NULL;
- uint64_t we;
- int i;
-
- for (i = 0; i < reg_array->num_elements; i++) {
- if (reg_array->r[i]->access->addr == addr) {
- reg = reg_array->r[i];
- break;
- }
- }
-
- if (!reg) {
- qemu_log_mask(LOG_GUEST_ERROR, "Write to unimplemented register at " \
- "address: %#" PRIx64 "\n", addr);
- return;
- }
-
- /* Generate appropriate write enable mask */
- if (reg->data_size < size) {
- we = MAKE_64BIT_MASK(0, reg->data_size * 8);
- } else {
- we = MAKE_64BIT_MASK(0, size * 8);
- }
-
- register_write(reg, value, we, reg_array->prefix,
- reg_array->debug);
-}
-
-uint64_t register_read_memory(void *opaque, hwaddr addr,
- unsigned size)
-{
- RegisterInfoArray *reg_array = opaque;
- RegisterInfo *reg = NULL;
- uint64_t read_val;
- int i;
-
- for (i = 0; i < reg_array->num_elements; i++) {
- if (reg_array->r[i]->access->addr == addr) {
- reg = reg_array->r[i];
- break;
- }
- }
-
- if (!reg) {
- qemu_log_mask(LOG_GUEST_ERROR, "Read to unimplemented register at " \
- "address: %#" PRIx64 "\n", addr);
- return 0;
- }
-
- read_val = register_read(reg, size * 8, reg_array->prefix,
- reg_array->debug);
-
- return extract64(read_val, 0, size * 8);
-}
-
-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)
-{
- const char *device_prefix = object_get_typename(OBJECT(owner));
- RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
- int i;
-
- r_array->r = g_new0(RegisterInfo *, num);
- r_array->num_elements = num;
- r_array->debug = debug_enabled;
- r_array->prefix = device_prefix;
-
- for (i = 0; i < num; i++) {
- int index = rae[i].addr / 4;
- RegisterInfo *r = &ri[index];
-
- *r = (RegisterInfo) {
- .data = &data[index],
- .data_size = sizeof(uint32_t),
- .access = &rae[i],
- .opaque = owner,
- };
- register_init(r);
-
- r_array->r[i] = r;
- }
-
- memory_region_init_io(&r_array->mem, OBJECT(owner), ops, r_array,
- device_prefix, memory_size);
-
- return r_array;
-}
-
-void register_finalize_block(RegisterInfoArray *r_array)
-{
- object_unparent(OBJECT(&r_array->mem));
- g_free(r_array->r);
- g_free(r_array);
-}
-
-static const TypeInfo register_info = {
- .name = TYPE_REGISTER,
- .parent = TYPE_DEVICE,
-};
-
-static void register_register_types(void)
-{
- type_register_static(&register_info);
-}
-
-type_init(register_register_types)
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index c0f560b28..a7dbe2b32 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -190,9 +190,9 @@ MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n)
return dev->mmio[n].memory;
}
-void sysbus_init_ioports(SysBusDevice *dev, uint32_t ioport, uint32_t size)
+void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
{
- uint32_t i;
+ pio_addr_t i;
for (i = 0; i < size; i++) {
assert(dev->num_pio < QDEV_MAX_PIO);
diff --git a/hw/core/uboot_image.h b/hw/core/uboot_image.h
index 34c11a70a..9fc2760b5 100644
--- a/hw/core/uboot_image.h
+++ b/hw/core/uboot_image.h
@@ -26,8 +26,8 @@
********************************************************************
*/
-#ifndef UBOOT_IMAGE_H
-#define UBOOT_IMAGE_H
+#ifndef __UBOOT_IMAGE_H__
+#define __UBOOT_IMAGE_H__
/*
* Operating System Codes
@@ -155,4 +155,4 @@ typedef struct uboot_image_header {
} uboot_image_header_t;
-#endif /* UBOOT_IMAGE_H */
+#endif /* __IMAGE_H__ */
diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs
index 942a4bb82..0954a1872 100644
--- a/hw/cpu/Makefile.objs
+++ b/hw/cpu/Makefile.objs
@@ -2,5 +2,4 @@ obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
obj-$(CONFIG_REALVIEW) += realview_mpcore.o
obj-$(CONFIG_A9MPCORE) += a9mpcore.o
obj-$(CONFIG_A15MPCORE) += a15mpcore.o
-obj-y += core.o
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index f17f29209..5459ae8c1 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -11,7 +11,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/cpu/a9mpcore.h"
-#include "qom/cpu.h"
static void a9mp_priv_set_irq(void *opaque, int irq, int level)
{
diff --git a/hw/cpu/core.c b/hw/cpu/core.c
deleted file mode 100644
index eff90c12b..000000000
--- a/hw/cpu/core.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.
- */
-#include "hw/cpu/core.h"
-#include "qapi/visitor.h"
-#include "qapi/error.h"
-#include "sysemu/cpus.h"
-
-static void core_prop_get_core_id(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- CPUCore *core = CPU_CORE(obj);
- int64_t value = core->core_id;
-
- visit_type_int(v, name, &value, errp);
-}
-
-static void core_prop_set_core_id(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- CPUCore *core = CPU_CORE(obj);
- Error *local_err = NULL;
- int64_t value;
-
- visit_type_int(v, name, &value, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- core->core_id = value;
-}
-
-static void core_prop_get_nr_threads(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- CPUCore *core = CPU_CORE(obj);
- int64_t value = core->nr_threads;
-
- visit_type_int(v, name, &value, errp);
-}
-
-static void core_prop_set_nr_threads(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- CPUCore *core = CPU_CORE(obj);
- Error *local_err = NULL;
- int64_t value;
-
- visit_type_int(v, name, &value, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- core->nr_threads = value;
-}
-
-static void cpu_core_instance_init(Object *obj)
-{
- CPUCore *core = CPU_CORE(obj);
-
- object_property_add(obj, "core-id", "int", core_prop_get_core_id,
- core_prop_set_core_id, NULL, NULL, NULL);
- object_property_add(obj, "nr-threads", "int", core_prop_get_nr_threads,
- core_prop_set_nr_threads, NULL, NULL, NULL);
- core->nr_threads = smp_threads;
-}
-
-static const TypeInfo cpu_core_type_info = {
- .name = TYPE_CPU_CORE,
- .parent = TYPE_DEVICE,
- .abstract = true,
- .instance_size = sizeof(CPUCore),
- .instance_init = cpu_core_instance_init,
-};
-
-static void cpu_core_register_types(void)
-{
- type_register_static(&cpu_core_type_info);
-}
-
-type_init(cpu_core_register_types)
diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c
index 60df8877c..9f5865874 100644
--- a/hw/cris/axis_dev88.c
+++ b/hw/cris/axis_dev88.c
@@ -37,7 +37,6 @@
#include "sysemu/block-backend.h"
#include "exec/address-spaces.h"
#include "sysemu/qtest.h"
-#include "sysemu/sysemu.h"
#define D(x)
#define DNAND(x)
@@ -342,7 +341,8 @@ void axisdev88_init(MachineState *machine)
sysbus_create_varargs("etraxfs,timer", 0x3005e000, irq[0x1b], nmi[1], NULL);
for (i = 0; i < 4; i++) {
- etraxfs_ser_create(0x30026000 + i * 0x2000, irq[0x14 + i], serial_hds[i]);
+ sysbus_create_simple("etraxfs,serial", 0x30026000 + i * 0x2000,
+ irq[0x14 + i]);
}
if (kernel_filename) {
diff --git a/hw/cris/boot.h b/hw/cris/boot.h
index 218854e5d..c4d3fa6f6 100644
--- a/hw/cris/boot.h
+++ b/hw/cris/boot.h
@@ -1,5 +1,5 @@
-#ifndef HW_CRIS_BOOT_H
-#define HW_CRIS_BOOT_H
+#ifndef _CRIS_BOOT_H
+#define HW_CRIS_BOOT_H 1
struct cris_load_info
{
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index 063889bea..d99780eeb 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -43,5 +43,3 @@ virtio-gpu.o-cflags := $(VIRGL_CFLAGS)
virtio-gpu.o-libs += $(VIRGL_LIBS)
virtio-gpu-3d.o-cflags := $(VIRGL_CFLAGS)
virtio-gpu-3d.o-libs += $(VIRGL_LIBS)
-obj-$(CONFIG_DPCD) += dpcd.o
-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx_dp.o
diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c
index 166edade7..05aa2d1e6 100644
--- a/hw/display/ads7846.c
+++ b/hw/display/ads7846.c
@@ -133,7 +133,7 @@ static const VMStateDescription vmstate_ads7846 = {
}
};
-static void ads7846_realize(SSISlave *d, Error **errp)
+static int ads7846_init(SSISlave *d)
{
DeviceState *dev = DEVICE(d);
ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, d);
@@ -152,13 +152,14 @@ static void ads7846_realize(SSISlave *d, Error **errp)
ads7846_int_update(s);
vmstate_register(NULL, -1, &vmstate_ads7846, s);
+ return 0;
}
static void ads7846_class_init(ObjectClass *klass, void *data)
{
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
- k->realize = ads7846_realize;
+ k->init = ads7846_init;
k->transfer = ads7846_transfer;
}
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
index 7eab92765..506f1d3d9 100644
--- a/hw/display/bcm2835_fb.c
+++ b/hw/display/bcm2835_fb.c
@@ -29,7 +29,6 @@
#include "hw/display/framebuffer.h"
#include "ui/pixel_ops.h"
#include "hw/misc/bcm2835_mbox_defs.h"
-#include "qemu/log.h"
#define DEFAULT_VCRAM_SIZE 0x4000000
#define BCM2835_FB_OFFSET 0x00100000
diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c
index cbf07d14d..c231960d9 100644
--- a/hw/display/blizzard.c
+++ b/hw/display/blizzard.c
@@ -925,83 +925,16 @@ static void blizzard_update_display(void *opaque)
s->my[1] = 0;
}
-static void blizzard_draw_line16_32(uint32_t *dest,
- const uint16_t *src, unsigned int width)
-{
- uint16_t data;
- unsigned int r, g, b;
- const uint16_t *end = (const void *) src + width;
- while (src < end) {
- data = *src ++;
- b = (data & 0x1f) << 3;
- data >>= 5;
- g = (data & 0x3f) << 2;
- data >>= 6;
- r = (data & 0x1f) << 3;
- data >>= 5;
- *dest++ = rgb_to_pixel32(r, g, b);
- }
-}
-
-static void blizzard_draw_line24mode1_32(uint32_t *dest,
- const uint8_t *src, unsigned int width)
-{
- /* TODO: check if SDL 24-bit planes are not in the same format and
- * if so, use memcpy */
- unsigned int r[2], g[2], b[2];
- const uint8_t *end = src + width;
- while (src < end) {
- g[0] = *src ++;
- r[0] = *src ++;
- r[1] = *src ++;
- b[0] = *src ++;
- *dest++ = rgb_to_pixel32(r[0], g[0], b[0]);
- b[1] = *src ++;
- g[1] = *src ++;
- *dest++ = rgb_to_pixel32(r[1], g[1], b[1]);
- }
-}
-
-static void blizzard_draw_line24mode2_32(uint32_t *dest,
- const uint8_t *src, unsigned int width)
-{
- unsigned int r, g, b;
- const uint8_t *end = src + width;
- while (src < end) {
- r = *src ++;
- src ++;
- b = *src ++;
- g = *src ++;
- *dest++ = rgb_to_pixel32(r, g, b);
- }
-}
-
-/* No rotation */
-static blizzard_fn_t blizzard_draw_fn_32[0x10] = {
- NULL,
- /* RGB 5:6:5*/
- (blizzard_fn_t) blizzard_draw_line16_32,
- /* RGB 6:6:6 mode 1 */
- (blizzard_fn_t) blizzard_draw_line24mode1_32,
- /* RGB 8:8:8 mode 1 */
- (blizzard_fn_t) blizzard_draw_line24mode1_32,
- NULL, NULL,
- /* RGB 6:6:6 mode 2 */
- (blizzard_fn_t) blizzard_draw_line24mode2_32,
- /* RGB 8:8:8 mode 2 */
- (blizzard_fn_t) blizzard_draw_line24mode2_32,
- /* YUV 4:2:2 */
- NULL,
- /* YUV 4:2:0 */
- NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
-};
-
-/* 90deg, 180deg and 270deg rotation */
-static blizzard_fn_t blizzard_draw_fn_r_32[0x10] = {
- /* TODO */
- [0 ... 0xf] = NULL,
-};
+#define DEPTH 8
+#include "blizzard_template.h"
+#define DEPTH 15
+#include "blizzard_template.h"
+#define DEPTH 16
+#include "blizzard_template.h"
+#define DEPTH 24
+#include "blizzard_template.h"
+#define DEPTH 32
+#include "blizzard_template.h"
static const GraphicHwOps blizzard_ops = {
.invalidate = blizzard_invalidate_display,
@@ -1018,10 +951,35 @@ void *s1d13745_init(qemu_irq gpio_int)
s->con = graphic_console_init(NULL, 0, &blizzard_ops, s);
surface = qemu_console_surface(s->con);
- assert(surface_bits_per_pixel(surface) == 32);
-
- s->line_fn_tab[0] = blizzard_draw_fn_32;
- s->line_fn_tab[1] = blizzard_draw_fn_r_32;
+ switch (surface_bits_per_pixel(surface)) {
+ case 0:
+ s->line_fn_tab[0] = s->line_fn_tab[1] =
+ g_malloc0(sizeof(blizzard_fn_t) * 0x10);
+ break;
+ case 8:
+ s->line_fn_tab[0] = blizzard_draw_fn_8;
+ s->line_fn_tab[1] = blizzard_draw_fn_r_8;
+ break;
+ case 15:
+ s->line_fn_tab[0] = blizzard_draw_fn_15;
+ s->line_fn_tab[1] = blizzard_draw_fn_r_15;
+ break;
+ case 16:
+ s->line_fn_tab[0] = blizzard_draw_fn_16;
+ s->line_fn_tab[1] = blizzard_draw_fn_r_16;
+ break;
+ case 24:
+ s->line_fn_tab[0] = blizzard_draw_fn_24;
+ s->line_fn_tab[1] = blizzard_draw_fn_r_24;
+ break;
+ case 32:
+ s->line_fn_tab[0] = blizzard_draw_fn_32;
+ s->line_fn_tab[1] = blizzard_draw_fn_r_32;
+ break;
+ default:
+ fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
+ exit(1);
+ }
blizzard_reset(s);
diff --git a/hw/display/blizzard_template.h b/hw/display/blizzard_template.h
new file mode 100644
index 000000000..b7ef27c80
--- /dev/null
+++ b/hw/display/blizzard_template.h
@@ -0,0 +1,146 @@
+/*
+ * QEMU Epson S1D13744/S1D13745 templates
+ *
+ * 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/>.
+ */
+
+#define SKIP_PIXEL(to) (to += deststep)
+#if DEPTH == 8
+# define PIXEL_TYPE uint8_t
+# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
+# define COPY_PIXEL1(to, from) (*to++ = from)
+#elif DEPTH == 15 || DEPTH == 16
+# define PIXEL_TYPE uint16_t
+# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
+# define COPY_PIXEL1(to, from) (*to++ = from)
+#elif DEPTH == 24
+# define PIXEL_TYPE uint8_t
+# define COPY_PIXEL(to, from) \
+ do { \
+ to[0] = from; \
+ to[1] = (from) >> 8; \
+ to[2] = (from) >> 16; \
+ SKIP_PIXEL(to); \
+ } while (0)
+
+# define COPY_PIXEL1(to, from) \
+ do { \
+ *to++ = from; \
+ *to++ = (from) >> 8; \
+ *to++ = (from) >> 16; \
+ } while (0)
+#elif DEPTH == 32
+# define PIXEL_TYPE uint32_t
+# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
+# define COPY_PIXEL1(to, from) (*to++ = from)
+#else
+# error unknown bit depth
+#endif
+
+#ifdef HOST_WORDS_BIGENDIAN
+# define SWAP_WORDS 1
+#endif
+
+static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest,
+ const uint16_t *src, unsigned int width)
+{
+#if !defined(SWAP_WORDS) && DEPTH == 16
+ memcpy(dest, src, width);
+#else
+ uint16_t data;
+ unsigned int r, g, b;
+ const uint16_t *end = (const void *) src + width;
+ while (src < end) {
+ data = *src ++;
+ b = (data & 0x1f) << 3;
+ data >>= 5;
+ g = (data & 0x3f) << 2;
+ data >>= 6;
+ r = (data & 0x1f) << 3;
+ data >>= 5;
+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
+ }
+#endif
+}
+
+static void glue(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest,
+ const uint8_t *src, unsigned int width)
+{
+ /* TODO: check if SDL 24-bit planes are not in the same format and
+ * if so, use memcpy */
+ unsigned int r[2], g[2], b[2];
+ const uint8_t *end = src + width;
+ while (src < end) {
+ g[0] = *src ++;
+ r[0] = *src ++;
+ r[1] = *src ++;
+ b[0] = *src ++;
+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[0], g[0], b[0]));
+ b[1] = *src ++;
+ g[1] = *src ++;
+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[1], g[1], b[1]));
+ }
+}
+
+static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest,
+ const uint8_t *src, unsigned int width)
+{
+ unsigned int r, g, b;
+ const uint8_t *end = src + width;
+ while (src < end) {
+ r = *src ++;
+ src ++;
+ b = *src ++;
+ g = *src ++;
+ COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b));
+ }
+}
+
+/* No rotation */
+static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = {
+ NULL,
+ /* RGB 5:6:5*/
+ (blizzard_fn_t) glue(blizzard_draw_line16_, DEPTH),
+ /* RGB 6:6:6 mode 1 */
+ (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH),
+ /* RGB 8:8:8 mode 1 */
+ (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH),
+ NULL, NULL,
+ /* RGB 6:6:6 mode 2 */
+ (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH),
+ /* RGB 8:8:8 mode 2 */
+ (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH),
+ /* YUV 4:2:2 */
+ NULL,
+ /* YUV 4:2:0 */
+ NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
+/* 90deg, 180deg and 270deg rotation */
+static blizzard_fn_t glue(blizzard_draw_fn_r_, DEPTH)[0x10] = {
+ /* TODO */
+ [0 ... 0xf] = NULL,
+};
+
+#undef DEPTH
+#undef SKIP_PIXEL
+#undef COPY_PIXEL
+#undef COPY_PIXEL1
+#undef PIXEL_TYPE
+
+#undef SWAP_WORDS
diff --git a/hw/display/cg3.c b/hw/display/cg3.c
index 117422039..fc0d97fa4 100644
--- a/hw/display/cg3.c
+++ b/hw/display/cg3.c
@@ -26,12 +26,10 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
-#include "cpu.h"
#include "qemu/error-report.h"
#include "ui/console.h"
#include "hw/sysbus.h"
#include "hw/loader.h"
-#include "qemu/log.h"
/* Change to 1 to enable debugging */
#define DEBUG_CG3 0
diff --git a/hw/display/dpcd.c b/hw/display/dpcd.c
deleted file mode 100644
index ce92ff6e2..000000000
--- a/hw/display/dpcd.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * dpcd.c
- *
- * 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/>.
- *
- */
-
-/*
- * This is a simple AUX slave which emulates a connected screen.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "hw/misc/auxbus.h"
-#include "hw/display/dpcd.h"
-
-#ifndef DEBUG_DPCD
-#define DEBUG_DPCD 0
-#endif
-
-#define DPRINTF(fmt, ...) do { \
- if (DEBUG_DPCD) { \
- qemu_log("dpcd: " fmt, ## __VA_ARGS__); \
- } \
-} while (0);
-
-#define DPCD_READABLE_AREA 0x600
-
-struct DPCDState {
- /*< private >*/
- AUXSlave parent_obj;
-
- /*< public >*/
- /*
- * The DCPD is 0x7FFFF length but read as 0 after offset 0x5FF.
- */
- uint8_t dpcd_info[DPCD_READABLE_AREA];
-
- MemoryRegion iomem;
-};
-
-static uint64_t dpcd_read(void *opaque, hwaddr offset, unsigned size)
-{
- uint8_t ret;
- DPCDState *e = DPCD(opaque);
-
- if (offset < DPCD_READABLE_AREA) {
- ret = e->dpcd_info[offset];
- } else {
- qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
- offset);
- ret = 0;
- }
-
- DPRINTF("read 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", ret, offset);
- return ret;
-}
-
-static void dpcd_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- DPCDState *e = DPCD(opaque);
-
- DPRINTF("write 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", (uint8_t)value, offset);
-
- if (offset < DPCD_READABLE_AREA) {
- e->dpcd_info[offset] = value;
- } else {
- qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
- offset);
- }
-}
-
-static const MemoryRegionOps aux_ops = {
- .read = dpcd_read,
- .write = dpcd_write,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
- .impl = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
-};
-
-static void dpcd_reset(DeviceState *dev)
-{
- DPCDState *s = DPCD(dev);
-
- memset(&(s->dpcd_info), 0, sizeof(s->dpcd_info));
-
- s->dpcd_info[DPCD_REVISION] = DPCD_REV_1_0;
- s->dpcd_info[DPCD_MAX_LINK_RATE] = DPCD_5_4GBPS;
- s->dpcd_info[DPCD_MAX_LANE_COUNT] = DPCD_FOUR_LANES;
- s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_0] = DPCD_EDID_PRESENT;
- /* buffer size */
- s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_1] = 0xFF;
-
- s->dpcd_info[DPCD_LANE0_1_STATUS] = DPCD_LANE0_CR_DONE
- | DPCD_LANE0_CHANNEL_EQ_DONE
- | DPCD_LANE0_SYMBOL_LOCKED
- | DPCD_LANE1_CR_DONE
- | DPCD_LANE1_CHANNEL_EQ_DONE
- | DPCD_LANE1_SYMBOL_LOCKED;
- s->dpcd_info[DPCD_LANE2_3_STATUS] = DPCD_LANE2_CR_DONE
- | DPCD_LANE2_CHANNEL_EQ_DONE
- | DPCD_LANE2_SYMBOL_LOCKED
- | DPCD_LANE3_CR_DONE
- | DPCD_LANE3_CHANNEL_EQ_DONE
- | DPCD_LANE3_SYMBOL_LOCKED;
-
- s->dpcd_info[DPCD_LANE_ALIGN_STATUS_UPDATED] = DPCD_INTERLANE_ALIGN_DONE;
- s->dpcd_info[DPCD_SINK_STATUS] = DPCD_RECEIVE_PORT_0_STATUS;
-}
-
-static void dpcd_init(Object *obj)
-{
- DPCDState *s = DPCD(obj);
-
- memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x7FFFF);
- aux_init_mmio(AUX_SLAVE(obj), &s->iomem);
-}
-
-static const VMStateDescription vmstate_dpcd = {
- .name = TYPE_DPCD,
- .version_id = 0,
- .minimum_version_id = 0,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8_ARRAY_V(dpcd_info, DPCDState, DPCD_READABLE_AREA, 0),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void dpcd_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- dc->reset = dpcd_reset;
- dc->vmsd = &vmstate_dpcd;
-}
-
-static const TypeInfo dpcd_info = {
- .name = TYPE_DPCD,
- .parent = TYPE_AUX_SLAVE,
- .instance_size = sizeof(DPCDState),
- .class_init = dpcd_class_init,
- .instance_init = dpcd_init,
-};
-
-static void dpcd_register_types(void)
-{
- type_register_static(&dpcd_info);
-}
-
-type_init(dpcd_register_types)
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index e5be71340..728eb214a 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -1909,10 +1909,9 @@ static const GraphicHwOps exynos4210_fimd_ops = {
.gfx_update = exynos4210_fimd_update,
};
-static void exynos4210_fimd_init(Object *obj)
+static int exynos4210_fimd_init(SysBusDevice *dev)
{
- Exynos4210fimdState *s = EXYNOS4210_FIMD(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ Exynos4210fimdState *s = EXYNOS4210_FIMD(dev);
s->ifb = NULL;
@@ -1920,32 +1919,28 @@ static void exynos4210_fimd_init(Object *obj)
sysbus_init_irq(dev, &s->irq[1]);
sysbus_init_irq(dev, &s->irq[2]);
- memory_region_init_io(&s->iomem, obj, &exynos4210_fimd_mmio_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_fimd_mmio_ops, s,
"exynos4210.fimd", FIMD_REGS_SIZE);
sysbus_init_mmio(dev, &s->iomem);
-}
-
-static void exynos4210_fimd_realize(DeviceState *dev, Error **errp)
-{
- Exynos4210fimdState *s = EXYNOS4210_FIMD(dev);
+ s->console = graphic_console_init(DEVICE(dev), 0, &exynos4210_fimd_ops, s);
- s->console = graphic_console_init(dev, 0, &exynos4210_fimd_ops, s);
+ return 0;
}
static void exynos4210_fimd_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
dc->vmsd = &exynos4210_fimd_vmstate;
dc->reset = exynos4210_fimd_reset;
- dc->realize = exynos4210_fimd_realize;
+ k->init = exynos4210_fimd_init;
}
static const TypeInfo exynos4210_fimd_info = {
.name = TYPE_EXYNOS4210_FIMD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210fimdState),
- .instance_init = exynos4210_fimd_init,
.class_init = exynos4210_fimd_class_init,
};
diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c
index b72fdb171..09dcdb46a 100644
--- a/hw/display/jazz_led.c
+++ b/hw/display/jazz_led.c
@@ -267,20 +267,16 @@ static const GraphicHwOps jazz_led_ops = {
.text_update = jazz_led_text_update,
};
-static void jazz_led_init(Object *obj)
+static int jazz_led_init(SysBusDevice *dev)
{
- LedState *s = JAZZ_LED(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ LedState *s = JAZZ_LED(dev);
- memory_region_init_io(&s->iomem, obj, &led_ops, s, "led", 1);
+ memory_region_init_io(&s->iomem, OBJECT(s), &led_ops, s, "led", 1);
sysbus_init_mmio(dev, &s->iomem);
-}
-static void jazz_led_realize(DeviceState *dev, Error **errp)
-{
- LedState *s = JAZZ_LED(dev);
+ s->con = graphic_console_init(DEVICE(dev), 0, &jazz_led_ops, s);
- s->con = graphic_console_init(dev, 0, &jazz_led_ops, s);
+ return 0;
}
static void jazz_led_reset(DeviceState *d)
@@ -295,18 +291,18 @@ static void jazz_led_reset(DeviceState *d)
static void jazz_led_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = jazz_led_init;
dc->desc = "Jazz LED display",
dc->vmsd = &vmstate_jazz_led;
dc->reset = jazz_led_reset;
- dc->realize = jazz_led_realize;
}
static const TypeInfo jazz_led_info = {
.name = TYPE_JAZZ_LED,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LedState),
- .instance_init = jazz_led_init,
.class_init = jazz_led_class_init,
};
diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c
index 9c0018448..9bc88f93b 100644
--- a/hw/display/milkymist-tmu2.c
+++ b/hw/display/milkymist-tmu2.c
@@ -20,7 +20,7 @@
*
*
* Specification available at:
- * http://milkymist.walle.cc/socdoc/tmu2.pdf
+ * http://www.milkymist.org/socdoc/tmu2.pdf
*
*/
@@ -29,7 +29,6 @@
#include "hw/sysbus.h"
#include "trace.h"
#include "qemu/error-report.h"
-#include "qapi/error.h"
#include <X11/Xlib.h>
#include <epoxy/gl.h>
@@ -444,25 +443,21 @@ static void milkymist_tmu2_reset(DeviceState *d)
}
}
-static void milkymist_tmu2_init(Object *obj)
+static int milkymist_tmu2_init(SysBusDevice *dev)
{
- MilkymistTMU2State *s = MILKYMIST_TMU2(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ MilkymistTMU2State *s = MILKYMIST_TMU2(dev);
+
+ if (tmu2_glx_init(s)) {
+ return 1;
+ }
sysbus_init_irq(dev, &s->irq);
- memory_region_init_io(&s->regs_region, obj, &tmu2_mmio_ops, s,
+ memory_region_init_io(&s->regs_region, OBJECT(s), &tmu2_mmio_ops, s,
"milkymist-tmu2", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
-}
-static void milkymist_tmu2_realize(DeviceState *dev, Error **errp)
-{
- MilkymistTMU2State *s = MILKYMIST_TMU2(dev);
-
- if (tmu2_glx_init(s)) {
- error_setg(errp, "tmu2_glx_init failed");
- }
+ return 0;
}
static const VMStateDescription vmstate_milkymist_tmu2 = {
@@ -478,8 +473,9 @@ static const VMStateDescription vmstate_milkymist_tmu2 = {
static void milkymist_tmu2_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- dc->realize = milkymist_tmu2_realize;
+ k->init = milkymist_tmu2_init;
dc->reset = milkymist_tmu2_reset;
dc->vmsd = &vmstate_milkymist_tmu2;
}
@@ -488,7 +484,6 @@ static const TypeInfo milkymist_tmu2_info = {
.name = TYPE_MILKYMIST_TMU2,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistTMU2State),
- .instance_init = milkymist_tmu2_init,
.class_init = milkymist_tmu2_class_init,
};
diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c
index 177fdac7d..19ca25647 100644
--- a/hw/display/milkymist-vgafb.c
+++ b/hw/display/milkymist-vgafb.c
@@ -19,7 +19,7 @@
*
*
* Specification available at:
- * http://milkymist.walle.cc/socdoc/vgafb.pdf
+ * http://www.milkymist.org/socdoc/vgafb.pdf
*/
#include "qemu/osdep.h"
@@ -292,21 +292,17 @@ static const GraphicHwOps vgafb_ops = {
.gfx_update = vgafb_update_display,
};
-static void milkymist_vgafb_init(Object *obj)
+static int milkymist_vgafb_init(SysBusDevice *dev)
{
- MilkymistVgafbState *s = MILKYMIST_VGAFB(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ MilkymistVgafbState *s = MILKYMIST_VGAFB(dev);
memory_region_init_io(&s->regs_region, OBJECT(s), &vgafb_mmio_ops, s,
"milkymist-vgafb", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
-}
-static void milkymist_vgafb_realize(DeviceState *dev, Error **errp)
-{
- MilkymistVgafbState *s = MILKYMIST_VGAFB(dev);
+ s->con = graphic_console_init(DEVICE(dev), 0, &vgafb_ops, s);
- s->con = graphic_console_init(dev, 0, &vgafb_ops, s);
+ return 0;
}
static int vgafb_post_load(void *opaque, int version_id)
@@ -335,18 +331,18 @@ static Property milkymist_vgafb_properties[] = {
static void milkymist_vgafb_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = milkymist_vgafb_init;
dc->reset = milkymist_vgafb_reset;
dc->vmsd = &vmstate_milkymist_vgafb;
dc->props = milkymist_vgafb_properties;
- dc->realize = milkymist_vgafb_realize;
}
static const TypeInfo milkymist_vgafb_info = {
.name = TYPE_MILKYMIST_VGAFB,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistVgafbState),
- .instance_init = milkymist_vgafb_init,
.class_init = milkymist_vgafb_class_init,
};
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
index 1025ff382..f0ce71fd6 100644
--- a/hw/display/omap_lcd_template.h
+++ b/hw/display/omap_lcd_template.h
@@ -27,7 +27,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if DEPTH == 32
+#if DEPTH == 8
+# define BPP 1
+# define PIXEL_TYPE uint8_t
+#elif DEPTH == 15 || DEPTH == 16
+# define BPP 2
+# define PIXEL_TYPE uint16_t
+#elif DEPTH == 32
# define BPP 4
# define PIXEL_TYPE uint32_t
#else
@@ -146,7 +152,7 @@ static void glue(draw_line12_, DEPTH)(void *opaque,
static void glue(draw_line16_, DEPTH)(void *opaque,
uint8_t *d, const uint8_t *s, int width, int deststep)
{
-#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
uint16_t v;
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
index 07a5effe0..ce1058bf8 100644
--- a/hw/display/omap_lcdc.c
+++ b/hw/display/omap_lcdc.c
@@ -71,9 +71,47 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
#define draw_line_func drawfn
+#define DEPTH 8
+#include "omap_lcd_template.h"
+#define DEPTH 15
+#include "omap_lcd_template.h"
+#define DEPTH 16
+#include "omap_lcd_template.h"
#define DEPTH 32
#include "omap_lcd_template.h"
+static draw_line_func draw_line_table2[33] = {
+ [0 ... 32] = NULL,
+ [8] = draw_line2_8,
+ [15] = draw_line2_15,
+ [16] = draw_line2_16,
+ [32] = draw_line2_32,
+}, draw_line_table4[33] = {
+ [0 ... 32] = NULL,
+ [8] = draw_line4_8,
+ [15] = draw_line4_15,
+ [16] = draw_line4_16,
+ [32] = draw_line4_32,
+}, draw_line_table8[33] = {
+ [0 ... 32] = NULL,
+ [8] = draw_line8_8,
+ [15] = draw_line8_15,
+ [16] = draw_line8_16,
+ [32] = draw_line8_32,
+}, draw_line_table12[33] = {
+ [0 ... 32] = NULL,
+ [8] = draw_line12_8,
+ [15] = draw_line12_15,
+ [16] = draw_line12_16,
+ [32] = draw_line12_32,
+}, draw_line_table16[33] = {
+ [0 ... 32] = NULL,
+ [8] = draw_line16_8,
+ [15] = draw_line16_15,
+ [16] = draw_line16_16,
+ [32] = draw_line16_32,
+};
+
static void omap_update_display(void *opaque)
{
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
@@ -105,25 +143,25 @@ static void omap_update_display(void *opaque)
/* Colour depth */
switch ((omap_lcd->palette[0] >> 12) & 7) {
case 1:
- draw_line = draw_line2_32;
+ draw_line = draw_line_table2[surface_bits_per_pixel(surface)];
bpp = 2;
break;
case 2:
- draw_line = draw_line4_32;
+ draw_line = draw_line_table4[surface_bits_per_pixel(surface)];
bpp = 4;
break;
case 3:
- draw_line = draw_line8_32;
+ draw_line = draw_line_table8[surface_bits_per_pixel(surface)];
bpp = 8;
break;
case 4 ... 7:
if (!omap_lcd->tft)
- draw_line = draw_line12_32;
+ draw_line = draw_line_table12[surface_bits_per_pixel(surface)];
else
- draw_line = draw_line16_32;
+ draw_line = draw_line_table16[surface_bits_per_pixel(surface)];
bpp = 16;
break;
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
index c069c0b7f..d589959f1 100644
--- a/hw/display/pl110.c
+++ b/hw/display/pl110.c
@@ -12,7 +12,6 @@
#include "ui/console.h"
#include "framebuffer.h"
#include "ui/pixel_ops.h"
-#include "qemu/log.h"
#define PL110_CR_EN 0x001
#define PL110_CR_BGR 0x100
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 0e2682d28..919dc5cd3 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -504,7 +504,6 @@ static void interface_set_compression_level(QXLInstance *sin, int level)
qxl_rom_set_dirty(qxl);
}
-#if SPICE_NEEDS_SET_MM_TIME
static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
{
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
@@ -518,7 +517,6 @@ static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
qxl->rom->mm_clock = cpu_to_le32(mm_time);
qxl_rom_set_dirty(qxl);
}
-#endif
static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
{
@@ -895,8 +893,7 @@ static void interface_update_area_complete(QXLInstance *sin,
int qxl_i;
qemu_mutex_lock(&qxl->ssd.lock);
- if (surface_id != 0 || !num_updated_rects ||
- !qxl->render_update_cookie_num) {
+ if (surface_id != 0 || !qxl->render_update_cookie_num) {
qemu_mutex_unlock(&qxl->ssd.lock);
return;
}
@@ -1071,9 +1068,7 @@ static const QXLInterface qxl_interface = {
.attache_worker = interface_attach_worker,
.set_compression_level = interface_set_compression_level,
-#if SPICE_NEEDS_SET_MM_TIME
.set_mm_time = interface_set_mm_time,
-#endif
.get_init_info = interface_get_init_info,
/* the callbacks below are called from spice server thread context */
@@ -1248,7 +1243,6 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
int pci_region;
pcibus_t pci_start;
pcibus_t pci_end;
- MemoryRegion *mr;
intptr_t virt_start;
QXLDevMemSlot memslot;
int i;
@@ -1295,11 +1289,11 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
switch (pci_region) {
case QXL_RAM_RANGE_INDEX:
- mr = &d->vga.vram;
+ virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram);
break;
case QXL_VRAM_RANGE_INDEX:
case 4 /* vram 64bit */:
- mr = &d->vram_bar;
+ virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar);
break;
default:
/* should not happen */
@@ -1307,7 +1301,6 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
return 1;
}
- virt_start = (intptr_t)memory_region_get_ram_ptr(mr);
memslot.slot_id = slot_id;
memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */
memslot.virt_start = virt_start + (guest_start - pci_start);
@@ -1317,8 +1310,7 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
qxl_rom_set_dirty(d);
qemu_spice_add_memslot(&d->ssd, &memslot, async);
- d->guest_slots[slot_id].mr = mr;
- d->guest_slots[slot_id].offset = memslot.virt_start - virt_start;
+ d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
d->guest_slots[slot_id].delta = delta;
d->guest_slots[slot_id].active = 1;
@@ -1345,60 +1337,39 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
}
/* can be also called from spice server thread context */
-static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
- uint32_t *s, uint64_t *o)
+void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
{
uint64_t phys = le64_to_cpu(pqxl);
uint32_t slot = (phys >> (64 - 8)) & 0xff;
uint64_t offset = phys & 0xffffffffffff;
- if (slot >= NUM_MEMSLOTS) {
- qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot,
- NUM_MEMSLOTS);
- return false;
- }
- if (!qxl->guest_slots[slot].active) {
- qxl_set_guest_bug(qxl, "inactive slot %d\n", slot);
- return false;
- }
- if (offset < qxl->guest_slots[slot].delta) {
- qxl_set_guest_bug(qxl,
- "slot %d offset %"PRIu64" < delta %"PRIu64"\n",
- slot, offset, qxl->guest_slots[slot].delta);
- return false;
- }
- offset -= qxl->guest_slots[slot].delta;
- if (offset > qxl->guest_slots[slot].size) {
- qxl_set_guest_bug(qxl,
- "slot %d offset %"PRIu64" > size %"PRIu64"\n",
- slot, offset, qxl->guest_slots[slot].size);
- return false;
- }
-
- *s = slot;
- *o = offset;
- return true;
-}
-
-/* can be also called from spice server thread context */
-void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
-{
- uint64_t offset;
- uint32_t slot;
- void *ptr;
-
switch (group_id) {
case MEMSLOT_GROUP_HOST:
- offset = le64_to_cpu(pqxl) & 0xffffffffffff;
return (void *)(intptr_t)offset;
case MEMSLOT_GROUP_GUEST:
- if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset)) {
+ if (slot >= NUM_MEMSLOTS) {
+ qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot,
+ NUM_MEMSLOTS);
+ return NULL;
+ }
+ if (!qxl->guest_slots[slot].active) {
+ qxl_set_guest_bug(qxl, "inactive slot %d\n", slot);
return NULL;
}
- ptr = memory_region_get_ram_ptr(qxl->guest_slots[slot].mr);
- ptr += qxl->guest_slots[slot].offset;
- ptr += offset;
- return ptr;
+ if (offset < qxl->guest_slots[slot].delta) {
+ qxl_set_guest_bug(qxl,
+ "slot %d offset %"PRIu64" < delta %"PRIu64"\n",
+ slot, offset, qxl->guest_slots[slot].delta);
+ return NULL;
+ }
+ offset -= qxl->guest_slots[slot].delta;
+ if (offset > qxl->guest_slots[slot].size) {
+ qxl_set_guest_bug(qxl,
+ "slot %d offset %"PRIu64" > size %"PRIu64"\n",
+ slot, offset, qxl->guest_slots[slot].size);
+ return NULL;
+ }
+ return qxl->guest_slots[slot].ptr + offset;
}
return NULL;
}
@@ -1813,24 +1784,9 @@ static void qxl_hw_update(void *opaque)
qxl_render_update(qxl);
}
-static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
- uint32_t height, int32_t stride)
-{
- uint64_t offset, size;
- uint32_t slot;
- bool rc;
-
- rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset);
- assert(rc == true);
- size = (uint64_t)height * abs(stride);
- trace_qxl_surfaces_dirty(qxl->id, offset, size);
- qxl_set_dirty(qxl->guest_slots[slot].mr,
- qxl->guest_slots[slot].offset + offset,
- qxl->guest_slots[slot].offset + offset + size);
-}
-
static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
{
+ uintptr_t vram_start;
int i;
if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
@@ -1838,13 +1794,16 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
}
/* dirty the primary surface */
- qxl_dirty_one_surface(qxl, qxl->guest_primary.surface.mem,
- qxl->guest_primary.surface.height,
- qxl->guest_primary.surface.stride);
+ qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
+ qxl->shadow_rom.surface0_area_size);
+
+ vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
/* dirty the off-screen surfaces */
for (i = 0; i < qxl->ssd.num_surfaces; i++) {
QXLSurfaceCmd *cmd;
+ intptr_t surface_offset;
+ int surface_size;
if (qxl->guest_surfaces.cmds[i] == 0) {
continue;
@@ -1854,9 +1813,15 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
MEMSLOT_GROUP_GUEST);
assert(cmd);
assert(cmd->type == QXL_SURFACE_CMD_CREATE);
- qxl_dirty_one_surface(qxl, cmd->u.surface_create.data,
- cmd->u.surface_create.height,
- cmd->u.surface_create.stride);
+ surface_offset = (intptr_t)qxl_phys2virt(qxl,
+ cmd->u.surface_create.data,
+ MEMSLOT_GROUP_GUEST);
+ assert(surface_offset);
+ surface_offset -= vram_start;
+ surface_size = cmd->u.surface_create.height *
+ abs(cmd->u.surface_create.stride);
+ trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
+ qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
}
}
@@ -1949,7 +1914,7 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl)
/* vram (surfaces, 64bit, bar 4+5) */
if (qxl->vram_size_mb != -1) {
- qxl->vram_size = (uint64_t)qxl->vram_size_mb * 1024 * 1024;
+ qxl->vram_size = qxl->vram_size_mb * 1024 * 1024;
}
if (qxl->vram_size < qxl->vram32_size) {
qxl->vram_size = qxl->vram32_size;
@@ -2055,9 +2020,9 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp)
dprint(qxl, 1, "ram/%s: %d MB [region 0]\n",
qxl->id == 0 ? "pri" : "sec",
qxl->vga.vram_size / (1024*1024));
- dprint(qxl, 1, "vram/32: %" PRIx64 "d MB [region 1]\n",
+ dprint(qxl, 1, "vram/32: %d MB [region 1]\n",
qxl->vram32_size / (1024*1024));
- dprint(qxl, 1, "vram/64: %" PRIx64 "d MB %s\n",
+ dprint(qxl, 1, "vram/64: %d MB %s\n",
qxl->vram_size / (1024*1024),
qxl->vram32_size < qxl->vram_size ? "[region 4]" : "[unmapped]");
@@ -2311,7 +2276,7 @@ static VMStateDescription qxl_vmstate = {
static Property qxl_properties[] = {
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size,
64 * 1024 * 1024),
- DEFINE_PROP_UINT64("vram_size", PCIQXLDevice, vram32_size,
+ DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram32_size,
64 * 1024 * 1024),
DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision,
QXL_DEFAULT_REVISION),
diff --git a/hw/display/qxl.h b/hw/display/qxl.h
index d2d49dd93..2ddf065e1 100644
--- a/hw/display/qxl.h
+++ b/hw/display/qxl.h
@@ -1,5 +1,5 @@
#ifndef HW_QXL_H
-#define HW_QXL_H
+#define HW_QXL_H 1
#include "qemu-common.h"
@@ -53,8 +53,7 @@ typedef struct PCIQXLDevice {
struct guest_slots {
QXLMemSlot slot;
- MemoryRegion *mr;
- uint64_t offset;
+ void *ptr;
uint64_t size;
uint64_t delta;
uint32_t active;
@@ -105,9 +104,9 @@ typedef struct PCIQXLDevice {
#endif
/* vram pci bar */
- uint64_t vram_size;
+ uint32_t vram_size;
MemoryRegion vram_bar;
- uint64_t vram32_size;
+ uint32_t vram32_size;
MemoryRegion vram32_bar;
/* io bar */
diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
index 6d1faf44a..14c1bf339 100644
--- a/hw/display/ssd0323.c
+++ b/hw/display/ssd0323.c
@@ -361,7 +361,7 @@ static const GraphicHwOps ssd0323_ops = {
.gfx_update = ssd0323_update_display,
};
-static void ssd0323_realize(SSISlave *d, Error **errp)
+static int ssd0323_init(SSISlave *d)
{
DeviceState *dev = DEVICE(d);
ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, d);
@@ -375,13 +375,14 @@ static void ssd0323_realize(SSISlave *d, Error **errp)
register_savevm(dev, "ssd0323_oled", -1, 1,
ssd0323_save, ssd0323_load, s);
+ return 0;
}
static void ssd0323_class_init(ObjectClass *klass, void *data)
{
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
- k->realize = ssd0323_realize;
+ k->init = ssd0323_init;
k->transfer = ssd0323_transfer;
k->cs_polarity = SSI_CS_HIGH;
}
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
index 92f7120ac..da3ceceb0 100644
--- a/hw/display/tc6393xb.c
+++ b/hw/display/tc6393xb.c
@@ -12,7 +12,6 @@
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu/host-utils.h"
#include "hw/hw.h"
#include "hw/devices.h"
#include "hw/block/flash.h"
diff --git a/hw/display/trace-events b/hw/display/trace-events
deleted file mode 100644
index 332ababd8..000000000
--- a/hw/display/trace-events
+++ /dev/null
@@ -1,122 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/display/jazz_led.c
-jazz_led_read(uint64_t addr, uint8_t val) "read addr=0x%"PRIx64": 0x%x"
-jazz_led_write(uint64_t addr, uint8_t new) "write addr=0x%"PRIx64": 0x%x"
-
-# hw/display/xenfb.c
-xenfb_mouse_event(void *opaque, int dx, int dy, int dz, int button_state, int abs_pointer_wanted) "%p x %d y %d z %d bs %#x abs %d"
-xenfb_input_connected(void *xendev, int abs_pointer_wanted) "%p abs %d"
-
-# hw/display/g364fb.c
-g364fb_read(uint64_t addr, uint32_t val) "read addr=0x%"PRIx64": 0x%x"
-g364fb_write(uint64_t addr, uint32_t new) "write addr=0x%"PRIx64": 0x%x"
-
-# hw/display/milkymist-tmu2.c
-milkymist_tmu2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_tmu2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_tmu2_start(void) "Start TMU"
-milkymist_tmu2_pulse_irq(void) "Pulse IRQ"
-
-# hw/display/milkymist-vgafb.c
-milkymist_vgafb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_vgafb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-
-# hw/display/vmware_vga.c
-vmware_value_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
-vmware_value_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
-vmware_palette_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
-vmware_palette_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
-vmware_scratch_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
-vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
-vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp"
-
-# hw/display/virtio-gpu.c
-virtio_gpu_features(bool virgl) "virgl %d"
-virtio_gpu_cmd_get_display_info(void) ""
-virtio_gpu_cmd_get_caps(void) ""
-virtio_gpu_cmd_set_scanout(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d"
-virtio_gpu_cmd_res_create_2d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h) "res 0x%x, fmt 0x%x, w %d, h %d"
-virtio_gpu_cmd_res_create_3d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h, uint32_t d) "res 0x%x, fmt 0x%x, w %d, h %d, d %d"
-virtio_gpu_cmd_res_unref(uint32_t res) "res 0x%x"
-virtio_gpu_cmd_res_back_attach(uint32_t res) "res 0x%x"
-virtio_gpu_cmd_res_back_detach(uint32_t res) "res 0x%x"
-virtio_gpu_cmd_res_xfer_toh_2d(uint32_t res) "res 0x%x"
-virtio_gpu_cmd_res_xfer_toh_3d(uint32_t res) "res 0x%x"
-virtio_gpu_cmd_res_xfer_fromh_3d(uint32_t res) "res 0x%x"
-virtio_gpu_cmd_res_flush(uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "res 0x%x, w %d, h %d, x %d, y %d"
-virtio_gpu_cmd_ctx_create(uint32_t ctx, const char *name) "ctx 0x%x, name %s"
-virtio_gpu_cmd_ctx_destroy(uint32_t ctx) "ctx 0x%x"
-virtio_gpu_cmd_ctx_res_attach(uint32_t ctx, uint32_t res) "ctx 0x%x, res 0x%x"
-virtio_gpu_cmd_ctx_res_detach(uint32_t ctx, uint32_t res) "ctx 0x%x, res 0x%x"
-virtio_gpu_cmd_ctx_submit(uint32_t ctx, uint32_t size) "ctx 0x%x, size %d"
-virtio_gpu_update_cursor(uint32_t scanout, uint32_t x, uint32_t y, const char *type, uint32_t res) "scanout %d, x %d, y %d, %s, res 0x%x"
-virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 0x%" PRIx64 ", type 0x%x"
-virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
-
-# hw/display/qxl.c
-disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d"
-disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t val) "%d %s addr=%u val=%u"
-qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %ux%u mem=%" PRIx64 " %u,%u"
-qxl_create_guest_primary_rest(int qid, int32_t stride, uint32_t type, uint32_t flags) "%d %d,%d,%d"
-qxl_destroy_primary(int qid) "%d"
-qxl_enter_vga_mode(int qid) "%d"
-qxl_exit_vga_mode(int qid) "%d"
-qxl_hard_reset(int qid, int64_t loadvm) "%d loadvm=%"PRId64
-qxl_interface_async_complete_io(int qid, uint32_t current_async, void *cookie) "%d current=%d cookie=%p"
-qxl_interface_attach_worker(int qid) "%d"
-qxl_interface_get_init_info(int qid) "%d"
-qxl_interface_set_compression_level(int qid, int64_t level) "%d %"PRId64
-qxl_interface_update_area_complete(int qid, uint32_t surface_id, uint32_t dirty_left, uint32_t dirty_right, uint32_t dirty_top, uint32_t dirty_bottom) "%d surface=%d [%d,%d,%d,%d]"
-qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d #=%d"
-qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
-qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
-qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
-qxl_io_log(int qid, const uint8_t *log_buf) "%d %s"
-qxl_io_read_unexpected(int qid) "%d"
-qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)"
-qxl_io_write(int qid, const char *mode, uint64_t addr, const char *aname, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " (%s) val=%"PRIu64" size=%u async=%d"
-qxl_memslot_add_guest(int qid, uint32_t slot_id, uint64_t guest_start, uint64_t guest_end) "%d %u: guest phys 0x%"PRIx64 " - 0x%" PRIx64
-qxl_post_load(int qid, const char *mode) "%d %s"
-qxl_pre_load(int qid) "%d"
-qxl_pre_save(int qid) "%d"
-qxl_reset_surfaces(int qid) "%d"
-qxl_ring_command_check(int qid, const char *mode) "%d %s"
-qxl_ring_command_get(int qid, const char *mode) "%d %s"
-qxl_ring_command_req_notification(int qid) "%d"
-qxl_ring_cursor_check(int qid, const char *mode) "%d %s"
-qxl_ring_cursor_get(int qid, const char *mode) "%d %s"
-qxl_ring_cursor_req_notification(int qid) "%d"
-qxl_ring_res_push(int qid, const char *mode, uint32_t surface_count, uint32_t free_res, void *last_release, const char *notify) "%d %s s#=%d res#=%d last=%p notify=%s"
-qxl_ring_res_push_rest(int qid, uint32_t ring_has, uint32_t ring_size, uint32_t prod, uint32_t cons) "%d ring %d/%d [%d,%d]"
-qxl_ring_res_put(int qid, uint32_t free_res) "%d #res=%d"
-qxl_set_mode(int qid, int modenr, uint32_t x_res, uint32_t y_res, uint32_t bits, uint64_t devmem) "%d mode=%d [ x=%d y=%d @ bpp=%d devmem=0x%" PRIx64 " ]"
-qxl_soft_reset(int qid) "%d"
-qxl_spice_destroy_surfaces_complete(int qid) "%d"
-qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d"
-qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d"
-qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) "%d sid=%d async=%d"
-qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) "%d s#=%d, res#=%d"
-qxl_spice_monitors_config(int qid) "%d"
-qxl_spice_loadvm_commands(int qid, void *ext, uint32_t count) "%d ext=%p count=%d"
-qxl_spice_oom(int qid) "%d"
-qxl_spice_reset_cursor(int qid) "%d"
-qxl_spice_reset_image_cache(int qid) "%d"
-qxl_spice_reset_memslots(int qid) "%d"
-qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]"
-qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d"
-qxl_surfaces_dirty(int qid, uint64_t offset, uint64_t size) "%d offset=0x%"PRIx64" size=0x%"PRIx64
-qxl_send_events(int qid, uint32_t events) "%d %d"
-qxl_send_events_vm_stopped(int qid, uint32_t events) "%d %d"
-qxl_set_guest_bug(int qid) "%d"
-qxl_interrupt_client_monitors_config(int qid, int num_heads, void *heads) "%d %d %p"
-qxl_client_monitors_config_unsupported_by_guest(int qid, uint32_t int_mask, void *client_monitors_config) "%d %X %p"
-qxl_client_monitors_config_unsupported_by_device(int qid, int revision) "%d revision=%d"
-qxl_client_monitors_config_capped(int qid, int requested, int limit) "%d %d %d"
-qxl_client_monitors_config_crc(int qid, unsigned size, uint32_t crc32) "%d %u %u"
-qxl_set_client_capabilities_unsupported_by_revision(int qid, int revision) "%d revision=%d"
-
-# hw/display/qxl-render.c
-qxl_render_blit(int32_t stride, int32_t left, int32_t right, int32_t top, int32_t bottom) "stride=%d [%d, %d, %d, %d]"
-qxl_render_guest_primary_resized(int32_t width, int32_t height, int32_t stride, int32_t bytes_pp, int32_t bits_pp) "%dx%d, stride %d, bpp %d, depth %d"
-qxl_render_update_area_done(void *cookie) "%p"
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 2a88b3c1b..9ebc54f22 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -700,7 +700,9 @@ static void vbe_update_vgaregs(VGACommonState *s)
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
{
VGACommonState *s = opaque;
- return s->vbe_index;
+ uint32_t val;
+ val = s->vbe_index;
+ return val;
}
uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
diff --git a/hw/display/vga.h b/hw/display/vga.h
index 16886f5ee..d917046da 100644
--- a/hw/display/vga.h
+++ b/hw/display/vga.h
@@ -14,8 +14,8 @@
*
*/
-#ifndef LINUX_VIDEO_VGA_H
-#define LINUX_VIDEO_VGA_H
+#ifndef __linux_video_vga_h__
+#define __linux_video_vga_h__
/* Some of the code below is taken from SVGAlib. The original,
unmodified copyright notice for that code is below. */
@@ -156,4 +156,4 @@
/* VGA graphics controller bit masks */
#define VGA_GR06_GRAPHICS_MODE 0x01
-#endif /* LINUX_VIDEO_VGA_H */
+#endif /* __linux_video_vga_h__ */
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index dd6c958da..3ce5544ef 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -21,11 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-
#ifndef HW_VGA_INT_H
-#define HW_VGA_INT_H
+#define HW_VGA_INT_H 1
-#include "hw/hw.h"
+#include <hw/hw.h>
#include "exec/memory.h"
#define ST01_V_RETRACE 0x08
diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c
index 758d33a09..fa192946a 100644
--- a/hw/display/virtio-gpu-3d.c
+++ b/hw/display/virtio-gpu-3d.c
@@ -17,11 +17,10 @@
#include "trace.h"
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-gpu.h"
-#include "qapi/error.h"
#ifdef CONFIG_VIRGL
-#include <virglrenderer.h>
+#include "virglrenderer.h"
static struct virgl_renderer_callbacks virtio_gpu_3d_cbs;
@@ -128,7 +127,7 @@ static void virgl_cmd_resource_flush(VirtIOGPU *g,
trace_virtio_gpu_cmd_res_flush(rf.resource_id,
rf.r.width, rf.r.height, rf.r.x, rf.r.y);
- for (i = 0; i < g->conf.max_outputs; i++) {
+ for (i = 0; i < VIRTIO_GPU_MAX_SCANOUT; i++) {
if (g->scanout[i].resource_id != rf.resource_id) {
continue;
}
@@ -147,7 +146,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
ss.r.width, ss.r.height, ss.r.x, ss.r.y);
- if (ss.scanout_id >= g->conf.max_outputs) {
+ if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUT) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
__func__, ss.scanout_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
@@ -171,14 +170,13 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
virgl_renderer_force_ctx_0();
dpy_gl_scanout(g->scanout[ss.scanout_id].con, info.tex_id,
info.flags & 1 /* FIXME: Y_0_TOP */,
- info.width, info.height,
ss.r.x, ss.r.y, ss.r.width, ss.r.height);
} else {
if (ss.scanout_id != 0) {
dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL);
}
dpy_gl_scanout(g->scanout[ss.scanout_id].con, 0, false,
- 0, 0, 0, 0, 0, 0);
+ 0, 0, 0, 0);
}
g->scanout[ss.scanout_id].resource_id = ss.resource_id;
}
@@ -285,7 +283,7 @@ static void virgl_resource_attach_backing(VirtIOGPU *g,
VIRTIO_GPU_FILL_CMD(att_rb);
trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id);
- ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, NULL, &res_iovs);
+ ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, &res_iovs);
if (ret != 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
@@ -581,7 +579,7 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g)
if (i != 0) {
dpy_gfx_replace_surface(g->scanout[i].con, NULL);
}
- dpy_gl_scanout(g->scanout[i].con, 0, false, 0, 0, 0, 0, 0, 0);
+ dpy_gl_scanout(g->scanout[i].con, 0, false, 0, 0, 0, 0);
}
}
diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c
index 34a724c75..a71b230d3 100644
--- a/hw/display/virtio-gpu-pci.c
+++ b/hw/display/virtio-gpu-pci.c
@@ -30,7 +30,9 @@ static void virtio_gpu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
int i;
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
- virtio_pci_force_virtio_1(vpci_dev);
+ /* force virtio-1.0 */
+ vpci_dev->flags &= ~VIRTIO_PCI_FLAG_DISABLE_MODERN;
+ vpci_dev->flags |= VIRTIO_PCI_FLAG_DISABLE_LEGACY;
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
for (i = 0; i < g->conf.max_outputs; i++) {
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 7fe6ed8bf..c181fb364 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -19,17 +19,12 @@
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-gpu.h"
#include "hw/virtio/virtio-bus.h"
-#include "migration/migration.h"
-#include "qemu/log.h"
-#include "qapi/error.h"
-
-#define VIRTIO_GPU_VM_VERSION 1
static struct virtio_gpu_simple_resource*
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
#ifdef CONFIG_VIRGL
-#include <virglrenderer.h>
+#include "virglrenderer.h"
#define VIRGL(_g, _virgl, _simple, ...) \
do { \
if (_g->use_virgl_renderer) { \
@@ -97,7 +92,7 @@ static void update_cursor_data_virgl(VirtIOGPU *g,
static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
{
struct virtio_gpu_scanout *s;
- bool move = cursor->hdr.type == VIRTIO_GPU_CMD_MOVE_CURSOR;
+ bool move = cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR;
if (cursor->pos.scanout_id >= g->conf.max_outputs) {
return;
@@ -110,7 +105,7 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
move ? "move" : "update",
cursor->resource_id);
- if (!move) {
+ if (move) {
if (!s->current_cursor) {
s->current_cursor = cursor_alloc(64, 64);
}
@@ -123,11 +118,6 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
g, s, cursor->resource_id);
}
dpy_cursor_define(s->con, s->current_cursor);
-
- s->cursor = *cursor;
- } else {
- s->cursor.pos.x = cursor->pos.x;
- s->cursor.pos.y = cursor->pos.y;
}
dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
cursor->resource_id ? 1 : 0);
@@ -474,7 +464,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
pixman_region_init_rect(&flush_region,
rf.r.x, rf.r.y, rf.r.width, rf.r.height);
- for (i = 0; i < g->conf.max_outputs; i++) {
+ for (i = 0; i < VIRTIO_GPU_MAX_SCANOUT; i++) {
struct virtio_gpu_scanout *scanout;
pixman_region16_t region, finalregion;
pixman_box16_t *extents;
@@ -503,11 +493,6 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
pixman_region_fini(&flush_region);
}
-static void virtio_unref_resource(pixman_image_t *image, void *data)
-{
- pixman_image_unref(data);
-}
-
static void virtio_gpu_set_scanout(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
@@ -522,13 +507,6 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
ss.r.width, ss.r.height, ss.r.x, ss.r.y);
- if (ss.scanout_id >= g->conf.max_outputs) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
- __func__, ss.scanout_id);
- cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
- return;
- }
-
g->enable = 1;
if (ss.resource_id == 0) {
scanout = &g->scanout[ss.scanout_id];
@@ -538,7 +516,8 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
res->scanout_bitmask &= ~(1 << ss.scanout_id);
}
}
- if (ss.scanout_id == 0) {
+ if (ss.scanout_id == 0 ||
+ ss.scanout_id >= g->conf.max_outputs) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: illegal scanout id specified %d",
__func__, ss.scanout_id);
@@ -553,6 +532,14 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
}
/* create a surface for this scanout */
+ if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUT ||
+ ss.scanout_id >= g->conf.max_outputs) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
+ __func__, ss.scanout_id);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+ return;
+ }
+
res = virtio_gpu_find_resource(g, ss.resource_id);
if (!res) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
@@ -584,15 +571,8 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
!= ((uint8_t *)pixman_image_get_data(res->image) + offset) ||
scanout->width != ss.r.width ||
scanout->height != ss.r.height) {
- pixman_image_t *rect;
- void *ptr = (uint8_t *)pixman_image_get_data(res->image) + offset;
- rect = pixman_image_create_bits(format, ss.r.width, ss.r.height, ptr,
- pixman_image_get_stride(res->image));
- pixman_image_ref(res->image);
- pixman_image_set_destroy_function(rect, virtio_unref_resource,
- res->image);
/* realloc the surface ptr */
- scanout->ds = qemu_create_displaysurface_pixman(rect);
+ scanout->ds = qemu_create_displaysurface_pixman(res->image);
if (!scanout->ds) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
@@ -610,7 +590,7 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
struct virtio_gpu_ctrl_command *cmd,
- uint64_t **addr, struct iovec **iov)
+ struct iovec **iov)
{
struct virtio_gpu_mem_entry *ents;
size_t esize, s;
@@ -636,16 +616,10 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
}
*iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries);
- if (addr) {
- *addr = g_malloc0(sizeof(uint64_t) * ab->nr_entries);
- }
for (i = 0; i < ab->nr_entries; i++) {
hwaddr len = ents[i].length;
(*iov)[i].iov_len = ents[i].length;
(*iov)[i].iov_base = cpu_physical_memory_map(ents[i].addr, &len, 1);
- if (addr) {
- (*addr)[i] = ents[i].addr;
- }
if (!(*iov)[i].iov_base || len != ents[i].length) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
" resource %d element %d\n",
@@ -653,10 +627,6 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
virtio_gpu_cleanup_mapping_iov(*iov, i);
g_free(ents);
*iov = NULL;
- if (addr) {
- g_free(*addr);
- *addr = NULL;
- }
return -1;
}
}
@@ -680,8 +650,6 @@ static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res)
virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt);
res->iov = NULL;
res->iov_cnt = 0;
- g_free(res->addrs);
- res->addrs = NULL;
}
static void
@@ -703,7 +671,7 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
return;
}
- ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->addrs, &res->iov);
+ ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->iov);
if (ret != 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
@@ -911,7 +879,7 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
{
VirtIOGPU *g = opaque;
- if (idx >= g->conf.max_outputs) {
+ if (idx > g->conf.max_outputs) {
return -1;
}
@@ -935,14 +903,8 @@ static void virtio_gpu_gl_block(void *opaque, bool block)
{
VirtIOGPU *g = opaque;
- if (block) {
- g->renderer_blocked++;
- } else {
- g->renderer_blocked--;
- }
- assert(g->renderer_blocked >= 0);
-
- if (g->renderer_blocked == 0) {
+ g->renderer_blocked = block;
+ if (!block) {
virtio_gpu_process_cmdq(g);
}
}
@@ -955,154 +917,11 @@ const GraphicHwOps virtio_gpu_ops = {
.gl_block = virtio_gpu_gl_block,
};
-static const VMStateDescription vmstate_virtio_gpu_scanout = {
- .name = "virtio-gpu-one-scanout",
- .version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(resource_id, struct virtio_gpu_scanout),
- VMSTATE_UINT32(width, struct virtio_gpu_scanout),
- VMSTATE_UINT32(height, struct virtio_gpu_scanout),
- VMSTATE_INT32(x, struct virtio_gpu_scanout),
- VMSTATE_INT32(y, struct virtio_gpu_scanout),
- VMSTATE_UINT32(cursor.resource_id, struct virtio_gpu_scanout),
- VMSTATE_UINT32(cursor.hot_x, struct virtio_gpu_scanout),
- VMSTATE_UINT32(cursor.hot_y, struct virtio_gpu_scanout),
- VMSTATE_UINT32(cursor.pos.x, struct virtio_gpu_scanout),
- VMSTATE_UINT32(cursor.pos.y, struct virtio_gpu_scanout),
- VMSTATE_END_OF_LIST()
- },
+static const VMStateDescription vmstate_virtio_gpu_unmigratable = {
+ .name = "virtio-gpu",
+ .unmigratable = 1,
};
-static const VMStateDescription vmstate_virtio_gpu_scanouts = {
- .name = "virtio-gpu-scanouts",
- .version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(enable, struct VirtIOGPU),
- VMSTATE_UINT32_EQUAL(conf.max_outputs, struct VirtIOGPU),
- VMSTATE_STRUCT_VARRAY_UINT32(scanout, struct VirtIOGPU,
- conf.max_outputs, 1,
- vmstate_virtio_gpu_scanout,
- struct virtio_gpu_scanout),
- VMSTATE_END_OF_LIST()
- },
-};
-
-static void virtio_gpu_save(QEMUFile *f, void *opaque, size_t size)
-{
- VirtIOGPU *g = opaque;
- VirtIODevice *vdev = VIRTIO_DEVICE(g);
- struct virtio_gpu_simple_resource *res;
- int i;
-
- virtio_save(vdev, f);
-
- /* in 2d mode we should never find unprocessed commands here */
- assert(QTAILQ_EMPTY(&g->cmdq));
-
- QTAILQ_FOREACH(res, &g->reslist, next) {
- qemu_put_be32(f, res->resource_id);
- qemu_put_be32(f, res->width);
- qemu_put_be32(f, res->height);
- qemu_put_be32(f, res->format);
- qemu_put_be32(f, res->iov_cnt);
- for (i = 0; i < res->iov_cnt; i++) {
- qemu_put_be64(f, res->addrs[i]);
- qemu_put_be32(f, res->iov[i].iov_len);
- }
- qemu_put_buffer(f, (void *)pixman_image_get_data(res->image),
- pixman_image_get_stride(res->image) * res->height);
- }
- qemu_put_be32(f, 0); /* end of list */
-
- vmstate_save_state(f, &vmstate_virtio_gpu_scanouts, g, NULL);
-}
-
-static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size)
-{
- VirtIOGPU *g = opaque;
- VirtIODevice *vdev = VIRTIO_DEVICE(g);
- struct virtio_gpu_simple_resource *res;
- struct virtio_gpu_scanout *scanout;
- uint32_t resource_id, pformat;
- int i, ret;
-
- ret = virtio_load(vdev, f, VIRTIO_GPU_VM_VERSION);
- if (ret) {
- return ret;
- }
-
- resource_id = qemu_get_be32(f);
- while (resource_id != 0) {
- res = g_new0(struct virtio_gpu_simple_resource, 1);
- res->resource_id = resource_id;
- res->width = qemu_get_be32(f);
- res->height = qemu_get_be32(f);
- res->format = qemu_get_be32(f);
- res->iov_cnt = qemu_get_be32(f);
-
- /* allocate */
- pformat = get_pixman_format(res->format);
- if (!pformat) {
- return -EINVAL;
- }
- res->image = pixman_image_create_bits(pformat,
- res->width, res->height,
- NULL, 0);
- if (!res->image) {
- return -EINVAL;
- }
-
- res->addrs = g_new(uint64_t, res->iov_cnt);
- res->iov = g_new(struct iovec, res->iov_cnt);
-
- /* read data */
- for (i = 0; i < res->iov_cnt; i++) {
- res->addrs[i] = qemu_get_be64(f);
- res->iov[i].iov_len = qemu_get_be32(f);
- }
- qemu_get_buffer(f, (void *)pixman_image_get_data(res->image),
- pixman_image_get_stride(res->image) * res->height);
-
- /* restore mapping */
- for (i = 0; i < res->iov_cnt; i++) {
- hwaddr len = res->iov[i].iov_len;
- res->iov[i].iov_base =
- cpu_physical_memory_map(res->addrs[i], &len, 1);
- if (!res->iov[i].iov_base || len != res->iov[i].iov_len) {
- return -EINVAL;
- }
- }
-
- QTAILQ_INSERT_HEAD(&g->reslist, res, next);
-
- resource_id = qemu_get_be32(f);
- }
-
- /* load & apply scanout state */
- vmstate_load_state(f, &vmstate_virtio_gpu_scanouts, g, 1);
- for (i = 0; i < g->conf.max_outputs; i++) {
- scanout = &g->scanout[i];
- if (!scanout->resource_id) {
- continue;
- }
- res = virtio_gpu_find_resource(g, scanout->resource_id);
- if (!res) {
- return -EINVAL;
- }
- scanout->ds = qemu_create_displaysurface_pixman(res->image);
- if (!scanout->ds) {
- return -EINVAL;
- }
-
- dpy_gfx_replace_surface(scanout->con, scanout->ds);
- dpy_gfx_update(scanout->con, 0, 0, scanout->width, scanout->height);
- update_cursor(g, &scanout->cursor);
- res->scanout_bitmask |= (1 << i);
- }
-
- return 0;
-}
-
static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
@@ -1110,11 +929,6 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
bool have_virgl;
int i;
- if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) {
- error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS);
- return;
- }
-
g->config_size = sizeof(struct virtio_gpu_config);
g->virtio_config.num_scanouts = g->conf.max_outputs;
virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
@@ -1160,19 +974,7 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
}
}
- if (virtio_gpu_virgl_enabled(g->conf)) {
- error_setg(&g->migration_blocker, "virgl is not yet migratable");
- migrate_add_blocker(g->migration_blocker);
- }
-}
-
-static void virtio_gpu_device_unrealize(DeviceState *qdev, Error **errp)
-{
- VirtIOGPU *g = VIRTIO_GPU(qdev);
- if (g->migration_blocker) {
- migrate_del_blocker(g->migration_blocker);
- error_free(g->migration_blocker);
- }
+ vmstate_register(qdev, -1, &vmstate_virtio_gpu_unmigratable, g);
}
static void virtio_gpu_instance_init(Object *obj)
@@ -1219,9 +1021,6 @@ static void virtio_gpu_reset(VirtIODevice *vdev)
#endif
}
-VMSTATE_VIRTIO_DEVICE(gpu, VIRTIO_GPU_VM_VERSION, virtio_gpu_load,
- virtio_gpu_save);
-
static Property virtio_gpu_properties[] = {
DEFINE_PROP_UINT32("max_outputs", VirtIOGPU, conf.max_outputs, 1),
#ifdef CONFIG_VIRGL
@@ -1239,7 +1038,6 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
vdc->realize = virtio_gpu_device_realize;
- vdc->unrealize = virtio_gpu_device_unrealize;
vdc->get_config = virtio_gpu_get_config;
vdc->set_config = virtio_gpu_set_config;
vdc->get_features = virtio_gpu_get_features;
@@ -1248,7 +1046,6 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data)
vdc->reset = virtio_gpu_reset;
dc->props = virtio_gpu_properties;
- dc->vmsd = &vmstate_virtio_gpu;
}
static const TypeInfo virtio_gpu_info = {
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index 5b510a17f..e58b165ae 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -4,7 +4,6 @@
#include "ui/console.h"
#include "vga_int.h"
#include "hw/virtio/virtio-pci.h"
-#include "qapi/error.h"
/*
* virtio-vga: This extends VirtioPCIProxy.
@@ -84,24 +83,12 @@ static const GraphicHwOps virtio_vga_ops = {
.gl_block = virtio_vga_gl_block,
};
-static const VMStateDescription vmstate_virtio_vga = {
- .name = "virtio-vga",
- .version_id = 2,
- .minimum_version_id = 2,
- .fields = (VMStateField[]) {
- /* no pci stuff here, saving the virtio device will handle that */
- VMSTATE_STRUCT(vga, VirtIOVGA, 0, vmstate_vga_common, VGACommonState),
- VMSTATE_END_OF_LIST()
- }
-};
-
/* VGA device wrapper around PCI device around virtio GPU */
static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
VirtIOVGA *vvga = VIRTIO_VGA(vpci_dev);
VirtIOGPU *g = &vvga->vdev;
VGACommonState *vga = &vvga->vga;
- Error *err = NULL;
uint32_t offset;
int i;
@@ -134,12 +121,10 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
/* init virtio bits */
qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus));
- virtio_pci_force_virtio_1(vpci_dev);
- object_property_set_bool(OBJECT(g), true, "realized", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
+ /* force virtio-1.0 */
+ vpci_dev->flags &= ~VIRTIO_PCI_FLAG_DISABLE_MODERN;
+ vpci_dev->flags |= VIRTIO_PCI_FLAG_DISABLE_LEGACY;
+ object_property_set_bool(OBJECT(g), true, "realized", errp);
/* add stdvga mmio regions */
pci_std_vga_mmio_region_init(vga, &vpci_dev->modern_bar,
@@ -177,7 +162,6 @@ static void virtio_vga_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->props = virtio_vga_properties;
dc->reset = virtio_vga_reset;
- dc->vmsd = &vmstate_virtio_vga;
dc->hotpluggable = false;
k->realize = virtio_vga_realize;
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 46b7d5ede..9866dfda5 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -25,6 +25,7 @@
*/
#include "qemu/osdep.h"
+#include <sys/mman.h>
#include "hw/hw.h"
#include "ui/console.h"
@@ -471,9 +472,9 @@ static int xenfb_map_fb(struct XenFB *xenfb)
xenfb->pixels = NULL;
}
- xenfb->fbpages = DIV_ROUND_UP(xenfb->fb_len, XC_PAGE_SIZE);
+ xenfb->fbpages = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
n_fbdirs = xenfb->fbpages * mode / 8;
- n_fbdirs = DIV_ROUND_UP(n_fbdirs, XC_PAGE_SIZE);
+ n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
pgmfns = g_malloc0(sizeof(xen_pfn_t) * n_fbdirs);
fbmfns = g_malloc0(sizeof(xen_pfn_t) * xenfb->fbpages);
diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
deleted file mode 100644
index f43eb0930..000000000
--- a/hw/display/xlnx_dp.c
+++ /dev/null
@@ -1,1338 +0,0 @@
-/*
- * xlnx_dp.c
- *
- * 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/>.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "hw/display/xlnx_dp.h"
-
-#ifndef DEBUG_DP
-#define DEBUG_DP 0
-#endif
-
-#define DPRINTF(fmt, ...) do { \
- if (DEBUG_DP) { \
- qemu_log("xlnx_dp: " fmt , ## __VA_ARGS__); \
- } \
-} while (0);
-
-/*
- * Register offset for DP.
- */
-#define DP_LINK_BW_SET (0x0000 >> 2)
-#define DP_LANE_COUNT_SET (0x0004 >> 2)
-#define DP_ENHANCED_FRAME_EN (0x0008 >> 2)
-#define DP_TRAINING_PATTERN_SET (0x000C >> 2)
-#define DP_LINK_QUAL_PATTERN_SET (0x0010 >> 2)
-#define DP_SCRAMBLING_DISABLE (0x0014 >> 2)
-#define DP_DOWNSPREAD_CTRL (0x0018 >> 2)
-#define DP_SOFTWARE_RESET (0x001C >> 2)
-#define DP_TRANSMITTER_ENABLE (0x0080 >> 2)
-#define DP_MAIN_STREAM_ENABLE (0x0084 >> 2)
-#define DP_FORCE_SCRAMBLER_RESET (0x00C0 >> 2)
-#define DP_VERSION_REGISTER (0x00F8 >> 2)
-#define DP_CORE_ID (0x00FC >> 2)
-
-#define DP_AUX_COMMAND_REGISTER (0x0100 >> 2)
-#define AUX_ADDR_ONLY_MASK (0x1000)
-#define AUX_COMMAND_MASK (0x0F00)
-#define AUX_COMMAND_SHIFT (8)
-#define AUX_COMMAND_NBYTES (0x000F)
-
-#define DP_AUX_WRITE_FIFO (0x0104 >> 2)
-#define DP_AUX_ADDRESS (0x0108 >> 2)
-#define DP_AUX_CLOCK_DIVIDER (0x010C >> 2)
-#define DP_TX_USER_FIFO_OVERFLOW (0x0110 >> 2)
-#define DP_INTERRUPT_SIGNAL_STATE (0x0130 >> 2)
-#define DP_AUX_REPLY_DATA (0x0134 >> 2)
-#define DP_AUX_REPLY_CODE (0x0138 >> 2)
-#define DP_AUX_REPLY_COUNT (0x013C >> 2)
-#define DP_REPLY_DATA_COUNT (0x0148 >> 2)
-#define DP_REPLY_STATUS (0x014C >> 2)
-#define DP_HPD_DURATION (0x0150 >> 2)
-#define DP_MAIN_STREAM_HTOTAL (0x0180 >> 2)
-#define DP_MAIN_STREAM_VTOTAL (0x0184 >> 2)
-#define DP_MAIN_STREAM_POLARITY (0x0188 >> 2)
-#define DP_MAIN_STREAM_HSWIDTH (0x018C >> 2)
-#define DP_MAIN_STREAM_VSWIDTH (0x0190 >> 2)
-#define DP_MAIN_STREAM_HRES (0x0194 >> 2)
-#define DP_MAIN_STREAM_VRES (0x0198 >> 2)
-#define DP_MAIN_STREAM_HSTART (0x019C >> 2)
-#define DP_MAIN_STREAM_VSTART (0x01A0 >> 2)
-#define DP_MAIN_STREAM_MISC0 (0x01A4 >> 2)
-#define DP_MAIN_STREAM_MISC1 (0x01A8 >> 2)
-#define DP_MAIN_STREAM_M_VID (0x01AC >> 2)
-#define DP_MSA_TRANSFER_UNIT_SIZE (0x01B0 >> 2)
-#define DP_MAIN_STREAM_N_VID (0x01B4 >> 2)
-#define DP_USER_DATA_COUNT_PER_LANE (0x01BC >> 2)
-#define DP_MIN_BYTES_PER_TU (0x01C4 >> 2)
-#define DP_FRAC_BYTES_PER_TU (0x01C8 >> 2)
-#define DP_INIT_WAIT (0x01CC >> 2)
-#define DP_PHY_RESET (0x0200 >> 2)
-#define DP_PHY_VOLTAGE_DIFF_LANE_0 (0x0220 >> 2)
-#define DP_PHY_VOLTAGE_DIFF_LANE_1 (0x0224 >> 2)
-#define DP_TRANSMIT_PRBS7 (0x0230 >> 2)
-#define DP_PHY_CLOCK_SELECT (0x0234 >> 2)
-#define DP_TX_PHY_POWER_DOWN (0x0238 >> 2)
-#define DP_PHY_PRECURSOR_LANE_0 (0x023C >> 2)
-#define DP_PHY_PRECURSOR_LANE_1 (0x0240 >> 2)
-#define DP_PHY_POSTCURSOR_LANE_0 (0x024C >> 2)
-#define DP_PHY_POSTCURSOR_LANE_1 (0x0250 >> 2)
-#define DP_PHY_STATUS (0x0280 >> 2)
-
-#define DP_TX_AUDIO_CONTROL (0x0300 >> 2)
-#define DP_TX_AUD_CTRL (1)
-
-#define DP_TX_AUDIO_CHANNELS (0x0304 >> 2)
-#define DP_TX_AUDIO_INFO_DATA(n) ((0x0308 + 4 * n) >> 2)
-#define DP_TX_M_AUD (0x0328 >> 2)
-#define DP_TX_N_AUD (0x032C >> 2)
-#define DP_TX_AUDIO_EXT_DATA(n) ((0x0330 + 4 * n) >> 2)
-#define DP_INT_STATUS (0x03A0 >> 2)
-#define DP_INT_MASK (0x03A4 >> 2)
-#define DP_INT_EN (0x03A8 >> 2)
-#define DP_INT_DS (0x03AC >> 2)
-
-/*
- * Registers offset for Audio Video Buffer configuration.
- */
-#define V_BLEND_OFFSET (0xA000)
-#define V_BLEND_BG_CLR_0 (0x0000 >> 2)
-#define V_BLEND_BG_CLR_1 (0x0004 >> 2)
-#define V_BLEND_BG_CLR_2 (0x0008 >> 2)
-#define V_BLEND_SET_GLOBAL_ALPHA_REG (0x000C >> 2)
-#define V_BLEND_OUTPUT_VID_FORMAT (0x0014 >> 2)
-#define V_BLEND_LAYER0_CONTROL (0x0018 >> 2)
-#define V_BLEND_LAYER1_CONTROL (0x001C >> 2)
-
-#define V_BLEND_RGB2YCBCR_COEFF(n) ((0x0020 + 4 * n) >> 2)
-#define V_BLEND_IN1CSC_COEFF(n) ((0x0044 + 4 * n) >> 2)
-
-#define V_BLEND_LUMA_IN1CSC_OFFSET (0x0068 >> 2)
-#define V_BLEND_CR_IN1CSC_OFFSET (0x006C >> 2)
-#define V_BLEND_CB_IN1CSC_OFFSET (0x0070 >> 2)
-#define V_BLEND_LUMA_OUTCSC_OFFSET (0x0074 >> 2)
-#define V_BLEND_CR_OUTCSC_OFFSET (0x0078 >> 2)
-#define V_BLEND_CB_OUTCSC_OFFSET (0x007C >> 2)
-
-#define V_BLEND_IN2CSC_COEFF(n) ((0x0080 + 4 * n) >> 2)
-
-#define V_BLEND_LUMA_IN2CSC_OFFSET (0x00A4 >> 2)
-#define V_BLEND_CR_IN2CSC_OFFSET (0x00A8 >> 2)
-#define V_BLEND_CB_IN2CSC_OFFSET (0x00AC >> 2)
-#define V_BLEND_CHROMA_KEY_ENABLE (0x01D0 >> 2)
-#define V_BLEND_CHROMA_KEY_COMP1 (0x01D4 >> 2)
-#define V_BLEND_CHROMA_KEY_COMP2 (0x01D8 >> 2)
-#define V_BLEND_CHROMA_KEY_COMP3 (0x01DC >> 2)
-
-/*
- * Registers offset for Audio Video Buffer configuration.
- */
-#define AV_BUF_MANAGER_OFFSET (0xB000)
-#define AV_BUF_FORMAT (0x0000 >> 2)
-#define AV_BUF_NON_LIVE_LATENCY (0x0008 >> 2)
-#define AV_CHBUF0 (0x0010 >> 2)
-#define AV_CHBUF1 (0x0014 >> 2)
-#define AV_CHBUF2 (0x0018 >> 2)
-#define AV_CHBUF3 (0x001C >> 2)
-#define AV_CHBUF4 (0x0020 >> 2)
-#define AV_CHBUF5 (0x0024 >> 2)
-#define AV_BUF_STC_CONTROL (0x002C >> 2)
-#define AV_BUF_STC_INIT_VALUE0 (0x0030 >> 2)
-#define AV_BUF_STC_INIT_VALUE1 (0x0034 >> 2)
-#define AV_BUF_STC_ADJ (0x0038 >> 2)
-#define AV_BUF_STC_VIDEO_VSYNC_TS_REG0 (0x003C >> 2)
-#define AV_BUF_STC_VIDEO_VSYNC_TS_REG1 (0x0040 >> 2)
-#define AV_BUF_STC_EXT_VSYNC_TS_REG0 (0x0044 >> 2)
-#define AV_BUF_STC_EXT_VSYNC_TS_REG1 (0x0048 >> 2)
-#define AV_BUF_STC_CUSTOM_EVENT_TS_REG0 (0x004C >> 2)
-#define AV_BUF_STC_CUSTOM_EVENT_TS_REG1 (0x0050 >> 2)
-#define AV_BUF_STC_CUSTOM_EVENT2_TS_REG0 (0x0054 >> 2)
-#define AV_BUF_STC_CUSTOM_EVENT2_TS_REG1 (0x0058 >> 2)
-#define AV_BUF_STC_SNAPSHOT0 (0x0060 >> 2)
-#define AV_BUF_STC_SNAPSHOT1 (0x0064 >> 2)
-#define AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT (0x0070 >> 2)
-#define AV_BUF_HCOUNT_VCOUNT_INT0 (0x0074 >> 2)
-#define AV_BUF_HCOUNT_VCOUNT_INT1 (0x0078 >> 2)
-#define AV_BUF_DITHER_CONFIG (0x007C >> 2)
-#define AV_BUF_DITHER_CONFIG_MAX (0x008C >> 2)
-#define AV_BUF_DITHER_CONFIG_MIN (0x0090 >> 2)
-#define AV_BUF_PATTERN_GEN_SELECT (0x0100 >> 2)
-#define AV_BUF_AUD_VID_CLK_SOURCE (0x0120 >> 2)
-#define AV_BUF_SRST_REG (0x0124 >> 2)
-#define AV_BUF_AUDIO_RDY_INTERVAL (0x0128 >> 2)
-#define AV_BUF_AUDIO_CH_CONFIG (0x012C >> 2)
-
-#define AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(n)((0x0200 + 4 * n) >> 2)
-
-#define AV_BUF_VIDEO_COMP_SCALE_FACTOR(n) ((0x020C + 4 * n) >> 2)
-
-#define AV_BUF_LIVE_VIDEO_COMP_SF(n) ((0x0218 + 4 * n) >> 2)
-
-#define AV_BUF_LIVE_VID_CONFIG (0x0224 >> 2)
-
-#define AV_BUF_LIVE_GFX_COMP_SF(n) ((0x0228 + 4 * n) >> 2)
-
-#define AV_BUF_LIVE_GFX_CONFIG (0x0234 >> 2)
-
-#define AUDIO_MIXER_REGISTER_OFFSET (0xC000)
-#define AUDIO_MIXER_VOLUME_CONTROL (0x0000 >> 2)
-#define AUDIO_MIXER_META_DATA (0x0004 >> 2)
-#define AUD_CH_STATUS_REG(n) ((0x0008 + 4 * n) >> 2)
-#define AUD_CH_A_DATA_REG(n) ((0x0020 + 4 * n) >> 2)
-#define AUD_CH_B_DATA_REG(n) ((0x0038 + 4 * n) >> 2)
-
-#define DP_AUDIO_DMA_CHANNEL(n) (4 + n)
-#define DP_GRAPHIC_DMA_CHANNEL (3)
-#define DP_VIDEO_DMA_CHANNEL (0)
-
-enum DPGraphicFmt {
- DP_GRAPHIC_RGBA8888 = 0 << 8,
- DP_GRAPHIC_ABGR8888 = 1 << 8,
- DP_GRAPHIC_RGB888 = 2 << 8,
- DP_GRAPHIC_BGR888 = 3 << 8,
- DP_GRAPHIC_RGBA5551 = 4 << 8,
- DP_GRAPHIC_RGBA4444 = 5 << 8,
- DP_GRAPHIC_RGB565 = 6 << 8,
- DP_GRAPHIC_8BPP = 7 << 8,
- DP_GRAPHIC_4BPP = 8 << 8,
- DP_GRAPHIC_2BPP = 9 << 8,
- DP_GRAPHIC_1BPP = 10 << 8,
- DP_GRAPHIC_MASK = 0xF << 8
-};
-
-enum DPVideoFmt {
- DP_NL_VID_CB_Y0_CR_Y1 = 0,
- DP_NL_VID_CR_Y0_CB_Y1 = 1,
- DP_NL_VID_Y0_CR_Y1_CB = 2,
- DP_NL_VID_Y0_CB_Y1_CR = 3,
- DP_NL_VID_YV16 = 4,
- DP_NL_VID_YV24 = 5,
- DP_NL_VID_YV16CL = 6,
- DP_NL_VID_MONO = 7,
- DP_NL_VID_YV16CL2 = 8,
- DP_NL_VID_YUV444 = 9,
- DP_NL_VID_RGB888 = 10,
- DP_NL_VID_RGBA8880 = 11,
- DP_NL_VID_RGB888_10BPC = 12,
- DP_NL_VID_YUV444_10BPC = 13,
- DP_NL_VID_YV16CL2_10BPC = 14,
- DP_NL_VID_YV16CL_10BPC = 15,
- DP_NL_VID_YV16_10BPC = 16,
- DP_NL_VID_YV24_10BPC = 17,
- DP_NL_VID_Y_ONLY_10BPC = 18,
- DP_NL_VID_YV16_420 = 19,
- DP_NL_VID_YV16CL_420 = 20,
- DP_NL_VID_YV16CL2_420 = 21,
- DP_NL_VID_YV16_420_10BPC = 22,
- DP_NL_VID_YV16CL_420_10BPC = 23,
- DP_NL_VID_YV16CL2_420_10BPC = 24,
- DP_NL_VID_FMT_MASK = 0x1F
-};
-
-typedef enum DPGraphicFmt DPGraphicFmt;
-typedef enum DPVideoFmt DPVideoFmt;
-
-static const VMStateDescription vmstate_dp = {
- .name = TYPE_XLNX_DP,
- .version_id = 1,
- .fields = (VMStateField[]){
- VMSTATE_UINT32_ARRAY(core_registers, XlnxDPState,
- DP_CORE_REG_ARRAY_SIZE),
- VMSTATE_UINT32_ARRAY(avbufm_registers, XlnxDPState,
- DP_AVBUF_REG_ARRAY_SIZE),
- VMSTATE_UINT32_ARRAY(vblend_registers, XlnxDPState,
- DP_VBLEND_REG_ARRAY_SIZE),
- VMSTATE_UINT32_ARRAY(audio_registers, XlnxDPState,
- DP_AUDIO_REG_ARRAY_SIZE),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void xlnx_dp_update_irq(XlnxDPState *s);
-
-static uint64_t xlnx_dp_audio_read(void *opaque, hwaddr offset, unsigned size)
-{
- XlnxDPState *s = XLNX_DP(opaque);
-
- offset = offset >> 2;
- return s->audio_registers[offset];
-}
-
-static void xlnx_dp_audio_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- XlnxDPState *s = XLNX_DP(opaque);
-
- offset = offset >> 2;
-
- switch (offset) {
- case AUDIO_MIXER_META_DATA:
- s->audio_registers[offset] = value & 0x00000001;
- break;
- default:
- s->audio_registers[offset] = value;
- break;
- }
-}
-
-static const MemoryRegionOps audio_ops = {
- .read = xlnx_dp_audio_read,
- .write = xlnx_dp_audio_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static inline uint32_t xlnx_dp_audio_get_volume(XlnxDPState *s,
- uint8_t channel)
-{
- switch (channel) {
- case 0:
- return extract32(s->audio_registers[AUDIO_MIXER_VOLUME_CONTROL], 0, 16);
- case 1:
- return extract32(s->audio_registers[AUDIO_MIXER_VOLUME_CONTROL], 16,
- 16);
- default:
- return 0;
- }
-}
-
-static inline void xlnx_dp_audio_activate(XlnxDPState *s)
-{
- bool activated = ((s->core_registers[DP_TX_AUDIO_CONTROL]
- & DP_TX_AUD_CTRL) != 0);
- AUD_set_active_out(s->amixer_output_stream, activated);
- xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(0),
- &s->audio_buffer_0);
- xlnx_dpdma_set_host_data_location(s->dpdma, DP_AUDIO_DMA_CHANNEL(1),
- &s->audio_buffer_1);
-}
-
-static inline void xlnx_dp_audio_mix_buffer(XlnxDPState *s)
-{
- /*
- * Audio packets are signed and have this shape:
- * | 16 | 16 | 16 | 16 | 16 | 16 | 16 | 16 |
- * | R3 | L3 | R2 | L2 | R1 | L1 | R0 | L0 |
- *
- * Output audio is 16bits saturated.
- */
- int i;
-
- if ((s->audio_data_available[0]) && (xlnx_dp_audio_get_volume(s, 0))) {
- for (i = 0; i < s->audio_data_available[0] / 2; i++) {
- s->temp_buffer[i] = (int64_t)(s->audio_buffer_0[i])
- * xlnx_dp_audio_get_volume(s, 0) / 8192;
- }
- s->byte_left = s->audio_data_available[0];
- } else {
- memset(s->temp_buffer, 0, s->audio_data_available[1] / 2);
- }
-
- if ((s->audio_data_available[1]) && (xlnx_dp_audio_get_volume(s, 1))) {
- if ((s->audio_data_available[0] == 0)
- || (s->audio_data_available[1] == s->audio_data_available[0])) {
- for (i = 0; i < s->audio_data_available[1] / 2; i++) {
- s->temp_buffer[i] += (int64_t)(s->audio_buffer_1[i])
- * xlnx_dp_audio_get_volume(s, 1) / 8192;
- }
- s->byte_left = s->audio_data_available[1];
- }
- }
-
- for (i = 0; i < s->byte_left / 2; i++) {
- s->out_buffer[i] = MAX(-32767, MIN(s->temp_buffer[i], 32767));
- }
-
- s->data_ptr = 0;
-}
-
-static void xlnx_dp_audio_callback(void *opaque, int avail)
-{
- /*
- * Get some data from the DPDMA and compute these datas.
- * Then wait for QEMU's audio subsystem to call this callback.
- */
- XlnxDPState *s = XLNX_DP(opaque);
- size_t written = 0;
-
- /* If there are already some data don't get more data. */
- if (s->byte_left == 0) {
- s->audio_data_available[0] = xlnx_dpdma_start_operation(s->dpdma, 4,
- true);
- s->audio_data_available[1] = xlnx_dpdma_start_operation(s->dpdma, 5,
- true);
- xlnx_dp_audio_mix_buffer(s);
- }
-
- /* Send the buffer through the audio. */
- if (s->byte_left <= MAX_QEMU_BUFFER_SIZE) {
- if (s->byte_left != 0) {
- written = AUD_write(s->amixer_output_stream,
- &s->out_buffer[s->data_ptr], s->byte_left);
- } else {
- /*
- * There is nothing to play.. We don't have any data! Fill the
- * buffer with zero's and send it.
- */
- written = 0;
- memset(s->out_buffer, 0, 1024);
- AUD_write(s->amixer_output_stream, s->out_buffer, 1024);
- }
- } else {
- written = AUD_write(s->amixer_output_stream,
- &s->out_buffer[s->data_ptr], MAX_QEMU_BUFFER_SIZE);
- }
- s->byte_left -= written;
- s->data_ptr += written;
-}
-
-/*
- * AUX channel related function.
- */
-static void xlnx_dp_aux_clear_rx_fifo(XlnxDPState *s)
-{
- fifo8_reset(&s->rx_fifo);
-}
-
-static void xlnx_dp_aux_push_rx_fifo(XlnxDPState *s, uint8_t *buf, size_t len)
-{
- DPRINTF("Push %u data in rx_fifo\n", (unsigned)len);
- fifo8_push_all(&s->rx_fifo, buf, len);
-}
-
-static uint8_t xlnx_dp_aux_pop_rx_fifo(XlnxDPState *s)
-{
- uint8_t ret;
-
- if (fifo8_is_empty(&s->rx_fifo)) {
- DPRINTF("rx_fifo underflow..\n");
- abort();
- }
- ret = fifo8_pop(&s->rx_fifo);
- DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret);
- return ret;
-}
-
-static void xlnx_dp_aux_clear_tx_fifo(XlnxDPState *s)
-{
- fifo8_reset(&s->tx_fifo);
-}
-
-static void xlnx_dp_aux_push_tx_fifo(XlnxDPState *s, uint8_t *buf, size_t len)
-{
- DPRINTF("Push %u data in tx_fifo\n", (unsigned)len);
- fifo8_push_all(&s->tx_fifo, buf, len);
-}
-
-static uint8_t xlnx_dp_aux_pop_tx_fifo(XlnxDPState *s)
-{
- uint8_t ret;
-
- if (fifo8_is_empty(&s->tx_fifo)) {
- DPRINTF("tx_fifo underflow..\n");
- abort();
- }
- ret = fifo8_pop(&s->tx_fifo);
- DPRINTF("pop 0x%2.2X from tx_fifo.\n", ret);
- return ret;
-}
-
-static uint32_t xlnx_dp_aux_get_address(XlnxDPState *s)
-{
- return s->core_registers[DP_AUX_ADDRESS];
-}
-
-/*
- * Get command from the register.
- */
-static void xlnx_dp_aux_set_command(XlnxDPState *s, uint32_t value)
-{
- bool address_only = (value & AUX_ADDR_ONLY_MASK) != 0;
- AUXCommand cmd = (value & AUX_COMMAND_MASK) >> AUX_COMMAND_SHIFT;
- uint8_t nbytes = (value & AUX_COMMAND_NBYTES) + 1;
- uint8_t buf[16];
- int i;
-
- /*
- * When an address_only command is executed nothing happen to the fifo, so
- * just make nbytes = 0.
- */
- if (address_only) {
- nbytes = 0;
- }
-
- switch (cmd) {
- case READ_AUX:
- case READ_I2C:
- case READ_I2C_MOT:
- s->core_registers[DP_AUX_REPLY_CODE] = aux_request(s->aux_bus, cmd,
- xlnx_dp_aux_get_address(s),
- nbytes, buf);
- s->core_registers[DP_REPLY_DATA_COUNT] = nbytes;
-
- if (s->core_registers[DP_AUX_REPLY_CODE] == AUX_I2C_ACK) {
- xlnx_dp_aux_push_rx_fifo(s, buf, nbytes);
- }
- break;
- case WRITE_AUX:
- case WRITE_I2C:
- case WRITE_I2C_MOT:
- for (i = 0; i < nbytes; i++) {
- buf[i] = xlnx_dp_aux_pop_tx_fifo(s);
- }
- s->core_registers[DP_AUX_REPLY_CODE] = aux_request(s->aux_bus, cmd,
- xlnx_dp_aux_get_address(s),
- nbytes, buf);
- xlnx_dp_aux_clear_tx_fifo(s);
- break;
- case WRITE_I2C_STATUS:
- qemu_log_mask(LOG_UNIMP, "xlnx_dp: Write i2c status not implemented\n");
- break;
- default:
- abort();
- }
-
- s->core_registers[DP_INTERRUPT_SIGNAL_STATE] |= 0x04;
-}
-
-static void xlnx_dp_set_dpdma(Object *obj, const char *name, Object *val,
- Error **errp)
-{
- XlnxDPState *s = XLNX_DP(obj);
- if (s->console) {
- DisplaySurface *surface = qemu_console_surface(s->console);
- XlnxDPDMAState *dma = XLNX_DPDMA(val);
- xlnx_dpdma_set_host_data_location(dma, DP_GRAPHIC_DMA_CHANNEL,
- surface_data(surface));
- }
-}
-
-static inline uint8_t xlnx_dp_global_alpha_value(XlnxDPState *s)
-{
- return (s->vblend_registers[V_BLEND_SET_GLOBAL_ALPHA_REG] & 0x1FE) >> 1;
-}
-
-static inline bool xlnx_dp_global_alpha_enabled(XlnxDPState *s)
-{
- /*
- * If the alpha is totally opaque (255) we consider the alpha is disabled to
- * reduce CPU consumption.
- */
- return ((xlnx_dp_global_alpha_value(s) != 0xFF) &&
- ((s->vblend_registers[V_BLEND_SET_GLOBAL_ALPHA_REG] & 0x01) != 0));
-}
-
-static void xlnx_dp_recreate_surface(XlnxDPState *s)
-{
- /*
- * Two possibilities, if blending is enabled the console displays
- * bout_plane, if not g_plane is displayed.
- */
- uint16_t width = s->core_registers[DP_MAIN_STREAM_HRES];
- uint16_t height = s->core_registers[DP_MAIN_STREAM_VRES];
- DisplaySurface *current_console_surface = qemu_console_surface(s->console);
-
- if ((width != 0) && (height != 0)) {
- /*
- * As dpy_gfx_replace_surface calls qemu_free_displaysurface on the
- * surface we need to be carefull and don't free the surface associated
- * to the console or double free will happen.
- */
- if (s->bout_plane.surface != current_console_surface) {
- qemu_free_displaysurface(s->bout_plane.surface);
- }
- if (s->v_plane.surface != current_console_surface) {
- qemu_free_displaysurface(s->v_plane.surface);
- }
- if (s->g_plane.surface != current_console_surface) {
- qemu_free_displaysurface(s->g_plane.surface);
- }
-
- s->g_plane.surface
- = qemu_create_displaysurface_from(width, height,
- s->g_plane.format, 0, NULL);
- s->v_plane.surface
- = qemu_create_displaysurface_from(width, height,
- s->v_plane.format, 0, NULL);
- if (xlnx_dp_global_alpha_enabled(s)) {
- s->bout_plane.surface =
- qemu_create_displaysurface_from(width,
- height,
- s->g_plane.format,
- 0, NULL);
- dpy_gfx_replace_surface(s->console, s->bout_plane.surface);
- } else {
- s->bout_plane.surface = NULL;
- dpy_gfx_replace_surface(s->console, s->g_plane.surface);
- }
-
- xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL,
- surface_data(s->g_plane.surface));
- xlnx_dpdma_set_host_data_location(s->dpdma, DP_VIDEO_DMA_CHANNEL,
- surface_data(s->v_plane.surface));
- }
-}
-
-/*
- * Change the graphic format of the surface.
- */
-static void xlnx_dp_change_graphic_fmt(XlnxDPState *s)
-{
- switch (s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK) {
- case DP_GRAPHIC_RGBA8888:
- s->g_plane.format = PIXMAN_r8g8b8a8;
- break;
- case DP_GRAPHIC_ABGR8888:
- s->g_plane.format = PIXMAN_a8b8g8r8;
- break;
- case DP_GRAPHIC_RGB565:
- s->g_plane.format = PIXMAN_r5g6b5;
- break;
- case DP_GRAPHIC_RGB888:
- s->g_plane.format = PIXMAN_r8g8b8;
- break;
- case DP_GRAPHIC_BGR888:
- s->g_plane.format = PIXMAN_b8g8r8;
- break;
- default:
- DPRINTF("error: unsupported graphic format %u.\n",
- s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK);
- abort();
- }
-
- switch (s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK) {
- case 0:
- s->v_plane.format = PIXMAN_x8b8g8r8;
- break;
- case DP_NL_VID_RGBA8880:
- s->v_plane.format = PIXMAN_x8b8g8r8;
- break;
- default:
- DPRINTF("error: unsupported video format %u.\n",
- s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK);
- abort();
- }
-
- xlnx_dp_recreate_surface(s);
-}
-
-static void xlnx_dp_update_irq(XlnxDPState *s)
-{
- uint32_t flags;
-
- flags = s->core_registers[DP_INT_STATUS] & ~s->core_registers[DP_INT_MASK];
- DPRINTF("update IRQ value = %" PRIx32 "\n", flags);
- qemu_set_irq(s->irq, flags != 0);
-}
-
-static uint64_t xlnx_dp_read(void *opaque, hwaddr offset, unsigned size)
-{
- XlnxDPState *s = XLNX_DP(opaque);
- uint64_t ret = 0;
-
- offset = offset >> 2;
-
- switch (offset) {
- case DP_TX_USER_FIFO_OVERFLOW:
- /* This register is cleared after a read */
- ret = s->core_registers[DP_TX_USER_FIFO_OVERFLOW];
- s->core_registers[DP_TX_USER_FIFO_OVERFLOW] = 0;
- break;
- case DP_AUX_REPLY_DATA:
- ret = xlnx_dp_aux_pop_rx_fifo(s);
- break;
- case DP_INTERRUPT_SIGNAL_STATE:
- /*
- * XXX: Not sure it is the right thing to do actually.
- * The register is not written by the device driver so it's stuck
- * to 0x04.
- */
- ret = s->core_registers[DP_INTERRUPT_SIGNAL_STATE];
- s->core_registers[DP_INTERRUPT_SIGNAL_STATE] &= ~0x04;
- break;
- case DP_AUX_WRITE_FIFO:
- case DP_TX_AUDIO_INFO_DATA(0):
- case DP_TX_AUDIO_INFO_DATA(1):
- case DP_TX_AUDIO_INFO_DATA(2):
- case DP_TX_AUDIO_INFO_DATA(3):
- case DP_TX_AUDIO_INFO_DATA(4):
- case DP_TX_AUDIO_INFO_DATA(5):
- case DP_TX_AUDIO_INFO_DATA(6):
- case DP_TX_AUDIO_INFO_DATA(7):
- case DP_TX_AUDIO_EXT_DATA(0):
- case DP_TX_AUDIO_EXT_DATA(1):
- case DP_TX_AUDIO_EXT_DATA(2):
- case DP_TX_AUDIO_EXT_DATA(3):
- case DP_TX_AUDIO_EXT_DATA(4):
- case DP_TX_AUDIO_EXT_DATA(5):
- case DP_TX_AUDIO_EXT_DATA(6):
- case DP_TX_AUDIO_EXT_DATA(7):
- case DP_TX_AUDIO_EXT_DATA(8):
- /* write only registers */
- ret = 0;
- break;
- default:
- assert(offset <= (0x3AC >> 2));
- ret = s->core_registers[offset];
- break;
- }
-
- DPRINTF("core read @%" PRIx64 " = 0x%8.8" PRIX64 "\n", offset << 2, ret);
- return ret;
-}
-
-static void xlnx_dp_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- XlnxDPState *s = XLNX_DP(opaque);
-
- DPRINTF("core write @%" PRIx64 " = 0x%8.8" PRIX64 "\n", offset, value);
-
- offset = offset >> 2;
-
- switch (offset) {
- /*
- * Only special write case are handled.
- */
- case DP_LINK_BW_SET:
- s->core_registers[offset] = value & 0x000000FF;
- break;
- case DP_LANE_COUNT_SET:
- case DP_MAIN_STREAM_MISC0:
- s->core_registers[offset] = value & 0x0000000F;
- break;
- case DP_TRAINING_PATTERN_SET:
- case DP_LINK_QUAL_PATTERN_SET:
- case DP_MAIN_STREAM_POLARITY:
- case DP_PHY_VOLTAGE_DIFF_LANE_0:
- case DP_PHY_VOLTAGE_DIFF_LANE_1:
- s->core_registers[offset] = value & 0x00000003;
- break;
- case DP_ENHANCED_FRAME_EN:
- case DP_SCRAMBLING_DISABLE:
- case DP_DOWNSPREAD_CTRL:
- case DP_MAIN_STREAM_ENABLE:
- case DP_TRANSMIT_PRBS7:
- s->core_registers[offset] = value & 0x00000001;
- break;
- case DP_PHY_CLOCK_SELECT:
- s->core_registers[offset] = value & 0x00000007;
- break;
- case DP_SOFTWARE_RESET:
- /*
- * No need to update this bit as it's read '0'.
- */
- /*
- * TODO: reset IP.
- */
- break;
- case DP_TRANSMITTER_ENABLE:
- s->core_registers[offset] = value & 0x01;
- break;
- case DP_FORCE_SCRAMBLER_RESET:
- /*
- * No need to update this bit as it's read '0'.
- */
- /*
- * TODO: force a scrambler reset??
- */
- break;
- case DP_AUX_COMMAND_REGISTER:
- s->core_registers[offset] = value & 0x00001F0F;
- xlnx_dp_aux_set_command(s, s->core_registers[offset]);
- break;
- case DP_MAIN_STREAM_HTOTAL:
- case DP_MAIN_STREAM_VTOTAL:
- case DP_MAIN_STREAM_HSTART:
- case DP_MAIN_STREAM_VSTART:
- s->core_registers[offset] = value & 0x0000FFFF;
- break;
- case DP_MAIN_STREAM_HRES:
- case DP_MAIN_STREAM_VRES:
- s->core_registers[offset] = value & 0x0000FFFF;
- xlnx_dp_recreate_surface(s);
- break;
- case DP_MAIN_STREAM_HSWIDTH:
- case DP_MAIN_STREAM_VSWIDTH:
- s->core_registers[offset] = value & 0x00007FFF;
- break;
- case DP_MAIN_STREAM_MISC1:
- s->core_registers[offset] = value & 0x00000086;
- break;
- case DP_MAIN_STREAM_M_VID:
- case DP_MAIN_STREAM_N_VID:
- s->core_registers[offset] = value & 0x00FFFFFF;
- break;
- case DP_MSA_TRANSFER_UNIT_SIZE:
- case DP_MIN_BYTES_PER_TU:
- case DP_INIT_WAIT:
- s->core_registers[offset] = value & 0x00000007;
- break;
- case DP_USER_DATA_COUNT_PER_LANE:
- s->core_registers[offset] = value & 0x0003FFFF;
- break;
- case DP_FRAC_BYTES_PER_TU:
- s->core_registers[offset] = value & 0x000003FF;
- break;
- case DP_PHY_RESET:
- s->core_registers[offset] = value & 0x00010003;
- /*
- * TODO: Reset something?
- */
- break;
- case DP_TX_PHY_POWER_DOWN:
- s->core_registers[offset] = value & 0x0000000F;
- /*
- * TODO: Power down things?
- */
- break;
- case DP_AUX_WRITE_FIFO: {
- uint8_t c = value;
- xlnx_dp_aux_push_tx_fifo(s, &c, 1);
- break;
- }
- case DP_AUX_CLOCK_DIVIDER:
- break;
- case DP_AUX_REPLY_COUNT:
- /*
- * Writing to this register clear the counter.
- */
- s->core_registers[offset] = 0x00000000;
- break;
- case DP_AUX_ADDRESS:
- s->core_registers[offset] = value & 0x000FFFFF;
- break;
- case DP_VERSION_REGISTER:
- case DP_CORE_ID:
- case DP_TX_USER_FIFO_OVERFLOW:
- case DP_AUX_REPLY_DATA:
- case DP_AUX_REPLY_CODE:
- case DP_REPLY_DATA_COUNT:
- case DP_REPLY_STATUS:
- case DP_HPD_DURATION:
- /*
- * Write to read only location..
- */
- break;
- case DP_TX_AUDIO_CONTROL:
- s->core_registers[offset] = value & 0x00000001;
- xlnx_dp_audio_activate(s);
- break;
- case DP_TX_AUDIO_CHANNELS:
- s->core_registers[offset] = value & 0x00000007;
- xlnx_dp_audio_activate(s);
- break;
- case DP_INT_STATUS:
- s->core_registers[DP_INT_STATUS] &= ~value;
- xlnx_dp_update_irq(s);
- break;
- case DP_INT_EN:
- s->core_registers[DP_INT_MASK] &= ~value;
- xlnx_dp_update_irq(s);
- break;
- case DP_INT_DS:
- s->core_registers[DP_INT_MASK] |= ~value;
- xlnx_dp_update_irq(s);
- break;
- default:
- assert(offset <= (0x504C >> 2));
- s->core_registers[offset] = value;
- break;
- }
-}
-
-static const MemoryRegionOps dp_ops = {
- .read = xlnx_dp_read,
- .write = xlnx_dp_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .impl = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-/*
- * This is to handle Read/Write to the Video Blender.
- */
-static void xlnx_dp_vblend_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- XlnxDPState *s = XLNX_DP(opaque);
- bool alpha_was_enabled;
-
- DPRINTF("vblend: write @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset,
- (uint32_t)value);
- offset = offset >> 2;
-
- switch (offset) {
- case V_BLEND_BG_CLR_0:
- case V_BLEND_BG_CLR_1:
- case V_BLEND_BG_CLR_2:
- s->vblend_registers[offset] = value & 0x00000FFF;
- break;
- case V_BLEND_SET_GLOBAL_ALPHA_REG:
- /*
- * A write to this register can enable or disable blending. Thus we need
- * to recreate the surfaces.
- */
- alpha_was_enabled = xlnx_dp_global_alpha_enabled(s);
- s->vblend_registers[offset] = value & 0x000001FF;
- if (xlnx_dp_global_alpha_enabled(s) != alpha_was_enabled) {
- xlnx_dp_recreate_surface(s);
- }
- break;
- case V_BLEND_OUTPUT_VID_FORMAT:
- s->vblend_registers[offset] = value & 0x00000017;
- break;
- case V_BLEND_LAYER0_CONTROL:
- case V_BLEND_LAYER1_CONTROL:
- s->vblend_registers[offset] = value & 0x00000103;
- break;
- case V_BLEND_RGB2YCBCR_COEFF(0):
- case V_BLEND_RGB2YCBCR_COEFF(1):
- case V_BLEND_RGB2YCBCR_COEFF(2):
- case V_BLEND_RGB2YCBCR_COEFF(3):
- case V_BLEND_RGB2YCBCR_COEFF(4):
- case V_BLEND_RGB2YCBCR_COEFF(5):
- case V_BLEND_RGB2YCBCR_COEFF(6):
- case V_BLEND_RGB2YCBCR_COEFF(7):
- case V_BLEND_RGB2YCBCR_COEFF(8):
- case V_BLEND_IN1CSC_COEFF(0):
- case V_BLEND_IN1CSC_COEFF(1):
- case V_BLEND_IN1CSC_COEFF(2):
- case V_BLEND_IN1CSC_COEFF(3):
- case V_BLEND_IN1CSC_COEFF(4):
- case V_BLEND_IN1CSC_COEFF(5):
- case V_BLEND_IN1CSC_COEFF(6):
- case V_BLEND_IN1CSC_COEFF(7):
- case V_BLEND_IN1CSC_COEFF(8):
- case V_BLEND_IN2CSC_COEFF(0):
- case V_BLEND_IN2CSC_COEFF(1):
- case V_BLEND_IN2CSC_COEFF(2):
- case V_BLEND_IN2CSC_COEFF(3):
- case V_BLEND_IN2CSC_COEFF(4):
- case V_BLEND_IN2CSC_COEFF(5):
- case V_BLEND_IN2CSC_COEFF(6):
- case V_BLEND_IN2CSC_COEFF(7):
- case V_BLEND_IN2CSC_COEFF(8):
- s->vblend_registers[offset] = value & 0x0000FFFF;
- break;
- case V_BLEND_LUMA_IN1CSC_OFFSET:
- case V_BLEND_CR_IN1CSC_OFFSET:
- case V_BLEND_CB_IN1CSC_OFFSET:
- case V_BLEND_LUMA_IN2CSC_OFFSET:
- case V_BLEND_CR_IN2CSC_OFFSET:
- case V_BLEND_CB_IN2CSC_OFFSET:
- case V_BLEND_LUMA_OUTCSC_OFFSET:
- case V_BLEND_CR_OUTCSC_OFFSET:
- case V_BLEND_CB_OUTCSC_OFFSET:
- s->vblend_registers[offset] = value & 0x3FFF7FFF;
- break;
- case V_BLEND_CHROMA_KEY_ENABLE:
- s->vblend_registers[offset] = value & 0x00000003;
- break;
- case V_BLEND_CHROMA_KEY_COMP1:
- case V_BLEND_CHROMA_KEY_COMP2:
- case V_BLEND_CHROMA_KEY_COMP3:
- s->vblend_registers[offset] = value & 0x0FFF0FFF;
- break;
- default:
- s->vblend_registers[offset] = value;
- break;
- }
-}
-
-static uint64_t xlnx_dp_vblend_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- XlnxDPState *s = XLNX_DP(opaque);
-
- DPRINTF("vblend: read @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset,
- s->vblend_registers[offset >> 2]);
- return s->vblend_registers[offset >> 2];
-}
-
-static const MemoryRegionOps vblend_ops = {
- .read = xlnx_dp_vblend_read,
- .write = xlnx_dp_vblend_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .impl = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-/*
- * This is to handle Read/Write to the Audio Video buffer manager.
- */
-static void xlnx_dp_avbufm_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- XlnxDPState *s = XLNX_DP(opaque);
-
- DPRINTF("avbufm: write @0x%" HWADDR_PRIX " = 0x%" PRIX32 "\n", offset,
- (uint32_t)value);
- offset = offset >> 2;
-
- switch (offset) {
- case AV_BUF_FORMAT:
- s->avbufm_registers[offset] = value & 0x00000FFF;
- xlnx_dp_change_graphic_fmt(s);
- break;
- case AV_CHBUF0:
- case AV_CHBUF1:
- case AV_CHBUF2:
- case AV_CHBUF3:
- case AV_CHBUF4:
- case AV_CHBUF5:
- s->avbufm_registers[offset] = value & 0x0000007F;
- break;
- case AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT:
- s->avbufm_registers[offset] = value & 0x0000007F;
- break;
- case AV_BUF_DITHER_CONFIG:
- s->avbufm_registers[offset] = value & 0x000007FF;
- break;
- case AV_BUF_DITHER_CONFIG_MAX:
- case AV_BUF_DITHER_CONFIG_MIN:
- s->avbufm_registers[offset] = value & 0x00000FFF;
- break;
- case AV_BUF_PATTERN_GEN_SELECT:
- s->avbufm_registers[offset] = value & 0xFFFFFF03;
- break;
- case AV_BUF_AUD_VID_CLK_SOURCE:
- s->avbufm_registers[offset] = value & 0x00000007;
- break;
- case AV_BUF_SRST_REG:
- s->avbufm_registers[offset] = value & 0x00000002;
- break;
- case AV_BUF_AUDIO_CH_CONFIG:
- s->avbufm_registers[offset] = value & 0x00000003;
- break;
- case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(0):
- case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(1):
- case AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(2):
- case AV_BUF_VIDEO_COMP_SCALE_FACTOR(0):
- case AV_BUF_VIDEO_COMP_SCALE_FACTOR(1):
- case AV_BUF_VIDEO_COMP_SCALE_FACTOR(2):
- s->avbufm_registers[offset] = value & 0x0000FFFF;
- break;
- case AV_BUF_LIVE_VIDEO_COMP_SF(0):
- case AV_BUF_LIVE_VIDEO_COMP_SF(1):
- case AV_BUF_LIVE_VIDEO_COMP_SF(2):
- case AV_BUF_LIVE_VID_CONFIG:
- case AV_BUF_LIVE_GFX_COMP_SF(0):
- case AV_BUF_LIVE_GFX_COMP_SF(1):
- case AV_BUF_LIVE_GFX_COMP_SF(2):
- case AV_BUF_LIVE_GFX_CONFIG:
- case AV_BUF_NON_LIVE_LATENCY:
- case AV_BUF_STC_CONTROL:
- case AV_BUF_STC_INIT_VALUE0:
- case AV_BUF_STC_INIT_VALUE1:
- case AV_BUF_STC_ADJ:
- case AV_BUF_STC_VIDEO_VSYNC_TS_REG0:
- case AV_BUF_STC_VIDEO_VSYNC_TS_REG1:
- case AV_BUF_STC_EXT_VSYNC_TS_REG0:
- case AV_BUF_STC_EXT_VSYNC_TS_REG1:
- case AV_BUF_STC_CUSTOM_EVENT_TS_REG0:
- case AV_BUF_STC_CUSTOM_EVENT_TS_REG1:
- case AV_BUF_STC_CUSTOM_EVENT2_TS_REG0:
- case AV_BUF_STC_CUSTOM_EVENT2_TS_REG1:
- case AV_BUF_STC_SNAPSHOT0:
- case AV_BUF_STC_SNAPSHOT1:
- case AV_BUF_HCOUNT_VCOUNT_INT0:
- case AV_BUF_HCOUNT_VCOUNT_INT1:
- qemu_log_mask(LOG_UNIMP, "avbufm: unimplmented");
- break;
- default:
- s->avbufm_registers[offset] = value;
- break;
- }
-}
-
-static uint64_t xlnx_dp_avbufm_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- XlnxDPState *s = XLNX_DP(opaque);
-
- offset = offset >> 2;
- return s->avbufm_registers[offset];
-}
-
-static const MemoryRegionOps avbufm_ops = {
- .read = xlnx_dp_avbufm_read,
- .write = xlnx_dp_avbufm_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .impl = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-/*
- * This is a global alpha blending using pixman.
- * Both graphic and video planes are multiplied with the global alpha
- * coefficient and added.
- */
-static inline void xlnx_dp_blend_surface(XlnxDPState *s)
-{
- pixman_fixed_t alpha1[] = { pixman_double_to_fixed(1),
- pixman_double_to_fixed(1),
- pixman_double_to_fixed(1.0) };
- pixman_fixed_t alpha2[] = { pixman_double_to_fixed(1),
- pixman_double_to_fixed(1),
- pixman_double_to_fixed(1.0) };
-
- if ((surface_width(s->g_plane.surface)
- != surface_width(s->v_plane.surface)) ||
- (surface_height(s->g_plane.surface)
- != surface_height(s->v_plane.surface))) {
- return;
- }
-
- alpha1[2] = pixman_double_to_fixed((double)(xlnx_dp_global_alpha_value(s))
- / 256.0);
- alpha2[2] = pixman_double_to_fixed((255.0
- - (double)xlnx_dp_global_alpha_value(s))
- / 256.0);
-
- pixman_image_set_filter(s->g_plane.surface->image,
- PIXMAN_FILTER_CONVOLUTION, alpha1, 3);
- pixman_image_composite(PIXMAN_OP_SRC, s->g_plane.surface->image, 0,
- s->bout_plane.surface->image, 0, 0, 0, 0, 0, 0,
- surface_width(s->g_plane.surface),
- surface_height(s->g_plane.surface));
- pixman_image_set_filter(s->v_plane.surface->image,
- PIXMAN_FILTER_CONVOLUTION, alpha2, 3);
- pixman_image_composite(PIXMAN_OP_ADD, s->v_plane.surface->image, 0,
- s->bout_plane.surface->image, 0, 0, 0, 0, 0, 0,
- surface_width(s->g_plane.surface),
- surface_height(s->g_plane.surface));
-}
-
-static void xlnx_dp_update_display(void *opaque)
-{
- XlnxDPState *s = XLNX_DP(opaque);
-
- if ((s->core_registers[DP_TRANSMITTER_ENABLE] & 0x01) == 0) {
- return;
- }
-
- s->core_registers[DP_INT_STATUS] |= (1 << 13);
- xlnx_dp_update_irq(s);
-
- xlnx_dpdma_trigger_vsync_irq(s->dpdma);
-
- /*
- * Trigger the DMA channel.
- */
- if (!xlnx_dpdma_start_operation(s->dpdma, 3, false)) {
- /*
- * An error occured don't do anything with the data..
- * Trigger an underflow interrupt.
- */
- s->core_registers[DP_INT_STATUS] |= (1 << 21);
- xlnx_dp_update_irq(s);
- return;
- }
-
- if (xlnx_dp_global_alpha_enabled(s)) {
- if (!xlnx_dpdma_start_operation(s->dpdma, 0, false)) {
- s->core_registers[DP_INT_STATUS] |= (1 << 21);
- xlnx_dp_update_irq(s);
- return;
- }
- xlnx_dp_blend_surface(s);
- }
-
- /*
- * XXX: We might want to update only what changed.
- */
- dpy_gfx_update(s->console, 0, 0, surface_width(s->g_plane.surface),
- surface_height(s->g_plane.surface));
-}
-
-static const GraphicHwOps xlnx_dp_gfx_ops = {
- .gfx_update = xlnx_dp_update_display,
-};
-
-static void xlnx_dp_init(Object *obj)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- XlnxDPState *s = XLNX_DP(obj);
-
- memory_region_init(&s->container, obj, TYPE_XLNX_DP, 0xC050);
-
- memory_region_init_io(&s->core_iomem, obj, &dp_ops, s, TYPE_XLNX_DP
- ".core", 0x3AF);
- memory_region_add_subregion(&s->container, 0x0000, &s->core_iomem);
-
- memory_region_init_io(&s->vblend_iomem, obj, &vblend_ops, s, TYPE_XLNX_DP
- ".v_blend", 0x1DF);
- memory_region_add_subregion(&s->container, 0xA000, &s->vblend_iomem);
-
- memory_region_init_io(&s->avbufm_iomem, obj, &avbufm_ops, s, TYPE_XLNX_DP
- ".av_buffer_manager", 0x238);
- memory_region_add_subregion(&s->container, 0xB000, &s->avbufm_iomem);
-
- memory_region_init_io(&s->audio_iomem, obj, &audio_ops, s, TYPE_XLNX_DP
- ".audio", sizeof(s->audio_registers));
- memory_region_add_subregion(&s->container, 0xC000, &s->audio_iomem);
-
- sysbus_init_mmio(sbd, &s->container);
- sysbus_init_irq(sbd, &s->irq);
-
- object_property_add_link(obj, "dpdma", TYPE_XLNX_DPDMA,
- (Object **) &s->dpdma,
- xlnx_dp_set_dpdma,
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
- &error_abort);
-
- /*
- * Initialize AUX Bus.
- */
- s->aux_bus = aux_init_bus(DEVICE(obj), "aux");
-
- /*
- * Initialize DPCD and EDID..
- */
- s->dpcd = DPCD(aux_create_slave(s->aux_bus, "dpcd", 0x00000));
- s->edid = I2CDDC(qdev_create(BUS(aux_get_i2c_bus(s->aux_bus)), "i2c-ddc"));
- i2c_set_slave_address(I2C_SLAVE(s->edid), 0x50);
-
- fifo8_create(&s->rx_fifo, 16);
- fifo8_create(&s->tx_fifo, 16);
-}
-
-static void xlnx_dp_realize(DeviceState *dev, Error **errp)
-{
- XlnxDPState *s = XLNX_DP(dev);
- DisplaySurface *surface;
- struct audsettings as;
-
- s->console = graphic_console_init(dev, 0, &xlnx_dp_gfx_ops, s);
- surface = qemu_console_surface(s->console);
- xlnx_dpdma_set_host_data_location(s->dpdma, DP_GRAPHIC_DMA_CHANNEL,
- surface_data(surface));
-
- as.freq = 44100;
- as.nchannels = 2;
- as.fmt = AUD_FMT_S16;
- as.endianness = 0;
-
- AUD_register_card("xlnx_dp.audio", &s->aud_card);
-
- s->amixer_output_stream = AUD_open_out(&s->aud_card,
- s->amixer_output_stream,
- "xlnx_dp.audio.out",
- s,
- xlnx_dp_audio_callback,
- &as);
- AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255);
- xlnx_dp_audio_activate(s);
-}
-
-static void xlnx_dp_reset(DeviceState *dev)
-{
- XlnxDPState *s = XLNX_DP(dev);
-
- memset(s->core_registers, 0, sizeof(s->core_registers));
- s->core_registers[DP_VERSION_REGISTER] = 0x04010000;
- s->core_registers[DP_CORE_ID] = 0x01020000;
- s->core_registers[DP_REPLY_STATUS] = 0x00000010;
- s->core_registers[DP_MSA_TRANSFER_UNIT_SIZE] = 0x00000040;
- s->core_registers[DP_INIT_WAIT] = 0x00000020;
- s->core_registers[DP_PHY_RESET] = 0x00010003;
- s->core_registers[DP_INT_MASK] = 0xFFFFF03F;
- s->core_registers[DP_PHY_STATUS] = 0x00000043;
- s->core_registers[DP_INTERRUPT_SIGNAL_STATE] = 0x00000001;
-
- s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(0)] = 0x00001000;
- s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(4)] = 0x00001000;
- s->vblend_registers[V_BLEND_RGB2YCBCR_COEFF(8)] = 0x00001000;
- s->vblend_registers[V_BLEND_IN1CSC_COEFF(0)] = 0x00001000;
- s->vblend_registers[V_BLEND_IN1CSC_COEFF(4)] = 0x00001000;
- s->vblend_registers[V_BLEND_IN1CSC_COEFF(8)] = 0x00001000;
- s->vblend_registers[V_BLEND_IN2CSC_COEFF(0)] = 0x00001000;
- s->vblend_registers[V_BLEND_IN2CSC_COEFF(4)] = 0x00001000;
- s->vblend_registers[V_BLEND_IN2CSC_COEFF(8)] = 0x00001000;
-
- s->avbufm_registers[AV_BUF_NON_LIVE_LATENCY] = 0x00000180;
- s->avbufm_registers[AV_BUF_OUTPUT_AUDIO_VIDEO_SELECT] = 0x00000008;
- s->avbufm_registers[AV_BUF_DITHER_CONFIG_MAX] = 0x00000FFF;
- s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(0)] = 0x00010101;
- s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(1)] = 0x00010101;
- s->avbufm_registers[AV_BUF_GRAPHICS_COMP_SCALE_FACTOR(2)] = 0x00010101;
- s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(0)] = 0x00010101;
- s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(1)] = 0x00010101;
- s->avbufm_registers[AV_BUF_VIDEO_COMP_SCALE_FACTOR(2)] = 0x00010101;
- s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(0)] = 0x00010101;
- s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(1)] = 0x00010101;
- s->avbufm_registers[AV_BUF_LIVE_VIDEO_COMP_SF(2)] = 0x00010101;
- s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(0)] = 0x00010101;
- s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(1)] = 0x00010101;
- s->avbufm_registers[AV_BUF_LIVE_GFX_COMP_SF(2)] = 0x00010101;
-
- memset(s->audio_registers, 0, sizeof(s->audio_registers));
- s->byte_left = 0;
-
- xlnx_dp_aux_clear_rx_fifo(s);
- xlnx_dp_change_graphic_fmt(s);
- xlnx_dp_update_irq(s);
-}
-
-static void xlnx_dp_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- dc->realize = xlnx_dp_realize;
- dc->vmsd = &vmstate_dp;
- dc->reset = xlnx_dp_reset;
-}
-
-static const TypeInfo xlnx_dp_info = {
- .name = TYPE_XLNX_DP,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(XlnxDPState),
- .instance_init = xlnx_dp_init,
- .class_init = xlnx_dp_class_init,
-};
-
-static void xlnx_dp_register_types(void)
-{
- type_register_static(&xlnx_dp_info);
-}
-
-type_init(xlnx_dp_register_types)
diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs
index 087c8e685..a1abbcf74 100644
--- a/hw/dma/Makefile.objs
+++ b/hw/dma/Makefile.objs
@@ -5,11 +5,9 @@ common-obj-$(CONFIG_PL330) += pl330.o
common-obj-$(CONFIG_I82374) += i82374.o
common-obj-$(CONFIG_I8257) += i8257.o
common-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
-common-obj-$(CONFIG_ZYNQ_DEVCFG) += xlnx-zynq-devcfg.o
common-obj-$(CONFIG_ETRAXFS) += etraxfs_dma.o
common-obj-$(CONFIG_STP2000) += sparc32_dma.o
common-obj-$(CONFIG_SUN4M) += sun4m_iommu.o
-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx_dpdma.o
obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
diff --git a/hw/dma/bcm2835_dma.c b/hw/dma/bcm2835_dma.c
index 5d144a263..542117599 100644
--- a/hw/dma/bcm2835_dma.c
+++ b/hw/dma/bcm2835_dma.c
@@ -6,7 +6,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/dma/bcm2835_dma.h"
-#include "qemu/log.h"
/* DMA CS Control and Status bits */
#define BCM2708_DMA_ACTIVE (1 << 0)
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
index 3bed5c339..9318108b8 100644
--- a/hw/dma/pl080.c
+++ b/hw/dma/pl080.c
@@ -10,7 +10,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
-#include "qemu/log.h"
#define PL080_MAX_CHANNELS 8
#define PL080_CONF_E 0x1
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
index c0bd9fec3..ea89ecb00 100644
--- a/hw/dma/pl330.c
+++ b/hw/dma/pl330.c
@@ -19,7 +19,6 @@
#include "qapi/error.h"
#include "qemu/timer.h"
#include "sysemu/dma.h"
-#include "qemu/log.h"
#ifndef PL330_ERR_DEBUG
#define PL330_ERR_DEBUG 0
diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c
index 634a4328f..2306abc35 100644
--- a/hw/dma/pxa2xx_dma.c
+++ b/hw/dma/pxa2xx_dma.c
@@ -12,7 +12,6 @@
#include "hw/hw.h"
#include "hw/arm/pxa.h"
#include "hw/sysbus.h"
-#include "qapi/error.h"
#define PXA255_DMA_NUM_CHANNELS 16
#define PXA27X_DMA_NUM_CHANNELS 32
@@ -451,36 +450,31 @@ static void pxa2xx_dma_request(void *opaque, int req_num, int on)
}
}
-static void pxa2xx_dma_init(Object *obj)
-{
- DeviceState *dev = DEVICE(obj);
- PXA2xxDMAState *s = PXA2XX_DMA(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-
- memset(s->req, 0, sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
-
- qdev_init_gpio_in(dev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
-
- memory_region_init_io(&s->iomem, obj, &pxa2xx_dma_ops, s,
- "pxa2xx.dma", 0x00010000);
- sysbus_init_mmio(sbd, &s->iomem);
- sysbus_init_irq(sbd, &s->irq);
-}
-
-static void pxa2xx_dma_realize(DeviceState *dev, Error **errp)
+static int pxa2xx_dma_init(SysBusDevice *sbd)
{
+ DeviceState *dev = DEVICE(sbd);
PXA2xxDMAState *s = PXA2XX_DMA(dev);
int i;
if (s->channels <= 0) {
- error_setg(errp, "channels value invalid");
- return;
+ return -1;
}
s->chan = g_new0(PXA2xxDMAChannel, s->channels);
for (i = 0; i < s->channels; i ++)
s->chan[i].state = DCSR_STOPINTR;
+
+ memset(s->req, 0, sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
+
+ qdev_init_gpio_in(dev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_dma_ops, s,
+ "pxa2xx.dma", 0x00010000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+
+ return 0;
}
DeviceState *pxa27x_dma_init(hwaddr base, qemu_irq irq)
@@ -559,18 +553,18 @@ static Property pxa2xx_dma_properties[] = {
static void pxa2xx_dma_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = pxa2xx_dma_init;
dc->desc = "PXA2xx DMA controller";
dc->vmsd = &vmstate_pxa2xx_dma;
dc->props = pxa2xx_dma_properties;
- dc->realize = pxa2xx_dma_realize;
}
static const TypeInfo pxa2xx_dma_info = {
.name = TYPE_PXA2XX_DMA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxDMAState),
- .instance_init = pxa2xx_dma_init,
.class_init = pxa2xx_dma_class_init,
};
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 2f2576faf..a06c2359a 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -27,7 +27,6 @@
#include "hw/mips/mips.h"
#include "hw/sysbus.h"
#include "qemu/timer.h"
-#include "qemu/log.h"
#include "exec/address-spaces.h"
#include "trace.h"
diff --git a/hw/dma/trace-events b/hw/dma/trace-events
deleted file mode 100644
index 22878dfdb..000000000
--- a/hw/dma/trace-events
+++ /dev/null
@@ -1,32 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/dma/rc4030.c
-jazzio_read(uint64_t addr, uint32_t ret) "read reg[0x%"PRIx64"] = 0x%x"
-jazzio_write(uint64_t addr, uint32_t val) "write reg[0x%"PRIx64"] = 0x%x"
-rc4030_read(uint64_t addr, uint32_t ret) "read reg[0x%"PRIx64"] = 0x%x"
-rc4030_write(uint64_t addr, uint32_t val) "write reg[0x%"PRIx64"] = 0x%x"
-
-# hw/dma/sparc32_dma.c
-ledma_memory_read(uint64_t addr) "DMA read addr 0x%"PRIx64
-ledma_memory_write(uint64_t addr) "DMA write addr 0x%"PRIx64
-sparc32_dma_set_irq_raise(void) "Raise IRQ"
-sparc32_dma_set_irq_lower(void) "Lower IRQ"
-espdma_memory_read(uint32_t addr) "DMA read addr 0x%08x"
-espdma_memory_write(uint32_t addr) "DMA write addr 0x%08x"
-sparc32_dma_mem_readl(uint64_t addr, uint32_t ret) "read dmareg %"PRIx64": 0x%08x"
-sparc32_dma_mem_writel(uint64_t addr, uint32_t old, uint32_t val) "write dmareg %"PRIx64": 0x%08x -> 0x%08x"
-sparc32_dma_enable_raise(void) "Raise DMA enable"
-sparc32_dma_enable_lower(void) "Lower DMA enable"
-
-# hw/dma/sun4m_iommu.c
-sun4m_iommu_mem_readl(uint64_t addr, uint32_t ret) "read reg[%"PRIx64"] = %x"
-sun4m_iommu_mem_writel(uint64_t addr, uint32_t val) "write reg[%"PRIx64"] = %x"
-sun4m_iommu_mem_writel_ctrl(uint64_t iostart) "iostart = %"PRIx64
-sun4m_iommu_mem_writel_tlbflush(uint32_t val) "tlb flush %x"
-sun4m_iommu_mem_writel_pgflush(uint32_t val) "page flush %x"
-sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "get flags addr %"PRIx64" => pte %"PRIx64", *pte = %x"
-sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x"
-sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64
-
-# hw/dma/i8257.c
-i8257_unregistered_dma(int nchan, int dma_pos, int dma_len) "unregistered DMA channel used nchan=%d dma_pos=%d dma_len=%d"
diff --git a/hw/dma/xlnx-zynq-devcfg.c b/hw/dma/xlnx-zynq-devcfg.c
deleted file mode 100644
index 3b1052343..000000000
--- a/hw/dma/xlnx-zynq-devcfg.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * QEMU model of the Xilinx Zynq 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.
- */
-
-#include "qemu/osdep.h"
-#include "hw/dma/xlnx-zynq-devcfg.h"
-#include "qemu/bitops.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/dma.h"
-#include "qemu/log.h"
-
-#define FREQ_HZ 900000000
-
-#define BTT_MAX 0x400
-
-#ifndef XLNX_ZYNQ_DEVCFG_ERR_DEBUG
-#define XLNX_ZYNQ_DEVCFG_ERR_DEBUG 0
-#endif
-
-#define DB_PRINT(fmt, args...) do { \
- if (XLNX_ZYNQ_DEVCFG_ERR_DEBUG) { \
- qemu_log("%s: " fmt, __func__, ## args); \
- } \
-} while (0);
-
-REG32(CTRL, 0x00)
- FIELD(CTRL, FORCE_RST, 31, 1) /* Not supported, wr ignored */
- FIELD(CTRL, PCAP_PR, 27, 1) /* Forced to 0 on bad unlock */
- FIELD(CTRL, PCAP_MODE, 26, 1)
- FIELD(CTRL, MULTIBOOT_EN, 24, 1)
- FIELD(CTRL, USER_MODE, 15, 1)
- FIELD(CTRL, PCFG_AES_FUSE, 12, 1)
- FIELD(CTRL, PCFG_AES_EN, 9, 3)
- FIELD(CTRL, SEU_EN, 8, 1)
- FIELD(CTRL, SEC_EN, 7, 1)
- FIELD(CTRL, SPNIDEN, 6, 1)
- FIELD(CTRL, SPIDEN, 5, 1)
- FIELD(CTRL, NIDEN, 4, 1)
- FIELD(CTRL, DBGEN, 3, 1)
- FIELD(CTRL, DAP_EN, 0, 3)
-
-REG32(LOCK, 0x04)
-#define AES_FUSE_LOCK 4
-#define AES_EN_LOCK 3
-#define SEU_LOCK 2
-#define SEC_LOCK 1
-#define DBG_LOCK 0
-
-/* mapping bits in R_LOCK to what they lock in R_CTRL */
-static const uint32_t lock_ctrl_map[] = {
- [AES_FUSE_LOCK] = R_CTRL_PCFG_AES_FUSE_MASK,
- [AES_EN_LOCK] = R_CTRL_PCFG_AES_EN_MASK,
- [SEU_LOCK] = R_CTRL_SEU_EN_MASK,
- [SEC_LOCK] = R_CTRL_SEC_EN_MASK,
- [DBG_LOCK] = R_CTRL_SPNIDEN_MASK | R_CTRL_SPIDEN_MASK |
- R_CTRL_NIDEN_MASK | R_CTRL_DBGEN_MASK |
- R_CTRL_DAP_EN_MASK,
-};
-
-REG32(CFG, 0x08)
- FIELD(CFG, RFIFO_TH, 10, 2)
- FIELD(CFG, WFIFO_TH, 8, 2)
- FIELD(CFG, RCLK_EDGE, 7, 1)
- FIELD(CFG, WCLK_EDGE, 6, 1)
- FIELD(CFG, DISABLE_SRC_INC, 5, 1)
- FIELD(CFG, DISABLE_DST_INC, 4, 1)
-#define R_CFG_RESET 0x50B
-
-REG32(INT_STS, 0x0C)
- FIELD(INT_STS, PSS_GTS_USR_B, 31, 1)
- FIELD(INT_STS, PSS_FST_CFG_B, 30, 1)
- FIELD(INT_STS, PSS_CFG_RESET_B, 27, 1)
- FIELD(INT_STS, RX_FIFO_OV, 18, 1)
- FIELD(INT_STS, WR_FIFO_LVL, 17, 1)
- FIELD(INT_STS, RD_FIFO_LVL, 16, 1)
- FIELD(INT_STS, DMA_CMD_ERR, 15, 1)
- FIELD(INT_STS, DMA_Q_OV, 14, 1)
- FIELD(INT_STS, DMA_DONE, 13, 1)
- FIELD(INT_STS, DMA_P_DONE, 12, 1)
- FIELD(INT_STS, P2D_LEN_ERR, 11, 1)
- FIELD(INT_STS, PCFG_DONE, 2, 1)
-#define R_INT_STS_RSVD ((0x7 << 24) | (0x1 << 19) | (0xF < 7))
-
-REG32(INT_MASK, 0x10)
-
-REG32(STATUS, 0x14)
- FIELD(STATUS, DMA_CMD_Q_F, 31, 1)
- FIELD(STATUS, DMA_CMD_Q_E, 30, 1)
- FIELD(STATUS, DMA_DONE_CNT, 28, 2)
- FIELD(STATUS, RX_FIFO_LVL, 20, 5)
- FIELD(STATUS, TX_FIFO_LVL, 12, 7)
- FIELD(STATUS, PSS_GTS_USR_B, 11, 1)
- FIELD(STATUS, PSS_FST_CFG_B, 10, 1)
- FIELD(STATUS, PSS_CFG_RESET_B, 5, 1)
-
-REG32(DMA_SRC_ADDR, 0x18)
-REG32(DMA_DST_ADDR, 0x1C)
-REG32(DMA_SRC_LEN, 0x20)
-REG32(DMA_DST_LEN, 0x24)
-REG32(ROM_SHADOW, 0x28)
-REG32(SW_ID, 0x30)
-REG32(UNLOCK, 0x34)
-
-#define R_UNLOCK_MAGIC 0x757BDF0D
-
-REG32(MCTRL, 0x80)
- FIELD(MCTRL, PS_VERSION, 28, 4)
- FIELD(MCTRL, PCFG_POR_B, 8, 1)
- FIELD(MCTRL, INT_PCAP_LPBK, 4, 1)
- FIELD(MCTRL, QEMU, 3, 1)
-
-static void xlnx_zynq_devcfg_update_ixr(XlnxZynqDevcfg *s)
-{
- qemu_set_irq(s->irq, ~s->regs[R_INT_MASK] & s->regs[R_INT_STS]);
-}
-
-static void xlnx_zynq_devcfg_reset(DeviceState *dev)
-{
- XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(dev);
- int i;
-
- for (i = 0; i < XLNX_ZYNQ_DEVCFG_R_MAX; ++i) {
- register_reset(&s->regs_info[i]);
- }
-}
-
-static void xlnx_zynq_devcfg_dma_go(XlnxZynqDevcfg *s)
-{
- do {
- uint8_t buf[BTT_MAX];
- XlnxZynqDevcfgDMACmd *dmah = s->dma_cmd_fifo;
- uint32_t btt = BTT_MAX;
- bool loopback = s->regs[R_MCTRL] & R_MCTRL_INT_PCAP_LPBK_MASK;
-
- btt = MIN(btt, dmah->src_len);
- if (loopback) {
- btt = MIN(btt, dmah->dest_len);
- }
- DB_PRINT("reading %x bytes from %x\n", btt, dmah->src_addr);
- dma_memory_read(&address_space_memory, dmah->src_addr, buf, btt);
- dmah->src_len -= btt;
- dmah->src_addr += btt;
- if (loopback && (dmah->src_len || dmah->dest_len)) {
- DB_PRINT("writing %x bytes from %x\n", btt, dmah->dest_addr);
- dma_memory_write(&address_space_memory, dmah->dest_addr, buf, btt);
- dmah->dest_len -= btt;
- dmah->dest_addr += btt;
- }
- if (!dmah->src_len && !dmah->dest_len) {
- DB_PRINT("dma operation finished\n");
- s->regs[R_INT_STS] |= R_INT_STS_DMA_DONE_MASK |
- R_INT_STS_DMA_P_DONE_MASK;
- s->dma_cmd_fifo_num--;
- memmove(s->dma_cmd_fifo, &s->dma_cmd_fifo[1],
- sizeof(s->dma_cmd_fifo) - sizeof(s->dma_cmd_fifo[0]));
- }
- xlnx_zynq_devcfg_update_ixr(s);
- } while (s->dma_cmd_fifo_num);
-}
-
-static void r_ixr_post_write(RegisterInfo *reg, uint64_t val)
-{
- XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
-
- xlnx_zynq_devcfg_update_ixr(s);
-}
-
-static uint64_t r_ctrl_pre_write(RegisterInfo *reg, uint64_t val)
-{
- XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(lock_ctrl_map); ++i) {
- if (s->regs[R_LOCK] & 1 << i) {
- val &= ~lock_ctrl_map[i];
- val |= lock_ctrl_map[i] & s->regs[R_CTRL];
- }
- }
- return val;
-}
-
-static void r_ctrl_post_write(RegisterInfo *reg, uint64_t val)
-{
- const char *device_prefix = object_get_typename(OBJECT(reg->opaque));
- uint32_t aes_en = FIELD_EX32(val, CTRL, PCFG_AES_EN);
-
- if (aes_en != 0 && aes_en != 7) {
- qemu_log_mask(LOG_UNIMP, "%s: warning, aes-en bits inconsistent,"
- "unimplemented security reset should happen!\n",
- device_prefix);
- }
-}
-
-static void r_unlock_post_write(RegisterInfo *reg, uint64_t val)
-{
- XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
- const char *device_prefix = object_get_typename(OBJECT(s));
-
- if (val == R_UNLOCK_MAGIC) {
- DB_PRINT("successful unlock\n");
- s->regs[R_CTRL] |= R_CTRL_PCAP_PR_MASK;
- s->regs[R_CTRL] |= R_CTRL_PCFG_AES_EN_MASK;
- memory_region_set_enabled(&s->iomem, true);
- } else { /* bad unlock attempt */
- qemu_log_mask(LOG_GUEST_ERROR, "%s: failed unlock\n", device_prefix);
- s->regs[R_CTRL] &= ~R_CTRL_PCAP_PR_MASK;
- s->regs[R_CTRL] &= ~R_CTRL_PCFG_AES_EN_MASK;
- /* core becomes inaccessible */
- memory_region_set_enabled(&s->iomem, false);
- }
-}
-
-static uint64_t r_lock_pre_write(RegisterInfo *reg, uint64_t val)
-{
- XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
-
- /* once bits are locked they stay locked */
- return s->regs[R_LOCK] | val;
-}
-
-static void r_dma_dst_len_post_write(RegisterInfo *reg, uint64_t val)
-{
- XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(reg->opaque);
-
- s->dma_cmd_fifo[s->dma_cmd_fifo_num] = (XlnxZynqDevcfgDMACmd) {
- .src_addr = s->regs[R_DMA_SRC_ADDR] & ~0x3UL,
- .dest_addr = s->regs[R_DMA_DST_ADDR] & ~0x3UL,
- .src_len = s->regs[R_DMA_SRC_LEN] << 2,
- .dest_len = s->regs[R_DMA_DST_LEN] << 2,
- };
- s->dma_cmd_fifo_num++;
- DB_PRINT("dma transfer started; %d total transfers pending\n",
- s->dma_cmd_fifo_num);
- xlnx_zynq_devcfg_dma_go(s);
-}
-
-static const RegisterAccessInfo xlnx_zynq_devcfg_regs_info[] = {
- { .name = "CTRL", .addr = A_CTRL,
- .reset = R_CTRL_PCAP_PR_MASK | R_CTRL_PCAP_MODE_MASK | 0x3 << 13,
- .rsvd = 0x1 << 28 | 0x3ff << 13 | 0x3 << 13,
- .pre_write = r_ctrl_pre_write,
- .post_write = r_ctrl_post_write,
- },
- { .name = "LOCK", .addr = A_LOCK,
- .rsvd = MAKE_64BIT_MASK(5, 64 - 5),
- .pre_write = r_lock_pre_write,
- },
- { .name = "CFG", .addr = A_CFG,
- .reset = R_CFG_RESET,
- .rsvd = 0xfffff00f,
- },
- { .name = "INT_STS", .addr = A_INT_STS,
- .w1c = ~R_INT_STS_RSVD,
- .reset = R_INT_STS_PSS_GTS_USR_B_MASK |
- R_INT_STS_PSS_CFG_RESET_B_MASK |
- R_INT_STS_WR_FIFO_LVL_MASK,
- .rsvd = R_INT_STS_RSVD,
- .post_write = r_ixr_post_write,
- },
- { .name = "INT_MASK", .addr = A_INT_MASK,
- .reset = ~0,
- .rsvd = R_INT_STS_RSVD,
- .post_write = r_ixr_post_write,
- },
- { .name = "STATUS", .addr = A_STATUS,
- .reset = R_STATUS_DMA_CMD_Q_E_MASK |
- R_STATUS_PSS_GTS_USR_B_MASK |
- R_STATUS_PSS_CFG_RESET_B_MASK,
- .ro = ~0,
- },
- { .name = "DMA_SRC_ADDR", .addr = A_DMA_SRC_ADDR, },
- { .name = "DMA_DST_ADDR", .addr = A_DMA_DST_ADDR, },
- { .name = "DMA_SRC_LEN", .addr = A_DMA_SRC_LEN,
- .ro = MAKE_64BIT_MASK(27, 64 - 27) },
- { .name = "DMA_DST_LEN", .addr = A_DMA_DST_LEN,
- .ro = MAKE_64BIT_MASK(27, 64 - 27),
- .post_write = r_dma_dst_len_post_write,
- },
- { .name = "ROM_SHADOW", .addr = A_ROM_SHADOW,
- .rsvd = ~0ull,
- },
- { .name = "SW_ID", .addr = A_SW_ID, },
- { .name = "UNLOCK", .addr = A_UNLOCK,
- .post_write = r_unlock_post_write,
- },
- { .name = "MCTRL", .addr = R_MCTRL * 4,
- /* Silicon 3.0 for version field, the mysterious reserved bit 23
- * and QEMU platform identifier.
- */
- .reset = 0x2 << R_MCTRL_PS_VERSION_SHIFT | 1 << 23 | R_MCTRL_QEMU_MASK,
- .ro = ~R_MCTRL_INT_PCAP_LPBK_MASK,
- .rsvd = 0x00f00303,
- },
-};
-
-static const MemoryRegionOps xlnx_zynq_devcfg_reg_ops = {
- .read = register_read_memory,
- .write = register_write_memory,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- }
-};
-
-static const VMStateDescription vmstate_xlnx_zynq_devcfg_dma_cmd = {
- .name = "xlnx_zynq_devcfg_dma_cmd",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(src_addr, XlnxZynqDevcfgDMACmd),
- VMSTATE_UINT32(dest_addr, XlnxZynqDevcfgDMACmd),
- VMSTATE_UINT32(src_len, XlnxZynqDevcfgDMACmd),
- VMSTATE_UINT32(dest_len, XlnxZynqDevcfgDMACmd),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_xlnx_zynq_devcfg = {
- .name = "xlnx_zynq_devcfg",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT_ARRAY(dma_cmd_fifo, XlnxZynqDevcfg,
- XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN, 0,
- vmstate_xlnx_zynq_devcfg_dma_cmd,
- XlnxZynqDevcfgDMACmd),
- VMSTATE_UINT8(dma_cmd_fifo_num, XlnxZynqDevcfg),
- VMSTATE_UINT32_ARRAY(regs, XlnxZynqDevcfg, XLNX_ZYNQ_DEVCFG_R_MAX),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void xlnx_zynq_devcfg_init(Object *obj)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- XlnxZynqDevcfg *s = XLNX_ZYNQ_DEVCFG(obj);
- RegisterInfoArray *reg_array;
-
- sysbus_init_irq(sbd, &s->irq);
-
- memory_region_init(&s->iomem, obj, "devcfg", XLNX_ZYNQ_DEVCFG_R_MAX * 4);
- reg_array =
- register_init_block32(DEVICE(obj), xlnx_zynq_devcfg_regs_info,
- ARRAY_SIZE(xlnx_zynq_devcfg_regs_info),
- s->regs_info, s->regs,
- &xlnx_zynq_devcfg_reg_ops,
- XLNX_ZYNQ_DEVCFG_ERR_DEBUG,
- XLNX_ZYNQ_DEVCFG_R_MAX);
- memory_region_add_subregion(&s->iomem,
- A_CTRL,
- &reg_array->mem);
-
- sysbus_init_mmio(sbd, &s->iomem);
-}
-
-static void xlnx_zynq_devcfg_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->reset = xlnx_zynq_devcfg_reset;
- dc->vmsd = &vmstate_xlnx_zynq_devcfg;
-}
-
-static const TypeInfo xlnx_zynq_devcfg_info = {
- .name = TYPE_XLNX_ZYNQ_DEVCFG,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(XlnxZynqDevcfg),
- .instance_init = xlnx_zynq_devcfg_init,
- .class_init = xlnx_zynq_devcfg_class_init,
-};
-
-static void xlnx_zynq_devcfg_register_types(void)
-{
- type_register_static(&xlnx_zynq_devcfg_info);
-}
-
-type_init(xlnx_zynq_devcfg_register_types)
diff --git a/hw/dma/xlnx_dpdma.c b/hw/dma/xlnx_dpdma.c
deleted file mode 100644
index 8ceb21ddb..000000000
--- a/hw/dma/xlnx_dpdma.c
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * xlnx_dpdma.c
- *
- * 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/>.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "hw/dma/xlnx_dpdma.h"
-
-#ifndef DEBUG_DPDMA
-#define DEBUG_DPDMA 0
-#endif
-
-#define DPRINTF(fmt, ...) do { \
- if (DEBUG_DPDMA) { \
- qemu_log("xlnx_dpdma: " fmt , ## __VA_ARGS__); \
- } \
-} while (0);
-
-/*
- * Registers offset for DPDMA.
- */
-#define DPDMA_ERR_CTRL (0x0000)
-#define DPDMA_ISR (0x0004 >> 2)
-#define DPDMA_IMR (0x0008 >> 2)
-#define DPDMA_IEN (0x000C >> 2)
-#define DPDMA_IDS (0x0010 >> 2)
-#define DPDMA_EISR (0x0014 >> 2)
-#define DPDMA_EIMR (0x0018 >> 2)
-#define DPDMA_EIEN (0x001C >> 2)
-#define DPDMA_EIDS (0x0020 >> 2)
-#define DPDMA_CNTL (0x0100 >> 2)
-
-#define DPDMA_GBL (0x0104 >> 2)
-#define DPDMA_GBL_TRG_CH(n) (1 << n)
-#define DPDMA_GBL_RTRG_CH(n) (1 << 6 << n)
-
-#define DPDMA_ALC0_CNTL (0x0108 >> 2)
-#define DPDMA_ALC0_STATUS (0x010C >> 2)
-#define DPDMA_ALC0_MAX (0x0110 >> 2)
-#define DPDMA_ALC0_MIN (0x0114 >> 2)
-#define DPDMA_ALC0_ACC (0x0118 >> 2)
-#define DPDMA_ALC0_ACC_TRAN (0x011C >> 2)
-#define DPDMA_ALC1_CNTL (0x0120 >> 2)
-#define DPDMA_ALC1_STATUS (0x0124 >> 2)
-#define DPDMA_ALC1_MAX (0x0128 >> 2)
-#define DPDMA_ALC1_MIN (0x012C >> 2)
-#define DPDMA_ALC1_ACC (0x0130 >> 2)
-#define DPDMA_ALC1_ACC_TRAN (0x0134 >> 2)
-
-#define DPDMA_DSCR_STRT_ADDRE_CH(n) ((0x0200 + n * 0x100) >> 2)
-#define DPDMA_DSCR_STRT_ADDR_CH(n) ((0x0204 + n * 0x100) >> 2)
-#define DPDMA_DSCR_NEXT_ADDRE_CH(n) ((0x0208 + n * 0x100) >> 2)
-#define DPDMA_DSCR_NEXT_ADDR_CH(n) ((0x020C + n * 0x100) >> 2)
-#define DPDMA_PYLD_CUR_ADDRE_CH(n) ((0x0210 + n * 0x100) >> 2)
-#define DPDMA_PYLD_CUR_ADDR_CH(n) ((0x0214 + n * 0x100) >> 2)
-
-#define DPDMA_CNTL_CH(n) ((0x0218 + n * 0x100) >> 2)
-#define DPDMA_CNTL_CH_EN (1)
-#define DPDMA_CNTL_CH_PAUSED (1 << 1)
-
-#define DPDMA_STATUS_CH(n) ((0x021C + n * 0x100) >> 2)
-#define DPDMA_STATUS_BURST_TYPE (1 << 4)
-#define DPDMA_STATUS_MODE (1 << 5)
-#define DPDMA_STATUS_EN_CRC (1 << 6)
-#define DPDMA_STATUS_LAST_DSCR (1 << 7)
-#define DPDMA_STATUS_LDSCR_FRAME (1 << 8)
-#define DPDMA_STATUS_IGNR_DONE (1 << 9)
-#define DPDMA_STATUS_DSCR_DONE (1 << 10)
-#define DPDMA_STATUS_EN_DSCR_UP (1 << 11)
-#define DPDMA_STATUS_EN_DSCR_INTR (1 << 12)
-#define DPDMA_STATUS_PREAMBLE_OFF (13)
-
-#define DPDMA_VDO_CH(n) ((0x0220 + n * 0x100) >> 2)
-#define DPDMA_PYLD_SZ_CH(n) ((0x0224 + n * 0x100) >> 2)
-#define DPDMA_DSCR_ID_CH(n) ((0x0228 + n * 0x100) >> 2)
-
-/*
- * Descriptor control field.
- */
-#define CONTROL_PREAMBLE_VALUE 0xA5
-
-#define DSCR_CTRL_PREAMBLE 0xFF
-#define DSCR_CTRL_EN_DSCR_DONE_INTR (1 << 8)
-#define DSCR_CTRL_EN_DSCR_UPDATE (1 << 9)
-#define DSCR_CTRL_IGNORE_DONE (1 << 10)
-#define DSCR_CTRL_AXI_BURST_TYPE (1 << 11)
-#define DSCR_CTRL_AXCACHE (0x0F << 12)
-#define DSCR_CTRL_AXPROT (0x2 << 16)
-#define DSCR_CTRL_DESCRIPTOR_MODE (1 << 18)
-#define DSCR_CTRL_LAST_DESCRIPTOR (1 << 19)
-#define DSCR_CTRL_ENABLE_CRC (1 << 20)
-#define DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME (1 << 21)
-
-/*
- * Descriptor timestamp field.
- */
-#define STATUS_DONE (1 << 31)
-
-#define DPDMA_FRAG_MAX_SZ (4096)
-
-enum DPDMABurstType {
- DPDMA_INCR = 0,
- DPDMA_FIXED = 1
-};
-
-enum DPDMAMode {
- DPDMA_CONTIGOUS = 0,
- DPDMA_FRAGMENTED = 1
-};
-
-struct DPDMADescriptor {
- uint32_t control;
- uint32_t descriptor_id;
- /* transfer size in byte. */
- uint32_t xfer_size;
- uint32_t line_size_stride;
- uint32_t timestamp_lsb;
- uint32_t timestamp_msb;
- /* contains extension for both descriptor and source. */
- uint32_t address_extension;
- uint32_t next_descriptor;
- uint32_t source_address;
- uint32_t address_extension_23;
- uint32_t address_extension_45;
- uint32_t source_address2;
- uint32_t source_address3;
- uint32_t source_address4;
- uint32_t source_address5;
- uint32_t crc;
-};
-
-typedef enum DPDMABurstType DPDMABurstType;
-typedef enum DPDMAMode DPDMAMode;
-typedef struct DPDMADescriptor DPDMADescriptor;
-
-static bool xlnx_dpdma_desc_is_last(DPDMADescriptor *desc)
-{
- return ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR) != 0);
-}
-
-static bool xlnx_dpdma_desc_is_last_of_frame(DPDMADescriptor *desc)
-{
- return ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME) != 0);
-}
-
-static uint64_t xlnx_dpdma_desc_get_source_address(DPDMADescriptor *desc,
- uint8_t frag)
-{
- uint64_t addr = 0;
- assert(frag < 5);
-
- switch (frag) {
- case 0:
- addr = desc->source_address
- + (extract32(desc->address_extension, 16, 12) << 20);
- break;
- case 1:
- addr = desc->source_address2
- + (extract32(desc->address_extension_23, 0, 12) << 8);
- break;
- case 2:
- addr = desc->source_address3
- + (extract32(desc->address_extension_23, 16, 12) << 20);
- break;
- case 3:
- addr = desc->source_address4
- + (extract32(desc->address_extension_45, 0, 12) << 8);
- break;
- case 4:
- addr = desc->source_address5
- + (extract32(desc->address_extension_45, 16, 12) << 20);
- break;
- default:
- addr = 0;
- break;
- }
-
- return addr;
-}
-
-static uint32_t xlnx_dpdma_desc_get_transfer_size(DPDMADescriptor *desc)
-{
- return desc->xfer_size;
-}
-
-static uint32_t xlnx_dpdma_desc_get_line_size(DPDMADescriptor *desc)
-{
- return extract32(desc->line_size_stride, 0, 18);
-}
-
-static uint32_t xlnx_dpdma_desc_get_line_stride(DPDMADescriptor *desc)
-{
- return extract32(desc->line_size_stride, 18, 14) * 16;
-}
-
-static inline bool xlnx_dpdma_desc_crc_enabled(DPDMADescriptor *desc)
-{
- return (desc->control & DSCR_CTRL_ENABLE_CRC) != 0;
-}
-
-static inline bool xlnx_dpdma_desc_check_crc(DPDMADescriptor *desc)
-{
- uint32_t *p = (uint32_t *)desc;
- uint32_t crc = 0;
- uint8_t i;
-
- /*
- * CRC is calculated on the whole descriptor except the last 32bits word
- * using 32bits addition.
- */
- for (i = 0; i < 15; i++) {
- crc += p[i];
- }
-
- return crc == desc->crc;
-}
-
-static inline bool xlnx_dpdma_desc_completion_interrupt(DPDMADescriptor *desc)
-{
- return (desc->control & DSCR_CTRL_EN_DSCR_DONE_INTR) != 0;
-}
-
-static inline bool xlnx_dpdma_desc_is_valid(DPDMADescriptor *desc)
-{
- return (desc->control & DSCR_CTRL_PREAMBLE) == CONTROL_PREAMBLE_VALUE;
-}
-
-static inline bool xlnx_dpdma_desc_is_contiguous(DPDMADescriptor *desc)
-{
- return (desc->control & DSCR_CTRL_DESCRIPTOR_MODE) == 0;
-}
-
-static inline bool xlnx_dpdma_desc_update_enabled(DPDMADescriptor *desc)
-{
- return (desc->control & DSCR_CTRL_EN_DSCR_UPDATE) != 0;
-}
-
-static inline void xlnx_dpdma_desc_set_done(DPDMADescriptor *desc)
-{
- desc->timestamp_msb |= STATUS_DONE;
-}
-
-static inline bool xlnx_dpdma_desc_is_already_done(DPDMADescriptor *desc)
-{
- return (desc->timestamp_msb & STATUS_DONE) != 0;
-}
-
-static inline bool xlnx_dpdma_desc_ignore_done_bit(DPDMADescriptor *desc)
-{
- return (desc->control & DSCR_CTRL_IGNORE_DONE) != 0;
-}
-
-static const VMStateDescription vmstate_xlnx_dpdma = {
- .name = TYPE_XLNX_DPDMA,
- .version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(registers, XlnxDPDMAState,
- XLNX_DPDMA_REG_ARRAY_SIZE),
- VMSTATE_BOOL_ARRAY(operation_finished, XlnxDPDMAState, 6),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void xlnx_dpdma_update_irq(XlnxDPDMAState *s)
-{
- bool flags;
-
- flags = ((s->registers[DPDMA_ISR] & (~s->registers[DPDMA_IMR]))
- || (s->registers[DPDMA_EISR] & (~s->registers[DPDMA_EIMR])));
- qemu_set_irq(s->irq, flags);
-}
-
-static uint64_t xlnx_dpdma_descriptor_start_address(XlnxDPDMAState *s,
- uint8_t channel)
-{
- return (s->registers[DPDMA_DSCR_STRT_ADDRE_CH(channel)] << 16)
- + s->registers[DPDMA_DSCR_STRT_ADDR_CH(channel)];
-}
-
-static uint64_t xlnx_dpdma_descriptor_next_address(XlnxDPDMAState *s,
- uint8_t channel)
-{
- return ((uint64_t)s->registers[DPDMA_DSCR_NEXT_ADDRE_CH(channel)] << 32)
- + s->registers[DPDMA_DSCR_NEXT_ADDR_CH(channel)];
-}
-
-static bool xlnx_dpdma_is_channel_enabled(XlnxDPDMAState *s,
- uint8_t channel)
-{
- return (s->registers[DPDMA_CNTL_CH(channel)] & DPDMA_CNTL_CH_EN) != 0;
-}
-
-static bool xlnx_dpdma_is_channel_paused(XlnxDPDMAState *s,
- uint8_t channel)
-{
- return (s->registers[DPDMA_CNTL_CH(channel)] & DPDMA_CNTL_CH_PAUSED) != 0;
-}
-
-static inline bool xlnx_dpdma_is_channel_retriggered(XlnxDPDMAState *s,
- uint8_t channel)
-{
- /* Clear the retriggered bit after reading it. */
- bool channel_is_retriggered = s->registers[DPDMA_GBL]
- & DPDMA_GBL_RTRG_CH(channel);
- s->registers[DPDMA_GBL] &= ~DPDMA_GBL_RTRG_CH(channel);
- return channel_is_retriggered;
-}
-
-static inline bool xlnx_dpdma_is_channel_triggered(XlnxDPDMAState *s,
- uint8_t channel)
-{
- return s->registers[DPDMA_GBL] & DPDMA_GBL_TRG_CH(channel);
-}
-
-static void xlnx_dpdma_update_desc_info(XlnxDPDMAState *s, uint8_t channel,
- DPDMADescriptor *desc)
-{
- s->registers[DPDMA_DSCR_NEXT_ADDRE_CH(channel)] =
- extract32(desc->address_extension, 0, 16);
- s->registers[DPDMA_DSCR_NEXT_ADDR_CH(channel)] = desc->next_descriptor;
- s->registers[DPDMA_PYLD_CUR_ADDRE_CH(channel)] =
- extract32(desc->address_extension, 16, 16);
- s->registers[DPDMA_PYLD_CUR_ADDR_CH(channel)] = desc->source_address;
- s->registers[DPDMA_VDO_CH(channel)] =
- extract32(desc->line_size_stride, 18, 14)
- + (extract32(desc->line_size_stride, 0, 18)
- << 14);
- s->registers[DPDMA_PYLD_SZ_CH(channel)] = desc->xfer_size;
- s->registers[DPDMA_DSCR_ID_CH(channel)] = desc->descriptor_id;
-
- /* Compute the status register with the descriptor information. */
- s->registers[DPDMA_STATUS_CH(channel)] =
- extract32(desc->control, 0, 8) << 13;
- if ((desc->control & DSCR_CTRL_EN_DSCR_DONE_INTR) != 0) {
- s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_DSCR_INTR;
- }
- if ((desc->control & DSCR_CTRL_EN_DSCR_UPDATE) != 0) {
- s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_DSCR_UP;
- }
- if ((desc->timestamp_msb & STATUS_DONE) != 0) {
- s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_DSCR_DONE;
- }
- if ((desc->control & DSCR_CTRL_IGNORE_DONE) != 0) {
- s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_IGNR_DONE;
- }
- if ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME) != 0) {
- s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_LDSCR_FRAME;
- }
- if ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR) != 0) {
- s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_LAST_DSCR;
- }
- if ((desc->control & DSCR_CTRL_ENABLE_CRC) != 0) {
- s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_CRC;
- }
- if ((desc->control & DSCR_CTRL_DESCRIPTOR_MODE) != 0) {
- s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_MODE;
- }
- if ((desc->control & DSCR_CTRL_AXI_BURST_TYPE) != 0) {
- s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_BURST_TYPE;
- }
-}
-
-static void xlnx_dpdma_dump_descriptor(DPDMADescriptor *desc)
-{
- if (DEBUG_DPDMA) {
- qemu_log("DUMP DESCRIPTOR:\n");
- qemu_hexdump((char *)desc, stdout, "", sizeof(DPDMADescriptor));
- }
-}
-
-static uint64_t xlnx_dpdma_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- XlnxDPDMAState *s = XLNX_DPDMA(opaque);
-
- DPRINTF("read @%" HWADDR_PRIx "\n", offset);
- offset = offset >> 2;
-
- switch (offset) {
- /*
- * Trying to read a write only register.
- */
- case DPDMA_GBL:
- return 0;
- default:
- assert(offset <= (0xFFC >> 2));
- return s->registers[offset];
- }
- return 0;
-}
-
-static void xlnx_dpdma_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- XlnxDPDMAState *s = XLNX_DPDMA(opaque);
-
- DPRINTF("write @%" HWADDR_PRIx " = %" PRIx64 "\n", offset, value);
- offset = offset >> 2;
-
- switch (offset) {
- case DPDMA_ISR:
- s->registers[DPDMA_ISR] &= ~value;
- xlnx_dpdma_update_irq(s);
- break;
- case DPDMA_IEN:
- s->registers[DPDMA_IMR] &= ~value;
- break;
- case DPDMA_IDS:
- s->registers[DPDMA_IMR] |= value;
- break;
- case DPDMA_EISR:
- s->registers[DPDMA_EISR] &= ~value;
- xlnx_dpdma_update_irq(s);
- break;
- case DPDMA_EIEN:
- s->registers[DPDMA_EIMR] &= ~value;
- break;
- case DPDMA_EIDS:
- s->registers[DPDMA_EIMR] |= value;
- break;
- case DPDMA_IMR:
- case DPDMA_EIMR:
- case DPDMA_DSCR_NEXT_ADDRE_CH(0):
- case DPDMA_DSCR_NEXT_ADDRE_CH(1):
- case DPDMA_DSCR_NEXT_ADDRE_CH(2):
- case DPDMA_DSCR_NEXT_ADDRE_CH(3):
- case DPDMA_DSCR_NEXT_ADDRE_CH(4):
- case DPDMA_DSCR_NEXT_ADDRE_CH(5):
- case DPDMA_DSCR_NEXT_ADDR_CH(0):
- case DPDMA_DSCR_NEXT_ADDR_CH(1):
- case DPDMA_DSCR_NEXT_ADDR_CH(2):
- case DPDMA_DSCR_NEXT_ADDR_CH(3):
- case DPDMA_DSCR_NEXT_ADDR_CH(4):
- case DPDMA_DSCR_NEXT_ADDR_CH(5):
- case DPDMA_PYLD_CUR_ADDRE_CH(0):
- case DPDMA_PYLD_CUR_ADDRE_CH(1):
- case DPDMA_PYLD_CUR_ADDRE_CH(2):
- case DPDMA_PYLD_CUR_ADDRE_CH(3):
- case DPDMA_PYLD_CUR_ADDRE_CH(4):
- case DPDMA_PYLD_CUR_ADDRE_CH(5):
- case DPDMA_PYLD_CUR_ADDR_CH(0):
- case DPDMA_PYLD_CUR_ADDR_CH(1):
- case DPDMA_PYLD_CUR_ADDR_CH(2):
- case DPDMA_PYLD_CUR_ADDR_CH(3):
- case DPDMA_PYLD_CUR_ADDR_CH(4):
- case DPDMA_PYLD_CUR_ADDR_CH(5):
- case DPDMA_STATUS_CH(0):
- case DPDMA_STATUS_CH(1):
- case DPDMA_STATUS_CH(2):
- case DPDMA_STATUS_CH(3):
- case DPDMA_STATUS_CH(4):
- case DPDMA_STATUS_CH(5):
- case DPDMA_VDO_CH(0):
- case DPDMA_VDO_CH(1):
- case DPDMA_VDO_CH(2):
- case DPDMA_VDO_CH(3):
- case DPDMA_VDO_CH(4):
- case DPDMA_VDO_CH(5):
- case DPDMA_PYLD_SZ_CH(0):
- case DPDMA_PYLD_SZ_CH(1):
- case DPDMA_PYLD_SZ_CH(2):
- case DPDMA_PYLD_SZ_CH(3):
- case DPDMA_PYLD_SZ_CH(4):
- case DPDMA_PYLD_SZ_CH(5):
- case DPDMA_DSCR_ID_CH(0):
- case DPDMA_DSCR_ID_CH(1):
- case DPDMA_DSCR_ID_CH(2):
- case DPDMA_DSCR_ID_CH(3):
- case DPDMA_DSCR_ID_CH(4):
- case DPDMA_DSCR_ID_CH(5):
- /*
- * Trying to write to a read only register..
- */
- break;
- case DPDMA_GBL:
- /*
- * This is a write only register so it's read as zero in the read
- * callback.
- * We store the value anyway so we can know if the channel is
- * enabled.
- */
- s->registers[offset] |= value & 0x00000FFF;
- break;
- case DPDMA_DSCR_STRT_ADDRE_CH(0):
- case DPDMA_DSCR_STRT_ADDRE_CH(1):
- case DPDMA_DSCR_STRT_ADDRE_CH(2):
- case DPDMA_DSCR_STRT_ADDRE_CH(3):
- case DPDMA_DSCR_STRT_ADDRE_CH(4):
- case DPDMA_DSCR_STRT_ADDRE_CH(5):
- value &= 0x0000FFFF;
- s->registers[offset] = value;
- break;
- case DPDMA_CNTL_CH(0):
- s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(0);
- value &= 0x3FFFFFFF;
- s->registers[offset] = value;
- break;
- case DPDMA_CNTL_CH(1):
- s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(1);
- value &= 0x3FFFFFFF;
- s->registers[offset] = value;
- break;
- case DPDMA_CNTL_CH(2):
- s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(2);
- value &= 0x3FFFFFFF;
- s->registers[offset] = value;
- break;
- case DPDMA_CNTL_CH(3):
- s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(3);
- value &= 0x3FFFFFFF;
- s->registers[offset] = value;
- break;
- case DPDMA_CNTL_CH(4):
- s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(4);
- value &= 0x3FFFFFFF;
- s->registers[offset] = value;
- break;
- case DPDMA_CNTL_CH(5):
- s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(5);
- value &= 0x3FFFFFFF;
- s->registers[offset] = value;
- break;
- default:
- assert(offset <= (0xFFC >> 2));
- s->registers[offset] = value;
- break;
- }
-}
-
-static const MemoryRegionOps dma_ops = {
- .read = xlnx_dpdma_read,
- .write = xlnx_dpdma_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .impl = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-static void xlnx_dpdma_init(Object *obj)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- XlnxDPDMAState *s = XLNX_DPDMA(obj);
-
- memory_region_init_io(&s->iomem, obj, &dma_ops, s,
- TYPE_XLNX_DPDMA, 0x1000);
- sysbus_init_mmio(sbd, &s->iomem);
- sysbus_init_irq(sbd, &s->irq);
-}
-
-static void xlnx_dpdma_reset(DeviceState *dev)
-{
- XlnxDPDMAState *s = XLNX_DPDMA(dev);
- size_t i;
-
- memset(s->registers, 0, sizeof(s->registers));
- s->registers[DPDMA_IMR] = 0x07FFFFFF;
- s->registers[DPDMA_EIMR] = 0xFFFFFFFF;
- s->registers[DPDMA_ALC0_MIN] = 0x0000FFFF;
- s->registers[DPDMA_ALC1_MIN] = 0x0000FFFF;
-
- for (i = 0; i < 6; i++) {
- s->data[i] = NULL;
- s->operation_finished[i] = true;
- }
-}
-
-static void xlnx_dpdma_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- dc->vmsd = &vmstate_xlnx_dpdma;
- dc->reset = xlnx_dpdma_reset;
-}
-
-static const TypeInfo xlnx_dpdma_info = {
- .name = TYPE_XLNX_DPDMA,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(XlnxDPDMAState),
- .instance_init = xlnx_dpdma_init,
- .class_init = xlnx_dpdma_class_init,
-};
-
-static void xlnx_dpdma_register_types(void)
-{
- type_register_static(&xlnx_dpdma_info);
-}
-
-size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel,
- bool one_desc)
-{
- uint64_t desc_addr;
- uint64_t source_addr[6];
- DPDMADescriptor desc;
- bool done = false;
- size_t ptr = 0;
-
- assert(channel <= 5);
-
- DPRINTF("start dpdma channel 0x%" PRIX8 "\n", channel);
-
- if (!xlnx_dpdma_is_channel_triggered(s, channel)) {
- DPRINTF("Channel isn't triggered..\n");
- return 0;
- }
-
- if (!xlnx_dpdma_is_channel_enabled(s, channel)) {
- DPRINTF("Channel isn't enabled..\n");
- return 0;
- }
-
- if (xlnx_dpdma_is_channel_paused(s, channel)) {
- DPRINTF("Channel is paused..\n");
- return 0;
- }
-
- do {
- if ((s->operation_finished[channel])
- || xlnx_dpdma_is_channel_retriggered(s, channel)) {
- desc_addr = xlnx_dpdma_descriptor_start_address(s, channel);
- s->operation_finished[channel] = false;
- } else {
- desc_addr = xlnx_dpdma_descriptor_next_address(s, channel);
- }
-
- if (dma_memory_read(&address_space_memory, desc_addr, &desc,
- sizeof(DPDMADescriptor))) {
- s->registers[DPDMA_EISR] |= ((1 << 1) << channel);
- xlnx_dpdma_update_irq(s);
- s->operation_finished[channel] = true;
- DPRINTF("Can't get the descriptor.\n");
- break;
- }
-
- xlnx_dpdma_update_desc_info(s, channel, &desc);
-
-#ifdef DEBUG_DPDMA
- xlnx_dpdma_dump_descriptor(&desc);
-#endif
-
- DPRINTF("location of the descriptor: %" PRIx64 "\n", desc_addr);
- if (!xlnx_dpdma_desc_is_valid(&desc)) {
- s->registers[DPDMA_EISR] |= ((1 << 7) << channel);
- xlnx_dpdma_update_irq(s);
- s->operation_finished[channel] = true;
- DPRINTF("Invalid descriptor..\n");
- break;
- }
-
- if (xlnx_dpdma_desc_crc_enabled(&desc)
- && !xlnx_dpdma_desc_check_crc(&desc)) {
- s->registers[DPDMA_EISR] |= ((1 << 13) << channel);
- xlnx_dpdma_update_irq(s);
- s->operation_finished[channel] = true;
- DPRINTF("Bad CRC for descriptor..\n");
- break;
- }
-
- if (xlnx_dpdma_desc_is_already_done(&desc)
- && !xlnx_dpdma_desc_ignore_done_bit(&desc)) {
- /* We are trying to process an already processed descriptor. */
- s->registers[DPDMA_EISR] |= ((1 << 25) << channel);
- xlnx_dpdma_update_irq(s);
- s->operation_finished[channel] = true;
- DPRINTF("Already processed descriptor..\n");
- break;
- }
-
- done = xlnx_dpdma_desc_is_last(&desc)
- || xlnx_dpdma_desc_is_last_of_frame(&desc);
-
- s->operation_finished[channel] = done;
- if (s->data[channel]) {
- int64_t transfer_len = xlnx_dpdma_desc_get_transfer_size(&desc);
- uint32_t line_size = xlnx_dpdma_desc_get_line_size(&desc);
- uint32_t line_stride = xlnx_dpdma_desc_get_line_stride(&desc);
- if (xlnx_dpdma_desc_is_contiguous(&desc)) {
- source_addr[0] = xlnx_dpdma_desc_get_source_address(&desc, 0);
- while (transfer_len != 0) {
- if (dma_memory_read(&address_space_memory,
- source_addr[0],
- &s->data[channel][ptr],
- line_size)) {
- s->registers[DPDMA_ISR] |= ((1 << 12) << channel);
- xlnx_dpdma_update_irq(s);
- DPRINTF("Can't get data.\n");
- break;
- }
- ptr += line_size;
- transfer_len -= line_size;
- source_addr[0] += line_stride;
- }
- } else {
- DPRINTF("Source address:\n");
- int frag;
- for (frag = 0; frag < 5; frag++) {
- source_addr[frag] =
- xlnx_dpdma_desc_get_source_address(&desc, frag);
- DPRINTF("Fragment %u: %" PRIx64 "\n", frag + 1,
- source_addr[frag]);
- }
-
- frag = 0;
- while ((transfer_len < 0) && (frag < 5)) {
- size_t fragment_len = DPDMA_FRAG_MAX_SZ
- - (source_addr[frag] % DPDMA_FRAG_MAX_SZ);
-
- if (dma_memory_read(&address_space_memory,
- source_addr[frag],
- &(s->data[channel][ptr]),
- fragment_len)) {
- s->registers[DPDMA_ISR] |= ((1 << 12) << channel);
- xlnx_dpdma_update_irq(s);
- DPRINTF("Can't get data.\n");
- break;
- }
- ptr += fragment_len;
- transfer_len -= fragment_len;
- frag += 1;
- }
- }
- }
-
- if (xlnx_dpdma_desc_update_enabled(&desc)) {
- /* The descriptor need to be updated when it's completed. */
- DPRINTF("update the descriptor with the done flag set.\n");
- xlnx_dpdma_desc_set_done(&desc);
- dma_memory_write(&address_space_memory, desc_addr, &desc,
- sizeof(DPDMADescriptor));
- }
-
- if (xlnx_dpdma_desc_completion_interrupt(&desc)) {
- DPRINTF("completion interrupt enabled!\n");
- s->registers[DPDMA_ISR] |= (1 << channel);
- xlnx_dpdma_update_irq(s);
- }
-
- } while (!done && !one_desc);
-
- return ptr;
-}
-
-void xlnx_dpdma_set_host_data_location(XlnxDPDMAState *s, uint8_t channel,
- void *p)
-{
- if (!s) {
- qemu_log_mask(LOG_UNIMP, "DPDMA client not attached to valid DPDMA"
- " instance\n");
- return;
- }
-
- assert(channel <= 5);
- s->data[channel] = p;
-}
-
-void xlnx_dpdma_trigger_vsync_irq(XlnxDPDMAState *s)
-{
- s->registers[DPDMA_ISR] |= (1 << 27);
- xlnx_dpdma_update_irq(s);
-}
-
-type_init(xlnx_dpdma_register_types)
diff --git a/hw/gpio/gpio_key.c b/hw/gpio/gpio_key.c
index b34aa49df..ef287727b 100644
--- a/hw/gpio/gpio_key.c
+++ b/hw/gpio/gpio_key.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
-#include "qemu/timer.h"
#define TYPE_GPIOKEY "gpio-key"
#define GPIOKEY(obj) OBJECT_CHECK(GPIOKEYState, (obj), TYPE_GPIOKEY)
diff --git a/hw/gpio/imx_gpio.c b/hw/gpio/imx_gpio.c
index f3574aa8f..ed7e247f5 100644
--- a/hw/gpio/imx_gpio.c
+++ b/hw/gpio/imx_gpio.c
@@ -19,7 +19,6 @@
#include "qemu/osdep.h"
#include "hw/gpio/imx_gpio.h"
-#include "qemu/log.h"
#ifndef DEBUG_IMX_GPIO
#define DEBUG_IMX_GPIO 0
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
index dabef4a11..9b1b004fc 100644
--- a/hw/gpio/omap_gpio.c
+++ b/hw/gpio/omap_gpio.c
@@ -23,7 +23,6 @@
#include "hw/arm/omap.h"
#include "hw/sysbus.h"
#include "qemu/error-report.h"
-#include "qapi/error.h"
struct omap_gpio_s {
qemu_irq irq;
@@ -679,46 +678,48 @@ static const MemoryRegionOps omap2_gpif_top_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void omap_gpio_init(Object *obj)
+static int omap_gpio_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- struct omap_gpif_s *s = OMAP1_GPIO(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ struct omap_gpif_s *s = OMAP1_GPIO(dev);
+ if (!s->clk) {
+ error_report("omap-gpio: clk not connected");
+ return -1;
+ }
qdev_init_gpio_in(dev, omap_gpio_set, 16);
qdev_init_gpio_out(dev, s->omap1.handler, 16);
sysbus_init_irq(sbd, &s->omap1.irq);
- memory_region_init_io(&s->iomem, obj, &omap_gpio_ops, &s->omap1,
+ memory_region_init_io(&s->iomem, OBJECT(s), &omap_gpio_ops, &s->omap1,
"omap.gpio", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
+ return 0;
}
-static void omap_gpio_realize(DeviceState *dev, Error **errp)
-{
- struct omap_gpif_s *s = OMAP1_GPIO(dev);
-
- if (!s->clk) {
- error_setg(errp, "omap-gpio: clk not connected");
- }
-}
-
-static void omap2_gpio_realize(DeviceState *dev, Error **errp)
+static int omap2_gpio_init(SysBusDevice *sbd)
{
+ DeviceState *dev = DEVICE(sbd);
struct omap2_gpif_s *s = OMAP2_GPIO(dev);
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
int i;
if (!s->iclk) {
- error_setg(errp, "omap2-gpio: iclk not connected");
- return;
+ error_report("omap2-gpio: iclk not connected");
+ return -1;
}
s->modulecount = s->mpu_model < omap2430 ? 4
- : s->mpu_model < omap3430 ? 5
- : 6;
+ : s->mpu_model < omap3430 ? 5
+ : 6;
+
+ for (i = 0; i < s->modulecount; i++) {
+ if (!s->fclk[i]) {
+ error_report("omap2-gpio: fclk%d not connected", i);
+ return -1;
+ }
+ }
if (s->mpu_model < omap3430) {
- memory_region_init_io(&s->iomem, OBJECT(dev), &omap2_gpif_top_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &omap2_gpif_top_ops, s,
"omap2.gpio", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
}
@@ -731,20 +732,17 @@ static void omap2_gpio_realize(DeviceState *dev, Error **errp)
for (i = 0; i < s->modulecount; i++) {
struct omap2_gpio_s *m = &s->modules[i];
- if (!s->fclk[i]) {
- error_setg(errp, "omap2-gpio: fclk%d not connected", i);
- return;
- }
-
m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
m->handler = &s->handler[i * 32];
sysbus_init_irq(sbd, &m->irq[0]); /* mpu irq */
sysbus_init_irq(sbd, &m->irq[1]); /* dsp irq */
sysbus_init_irq(sbd, &m->wkup);
- memory_region_init_io(&m->iomem, OBJECT(dev), &omap2_gpio_module_ops, m,
+ memory_region_init_io(&m->iomem, OBJECT(s), &omap2_gpio_module_ops, m,
"omap.gpio-module", 0x1000);
sysbus_init_mmio(sbd, &m->iomem);
}
+
+ return 0;
}
/* Using qdev pointer properties for the clocks is not ideal.
@@ -768,8 +766,9 @@ static Property omap_gpio_properties[] = {
static void omap_gpio_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- dc->realize = omap_gpio_realize;
+ k->init = omap_gpio_init;
dc->reset = omap_gpif_reset;
dc->props = omap_gpio_properties;
/* Reason: pointer property "clk" */
@@ -780,7 +779,6 @@ static const TypeInfo omap_gpio_info = {
.name = TYPE_OMAP1_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct omap_gpif_s),
- .instance_init = omap_gpio_init,
.class_init = omap_gpio_class_init,
};
@@ -799,8 +797,9 @@ static Property omap2_gpio_properties[] = {
static void omap2_gpio_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- dc->realize = omap2_gpio_realize;
+ k->init = omap2_gpio_init;
dc->reset = omap2_gpif_reset;
dc->props = omap2_gpio_properties;
/* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index 4ae2aa156..29dc7fc38 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -10,7 +10,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
-#include "qemu/log.h"
//#define DEBUG_PL061 1
@@ -341,6 +340,20 @@ static const MemoryRegionOps pl061_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
+static int pl061_initfn(SysBusDevice *sbd)
+{
+ DeviceState *dev = DEVICE(sbd);
+ PL061State *s = PL061(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &pl061_ops, s, "pl061", 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+ qdev_init_gpio_in(dev, pl061_set_irq, 8);
+ qdev_init_gpio_out(dev, s->out, 8);
+
+ return 0;
+}
+
static void pl061_luminary_init(Object *obj)
{
PL061State *s = PL061(obj);
@@ -352,23 +365,17 @@ static void pl061_luminary_init(Object *obj)
static void pl061_init(Object *obj)
{
PL061State *s = PL061(obj);
- DeviceState *dev = DEVICE(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
s->id = pl061_id;
s->rsvd_start = 0x424;
-
- memory_region_init_io(&s->iomem, obj, &pl061_ops, s, "pl061", 0x1000);
- sysbus_init_mmio(sbd, &s->iomem);
- sysbus_init_irq(sbd, &s->irq);
- qdev_init_gpio_in(dev, pl061_set_irq, 8);
- qdev_init_gpio_out(dev, s->out, 8);
}
static void pl061_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = pl061_initfn;
dc->vmsd = &vmstate_pl061;
dc->reset = &pl061_reset;
}
diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index 15865e108..555da281c 100644
--- a/hw/gpio/zaurus.c
+++ b/hw/gpio/zaurus.c
@@ -167,18 +167,19 @@ static void scoop_gpio_set(void *opaque, int line, int level)
s->gpio_level &= ~(1 << line);
}
-static void scoop_init(Object *obj)
+static int scoop_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- ScoopInfo *s = SCOOP(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ ScoopInfo *s = SCOOP(dev);
s->status = 0x02;
qdev_init_gpio_out(dev, s->handler, 16);
qdev_init_gpio_in(dev, scoop_gpio_set, 16);
- memory_region_init_io(&s->iomem, obj, &scoop_ops, s, "scoop", 0x1000);
+ memory_region_init_io(&s->iomem, OBJECT(s), &scoop_ops, s, "scoop", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
+
+ return 0;
}
static int scoop_post_load(void *opaque, int version_id)
@@ -238,7 +239,9 @@ static const VMStateDescription vmstate_scoop_regs = {
static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = scoop_init;
dc->desc = "Scoop2 Sharp custom ASIC";
dc->vmsd = &vmstate_scoop_regs;
}
@@ -247,7 +250,6 @@ static const TypeInfo scoop_sysbus_info = {
.name = TYPE_SCOOP,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ScoopInfo),
- .instance_init = scoop_init,
.class_init = scoop_sysbus_class_init,
};
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index a081b8ef2..aeb8f38d7 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -1,10 +1,8 @@
common-obj-y += core.o smbus.o smbus_eeprom.o
-common-obj-$(CONFIG_DDC) += i2c-ddc.o
common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o
common-obj-$(CONFIG_APM) += pm_smbus.o
common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o
common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
-common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
obj-$(CONFIG_OMAP) += omap_i2c.o
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
deleted file mode 100644
index ce5b1f0fa..000000000
--- a/hw/i2c/aspeed_i2c.c
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * ARM Aspeed 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "qemu/log.h"
-#include "hw/i2c/aspeed_i2c.h"
-
-/* I2C Global Register */
-
-#define I2C_CTRL_STATUS 0x00 /* Device Interrupt Status */
-#define I2C_CTRL_ASSIGN 0x08 /* Device Interrupt Target
- Assignment */
-
-/* I2C Device (Bus) Register */
-
-#define I2CD_FUN_CTRL_REG 0x00 /* I2CD Function Control */
-#define I2CD_BUFF_SEL_MASK (0x7 << 20)
-#define I2CD_BUFF_SEL(x) (x << 20)
-#define I2CD_M_SDA_LOCK_EN (0x1 << 16)
-#define I2CD_MULTI_MASTER_DIS (0x1 << 15)
-#define I2CD_M_SCL_DRIVE_EN (0x1 << 14)
-#define I2CD_MSB_STS (0x1 << 9)
-#define I2CD_SDA_DRIVE_1T_EN (0x1 << 8)
-#define I2CD_M_SDA_DRIVE_1T_EN (0x1 << 7)
-#define I2CD_M_HIGH_SPEED_EN (0x1 << 6)
-#define I2CD_DEF_ADDR_EN (0x1 << 5)
-#define I2CD_DEF_ALERT_EN (0x1 << 4)
-#define I2CD_DEF_ARP_EN (0x1 << 3)
-#define I2CD_DEF_GCALL_EN (0x1 << 2)
-#define I2CD_SLAVE_EN (0x1 << 1)
-#define I2CD_MASTER_EN (0x1)
-
-#define I2CD_AC_TIMING_REG1 0x04 /* Clock and AC Timing Control #1 */
-#define I2CD_AC_TIMING_REG2 0x08 /* Clock and AC Timing Control #1 */
-#define I2CD_INTR_CTRL_REG 0x0c /* I2CD Interrupt Control */
-#define I2CD_INTR_STS_REG 0x10 /* I2CD Interrupt Status */
-#define I2CD_INTR_SDA_DL_TIMEOUT (0x1 << 14)
-#define I2CD_INTR_BUS_RECOVER_DONE (0x1 << 13)
-#define I2CD_INTR_SMBUS_ALERT (0x1 << 12) /* Bus [0-3] only */
-#define I2CD_INTR_SMBUS_ARP_ADDR (0x1 << 11) /* Removed */
-#define I2CD_INTR_SMBUS_DEV_ALERT_ADDR (0x1 << 10) /* Removed */
-#define I2CD_INTR_SMBUS_DEF_ADDR (0x1 << 9) /* Removed */
-#define I2CD_INTR_GCALL_ADDR (0x1 << 8) /* Removed */
-#define I2CD_INTR_SLAVE_MATCH (0x1 << 7) /* use RX_DONE */
-#define I2CD_INTR_SCL_TIMEOUT (0x1 << 6)
-#define I2CD_INTR_ABNORMAL (0x1 << 5)
-#define I2CD_INTR_NORMAL_STOP (0x1 << 4)
-#define I2CD_INTR_ARBIT_LOSS (0x1 << 3)
-#define I2CD_INTR_RX_DONE (0x1 << 2)
-#define I2CD_INTR_TX_NAK (0x1 << 1)
-#define I2CD_INTR_TX_ACK (0x1 << 0)
-
-#define I2CD_CMD_REG 0x14 /* I2CD Command/Status */
-#define I2CD_SDA_OE (0x1 << 28)
-#define I2CD_SDA_O (0x1 << 27)
-#define I2CD_SCL_OE (0x1 << 26)
-#define I2CD_SCL_O (0x1 << 25)
-#define I2CD_TX_TIMING (0x1 << 24)
-#define I2CD_TX_STATUS (0x1 << 23)
-
-#define I2CD_TX_STATE_SHIFT 19 /* Tx State Machine */
-#define I2CD_TX_STATE_MASK 0xf
-#define I2CD_IDLE 0x0
-#define I2CD_MACTIVE 0x8
-#define I2CD_MSTART 0x9
-#define I2CD_MSTARTR 0xa
-#define I2CD_MSTOP 0xb
-#define I2CD_MTXD 0xc
-#define I2CD_MRXACK 0xd
-#define I2CD_MRXD 0xe
-#define I2CD_MTXACK 0xf
-#define I2CD_SWAIT 0x1
-#define I2CD_SRXD 0x4
-#define I2CD_STXACK 0x5
-#define I2CD_STXD 0x6
-#define I2CD_SRXACK 0x7
-#define I2CD_RECOVER 0x3
-
-#define I2CD_SCL_LINE_STS (0x1 << 18)
-#define I2CD_SDA_LINE_STS (0x1 << 17)
-#define I2CD_BUS_BUSY_STS (0x1 << 16)
-#define I2CD_SDA_OE_OUT_DIR (0x1 << 15)
-#define I2CD_SDA_O_OUT_DIR (0x1 << 14)
-#define I2CD_SCL_OE_OUT_DIR (0x1 << 13)
-#define I2CD_SCL_O_OUT_DIR (0x1 << 12)
-#define I2CD_BUS_RECOVER_CMD_EN (0x1 << 11)
-#define I2CD_S_ALT_EN (0x1 << 10)
-#define I2CD_RX_DMA_ENABLE (0x1 << 9)
-#define I2CD_TX_DMA_ENABLE (0x1 << 8)
-
-/* Command Bit */
-#define I2CD_M_STOP_CMD (0x1 << 5)
-#define I2CD_M_S_RX_CMD_LAST (0x1 << 4)
-#define I2CD_M_RX_CMD (0x1 << 3)
-#define I2CD_S_TX_CMD (0x1 << 2)
-#define I2CD_M_TX_CMD (0x1 << 1)
-#define I2CD_M_START_CMD (0x1)
-
-#define I2CD_DEV_ADDR_REG 0x18 /* Slave Device Address */
-#define I2CD_BUF_CTRL_REG 0x1c /* Pool Buffer Control */
-#define I2CD_BYTE_BUF_REG 0x20 /* Transmit/Receive Byte Buffer */
-#define I2CD_BYTE_BUF_TX_SHIFT 0
-#define I2CD_BYTE_BUF_TX_MASK 0xff
-#define I2CD_BYTE_BUF_RX_SHIFT 8
-#define I2CD_BYTE_BUF_RX_MASK 0xff
-
-
-static inline bool aspeed_i2c_bus_is_master(AspeedI2CBus *bus)
-{
- return bus->ctrl & I2CD_MASTER_EN;
-}
-
-static inline bool aspeed_i2c_bus_is_enabled(AspeedI2CBus *bus)
-{
- return bus->ctrl & (I2CD_MASTER_EN | I2CD_SLAVE_EN);
-}
-
-static inline void aspeed_i2c_bus_raise_interrupt(AspeedI2CBus *bus)
-{
- bus->intr_status &= bus->intr_ctrl;
- if (bus->intr_status) {
- bus->controller->intr_status |= 1 << bus->id;
- qemu_irq_raise(bus->controller->irq);
- }
-}
-
-static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- AspeedI2CBus *bus = opaque;
-
- switch (offset) {
- case I2CD_FUN_CTRL_REG:
- return bus->ctrl;
- case I2CD_AC_TIMING_REG1:
- return bus->timing[0];
- case I2CD_AC_TIMING_REG2:
- return bus->timing[1];
- case I2CD_INTR_CTRL_REG:
- return bus->intr_ctrl;
- case I2CD_INTR_STS_REG:
- return bus->intr_status;
- case I2CD_BYTE_BUF_REG:
- return bus->buf;
- case I2CD_CMD_REG:
- return bus->cmd | (i2c_bus_busy(bus->bus) << 16);
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset);
- return -1;
- }
-}
-
-static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
-{
- bus->cmd |= value & 0xFFFF;
- bus->intr_status = 0;
-
- if (bus->cmd & I2CD_M_START_CMD) {
- if (i2c_start_transfer(bus->bus, extract32(bus->buf, 1, 7),
- extract32(bus->buf, 0, 1))) {
- bus->intr_status |= I2CD_INTR_TX_NAK;
- } else {
- bus->intr_status |= I2CD_INTR_TX_ACK;
- }
-
- } else if (bus->cmd & I2CD_M_TX_CMD) {
- if (i2c_send(bus->bus, bus->buf)) {
- bus->intr_status |= (I2CD_INTR_TX_NAK | I2CD_INTR_ABNORMAL);
- i2c_end_transfer(bus->bus);
- } else {
- bus->intr_status |= I2CD_INTR_TX_ACK;
- }
-
- } else if (bus->cmd & I2CD_M_RX_CMD) {
- int ret = i2c_recv(bus->bus);
- if (ret < 0) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: read failed\n", __func__);
- ret = 0xff;
- } else {
- bus->intr_status |= I2CD_INTR_RX_DONE;
- }
- bus->buf = (ret & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
- }
-
- if (bus->cmd & (I2CD_M_STOP_CMD | I2CD_M_S_RX_CMD_LAST)) {
- if (!i2c_bus_busy(bus->bus)) {
- bus->intr_status |= I2CD_INTR_ABNORMAL;
- } else {
- i2c_end_transfer(bus->bus);
- bus->intr_status |= I2CD_INTR_NORMAL_STOP;
- }
- }
-
- /* command is handled, reset it and check for interrupts */
- bus->cmd &= ~0xFFFF;
- aspeed_i2c_bus_raise_interrupt(bus);
-}
-
-static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- AspeedI2CBus *bus = opaque;
-
- switch (offset) {
- case I2CD_FUN_CTRL_REG:
- if (value & I2CD_SLAVE_EN) {
- qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n",
- __func__);
- break;
- }
- bus->ctrl = value & 0x0071C3FF;
- break;
- case I2CD_AC_TIMING_REG1:
- bus->timing[0] = value & 0xFFFFF0F;
- break;
- case I2CD_AC_TIMING_REG2:
- bus->timing[1] = value & 0x7;
- break;
- case I2CD_INTR_CTRL_REG:
- bus->intr_ctrl = value & 0x7FFF;
- break;
- case I2CD_INTR_STS_REG:
- bus->intr_status &= ~(value & 0x7FFF);
- bus->controller->intr_status &= ~(1 << bus->id);
- qemu_irq_lower(bus->controller->irq);
- break;
- case I2CD_DEV_ADDR_REG:
- qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n",
- __func__);
- break;
- case I2CD_BYTE_BUF_REG:
- bus->buf = (value & I2CD_BYTE_BUF_TX_MASK) << I2CD_BYTE_BUF_TX_SHIFT;
- break;
- case I2CD_CMD_REG:
- if (!aspeed_i2c_bus_is_enabled(bus)) {
- break;
- }
-
- if (!aspeed_i2c_bus_is_master(bus)) {
- qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n",
- __func__);
- break;
- }
-
- aspeed_i2c_bus_handle_cmd(bus, value);
- break;
-
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- }
-}
-
-static uint64_t aspeed_i2c_ctrl_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- AspeedI2CState *s = opaque;
-
- switch (offset) {
- case I2C_CTRL_STATUS:
- return s->intr_status;
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- break;
- }
-
- return -1;
-}
-
-static void aspeed_i2c_ctrl_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- switch (offset) {
- case I2C_CTRL_STATUS:
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- break;
- }
-}
-
-static const MemoryRegionOps aspeed_i2c_bus_ops = {
- .read = aspeed_i2c_bus_read,
- .write = aspeed_i2c_bus_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static const MemoryRegionOps aspeed_i2c_ctrl_ops = {
- .read = aspeed_i2c_ctrl_read,
- .write = aspeed_i2c_ctrl_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static const VMStateDescription aspeed_i2c_bus_vmstate = {
- .name = TYPE_ASPEED_I2C,
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(id, AspeedI2CBus),
- VMSTATE_UINT32(ctrl, AspeedI2CBus),
- VMSTATE_UINT32_ARRAY(timing, AspeedI2CBus, 2),
- VMSTATE_UINT32(intr_ctrl, AspeedI2CBus),
- VMSTATE_UINT32(intr_status, AspeedI2CBus),
- VMSTATE_UINT32(cmd, AspeedI2CBus),
- VMSTATE_UINT32(buf, AspeedI2CBus),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription aspeed_i2c_vmstate = {
- .name = TYPE_ASPEED_I2C,
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(intr_status, AspeedI2CState),
- VMSTATE_STRUCT_ARRAY(busses, AspeedI2CState,
- ASPEED_I2C_NR_BUSSES, 1, aspeed_i2c_bus_vmstate,
- AspeedI2CBus),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void aspeed_i2c_reset(DeviceState *dev)
-{
- int i;
- AspeedI2CState *s = ASPEED_I2C(dev);
-
- s->intr_status = 0;
-
- for (i = 0; i < ASPEED_I2C_NR_BUSSES; i++) {
- s->busses[i].intr_ctrl = 0;
- s->busses[i].intr_status = 0;
- s->busses[i].cmd = 0;
- s->busses[i].buf = 0;
- i2c_end_transfer(s->busses[i].bus);
- }
-}
-
-/*
- * Address Definitions
- *
- * 0x000 ... 0x03F: Global Register
- * 0x040 ... 0x07F: Device 1
- * 0x080 ... 0x0BF: Device 2
- * 0x0C0 ... 0x0FF: Device 3
- * 0x100 ... 0x13F: Device 4
- * 0x140 ... 0x17F: Device 5
- * 0x180 ... 0x1BF: Device 6
- * 0x1C0 ... 0x1FF: Device 7
- * 0x200 ... 0x2FF: Buffer Pool (unused in linux driver)
- * 0x300 ... 0x33F: Device 8
- * 0x340 ... 0x37F: Device 9
- * 0x380 ... 0x3BF: Device 10
- * 0x3C0 ... 0x3FF: Device 11
- * 0x400 ... 0x43F: Device 12
- * 0x440 ... 0x47F: Device 13
- * 0x480 ... 0x4BF: Device 14
- * 0x800 ... 0xFFF: Buffer Pool (unused in linux driver)
- */
-static void aspeed_i2c_realize(DeviceState *dev, Error **errp)
-{
- int i;
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- AspeedI2CState *s = ASPEED_I2C(dev);
-
- sysbus_init_irq(sbd, &s->irq);
- memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_i2c_ctrl_ops, s,
- "aspeed.i2c", 0x1000);
- sysbus_init_mmio(sbd, &s->iomem);
-
- for (i = 0; i < ASPEED_I2C_NR_BUSSES; i++) {
- char name[16];
- int offset = i < 7 ? 1 : 5;
- snprintf(name, sizeof(name), "aspeed.i2c.%d", i);
- s->busses[i].controller = s;
- s->busses[i].id = i;
- s->busses[i].bus = i2c_init_bus(dev, name);
- memory_region_init_io(&s->busses[i].mr, OBJECT(dev),
- &aspeed_i2c_bus_ops, &s->busses[i], name, 0x40);
- memory_region_add_subregion(&s->iomem, 0x40 * (i + offset),
- &s->busses[i].mr);
- }
-}
-
-static void aspeed_i2c_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->vmsd = &aspeed_i2c_vmstate;
- dc->reset = aspeed_i2c_reset;
- dc->realize = aspeed_i2c_realize;
- dc->desc = "Aspeed I2C Controller";
-}
-
-static const TypeInfo aspeed_i2c_info = {
- .name = TYPE_ASPEED_I2C,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(AspeedI2CState),
- .class_init = aspeed_i2c_class_init,
-};
-
-static void aspeed_i2c_register_types(void)
-{
- type_register_static(&aspeed_i2c_info);
-}
-
-type_init(aspeed_i2c_register_types)
-
-
-I2CBus *aspeed_i2c_get_bus(DeviceState *dev, int busnr)
-{
- AspeedI2CState *s = ASPEED_I2C(dev);
- I2CBus *bus = NULL;
-
- if (busnr >= 0 && busnr < ASPEED_I2C_NR_BUSSES) {
- bus = s->busses[busnr].bus;
- }
-
- return bus;
-}
diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c
index d3a29891f..6ed206020 100644
--- a/hw/i2c/bitbang_i2c.c
+++ b/hw/i2c/bitbang_i2c.c
@@ -210,14 +210,13 @@ static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
}
}
-static void gpio_i2c_init(Object *obj)
+static int gpio_i2c_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- GPIOI2CState *s = GPIO_I2C(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ GPIOI2CState *s = GPIO_I2C(dev);
I2CBus *bus;
- memory_region_init(&s->dummy_iomem, obj, "gpio_i2c", 0);
+ memory_region_init(&s->dummy_iomem, OBJECT(s), "gpio_i2c", 0);
sysbus_init_mmio(sbd, &s->dummy_iomem);
bus = i2c_init_bus(dev, "i2c");
@@ -225,12 +224,16 @@ static void gpio_i2c_init(Object *obj)
qdev_init_gpio_in(dev, bitbang_i2c_gpio_set, 2);
qdev_init_gpio_out(dev, &s->out, 1);
+
+ return 0;
}
static void gpio_i2c_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = gpio_i2c_init;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->desc = "Virtual GPIO to I2C bridge";
}
@@ -239,7 +242,6 @@ static const TypeInfo gpio_i2c_info = {
.name = TYPE_GPIO_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(GPIOI2CState),
- .instance_init = gpio_i2c_init,
.class_init = gpio_i2c_class_init,
};
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index 4afbe0bde..ba22104af 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -10,21 +10,12 @@
#include "qemu/osdep.h"
#include "hw/i2c/i2c.h"
-typedef struct I2CNode I2CNode;
-
-struct I2CNode {
- I2CSlave *elt;
- QLIST_ENTRY(I2CNode) next;
-};
-
-#define I2C_BROADCAST 0x00
-
struct I2CBus
{
BusState qbus;
- QLIST_HEAD(, I2CNode) current_devs;
+ I2CSlave *current_dev;
+ I2CSlave *dev;
uint8_t saved_address;
- bool broadcast;
};
static Property i2c_props[] = {
@@ -45,14 +36,17 @@ static void i2c_bus_pre_save(void *opaque)
{
I2CBus *bus = opaque;
- bus->saved_address = -1;
- if (!QLIST_EMPTY(&bus->current_devs)) {
- if (!bus->broadcast) {
- bus->saved_address = QLIST_FIRST(&bus->current_devs)->elt->address;
- } else {
- bus->saved_address = I2C_BROADCAST;
- }
- }
+ bus->saved_address = bus->current_dev ? bus->current_dev->address : -1;
+}
+
+static int i2c_bus_post_load(void *opaque, int version_id)
+{
+ I2CBus *bus = opaque;
+
+ /* The bus is loaded before attached devices, so load and save the
+ current device id. Devices will check themselves as loaded. */
+ bus->current_dev = NULL;
+ return 0;
}
static const VMStateDescription vmstate_i2c_bus = {
@@ -60,6 +54,7 @@ static const VMStateDescription vmstate_i2c_bus = {
.version_id = 1,
.minimum_version_id = 1,
.pre_save = i2c_bus_pre_save,
+ .post_load = i2c_bus_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT8(saved_address, I2CBus),
VMSTATE_END_OF_LIST()
@@ -72,7 +67,6 @@ I2CBus *i2c_init_bus(DeviceState *parent, const char *name)
I2CBus *bus;
bus = I2C_BUS(qbus_create(TYPE_I2C_BUS, parent, name));
- QLIST_INIT(&bus->current_devs);
vmstate_register(NULL, -1, &vmstate_i2c_bus, bus);
return bus;
}
@@ -85,7 +79,7 @@ void i2c_set_slave_address(I2CSlave *dev, uint8_t address)
/* Return nonzero if bus is busy. */
int i2c_bus_busy(I2CBus *bus)
{
- return !QLIST_EMPTY(&bus->current_devs);
+ return bus->current_dev != NULL;
}
/* Returns non-zero if the address is not valid. */
@@ -93,127 +87,95 @@ int i2c_bus_busy(I2CBus *bus)
int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv)
{
BusChild *kid;
+ I2CSlave *slave = NULL;
I2CSlaveClass *sc;
- I2CNode *node;
-
- if (address == I2C_BROADCAST) {
- /*
- * This is a broadcast, the current_devs will be all the devices of the
- * bus.
- */
- bus->broadcast = true;
- }
QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
DeviceState *qdev = kid->child;
I2CSlave *candidate = I2C_SLAVE(qdev);
- if ((candidate->address == address) || (bus->broadcast)) {
- node = g_malloc(sizeof(struct I2CNode));
- node->elt = candidate;
- QLIST_INSERT_HEAD(&bus->current_devs, node, next);
- if (!bus->broadcast) {
- break;
- }
+ if (candidate->address == address) {
+ slave = candidate;
+ break;
}
}
- if (QLIST_EMPTY(&bus->current_devs)) {
+ if (!slave) {
return 1;
}
- QLIST_FOREACH(node, &bus->current_devs, next) {
- sc = I2C_SLAVE_GET_CLASS(node->elt);
- /* If the bus is already busy, assume this is a repeated
- start condition. */
- if (sc->event) {
- sc->event(node->elt, recv ? I2C_START_RECV : I2C_START_SEND);
- }
+ sc = I2C_SLAVE_GET_CLASS(slave);
+ /* If the bus is already busy, assume this is a repeated
+ start condition. */
+ bus->current_dev = slave;
+ if (sc->event) {
+ sc->event(slave, recv ? I2C_START_RECV : I2C_START_SEND);
}
return 0;
}
void i2c_end_transfer(I2CBus *bus)
{
+ I2CSlave *dev = bus->current_dev;
I2CSlaveClass *sc;
- I2CNode *node, *next;
- if (QLIST_EMPTY(&bus->current_devs)) {
+ if (!dev) {
return;
}
- QLIST_FOREACH_SAFE(node, &bus->current_devs, next, next) {
- sc = I2C_SLAVE_GET_CLASS(node->elt);
- if (sc->event) {
- sc->event(node->elt, I2C_FINISH);
- }
- QLIST_REMOVE(node, next);
- g_free(node);
+ sc = I2C_SLAVE_GET_CLASS(dev);
+ if (sc->event) {
+ sc->event(dev, I2C_FINISH);
}
- bus->broadcast = false;
+
+ bus->current_dev = NULL;
}
-int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
+int i2c_send(I2CBus *bus, uint8_t data)
{
+ I2CSlave *dev = bus->current_dev;
I2CSlaveClass *sc;
- I2CNode *node;
- int ret = 0;
-
- if (send) {
- QLIST_FOREACH(node, &bus->current_devs, next) {
- sc = I2C_SLAVE_GET_CLASS(node->elt);
- if (sc->send) {
- ret = ret || sc->send(node->elt, *data);
- } else {
- ret = -1;
- }
- }
- return ret ? -1 : 0;
- } else {
- if ((QLIST_EMPTY(&bus->current_devs)) || (bus->broadcast)) {
- return -1;
- }
- sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
- if (sc->recv) {
- ret = sc->recv(QLIST_FIRST(&bus->current_devs)->elt);
- if (ret < 0) {
- return ret;
- } else {
- *data = ret;
- return 0;
- }
- }
+ if (!dev) {
return -1;
}
-}
-int i2c_send(I2CBus *bus, uint8_t data)
-{
- return i2c_send_recv(bus, &data, true);
+ sc = I2C_SLAVE_GET_CLASS(dev);
+ if (sc->send) {
+ return sc->send(dev, data);
+ }
+
+ return -1;
}
int i2c_recv(I2CBus *bus)
{
- uint8_t data;
- int ret = i2c_send_recv(bus, &data, false);
+ I2CSlave *dev = bus->current_dev;
+ I2CSlaveClass *sc;
+
+ if (!dev) {
+ return -1;
+ }
- return ret < 0 ? ret : data;
+ sc = I2C_SLAVE_GET_CLASS(dev);
+ if (sc->recv) {
+ return sc->recv(dev);
+ }
+
+ return -1;
}
void i2c_nack(I2CBus *bus)
{
+ I2CSlave *dev = bus->current_dev;
I2CSlaveClass *sc;
- I2CNode *node;
- if (QLIST_EMPTY(&bus->current_devs)) {
+ if (!dev) {
return;
}
- QLIST_FOREACH(node, &bus->current_devs, next) {
- sc = I2C_SLAVE_GET_CLASS(node->elt);
- if (sc->event) {
- sc->event(node->elt, I2C_NACK);
- }
+ sc = I2C_SLAVE_GET_CLASS(dev);
+ if (sc->event) {
+ sc->event(dev, I2C_NACK);
}
}
@@ -221,14 +183,9 @@ static int i2c_slave_post_load(void *opaque, int version_id)
{
I2CSlave *dev = opaque;
I2CBus *bus;
- I2CNode *node;
-
bus = I2C_BUS(qdev_get_parent_bus(DEVICE(dev)));
- if ((bus->saved_address == dev->address) ||
- (bus->saved_address == I2C_BROADCAST)) {
- node = g_malloc(sizeof(struct I2CNode));
- node->elt = dev;
- QLIST_INSERT_HEAD(&bus->current_devs, node, next);
+ if (bus->saved_address == dev->address) {
+ bus->current_dev = dev;
}
return 0;
}
diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c
index c96fa7d7b..8c2a2c163 100644
--- a/hw/i2c/exynos4210_i2c.c
+++ b/hw/i2c/exynos4210_i2c.c
@@ -299,32 +299,33 @@ static void exynos4210_i2c_reset(DeviceState *d)
s->scl_free = true;
}
-static void exynos4210_i2c_init(Object *obj)
+static int exynos4210_i2c_realize(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- Exynos4210I2CState *s = EXYNOS4_I2C(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ Exynos4210I2CState *s = EXYNOS4_I2C(dev);
- memory_region_init_io(&s->iomem, obj, &exynos4210_i2c_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_i2c_ops, s,
TYPE_EXYNOS4_I2C, EXYNOS4_I2C_MEM_SIZE);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
s->bus = i2c_init_bus(dev, "i2c");
+ return 0;
}
static void exynos4210_i2c_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sbdc = SYS_BUS_DEVICE_CLASS(klass);
dc->vmsd = &exynos4210_i2c_vmstate;
dc->reset = exynos4210_i2c_reset;
+ sbdc->init = exynos4210_i2c_realize;
}
static const TypeInfo exynos4210_i2c_type_info = {
.name = TYPE_EXYNOS4_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210I2CState),
- .instance_init = exynos4210_i2c_init,
.class_init = exynos4210_i2c_class_init,
};
diff --git a/hw/i2c/i2c-ddc.c b/hw/i2c/i2c-ddc.c
deleted file mode 100644
index 122721293..000000000
--- a/hw/i2c/i2c-ddc.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/* 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/>.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "hw/i2c/i2c.h"
-#include "hw/i2c/i2c-ddc.h"
-
-#ifndef DEBUG_I2CDDC
-#define DEBUG_I2CDDC 0
-#endif
-
-#define DPRINTF(fmt, ...) do { \
- if (DEBUG_I2CDDC) { \
- qemu_log("i2c-ddc: " fmt , ## __VA_ARGS__); \
- } \
-} while (0);
-
-/* Structure defining a monitor's characteristics in a
- * readable format: this should be passed to build_edid_blob()
- * to convert it into the 128 byte binary EDID blob.
- * Not all bits of the EDID are customisable here.
- */
-struct EDIDData {
- char manuf_id[3]; /* three upper case letters */
- uint16_t product_id;
- uint32_t serial_no;
- uint8_t manuf_week;
- int manuf_year;
- uint8_t h_cm;
- uint8_t v_cm;
- uint8_t gamma;
- char monitor_name[14];
- char serial_no_string[14];
- /* Range limits */
- uint8_t vmin; /* Hz */
- uint8_t vmax; /* Hz */
- uint8_t hmin; /* kHz */
- uint8_t hmax; /* kHz */
- uint8_t pixclock; /* MHz / 10 */
- uint8_t timing_data[18];
-};
-
-typedef struct EDIDData EDIDData;
-
-/* EDID data for a simple LCD monitor */
-static const EDIDData lcd_edid = {
- /* The manuf_id ought really to be an assigned EISA ID */
- .manuf_id = "QMU",
- .product_id = 0,
- .serial_no = 1,
- .manuf_week = 1,
- .manuf_year = 2011,
- .h_cm = 40,
- .v_cm = 30,
- .gamma = 0x78,
- .monitor_name = "QEMU monitor",
- .serial_no_string = "1",
- .vmin = 40,
- .vmax = 120,
- .hmin = 30,
- .hmax = 100,
- .pixclock = 18,
- .timing_data = {
- /* Borrowed from a 21" LCD */
- 0x48, 0x3f, 0x40, 0x30, 0x62, 0xb0, 0x32, 0x40, 0x40,
- 0xc0, 0x13, 0x00, 0x98, 0x32, 0x11, 0x00, 0x00, 0x1e
- }
-};
-
-static uint8_t manuf_char_to_int(char c)
-{
- return (c - 'A') & 0x1f;
-}
-
-static void write_ascii_descriptor_block(uint8_t *descblob, uint8_t blocktype,
- const char *string)
-{
- /* Write an EDID Descriptor Block of the "ascii string" type */
- int i;
- descblob[0] = descblob[1] = descblob[2] = descblob[4] = 0;
- descblob[3] = blocktype;
- /* The rest is 13 bytes of ASCII; if less then the rest must
- * be filled with newline then spaces
- */
- for (i = 5; i < 19; i++) {
- descblob[i] = string[i - 5];
- if (!descblob[i]) {
- break;
- }
- }
- if (i < 19) {
- descblob[i++] = '\n';
- }
- for ( ; i < 19; i++) {
- descblob[i] = ' ';
- }
-}
-
-static void write_range_limits_descriptor(const EDIDData *edid,
- uint8_t *descblob)
-{
- int i;
- descblob[0] = descblob[1] = descblob[2] = descblob[4] = 0;
- descblob[3] = 0xfd;
- descblob[5] = edid->vmin;
- descblob[6] = edid->vmax;
- descblob[7] = edid->hmin;
- descblob[8] = edid->hmax;
- descblob[9] = edid->pixclock;
- descblob[10] = 0;
- descblob[11] = 0xa;
- for (i = 12; i < 19; i++) {
- descblob[i] = 0x20;
- }
-}
-
-static void build_edid_blob(const EDIDData *edid, uint8_t *blob)
-{
- /* Write an EDID 1.3 format blob (128 bytes) based
- * on the EDIDData structure.
- */
- int i;
- uint8_t cksum;
-
- /* 00-07 : header */
- blob[0] = blob[7] = 0;
- for (i = 1 ; i < 7; i++) {
- blob[i] = 0xff;
- }
- /* 08-09 : manufacturer ID */
- blob[8] = (manuf_char_to_int(edid->manuf_id[0]) << 2)
- | (manuf_char_to_int(edid->manuf_id[1]) >> 3);
- blob[9] = (manuf_char_to_int(edid->manuf_id[1]) << 5)
- | manuf_char_to_int(edid->manuf_id[2]);
- /* 10-11 : product ID code */
- blob[10] = edid->product_id;
- blob[11] = edid->product_id >> 8;
- blob[12] = edid->serial_no;
- blob[13] = edid->serial_no >> 8;
- blob[14] = edid->serial_no >> 16;
- blob[15] = edid->serial_no >> 24;
- /* 16 : week of manufacture */
- blob[16] = edid->manuf_week;
- /* 17 : year of manufacture - 1990 */
- blob[17] = edid->manuf_year - 1990;
- /* 18, 19 : EDID version and revision */
- blob[18] = 1;
- blob[19] = 3;
- /* 20 - 24 : basic display parameters */
- /* We are always a digital display */
- blob[20] = 0x80;
- /* 21, 22 : max h/v size in cm */
- blob[21] = edid->h_cm;
- blob[22] = edid->v_cm;
- /* 23 : gamma (divide by 100 then add 1 for actual value) */
- blob[23] = edid->gamma;
- /* 24 feature support: no power management, RGB, preferred timing mode,
- * standard colour space
- */
- blob[24] = 0x0e;
- /* 25 - 34 : chromaticity coordinates. These are the
- * standard sRGB chromaticity values
- */
- blob[25] = 0xee;
- blob[26] = 0x91;
- blob[27] = 0xa3;
- blob[28] = 0x54;
- blob[29] = 0x4c;
- blob[30] = 0x99;
- blob[31] = 0x26;
- blob[32] = 0x0f;
- blob[33] = 0x50;
- blob[34] = 0x54;
- /* 35, 36 : Established timings: claim to support everything */
- blob[35] = blob[36] = 0xff;
- /* 37 : manufacturer's reserved timing: none */
- blob[37] = 0;
- /* 38 - 53 : standard timing identification
- * don't claim anything beyond what the 'established timings'
- * already provide. Unused slots must be (0x1, 0x1)
- */
- for (i = 38; i < 54; i++) {
- blob[i] = 0x1;
- }
- /* 54 - 71 : descriptor block 1 : must be preferred timing data */
- memcpy(blob + 54, edid->timing_data, 18);
- /* 72 - 89, 90 - 107, 108 - 125 : descriptor block 2, 3, 4
- * Order not important, but we must have a monitor name and a
- * range limits descriptor.
- */
- write_range_limits_descriptor(edid, blob + 72);
- write_ascii_descriptor_block(blob + 90, 0xfc, edid->monitor_name);
- write_ascii_descriptor_block(blob + 108, 0xff, edid->serial_no_string);
-
- /* 126 : extension flag */
- blob[126] = 0;
-
- cksum = 0;
- for (i = 0; i < 127; i++) {
- cksum += blob[i];
- }
- /* 127 : checksum */
- blob[127] = -cksum;
- if (DEBUG_I2CDDC) {
- qemu_hexdump((char *)blob, stdout, "", 128);
- }
-}
-
-static void i2c_ddc_reset(DeviceState *ds)
-{
- I2CDDCState *s = I2CDDC(ds);
-
- s->firstbyte = false;
- s->reg = 0;
-}
-
-static void i2c_ddc_event(I2CSlave *i2c, enum i2c_event event)
-{
- I2CDDCState *s = I2CDDC(i2c);
-
- if (event == I2C_START_SEND) {
- s->firstbyte = true;
- }
-}
-
-static int i2c_ddc_rx(I2CSlave *i2c)
-{
- I2CDDCState *s = I2CDDC(i2c);
-
- int value;
- value = s->edid_blob[s->reg];
- s->reg++;
- return value;
-}
-
-static int i2c_ddc_tx(I2CSlave *i2c, uint8_t data)
-{
- I2CDDCState *s = I2CDDC(i2c);
- if (s->firstbyte) {
- s->reg = data;
- s->firstbyte = false;
- DPRINTF("[EDID] Written new pointer: %u\n", data);
- return 1;
- }
-
- /* Ignore all writes */
- s->reg++;
- return 1;
-}
-
-static void i2c_ddc_init(Object *obj)
-{
- I2CDDCState *s = I2CDDC(obj);
- build_edid_blob(&lcd_edid, s->edid_blob);
-}
-
-static const VMStateDescription vmstate_i2c_ddc = {
- .name = TYPE_I2CDDC,
- .version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_BOOL(firstbyte, I2CDDCState),
- VMSTATE_UINT8(reg, I2CDDCState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void i2c_ddc_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
-
- dc->reset = i2c_ddc_reset;
- dc->vmsd = &vmstate_i2c_ddc;
- isc->event = i2c_ddc_event;
- isc->recv = i2c_ddc_rx;
- isc->send = i2c_ddc_tx;
-}
-
-static TypeInfo i2c_ddc_info = {
- .name = TYPE_I2CDDC,
- .parent = TYPE_I2C_SLAVE,
- .instance_size = sizeof(I2CDDCState),
- .instance_init = i2c_ddc_init,
- .class_init = i2c_ddc_class_init
-};
-
-static void ddc_register_devices(void)
-{
- type_register_static(&i2c_ddc_info);
-}
-
-type_init(ddc_register_devices);
diff --git a/hw/i2c/imx_i2c.c b/hw/i2c/imx_i2c.c
index 37e5a62ce..e19d4fa74 100644
--- a/hw/i2c/imx_i2c.c
+++ b/hw/i2c/imx_i2c.c
@@ -21,7 +21,6 @@
#include "qemu/osdep.h"
#include "hw/i2c/imx_i2c.h"
#include "hw/i2c/i2c.h"
-#include "qemu/log.h"
#ifndef DEBUG_IMX_I2C
#define DEBUG_IMX_I2C 0
diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c
index f7c92ea00..67fbbff8e 100644
--- a/hw/i2c/omap_i2c.c
+++ b/hw/i2c/omap_i2c.c
@@ -22,7 +22,6 @@
#include "hw/arm/omap.h"
#include "hw/sysbus.h"
#include "qemu/error-report.h"
-#include "qapi/error.h"
#define TYPE_OMAP_I2C "omap_i2c"
#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
@@ -446,35 +445,29 @@ static const MemoryRegionOps omap_i2c_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void omap_i2c_init(Object *obj)
-{
- DeviceState *dev = DEVICE(obj);
- OMAPI2CState *s = OMAP_I2C(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-
- sysbus_init_irq(sbd, &s->irq);
- sysbus_init_irq(sbd, &s->drq[0]);
- sysbus_init_irq(sbd, &s->drq[1]);
- sysbus_init_mmio(sbd, &s->iomem);
- s->bus = i2c_init_bus(dev, NULL);
-}
-
-static void omap_i2c_realize(DeviceState *dev, Error **errp)
+static int omap_i2c_init(SysBusDevice *sbd)
{
+ DeviceState *dev = DEVICE(sbd);
OMAPI2CState *s = OMAP_I2C(dev);
- memory_region_init_io(&s->iomem, OBJECT(dev), &omap_i2c_ops, s, "omap.i2c",
- (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
-
if (!s->fclk) {
- error_setg(errp, "omap_i2c: fclk not connected");
- return;
+ error_report("omap_i2c: fclk not connected");
+ return -1;
}
if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
/* Note that OMAP1 doesn't have a separate interface clock */
- error_setg(errp, "omap_i2c: iclk not connected");
- return;
+ error_report("omap_i2c: iclk not connected");
+ return -1;
}
+
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_irq(sbd, &s->drq[0]);
+ sysbus_init_irq(sbd, &s->drq[1]);
+ memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c",
+ (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ s->bus = i2c_init_bus(dev, NULL);
+ return 0;
}
static Property omap_i2c_properties[] = {
@@ -487,19 +480,18 @@ static Property omap_i2c_properties[] = {
static void omap_i2c_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
-
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = omap_i2c_init;
dc->props = omap_i2c_properties;
dc->reset = omap_i2c_reset;
/* Reason: pointer properties "iclk", "fclk" */
dc->cannot_instantiate_with_device_add_yet = true;
- dc->realize = omap_i2c_realize;
}
static const TypeInfo omap_i2c_info = {
.name = TYPE_OMAP_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(OMAPI2CState),
- .instance_init = omap_i2c_init,
.class_init = omap_i2c_class_init,
};
diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c
index 48fab2262..498f03e83 100644
--- a/hw/i2c/smbus_ich9.c
+++ b/hw/i2c/smbus_ich9.c
@@ -35,6 +35,7 @@
#include "hw/i386/ich9.h"
+#define TYPE_ICH9_SMB_DEVICE "ICH9 SMB"
#define ICH9_SMB_DEVICE(obj) \
OBJECT_CHECK(ICH9SMBState, (obj), TYPE_ICH9_SMB_DEVICE)
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
index da9f298ee..fee3bc761 100644
--- a/hw/i2c/versatile_i2c.c
+++ b/hw/i2c/versatile_i2c.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "bitbang_i2c.h"
-#include "qemu/log.h"
#define TYPE_VERSATILE_I2C "versatile_i2c"
#define VERSATILE_I2C(obj) \
@@ -79,25 +78,32 @@ static const MemoryRegionOps versatile_i2c_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void versatile_i2c_init(Object *obj)
+static int versatile_i2c_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- VersatileI2CState *s = VERSATILE_I2C(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ VersatileI2CState *s = VERSATILE_I2C(dev);
I2CBus *bus;
bus = i2c_init_bus(dev, "i2c");
s->bitbang = bitbang_i2c_init(bus);
- memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &versatile_i2c_ops, s,
"versatile_i2c", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
+ return 0;
+}
+
+static void versatile_i2c_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = versatile_i2c_init;
}
static const TypeInfo versatile_i2c_info = {
.name = TYPE_VERSATILE_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(VersatileI2CState),
- .instance_init = versatile_i2c_init,
+ .class_init = versatile_i2c_class_init,
};
static void versatile_i2c_register_types(void)
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 90e94ffef..b52d5b875 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -2,7 +2,7 @@ obj-$(CONFIG_KVM) += kvm/
obj-y += multiboot.o
obj-y += pc.o pc_piix.o pc_q35.o
obj-y += pc_sysfw.o
-obj-y += x86-iommu.o intel_iommu.o
+obj-y += intel_iommu.o
obj-$(CONFIG_XEN) += ../xenpv/ xen/
obj-y += kvmvapic.o
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index a26a4bb03..64770034f 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -23,6 +23,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "acpi-build.h"
+#include <glib.h>
#include "qemu-common.h"
#include "qemu/bitmap.h"
#include "qemu/error-report.h"
@@ -33,7 +34,6 @@
#include "hw/timer/hpet.h"
#include "hw/acpi/acpi-defs.h"
#include "hw/acpi/acpi.h"
-#include "hw/acpi/cpu.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/acpi/bios-linker-loader.h"
#include "hw/loader.h"
@@ -44,7 +44,6 @@
#include "hw/acpi/tpm.h"
#include "sysemu/tpm_backend.h"
#include "hw/timer/mc146818rtc_regs.h"
-#include "sysemu/numa.h"
/* Supported chipsets: */
#include "hw/acpi/piix4.h"
@@ -52,16 +51,13 @@
#include "hw/i386/ich9.h"
#include "hw/pci/pci_bus.h"
#include "hw/pci-host/q35.h"
-#include "hw/i386/x86-iommu.h"
+#include "hw/i386/intel_iommu.h"
#include "hw/timer/hpet.h"
#include "hw/acpi/aml-build.h"
#include "qapi/qmp/qint.h"
#include "qom/qom-qobject.h"
-#include "hw/i386/x86-iommu.h"
-
-#include "hw/acpi/ipmi.h"
/* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
* -M pc-i440fx-2.0. Even if the actual amount of AML generated grows
@@ -81,9 +77,6 @@
#define ACPI_BUILD_DPRINTF(fmt, ...)
#endif
-/* Default IOAPIC ID */
-#define ACPI_BUILD_IOAPIC_ID 0x0
-
typedef struct AcpiMcfgInfo {
uint64_t mcfg_base;
uint32_t mcfg_size;
@@ -101,6 +94,7 @@ typedef struct AcpiPmInfo {
uint32_t gpe0_blk_len;
uint32_t io_base;
uint16_t cpu_hp_io_base;
+ uint16_t cpu_hp_io_len;
uint16_t mem_hp_io_base;
uint16_t mem_hp_io_len;
uint16_t pcihp_io_base;
@@ -148,6 +142,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
}
assert(obj);
+ pm->cpu_hp_io_len = ACPI_GPE_PROC_LEN;
pm->mem_hp_io_base = ACPI_MEMORY_HOTPLUG_BASE;
pm->mem_hp_io_len = ACPI_MEMORY_HOTPLUG_IO_LEN;
@@ -233,27 +228,26 @@ static Object *acpi_get_i386_pci_host(void)
return OBJECT(host);
}
-static void acpi_get_pci_holes(Range *hole, Range *hole64)
+static void acpi_get_pci_info(PcPciInfo *info)
{
Object *pci_host;
+
pci_host = acpi_get_i386_pci_host();
g_assert(pci_host);
- range_set_bounds1(hole,
- object_property_get_int(pci_host,
+ info->w32.begin = object_property_get_int(pci_host,
PCI_HOST_PROP_PCI_HOLE_START,
- NULL),
- object_property_get_int(pci_host,
- PCI_HOST_PROP_PCI_HOLE_END,
- NULL));
- range_set_bounds1(hole64,
- object_property_get_int(pci_host,
+ NULL);
+ info->w32.end = object_property_get_int(pci_host,
+ PCI_HOST_PROP_PCI_HOLE_END,
+ NULL);
+ info->w64.begin = object_property_get_int(pci_host,
PCI_HOST_PROP_PCI_HOLE64_START,
- NULL),
- object_property_get_int(pci_host,
- PCI_HOST_PROP_PCI_HOLE64_END,
- NULL));
+ NULL);
+ info->w64.end = object_property_get_int(pci_host,
+ PCI_HOST_PROP_PCI_HOLE64_END,
+ NULL);
}
#define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT */
@@ -268,7 +262,7 @@ static void acpi_align_size(GArray *blob, unsigned align)
/* FACS */
static void
-build_facs(GArray *table_data, BIOSLinker *linker)
+build_facs(GArray *table_data, GArray *linker)
{
AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
memcpy(&facs->signature, "FACS", 4);
@@ -313,61 +307,38 @@ static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm)
/* FADT */
static void
-build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm,
- unsigned facs_tbl_offset, unsigned dsdt_tbl_offset,
+build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
+ unsigned facs, unsigned dsdt,
const char *oem_id, const char *oem_table_id)
{
AcpiFadtDescriptorRev1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
- unsigned fw_ctrl_offset = (char *)&fadt->firmware_ctrl - table_data->data;
- unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data;
+ fadt->firmware_ctrl = cpu_to_le32(facs);
/* FACS address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_TABLE_FILE, fw_ctrl_offset, sizeof(fadt->firmware_ctrl),
- ACPI_BUILD_TABLE_FILE, facs_tbl_offset);
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+ ACPI_BUILD_TABLE_FILE,
+ table_data, &fadt->firmware_ctrl,
+ sizeof fadt->firmware_ctrl);
+ fadt->dsdt = cpu_to_le32(dsdt);
/* DSDT address to be filled by Guest linker */
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+ ACPI_BUILD_TABLE_FILE,
+ table_data, &fadt->dsdt,
+ sizeof fadt->dsdt);
+
fadt_setup(fadt, pm);
- bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt),
- ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset);
build_header(linker, table_data,
(void *)fadt, "FACP", sizeof(*fadt), 1, oem_id, oem_table_id);
}
-void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
- CPUArchIdList *apic_ids, GArray *entry)
-{
- int apic_id;
- AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic);
-
- apic_id = apic_ids->cpus[uid].arch_id;
- apic->type = ACPI_APIC_PROCESSOR;
- apic->length = sizeof(*apic);
- apic->processor_id = uid;
- apic->local_apic_id = apic_id;
- if (apic_ids->cpus[uid].cpu != NULL) {
- apic->flags = cpu_to_le32(1);
- } else {
- /* ACPI spec says that LAPIC entry for non present
- * CPU may be omitted from MADT or it must be marked
- * as disabled. However omitting non present CPU from
- * MADT breaks hotplug on linux. So possible CPUs
- * should be put in MADT but kept disabled.
- */
- apic->flags = cpu_to_le32(0);
- }
-}
-
static void
-build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
+build_madt(GArray *table_data, GArray *linker, PCMachineState *pcms)
{
MachineClass *mc = MACHINE_GET_CLASS(pcms);
CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(pcms));
int madt_start = table_data->len;
- AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
- AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
AcpiMultipleApicTable *madt;
AcpiMadtIoApic *io_apic;
@@ -380,13 +351,31 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
madt->flags = cpu_to_le32(1);
for (i = 0; i < apic_ids->len; i++) {
- adevc->madt_cpu(adev, i, apic_ids, table_data);
+ AcpiMadtProcessorApic *apic = acpi_data_push(table_data, sizeof *apic);
+ int apic_id = apic_ids->cpus[i].arch_id;
+
+ apic->type = ACPI_APIC_PROCESSOR;
+ apic->length = sizeof(*apic);
+ apic->processor_id = apic_id;
+ apic->local_apic_id = apic_id;
+ if (apic_ids->cpus[i].cpu != NULL) {
+ apic->flags = cpu_to_le32(1);
+ } else {
+ /* ACPI spec says that LAPIC entry for non present
+ * CPU may be omitted from MADT or it must be marked
+ * as disabled. However omitting non present CPU from
+ * MADT breaks hotplug on linux. So possible CPUs
+ * should be put in MADT but kept disabled.
+ */
+ apic->flags = cpu_to_le32(0);
+ }
}
g_free(apic_ids);
io_apic = acpi_data_push(table_data, sizeof *io_apic);
io_apic->type = ACPI_APIC_IO;
io_apic->length = sizeof(*io_apic);
+#define ACPI_BUILD_IOAPIC_ID 0x0
io_apic->io_apic_id = ACPI_BUILD_IOAPIC_ID;
io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
io_apic->interrupt = cpu_to_le32(0);
@@ -600,10 +589,6 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
QLIST_FOREACH(sec, &bus->child, sibling) {
int32_t devfn = sec->parent_dev->devfn;
- if (pci_bus_is_root(sec) || pci_bus_is_express(sec)) {
- continue;
- }
-
aml_append(method, aml_name("^S%.02X.PCNT", devfn));
}
}
@@ -751,27 +736,6 @@ static void crs_range_free(gpointer data)
g_free(entry);
}
-typedef struct CrsRangeSet {
- GPtrArray *io_ranges;
- GPtrArray *mem_ranges;
- GPtrArray *mem_64bit_ranges;
- } CrsRangeSet;
-
-static void crs_range_set_init(CrsRangeSet *range_set)
-{
- range_set->io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
- range_set->mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
- range_set->mem_64bit_ranges =
- g_ptr_array_new_with_free_func(crs_range_free);
-}
-
-static void crs_range_set_free(CrsRangeSet *range_set)
-{
- g_ptr_array_free(range_set->io_ranges, true);
- g_ptr_array_free(range_set->mem_ranges, true);
- g_ptr_array_free(range_set->mem_64bit_ranges, true);
-}
-
static gint crs_range_compare(gconstpointer a, gconstpointer b)
{
CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
@@ -856,17 +820,18 @@ static void crs_range_merge(GPtrArray *range)
g_ptr_array_free(tmp, true);
}
-static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
+static Aml *build_crs(PCIHostState *host,
+ GPtrArray *io_ranges, GPtrArray *mem_ranges)
{
Aml *crs = aml_resource_template();
- CrsRangeSet temp_range_set;
+ GPtrArray *host_io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
+ GPtrArray *host_mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
CrsRangeEntry *entry;
uint8_t max_bus = pci_bus_num(host->bus);
uint8_t type;
int devfn;
int i;
- crs_range_set_init(&temp_range_set);
for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) {
uint64_t range_base, range_limit;
PCIDevice *dev = host->bus->devices[devfn];
@@ -890,11 +855,9 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
}
if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
- crs_range_insert(temp_range_set.io_ranges,
- range_base, range_limit);
+ crs_range_insert(host_io_ranges, range_base, range_limit);
} else { /* "memory" */
- crs_range_insert(temp_range_set.mem_ranges,
- range_base, range_limit);
+ crs_range_insert(host_mem_ranges, range_base, range_limit);
}
}
@@ -913,8 +876,7 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
* that do not support multiple root buses
*/
if (range_base && range_base <= range_limit) {
- crs_range_insert(temp_range_set.io_ranges,
- range_base, range_limit);
+ crs_range_insert(host_io_ranges, range_base, range_limit);
}
range_base =
@@ -927,14 +889,7 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
* that do not support multiple root buses
*/
if (range_base && range_base <= range_limit) {
- uint64_t length = range_limit - range_base + 1;
- if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
- crs_range_insert(temp_range_set.mem_ranges,
- range_base, range_limit);
- } else {
- crs_range_insert(temp_range_set.mem_64bit_ranges,
- range_base, range_limit);
- }
+ crs_range_insert(host_mem_ranges, range_base, range_limit);
}
range_base =
@@ -947,55 +902,35 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
* that do not support multiple root buses
*/
if (range_base && range_base <= range_limit) {
- uint64_t length = range_limit - range_base + 1;
- if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
- crs_range_insert(temp_range_set.mem_ranges,
- range_base, range_limit);
- } else {
- crs_range_insert(temp_range_set.mem_64bit_ranges,
- range_base, range_limit);
- }
+ crs_range_insert(host_mem_ranges, range_base, range_limit);
}
}
}
- crs_range_merge(temp_range_set.io_ranges);
- for (i = 0; i < temp_range_set.io_ranges->len; i++) {
- entry = g_ptr_array_index(temp_range_set.io_ranges, i);
+ crs_range_merge(host_io_ranges);
+ for (i = 0; i < host_io_ranges->len; i++) {
+ entry = g_ptr_array_index(host_io_ranges, i);
aml_append(crs,
aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
AML_POS_DECODE, AML_ENTIRE_RANGE,
0, entry->base, entry->limit, 0,
entry->limit - entry->base + 1));
- crs_range_insert(range_set->io_ranges, entry->base, entry->limit);
+ crs_range_insert(io_ranges, entry->base, entry->limit);
}
+ g_ptr_array_free(host_io_ranges, true);
- crs_range_merge(temp_range_set.mem_ranges);
- for (i = 0; i < temp_range_set.mem_ranges->len; i++) {
- entry = g_ptr_array_index(temp_range_set.mem_ranges, i);
+ crs_range_merge(host_mem_ranges);
+ for (i = 0; i < host_mem_ranges->len; i++) {
+ entry = g_ptr_array_index(host_mem_ranges, i);
aml_append(crs,
aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
AML_MAX_FIXED, AML_NON_CACHEABLE,
AML_READ_WRITE,
0, entry->base, entry->limit, 0,
entry->limit - entry->base + 1));
- crs_range_insert(range_set->mem_ranges, entry->base, entry->limit);
- }
-
- crs_range_merge(temp_range_set.mem_64bit_ranges);
- for (i = 0; i < temp_range_set.mem_64bit_ranges->len; i++) {
- entry = g_ptr_array_index(temp_range_set.mem_64bit_ranges, i);
- aml_append(crs,
- aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
- AML_MAX_FIXED, AML_NON_CACHEABLE,
- AML_READ_WRITE,
- 0, entry->base, entry->limit, 0,
- entry->limit - entry->base + 1));
- crs_range_insert(range_set->mem_64bit_ranges,
- entry->base, entry->limit);
+ crs_range_insert(mem_ranges, entry->base, entry->limit);
}
-
- crs_range_set_free(&temp_range_set);
+ g_ptr_array_free(host_mem_ranges, true);
aml_append(crs,
aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
@@ -1008,6 +943,114 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
return crs;
}
+static void build_processor_devices(Aml *sb_scope, MachineState *machine,
+ AcpiPmInfo *pm)
+{
+ int i, apic_idx;
+ Aml *dev;
+ Aml *crs;
+ Aml *pkg;
+ Aml *field;
+ Aml *ifctx;
+ Aml *method;
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
+ CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
+ PCMachineState *pcms = PC_MACHINE(machine);
+
+ /* The current AML generator can cover the APIC ID range [0..255],
+ * inclusive, for VCPU hotplug. */
+ QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
+ g_assert(pcms->apic_id_limit <= ACPI_CPU_HOTPLUG_ID_LIMIT);
+
+ /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
+ dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06")));
+ aml_append(dev,
+ aml_name_decl("_UID", aml_string("CPU Hotplug resources"))
+ );
+ /* device present, functioning, decoding, not shown in UI */
+ aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
+ crs = aml_resource_template();
+ aml_append(crs,
+ aml_io(AML_DECODE16, pm->cpu_hp_io_base, pm->cpu_hp_io_base, 1,
+ pm->cpu_hp_io_len)
+ );
+ aml_append(dev, aml_name_decl("_CRS", crs));
+ aml_append(sb_scope, dev);
+ /* declare CPU hotplug MMIO region and PRS field to access it */
+ aml_append(sb_scope, aml_operation_region(
+ "PRST", AML_SYSTEM_IO, aml_int(pm->cpu_hp_io_base), pm->cpu_hp_io_len));
+ field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
+ aml_append(field, aml_named_field("PRS", 256));
+ aml_append(sb_scope, field);
+
+ /* build Processor object for each processor */
+ for (i = 0; i < apic_ids->len; i++) {
+ int apic_id = apic_ids->cpus[i].arch_id;
+
+ assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT);
+
+ dev = aml_processor(apic_id, 0, 0, "CP%.02X", apic_id);
+
+ method = aml_method("_MAT", 0, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_return(aml_call1(CPU_MAT_METHOD, aml_int(apic_id))));
+ aml_append(dev, method);
+
+ method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_return(aml_call1(CPU_STATUS_METHOD, aml_int(apic_id))));
+ aml_append(dev, method);
+
+ method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_return(aml_call2(CPU_EJECT_METHOD, aml_int(apic_id),
+ aml_arg(0)))
+ );
+ aml_append(dev, method);
+
+ aml_append(sb_scope, dev);
+ }
+
+ /* build this code:
+ * Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
+ */
+ /* Arg0 = Processor ID = APIC ID */
+ method = aml_method(AML_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
+ for (i = 0; i < apic_ids->len; i++) {
+ int apic_id = apic_ids->cpus[i].arch_id;
+
+ ifctx = aml_if(aml_equal(aml_arg(0), aml_int(apic_id)));
+ aml_append(ifctx,
+ aml_notify(aml_name("CP%.02X", apic_id), aml_arg(1))
+ );
+ aml_append(method, ifctx);
+ }
+ aml_append(sb_scope, method);
+
+ /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
+ *
+ * Note: The ability to create variable-sized packages was first
+ * introduced in ACPI 2.0. ACPI 1.0 only allowed fixed-size packages
+ * ith up to 255 elements. Windows guests up to win2k8 fail when
+ * VarPackageOp is used.
+ */
+ pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) :
+ aml_varpackage(pcms->apic_id_limit);
+
+ for (i = 0, apic_idx = 0; i < apic_ids->len; i++) {
+ int apic_id = apic_ids->cpus[i].arch_id;
+
+ for (; apic_idx < apic_id; apic_idx++) {
+ aml_append(pkg, aml_int(0));
+ }
+ aml_append(pkg, aml_int(apic_ids->cpus[i].cpu ? 1 : 0));
+ apic_idx = apic_id + 1;
+ }
+ aml_append(sb_scope, aml_name_decl(CPU_ON_BITMAP, pkg));
+ g_free(apic_ids);
+}
+
static void build_memory_devices(Aml *sb_scope, int nr_mem,
uint16_t io_base, uint16_t io_len)
{
@@ -1405,10 +1448,8 @@ static Aml *build_com_device_aml(uint8_t uid)
static void build_isa_devices_aml(Aml *table)
{
ISADevice *fdc = pc_find_fdc0();
- bool ambiguous;
Aml *scope = aml_scope("_SB.PCI0.ISA");
- Object *obj = object_resolve_path_type("", TYPE_ISA_BUS, &ambiguous);
aml_append(scope, build_rtc_device_aml());
aml_append(scope, build_kbd_device_aml());
@@ -1420,14 +1461,6 @@ static void build_isa_devices_aml(Aml *table)
aml_append(scope, build_com_device_aml(1));
aml_append(scope, build_com_device_aml(2));
- if (ambiguous) {
- error_report("Multiple ISA busses, unable to define IPMI ACPI data");
- } else if (!obj) {
- error_report("No ISA bus, unable to define IPMI ACPI data");
- } else {
- build_acpi_ipmi_devices(scope, BUS(obj));
- }
-
aml_append(table, scope);
}
@@ -1946,15 +1979,15 @@ static Aml *build_q35_osc_method(void)
}
static void
-build_dsdt(GArray *table_data, BIOSLinker *linker,
+build_dsdt(GArray *table_data, GArray *linker,
AcpiPmInfo *pm, AcpiMiscInfo *misc,
- Range *pci_hole, Range *pci_hole64, MachineState *machine)
+ PcPciInfo *pci, MachineState *machine)
{
CrsRangeEntry *entry;
Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs;
- CrsRangeSet crs_range_set;
+ GPtrArray *mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
+ GPtrArray *io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
PCMachineState *pcms = PC_MACHINE(machine);
- PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
uint32_t nr_mem = machine->ram_slots;
int root_bus_limit = 0xFF;
PCIBus *bus = NULL;
@@ -2010,15 +2043,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
build_q35_pci0_int(dsdt);
}
- if (pcmc->legacy_cpu_hotplug) {
- build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
- } else {
- CPUHotplugFeatures opts = {
- .apci_1_compatible = true, .has_legacy_cphp = true
- };
- build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base,
- "\\_SB.PCI0", "\\_GPE._E02");
- }
+ build_cpu_hotplug_aml(dsdt);
build_memory_hotplug_aml(dsdt, nr_mem, pm->mem_hp_io_base,
pm->mem_hp_io_len);
@@ -2026,6 +2051,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
{
aml_append(scope, aml_name_decl("_HID", aml_string("ACPI0006")));
+ aml_append(scope, aml_method("_L00", 0, AML_NOTSERIALIZED));
+
if (misc->is_piix4) {
method = aml_method("_E01", 0, AML_NOTSERIALIZED);
aml_append(method,
@@ -2033,15 +2060,33 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
aml_append(method, aml_call0("\\_SB.PCI0.PCNT"));
aml_append(method, aml_release(aml_name("\\_SB.PCI0.BLCK")));
aml_append(scope, method);
+ } else {
+ aml_append(scope, aml_method("_L01", 0, AML_NOTSERIALIZED));
}
+ method = aml_method("_E02", 0, AML_NOTSERIALIZED);
+ aml_append(method, aml_call0("\\_SB." CPU_SCAN_METHOD));
+ aml_append(scope, method);
+
method = aml_method("_E03", 0, AML_NOTSERIALIZED);
aml_append(method, aml_call0(MEMORY_HOTPLUG_HANDLER_PATH));
aml_append(scope, method);
+
+ aml_append(scope, aml_method("_L04", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L05", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L06", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L07", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L08", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L09", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L0A", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L0B", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L0C", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L0D", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L0E", 0, AML_NOTSERIALIZED));
+ aml_append(scope, aml_method("_L0F", 0, AML_NOTSERIALIZED));
}
aml_append(dsdt, scope);
- crs_range_set_init(&crs_range_set);
bus = PC_MACHINE(machine)->bus;
if (bus) {
QLIST_FOREACH(bus, &bus->child, sibling) {
@@ -2068,7 +2113,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
}
aml_append(dev, build_prt(false));
- crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set);
+ crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent),
+ io_ranges, mem_ranges);
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
aml_append(dsdt, scope);
@@ -2089,9 +2135,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
AML_POS_DECODE, AML_ENTIRE_RANGE,
0x0000, 0x0000, 0x0CF7, 0x0000, 0x0CF8));
- crs_replace_with_free_ranges(crs_range_set.io_ranges, 0x0D00, 0xFFFF);
- for (i = 0; i < crs_range_set.io_ranges->len; i++) {
- entry = g_ptr_array_index(crs_range_set.io_ranges, i);
+ crs_replace_with_free_ranges(io_ranges, 0x0D00, 0xFFFF);
+ for (i = 0; i < io_ranges->len; i++) {
+ entry = g_ptr_array_index(io_ranges, i);
aml_append(crs,
aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
AML_POS_DECODE, AML_ENTIRE_RANGE,
@@ -2104,11 +2150,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
AML_CACHEABLE, AML_READ_WRITE,
0, 0x000A0000, 0x000BFFFF, 0, 0x00020000));
- crs_replace_with_free_ranges(crs_range_set.mem_ranges,
- range_lob(pci_hole),
- range_upb(pci_hole));
- for (i = 0; i < crs_range_set.mem_ranges->len; i++) {
- entry = g_ptr_array_index(crs_range_set.mem_ranges, i);
+ crs_replace_with_free_ranges(mem_ranges, pci->w32.begin, pci->w32.end - 1);
+ for (i = 0; i < mem_ranges->len; i++) {
+ entry = g_ptr_array_index(mem_ranges, i);
aml_append(crs,
aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
AML_NON_CACHEABLE, AML_READ_WRITE,
@@ -2116,19 +2160,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
0, entry->limit - entry->base + 1));
}
- if (!range_is_empty(pci_hole64)) {
- crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges,
- range_lob(pci_hole64),
- range_upb(pci_hole64));
- for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) {
- entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i);
- aml_append(crs,
- aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
- AML_MAX_FIXED,
- AML_CACHEABLE, AML_READ_WRITE,
- 0, entry->base, entry->limit,
- 0, entry->limit - entry->base + 1));
- }
+ if (pci->w64.begin) {
+ aml_append(crs,
+ aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
+ AML_CACHEABLE, AML_READ_WRITE,
+ 0, pci->w64.begin, pci->w64.end - 1, 0,
+ pci->w64.end - pci->w64.begin));
}
if (misc->tpm_version != TPM_VERSION_UNSPEC) {
@@ -2150,7 +2187,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
- crs_range_set_free(&crs_range_set);
+ g_ptr_array_free(io_ranges, true);
+ g_ptr_array_free(mem_ranges, true);
/* reserve PCIHP resources */
if (pm->pcihp_io_len) {
@@ -2284,6 +2322,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
sb_scope = aml_scope("\\_SB");
{
+ build_processor_devices(sb_scope, machine, pm);
+
build_memory_devices(sb_scope, nr_mem, pm->mem_hp_io_base,
pm->mem_hp_io_len);
@@ -2333,7 +2373,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
}
static void
-build_hpet(GArray *table_data, BIOSLinker *linker)
+build_hpet(GArray *table_data, GArray *linker)
{
Acpi20Hpet *hpet;
@@ -2348,31 +2388,32 @@ build_hpet(GArray *table_data, BIOSLinker *linker)
}
static void
-build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
+build_tpm_tcpa(GArray *table_data, GArray *linker, GArray *tcpalog)
{
Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa);
- unsigned log_addr_size = sizeof(tcpa->log_area_start_address);
- unsigned log_addr_offset =
- (char *)&tcpa->log_area_start_address - table_data->data;
+ uint64_t log_area_start_address = acpi_data_len(tcpalog);
tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);
tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
- acpi_data_push(tcpalog, le32_to_cpu(tcpa->log_area_minimum_length));
+ tcpa->log_area_start_address = cpu_to_le64(log_area_start_address);
- bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1,
+ bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, 1,
false /* high memory */);
/* log area start address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
- ACPI_BUILD_TPMLOG_FILE, 0);
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+ ACPI_BUILD_TPMLOG_FILE,
+ table_data, &tcpa->log_area_start_address,
+ sizeof(tcpa->log_area_start_address));
build_header(linker, table_data,
(void *)tcpa, "TCPA", sizeof(*tcpa), 2, NULL, NULL);
+
+ acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
}
static void
-build_tpm2(GArray *table_data, BIOSLinker *linker)
+build_tpm2(GArray *table_data, GArray *linker)
{
Acpi20TPM2 *tpm2_ptr;
@@ -2386,14 +2427,35 @@ build_tpm2(GArray *table_data, BIOSLinker *linker)
(void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL);
}
+typedef enum {
+ MEM_AFFINITY_NOFLAGS = 0,
+ MEM_AFFINITY_ENABLED = (1 << 0),
+ MEM_AFFINITY_HOTPLUGGABLE = (1 << 1),
+ MEM_AFFINITY_NON_VOLATILE = (1 << 2),
+} MemoryAffinityFlags;
+
+static void
+acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
+ uint64_t len, int node, MemoryAffinityFlags flags)
+{
+ numamem->type = ACPI_SRAT_MEMORY;
+ numamem->length = sizeof(*numamem);
+ memset(numamem->proximity, 0, 4);
+ numamem->proximity[0] = node;
+ numamem->flags = cpu_to_le32(flags);
+ numamem->base_addr = cpu_to_le64(base);
+ numamem->range_length = cpu_to_le64(len);
+}
+
static void
-build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
+build_srat(GArray *table_data, GArray *linker, MachineState *machine)
{
AcpiSystemResourceAffinityTable *srat;
AcpiSratProcessorAffinity *core;
AcpiSratMemoryAffinity *numamem;
int i;
+ uint64_t curnode;
int srat_start, numa_start, slots;
uint64_t mem_len, mem_base, next_base;
MachineClass *mc = MACHINE_GET_CLASS(machine);
@@ -2409,19 +2471,14 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
srat->reserved1 = cpu_to_le32(1);
for (i = 0; i < apic_ids->len; i++) {
- int j;
int apic_id = apic_ids->cpus[i].arch_id;
core = acpi_data_push(table_data, sizeof *core);
- core->type = ACPI_SRAT_PROCESSOR_APIC;
+ core->type = ACPI_SRAT_PROCESSOR;
core->length = sizeof(*core);
core->local_apic_id = apic_id;
- for (j = 0; j < nb_numa_nodes; j++) {
- if (test_bit(i, numa_info[j].node_cpu)) {
- core->proximity_lo = j;
- break;
- }
- }
+ curnode = pcms->node_cpu[apic_id];
+ core->proximity_lo = curnode;
memset(core->proximity_hi, 0, 3);
core->local_sapic_eid = 0;
core->flags = cpu_to_le32(1);
@@ -2435,7 +2492,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
numa_start = table_data->len;
numamem = acpi_data_push(table_data, sizeof *numamem);
- build_srat_memory(numamem, 0, 640 * 1024, 0, MEM_AFFINITY_ENABLED);
+ acpi_build_srat_memory(numamem, 0, 640*1024, 0, MEM_AFFINITY_ENABLED);
next_base = 1024 * 1024;
for (i = 1; i < pcms->numa_nodes + 1; ++i) {
mem_base = next_base;
@@ -2451,21 +2508,21 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
mem_len -= next_base - pcms->below_4g_mem_size;
if (mem_len > 0) {
numamem = acpi_data_push(table_data, sizeof *numamem);
- build_srat_memory(numamem, mem_base, mem_len, i - 1,
- MEM_AFFINITY_ENABLED);
+ acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1,
+ MEM_AFFINITY_ENABLED);
}
mem_base = 1ULL << 32;
mem_len = next_base - pcms->below_4g_mem_size;
next_base += (1ULL << 32) - pcms->below_4g_mem_size;
}
numamem = acpi_data_push(table_data, sizeof *numamem);
- build_srat_memory(numamem, mem_base, mem_len, i - 1,
- MEM_AFFINITY_ENABLED);
+ acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1,
+ MEM_AFFINITY_ENABLED);
}
slots = (table_data->len - numa_start) / sizeof *numamem;
for (; slots < pcms->numa_nodes + 2; slots++) {
numamem = acpi_data_push(table_data, sizeof *numamem);
- build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
+ acpi_build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
}
/*
@@ -2475,9 +2532,10 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
*/
if (hotplugabble_address_space_size) {
numamem = acpi_data_push(table_data, sizeof *numamem);
- build_srat_memory(numamem, pcms->hotplug_memory.base,
- hotplugabble_address_space_size, 0,
- MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
+ acpi_build_srat_memory(numamem, pcms->hotplug_memory.base,
+ hotplugabble_address_space_size, 0,
+ MEM_AFFINITY_HOTPLUGGABLE |
+ MEM_AFFINITY_ENABLED);
}
build_header(linker, table_data,
@@ -2488,7 +2546,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
}
static void
-build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
+build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
{
AcpiTableMcfg *mcfg;
const char *sig;
@@ -2516,75 +2574,51 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
}
-/*
- * VT-d spec 8.1 DMA Remapping Reporting Structure
- * (version Oct. 2014 or later)
- */
static void
-build_dmar_q35(GArray *table_data, BIOSLinker *linker)
+build_dmar_q35(GArray *table_data, GArray *linker)
{
int dmar_start = table_data->len;
AcpiTableDmar *dmar;
AcpiDmarHardwareUnit *drhd;
- uint8_t dmar_flags = 0;
- X86IOMMUState *iommu = x86_iommu_get_default();
- AcpiDmarDeviceScope *scope = NULL;
- /* Root complex IOAPIC use one path[0] only */
- size_t ioapic_scope_size = sizeof(*scope) + sizeof(scope->path[0]);
-
- assert(iommu);
- if (iommu->intr_supported) {
- dmar_flags |= 0x1; /* Flags: 0x1: INT_REMAP */
- }
dmar = acpi_data_push(table_data, sizeof(*dmar));
dmar->host_address_width = VTD_HOST_ADDRESS_WIDTH - 1;
- dmar->flags = dmar_flags;
+ dmar->flags = 0; /* No intr_remap for now */
/* DMAR Remapping Hardware Unit Definition structure */
- drhd = acpi_data_push(table_data, sizeof(*drhd) + ioapic_scope_size);
+ drhd = acpi_data_push(table_data, sizeof(*drhd));
drhd->type = cpu_to_le16(ACPI_DMAR_TYPE_HARDWARE_UNIT);
- drhd->length = cpu_to_le16(sizeof(*drhd) + ioapic_scope_size);
+ drhd->length = cpu_to_le16(sizeof(*drhd)); /* No device scope now */
drhd->flags = ACPI_DMAR_INCLUDE_PCI_ALL;
drhd->pci_segment = cpu_to_le16(0);
drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
- /* Scope definition for the root-complex IOAPIC. See VT-d spec
- * 8.3.1 (version Oct. 2014 or later). */
- scope = &drhd->scope[0];
- scope->entry_type = 0x03; /* Type: 0x03 for IOAPIC */
- scope->length = ioapic_scope_size;
- scope->enumeration_id = ACPI_BUILD_IOAPIC_ID;
- scope->bus = Q35_PSEUDO_BUS_PLATFORM;
- scope->path[0] = cpu_to_le16(Q35_PSEUDO_DEVFN_IOAPIC);
-
build_header(linker, table_data, (void *)(table_data->data + dmar_start),
"DMAR", table_data->len - dmar_start, 1, NULL, NULL);
}
static GArray *
-build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
+build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
{
AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
- unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
- unsigned rsdt_pa_offset =
- (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
- bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
+ bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 16,
true /* fseg memory */);
memcpy(&rsdp->signature, "RSD PTR ", 8);
memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
+ rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
/* Address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
- ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
-
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
+ ACPI_BUILD_TABLE_FILE,
+ rsdp_table, &rsdp->rsdt_physical_address,
+ sizeof rsdp->rsdt_physical_address);
+ rsdp->checksum = 0;
/* Checksum to be filled by Guest linker */
bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
- (char *)rsdp - rsdp_table->data, sizeof *rsdp,
- (char *)&rsdp->checksum - rsdp_table->data);
+ rsdp_table, rsdp, sizeof *rsdp,
+ &rsdp->checksum);
return rsdp_table;
}
@@ -2624,7 +2658,12 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
static bool acpi_has_iommu(void)
{
- return !!x86_iommu_get_default();
+ bool ambiguous;
+ Object *intel_iommu;
+
+ intel_iommu = object_resolve_path_type("", TYPE_INTEL_IOMMU_DEVICE,
+ &ambiguous);
+ return intel_iommu && !ambiguous;
}
static
@@ -2637,7 +2676,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
AcpiPmInfo pm;
AcpiMiscInfo misc;
AcpiMcfgInfo mcfg;
- Range pci_hole, pci_hole64;
+ PcPciInfo pci;
uint8_t *u;
size_t aml_len = 0;
GArray *tables_blob = tables->table_data;
@@ -2645,15 +2684,14 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
acpi_get_pm_info(&pm);
acpi_get_misc_info(&misc);
- acpi_get_pci_holes(&pci_hole, &pci_hole64);
+ acpi_get_pci_info(&pci);
acpi_get_slic_oem(&slic_oem);
table_offsets = g_array_new(false, true /* clear */,
sizeof(uint32_t));
ACPI_BUILD_DPRINTF("init ACPI tables\n");
- bios_linker_loader_alloc(tables->linker,
- ACPI_BUILD_TABLE_FILE, tables_blob,
+ bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE,
64 /* Ensure FACS is aligned */,
false /* high memory */);
@@ -2667,8 +2705,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
/* DSDT is pointed to by FADT */
dsdt = tables_blob->len;
- build_dsdt(tables_blob, tables->linker, &pm, &misc,
- &pci_hole, &pci_hole64, machine);
+ build_dsdt(tables_blob, tables->linker, &pm, &misc, &pci, machine);
/* Count the size of the DSDT and SSDT, we will need it for legacy
* sizing of ACPI tables.
@@ -2711,8 +2748,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
build_dmar_q35(tables_blob, tables->linker);
}
if (pcms->acpi_nvdimm_state.is_enabled) {
- nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,
- pcms->acpi_nvdimm_state.dsm_mem);
+ nvdimm_build_acpi(table_offsets, tables_blob, tables->linker);
}
/* Add tables supplied by user (if any) */
@@ -2775,7 +2811,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
}
- acpi_align_size(tables->linker->cmd_blob, ACPI_BUILD_ALIGN_SIZE);
+ acpi_align_size(tables->linker, ACPI_BUILD_ALIGN_SIZE);
/* Cleanup memory that's no longer used. */
g_array_free(table_offsets, true);
@@ -2815,7 +2851,7 @@ static void acpi_build_update(void *build_opaque)
acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
}
- acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob);
+ acpi_ram_update(build_state->linker_mr, tables.linker);
acpi_build_tables_cleanup(&tables, true);
}
@@ -2879,8 +2915,7 @@ void acpi_setup(void)
assert(build_state->table_mr != NULL);
build_state->linker_mr =
- acpi_add_rom_blob(build_state, tables.linker->cmd_blob,
- "etc/table-loader", 0);
+ acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 28c31a2cd..347718f93 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -20,23 +20,16 @@
*/
#include "qemu/osdep.h"
-#include "qemu/error-report.h"
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
#include "intel_iommu_internal.h"
#include "hw/pci/pci.h"
-#include "hw/pci/pci_bus.h"
-#include "hw/i386/pc.h"
-#include "hw/boards.h"
-#include "hw/i386/x86-iommu.h"
-#include "hw/pci-host/q35.h"
-#include "sysemu/kvm.h"
/*#define DEBUG_INTEL_IOMMU*/
#ifdef DEBUG_INTEL_IOMMU
enum {
DEBUG_GENERAL, DEBUG_CSR, DEBUG_INV, DEBUG_MMU, DEBUG_FLOG,
- DEBUG_CACHE, DEBUG_IR,
+ DEBUG_CACHE,
};
#define VTD_DBGBIT(x) (1 << DEBUG_##x)
static int vtd_dbgflags = VTD_DBGBIT(GENERAL) | VTD_DBGBIT(CSR);
@@ -197,7 +190,7 @@ static void vtd_reset_context_cache(IntelIOMMUState *s)
VTD_DPRINTF(CACHE, "global context_cache_gen=1");
while (g_hash_table_iter_next (&bus_it, NULL, (void**)&vtd_bus)) {
- for (devfn_it = 0; devfn_it < X86_IOMMU_PCI_DEVFN_MAX; ++devfn_it) {
+ for (devfn_it = 0; devfn_it < VTD_PCI_DEVFN_MAX; ++devfn_it) {
vtd_as = vtd_bus->dev_as[devfn_it];
if (!vtd_as) {
continue;
@@ -906,27 +899,6 @@ static void vtd_root_table_setup(IntelIOMMUState *s)
(s->root_extended ? "(extended)" : ""));
}
-static void vtd_iec_notify_all(IntelIOMMUState *s, bool global,
- uint32_t index, uint32_t mask)
-{
- x86_iommu_iec_notify_all(X86_IOMMU_DEVICE(s), global, index, mask);
-}
-
-static void vtd_interrupt_remap_table_setup(IntelIOMMUState *s)
-{
- uint64_t value = 0;
- value = vtd_get_quad_raw(s, DMAR_IRTA_REG);
- s->intr_size = 1UL << ((value & VTD_IRTA_SIZE_MASK) + 1);
- s->intr_root = value & VTD_IRTA_ADDR_MASK;
- s->intr_eime = value & VTD_IRTA_EIME;
-
- /* Notify global invalidation */
- vtd_iec_notify_all(s, true, 0, 0);
-
- VTD_DPRINTF(CSR, "int remap table addr 0x%"PRIx64 " size %"PRIu32,
- s->intr_root, s->intr_size);
-}
-
static void vtd_context_global_invalidate(IntelIOMMUState *s)
{
s->context_cache_gen++;
@@ -990,7 +962,7 @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
vtd_bus = vtd_find_as_from_bus_num(s, VTD_SID_TO_BUS(source_id));
if (vtd_bus) {
devfn = VTD_SID_TO_DEVFN(source_id);
- for (devfn_it = 0; devfn_it < X86_IOMMU_PCI_DEVFN_MAX; ++devfn_it) {
+ for (devfn_it = 0; devfn_it < VTD_PCI_DEVFN_MAX; ++devfn_it) {
vtd_as = vtd_bus->dev_as[devfn_it];
if (vtd_as && ((devfn_it & mask) == (devfn & mask))) {
VTD_DPRINTF(INV, "invalidate context-cahce of devfn 0x%"PRIx16,
@@ -1165,16 +1137,6 @@ static void vtd_handle_gcmd_srtp(IntelIOMMUState *s)
vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_RTPS);
}
-/* Set Interrupt Remap Table Pointer */
-static void vtd_handle_gcmd_sirtp(IntelIOMMUState *s)
-{
- VTD_DPRINTF(CSR, "set Interrupt Remap Table Pointer");
-
- vtd_interrupt_remap_table_setup(s);
- /* Ok - report back to driver */
- vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_IRTPS);
-}
-
/* Handle Translation Enable/Disable */
static void vtd_handle_gcmd_te(IntelIOMMUState *s, bool en)
{
@@ -1194,22 +1156,6 @@ static void vtd_handle_gcmd_te(IntelIOMMUState *s, bool en)
}
}
-/* Handle Interrupt Remap Enable/Disable */
-static void vtd_handle_gcmd_ire(IntelIOMMUState *s, bool en)
-{
- VTD_DPRINTF(CSR, "Interrupt Remap Enable %s", (en ? "on" : "off"));
-
- if (en) {
- s->intr_enabled = true;
- /* Ok - report back to driver */
- vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_IRES);
- } else {
- s->intr_enabled = false;
- /* Ok - report back to driver */
- vtd_set_clear_mask_long(s, DMAR_GSTS_REG, VTD_GSTS_IRES, 0);
- }
-}
-
/* Handle write to Global Command Register */
static void vtd_handle_gcmd_write(IntelIOMMUState *s)
{
@@ -1230,14 +1176,6 @@ static void vtd_handle_gcmd_write(IntelIOMMUState *s)
/* Queued Invalidation Enable */
vtd_handle_gcmd_qie(s, val & VTD_GCMD_QIE);
}
- if (val & VTD_GCMD_SIRTP) {
- /* Set/update the interrupt remapping root-table pointer */
- vtd_handle_gcmd_sirtp(s);
- }
- if (changed & VTD_GCMD_IRE) {
- /* Interrupt remap enable/disable */
- vtd_handle_gcmd_ire(s, val & VTD_GCMD_IRE);
- }
}
/* Handle write to Context Command Register */
@@ -1423,21 +1361,6 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
return true;
}
-static bool vtd_process_inv_iec_desc(IntelIOMMUState *s,
- VTDInvDesc *inv_desc)
-{
- VTD_DPRINTF(INV, "inv ir glob %d index %d mask %d",
- inv_desc->iec.granularity,
- inv_desc->iec.index,
- inv_desc->iec.index_mask);
-
- vtd_iec_notify_all(s, !inv_desc->iec.granularity,
- inv_desc->iec.index,
- inv_desc->iec.index_mask);
-
- return true;
-}
-
static bool vtd_process_inv_desc(IntelIOMMUState *s)
{
VTDInvDesc inv_desc;
@@ -1477,15 +1400,6 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
}
break;
- case VTD_INV_DESC_IEC:
- VTD_DPRINTF(INV, "Invalidation Interrupt Entry Cache "
- "Descriptor hi 0x%"PRIx64 " lo 0x%"PRIx64,
- inv_desc.hi, inv_desc.lo);
- if (!vtd_process_inv_iec_desc(s, &inv_desc)) {
- return false;
- }
- break;
-
default:
VTD_DPRINTF(GENERAL, "error: unkonw Invalidation Descriptor type "
"hi 0x%"PRIx64 " lo 0x%"PRIx64 " type %"PRIu8,
@@ -1914,23 +1828,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
vtd_update_fsts_ppf(s);
break;
- case DMAR_IRTA_REG:
- VTD_DPRINTF(IR, "DMAR_IRTA_REG write addr 0x%"PRIx64
- ", size %d, val 0x%"PRIx64, addr, size, val);
- if (size == 4) {
- vtd_set_long(s, addr, val);
- } else {
- vtd_set_quad(s, addr, val);
- }
- break;
-
- case DMAR_IRTA_REG_HI:
- VTD_DPRINTF(IR, "DMAR_IRTA_REG_HI write addr 0x%"PRIx64
- ", size %d, val 0x%"PRIx64, addr, size, val);
- assert(size == 4);
- vtd_set_long(s, addr, val);
- break;
-
default:
VTD_DPRINTF(GENERAL, "error: unhandled reg write addr 0x%"PRIx64
", size %d, val 0x%"PRIx64, addr, size, val);
@@ -1974,16 +1871,6 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
return ret;
}
-static void vtd_iommu_notify_started(MemoryRegion *iommu)
-{
- VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
-
- hw_error("Device at bus %s addr %02x.%d requires iommu notifier which "
- "is currently not supported by intel-iommu emulation",
- vtd_as->bus->qbus.name, PCI_SLOT(vtd_as->devfn),
- PCI_FUNC(vtd_as->devfn));
-}
-
static const VMStateDescription vtd_vmstate = {
.name = "iommu-intel",
.unmigratable = 1,
@@ -2008,295 +1895,6 @@ static Property vtd_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-/* Read IRTE entry with specific index */
-static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
- VTD_IR_TableEntry *entry, uint16_t sid)
-{
- static const uint16_t vtd_svt_mask[VTD_SQ_MAX] = \
- {0xffff, 0xfffb, 0xfff9, 0xfff8};
- dma_addr_t addr = 0x00;
- uint16_t mask, source_id;
- uint8_t bus, bus_max, bus_min;
-
- addr = iommu->intr_root + index * sizeof(*entry);
- if (dma_memory_read(&address_space_memory, addr, entry,
- sizeof(*entry))) {
- VTD_DPRINTF(GENERAL, "error: fail to access IR root at 0x%"PRIx64
- " + %"PRIu16, iommu->intr_root, index);
- return -VTD_FR_IR_ROOT_INVAL;
- }
-
- if (!entry->irte.present) {
- VTD_DPRINTF(GENERAL, "error: present flag not set in IRTE"
- " entry index %u value 0x%"PRIx64 " 0x%"PRIx64,
- index, le64_to_cpu(entry->data[1]),
- le64_to_cpu(entry->data[0]));
- return -VTD_FR_IR_ENTRY_P;
- }
-
- if (entry->irte.__reserved_0 || entry->irte.__reserved_1 ||
- entry->irte.__reserved_2) {
- VTD_DPRINTF(GENERAL, "error: IRTE entry index %"PRIu16
- " reserved fields non-zero: 0x%"PRIx64 " 0x%"PRIx64,
- index, le64_to_cpu(entry->data[1]),
- le64_to_cpu(entry->data[0]));
- return -VTD_FR_IR_IRTE_RSVD;
- }
-
- if (sid != X86_IOMMU_SID_INVALID) {
- /* Validate IRTE SID */
- source_id = le32_to_cpu(entry->irte.source_id);
- switch (entry->irte.sid_vtype) {
- case VTD_SVT_NONE:
- VTD_DPRINTF(IR, "No SID validation for IRTE index %d", index);
- break;
-
- case VTD_SVT_ALL:
- mask = vtd_svt_mask[entry->irte.sid_q];
- if ((source_id & mask) != (sid & mask)) {
- VTD_DPRINTF(GENERAL, "SID validation for IRTE index "
- "%d failed (reqid 0x%04x sid 0x%04x)", index,
- sid, source_id);
- return -VTD_FR_IR_SID_ERR;
- }
- break;
-
- case VTD_SVT_BUS:
- bus_max = source_id >> 8;
- bus_min = source_id & 0xff;
- bus = sid >> 8;
- if (bus > bus_max || bus < bus_min) {
- VTD_DPRINTF(GENERAL, "SID validation for IRTE index %d "
- "failed (bus %d outside %d-%d)", index, bus,
- bus_min, bus_max);
- return -VTD_FR_IR_SID_ERR;
- }
- break;
-
- default:
- VTD_DPRINTF(GENERAL, "Invalid SVT bits (0x%x) in IRTE index "
- "%d", entry->irte.sid_vtype, index);
- /* Take this as verification failure. */
- return -VTD_FR_IR_SID_ERR;
- break;
- }
- }
-
- return 0;
-}
-
-/* Fetch IRQ information of specific IR index */
-static int vtd_remap_irq_get(IntelIOMMUState *iommu, uint16_t index,
- VTDIrq *irq, uint16_t sid)
-{
- VTD_IR_TableEntry irte = {};
- int ret = 0;
-
- ret = vtd_irte_get(iommu, index, &irte, sid);
- if (ret) {
- return ret;
- }
-
- irq->trigger_mode = irte.irte.trigger_mode;
- irq->vector = irte.irte.vector;
- irq->delivery_mode = irte.irte.delivery_mode;
- irq->dest = le32_to_cpu(irte.irte.dest_id);
- if (!iommu->intr_eime) {
-#define VTD_IR_APIC_DEST_MASK (0xff00ULL)
-#define VTD_IR_APIC_DEST_SHIFT (8)
- irq->dest = (irq->dest & VTD_IR_APIC_DEST_MASK) >>
- VTD_IR_APIC_DEST_SHIFT;
- }
- irq->dest_mode = irte.irte.dest_mode;
- irq->redir_hint = irte.irte.redir_hint;
-
- VTD_DPRINTF(IR, "remapping interrupt index %d: trig:%u,vec:%u,"
- "deliver:%u,dest:%u,dest_mode:%u", index,
- irq->trigger_mode, irq->vector, irq->delivery_mode,
- irq->dest, irq->dest_mode);
-
- return 0;
-}
-
-/* Generate one MSI message from VTDIrq info */
-static void vtd_generate_msi_message(VTDIrq *irq, MSIMessage *msg_out)
-{
- VTD_MSIMessage msg = {};
-
- /* Generate address bits */
- msg.dest_mode = irq->dest_mode;
- msg.redir_hint = irq->redir_hint;
- msg.dest = irq->dest;
- msg.__addr_head = cpu_to_le32(0xfee);
- /* Keep this from original MSI address bits */
- msg.__not_used = irq->msi_addr_last_bits;
-
- /* Generate data bits */
- msg.vector = irq->vector;
- msg.delivery_mode = irq->delivery_mode;
- msg.level = 1;
- msg.trigger_mode = irq->trigger_mode;
-
- msg_out->address = msg.msi_addr;
- msg_out->data = msg.msi_data;
-}
-
-/* Interrupt remapping for MSI/MSI-X entry */
-static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,
- MSIMessage *origin,
- MSIMessage *translated,
- uint16_t sid)
-{
- int ret = 0;
- VTD_IR_MSIAddress addr;
- uint16_t index;
- VTDIrq irq = {};
-
- assert(origin && translated);
-
- if (!iommu || !iommu->intr_enabled) {
- goto do_not_translate;
- }
-
- if (origin->address & VTD_MSI_ADDR_HI_MASK) {
- VTD_DPRINTF(GENERAL, "error: MSI addr high 32 bits nonzero"
- " during interrupt remapping: 0x%"PRIx32,
- (uint32_t)((origin->address & VTD_MSI_ADDR_HI_MASK) >> \
- VTD_MSI_ADDR_HI_SHIFT));
- return -VTD_FR_IR_REQ_RSVD;
- }
-
- addr.data = origin->address & VTD_MSI_ADDR_LO_MASK;
- if (le16_to_cpu(addr.addr.__head) != 0xfee) {
- VTD_DPRINTF(GENERAL, "error: MSI addr low 32 bits invalid: "
- "0x%"PRIx32, addr.data);
- return -VTD_FR_IR_REQ_RSVD;
- }
-
- /* This is compatible mode. */
- if (addr.addr.int_mode != VTD_IR_INT_FORMAT_REMAP) {
- goto do_not_translate;
- }
-
- index = addr.addr.index_h << 15 | le16_to_cpu(addr.addr.index_l);
-
-#define VTD_IR_MSI_DATA_SUBHANDLE (0x0000ffff)
-#define VTD_IR_MSI_DATA_RESERVED (0xffff0000)
-
- if (addr.addr.sub_valid) {
- /* See VT-d spec 5.1.2.2 and 5.1.3 on subhandle */
- index += origin->data & VTD_IR_MSI_DATA_SUBHANDLE;
- }
-
- ret = vtd_remap_irq_get(iommu, index, &irq, sid);
- if (ret) {
- return ret;
- }
-
- if (addr.addr.sub_valid) {
- VTD_DPRINTF(IR, "received MSI interrupt");
- if (origin->data & VTD_IR_MSI_DATA_RESERVED) {
- VTD_DPRINTF(GENERAL, "error: MSI data bits non-zero for "
- "interrupt remappable entry: 0x%"PRIx32,
- origin->data);
- return -VTD_FR_IR_REQ_RSVD;
- }
- } else {
- uint8_t vector = origin->data & 0xff;
- VTD_DPRINTF(IR, "received IOAPIC interrupt");
- /* IOAPIC entry vector should be aligned with IRTE vector
- * (see vt-d spec 5.1.5.1). */
- if (vector != irq.vector) {
- VTD_DPRINTF(GENERAL, "IOAPIC vector inconsistent: "
- "entry: %d, IRTE: %d, index: %d",
- vector, irq.vector, index);
- }
- }
-
- /*
- * We'd better keep the last two bits, assuming that guest OS
- * might modify it. Keep it does not hurt after all.
- */
- irq.msi_addr_last_bits = addr.addr.__not_care;
-
- /* Translate VTDIrq to MSI message */
- vtd_generate_msi_message(&irq, translated);
-
- VTD_DPRINTF(IR, "mapping MSI 0x%"PRIx64":0x%"PRIx32 " -> "
- "0x%"PRIx64":0x%"PRIx32, origin->address, origin->data,
- translated->address, translated->data);
- return 0;
-
-do_not_translate:
- memcpy(translated, origin, sizeof(*origin));
- return 0;
-}
-
-static int vtd_int_remap(X86IOMMUState *iommu, MSIMessage *src,
- MSIMessage *dst, uint16_t sid)
-{
- return vtd_interrupt_remap_msi(INTEL_IOMMU_DEVICE(iommu),
- src, dst, sid);
-}
-
-static MemTxResult vtd_mem_ir_read(void *opaque, hwaddr addr,
- uint64_t *data, unsigned size,
- MemTxAttrs attrs)
-{
- return MEMTX_OK;
-}
-
-static MemTxResult vtd_mem_ir_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size,
- MemTxAttrs attrs)
-{
- int ret = 0;
- MSIMessage from = {}, to = {};
- uint16_t sid = X86_IOMMU_SID_INVALID;
-
- from.address = (uint64_t) addr + VTD_INTERRUPT_ADDR_FIRST;
- from.data = (uint32_t) value;
-
- if (!attrs.unspecified) {
- /* We have explicit Source ID */
- sid = attrs.requester_id;
- }
-
- ret = vtd_interrupt_remap_msi(opaque, &from, &to, sid);
- if (ret) {
- /* TODO: report error */
- VTD_DPRINTF(GENERAL, "int remap fail for addr 0x%"PRIx64
- " data 0x%"PRIx32, from.address, from.data);
- /* Drop this interrupt */
- return MEMTX_ERROR;
- }
-
- VTD_DPRINTF(IR, "delivering MSI 0x%"PRIx64":0x%"PRIx32
- " for device sid 0x%04x",
- to.address, to.data, sid);
-
- if (dma_memory_write(&address_space_memory, to.address,
- &to.data, size)) {
- VTD_DPRINTF(GENERAL, "error: fail to write 0x%"PRIx64
- " value 0x%"PRIx32, to.address, to.data);
- }
-
- return MEMTX_OK;
-}
-
-static const MemoryRegionOps vtd_mem_ir_ops = {
- .read_with_attrs = vtd_mem_ir_read,
- .write_with_attrs = vtd_mem_ir_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .impl = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
{
@@ -2306,8 +1904,7 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
if (!vtd_bus) {
/* No corresponding free() */
- vtd_bus = g_malloc0(sizeof(VTDBus) + sizeof(VTDAddressSpace *) * \
- X86_IOMMU_PCI_DEVFN_MAX);
+ vtd_bus = g_malloc0(sizeof(VTDBus) + sizeof(VTDAddressSpace *) * VTD_PCI_DEVFN_MAX);
vtd_bus->bus = bus;
key = (uintptr_t)bus;
g_hash_table_insert(s->vtd_as_by_busptr, &key, vtd_bus);
@@ -2324,11 +1921,6 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
vtd_dev_as->context_cache_entry.context_cache_gen = 0;
memory_region_init_iommu(&vtd_dev_as->iommu, OBJECT(s),
&s->iommu_ops, "intel_iommu", UINT64_MAX);
- memory_region_init_io(&vtd_dev_as->iommu_ir, OBJECT(s),
- &vtd_mem_ir_ops, s, "intel_iommu_ir",
- VTD_INTERRUPT_ADDR_SIZE);
- memory_region_add_subregion(&vtd_dev_as->iommu, VTD_INTERRUPT_ADDR_FIRST,
- &vtd_dev_as->iommu_ir);
address_space_init(&vtd_dev_as->as,
&vtd_dev_as->iommu, "intel_iommu");
}
@@ -2340,15 +1932,12 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
*/
static void vtd_init(IntelIOMMUState *s)
{
- X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s);
-
memset(s->csr, 0, DMAR_REG_SIZE);
memset(s->wmask, 0, DMAR_REG_SIZE);
memset(s->w1cmask, 0, DMAR_REG_SIZE);
memset(s->womask, 0, DMAR_REG_SIZE);
s->iommu_ops.translate = vtd_iommu_translate;
- s->iommu_ops.notify_started = vtd_iommu_notify_started;
s->root = 0;
s->root_extended = false;
s->dmar_enabled = false;
@@ -2363,10 +1952,6 @@ static void vtd_init(IntelIOMMUState *s)
VTD_CAP_SAGAW | VTD_CAP_MAMV | VTD_CAP_PSI | VTD_CAP_SLLPS;
s->ecap = VTD_ECAP_QI | VTD_ECAP_IRO;
- if (x86_iommu->intr_supported) {
- s->ecap |= VTD_ECAP_IR | VTD_ECAP_EIM | VTD_ECAP_MHMV;
- }
-
vtd_reset_context_cache(s);
vtd_reset_iotlb(s);
@@ -2416,11 +2001,6 @@ static void vtd_init(IntelIOMMUState *s)
/* Fault Recording Registers, 128-bit */
vtd_define_quad(s, DMAR_FRCD_REG_0_0, 0, 0, 0);
vtd_define_quad(s, DMAR_FRCD_REG_0_2, 0, 0, 0x8000000000000000ULL);
-
- /*
- * Interrupt remapping registers.
- */
- vtd_define_quad(s, DMAR_IRTA_REG, 0, 0xfffffffffffff80fULL, 0);
}
/* Should not reset address_spaces when reset because devices will still use
@@ -2434,23 +2014,9 @@ static void vtd_reset(DeviceState *dev)
vtd_init(s);
}
-static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
-{
- IntelIOMMUState *s = opaque;
- VTDAddressSpace *vtd_as;
-
- assert(0 <= devfn && devfn <= X86_IOMMU_PCI_DEVFN_MAX);
-
- vtd_as = vtd_find_add_as(s, bus, devfn);
- return &vtd_as->as;
-}
-
static void vtd_realize(DeviceState *dev, Error **errp)
{
- PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
- PCIBus *bus = pcms->bus;
IntelIOMMUState *s = INTEL_IOMMU_DEVICE(dev);
- X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(dev);
VTD_DPRINTF(GENERAL, "");
memset(s->vtd_as_by_bus_num, 0, sizeof(s->vtd_as_by_bus_num));
@@ -2463,36 +2029,21 @@ static void vtd_realize(DeviceState *dev, Error **errp)
s->vtd_as_by_busptr = g_hash_table_new_full(vtd_uint64_hash, vtd_uint64_equal,
g_free, g_free);
vtd_init(s);
- sysbus_mmio_map(SYS_BUS_DEVICE(s), 0, Q35_HOST_BRIDGE_IOMMU_ADDR);
- pci_setup_iommu(bus, vtd_host_dma_iommu, dev);
- /* Pseudo address space under root PCI bus. */
- pcms->ioapic_as = vtd_host_dma_iommu(bus, s, Q35_PSEUDO_DEVFN_IOAPIC);
-
- /* Currently Intel IOMMU IR only support "kernel-irqchip={off|split}" */
- if (x86_iommu->intr_supported && kvm_irqchip_in_kernel() &&
- !kvm_irqchip_is_split()) {
- error_report("Intel Interrupt Remapping cannot work with "
- "kernel-irqchip=on, please use 'split|off'.");
- exit(1);
- }
}
static void vtd_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- X86IOMMUClass *x86_class = X86_IOMMU_CLASS(klass);
dc->reset = vtd_reset;
+ dc->realize = vtd_realize;
dc->vmsd = &vtd_vmstate;
dc->props = vtd_properties;
- dc->hotpluggable = false;
- x86_class->realize = vtd_realize;
- x86_class->int_remap = vtd_int_remap;
}
static const TypeInfo vtd_info = {
.name = TYPE_INTEL_IOMMU_DEVICE,
- .parent = TYPE_X86_IOMMU_DEVICE,
+ .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IntelIOMMUState),
.class_init = vtd_class_init,
};
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 0829a5064..e5f514c6e 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -110,8 +110,6 @@
/* Interrupt Address Range */
#define VTD_INTERRUPT_ADDR_FIRST 0xfee00000ULL
#define VTD_INTERRUPT_ADDR_LAST 0xfeefffffULL
-#define VTD_INTERRUPT_ADDR_SIZE (VTD_INTERRUPT_ADDR_LAST - \
- VTD_INTERRUPT_ADDR_FIRST + 1)
/* The shift of source_id in the key of IOTLB hash table */
#define VTD_IOTLB_SID_SHIFT 36
@@ -174,19 +172,10 @@
#define VTD_RTADDR_RTT (1ULL << 11)
#define VTD_RTADDR_ADDR_MASK (VTD_HAW_MASK ^ 0xfffULL)
-/* IRTA_REG */
-#define VTD_IRTA_ADDR_MASK (VTD_HAW_MASK ^ 0xfffULL)
-#define VTD_IRTA_EIME (1ULL << 11)
-#define VTD_IRTA_SIZE_MASK (0xfULL)
-
/* ECAP_REG */
/* (offset >> 4) << 8 */
#define VTD_ECAP_IRO (DMAR_IOTLB_REG_OFFSET << 4)
#define VTD_ECAP_QI (1ULL << 1)
-/* Interrupt Remapping support */
-#define VTD_ECAP_IR (1ULL << 3)
-#define VTD_ECAP_EIM (1ULL << 4)
-#define VTD_ECAP_MHMV (15ULL << 20)
/* CAP_REG */
/* (offset >> 4) << 24 */
@@ -276,19 +265,6 @@ typedef enum VTDFaultReason {
* context-entry.
*/
VTD_FR_CONTEXT_ENTRY_TT,
-
- /* Interrupt remapping transition faults */
- VTD_FR_IR_REQ_RSVD = 0x20, /* One or more IR request reserved
- * fields set */
- VTD_FR_IR_INDEX_OVER = 0x21, /* Index value greater than max */
- VTD_FR_IR_ENTRY_P = 0x22, /* Present (P) not set in IRTE */
- VTD_FR_IR_ROOT_INVAL = 0x23, /* IR Root table invalid */
- VTD_FR_IR_IRTE_RSVD = 0x24, /* IRTE Rsvd field non-zero with
- * Present flag set */
- VTD_FR_IR_REQ_COMPAT = 0x25, /* Encountered compatible IR
- * request while disabled */
- VTD_FR_IR_SID_ERR = 0x26, /* Invalid Source-ID */
-
/* This is not a normal fault reason. We use this to indicate some faults
* that are not referenced by the VT-d specification.
* Fault event with such reason should not be recorded.
@@ -299,35 +275,17 @@ typedef enum VTDFaultReason {
#define VTD_CONTEXT_CACHE_GEN_MAX 0xffffffffUL
-/* Interrupt Entry Cache Invalidation Descriptor: VT-d 6.5.2.7. */
-struct VTDInvDescIEC {
- uint32_t type:4; /* Should always be 0x4 */
- uint32_t granularity:1; /* If set, it's global IR invalidation */
- uint32_t resved_1:22;
- uint32_t index_mask:5; /* 2^N for continuous int invalidation */
- uint32_t index:16; /* Start index to invalidate */
- uint32_t reserved_2:16;
-};
-typedef struct VTDInvDescIEC VTDInvDescIEC;
-
/* Queued Invalidation Descriptor */
-union VTDInvDesc {
- struct {
- uint64_t lo;
- uint64_t hi;
- };
- union {
- VTDInvDescIEC iec;
- };
+struct VTDInvDesc {
+ uint64_t lo;
+ uint64_t hi;
};
-typedef union VTDInvDesc VTDInvDesc;
+typedef struct VTDInvDesc VTDInvDesc;
/* Masks for struct VTDInvDesc */
#define VTD_INV_DESC_TYPE 0xf
#define VTD_INV_DESC_CC 0x1 /* Context-cache Invalidate Desc */
#define VTD_INV_DESC_IOTLB 0x2
-#define VTD_INV_DESC_IEC 0x4 /* Interrupt Entry Cache
- Invalidate Descriptor */
#define VTD_INV_DESC_WAIT 0x5 /* Invalidation Wait Descriptor */
#define VTD_INV_DESC_NONE 0 /* Not an Invalidate Descriptor */
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index 2bd0de82b..3c7c8fa00 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -10,8 +10,6 @@
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "cpu.h"
#include "hw/i386/apic_internal.h"
#include "hw/pci/msi.h"
#include "sysemu/kvm.h"
@@ -184,24 +182,19 @@ static void kvm_apic_realize(DeviceState *dev, Error **errp)
{
APICCommonState *s = APIC_COMMON(dev);
- memory_region_init_io(&s->io_memory, OBJECT(s), &kvm_apic_io_ops, s,
- "kvm-apic-msi", APIC_SPACE_SIZE);
+ memory_region_init_io(&s->io_memory, NULL, &kvm_apic_io_ops, s, "kvm-apic-msi",
+ APIC_SPACE_SIZE);
if (kvm_has_gsi_routing()) {
msi_nonbroken = true;
}
}
-static void kvm_apic_unrealize(DeviceState *dev, Error **errp)
-{
-}
-
static void kvm_apic_class_init(ObjectClass *klass, void *data)
{
APICCommonClass *k = APIC_COMMON_CLASS(klass);
k->realize = kvm_apic_realize;
- k->unrealize = kvm_apic_unrealize;
k->reset = kvm_apic_reset;
k->set_base = kvm_apic_set_base;
k->set_tpr = kvm_apic_set_tpr;
diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
index 0f75dd385..a3b300cad 100644
--- a/hw/i386/kvm/clock.c
+++ b/hw/i386/kvm/clock.c
@@ -15,7 +15,6 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
-#include "cpu.h"
#include "qemu/host-utils.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c
index 521a58498..a4462e5ca 100644
--- a/hw/i386/kvm/i8254.c
+++ b/hw/i386/kvm/i8254.c
@@ -22,9 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-
#include "qemu/osdep.h"
-#include <linux/kvm.h>
#include "qapi/error.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index 8238fbc63..8abce52b7 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -20,10 +20,9 @@
* Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com)
* Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com)
*/
-
#include "qemu/osdep.h"
-#include <linux/kvm.h>
#include "qapi/error.h"
+#include <sys/mman.h>
#include "hw/hw.h"
#include "hw/i386/pc.h"
#include "qemu/error-report.h"
@@ -37,6 +36,8 @@
#include "kvm_i386.h"
#include "hw/pci/pci-assign.h"
+#define MSIX_PAGE_SIZE 0x1000
+
/* From linux/ioport.h */
#define IORESOURCE_IO 0x00000100 /* Resource type */
#define IORESOURCE_MEM 0x00000200
@@ -121,7 +122,6 @@ typedef struct AssignedDevice {
int *msi_virq;
MSIXTableEntry *msix_table;
hwaddr msix_table_addr;
- uint16_t msix_table_size;
uint16_t msix_max;
MemoryRegion mmio;
char *configfd_name;
@@ -974,9 +974,10 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev)
}
if (ctrl_byte & PCI_MSI_FLAGS_ENABLE) {
+ MSIMessage msg = msi_get_message(pci_dev, 0);
int virq;
- virq = kvm_irqchip_add_msi_route(kvm_state, 0, pci_dev);
+ virq = kvm_irqchip_add_msi_route(kvm_state, msg, pci_dev);
if (virq < 0) {
perror("assigned_dev_update_msi: kvm_irqchip_add_msi_route");
return;
@@ -1015,7 +1016,6 @@ static void assigned_dev_update_msi_msg(PCIDevice *pci_dev)
kvm_irqchip_update_msi_route(kvm_state, assigned_dev->msi_virq[0],
msi_get_message(pci_dev, 0), pci_dev);
- kvm_irqchip_commit_routes(kvm_state);
}
static bool assigned_dev_msix_masked(MSIXTableEntry *entry)
@@ -1042,6 +1042,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
uint16_t entries_nr = 0;
int i, r = 0;
MSIXTableEntry *entry = adev->msix_table;
+ MSIMessage msg;
/* Get the usable entry number for allocating */
for (i = 0; i < adev->msix_max; i++, entry++) {
@@ -1078,7 +1079,9 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
continue;
}
- r = kvm_irqchip_add_msi_route(kvm_state, i, pci_dev);
+ msg.address = entry->addr_lo | ((uint64_t)entry->addr_hi << 32);
+ msg.data = entry->data;
+ r = kvm_irqchip_add_msi_route(kvm_state, msg, pci_dev);
if (r < 0) {
return r;
}
@@ -1307,7 +1310,6 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
bar_nr = msix_table_entry & PCI_MSIX_FLAGS_BIRMASK;
msix_table_entry &= ~PCI_MSIX_FLAGS_BIRMASK;
dev->msix_table_addr = pci_region[bar_nr].base_addr + msix_table_entry;
- dev->msix_table_size = msix_max * sizeof(MSIXTableEntry);
dev->msix_max = msix_max;
}
@@ -1479,7 +1481,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
* error bits, leave the rest. */
status = pci_get_long(pci_dev->config + pos + PCI_X_STATUS);
status &= ~(PCI_X_STATUS_BUS | PCI_X_STATUS_DEVFN);
- status |= pci_get_bdf(pci_dev);
+ status |= pci_requester_id(pci_dev);
status &= ~(PCI_X_STATUS_SPL_DISC | PCI_X_STATUS_UNX_SPL |
PCI_X_STATUS_SPL_ERR);
pci_set_long(pci_dev->config + pos + PCI_X_STATUS, status);
@@ -1603,7 +1605,6 @@ static void assigned_dev_msix_mmio_write(void *opaque, hwaddr addr,
if (ret) {
error_report("Error updating irq routing entry (%d)", ret);
}
- kvm_irqchip_commit_routes(kvm_state);
}
}
}
@@ -1632,7 +1633,7 @@ static void assigned_dev_msix_reset(AssignedDevice *dev)
return;
}
- memset(dev->msix_table, 0, dev->msix_table_size);
+ memset(dev->msix_table, 0, MSIX_PAGE_SIZE);
for (i = 0, entry = dev->msix_table; i < dev->msix_max; i++, entry++) {
entry->ctrl = cpu_to_le32(0x1); /* Masked */
@@ -1641,8 +1642,8 @@ static void assigned_dev_msix_reset(AssignedDevice *dev)
static void assigned_dev_register_msix_mmio(AssignedDevice *dev, Error **errp)
{
- dev->msix_table = mmap(NULL, dev->msix_table_size, PROT_READ | PROT_WRITE,
- MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+ dev->msix_table = mmap(NULL, MSIX_PAGE_SIZE, PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
if (dev->msix_table == MAP_FAILED) {
error_setg_errno(errp, errno, "failed to allocate msix_table");
dev->msix_table = NULL;
@@ -1652,7 +1653,7 @@ static void assigned_dev_register_msix_mmio(AssignedDevice *dev, Error **errp)
assigned_dev_msix_reset(dev);
memory_region_init_io(&dev->mmio, OBJECT(dev), &assigned_dev_msix_mmio_ops,
- dev, "assigned-dev-msix", dev->msix_table_size);
+ dev, "assigned-dev-msix", MSIX_PAGE_SIZE);
}
static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev)
@@ -1661,7 +1662,7 @@ static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev)
return;
}
- if (munmap(dev->msix_table, dev->msix_table_size) == -1) {
+ if (munmap(dev->msix_table, MSIX_PAGE_SIZE) == -1) {
error_report("error unmapping msix_table! %s", strerror(errno));
}
dev->msix_table = NULL;
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 3bf1ddd97..ff1e31a4d 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -9,9 +9,6 @@
* top-level directory.
*/
#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "cpu.h"
-#include "exec/exec-all.h"
#include "sysemu/sysemu.h"
#include "sysemu/cpus.h"
#include "sysemu/kvm.h"
@@ -400,7 +397,7 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
uint32_t imm32 = 0;
target_ulong current_pc = 0;
target_ulong current_cs_base = 0;
- uint32_t current_flags = 0;
+ int current_flags = 0;
if (smp_cpus == 1) {
handlers = &s->rom_state.up;
@@ -449,8 +446,9 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
resume_all_vcpus();
if (!kvm_enabled()) {
+ cs->current_tb = NULL;
tb_gen_code(cs, current_pc, current_cs_base, current_flags, 1);
- cpu_loop_exit_noexc(cs);
+ cpu_resume_from_signal(cs, NULL);
}
}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 022dd1b20..99437e0b7 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -67,7 +67,6 @@
#include "qapi/visitor.h"
#include "qapi-visit.h"
#include "qom/cpu.h"
-#include "hw/nmi.h"
/* debug PC/ISA interrupts */
//#define DEBUG_IRQ
@@ -381,7 +380,7 @@ ISADevice *pc_find_fdc0(void)
error_report("warning: multiple floppy disk controllers with "
"iobase=0x3f0 have been found");
error_printf("the one being picked for CMOS setup might not reflect "
- "your intent\n");
+ "your intent");
}
return state.floppy;
@@ -471,6 +470,9 @@ void pc_cmos_init(PCMachineState *pcms,
rtc_set_memory(s, 0x5c, val >> 8);
rtc_set_memory(s, 0x5d, val >> 16);
+ /* set the number of CPU */
+ rtc_set_memory(s, 0x5f, smp_cpus - 1);
+
object_property_add_link(OBJECT(pcms), "rtc_state",
TYPE_ISA_DEVICE,
(Object **)&pcms->rtc,
@@ -502,7 +504,7 @@ typedef struct Port92State {
MemoryRegion io;
uint8_t outport;
- qemu_irq a20_out;
+ qemu_irq *a20_out;
} Port92State;
static void port92_write(void *opaque, hwaddr addr, uint64_t val,
@@ -513,7 +515,7 @@ static void port92_write(void *opaque, hwaddr addr, uint64_t val,
DPRINTF("port92: write 0x%02" PRIx64 "\n", val);
s->outport = val;
- qemu_set_irq(s->a20_out, (val >> 1) & 1);
+ qemu_set_irq(*s->a20_out, (val >> 1) & 1);
if ((val & 1) && !(oldval & 1)) {
qemu_system_reset_request();
}
@@ -532,7 +534,9 @@ static uint64_t port92_read(void *opaque, hwaddr addr,
static void port92_init(ISADevice *dev, qemu_irq *a20_out)
{
- qdev_connect_gpio_out_named(DEVICE(dev), PORT92_A20_LINE, 0, *a20_out);
+ Port92State *s = PORT92(dev);
+
+ s->a20_out = a20_out;
}
static const VMStateDescription vmstate_port92_isa = {
@@ -569,8 +573,6 @@ static void port92_initfn(Object *obj)
memory_region_init_io(&s->io, OBJECT(s), &port92_ops, s, "port92", 1);
s->outport = 0;
-
- qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, PORT92_A20_LINE, 1);
}
static void port92_realizefn(DeviceState *dev, Error **errp)
@@ -762,6 +764,8 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
acpi_tables, acpi_tables_len);
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
+ pc_build_smbios(fw_cfg);
+
fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
&e820_reserve, sizeof(e820_reserve));
fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
@@ -809,26 +813,11 @@ static long get_file_size(FILE *f)
return size;
}
-/* setup_data types */
-#define SETUP_NONE 0
-#define SETUP_E820_EXT 1
-#define SETUP_DTB 2
-#define SETUP_PCI 3
-#define SETUP_EFI 4
-
-struct setup_data {
- uint64_t next;
- uint32_t type;
- uint32_t len;
- uint8_t data[0];
-} __attribute__((packed));
-
static void load_linux(PCMachineState *pcms,
FWCfgState *fw_cfg)
{
uint16_t protocol;
int setup_size, kernel_size, initrd_size = 0, cmdline_size;
- int dtb_size, setup_data_offset;
uint32_t initrd_max;
uint8_t header[8192], *setup, *kernel, *initrd_data;
hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
@@ -836,10 +825,8 @@ static void load_linux(PCMachineState *pcms,
char *vmode;
MachineState *machine = MACHINE(pcms);
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
- struct setup_data *setup_data;
const char *kernel_filename = machine->kernel_filename;
const char *initrd_filename = machine->initrd_filename;
- const char *dtb_filename = machine->dtb;
const char *kernel_cmdline = machine->kernel_cmdline;
/* Align to 16 bytes as a paranoia measure */
@@ -1002,35 +989,6 @@ static void load_linux(PCMachineState *pcms,
exit(1);
}
fclose(f);
-
- /* append dtb to kernel */
- if (dtb_filename) {
- if (protocol < 0x209) {
- fprintf(stderr, "qemu: Linux kernel too old to load a dtb\n");
- exit(1);
- }
-
- dtb_size = get_image_size(dtb_filename);
- if (dtb_size <= 0) {
- fprintf(stderr, "qemu: error reading dtb %s: %s\n",
- dtb_filename, strerror(errno));
- exit(1);
- }
-
- setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
- kernel_size = setup_data_offset + sizeof(struct setup_data) + dtb_size;
- kernel = g_realloc(kernel, kernel_size);
-
- stq_p(header+0x250, prot_addr + setup_data_offset);
-
- setup_data = (struct setup_data *)(kernel + setup_data_offset);
- setup_data->next = 0;
- setup_data->type = cpu_to_le32(SETUP_DTB);
- setup_data->len = cpu_to_le32(dtb_size);
-
- load_image_size(dtb_filename, setup_data->data, dtb_size);
- }
-
memcpy(setup, header, MIN(sizeof(header), setup_size));
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
@@ -1041,13 +999,8 @@ static void load_linux(PCMachineState *pcms,
fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
- if (fw_cfg_dma_enabled(fw_cfg)) {
- option_rom[nb_option_roms].name = "linuxboot_dma.bin";
- option_rom[nb_option_roms].bootindex = 0;
- } else {
- option_rom[nb_option_roms].name = "linuxboot.bin";
- option_rom[nb_option_roms].bootindex = 0;
- }
+ option_rom[nb_option_roms].name = "linuxboot.bin";
+ option_rom[nb_option_roms].bootindex = 0;
nb_option_roms++;
}
@@ -1087,28 +1040,21 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
}
}
-static int pc_present_cpus_count(PCMachineState *pcms)
-{
- int i, boot_cpus = 0;
- for (i = 0; i < pcms->possible_cpus->len; i++) {
- if (pcms->possible_cpus->cpus[i].cpu) {
- boot_cpus++;
- }
- }
- return boot_cpus;
-}
-
-static X86CPU *pc_new_cpu(const char *typename, int64_t apic_id,
+static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,
Error **errp)
{
X86CPU *cpu = NULL;
Error *local_err = NULL;
- cpu = X86_CPU(object_new(typename));
+ cpu = cpu_x86_create(cpu_model, &local_err);
+ if (local_err != NULL) {
+ goto out;
+ }
object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err);
object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
+out:
if (local_err) {
error_propagate(errp, local_err);
object_unref(OBJECT(cpu));
@@ -1120,8 +1066,7 @@ static X86CPU *pc_new_cpu(const char *typename, int64_t apic_id,
void pc_hot_add_cpu(const int64_t id, Error **errp)
{
X86CPU *cpu;
- ObjectClass *oc;
- PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+ MachineState *machine = MACHINE(qdev_get_machine());
int64_t apic_id = x86_cpu_apic_id_from_index(id);
Error *local_err = NULL;
@@ -1130,6 +1075,18 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
return;
}
+ if (cpu_exists(apic_id)) {
+ error_setg(errp, "Unable to add CPU: %" PRIi64
+ ", it already exists", id);
+ return;
+ }
+
+ if (id >= max_cpus) {
+ error_setg(errp, "Unable to add CPU: %" PRIi64
+ ", max allowed: %d", id, max_cpus - 1);
+ return;
+ }
+
if (apic_id >= ACPI_CPU_HOTPLUG_ID_LIMIT) {
error_setg(errp, "Unable to add CPU: %" PRIi64
", resulting APIC ID (%" PRIi64 ") is too large",
@@ -1137,9 +1094,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
return;
}
- assert(pcms->possible_cpus->cpus[0].cpu); /* BSP is always present */
- oc = OBJECT_CLASS(CPU_GET_CLASS(pcms->possible_cpus->cpus[0].cpu));
- cpu = pc_new_cpu(object_class_get_name(oc), apic_id, &local_err);
+ cpu = pc_new_cpu(machine->cpu_model, apic_id, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -1150,10 +1105,6 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
void pc_cpus_init(PCMachineState *pcms)
{
int i;
- CPUClass *cc;
- ObjectClass *oc;
- const char *typename;
- gchar **model_pieces;
X86CPU *cpu = NULL;
MachineState *machine = MACHINE(pcms);
@@ -1166,22 +1117,6 @@ void pc_cpus_init(PCMachineState *pcms)
#endif
}
- model_pieces = g_strsplit(machine->cpu_model, ",", 2);
- if (!model_pieces[0]) {
- error_report("Invalid/empty CPU model name");
- exit(1);
- }
-
- oc = cpu_class_by_name(TYPE_X86_CPU, model_pieces[0]);
- if (oc == NULL) {
- error_report("Unable to find CPU definition: %s", model_pieces[0]);
- exit(1);
- }
- typename = object_class_get_name(oc);
- cc = CPU_CLASS(oc);
- cc->parse_features(typename, model_pieces[1], &error_fatal);
- g_strfreev(model_pieces);
-
/* Calculates the limit to CPU APIC ID values
*
* Limit for the APIC ID value, so that all
@@ -1202,8 +1137,9 @@ void pc_cpus_init(PCMachineState *pcms)
pcms->possible_cpus->cpus[i].arch_id = x86_cpu_apic_id_from_index(i);
pcms->possible_cpus->len++;
if (i < smp_cpus) {
- cpu = pc_new_cpu(typename, x86_cpu_apic_id_from_index(i),
+ cpu = pc_new_cpu(machine->cpu_model, x86_cpu_apic_id_from_index(i),
&error_fatal);
+ pcms->possible_cpus->cpus[i].cpu = CPU(cpu);
object_unref(OBJECT(cpu));
}
}
@@ -1212,33 +1148,13 @@ void pc_cpus_init(PCMachineState *pcms)
smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
}
-static void pc_build_feature_control_file(PCMachineState *pcms)
-{
- X86CPU *cpu = X86_CPU(pcms->possible_cpus->cpus[0].cpu);
- CPUX86State *env = &cpu->env;
- uint32_t unused, ecx, edx;
- uint64_t feature_control_bits = 0;
- uint64_t *val;
-
- cpu_x86_cpuid(env, 1, 0, &unused, &unused, &ecx, &edx);
- if (ecx & CPUID_EXT_VMX) {
- feature_control_bits |= FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
- }
-
- if ((edx & (CPUID_EXT2_MCE | CPUID_EXT2_MCA)) ==
- (CPUID_EXT2_MCE | CPUID_EXT2_MCA) &&
- (env->mcg_cap & MCG_LMCE_P)) {
- feature_control_bits |= FEATURE_CONTROL_LMCE;
- }
-
- if (!feature_control_bits) {
- return;
- }
-
- val = g_malloc(sizeof(*val));
- *val = cpu_to_le64(feature_control_bits | FEATURE_CONTROL_LOCKED);
- fw_cfg_add_file(pcms->fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
-}
+/* pci-info ROM file. Little endian format */
+typedef struct PcRomPciInfo {
+ uint64_t w32_min;
+ uint64_t w32_max;
+ uint64_t w64_min;
+ uint64_t w64_max;
+} PcRomPciInfo;
static
void pc_machine_done(Notifier *notifier, void *data)
@@ -1247,9 +1163,6 @@ void pc_machine_done(Notifier *notifier, void *data)
PCMachineState, machine_done);
PCIBus *bus = pcms->bus;
- /* set the number of CPUs */
- rtc_set_memory(pcms->rtc, 0x5f, pc_present_cpus_count(pcms) - 1);
-
if (bus) {
int extra_hosts = 0;
@@ -1268,15 +1181,11 @@ void pc_machine_done(Notifier *notifier, void *data)
}
acpi_setup();
- if (pcms->fw_cfg) {
- pc_build_smbios(pcms->fw_cfg);
- pc_build_feature_control_file(pcms);
- }
}
void pc_guest_info_init(PCMachineState *pcms)
{
- int i;
+ int i, j;
pcms->apic_xrupt_override = kvm_allows_irq0_override();
pcms->numa_nodes = nb_numa_nodes;
@@ -1286,6 +1195,20 @@ void pc_guest_info_init(PCMachineState *pcms)
pcms->node_mem[i] = numa_info[i].node_mem;
}
+ pcms->node_cpu = g_malloc0(pcms->apic_id_limit *
+ sizeof *pcms->node_cpu);
+
+ for (i = 0; i < max_cpus; i++) {
+ unsigned int apic_id = x86_cpu_apic_id_from_index(i);
+ assert(apic_id < pcms->apic_id_limit);
+ for (j = 0; j < nb_numa_nodes; j++) {
+ if (test_bit(i, numa_info[j].node_cpu)) {
+ pcms->node_cpu[apic_id] = j;
+ break;
+ }
+ }
+ }
+
pcms->machine_done.notify = pc_machine_done;
qemu_add_machine_init_done_notifier(&pcms->machine_done);
}
@@ -1340,7 +1263,6 @@ void xen_load_linux(PCMachineState *pcms)
load_linux(pcms, fw_cfg);
for (i = 0; i < nb_option_roms; i++) {
assert(!strcmp(option_rom[i].name, "linuxboot.bin") ||
- !strcmp(option_rom[i].name, "linuxboot_dma.bin") ||
!strcmp(option_rom[i].name, "multiboot.bin"));
rom_add_option(option_rom[i].name, option_rom[i].bootindex);
}
@@ -1473,9 +1395,6 @@ void pc_memory_init(PCMachineState *pcms,
rom_add_option(option_rom[i].name, option_rom[i].bootindex);
}
pcms->fw_cfg = fw_cfg;
-
- /* Init default IOAPIC address space */
- pcms->ioapic_as = &address_space_memory;
}
qemu_irq pc_allocate_cpu_irq(void)
@@ -1757,204 +1676,44 @@ static int pc_apic_cmp(const void *a, const void *b)
return apic_a->arch_id - apic_b->arch_id;
}
-/* returns pointer to CPUArchId descriptor that matches CPU's apic_id
- * in pcms->possible_cpus->cpus, if pcms->possible_cpus->cpus has no
- * entry correponding to CPU's apic_id returns NULL.
- */
-static CPUArchId *pc_find_cpu_slot(PCMachineState *pcms, CPUState *cpu,
- int *idx)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
- CPUArchId apic_id, *found_cpu;
-
- apic_id.arch_id = cc->get_arch_id(CPU(cpu));
- found_cpu = bsearch(&apic_id, pcms->possible_cpus->cpus,
- pcms->possible_cpus->len, sizeof(*pcms->possible_cpus->cpus),
- pc_apic_cmp);
- if (found_cpu && idx) {
- *idx = found_cpu - pcms->possible_cpus->cpus;
- }
- return found_cpu;
-}
-
static void pc_cpu_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- CPUArchId *found_cpu;
- HotplugHandlerClass *hhc;
- Error *local_err = NULL;
- PCMachineState *pcms = PC_MACHINE(hotplug_dev);
-
- if (pcms->acpi_dev) {
- hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
- hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
- if (local_err) {
- goto out;
- }
- }
-
- if (dev->hotplugged) {
- /* increment the number of CPUs */
- rtc_set_memory(pcms->rtc, 0x5f, rtc_get_memory(pcms->rtc, 0x5f) + 1);
- }
-
- found_cpu = pc_find_cpu_slot(pcms, CPU(dev), NULL);
- found_cpu->cpu = CPU(dev);
-out:
- error_propagate(errp, local_err);
-}
-static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- int idx = -1;
+ CPUClass *cc = CPU_GET_CLASS(dev);
+ CPUArchId apic_id, *found_cpu;
HotplugHandlerClass *hhc;
Error *local_err = NULL;
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
- pc_find_cpu_slot(pcms, CPU(dev), &idx);
- assert(idx != -1);
- if (idx == 0) {
- error_setg(&local_err, "Boot CPU is unpluggable");
+ if (!dev->hotplugged) {
goto out;
}
- hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
- hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
-
- if (local_err) {
+ if (!pcms->acpi_dev) {
+ error_setg(&local_err,
+ "cpu hotplug is not enabled: missing acpi device");
goto out;
}
- out:
- error_propagate(errp, local_err);
-
-}
-
-static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- CPUArchId *found_cpu;
- HotplugHandlerClass *hhc;
- Error *local_err = NULL;
- PCMachineState *pcms = PC_MACHINE(hotplug_dev);
-
hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
- hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
-
+ hhc->plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
if (local_err) {
goto out;
}
- found_cpu = pc_find_cpu_slot(pcms, CPU(dev), NULL);
- found_cpu->cpu = NULL;
- object_unparent(OBJECT(dev));
+ /* increment the number of CPUs */
+ rtc_set_memory(pcms->rtc, 0x5f, rtc_get_memory(pcms->rtc, 0x5f) + 1);
- rtc_set_memory(pcms->rtc, 0x5f, rtc_get_memory(pcms->rtc, 0x5f) - 1);
- out:
+ apic_id.arch_id = cc->get_arch_id(CPU(dev));
+ found_cpu = bsearch(&apic_id, pcms->possible_cpus->cpus,
+ pcms->possible_cpus->len, sizeof(*pcms->possible_cpus->cpus),
+ pc_apic_cmp);
+ assert(found_cpu);
+ found_cpu->cpu = CPU(dev);
+out:
error_propagate(errp, local_err);
}
-static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- int idx;
- CPUState *cs;
- CPUArchId *cpu_slot;
- X86CPUTopoInfo topo;
- X86CPU *cpu = X86_CPU(dev);
- PCMachineState *pcms = PC_MACHINE(hotplug_dev);
-
- /* if APIC ID is not set, set it based on socket/core/thread properties */
- if (cpu->apic_id == UNASSIGNED_APIC_ID) {
- int max_socket = (max_cpus - 1) / smp_threads / smp_cores;
-
- if (cpu->socket_id < 0) {
- error_setg(errp, "CPU socket-id is not set");
- return;
- } else if (cpu->socket_id > max_socket) {
- error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u",
- cpu->socket_id, max_socket);
- return;
- }
- if (cpu->core_id < 0) {
- error_setg(errp, "CPU core-id is not set");
- return;
- } else if (cpu->core_id > (smp_cores - 1)) {
- error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u",
- cpu->core_id, smp_cores - 1);
- return;
- }
- if (cpu->thread_id < 0) {
- error_setg(errp, "CPU thread-id is not set");
- return;
- } else if (cpu->thread_id > (smp_threads - 1)) {
- error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u",
- cpu->thread_id, smp_threads - 1);
- return;
- }
-
- topo.pkg_id = cpu->socket_id;
- topo.core_id = cpu->core_id;
- topo.smt_id = cpu->thread_id;
- cpu->apic_id = apicid_from_topo_ids(smp_cores, smp_threads, &topo);
- }
-
- cpu_slot = pc_find_cpu_slot(pcms, CPU(dev), &idx);
- if (!cpu_slot) {
- x86_topo_ids_from_apicid(cpu->apic_id, smp_cores, smp_threads, &topo);
- error_setg(errp, "Invalid CPU [socket: %u, core: %u, thread: %u] with"
- " APIC ID %" PRIu32 ", valid index range 0:%d",
- topo.pkg_id, topo.core_id, topo.smt_id, cpu->apic_id,
- pcms->possible_cpus->len - 1);
- return;
- }
-
- if (cpu_slot->cpu) {
- error_setg(errp, "CPU[%d] with APIC ID %" PRIu32 " exists",
- idx, cpu->apic_id);
- return;
- }
-
- /* if 'address' properties socket-id/core-id/thread-id are not set, set them
- * so that query_hotpluggable_cpus would show correct values
- */
- /* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn()
- * once -smp refactoring is complete and there will be CPU private
- * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */
- x86_topo_ids_from_apicid(cpu->apic_id, smp_cores, smp_threads, &topo);
- if (cpu->socket_id != -1 && cpu->socket_id != topo.pkg_id) {
- error_setg(errp, "property socket-id: %u doesn't match set apic-id:"
- " 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id, topo.pkg_id);
- return;
- }
- cpu->socket_id = topo.pkg_id;
-
- if (cpu->core_id != -1 && cpu->core_id != topo.core_id) {
- error_setg(errp, "property core-id: %u doesn't match set apic-id:"
- " 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id, topo.core_id);
- return;
- }
- cpu->core_id = topo.core_id;
-
- if (cpu->thread_id != -1 && cpu->thread_id != topo.smt_id) {
- error_setg(errp, "property thread-id: %u doesn't match set apic-id:"
- " 0x%x (thread-id: %u)", cpu->thread_id, cpu->apic_id, topo.smt_id);
- return;
- }
- cpu->thread_id = topo.smt_id;
-
- cs = CPU(cpu);
- cs->cpu_index = idx;
-}
-
-static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
- pc_cpu_pre_plug(hotplug_dev, dev, errp);
- }
-}
-
static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
@@ -1970,8 +1729,6 @@ static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
pc_dimm_unplug_request(hotplug_dev, dev, errp);
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
- pc_cpu_unplug_request_cb(hotplug_dev, dev, errp);
} else {
error_setg(errp, "acpi: device unplug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -1983,8 +1740,6 @@ static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
pc_dimm_unplug(hotplug_dev, dev, errp);
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
- pc_cpu_unplug_cb(hotplug_dev, dev, errp);
} else {
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -2137,7 +1892,7 @@ static void pc_machine_initfn(Object *obj)
pc_machine_get_hotplug_memory_region_size,
NULL, NULL, NULL, &error_abort);
- pcms->max_ram_below_4g = 0; /* use default */
+ pcms->max_ram_below_4g = 1ULL << 32; /* 4G */
object_property_add(obj, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
pc_machine_get_max_ram_below_4g,
pc_machine_set_max_ram_below_4g,
@@ -2208,72 +1963,11 @@ static CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *machine)
return list;
}
-static HotpluggableCPUList *pc_query_hotpluggable_cpus(MachineState *machine)
-{
- int i;
- CPUState *cpu;
- HotpluggableCPUList *head = NULL;
- PCMachineState *pcms = PC_MACHINE(machine);
- const char *cpu_type;
-
- cpu = pcms->possible_cpus->cpus[0].cpu;
- assert(cpu); /* BSP is always present */
- cpu_type = object_class_get_name(OBJECT_CLASS(CPU_GET_CLASS(cpu)));
-
- for (i = 0; i < pcms->possible_cpus->len; i++) {
- X86CPUTopoInfo topo;
- HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
- HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
- CpuInstanceProperties *cpu_props = g_new0(typeof(*cpu_props), 1);
- const uint32_t apic_id = pcms->possible_cpus->cpus[i].arch_id;
-
- x86_topo_ids_from_apicid(apic_id, smp_cores, smp_threads, &topo);
-
- cpu_item->type = g_strdup(cpu_type);
- cpu_item->vcpus_count = 1;
- cpu_props->has_socket_id = true;
- cpu_props->socket_id = topo.pkg_id;
- cpu_props->has_core_id = true;
- cpu_props->core_id = topo.core_id;
- cpu_props->has_thread_id = true;
- cpu_props->thread_id = topo.smt_id;
- cpu_item->props = cpu_props;
-
- cpu = pcms->possible_cpus->cpus[i].cpu;
- if (cpu) {
- cpu_item->has_qom_path = true;
- cpu_item->qom_path = object_get_canonical_path(OBJECT(cpu));
- }
-
- list_item->value = cpu_item;
- list_item->next = head;
- head = list_item;
- }
- return head;
-}
-
-static void x86_nmi(NMIState *n, int cpu_index, Error **errp)
-{
- /* cpu index isn't used */
- CPUState *cs;
-
- CPU_FOREACH(cs) {
- X86CPU *cpu = X86_CPU(cs);
-
- if (!cpu->apic_state) {
- cpu_interrupt(cs, CPU_INTERRUPT_NMI);
- } else {
- apic_deliver_nmi(cpu->apic_state);
- }
- }
-}
-
static void pc_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
PCMachineClass *pcmc = PC_MACHINE_CLASS(oc);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
- NMIClass *nc = NMI_CLASS(oc);
pcmc->get_hotplug_handler = mc->get_hotplug_handler;
pcmc->pci_enabled = true;
@@ -2292,16 +1986,13 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
mc->get_hotplug_handler = pc_get_hotpug_handler;
mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id;
mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids;
- mc->query_hotpluggable_cpus = pc_query_hotpluggable_cpus;
mc->default_boot_order = "cad";
mc->hot_add_cpu = pc_hot_add_cpu;
mc->max_cpus = 255;
mc->reset = pc_machine_reset;
- hc->pre_plug = pc_machine_device_pre_plug_cb;
hc->plug = pc_machine_device_plug_cb;
hc->unplug_request = pc_machine_device_unplug_request_cb;
hc->unplug = pc_machine_device_unplug_cb;
- nc->nmi_monitor_handler = x86_nmi;
}
static const TypeInfo pc_machine_info = {
@@ -2314,7 +2005,6 @@ static const TypeInfo pc_machine_info = {
.class_init = pc_machine_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_HOTPLUG_HANDLER },
- { TYPE_NMI },
{ }
},
};
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index a07dc816b..7f50116bc 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -23,6 +23,7 @@
*/
#include "qemu/osdep.h"
+#include <glib.h>
#include "hw/hw.h"
#include "hw/loader.h"
@@ -86,65 +87,42 @@ static void pc_init1(MachineState *machine,
MemoryRegion *rom_memory;
ram_addr_t lowmem;
- /*
- * Calculate ram split, for memory below and above 4G. It's a bit
- * complicated for backward compatibility reasons ...
- *
- * - Traditional split is 3.5G (lowmem = 0xe0000000). This is the
- * default value for max_ram_below_4g now.
- *
- * - Then, to gigabyte align the memory, we move the split to 3G
- * (lowmem = 0xc0000000). But only in case we have to split in
- * the first place, i.e. ram_size is larger than (traditional)
- * lowmem. And for new machine types (gigabyte_align = true)
- * only, for live migration compatibility reasons.
- *
- * - Next the max-ram-below-4g option was added, which allowed to
- * reduce lowmem to a smaller value, to allow a larger PCI I/O
- * window below 4G. qemu doesn't enforce gigabyte alignment here,
- * but prints a warning.
- *
- * - Finally max-ram-below-4g got updated to also allow raising lowmem,
- * so legacy non-PAE guests can get as much memory as possible in
- * the 32bit address space below 4G.
- *
- * - Note that Xen has its own ram setp code in xen_ram_init(),
- * called via xen_hvm_init().
- *
- * Examples:
- * qemu -M pc-1.7 -m 4G (old default) -> 3584M low, 512M high
- * qemu -M pc -m 4G (new default) -> 3072M low, 1024M high
- * qemu -M pc,max-ram-below-4g=2G -m 4G -> 2048M low, 2048M high
- * qemu -M pc,max-ram-below-4g=4G -m 3968M -> 3968M low (=4G-128M)
+ /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory).
+ * If it doesn't, we need to split it in chunks below and above 4G.
+ * In any case, try to make sure that guest addresses aligned at
+ * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
+ * For old machine types, use whatever split we used historically to avoid
+ * breaking migration.
*/
- if (xen_enabled()) {
- xen_hvm_init(pcms, &ram_memory);
+ if (machine->ram_size >= 0xe0000000) {
+ lowmem = pcmc->gigabyte_align ? 0xc0000000 : 0xe0000000;
} else {
- if (!pcms->max_ram_below_4g) {
- pcms->max_ram_below_4g = 0xe0000000; /* default: 3.5G */
- }
+ lowmem = 0xe0000000;
+ }
+
+ /* Handle the machine opt max-ram-below-4g. It is basically doing
+ * min(qemu limit, user limit).
+ */
+ if (lowmem > pcms->max_ram_below_4g) {
lowmem = pcms->max_ram_below_4g;
- if (machine->ram_size >= pcms->max_ram_below_4g) {
- if (pcmc->gigabyte_align) {
- if (lowmem > 0xc0000000) {
- lowmem = 0xc0000000;
- }
- if (lowmem & ((1ULL << 30) - 1)) {
- error_report("Warning: Large machine and max_ram_below_4g "
- "(%" PRIu64 ") not a multiple of 1G; "
- "possible bad performance.",
- pcms->max_ram_below_4g);
- }
- }
+ if (machine->ram_size - lowmem > lowmem &&
+ lowmem & ((1ULL << 30) - 1)) {
+ error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64
+ ") not a multiple of 1G; possible bad performance.",
+ pcms->max_ram_below_4g);
}
+ }
- if (machine->ram_size >= lowmem) {
- pcms->above_4g_mem_size = machine->ram_size - lowmem;
- pcms->below_4g_mem_size = lowmem;
- } else {
- pcms->above_4g_mem_size = 0;
- pcms->below_4g_mem_size = machine->ram_size;
- }
+ if (machine->ram_size >= lowmem) {
+ pcms->above_4g_mem_size = machine->ram_size - lowmem;
+ pcms->below_4g_mem_size = lowmem;
+ } else {
+ pcms->above_4g_mem_size = 0;
+ pcms->below_4g_mem_size = machine->ram_size;
+ }
+
+ if (xen_enabled()) {
+ xen_hvm_init(pcms, &ram_memory);
}
pc_cpus_init(pcms);
@@ -268,7 +246,7 @@ static void pc_init1(MachineState *machine,
pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
- if (pcmc->pci_enabled && machine_usb(machine)) {
+ if (pcmc->pci_enabled && usb_enabled()) {
pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
}
@@ -438,27 +416,13 @@ static void pc_i440fx_machine_options(MachineClass *m)
m->default_display = "std";
}
-static void pc_i440fx_2_7_machine_options(MachineClass *m)
+static void pc_i440fx_2_6_machine_options(MachineClass *m)
{
pc_i440fx_machine_options(m);
m->alias = "pc";
m->is_default = 1;
}
-DEFINE_I440FX_MACHINE(v2_7, "pc-i440fx-2.7", NULL,
- pc_i440fx_2_7_machine_options);
-
-
-static void pc_i440fx_2_6_machine_options(MachineClass *m)
-{
- PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
- pc_i440fx_2_7_machine_options(m);
- m->is_default = 0;
- m->alias = NULL;
- pcmc->legacy_cpu_hotplug = true;
- SET_MACHINE_COMPAT(m, PC_COMPAT_2_6);
-}
-
DEFINE_I440FX_MACHINE(v2_6, "pc-i440fx-2.6", NULL,
pc_i440fx_2_6_machine_options);
@@ -467,6 +431,8 @@ static void pc_i440fx_2_5_machine_options(MachineClass *m)
{
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_i440fx_2_6_machine_options(m);
+ m->alias = NULL;
+ m->is_default = 0;
pcmc->save_tsc_khz = false;
m->legacy_fw_cfg_order = 1;
SET_MACHINE_COMPAT(m, PC_COMPAT_2_5);
@@ -616,7 +582,7 @@ DEFINE_I440FX_MACHINE(v1_4, "pc-i440fx-1.4", pc_compat_1_4,
#define PC_COMPAT_1_3 \
- PC_CPU_MODEL_IDS("1.3.0") \
+ PC_COMPAT_1_4 \
{\
.driver = "usb-tablet",\
.property = "usb_version",\
@@ -648,7 +614,7 @@ DEFINE_I440FX_MACHINE(v1_3, "pc-1.3", pc_compat_1_3,
#define PC_COMPAT_1_2 \
- PC_CPU_MODEL_IDS("1.2.0") \
+ PC_COMPAT_1_3 \
{\
.driver = "nec-usb-xhci",\
.property = "msi",\
@@ -687,7 +653,7 @@ DEFINE_I440FX_MACHINE(v1_2, "pc-1.2", pc_compat_1_2,
#define PC_COMPAT_1_1 \
- PC_CPU_MODEL_IDS("1.1.0") \
+ PC_COMPAT_1_2 \
{\
.driver = "virtio-scsi-pci",\
.property = "hotplug",\
@@ -730,7 +696,7 @@ DEFINE_I440FX_MACHINE(v1_1, "pc-1.1", pc_compat_1_2,
#define PC_COMPAT_1_0 \
- PC_CPU_MODEL_IDS("1.0") \
+ PC_COMPAT_1_1 \
{\
.driver = TYPE_ISA_FDC,\
.property = "check_media_rate",\
@@ -761,7 +727,7 @@ DEFINE_I440FX_MACHINE(v1_0, "pc-1.0", pc_compat_1_2,
#define PC_COMPAT_0_15 \
- PC_CPU_MODEL_IDS("0.15")
+ PC_COMPAT_1_0
static void pc_i440fx_0_15_machine_options(MachineClass *m)
{
@@ -775,7 +741,7 @@ DEFINE_I440FX_MACHINE(v0_15, "pc-0.15", pc_compat_1_2,
#define PC_COMPAT_0_14 \
- PC_CPU_MODEL_IDS("0.14") \
+ PC_COMPAT_0_15 \
{\
.driver = "virtio-blk-pci",\
.property = "event_idx",\
@@ -814,7 +780,7 @@ DEFINE_I440FX_MACHINE(v0_14, "pc-0.14", pc_compat_1_2,
#define PC_COMPAT_0_13 \
- PC_CPU_MODEL_IDS("0.13") \
+ PC_COMPAT_0_14 \
{\
.driver = TYPE_PCI_DEVICE,\
.property = "command_serr_enable",\
@@ -851,7 +817,7 @@ DEFINE_I440FX_MACHINE(v0_13, "pc-0.13", pc_compat_0_13,
#define PC_COMPAT_0_12 \
- PC_CPU_MODEL_IDS("0.12") \
+ PC_COMPAT_0_13 \
{\
.driver = "virtio-serial-pci",\
.property = "max_ports",\
@@ -886,7 +852,7 @@ DEFINE_I440FX_MACHINE(v0_12, "pc-0.12", pc_compat_0_13,
#define PC_COMPAT_0_11 \
- PC_CPU_MODEL_IDS("0.11") \
+ PC_COMPAT_0_12 \
{\
.driver = "virtio-blk-pci",\
.property = "vectors",\
@@ -917,7 +883,7 @@ DEFINE_I440FX_MACHINE(v0_11, "pc-0.11", pc_compat_0_13,
#define PC_COMPAT_0_10 \
- PC_CPU_MODEL_IDS("0.10") \
+ PC_COMPAT_0_11 \
{\
.driver = "virtio-blk-pci",\
.property = "class",\
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index c0b996192..04aae8958 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -60,7 +60,6 @@ static void pc_q35_init(MachineState *machine)
PCIHostState *phb;
PCIBus *host_bus;
PCIDevice *lpc;
- DeviceState *lpc_dev;
BusState *idebus[MAX_SATA_PORTS];
ISADevice *rtc_state;
MemoryRegion *system_io = get_system_io();
@@ -94,9 +93,6 @@ static void pc_q35_init(MachineState *machine)
/* Handle the machine opt max-ram-below-4g. It is basically doing
* min(qemu limit, user limit).
*/
- if (!pcms->max_ram_below_4g) {
- pcms->max_ram_below_4g = 1ULL << 32; /* default: 4G */;
- }
if (lowmem > pcms->max_ram_below_4g) {
lowmem = pcms->max_ram_below_4g;
if (machine->ram_size - lowmem > lowmem &&
@@ -163,22 +159,17 @@ static void pc_q35_init(MachineState *machine)
q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));
object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host), NULL);
- object_property_set_link(OBJECT(q35_host), OBJECT(ram_memory),
- MCH_HOST_PROP_RAM_MEM, NULL);
- object_property_set_link(OBJECT(q35_host), OBJECT(pci_memory),
- MCH_HOST_PROP_PCI_MEM, NULL);
- object_property_set_link(OBJECT(q35_host), OBJECT(get_system_memory()),
- MCH_HOST_PROP_SYSTEM_MEM, NULL);
- object_property_set_link(OBJECT(q35_host), OBJECT(system_io),
- MCH_HOST_PROP_IO_MEM, NULL);
- object_property_set_int(OBJECT(q35_host), pcms->below_4g_mem_size,
- PCI_HOST_BELOW_4G_MEM_SIZE, NULL);
- object_property_set_int(OBJECT(q35_host), pcms->above_4g_mem_size,
- PCI_HOST_ABOVE_4G_MEM_SIZE, NULL);
+ q35_host->mch.ram_memory = ram_memory;
+ q35_host->mch.pci_address_space = pci_memory;
+ q35_host->mch.system_memory = get_system_memory();
+ q35_host->mch.address_space_io = system_io;
+ q35_host->mch.below_4g_mem_size = pcms->below_4g_mem_size;
+ q35_host->mch.above_4g_mem_size = pcms->above_4g_mem_size;
/* pci */
qdev_init_nofail(DEVICE(q35_host));
phb = PCI_HOST_BRIDGE(q35_host);
host_bus = phb->bus;
+ pcms->bus = phb->bus;
/* create ISA bus */
lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
ICH9_LPC_FUNC), true,
@@ -193,15 +184,16 @@ static void pc_q35_init(MachineState *machine)
PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
ich9_lpc = ICH9_LPC_DEVICE(lpc);
- lpc_dev = DEVICE(lpc);
- for (i = 0; i < GSI_NUM_PINS; i++) {
- qdev_connect_gpio_out_named(lpc_dev, ICH9_GPIO_GSI, i, gsi[i]);
- }
+ ich9_lpc->pic = gsi;
+ ich9_lpc->ioapic = gsi_state->ioapic_irq;
pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
ICH9_LPC_NB_PIRQS);
pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
isa_bus = ich9_lpc->isa_bus;
+ /*end early*/
+ isa_bus_irqs(isa_bus, gsi);
+
if (kvm_pic_in_kernel()) {
i8259 = kvm_i8259_init(isa_bus);
} else if (xen_enabled()) {
@@ -242,7 +234,7 @@ static void pc_q35_init(MachineState *machine)
ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports);
ahci_ide_create_devs(ahci, hd);
- if (machine_usb(machine)) {
+ if (usb_enabled()) {
/* Should we create 6 UHCI according to ich9 spec? */
ehci_create_ich9_with_companions(host_bus, 0x1d);
}
@@ -289,27 +281,14 @@ static void pc_q35_machine_options(MachineClass *m)
m->default_machine_opts = "firmware=bios-256k.bin";
m->default_display = "std";
m->no_floppy = 1;
- m->has_dynamic_sysbus = true;
}
-static void pc_q35_2_7_machine_options(MachineClass *m)
+static void pc_q35_2_6_machine_options(MachineClass *m)
{
pc_q35_machine_options(m);
m->alias = "q35";
}
-DEFINE_Q35_MACHINE(v2_7, "pc-q35-2.7", NULL,
- pc_q35_2_7_machine_options);
-
-static void pc_q35_2_6_machine_options(MachineClass *m)
-{
- PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
- pc_q35_2_7_machine_options(m);
- m->alias = NULL;
- pcmc->legacy_cpu_hotplug = true;
- SET_MACHINE_COMPAT(m, PC_COMPAT_2_6);
-}
-
DEFINE_Q35_MACHINE(v2_6, "pc-q35-2.6", NULL,
pc_q35_2_6_machine_options);
@@ -317,6 +296,7 @@ static void pc_q35_2_5_machine_options(MachineClass *m)
{
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_q35_2_6_machine_options(m);
+ m->alias = NULL;
pcmc->save_tsc_khz = false;
m->legacy_fw_cfg_order = 1;
SET_MACHINE_COMPAT(m, PC_COMPAT_2_5);
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
deleted file mode 100644
index 7735e46ea..000000000
--- a/hw/i386/trace-events
+++ /dev/null
@@ -1,15 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/i386/xen/xen_platform.c
-xen_platform_log(char *s) "xen platform: %s"
-
-# hw/i386/xen/xen_pvdevice.c
-xen_pv_mmio_read(uint64_t addr) "WARNING: read from Xen PV Device MMIO space (address %"PRIx64")"
-xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (address %"PRIx64")"
-
-# hw/i386/pc.c
-mhp_pc_dimm_assigned_slot(int slot) "0x%d"
-mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
-
-# hw/i386/x86-iommu.c
-x86_iommu_iec_notify(bool global, uint32_t index, uint32_t mask) "Notify IEC invalidation: global=%d index=%" PRIu32 " mask=%" PRIu32
diff --git a/hw/i386/x86-iommu.c b/hw/i386/x86-iommu.c
deleted file mode 100644
index ce26b2a71..000000000
--- a/hw/i386/x86-iommu.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * QEMU emulation of common X86 IOMMU
- *
- * 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/>.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "hw/boards.h"
-#include "hw/i386/x86-iommu.h"
-#include "qemu/error-report.h"
-#include "trace.h"
-
-void x86_iommu_iec_register_notifier(X86IOMMUState *iommu,
- iec_notify_fn fn, void *data)
-{
- IEC_Notifier *notifier = g_new0(IEC_Notifier, 1);
-
- notifier->iec_notify = fn;
- notifier->private = data;
-
- QLIST_INSERT_HEAD(&iommu->iec_notifiers, notifier, list);
-}
-
-void x86_iommu_iec_notify_all(X86IOMMUState *iommu, bool global,
- uint32_t index, uint32_t mask)
-{
- IEC_Notifier *notifier;
-
- trace_x86_iommu_iec_notify(global, index, mask);
-
- QLIST_FOREACH(notifier, &iommu->iec_notifiers, list) {
- if (notifier->iec_notify) {
- notifier->iec_notify(notifier->private, global,
- index, mask);
- }
- }
-}
-
-/* Default X86 IOMMU device */
-static X86IOMMUState *x86_iommu_default = NULL;
-
-static void x86_iommu_set_default(X86IOMMUState *x86_iommu)
-{
- assert(x86_iommu);
-
- if (x86_iommu_default) {
- error_report("QEMU does not support multiple vIOMMUs "
- "for x86 yet.");
- exit(1);
- }
-
- x86_iommu_default = x86_iommu;
-}
-
-X86IOMMUState *x86_iommu_get_default(void)
-{
- return x86_iommu_default;
-}
-
-static void x86_iommu_realize(DeviceState *dev, Error **errp)
-{
- X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(dev);
- X86IOMMUClass *x86_class = X86_IOMMU_GET_CLASS(dev);
- QLIST_INIT(&x86_iommu->iec_notifiers);
- if (x86_class->realize) {
- x86_class->realize(dev, errp);
- }
- x86_iommu_set_default(X86_IOMMU_DEVICE(dev));
-}
-
-static void x86_iommu_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = x86_iommu_realize;
-}
-
-static bool x86_iommu_intremap_prop_get(Object *o, Error **errp)
-{
- X86IOMMUState *s = X86_IOMMU_DEVICE(o);
- return s->intr_supported;
-}
-
-static void x86_iommu_intremap_prop_set(Object *o, bool value, Error **errp)
-{
- X86IOMMUState *s = X86_IOMMU_DEVICE(o);
- s->intr_supported = value;
-}
-
-static void x86_iommu_instance_init(Object *o)
-{
- X86IOMMUState *s = X86_IOMMU_DEVICE(o);
-
- /* By default, do not support IR */
- s->intr_supported = false;
- object_property_add_bool(o, "intremap", x86_iommu_intremap_prop_get,
- x86_iommu_intremap_prop_set, NULL);
-}
-
-static const TypeInfo x86_iommu_info = {
- .name = TYPE_X86_IOMMU_DEVICE,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_init = x86_iommu_instance_init,
- .instance_size = sizeof(X86IOMMUState),
- .class_init = x86_iommu_class_init,
- .class_size = sizeof(X86IOMMUClass),
- .abstract = true,
-};
-
-static void x86_iommu_register_types(void)
-{
- type_register_static(&x86_iommu_info);
-}
-
-type_init(x86_iommu_register_types)
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index f3438ad78..a1e651635 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -22,17 +22,17 @@
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/pci/msi.h"
-#include "hw/i386/pc.h"
-#include "hw/pci/pci.h"
+#include <hw/hw.h>
+#include <hw/pci/msi.h>
+#include <hw/i386/pc.h>
+#include <hw/pci/pci.h>
#include "qemu/error-report.h"
#include "sysemu/block-backend.h"
#include "sysemu/dma.h"
-#include "hw/ide/internal.h"
-#include "hw/ide/pci.h"
-#include "hw/ide/ahci.h"
+#include "internal.h"
+#include <hw/ide/pci.h>
+#include <hw/ide/ahci.h>
#define DEBUG_AHCI 0
@@ -1007,8 +1007,7 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs)
dma_acct_start(ide_state->blk, &ncq_tfs->acct,
&ncq_tfs->sglist, BLOCK_ACCT_READ);
ncq_tfs->aiocb = dma_blk_read(ide_state->blk, &ncq_tfs->sglist,
- ncq_tfs->lba << BDRV_SECTOR_BITS,
- ncq_cb, ncq_tfs);
+ ncq_tfs->lba, ncq_cb, ncq_tfs);
break;
case WRITE_FPDMA_QUEUED:
DPRINTF(port, "NCQ writing %d sectors to LBA %"PRId64", tag %d\n",
@@ -1020,8 +1019,7 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs)
dma_acct_start(ide_state->blk, &ncq_tfs->acct,
&ncq_tfs->sglist, BLOCK_ACCT_WRITE);
ncq_tfs->aiocb = dma_blk_write(ide_state->blk, &ncq_tfs->sglist,
- ncq_tfs->lba << BDRV_SECTOR_BITS,
- ncq_cb, ncq_tfs);
+ ncq_tfs->lba, ncq_cb, ncq_tfs);
break;
default:
DPRINTF(port, "error: unsupported NCQ command (0x%02x) received\n",
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
new file mode 100644
index 000000000..bc777ed5c
--- /dev/null
+++ b/hw/ide/ahci.h
@@ -0,0 +1,405 @@
+/*
+ * 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 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>
+
+#define AHCI_MEM_BAR_SIZE 0x1000
+#define AHCI_MAX_PORTS 32
+#define AHCI_MAX_SG 168 /* hardware max is 64K */
+#define AHCI_DMA_BOUNDARY 0xffffffff
+#define AHCI_USE_CLUSTERING 0
+#define AHCI_MAX_CMDS 32
+#define AHCI_CMD_SZ 32
+#define AHCI_CMD_SLOT_SZ (AHCI_MAX_CMDS * AHCI_CMD_SZ)
+#define AHCI_RX_FIS_SZ 256
+#define AHCI_CMD_TBL_CDB 0x40
+#define AHCI_CMD_TBL_HDR_SZ 0x80
+#define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16))
+#define AHCI_CMD_TBL_AR_SZ (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS)
+#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
+ AHCI_RX_FIS_SZ)
+
+#define AHCI_IRQ_ON_SG (1U << 31)
+#define AHCI_CMD_ATAPI (1 << 5)
+#define AHCI_CMD_WRITE (1 << 6)
+#define AHCI_CMD_PREFETCH (1 << 7)
+#define AHCI_CMD_RESET (1 << 8)
+#define AHCI_CMD_CLR_BUSY (1 << 10)
+
+#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */
+#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */
+#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */
+
+/* global controller registers */
+#define HOST_CAP 0x00 /* host capabilities */
+#define HOST_CTL 0x04 /* global host control */
+#define HOST_IRQ_STAT 0x08 /* interrupt status */
+#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */
+#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */
+
+/* HOST_CTL bits */
+#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */
+#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */
+#define HOST_CTL_AHCI_EN (1U << 31) /* AHCI enabled */
+
+/* HOST_CAP bits */
+#define HOST_CAP_SSC (1 << 14) /* Slumber capable */
+#define HOST_CAP_AHCI (1 << 18) /* AHCI only */
+#define HOST_CAP_CLO (1 << 24) /* Command List Override support */
+#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */
+#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */
+#define HOST_CAP_64 (1U << 31) /* PCI DAC (64-bit DMA) support */
+
+/* registers for each SATA port */
+#define PORT_LST_ADDR 0x00 /* command list DMA addr */
+#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */
+#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */
+#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */
+#define PORT_IRQ_STAT 0x10 /* interrupt status */
+#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */
+#define PORT_CMD 0x18 /* port command */
+#define PORT_TFDATA 0x20 /* taskfile data */
+#define PORT_SIG 0x24 /* device TF signature */
+#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */
+#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */
+#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */
+#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */
+#define PORT_CMD_ISSUE 0x38 /* command issue */
+#define PORT_RESERVED 0x3c /* reserved */
+
+/* PORT_IRQ_{STAT,MASK} bits */
+#define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */
+#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
+#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */
+#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */
+#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */
+#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */
+#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */
+#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */
+
+#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */
+#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */
+#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */
+#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */
+#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */
+#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */
+#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */
+#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */
+#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */
+
+#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \
+ PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \
+ PORT_IRQ_UNK_FIS)
+#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \
+ PORT_IRQ_HBUS_DATA_ERR)
+#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \
+ PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \
+ PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
+
+/* PORT_CMD bits */
+#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */
+#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */
+#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */
+#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */
+#define PORT_CMD_CLO (1 << 3) /* Command list override */
+#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */
+#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */
+#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */
+
+#define PORT_CMD_ICC_MASK (0xfU << 28) /* i/f ICC state mask */
+#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */
+#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */
+#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */
+
+#define PORT_CMD_RO_MASK 0x007dffe0 /* Which CMD bits are read only? */
+
+/* ap->flags bits */
+#define AHCI_FLAG_NO_NCQ (1 << 24)
+#define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */
+#define AHCI_FLAG_HONOR_PI (1 << 26) /* honor PORTS_IMPL */
+#define AHCI_FLAG_IGN_SERR_INTERNAL (1 << 27) /* ignore SERR_INTERNAL */
+#define AHCI_FLAG_32BIT_ONLY (1 << 28) /* force 32bit */
+
+#define ATA_SRST (1 << 2) /* software reset */
+
+#define STATE_RUN 0
+#define STATE_RESET 1
+
+#define SATA_SCR_SSTATUS_DET_NODEV 0x0
+#define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3
+
+#define SATA_SCR_SSTATUS_SPD_NODEV 0x00
+#define SATA_SCR_SSTATUS_SPD_GEN1 0x10
+
+#define SATA_SCR_SSTATUS_IPM_NODEV 0x000
+#define SATA_SCR_SSTATUS_IPM_ACTIVE 0X100
+
+#define AHCI_SCR_SCTL_DET 0xf
+
+#define SATA_FIS_TYPE_REGISTER_H2D 0x27
+#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80
+#define SATA_FIS_TYPE_REGISTER_D2H 0x34
+#define SATA_FIS_TYPE_PIO_SETUP 0x5f
+#define SATA_FIS_TYPE_SDB 0xA1
+
+#define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f
+#define AHCI_CMD_HDR_PRDT_LEN 16
+
+#define SATA_SIGNATURE_CDROM 0xeb140101
+#define SATA_SIGNATURE_DISK 0x00000101
+
+#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20
+ /* Shouldn't this be 0x2c? */
+
+#define AHCI_PORT_REGS_START_ADDR 0x100
+#define AHCI_PORT_ADDR_OFFSET_MASK 0x7f
+#define AHCI_PORT_ADDR_OFFSET_LEN 0x80
+
+#define AHCI_NUM_COMMAND_SLOTS 31
+#define AHCI_SUPPORTED_SPEED 20
+#define AHCI_SUPPORTED_SPEED_GEN1 1
+#define AHCI_VERSION_1_0 0x10000
+
+#define AHCI_PROGMODE_MAJOR_REV_1 1
+
+#define AHCI_COMMAND_TABLE_ACMD 0x40
+
+#define AHCI_PRDT_SIZE_MASK 0x3fffff
+
+#define IDE_FEATURE_DMA 1
+
+#define READ_FPDMA_QUEUED 0x60
+#define WRITE_FPDMA_QUEUED 0x61
+#define NCQ_NON_DATA 0x63
+#define RECEIVE_FPDMA_QUEUED 0x65
+#define SEND_FPDMA_QUEUED 0x64
+
+#define NCQ_FIS_FUA_MASK 0x80
+#define NCQ_FIS_RARC_MASK 0x01
+
+#define RES_FIS_DSFIS 0x00
+#define RES_FIS_PSFIS 0x20
+#define RES_FIS_RFIS 0x40
+#define RES_FIS_SDBFIS 0x58
+#define RES_FIS_UFIS 0x60
+
+#define SATA_CAP_SIZE 0x8
+#define SATA_CAP_REV 0x2
+#define SATA_CAP_BAR 0x4
+
+typedef struct AHCIControlRegs {
+ uint32_t cap;
+ uint32_t ghc;
+ uint32_t irqstatus;
+ uint32_t impl;
+ uint32_t version;
+} AHCIControlRegs;
+
+typedef struct AHCIPortRegs {
+ uint32_t lst_addr;
+ uint32_t lst_addr_hi;
+ uint32_t fis_addr;
+ uint32_t fis_addr_hi;
+ uint32_t irq_stat;
+ uint32_t irq_mask;
+ uint32_t cmd;
+ uint32_t unused0;
+ uint32_t tfdata;
+ uint32_t sig;
+ uint32_t scr_stat;
+ uint32_t scr_ctl;
+ uint32_t scr_err;
+ uint32_t scr_act;
+ uint32_t cmd_issue;
+ uint32_t reserved;
+} AHCIPortRegs;
+
+typedef struct AHCICmdHdr {
+ uint16_t opts;
+ uint16_t prdtl;
+ uint32_t status;
+ uint64_t tbl_addr;
+ uint32_t reserved[4];
+} QEMU_PACKED AHCICmdHdr;
+
+typedef struct AHCI_SG {
+ uint64_t addr;
+ uint32_t reserved;
+ uint32_t flags_size;
+} QEMU_PACKED AHCI_SG;
+
+typedef struct AHCIDevice AHCIDevice;
+
+typedef struct NCQTransferState {
+ AHCIDevice *drive;
+ BlockAIOCB *aiocb;
+ AHCICmdHdr *cmdh;
+ QEMUSGList sglist;
+ BlockAcctCookie acct;
+ uint32_t sector_count;
+ uint64_t lba;
+ uint8_t tag;
+ uint8_t cmd;
+ uint8_t slot;
+ bool used;
+ bool halt;
+} NCQTransferState;
+
+struct AHCIDevice {
+ IDEDMA dma;
+ IDEBus port;
+ int port_no;
+ uint32_t port_state;
+ uint32_t finished;
+ AHCIPortRegs port_regs;
+ struct AHCIState *hba;
+ QEMUBH *check_bh;
+ uint8_t *lst;
+ uint8_t *res_fis;
+ bool done_atapi_packet;
+ int32_t busy_slot;
+ bool init_d2h_sent;
+ AHCICmdHdr *cur_cmd;
+ NCQTransferState ncq_tfs[AHCI_MAX_CMDS];
+};
+
+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;
+
+typedef struct AHCIPCIState {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
+ AHCIState ahci;
+} AHCIPCIState;
+
+#define TYPE_ICH9_AHCI "ich9-ahci"
+
+#define ICH_AHCI(obj) \
+ OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI)
+
+extern const VMStateDescription vmstate_ahci;
+
+#define VMSTATE_AHCI(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(AHCIState), \
+ .vmsd = &vmstate_ahci, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, AHCIState), \
+}
+
+/**
+ * NCQFrame is the same as a Register H2D FIS (described in SATA 3.2),
+ * but some fields have been re-mapped and re-purposed, as seen in
+ * SATA 3.2 section 13.6.4.1 ("READ FPDMA QUEUED")
+ *
+ * cmd_fis[3], feature 7:0, becomes sector count 7:0.
+ * cmd_fis[7], device 7:0, uses bit 7 as the Force Unit Access bit.
+ * cmd_fis[11], feature 15:8, becomes sector count 15:8.
+ * cmd_fis[12], count 7:0, becomes the NCQ TAG (7:3) and RARC bit (0)
+ * cmd_fis[13], count 15:8, becomes the priority value (7:6)
+ * bytes 16-19 become an le32 "auxiliary" field.
+ */
+typedef struct NCQFrame {
+ uint8_t fis_type;
+ uint8_t c;
+ uint8_t command;
+ uint8_t sector_count_low; /* (feature 7:0) */
+ uint8_t lba0;
+ uint8_t lba1;
+ uint8_t lba2;
+ uint8_t fua; /* (device 7:0) */
+ uint8_t lba3;
+ uint8_t lba4;
+ uint8_t lba5;
+ uint8_t sector_count_high; /* (feature 15:8) */
+ uint8_t tag; /* (count 0:7) */
+ uint8_t prio; /* (count 15:8) */
+ uint8_t icc;
+ uint8_t control;
+ uint8_t aux0;
+ uint8_t aux1;
+ uint8_t aux2;
+ uint8_t aux3;
+} QEMU_PACKED NCQFrame;
+
+typedef struct SDBFIS {
+ uint8_t type;
+ uint8_t flags;
+ uint8_t status;
+ uint8_t error;
+ uint32_t payload;
+} QEMU_PACKED SDBFIS;
+
+void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports);
+void ahci_init(AHCIState *s, DeviceState *qdev);
+void ahci_uninit(AHCIState *s);
+
+void ahci_reset(AHCIState *s);
+
+void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd);
+
+#define TYPE_SYSBUS_AHCI "sysbus-ahci"
+#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI)
+
+typedef struct SysbusAHCIState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ AHCIState ahci;
+ uint32_t num_ports;
+} SysbusAHCIState;
+
+#define TYPE_ALLWINNER_AHCI "allwinner-ahci"
+#define ALLWINNER_AHCI(obj) OBJECT_CHECK(AllwinnerAHCIState, (obj), \
+ TYPE_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/hw/ide/atapi.c b/hw/ide/atapi.c
index 618967503..8592a4ae1 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -28,9 +28,6 @@
#include "hw/scsi/scsi.h"
#include "sysemu/block-backend.h"
-#define ATAPI_SECTOR_BITS (2 + BDRV_SECTOR_BITS)
-#define ATAPI_SECTOR_SIZE (1 << ATAPI_SECTOR_BITS)
-
static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
static void padstr8(uint8_t *buf, int buf_size, const char *src)
@@ -114,7 +111,7 @@ cd_read_sector_sync(IDEState *s)
{
int ret;
block_acct_start(blk_get_stats(s->blk), &s->acct,
- ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ);
+ 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
#ifdef DEBUG_IDE_ATAPI
printf("cd_read_sector_sync: lba=%d\n", s->lba);
@@ -122,12 +119,12 @@ cd_read_sector_sync(IDEState *s)
switch (s->cd_sector_size) {
case 2048:
- ret = blk_pread(s->blk, (int64_t)s->lba << ATAPI_SECTOR_BITS,
- s->io_buffer, ATAPI_SECTOR_SIZE);
+ ret = blk_read(s->blk, (int64_t)s->lba << 2,
+ s->io_buffer, 4);
break;
case 2352:
- ret = blk_pread(s->blk, (int64_t)s->lba << ATAPI_SECTOR_BITS,
- s->io_buffer + 16, ATAPI_SECTOR_SIZE);
+ ret = blk_read(s->blk, (int64_t)s->lba << 2,
+ s->io_buffer + 16, 4);
if (ret >= 0) {
cd_data_to_raw(s->io_buffer, s->lba);
}
@@ -185,7 +182,7 @@ static int cd_read_sector(IDEState *s)
s->iov.iov_base = (s->cd_sector_size == 2352) ?
s->io_buffer + 16 : s->io_buffer;
- s->iov.iov_len = ATAPI_SECTOR_SIZE;
+ s->iov.iov_len = 4 * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
#ifdef DEBUG_IDE_ATAPI
@@ -193,7 +190,7 @@ static int cd_read_sector(IDEState *s)
#endif
block_acct_start(blk_get_stats(s->blk), &s->acct,
- ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ);
+ 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
ide_buffered_readv(s, (int64_t)s->lba << 2, &s->qiov, 4,
cd_read_sector_cb, s);
@@ -439,7 +436,7 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
#endif
s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);
- s->bus->dma->iov.iov_len = n * ATAPI_SECTOR_SIZE;
+ s->bus->dma->iov.iov_len = n * 4 * 512;
qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
s->bus->dma->aiocb = ide_buffered_readv(s, (int64_t)s->lba << 2,
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 9ebb8d4fb..49294a531 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -23,15 +23,15 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/pci/pci.h"
-#include "hw/isa/isa.h"
+#include <hw/hw.h>
+#include <hw/i386/pc.h>
+#include <hw/pci/pci.h>
+#include <hw/isa/isa.h>
#include "sysemu/block-backend.h"
#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
-#include "hw/ide/pci.h"
+#include <hw/ide/pci.h>
/* CMD646 specific */
#define CFR 0x50
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 45b6df132..aa11f134d 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -23,10 +23,10 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/pci/pci.h"
-#include "hw/isa/isa.h"
+#include <hw/hw.h>
+#include <hw/i386/pc.h>
+#include <hw/pci/pci.h>
+#include <hw/isa/isa.h>
#include "qemu/error-report.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
@@ -35,7 +35,7 @@
#include "sysemu/block-backend.h"
#include "qemu/cutils.h"
-#include "hw/ide/internal.h"
+#include <hw/ide/internal.h>
/* These values were based on a Seagate ST3500418AS but have been modified
to make more sense in QEMU */
@@ -423,10 +423,8 @@ static void ide_issue_trim_cb(void *opaque, int ret)
}
/* Got an entry! Submit and exit. */
- iocb->aiocb = blk_aio_pdiscard(iocb->blk,
- sector << BDRV_SECTOR_BITS,
- count << BDRV_SECTOR_BITS,
- ide_issue_trim_cb, opaque);
+ iocb->aiocb = blk_aio_discard(iocb->blk, sector, count,
+ ide_issue_trim_cb, opaque);
return;
}
@@ -443,14 +441,13 @@ static void ide_issue_trim_cb(void *opaque, int ret)
}
}
-BlockAIOCB *ide_issue_trim(
- int64_t offset, QEMUIOVector *qiov,
- BlockCompletionFunc *cb, void *cb_opaque, void *opaque)
+BlockAIOCB *ide_issue_trim(BlockBackend *blk,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+ BlockCompletionFunc *cb, void *opaque)
{
- BlockBackend *blk = opaque;
TrimAIOCB *iocb;
- iocb = blk_aio_get(&trim_aiocb_info, blk, cb, cb_opaque);
+ iocb = blk_aio_get(&trim_aiocb_info, blk, cb, opaque);
iocb->blk = blk;
iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
iocb->ret = 0;
@@ -468,20 +465,6 @@ void ide_abort_command(IDEState *s)
s->error = ABRT_ERR;
}
-static void ide_set_retry(IDEState *s)
-{
- s->bus->retry_unit = s->unit;
- s->bus->retry_sector_num = ide_get_sector(s);
- s->bus->retry_nsector = s->nsector;
-}
-
-static void ide_clear_retry(IDEState *s)
-{
- s->bus->retry_unit = -1;
- s->bus->retry_sector_num = 0;
- s->bus->retry_nsector = 0;
-}
-
/* prepare data transfer and tell what to do after */
void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
EndTransferFunc *end_transfer_func)
@@ -489,7 +472,6 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
s->end_transfer_func = end_transfer_func;
s->data_ptr = buf;
s->data_end = buf + size;
- ide_set_retry(s);
if (!(s->status & ERR_STAT)) {
s->status |= DRQ_STAT;
}
@@ -634,8 +616,8 @@ BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num,
req->iov.iov_len = iov->size;
qemu_iovec_init_external(&req->qiov, &req->iov, 1);
- aioreq = blk_aio_preadv(s->blk, sector_num << BDRV_SECTOR_BITS,
- &req->qiov, 0, ide_buffered_readv_cb, req);
+ aioreq = blk_aio_readv(s->blk, sector_num, &req->qiov, nb_sectors,
+ ide_buffered_readv_cb, req);
QLIST_INSERT_HEAD(&s->buffered_requests, req, list);
return aioreq;
@@ -773,7 +755,9 @@ void dma_buf_commit(IDEState *s, uint32_t tx_bytes)
void ide_set_inactive(IDEState *s, bool more)
{
s->bus->dma->aiocb = NULL;
- ide_clear_retry(s);
+ s->bus->retry_unit = -1;
+ s->bus->retry_sector_num = 0;
+ s->bus->retry_nsector = 0;
if (s->bus->dma->ops->set_inactive) {
s->bus->dma->ops->set_inactive(s->bus->dma, more);
}
@@ -815,7 +799,6 @@ static void ide_dma_cb(void *opaque, int ret)
IDEState *s = opaque;
int n;
int64_t sector_num;
- uint64_t offset;
bool stay_active = false;
if (ret == -ECANCELED) {
@@ -878,20 +861,18 @@ static void ide_dma_cb(void *opaque, int ret)
return;
}
- offset = sector_num << BDRV_SECTOR_BITS;
switch (s->dma_cmd) {
case IDE_DMA_READ:
- s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, offset,
+ s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, sector_num,
ide_dma_cb, s);
break;
case IDE_DMA_WRITE:
- s->bus->dma->aiocb = dma_blk_write(s->blk, &s->sg, offset,
+ s->bus->dma->aiocb = dma_blk_write(s->blk, &s->sg, sector_num,
ide_dma_cb, s);
break;
case IDE_DMA_TRIM:
- s->bus->dma->aiocb = dma_blk_io(blk_get_aio_context(s->blk),
- &s->sg, offset,
- ide_issue_trim, s->blk, ide_dma_cb, s,
+ s->bus->dma->aiocb = dma_blk_io(s->blk, &s->sg, sector_num,
+ ide_issue_trim, ide_dma_cb, s,
DMA_DIRECTION_TO_DEVICE);
break;
default:
@@ -931,7 +912,9 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
void ide_start_dma(IDEState *s, BlockCompletionFunc *cb)
{
s->io_buffer_index = 0;
- ide_set_retry(s);
+ s->bus->retry_unit = s->unit;
+ s->bus->retry_sector_num = ide_get_sector(s);
+ s->bus->retry_nsector = s->nsector;
if (s->bus->dma->ops->start_dma) {
s->bus->dma->ops->start_dma(s->bus->dma, s, cb);
}
@@ -1025,8 +1008,8 @@ static void ide_sector_write(IDEState *s)
block_acct_start(blk_get_stats(s->blk), &s->acct,
n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE);
- s->pio_aiocb = blk_aio_pwritev(s->blk, sector_num << BDRV_SECTOR_BITS,
- &s->qiov, 0, ide_sector_write_cb, s);
+ s->pio_aiocb = blk_aio_writev(s->blk, sector_num, &s->qiov, n,
+ ide_sector_write_cb, s);
}
static void ide_flush_cb(void *opaque, int ret)
@@ -1061,7 +1044,6 @@ static void ide_flush_cache(IDEState *s)
}
s->status |= BUSY_STAT;
- ide_set_retry(s);
block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH);
s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
}
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 459916977..0a13334ba 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -61,15 +61,16 @@
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/pci/msi.h"
-#include "hw/i386/pc.h"
-#include "hw/pci/pci.h"
-#include "hw/isa/isa.h"
+#include <hw/hw.h>
+#include <hw/pci/msi.h>
+#include <hw/i386/pc.h>
+#include <hw/pci/pci.h>
+#include <hw/isa/isa.h>
#include "sysemu/block-backend.h"
#include "sysemu/dma.h"
-#include "hw/ide/pci.h"
-#include "hw/ide/ahci.h"
+
+#include <hw/ide/pci.h>
+#include <hw/ide/ahci.h>
#define ICH9_MSI_CAP_OFFSET 0x80
#define ICH9_SATA_CAP_OFFSET 0xA8
@@ -110,7 +111,6 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
int sata_cap_offset;
uint8_t *sata_cap;
d = ICH_AHCI(dev);
- int ret;
ahci_realize(&d->ahci, DEVICE(dev), pci_get_address_space(dev), 6);
@@ -146,10 +146,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
/* Although the AHCI 1.3 specification states that the first capability
* should be PMCAP, the Intel ICH9 data sheet specifies that the ICH9
* AHCI device puts the MSI capability first, pointing to 0x80. */
- ret = msi_init(dev, ICH9_MSI_CAP_OFFSET, 1, true, false, NULL);
- /* Any error other than -ENOTSUP(board's MSI support is broken)
- * is a programming error. Fall back to INTx silently on -ENOTSUP */
- assert(!ret || ret == -ENOTSUP);
+ msi_init(dev, ICH9_MSI_CAP_OFFSET, 1, true, false);
}
static void pci_ich9_uninit(PCIDevice *dev)
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
new file mode 100644
index 000000000..d2c458f57
--- /dev/null
+++ b/hw/ide/internal.h
@@ -0,0 +1,635 @@
+#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 <hw/ide.h>
+#include <hw/isa/isa.h>
+#include "sysemu/dma.h"
+#include "sysemu/sysemu.h"
+#include "hw/block/block.h"
+#include "block/scsi.h"
+
+/* debug IDE devices */
+//#define DEBUG_IDE
+//#define DEBUG_IDE_ATAPI
+//#define DEBUG_AIO
+#define USE_DMA_CDROM
+
+typedef struct IDEBus IDEBus;
+typedef struct IDEDevice IDEDevice;
+typedef struct IDEState IDEState;
+typedef struct IDEDMA IDEDMA;
+typedef struct IDEDMAOps IDEDMAOps;
+
+#define TYPE_IDE_BUS "IDE"
+#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS)
+
+/* Bits of HD_STATUS */
+#define ERR_STAT 0x01
+#define INDEX_STAT 0x02
+#define ECC_STAT 0x04 /* Corrected error */
+#define DRQ_STAT 0x08
+#define SEEK_STAT 0x10
+#define SRV_STAT 0x10
+#define WRERR_STAT 0x20
+#define READY_STAT 0x40
+#define BUSY_STAT 0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR 0x01 /* Bad address mark */
+#define TRK0_ERR 0x02 /* couldn't find track 0 */
+#define ABRT_ERR 0x04 /* Command aborted */
+#define MCR_ERR 0x08 /* media change request */
+#define ID_ERR 0x10 /* ID field not found */
+#define MC_ERR 0x20 /* media changed */
+#define ECC_ERR 0x40 /* Uncorrectable ECC error */
+#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
+#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
+
+/* Bits of HD_NSECTOR */
+#define CD 0x01
+#define IO 0x02
+#define REL 0x04
+#define TAG_MASK 0xf8
+
+#define IDE_CMD_RESET 0x04
+#define IDE_CMD_DISABLE_IRQ 0x02
+
+/* ACS-2 T13/2015-D Table B.2 Command codes */
+#define WIN_NOP 0x00
+/* reserved 0x01..0x02 */
+#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
+/* reserved 0x04..0x05 */
+#define WIN_DSM 0x06
+/* reserved 0x07 */
+#define WIN_DEVICE_RESET 0x08
+/* reserved 0x09..0x0a */
+/* REQUEST SENSE DATA EXT 0x0B */
+/* reserved 0x0C..0x0F */
+#define WIN_RECAL 0x10 /* obsolete since ATA4 */
+/* obsolete since ATA3, retired in ATA4 0x11..0x1F */
+#define WIN_READ 0x20 /* 28-Bit */
+#define WIN_READ_ONCE 0x21 /* 28-Bit w/o retries, obsolete since ATA5 */
+/* obsolete since ATA4 0x22..0x23 */
+#define WIN_READ_EXT 0x24 /* 48-Bit */
+#define WIN_READDMA_EXT 0x25 /* 48-Bit */
+#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit, obsolete since ACS2 */
+#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */
+/* reserved 0x28 */
+#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */
+/* READ STREAM DMA EXT 0x2A */
+/* READ STREAM EXT 0x2B */
+/* reserved 0x2C..0x2E */
+/* READ LOG EXT 0x2F */
+#define WIN_WRITE 0x30 /* 28-Bit */
+#define WIN_WRITE_ONCE 0x31 /* 28-Bit w/o retries, obsolete since ATA5 */
+/* obsolete since ATA4 0x32..0x33 */
+#define WIN_WRITE_EXT 0x34 /* 48-Bit */
+#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */
+#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */
+#define WIN_SET_MAX_EXT 0x37 /* 48-Bit, obsolete since ACS2 */
+#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */
+#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */
+#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */
+/* WRITE STREAM DMA EXT 0x3A */
+/* WRITE STREAM EXT 0x3B */
+#define WIN_WRITE_VERIFY 0x3C /* 28-Bit, obsolete since ATA4 */
+/* WRITE DMA FUA EXT 0x3D */
+/* obsolete since ACS2 0x3E */
+/* WRITE LOG EXT 0x3F */
+#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */
+#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - w/o retries, obsolete since ATA5 */
+#define WIN_VERIFY_EXT 0x42 /* 48-Bit */
+/* reserved 0x43..0x44 */
+/* WRITE UNCORRECTABLE EXT 0x45 */
+/* reserved 0x46 */
+/* READ LOG DMA EXT 0x47 */
+/* reserved 0x48..0x4F */
+/* obsolete since ATA4 0x50 */
+/* CONFIGURE STREAM 0x51 */
+/* reserved 0x52..0x56 */
+/* WRITE LOG DMA EXT 0x57 */
+/* reserved 0x58..0x5A */
+/* TRUSTED NON DATA 0x5B */
+/* TRUSTED RECEIVE 0x5C */
+/* TRUSTED RECEIVE DMA 0x5D */
+/* TRUSTED SEND 0x5E */
+/* TRUSTED SEND DMA 0x5F */
+/* READ FPDMA QUEUED 0x60 */
+/* WRITE FPDMA QUEUED 0x61 */
+/* reserved 0x62->0x6F */
+#define WIN_SEEK 0x70 /* obsolete since ATA7 */
+/* reserved 0x71-0x7F */
+/* vendor specific 0x80-0x86 */
+#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */
+/* vendor specific 0x88-0x8F */
+#define WIN_DIAGNOSE 0x90
+#define WIN_SPECIFY 0x91 /* set drive geometry translation, obsolete since ATA6 */
+#define WIN_DOWNLOAD_MICROCODE 0x92
+/* DOWNLOAD MICROCODE DMA 0x93 */
+#define WIN_STANDBYNOW2 0x94 /* retired in ATA4 */
+#define WIN_IDLEIMMEDIATE2 0x95 /* force drive to become "ready", retired in ATA4 */
+#define WIN_STANDBY2 0x96 /* retired in ATA4 */
+#define WIN_SETIDLE2 0x97 /* retired in ATA4 */
+#define WIN_CHECKPOWERMODE2 0x98 /* retired in ATA4 */
+#define WIN_SLEEPNOW2 0x99 /* retired in ATA4 */
+/* vendor specific 0x9A */
+/* reserved 0x9B..0x9F */
+#define WIN_PACKETCMD 0xA0 /* Send a packet command. */
+#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */
+#define WIN_QUEUED_SERVICE 0xA2 /* obsolete since ACS2 */
+/* reserved 0xA3..0xAF */
+#define WIN_SMART 0xB0 /* self-monitoring and reporting */
+/* Device Configuration Overlay 0xB1 */
+/* reserved 0xB2..0xB3 */
+/* Sanitize Device 0xB4 */
+/* reserved 0xB5 */
+/* NV Cache 0xB6 */
+/* reserved for CFA 0xB7..0xBB */
+#define CFA_ACCESS_METADATA_STORAGE 0xB8
+/* reserved 0xBC..0xBF */
+#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */
+/* vendor specific 0xC1..0xC3 */
+#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/
+#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
+#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
+#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers, obsolete since ACS2 */
+#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */
+#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - w/o retries, obsolete since ATA5 */
+#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */
+#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - w/o retries, obsolete since ATA5 */
+#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers, obsolete since ACS2 */
+#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
+/* WRITE MULTIPLE FUA EXT 0xCE */
+/* reserved 0xCF..0xDO */
+/* CHECK MEDIA CARD TYPE 0xD1 */
+/* reserved for media card pass through 0xD2..0xD4 */
+/* reserved 0xD5..0xD9 */
+#define WIN_GETMEDIASTATUS 0xDA /* obsolete since ATA8 */
+/* obsolete since ATA3, retired in ATA4 0xDB..0xDD */
+#define WIN_DOORLOCK 0xDE /* lock door on removable drives, obsolete since ATA8 */
+#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives, obsolete since ATA8 */
+#define WIN_STANDBYNOW1 0xE0
+#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */
+#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */
+#define WIN_SETIDLE1 0xE3
+#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */
+#define WIN_CHECKPOWERMODE1 0xE5
+#define WIN_SLEEPNOW1 0xE6
+#define WIN_FLUSH_CACHE 0xE7
+#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
+/* READ BUFFER DMA 0xE9 */
+#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */
+/* WRITE BUFFER DMA 0xEB */
+#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */
+#define WIN_MEDIAEJECT 0xED /* obsolete since ATA8 */
+/* obsolete since ATA4 0xEE */
+#define WIN_SETFEATURES 0xEF /* set special drive features */
+#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature, vendor specific */
+#define WIN_SECURITY_SET_PASS 0xF1
+#define WIN_SECURITY_UNLOCK 0xF2
+#define WIN_SECURITY_ERASE_PREPARE 0xF3
+#define WIN_SECURITY_ERASE_UNIT 0xF4
+#define WIN_SECURITY_FREEZE_LOCK 0xF5
+#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP; not specified in T13! */
+#define WIN_SECURITY_DISABLE 0xF6
+/* vendor specific 0xF7 */
+#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */
+#define WIN_SET_MAX 0xF9
+/* vendor specific 0xFA..0xFF */
+
+/* set to 1 set disable mult support */
+#define MAX_MULT_SECTORS 16
+
+#define IDE_DMA_BUF_SECTORS 256
+
+/* feature values for Data Set Management */
+#define DSM_TRIM 0x01
+
+#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS)
+#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS"
+#endif
+
+/* ATAPI defines */
+
+#define ATAPI_PACKET_SIZE 12
+
+/* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+#define GPCMD_BLANK 0xa1
+#define GPCMD_CLOSE_TRACK 0x5b
+#define GPCMD_FLUSH_CACHE 0x35
+#define GPCMD_FORMAT_UNIT 0x04
+#define GPCMD_GET_CONFIGURATION 0x46
+#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
+#define GPCMD_GET_PERFORMANCE 0xac
+#define GPCMD_INQUIRY 0x12
+#define GPCMD_LOAD_UNLOAD 0xa6
+#define GPCMD_MECHANISM_STATUS 0xbd
+#define GPCMD_MODE_SELECT_10 0x55
+#define GPCMD_MODE_SENSE_10 0x5a
+#define GPCMD_PAUSE_RESUME 0x4b
+#define GPCMD_PLAY_AUDIO_10 0x45
+#define GPCMD_PLAY_AUDIO_MSF 0x47
+#define GPCMD_PLAY_AUDIO_TI 0x48
+#define GPCMD_PLAY_CD 0xbc
+#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
+#define GPCMD_READ_10 0x28
+#define GPCMD_READ_12 0xa8
+#define GPCMD_READ_CDVD_CAPACITY 0x25
+#define GPCMD_READ_CD 0xbe
+#define GPCMD_READ_CD_MSF 0xb9
+#define GPCMD_READ_DISC_INFO 0x51
+#define GPCMD_READ_DVD_STRUCTURE 0xad
+#define GPCMD_READ_FORMAT_CAPACITIES 0x23
+#define GPCMD_READ_HEADER 0x44
+#define GPCMD_READ_TRACK_RZONE_INFO 0x52
+#define GPCMD_READ_SUBCHANNEL 0x42
+#define GPCMD_READ_TOC_PMA_ATIP 0x43
+#define GPCMD_REPAIR_RZONE_TRACK 0x58
+#define GPCMD_REPORT_KEY 0xa4
+#define GPCMD_REQUEST_SENSE 0x03
+#define GPCMD_RESERVE_RZONE_TRACK 0x53
+#define GPCMD_SCAN 0xba
+#define GPCMD_SEEK 0x2b
+#define GPCMD_SEND_DVD_STRUCTURE 0xad
+#define GPCMD_SEND_EVENT 0xa2
+#define GPCMD_SEND_KEY 0xa3
+#define GPCMD_SEND_OPC 0x54
+#define GPCMD_SET_READ_AHEAD 0xa7
+#define GPCMD_SET_STREAMING 0xb6
+#define GPCMD_START_STOP_UNIT 0x1b
+#define GPCMD_STOP_PLAY_SCAN 0x4e
+#define GPCMD_TEST_UNIT_READY 0x00
+#define GPCMD_VERIFY_10 0x2f
+#define GPCMD_WRITE_10 0x2a
+#define GPCMD_WRITE_AND_VERIFY_10 0x2e
+/* This is listed as optional in ATAPI 2.6, but is (curiously)
+ * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji
+ * Table 377 as an MMC command for SCSi devices though... Most ATAPI
+ * drives support it. */
+#define GPCMD_SET_SPEED 0xbb
+/* This seems to be a SCSI specific CD-ROM opcode
+ * to play data at track/index */
+#define GPCMD_PLAYAUDIO_TI 0x48
+/*
+ * From MS Media Status Notification Support Specification. For
+ * older drives only.
+ */
+#define GPCMD_GET_MEDIA_STATUS 0xda
+#define GPCMD_MODE_SENSE_6 0x1a
+
+#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */
+#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */
+#define ATAPI_INT_REASON_REL 0x04
+#define ATAPI_INT_REASON_TAG 0xf8
+
+/* same constants as bochs */
+#define ASC_NO_SEEK_COMPLETE 0x02
+#define ASC_ILLEGAL_OPCODE 0x20
+#define ASC_LOGICAL_BLOCK_OOR 0x21
+#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
+#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
+#define ASC_INCOMPATIBLE_FORMAT 0x30
+#define ASC_MEDIUM_NOT_PRESENT 0x3a
+#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
+#define ASC_DATA_PHASE_ERROR 0x4b
+#define ASC_MEDIA_REMOVAL_PREVENTED 0x53
+
+#define CFA_NO_ERROR 0x00
+#define CFA_MISC_ERROR 0x09
+#define CFA_INVALID_COMMAND 0x20
+#define CFA_INVALID_ADDRESS 0x21
+#define CFA_ADDRESS_OVERFLOW 0x2f
+
+#define SMART_READ_DATA 0xd0
+#define SMART_READ_THRESH 0xd1
+#define SMART_ATTR_AUTOSAVE 0xd2
+#define SMART_SAVE_ATTR 0xd3
+#define SMART_EXECUTE_OFFLINE 0xd4
+#define SMART_READ_LOG 0xd5
+#define SMART_WRITE_LOG 0xd6
+#define SMART_ENABLE 0xd8
+#define SMART_DISABLE 0xd9
+#define SMART_STATUS 0xda
+
+typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind;
+
+typedef void EndTransferFunc(IDEState *);
+
+typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *);
+typedef void DMAVoidFunc(IDEDMA *);
+typedef int DMAIntFunc(IDEDMA *, int);
+typedef int32_t DMAInt32Func(IDEDMA *, int32_t len);
+typedef void DMAu32Func(IDEDMA *, uint32_t);
+typedef void DMAStopFunc(IDEDMA *, bool);
+typedef void DMARestartFunc(void *, int, RunState);
+
+struct unreported_events {
+ bool eject_request;
+ bool new_media;
+};
+
+enum ide_dma_cmd {
+ IDE_DMA_READ,
+ IDE_DMA_WRITE,
+ IDE_DMA_TRIM,
+ IDE_DMA_ATAPI,
+};
+
+#define ide_cmd_is_read(s) \
+ ((s)->dma_cmd == IDE_DMA_READ)
+
+typedef struct IDEBufferedRequest {
+ QLIST_ENTRY(IDEBufferedRequest) list;
+ struct iovec iov;
+ 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;
+ struct iovec iov;
+ 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 *start_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;
+ struct iovec iov;
+ 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;
+};
+
+#define TYPE_IDE_DEVICE "ide-device"
+#define IDE_DEVICE(obj) \
+ OBJECT_CHECK(IDEDevice, (obj), TYPE_IDE_DEVICE)
+#define IDE_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(IDEDeviceClass, (klass), TYPE_IDE_DEVICE)
+#define IDE_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(IDEDeviceClass, (obj), TYPE_IDE_DEVICE)
+
+typedef struct IDEDeviceClass {
+ DeviceClass parent_class;
+ int (*init)(IDEDevice *dev);
+} IDEDeviceClass;
+
+struct IDEDevice {
+ DeviceState qdev;
+ uint32_t unit;
+ BlockConf conf;
+ int chs_trans;
+ char *version;
+ char *serial;
+ char *model;
+ uint64_t wwn;
+};
+
+/* These are used for the error_status field of IDEBus */
+#define IDE_RETRY_MASK 0xf8
+#define IDE_RETRY_DMA 0x08
+#define IDE_RETRY_PIO 0x10
+#define IDE_RETRY_ATAPI 0x20 /* reused IDE_RETRY_READ bit */
+#define IDE_RETRY_READ 0x20
+#define IDE_RETRY_FLUSH 0x40
+#define IDE_RETRY_TRIM 0x80
+#define IDE_RETRY_HBA 0x100
+
+#define IS_IDE_RETRY_DMA(_status) \
+ ((_status) & IDE_RETRY_DMA)
+
+#define IS_IDE_RETRY_PIO(_status) \
+ ((_status) & IDE_RETRY_PIO)
+
+/*
+ * The method of the IDE_RETRY_ATAPI determination is to use a previously
+ * impossible bit combination as a new status value.
+ */
+#define IS_IDE_RETRY_ATAPI(_status) \
+ (((_status) & IDE_RETRY_MASK) == IDE_RETRY_ATAPI)
+
+static inline uint8_t ide_dma_cmd_to_retry(uint8_t dma_cmd)
+{
+ switch (dma_cmd) {
+ case IDE_DMA_READ:
+ return IDE_RETRY_DMA | IDE_RETRY_READ;
+ case IDE_DMA_WRITE:
+ return IDE_RETRY_DMA;
+ case IDE_DMA_TRIM:
+ return IDE_RETRY_DMA | IDE_RETRY_TRIM;
+ case IDE_DMA_ATAPI:
+ return IDE_RETRY_ATAPI;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static inline IDEState *idebus_active_if(IDEBus *bus)
+{
+ return bus->ifs + bus->unit;
+}
+
+static inline void ide_set_irq(IDEBus *bus)
+{
+ if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) {
+ qemu_irq_raise(bus->irq);
+ }
+}
+
+/* hw/ide/core.c */
+extern const VMStateDescription vmstate_ide_bus;
+
+#define VMSTATE_IDE_BUS(_field, _state) \
+ VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_bus, IDEBus)
+
+#define VMSTATE_IDE_BUS_ARRAY(_field, _state, _num) \
+ VMSTATE_STRUCT_ARRAY(_field, _state, _num, 1, vmstate_ide_bus, IDEBus)
+
+extern const VMStateDescription vmstate_ide_drive;
+
+#define VMSTATE_IDE_DRIVES(_field, _state) \
+ VMSTATE_STRUCT_ARRAY(_field, _state, 2, 3, vmstate_ide_drive, IDEState)
+
+#define VMSTATE_IDE_DRIVE(_field, _state) \
+ VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_drive, IDEState)
+
+void ide_bus_reset(IDEBus *bus);
+int64_t ide_get_sector(IDEState *s);
+void ide_set_sector(IDEState *s, int64_t sector_num);
+
+void ide_start_dma(IDEState *s, BlockCompletionFunc *cb);
+void dma_buf_commit(IDEState *s, uint32_t tx_bytes);
+void ide_dma_error(IDEState *s);
+void ide_abort_command(IDEState *s);
+
+void ide_atapi_cmd_ok(IDEState *s);
+void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc);
+void ide_atapi_dma_restart(IDEState *s);
+void ide_atapi_io_error(IDEState *s, int ret);
+
+void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val);
+uint32_t ide_ioport_read(void *opaque, uint32_t addr1);
+uint32_t ide_status_read(void *opaque, uint32_t addr);
+void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val);
+void ide_data_writew(void *opaque, uint32_t addr, uint32_t val);
+uint32_t ide_data_readw(void *opaque, uint32_t addr);
+void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
+uint32_t ide_data_readl(void *opaque, uint32_t addr);
+
+int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
+ const char *version, const char *serial, const char *model,
+ uint64_t wwn,
+ uint32_t cylinders, uint32_t heads, uint32_t secs,
+ int chs_trans);
+void ide_init2(IDEBus *bus, qemu_irq irq);
+void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
+void ide_register_restart_cb(IDEBus *bus);
+
+void ide_exec_cmd(IDEBus *bus, uint32_t val);
+
+void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
+ EndTransferFunc *end_transfer_func);
+void ide_transfer_stop(IDEState *s);
+void ide_set_inactive(IDEState *s, bool more);
+BlockAIOCB *ide_issue_trim(BlockBackend *blk,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+ BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num,
+ QEMUIOVector *iov, int nb_sectors,
+ BlockCompletionFunc *cb, void *opaque);
+void ide_cancel_dma_sync(IDEState *s);
+
+/* hw/ide/atapi.c */
+void ide_atapi_cmd(IDEState *s);
+void ide_atapi_cmd_reply_end(IDEState *s);
+
+/* hw/ide/qdev.c */
+void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
+ int bus_id, int max_units);
+IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive);
+
+int ide_handle_rw_error(IDEState *s, int error, int op);
+
+#endif /* HW_IDE_INTERNAL_H */
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 40213d662..eba567c87 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -23,13 +23,13 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/isa/isa.h"
+#include <hw/hw.h>
+#include <hw/i386/pc.h>
+#include <hw/isa/isa.h>
#include "sysemu/block-backend.h"
#include "sysemu/dma.h"
-#include "hw/ide/internal.h"
+#include <hw/ide/internal.h>
/***********************************************************/
/* ISA IDE definitions */
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 76f97c253..664328d17 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -29,7 +29,7 @@
#include "sysemu/block-backend.h"
#include "sysemu/dma.h"
-#include "hw/ide/internal.h"
+#include <hw/ide/internal.h>
/* debug MACIO */
// #define DEBUG_MACIO
@@ -55,8 +55,8 @@ static const int debug_macio = 0;
/*
* Unaligned DMA read/write access functions required for OS X/Darwin which
* don't perform DMA transactions on sector boundaries. These functions are
- * modelled on bdrv_co_preadv()/bdrv_co_pwritev() and so should be easy to
- * remove if the unaligned block APIs are ever exposed.
+ * modelled on bdrv_co_do_preadv()/bdrv_co_do_pwritev() and so should be
+ * easy to remove if the unaligned block APIs are ever exposed.
*/
static void pmac_dma_read(BlockBackend *blk,
@@ -66,7 +66,8 @@ static void pmac_dma_read(BlockBackend *blk,
DBDMA_io *io = opaque;
MACIOIDEState *m = io->opaque;
IDEState *s = idebus_active_if(&m->bus);
- dma_addr_t dma_addr;
+ dma_addr_t dma_addr, dma_len;
+ void *mem;
int64_t sector_num;
int nsector;
uint64_t align = BDRV_SECTOR_SIZE;
@@ -83,10 +84,9 @@ static void pmac_dma_read(BlockBackend *blk,
sector_num, nsector);
dma_addr = io->addr;
- io->dir = DMA_DIRECTION_FROM_DEVICE;
- io->dma_len = io->len;
- io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len,
- io->dir);
+ dma_len = io->len;
+ mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
+ DMA_DIRECTION_FROM_DEVICE);
if (offset & (align - 1)) {
head_bytes = offset & (align - 1);
@@ -100,7 +100,7 @@ static void pmac_dma_read(BlockBackend *blk,
offset = offset & ~(align - 1);
}
- qemu_iovec_add(&io->iov, io->dma_mem, io->len);
+ qemu_iovec_add(&io->iov, mem, io->len);
if ((offset + bytes) & (align - 1)) {
tail_bytes = (offset + bytes) & (align - 1);
@@ -120,7 +120,8 @@ static void pmac_dma_read(BlockBackend *blk,
MACIO_DPRINTF("--- Block read transfer - sector_num: %" PRIx64 " "
"nsector: %x\n", (offset >> 9), (bytes >> 9));
- s->bus->dma->aiocb = blk_aio_preadv(blk, offset, &io->iov, 0, cb, io);
+ s->bus->dma->aiocb = blk_aio_readv(blk, (offset >> 9), &io->iov,
+ (bytes >> 9), cb, io);
}
static void pmac_dma_write(BlockBackend *blk,
@@ -130,7 +131,8 @@ static void pmac_dma_write(BlockBackend *blk,
DBDMA_io *io = opaque;
MACIOIDEState *m = io->opaque;
IDEState *s = idebus_active_if(&m->bus);
- dma_addr_t dma_addr;
+ dma_addr_t dma_addr, dma_len;
+ void *mem;
int64_t sector_num;
int nsector;
uint64_t align = BDRV_SECTOR_SIZE;
@@ -148,10 +150,9 @@ static void pmac_dma_write(BlockBackend *blk,
sector_num, nsector);
dma_addr = io->addr;
- io->dir = DMA_DIRECTION_TO_DEVICE;
- io->dma_len = io->len;
- io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len,
- io->dir);
+ dma_len = io->len;
+ mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
+ DMA_DIRECTION_TO_DEVICE);
if (offset & (align - 1)) {
head_bytes = offset & (align - 1);
@@ -163,7 +164,7 @@ static void pmac_dma_write(BlockBackend *blk,
blk_pread(s->blk, (sector_num << 9), &io->head_remainder, align);
qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes);
- qemu_iovec_add(&io->iov, io->dma_mem, io->len);
+ qemu_iovec_add(&io->iov, mem, io->len);
bytes += offset & (align - 1);
offset = offset & ~(align - 1);
@@ -181,7 +182,7 @@ static void pmac_dma_write(BlockBackend *blk,
blk_pread(s->blk, (sector_num << 9), &io->tail_remainder, align);
if (!unaligned_head) {
- qemu_iovec_add(&io->iov, io->dma_mem, io->len);
+ qemu_iovec_add(&io->iov, mem, io->len);
}
qemu_iovec_add(&io->iov, &io->tail_remainder + tail_bytes,
@@ -193,7 +194,7 @@ static void pmac_dma_write(BlockBackend *blk,
}
if (!unaligned_head && !unaligned_tail) {
- qemu_iovec_add(&io->iov, io->dma_mem, io->len);
+ qemu_iovec_add(&io->iov, mem, io->len);
}
s->io_buffer_size -= io->len;
@@ -204,7 +205,8 @@ static void pmac_dma_write(BlockBackend *blk,
MACIO_DPRINTF("--- Block write transfer - sector_num: %" PRIx64 " "
"nsector: %x\n", (offset >> 9), (bytes >> 9));
- s->bus->dma->aiocb = blk_aio_pwritev(blk, offset, &io->iov, 0, cb, io);
+ s->bus->dma->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov,
+ (bytes >> 9), cb, io);
}
static void pmac_dma_trim(BlockBackend *blk,
@@ -214,23 +216,24 @@ static void pmac_dma_trim(BlockBackend *blk,
DBDMA_io *io = opaque;
MACIOIDEState *m = io->opaque;
IDEState *s = idebus_active_if(&m->bus);
- dma_addr_t dma_addr;
+ dma_addr_t dma_addr, dma_len;
+ void *mem;
qemu_iovec_destroy(&io->iov);
qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1);
dma_addr = io->addr;
- io->dir = DMA_DIRECTION_TO_DEVICE;
- io->dma_len = io->len;
- io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len,
- io->dir);
+ dma_len = io->len;
+ mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
+ DMA_DIRECTION_TO_DEVICE);
- qemu_iovec_add(&io->iov, io->dma_mem, io->len);
+ qemu_iovec_add(&io->iov, mem, io->len);
s->io_buffer_size -= io->len;
s->io_buffer_index += io->len;
io->len = 0;
- s->bus->dma->aiocb = ide_issue_trim(offset, &io->iov, cb, io, blk);
+ s->bus->dma->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov,
+ (bytes >> 9), cb, io);
}
static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
@@ -271,8 +274,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
if (s->lba == -1) {
/* Non-block ATAPI transfer - just copy to RAM */
s->io_buffer_size = MIN(s->io_buffer_size, io->len);
- dma_memory_write(&address_space_memory, io->addr, s->io_buffer,
- s->io_buffer_size);
+ cpu_physical_memory_write(io->addr, s->io_buffer, s->io_buffer_size);
io->len = 0;
ide_atapi_cmd_ok(s);
m->dma_active = false;
@@ -286,9 +288,6 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
return;
done:
- dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
- io->dir, io->dma_len);
-
if (ret < 0) {
block_acct_failed(blk_get_stats(s->blk), &s->acct);
} else {
@@ -355,9 +354,6 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
return;
done:
- dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
- io->dir, io->dma_len);
-
if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
if (ret < 0) {
block_acct_failed(blk_get_stats(s->blk), &s->acct);
@@ -407,7 +403,7 @@ static void pmac_ide_flush(DBDMA_io *io)
IDEState *s = idebus_active_if(&m->bus);
if (s->bus->dma->aiocb) {
- blk_drain(s->blk);
+ blk_drain_all();
}
}
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index e3fd30e45..5c9db8047 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -23,13 +23,13 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/pcmcia.h"
+#include <hw/hw.h>
+#include <hw/i386/pc.h>
+#include <hw/pcmcia.h>
#include "sysemu/block-backend.h"
#include "sysemu/dma.h"
-#include "hw/ide/internal.h"
+#include <hw/ide/internal.h>
#define TYPE_MICRODRIVE "microdrive"
#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE)
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index 6f12f456e..493f65a1d 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -28,7 +28,7 @@
#include "sysemu/block-backend.h"
#include "sysemu/dma.h"
-#include "hw/ide/internal.h"
+#include <hw/ide/internal.h>
/***********************************************************/
/* MMIO based ide port
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 3cfb510af..8d56a00b1 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -23,14 +23,14 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/pci/pci.h"
-#include "hw/isa/isa.h"
+#include <hw/hw.h>
+#include <hw/i386/pc.h>
+#include <hw/pci/pci.h>
+#include <hw/isa/isa.h>
#include "sysemu/block-backend.h"
#include "sysemu/dma.h"
#include "qemu/error-report.h"
-#include "hw/ide/pci.h"
+#include <hw/ide/pci.h>
#define BMDMA_PAGE_SIZE 4096
diff --git a/hw/ide/pci.h b/hw/ide/pci.h
new file mode 100644
index 000000000..0f2d4b91a
--- /dev/null
+++ b/hw/ide/pci.h
@@ -0,0 +1,76 @@
+#ifndef HW_IDE_PCI_H
+#define HW_IDE_PCI_H
+
+#include <hw/ide/internal.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;
+
+typedef struct CMD646BAR {
+ MemoryRegion cmd;
+ MemoryRegion data;
+ IDEBus *bus;
+ struct PCIIDEState *pci_dev;
+} CMD646BAR;
+
+#define TYPE_PCI_IDE "pci-ide"
+#define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE)
+
+typedef struct PCIIDEState {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
+ IDEBus bus[2];
+ BMDMAState bmdma[2];
+ uint32_t secondary; /* used only for cmd646 */
+ MemoryRegion bmdma_bar;
+ CMD646BAR cmd646_bar[2]; /* used only for cmd646 */
+} PCIIDEState;
+
+
+static inline IDEState *bmdma_active_if(BMDMAState *bmdma)
+{
+ assert(bmdma->bus->retry_unit != (uint8_t)-1);
+ return bmdma->bus->ifs + bmdma->bus->retry_unit;
+}
+
+
+void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d);
+void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val);
+extern MemoryRegionOps bmdma_addr_ioport_ops;
+void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table);
+
+extern const VMStateDescription vmstate_ide_pci;
+#endif
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index c190fcaa3..6d76ce980 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -24,15 +24,15 @@
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/pci/pci.h"
-#include "hw/isa/isa.h"
+#include <hw/hw.h>
+#include <hw/i386/pc.h>
+#include <hw/pci/pci.h>
+#include <hw/isa/isa.h>
#include "sysemu/block-backend.h"
#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
-#include "hw/ide/pci.h"
+#include <hw/ide/pci.h>
static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size)
{
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 67c76bfcd..4bc74a32d 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -17,11 +17,11 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
+#include <hw/hw.h>
#include "sysemu/dma.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
-#include "hw/ide/internal.h"
+#include <hw/ide/internal.h>
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
#include "hw/block/block.h"
@@ -180,7 +180,6 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
return -1;
}
}
- blkconf_apply_backend_options(&dev->conf);
if (ide_init_drive(s, dev->conf.blk, kind,
dev->version, dev->serial, dev->model, dev->wwn,
@@ -234,7 +233,9 @@ static void ide_dev_set_bootindex(Object *obj, Visitor *v, const char *name,
d->unit ? "/disk@1" : "/disk@0");
}
out:
- error_propagate(errp, local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ }
}
static void ide_dev_instance_init(Object *obj)
@@ -264,7 +265,6 @@ static int ide_drive_initfn(IDEDevice *dev)
#define DEFINE_IDE_DEV_PROPERTIES() \
DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \
- DEFINE_BLOCK_ERROR_PROPERTIES(IDEDrive, dev.conf), \
DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \
DEFINE_PROP_UINT64("wwn", IDEDrive, dev.wwn, 0), \
DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),\
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 5b32ecb38..d3f72267a 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -24,15 +24,15 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/pci/pci.h"
-#include "hw/isa/isa.h"
+#include <hw/hw.h>
+#include <hw/i386/pc.h>
+#include <hw/pci/pci.h>
+#include <hw/isa/isa.h>
#include "sysemu/block-backend.h"
#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
-#include "hw/ide/pci.h"
+#include <hw/ide/pci.h>
static uint64_t bmdma_read(void *opaque, hwaddr addr,
unsigned size)
diff --git a/hw/input/hid.c b/hw/input/hid.c
index 5e2850e65..d92c7463b 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -27,7 +27,6 @@
#include "ui/console.h"
#include "qemu/timer.h"
#include "hw/input/hid.h"
-#include "trace.h"
#define HID_USAGE_ERROR_ROLLOVER 0x01
#define HID_USAGE_POSTFAIL 0x02
@@ -235,7 +234,7 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
key->down,
scancodes);
if (hs->n + count > QUEUE_LENGTH) {
- trace_hid_kbd_queue_full();
+ fprintf(stderr, "usb-kbd: warning: key event queue full\n");
return;
}
for (i = 0; i < count; i++) {
diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
index dc57e2c76..1d932ec19 100644
--- a/hw/input/pckbd.c
+++ b/hw/input/pckbd.c
@@ -146,7 +146,7 @@ typedef struct KBDState {
qemu_irq irq_kbd;
qemu_irq irq_mouse;
- qemu_irq a20_out;
+ qemu_irq *a20_out;
hwaddr mask;
} KBDState;
@@ -224,7 +224,9 @@ static void outport_write(KBDState *s, uint32_t val)
{
DPRINTF("kbd: write outport=0x%02x\n", val);
s->outport = val;
- qemu_set_irq(s->a20_out, (val >> 1) & 1);
+ if (s->a20_out) {
+ qemu_set_irq(*s->a20_out, (val >> 1) & 1);
+ }
if (!(val & 1)) {
qemu_system_reset_request();
}
@@ -293,11 +295,15 @@ static void kbd_write_command(void *opaque, hwaddr addr,
kbd_queue(s, s->outport, 0);
break;
case KBD_CCMD_ENABLE_A20:
- qemu_irq_raise(s->a20_out);
+ if (s->a20_out) {
+ qemu_irq_raise(*s->a20_out);
+ }
s->outport |= KBD_OUT_A20;
break;
case KBD_CCMD_DISABLE_A20:
- qemu_irq_lower(s->a20_out);
+ if (s->a20_out) {
+ qemu_irq_lower(*s->a20_out);
+ }
s->outport &= ~KBD_OUT_A20;
break;
case KBD_CCMD_RESET:
@@ -501,7 +507,10 @@ void i8042_isa_mouse_fake_event(void *opaque)
void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out)
{
- qdev_connect_gpio_out_named(DEVICE(dev), I8042_A20_LINE, 0, *a20_out);
+ ISAKBDState *isa = I8042(dev);
+ KBDState *s = &isa->kbd;
+
+ s->a20_out = a20_out;
}
static const VMStateDescription vmstate_kbd_isa = {
@@ -543,8 +552,6 @@ static void i8042_initfn(Object *obj)
"i8042-data", 1);
memory_region_init_io(isa_s->io + 1, obj, &i8042_cmd_ops, s,
"i8042-cmd", 1);
-
- qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, I8042_A20_LINE, 1);
}
static void i8042_realizefn(DeviceState *dev, Error **errp)
diff --git a/hw/input/pl050.c b/hw/input/pl050.c
index be9cd57b1..3092b0fe3 100644
--- a/hw/input/pl050.c
+++ b/hw/input/pl050.c
@@ -10,7 +10,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "hw/input/ps2.h"
-#include "qemu/log.h"
#define TYPE_PL050 "pl050"
#define PL050(obj) OBJECT_CHECK(PL050State, (obj), TYPE_PL050)
diff --git a/hw/input/trace-events b/hw/input/trace-events
deleted file mode 100644
index 8c4003f36..000000000
--- a/hw/input/trace-events
+++ /dev/null
@@ -1,31 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/input/ps2.c
-ps2_put_keycode(void *opaque, int keycode) "%p keycode %d"
-ps2_read_data(void *opaque) "%p"
-ps2_set_ledstate(void *s, int ledstate) "%p ledstate %d"
-ps2_reset_keyboard(void *s) "%p"
-ps2_write_keyboard(void *opaque, int val) "%p val %d"
-ps2_keyboard_set_translation(void *opaque, int mode) "%p mode %d"
-ps2_mouse_send_packet(void *s, int dx1, int dy1, int dz1, int b) "%p x %d y %d z %d bs %#x"
-ps2_mouse_event_disabled(void *opaque, int dx, int dy, int dz, int buttons_state, int mouse_dx, int mouse_dy, int mouse_dz) "%p x %d y %d z %d bs %#x mx %d my %d mz %d "
-ps2_mouse_event(void *opaque, int dx, int dy, int dz, int buttons_state, int mouse_dx, int mouse_dy, int mouse_dz) "%p x %d y %d z %d bs %#x mx %d my %d mz %d "
-ps2_mouse_fake_event(void *opaque) "%p"
-ps2_write_mouse(void *opaque, int val) "%p val %d"
-ps2_kbd_reset(void *opaque) "%p"
-ps2_mouse_reset(void *opaque) "%p"
-ps2_kbd_init(void *s) "%p"
-ps2_mouse_init(void *s) "%p"
-
-# hw/input/milkymist-softusb.c
-milkymist_softusb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_softusb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_softusb_mevt(uint8_t m) "m %d"
-milkymist_softusb_kevt(uint8_t m) "m %d"
-milkymist_softusb_pulse_irq(void) "Pulse IRQ"
-
-# hw/input/hid.c
-hid_kbd_queue_full(void) "queue full"
-
-# hw/input/virtio
-virtio_input_queue_full(void) "queue full"
diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c
index ccdf7308a..f59749a94 100644
--- a/hw/input/virtio-input.c
+++ b/hw/input/virtio-input.c
@@ -7,7 +7,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/iov.h"
-#include "trace.h"
#include "hw/qdev.h"
#include "hw/virtio/virtio.h"
@@ -48,7 +47,7 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0);
if (have < need) {
vinput->qindex = 0;
- trace_virtio_input_queue_full();
+ fprintf(stderr, "%s: ENOSPC in vq, dropping events\n", __func__);
return;
}
@@ -217,14 +216,26 @@ static void virtio_input_reset(VirtIODevice *vdev)
}
}
-static int virtio_input_load(QEMUFile *f, void *opaque, size_t size)
+static void virtio_input_save(QEMUFile *f, void *opaque)
+{
+ VirtIOInput *vinput = opaque;
+ VirtIODevice *vdev = VIRTIO_DEVICE(vinput);
+
+ virtio_save(vdev, f);
+}
+
+static int virtio_input_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIOInput *vinput = opaque;
VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(vinput);
VirtIODevice *vdev = VIRTIO_DEVICE(vinput);
int ret;
- ret = virtio_load(vdev, f, VIRTIO_INPUT_VM_VERSION);
+ if (version_id != VIRTIO_INPUT_VM_VERSION) {
+ return -EINVAL;
+ }
+
+ ret = virtio_load(vdev, f, version_id);
if (ret) {
return ret;
}
@@ -268,24 +279,20 @@ static void virtio_input_device_realize(DeviceState *dev, Error **errp)
vinput->cfg_size);
vinput->evt = virtio_add_queue(vdev, 64, virtio_input_handle_evt);
vinput->sts = virtio_add_queue(vdev, 64, virtio_input_handle_sts);
-}
-
-static void virtio_input_finalize(Object *obj)
-{
- VirtIOInput *vinput = VIRTIO_INPUT(obj);
- VirtIOInputConfig *cfg, *next;
- QTAILQ_FOREACH_SAFE(cfg, &vinput->cfg_list, node, next) {
- QTAILQ_REMOVE(&vinput->cfg_list, cfg, node);
- g_free(cfg);
- }
+ register_savevm(dev, "virtio-input", -1, VIRTIO_INPUT_VM_VERSION,
+ virtio_input_save, virtio_input_load, vinput);
}
+
static void virtio_input_device_unrealize(DeviceState *dev, Error **errp)
{
VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev);
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOInput *vinput = VIRTIO_INPUT(dev);
Error *local_err = NULL;
+ unregister_savevm(dev, "virtio-input", vinput);
+
if (vic->unrealize) {
vic->unrealize(dev, &local_err);
if (local_err) {
@@ -296,9 +303,6 @@ static void virtio_input_device_unrealize(DeviceState *dev, Error **errp)
virtio_cleanup(vdev);
}
-VMSTATE_VIRTIO_DEVICE(input, VIRTIO_INPUT_VM_VERSION, virtio_input_load,
- virtio_vmstate_save);
-
static Property virtio_input_properties[] = {
DEFINE_PROP_STRING("serial", VirtIOInput, serial),
DEFINE_PROP_END_OF_LIST(),
@@ -310,7 +314,6 @@ static void virtio_input_class_init(ObjectClass *klass, void *data)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->props = virtio_input_properties;
- dc->vmsd = &vmstate_virtio_input;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
vdc->realize = virtio_input_device_realize;
vdc->unrealize = virtio_input_device_unrealize;
@@ -328,7 +331,6 @@ static const TypeInfo virtio_input_info = {
.class_size = sizeof(VirtIOInputClass),
.class_init = virtio_input_class_init,
.abstract = true,
- .instance_finalize = virtio_input_finalize,
};
/* ----------------------------------------------------------------- */
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 05ec21b21..0e47f0f9e 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -13,9 +13,6 @@ common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o
common-obj-$(CONFIG_ARM_GIC) += arm_gic.o
common-obj-$(CONFIG_ARM_GIC) += arm_gicv2m.o
common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_common.o
-common-obj-$(CONFIG_ARM_GIC) += arm_gicv3.o
-common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_dist.o
-common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_redist.o
common-obj-$(CONFIG_OPENPIC) += openpic.o
obj-$(CONFIG_APIC) += apic.o apic_common.o
@@ -30,11 +27,8 @@ obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o
obj-$(CONFIG_SH4) += sh_intc.o
obj-$(CONFIG_XICS) += xics.o
-obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
obj-$(CONFIG_XICS_KVM) += xics_kvm.o
obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
obj-$(CONFIG_S390_FLIC) += s390_flic.o
obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o
obj-$(CONFIG_ASPEED_SOC) += aspeed_vic.o
-obj-$(CONFIG_ARM_GIC) += arm_gicv3_cpuif.o
-obj-$(CONFIG_MIPS_CPS) += mips_gic.o
diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
index 11f13663c..dc971a160 100644
--- a/hw/intc/allwinner-a10-pic.c
+++ b/hw/intc/allwinner-a10-pic.c
@@ -20,7 +20,6 @@
#include "hw/devices.h"
#include "sysemu/sysemu.h"
#include "hw/intc/allwinner-a10-pic.h"
-#include "qemu/log.h"
static void aw_a10_pic_update(AwA10PICState *s)
{
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 45887d99c..28c2ea540 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -17,8 +17,6 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>
*/
#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "cpu.h"
#include "qemu/thread.h"
#include "hw/i386/apic_internal.h"
#include "hw/i386/apic.h"
@@ -28,9 +26,7 @@
#include "trace.h"
#include "hw/i386/pc.h"
#include "hw/i386/apic-msidef.h"
-#include "qapi/error.h"
-#define MAX_APICS 255
#define MAX_APIC_WORDS 8
#define SYNC_FROM_VAPIC 0x1
@@ -421,7 +417,7 @@ static int apic_find_dest(uint8_t dest)
int i;
if (apic && apic->id == dest)
- return dest; /* shortcut in case apic->id == local_apics[dest]->id */
+ return dest; /* shortcut in case apic->id == apic->idx */
for (i = 0; i < MAX_APICS; i++) {
apic = local_apics[i];
@@ -504,14 +500,14 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode,
break;
case 1:
memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
- apic_set_bit(deliver_bitmask, s->id);
+ apic_set_bit(deliver_bitmask, s->idx);
break;
case 2:
memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
break;
case 3:
memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
- apic_reset_bit(deliver_bitmask, s->id);
+ apic_reset_bit(deliver_bitmask, s->idx);
break;
}
@@ -872,36 +868,20 @@ static void apic_realize(DeviceState *dev, Error **errp)
{
APICCommonState *s = APIC_COMMON(dev);
- if (s->id >= MAX_APICS) {
- error_setg(errp, "%s initialization failed. APIC ID %d is invalid",
- object_get_typename(OBJECT(dev)), s->id);
- return;
- }
-
memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
APIC_SPACE_SIZE);
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s);
- local_apics[s->id] = s;
+ local_apics[s->idx] = s;
msi_nonbroken = true;
}
-static void apic_unrealize(DeviceState *dev, Error **errp)
-{
- APICCommonState *s = APIC_COMMON(dev);
-
- timer_del(s->timer);
- timer_free(s->timer);
- local_apics[s->id] = NULL;
-}
-
static void apic_class_init(ObjectClass *klass, void *data)
{
APICCommonClass *k = APIC_COMMON_CLASS(klass);
k->realize = apic_realize;
- k->unrealize = apic_unrealize;
k->set_base = apic_set_base;
k->set_tpr = apic_set_tpr;
k->get_tpr = apic_get_tpr;
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index 14ac43c18..4abe145c6 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -19,8 +19,6 @@
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu-common.h"
-#include "cpu.h"
#include "hw/i386/apic.h"
#include "hw/i386/apic_internal.h"
#include "trace.h"
@@ -294,14 +292,19 @@ static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
return 0;
}
-static const VMStateDescription vmstate_apic_common;
-
static void apic_common_realize(DeviceState *dev, Error **errp)
{
APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info;
static DeviceState *vapic;
- int instance_id = s->id;
+ static int apic_no;
+
+ if (apic_no >= MAX_APICS) {
+ error_setg(errp, "%s initialization failed.",
+ object_get_typename(OBJECT(dev)));
+ return;
+ }
+ s->idx = apic_no++;
info = APIC_COMMON_GET_CLASS(s);
info->realize(dev, errp);
@@ -316,24 +319,6 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
info->enable_tpr_reporting(s, true);
}
- if (s->legacy_instance_id) {
- instance_id = -1;
- }
- vmstate_register_with_alias_id(NULL, instance_id, &vmstate_apic_common,
- s, -1, 0);
-}
-
-static void apic_common_unrealize(DeviceState *dev, Error **errp)
-{
- APICCommonState *s = APIC_COMMON(dev);
- APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
-
- vmstate_unregister(NULL, &vmstate_apic_common, s);
- info->unrealize(dev, errp);
-
- if (apic_report_tpr_access && info->enable_tpr_reporting) {
- info->enable_tpr_reporting(s, false);
- }
}
static int apic_pre_load(void *opaque)
@@ -431,8 +416,6 @@ static Property apic_properties_common[] = {
DEFINE_PROP_UINT8("version", APICCommonState, version, 0x14),
DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
true),
- DEFINE_PROP_BOOL("legacy-instance-id", APICCommonState, legacy_instance_id,
- false),
DEFINE_PROP_END_OF_LIST(),
};
@@ -440,10 +423,10 @@ static void apic_common_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->vmsd = &vmstate_apic_common;
dc->reset = apic_reset_common;
dc->props = apic_properties_common;
dc->realize = apic_common_realize;
- dc->unrealize = apic_common_unrealize;
/*
* Reason: APIC and CPU need to be wired up by
* x86_cpu_apic_create()
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index b30cc9174..f55124174 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -23,8 +23,6 @@
#include "gic_internal.h"
#include "qapi/error.h"
#include "qom/cpu.h"
-#include "qemu/log.h"
-#include "trace.h"
//#define DEBUG_GIC
@@ -95,11 +93,6 @@ void gic_update(GICState *s)
}
}
- if (best_irq != 1023) {
- trace_gic_update_bestirq(cpu, best_irq, best_prio,
- s->priority_mask[cpu], s->running_priority[cpu]);
- }
-
irq_level = fiq_level = 0;
if (best_prio < s->priority_mask[cpu]) {
@@ -113,12 +106,10 @@ void gic_update(GICState *s)
DPRINTF("Raised pending FIQ %d (cpu %d)\n",
best_irq, cpu);
fiq_level = 1;
- trace_gic_update_set_irq(cpu, "fiq", fiq_level);
} else {
DPRINTF("Raised pending IRQ %d (cpu %d)\n",
best_irq, cpu);
irq_level = 1;
- trace_gic_update_set_irq(cpu, "irq", irq_level);
}
}
}
@@ -206,7 +197,6 @@ static void gic_set_irq(void *opaque, int irq, int level)
} else {
gic_set_irq_generic(s, irq, level, cm, target);
}
- trace_gic_set_irq(irq, level, cm, target);
gic_update(s);
}
@@ -342,7 +332,6 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
* is in the wrong group.
*/
irq = gic_get_current_pending_irq(s, cpu, attrs);
- trace_gic_acknowledge_irq(cpu, irq);
if (irq >= GIC_MAXIRQ) {
DPRINTF("ACK, no pending interrupt or it is hidden: %d\n", irq);
@@ -661,11 +650,6 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
goto bad_reg;
res = 0;
for (i = 0; i < 8; i++) {
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
- continue; /* Ignore Non-secure access of Group0 IRQ */
- }
-
if (GIC_TEST_ENABLED(irq + i, cm)) {
res |= (1 << i);
}
@@ -682,11 +666,6 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
res = 0;
mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK;
for (i = 0; i < 8; i++) {
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
- continue; /* Ignore Non-secure access of Group0 IRQ */
- }
-
if (gic_test_pending(s, irq + i, mask)) {
res |= (1 << i);
}
@@ -699,11 +678,6 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
res = 0;
mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK;
for (i = 0; i < 8; i++) {
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
- continue; /* Ignore Non-secure access of Group0 IRQ */
- }
-
if (GIC_TEST_ACTIVE(irq + i, mask)) {
res |= (1 << i);
}
@@ -737,11 +711,6 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
goto bad_reg;
res = 0;
for (i = 0; i < 4; i++) {
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
- continue; /* Ignore Non-secure access of Group0 IRQ */
- }
-
if (GIC_TEST_MODEL(irq + i))
res |= (1 << (i * 2));
if (GIC_TEST_EDGE_TRIGGER(irq + i))
@@ -762,12 +731,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
/* GICD_SPENDSGIRn */
}
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq, 1 << cpu)) {
- res = 0; /* Ignore Non-secure access of Group0 IRQ */
- } else {
- res = s->sgi_pending[irq][cpu];
- }
+ res = s->sgi_pending[irq][cpu];
} else if (offset < 0xfd0) {
goto bad_reg;
} else if (offset < 0x1000) {
@@ -887,14 +851,8 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
(irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq + i);
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
- continue; /* Ignore Non-secure access of Group0 IRQ */
- }
-
if (!GIC_TEST_ENABLED(irq + i, cm)) {
DPRINTF("Enabled IRQ %d\n", irq + i);
- trace_gic_enable_irq(irq + i);
}
GIC_SET_ENABLED(irq + i, cm);
/* If a raised level triggered IRQ enabled then mark
@@ -919,14 +877,8 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
if (value & (1 << i)) {
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
- continue; /* Ignore Non-secure access of Group0 IRQ */
- }
-
if (GIC_TEST_ENABLED(irq + i, cm)) {
DPRINTF("Disabled IRQ %d\n", irq + i);
- trace_gic_disable_irq(irq + i);
}
GIC_CLEAR_ENABLED(irq + i, cm);
}
@@ -942,11 +894,6 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
- continue; /* Ignore Non-secure access of Group0 IRQ */
- }
-
GIC_SET_PENDING(irq + i, GIC_TARGET(irq + i));
}
}
@@ -960,11 +907,6 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
}
for (i = 0; i < 8; i++) {
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
- continue; /* Ignore Non-secure access of Group0 IRQ */
- }
-
/* ??? This currently clears the pending bit for all CPUs, even
for per-CPU interrupts. It's unclear whether this is the
corect behavior. */
@@ -1005,11 +947,6 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
if (irq < GIC_NR_SGIS)
value |= 0xaa;
for (i = 0; i < 4; i++) {
- if (s->security_extn && !attrs.secure &&
- !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
- continue; /* Ignore Non-secure access of Group0 IRQ */
- }
-
if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
if (value & (1 << (i * 2))) {
GIC_SET_MODEL(irq + i);
@@ -1033,12 +970,9 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
}
irq = (offset - 0xf10);
- if (!s->security_extn || attrs.secure ||
- GIC_TEST_GROUP(irq, 1 << cpu)) {
- s->sgi_pending[irq][cpu] &= ~value;
- if (s->sgi_pending[irq][cpu] == 0) {
- GIC_CLEAR_PENDING(irq, 1 << cpu);
- }
+ s->sgi_pending[irq][cpu] &= ~value;
+ if (s->sgi_pending[irq][cpu] == 0) {
+ GIC_CLEAR_PENDING(irq, 1 << cpu);
}
} else if (offset < 0xf30) {
/* GICD_SPENDSGIRn */
@@ -1047,11 +981,8 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
}
irq = (offset - 0xf20);
- if (!s->security_extn || attrs.secure ||
- GIC_TEST_GROUP(irq, 1 << cpu)) {
- GIC_SET_PENDING(irq, 1 << cpu);
- s->sgi_pending[irq][cpu] |= value;
- }
+ GIC_SET_PENDING(irq, 1 << cpu);
+ s->sgi_pending[irq][cpu] |= value;
} else {
goto bad_reg;
}
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index 5593cdb3e..bc85ab769 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -21,8 +21,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu-common.h"
-#include "cpu.h"
#include "hw/sysbus.h"
#include "migration/migration.h"
#include "sysemu/kvm.h"
diff --git a/hw/intc/arm_gicv2m.c b/hw/intc/arm_gicv2m.c
index 3922fbc1c..e8b5177dc 100644
--- a/hw/intc/arm_gicv2m.c
+++ b/hw/intc/arm_gicv2m.c
@@ -29,8 +29,6 @@
#include "qapi/error.h"
#include "hw/sysbus.h"
#include "hw/pci/msi.h"
-#include "sysemu/kvm.h"
-#include "qemu/log.h"
#define TYPE_ARM_GICV2M "arm-gicv2m"
#define ARM_GICV2M(obj) OBJECT_CHECK(ARMGICv2mState, (obj), TYPE_ARM_GICV2M)
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
deleted file mode 100644
index 8a6c64721..000000000
--- a/hw/intc/arm_gicv3.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * 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.
- */
-
-/* This file contains implementation code for an interrupt controller
- * which implements the GICv3 architecture. Specifically this is where
- * the device class itself and the functions for handling interrupts
- * coming in and going out live.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "hw/sysbus.h"
-#include "hw/intc/arm_gicv3.h"
-#include "gicv3_internal.h"
-
-static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio)
-{
- /* Return true if this IRQ at this priority should take
- * precedence over the current recorded highest priority
- * pending interrupt for this CPU. We also return true if
- * the current recorded highest priority pending interrupt
- * is the same as this one (a property which the calling code
- * relies on).
- */
- if (prio < cs->hppi.prio) {
- return true;
- }
- /* If multiple pending interrupts have the same priority then it is an
- * IMPDEF choice which of them to signal to the CPU. We choose to
- * signal the one with the lowest interrupt number.
- */
- if (prio == cs->hppi.prio && irq <= cs->hppi.irq) {
- return true;
- }
- return false;
-}
-
-static uint32_t gicd_int_pending(GICv3State *s, int irq)
-{
- /* Recalculate which distributor interrupts are actually pending
- * in the group of 32 interrupts starting at irq (which should be a multiple
- * of 32), and return a 32-bit integer which has a bit set for each
- * interrupt that is eligible to be signaled to the CPU interface.
- *
- * An interrupt is pending if:
- * + the PENDING latch is set OR it is level triggered and the input is 1
- * + its ENABLE bit is set
- * + the GICD enable bit for its group is set
- * Conveniently we can bulk-calculate this with bitwise operations.
- */
- uint32_t pend, grpmask;
- uint32_t pending = *gic_bmp_ptr32(s->pending, irq);
- uint32_t edge_trigger = *gic_bmp_ptr32(s->edge_trigger, irq);
- uint32_t level = *gic_bmp_ptr32(s->level, irq);
- uint32_t group = *gic_bmp_ptr32(s->group, irq);
- uint32_t grpmod = *gic_bmp_ptr32(s->grpmod, irq);
- uint32_t enable = *gic_bmp_ptr32(s->enabled, irq);
-
- pend = pending | (~edge_trigger & level);
- pend &= enable;
-
- if (s->gicd_ctlr & GICD_CTLR_DS) {
- grpmod = 0;
- }
-
- grpmask = 0;
- if (s->gicd_ctlr & GICD_CTLR_EN_GRP1NS) {
- grpmask |= group;
- }
- if (s->gicd_ctlr & GICD_CTLR_EN_GRP1S) {
- grpmask |= (~group & grpmod);
- }
- if (s->gicd_ctlr & GICD_CTLR_EN_GRP0) {
- grpmask |= (~group & ~grpmod);
- }
- pend &= grpmask;
-
- return pend;
-}
-
-static uint32_t gicr_int_pending(GICv3CPUState *cs)
-{
- /* Recalculate which redistributor interrupts are actually pending,
- * and return a 32-bit integer which has a bit set for each interrupt
- * that is eligible to be signaled to the CPU interface.
- *
- * An interrupt is pending if:
- * + the PENDING latch is set OR it is level triggered and the input is 1
- * + its ENABLE bit is set
- * + the GICD enable bit for its group is set
- * Conveniently we can bulk-calculate this with bitwise operations.
- */
- uint32_t pend, grpmask, grpmod;
-
- pend = cs->gicr_ipendr0 | (~cs->edge_trigger & cs->level);
- pend &= cs->gicr_ienabler0;
-
- if (cs->gic->gicd_ctlr & GICD_CTLR_DS) {
- grpmod = 0;
- } else {
- grpmod = cs->gicr_igrpmodr0;
- }
-
- grpmask = 0;
- if (cs->gic->gicd_ctlr & GICD_CTLR_EN_GRP1NS) {
- grpmask |= cs->gicr_igroupr0;
- }
- if (cs->gic->gicd_ctlr & GICD_CTLR_EN_GRP1S) {
- grpmask |= (~cs->gicr_igroupr0 & grpmod);
- }
- if (cs->gic->gicd_ctlr & GICD_CTLR_EN_GRP0) {
- grpmask |= (~cs->gicr_igroupr0 & ~grpmod);
- }
- pend &= grpmask;
-
- return pend;
-}
-
-/* Update the interrupt status after state in a redistributor
- * or CPU interface has changed, but don't tell the CPU i/f.
- */
-static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
-{
- /* Find the highest priority pending interrupt among the
- * redistributor interrupts (SGIs and PPIs).
- */
- bool seenbetter = false;
- uint8_t prio;
- int i;
- uint32_t pend;
-
- /* Find out which redistributor interrupts are eligible to be
- * signaled to the CPU interface.
- */
- pend = gicr_int_pending(cs);
-
- if (pend) {
- for (i = 0; i < GIC_INTERNAL; i++) {
- if (!(pend & (1 << i))) {
- continue;
- }
- prio = cs->gicr_ipriorityr[i];
- if (irqbetter(cs, i, prio)) {
- cs->hppi.irq = i;
- cs->hppi.prio = prio;
- seenbetter = true;
- }
- }
- }
-
- if (seenbetter) {
- cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq);
- }
-
- /* If the best interrupt we just found would preempt whatever
- * was the previous best interrupt before this update, then
- * we know it's definitely the best one now.
- * If we didn't find an interrupt that would preempt the previous
- * best, and the previous best is outside our range (or there was no
- * previous pending interrupt at all), then that is still valid, and
- * we leave it as the best.
- * Otherwise, we need to do a full update (because the previous best
- * interrupt has reduced in priority and any other interrupt could
- * now be the new best one).
- */
- if (!seenbetter && cs->hppi.prio != 0xff && cs->hppi.irq < GIC_INTERNAL) {
- gicv3_full_update_noirqset(cs->gic);
- }
-}
-
-/* Update the GIC status after state in a redistributor or
- * CPU interface has changed, and inform the CPU i/f of
- * its new highest priority pending interrupt.
- */
-void gicv3_redist_update(GICv3CPUState *cs)
-{
- gicv3_redist_update_noirqset(cs);
- gicv3_cpuif_update(cs);
-}
-
-/* Update the GIC status after state in the distributor has
- * changed affecting @len interrupts starting at @start,
- * but don't tell the CPU i/f.
- */
-static void gicv3_update_noirqset(GICv3State *s, int start, int len)
-{
- int i;
- uint8_t prio;
- uint32_t pend = 0;
-
- assert(start >= GIC_INTERNAL);
- assert(len > 0);
-
- for (i = 0; i < s->num_cpu; i++) {
- s->cpu[i].seenbetter = false;
- }
-
- /* Find the highest priority pending interrupt in this range. */
- for (i = start; i < start + len; i++) {
- GICv3CPUState *cs;
-
- if (i == start || (i & 0x1f) == 0) {
- /* Calculate the next 32 bits worth of pending status */
- pend = gicd_int_pending(s, i & ~0x1f);
- }
-
- if (!(pend & (1 << (i & 0x1f)))) {
- continue;
- }
- cs = s->gicd_irouter_target[i];
- if (!cs) {
- /* Interrupts targeting no implemented CPU should remain pending
- * and not be forwarded to any CPU.
- */
- continue;
- }
- prio = s->gicd_ipriority[i];
- if (irqbetter(cs, i, prio)) {
- cs->hppi.irq = i;
- cs->hppi.prio = prio;
- cs->seenbetter = true;
- }
- }
-
- /* If the best interrupt we just found would preempt whatever
- * was the previous best interrupt before this update, then
- * we know it's definitely the best one now.
- * If we didn't find an interrupt that would preempt the previous
- * best, and the previous best is outside our range (or there was
- * no previous pending interrupt at all), then that
- * is still valid, and we leave it as the best.
- * Otherwise, we need to do a full update (because the previous best
- * interrupt has reduced in priority and any other interrupt could
- * now be the new best one).
- */
- for (i = 0; i < s->num_cpu; i++) {
- GICv3CPUState *cs = &s->cpu[i];
-
- if (cs->seenbetter) {
- cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq);
- }
-
- if (!cs->seenbetter && cs->hppi.prio != 0xff &&
- cs->hppi.irq >= start && cs->hppi.irq < start + len) {
- gicv3_full_update_noirqset(s);
- break;
- }
- }
-}
-
-void gicv3_update(GICv3State *s, int start, int len)
-{
- int i;
-
- gicv3_update_noirqset(s, start, len);
- for (i = 0; i < s->num_cpu; i++) {
- gicv3_cpuif_update(&s->cpu[i]);
- }
-}
-
-void gicv3_full_update_noirqset(GICv3State *s)
-{
- /* Completely recalculate the GIC status from scratch, but
- * don't update any outbound IRQ lines.
- */
- int i;
-
- for (i = 0; i < s->num_cpu; i++) {
- s->cpu[i].hppi.prio = 0xff;
- }
-
- /* Note that we can guarantee that these functions will not
- * recursively call back into gicv3_full_update(), because
- * at each point the "previous best" is always outside the
- * range we ask them to update.
- */
- gicv3_update_noirqset(s, GIC_INTERNAL, s->num_irq - GIC_INTERNAL);
-
- for (i = 0; i < s->num_cpu; i++) {
- gicv3_redist_update_noirqset(&s->cpu[i]);
- }
-}
-
-void gicv3_full_update(GICv3State *s)
-{
- /* Completely recalculate the GIC status from scratch, including
- * updating outbound IRQ lines.
- */
- int i;
-
- gicv3_full_update_noirqset(s);
- for (i = 0; i < s->num_cpu; i++) {
- gicv3_cpuif_update(&s->cpu[i]);
- }
-}
-
-/* Process a change in an external IRQ input. */
-static void gicv3_set_irq(void *opaque, int irq, int level)
-{
- /* Meaning of the 'irq' parameter:
- * [0..N-1] : external interrupts
- * [N..N+31] : PPI (internal) interrupts for CPU 0
- * [N+32..N+63] : PPI (internal interrupts for CPU 1
- * ...
- */
- GICv3State *s = opaque;
-
- if (irq < (s->num_irq - GIC_INTERNAL)) {
- /* external interrupt (SPI) */
- gicv3_dist_set_irq(s, irq + GIC_INTERNAL, level);
- } else {
- /* per-cpu interrupt (PPI) */
- int cpu;
-
- irq -= (s->num_irq - GIC_INTERNAL);
- cpu = irq / GIC_INTERNAL;
- irq %= GIC_INTERNAL;
- assert(cpu < s->num_cpu);
- /* Raising SGIs via this function would be a bug in how the board
- * model wires up interrupts.
- */
- assert(irq >= GIC_NR_SGIS);
- gicv3_redist_set_irq(&s->cpu[cpu], irq, level);
- }
-}
-
-static void arm_gicv3_post_load(GICv3State *s)
-{
- /* Recalculate our cached idea of the current highest priority
- * pending interrupt, but don't set IRQ or FIQ lines.
- */
- gicv3_full_update_noirqset(s);
- /* Repopulate the cache of GICv3CPUState pointers for target CPUs */
- gicv3_cache_all_target_cpustates(s);
-}
-
-static const MemoryRegionOps gic_ops[] = {
- {
- .read_with_attrs = gicv3_dist_read,
- .write_with_attrs = gicv3_dist_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- },
- {
- .read_with_attrs = gicv3_redist_read,
- .write_with_attrs = gicv3_redist_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- }
-};
-
-static void arm_gic_realize(DeviceState *dev, Error **errp)
-{
- /* Device instance realize function for the GIC sysbus device */
- GICv3State *s = ARM_GICV3(dev);
- ARMGICv3Class *agc = ARM_GICV3_GET_CLASS(s);
- Error *local_err = NULL;
-
- agc->parent_realize(dev, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops);
-
- gicv3_init_cpuif(s);
-}
-
-static void arm_gicv3_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass);
- ARMGICv3Class *agc = ARM_GICV3_CLASS(klass);
-
- agcc->post_load = arm_gicv3_post_load;
- agc->parent_realize = dc->realize;
- dc->realize = arm_gic_realize;
-}
-
-static const TypeInfo arm_gicv3_info = {
- .name = TYPE_ARM_GICV3,
- .parent = TYPE_ARM_GICV3_COMMON,
- .instance_size = sizeof(GICv3State),
- .class_init = arm_gicv3_class_init,
- .class_size = sizeof(ARMGICv3Class),
-};
-
-static void arm_gicv3_register_types(void)
-{
- type_register_static(&arm_gicv3_info);
-}
-
-type_init(arm_gicv3_register_types)
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 0f8c4b86e..b9d3824f2 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -3,9 +3,8 @@
*
* 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
+ * Extended to 64 cores by Shlomo Pongratz
*
* 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
@@ -23,10 +22,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qom/cpu.h"
#include "hw/intc/arm_gicv3_common.h"
-#include "gicv3_internal.h"
-#include "hw/arm/linux-boot-if.h"
static void gicv3_pre_save(void *opaque)
{
@@ -49,59 +45,11 @@ static int gicv3_post_load(void *opaque, int version_id)
return 0;
}
-static const VMStateDescription vmstate_gicv3_cpu = {
- .name = "arm_gicv3_cpu",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(level, GICv3CPUState),
- VMSTATE_UINT32(gicr_ctlr, GICv3CPUState),
- VMSTATE_UINT32_ARRAY(gicr_statusr, GICv3CPUState, 2),
- VMSTATE_UINT32(gicr_waker, GICv3CPUState),
- VMSTATE_UINT64(gicr_propbaser, GICv3CPUState),
- VMSTATE_UINT64(gicr_pendbaser, GICv3CPUState),
- VMSTATE_UINT32(gicr_igroupr0, GICv3CPUState),
- VMSTATE_UINT32(gicr_ienabler0, GICv3CPUState),
- VMSTATE_UINT32(gicr_ipendr0, GICv3CPUState),
- VMSTATE_UINT32(gicr_iactiver0, GICv3CPUState),
- VMSTATE_UINT32(edge_trigger, GICv3CPUState),
- VMSTATE_UINT32(gicr_igrpmodr0, GICv3CPUState),
- VMSTATE_UINT32(gicr_nsacr, GICv3CPUState),
- VMSTATE_UINT8_ARRAY(gicr_ipriorityr, GICv3CPUState, GIC_INTERNAL),
- VMSTATE_UINT64_ARRAY(icc_ctlr_el1, GICv3CPUState, 2),
- VMSTATE_UINT64(icc_pmr_el1, GICv3CPUState),
- VMSTATE_UINT64_ARRAY(icc_bpr, GICv3CPUState, 3),
- VMSTATE_UINT64_2DARRAY(icc_apr, GICv3CPUState, 3, 4),
- VMSTATE_UINT64_ARRAY(icc_igrpen, GICv3CPUState, 3),
- VMSTATE_UINT64(icc_ctlr_el3, GICv3CPUState),
- VMSTATE_END_OF_LIST()
- }
-};
-
static const VMStateDescription vmstate_gicv3 = {
.name = "arm_gicv3",
- .version_id = 1,
- .minimum_version_id = 1,
+ .unmigratable = 1,
.pre_save = gicv3_pre_save,
.post_load = gicv3_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(gicd_ctlr, GICv3State),
- VMSTATE_UINT32_ARRAY(gicd_statusr, GICv3State, 2),
- VMSTATE_UINT32_ARRAY(group, GICv3State, GICV3_BMP_SIZE),
- VMSTATE_UINT32_ARRAY(grpmod, GICv3State, GICV3_BMP_SIZE),
- VMSTATE_UINT32_ARRAY(enabled, GICv3State, GICV3_BMP_SIZE),
- VMSTATE_UINT32_ARRAY(pending, GICv3State, GICV3_BMP_SIZE),
- VMSTATE_UINT32_ARRAY(active, GICv3State, GICV3_BMP_SIZE),
- VMSTATE_UINT32_ARRAY(level, GICv3State, GICV3_BMP_SIZE),
- VMSTATE_UINT32_ARRAY(edge_trigger, GICv3State, GICV3_BMP_SIZE),
- VMSTATE_UINT8_ARRAY(gicd_ipriority, GICv3State, GICV3_MAXIRQ),
- VMSTATE_UINT64_ARRAY(gicd_irouter, GICv3State, GICV3_MAXIRQ),
- VMSTATE_UINT32_ARRAY(gicd_nsacr, GICv3State,
- DIV_ROUND_UP(GICV3_MAXIRQ, 16)),
- VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, GICv3State, num_cpu,
- vmstate_gicv3_cpu, GICv3CPUState),
- VMSTATE_END_OF_LIST()
- }
};
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
@@ -120,11 +68,14 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
i = s->num_irq - GIC_INTERNAL + GIC_INTERNAL * s->num_cpu;
qdev_init_gpio_in(DEVICE(s), handler, i);
+ s->parent_irq = g_malloc(s->num_cpu * sizeof(qemu_irq));
+ s->parent_fiq = g_malloc(s->num_cpu * sizeof(qemu_irq));
+
for (i = 0; i < s->num_cpu; i++) {
- sysbus_init_irq(sbd, &s->cpu[i].parent_irq);
+ sysbus_init_irq(sbd, &s->parent_irq[i]);
}
for (i = 0; i < s->num_cpu; i++) {
- sysbus_init_irq(sbd, &s->cpu[i].parent_fiq);
+ sysbus_init_irq(sbd, &s->parent_fiq[i]);
}
memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
@@ -139,7 +90,6 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
{
GICv3State *s = ARM_GICV3_COMMON(dev);
- int i;
/* revision property is actually reserved and currently used only in order
* to keep the interface compatible with GICv2 code, avoiding extra
@@ -150,164 +100,11 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
error_setg(errp, "unsupported GIC revision %d", s->revision);
return;
}
-
- if (s->num_irq > GICV3_MAXIRQ) {
- error_setg(errp,
- "requested %u interrupt lines exceeds GIC maximum %d",
- s->num_irq, GICV3_MAXIRQ);
- return;
- }
- if (s->num_irq < GIC_INTERNAL) {
- error_setg(errp,
- "requested %u interrupt lines is below GIC minimum %d",
- s->num_irq, GIC_INTERNAL);
- return;
- }
-
- /* ITLinesNumber is represented as (N / 32) - 1, so this is an
- * implementation imposed restriction, not an architectural one,
- * so we don't have to deal with bitfields where only some of the
- * bits in a 32-bit word should be valid.
- */
- if (s->num_irq % 32) {
- error_setg(errp,
- "%d interrupt lines unsupported: not divisible by 32",
- s->num_irq);
- return;
- }
-
- s->cpu = g_new0(GICv3CPUState, s->num_cpu);
-
- for (i = 0; i < s->num_cpu; i++) {
- CPUState *cpu = qemu_get_cpu(i);
- uint64_t cpu_affid;
- int last;
-
- s->cpu[i].cpu = cpu;
- s->cpu[i].gic = s;
-
- /* Pre-construct the GICR_TYPER:
- * For our implementation:
- * Top 32 bits are the affinity value of the associated CPU
- * CommonLPIAff == 01 (redistributors with same Aff3 share LPI table)
- * Processor_Number == CPU index starting from 0
- * DPGS == 0 (GICR_CTLR.DPG* not supported)
- * Last == 1 if this is the last redistributor in a series of
- * contiguous redistributor pages
- * DirectLPI == 0 (direct injection of LPIs not supported)
- * VLPIS == 0 (virtual LPIs not supported)
- * PLPIS == 0 (physical LPIs not supported)
- */
- cpu_affid = object_property_get_int(OBJECT(cpu), "mp-affinity", NULL);
- last = (i == s->num_cpu - 1);
-
- /* The CPU mp-affinity property is in MPIDR register format; squash
- * the affinity bytes into 32 bits as the GICR_TYPER has them.
- */
- cpu_affid = (cpu_affid & 0xFF00000000ULL >> 8) | (cpu_affid & 0xFFFFFF);
- s->cpu[i].gicr_typer = (cpu_affid << 32) |
- (1 << 24) |
- (i << 8) |
- (last << 4);
- }
}
static void arm_gicv3_common_reset(DeviceState *dev)
{
- GICv3State *s = ARM_GICV3_COMMON(dev);
- int i;
-
- for (i = 0; i < s->num_cpu; i++) {
- GICv3CPUState *cs = &s->cpu[i];
-
- cs->level = 0;
- cs->gicr_ctlr = 0;
- cs->gicr_statusr[GICV3_S] = 0;
- cs->gicr_statusr[GICV3_NS] = 0;
- cs->gicr_waker = GICR_WAKER_ProcessorSleep | GICR_WAKER_ChildrenAsleep;
- cs->gicr_propbaser = 0;
- cs->gicr_pendbaser = 0;
- /* If we're resetting a TZ-aware GIC as if secure firmware
- * had set it up ready to start a kernel in non-secure, we
- * need to set interrupts to group 1 so the kernel can use them.
- * Otherwise they reset to group 0 like the hardware.
- */
- if (s->irq_reset_nonsecure) {
- cs->gicr_igroupr0 = 0xffffffff;
- } else {
- cs->gicr_igroupr0 = 0;
- }
-
- cs->gicr_ienabler0 = 0;
- cs->gicr_ipendr0 = 0;
- cs->gicr_iactiver0 = 0;
- cs->edge_trigger = 0xffff;
- cs->gicr_igrpmodr0 = 0;
- cs->gicr_nsacr = 0;
- memset(cs->gicr_ipriorityr, 0, sizeof(cs->gicr_ipriorityr));
-
- cs->hppi.prio = 0xff;
-
- /* State in the CPU interface must *not* be reset here, because it
- * is part of the CPU's reset domain, not the GIC device's.
- */
- }
-
- /* For our implementation affinity routing is always enabled */
- if (s->security_extn) {
- s->gicd_ctlr = GICD_CTLR_ARE_S | GICD_CTLR_ARE_NS;
- } else {
- s->gicd_ctlr = GICD_CTLR_DS | GICD_CTLR_ARE;
- }
-
- s->gicd_statusr[GICV3_S] = 0;
- s->gicd_statusr[GICV3_NS] = 0;
-
- memset(s->group, 0, sizeof(s->group));
- memset(s->grpmod, 0, sizeof(s->grpmod));
- memset(s->enabled, 0, sizeof(s->enabled));
- memset(s->pending, 0, sizeof(s->pending));
- memset(s->active, 0, sizeof(s->active));
- memset(s->level, 0, sizeof(s->level));
- memset(s->edge_trigger, 0, sizeof(s->edge_trigger));
- memset(s->gicd_ipriority, 0, sizeof(s->gicd_ipriority));
- memset(s->gicd_irouter, 0, sizeof(s->gicd_irouter));
- memset(s->gicd_nsacr, 0, sizeof(s->gicd_nsacr));
- /* GICD_IROUTER are UNKNOWN at reset so in theory the guest must
- * write these to get sane behaviour and we need not populate the
- * pointer cache here; however having the cache be different for
- * "happened to be 0 from reset" and "guest wrote 0" would be
- * too confusing.
- */
- gicv3_cache_all_target_cpustates(s);
-
- if (s->irq_reset_nonsecure) {
- /* If we're resetting a TZ-aware GIC as if secure firmware
- * had set it up ready to start a kernel in non-secure, we
- * need to set interrupts to group 1 so the kernel can use them.
- * Otherwise they reset to group 0 like the hardware.
- */
- for (i = GIC_INTERNAL; i < s->num_irq; i++) {
- gicv3_gicd_group_set(s, i);
- }
- }
-}
-
-static void arm_gic_common_linux_init(ARMLinuxBootIf *obj,
- bool secure_boot)
-{
- GICv3State *s = ARM_GICV3_COMMON(obj);
-
- if (s->security_extn && !secure_boot) {
- /* We're directly booting a kernel into NonSecure. If this GIC
- * implements the security extensions then we must configure it
- * to have all the interrupts be NonSecure (this is a job that
- * is done by the Secure boot firmware in real hardware, and in
- * this mode QEMU is acting as a minimalist firmware-and-bootloader
- * equivalent).
- */
- s->irq_reset_nonsecure = true;
- }
+ /* TODO */
}
static Property arm_gicv3_common_properties[] = {
@@ -321,13 +118,11 @@ static Property arm_gicv3_common_properties[] = {
static void arm_gicv3_common_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- ARMLinuxBootIfClass *albifc = ARM_LINUX_BOOT_IF_CLASS(klass);
dc->reset = arm_gicv3_common_reset;
dc->realize = arm_gicv3_common_realize;
dc->props = arm_gicv3_common_properties;
dc->vmsd = &vmstate_gicv3;
- albifc->arm_linux_init = arm_gic_common_linux_init;
}
static const TypeInfo arm_gicv3_common_type = {
@@ -337,10 +132,6 @@ static const TypeInfo arm_gicv3_common_type = {
.class_size = sizeof(ARMGICv3CommonClass),
.class_init = arm_gicv3_common_class_init,
.abstract = true,
- .interfaces = (InterfaceInfo []) {
- { TYPE_ARM_LINUX_BOOT_IF },
- { },
- },
};
static void register_types(void)
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
deleted file mode 100644
index 4633172be..000000000
--- a/hw/intc/arm_gicv3_cpuif.c
+++ /dev/null
@@ -1,1348 +0,0 @@
-/*
- * ARM Generic Interrupt Controller v3
- *
- * Copyright (c) 2016 Linaro Limited
- * Written by Peter Maydell
- *
- * This code is licensed under the GPL, version 2 or (at your option)
- * any later version.
- */
-
-/* This file contains the code for the system register interface
- * portions of the GICv3.
- */
-
-#include "qemu/osdep.h"
-#include "trace.h"
-#include "gicv3_internal.h"
-#include "cpu.h"
-
-static GICv3CPUState *icc_cs_from_env(CPUARMState *env)
-{
- /* Given the CPU, find the right GICv3CPUState struct.
- * Since we registered the CPU interface with the EL change hook as
- * the opaque pointer, we can just directly get from the CPU to it.
- */
- return arm_get_el_change_hook_opaque(arm_env_get_cpu(env));
-}
-
-static bool gicv3_use_ns_bank(CPUARMState *env)
-{
- /* Return true if we should use the NonSecure bank for a banked GIC
- * CPU interface register. Note that this differs from the
- * access_secure_reg() function because GICv3 banked registers are
- * banked even for AArch64, unlike the other CPU system registers.
- */
- return !arm_is_secure_below_el3(env);
-}
-
-static int icc_highest_active_prio(GICv3CPUState *cs)
-{
- /* Calculate the current running priority based on the set bits
- * in the Active Priority Registers.
- */
- int i;
-
- for (i = 0; i < ARRAY_SIZE(cs->icc_apr[0]); i++) {
- uint32_t apr = cs->icc_apr[GICV3_G0][i] |
- cs->icc_apr[GICV3_G1][i] | cs->icc_apr[GICV3_G1NS][i];
-
- if (!apr) {
- continue;
- }
- return (i * 32 + ctz32(apr)) << (GIC_MIN_BPR + 1);
- }
- /* No current active interrupts: return idle priority */
- return 0xff;
-}
-
-static uint32_t icc_gprio_mask(GICv3CPUState *cs, int group)
-{
- /* Return a mask word which clears the subpriority bits from
- * a priority value for an interrupt in the specified group.
- * This depends on the BPR value:
- * a BPR of 0 means the group priority bits are [7:1];
- * a BPR of 1 means they are [7:2], and so on down to
- * a BPR of 7 meaning no group priority bits at all.
- * Which BPR to use depends on the group of the interrupt and
- * the current ICC_CTLR.CBPR settings.
- */
- if ((group == GICV3_G1 && cs->icc_ctlr_el1[GICV3_S] & ICC_CTLR_EL1_CBPR) ||
- (group == GICV3_G1NS &&
- cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_CBPR)) {
- group = GICV3_G0;
- }
-
- return ~0U << ((cs->icc_bpr[group] & 7) + 1);
-}
-
-static bool icc_no_enabled_hppi(GICv3CPUState *cs)
-{
- /* Return true if there is no pending interrupt, or the
- * highest priority pending interrupt is in a group which has been
- * disabled at the CPU interface by the ICC_IGRPEN* register enable bits.
- */
- return cs->hppi.prio == 0xff || (cs->icc_igrpen[cs->hppi.grp] == 0);
-}
-
-static bool icc_hppi_can_preempt(GICv3CPUState *cs)
-{
- /* Return true if we have a pending interrupt of sufficient
- * priority to preempt.
- */
- int rprio;
- uint32_t mask;
-
- if (icc_no_enabled_hppi(cs)) {
- return false;
- }
-
- if (cs->hppi.prio >= cs->icc_pmr_el1) {
- /* Priority mask masks this interrupt */
- return false;
- }
-
- rprio = icc_highest_active_prio(cs);
- if (rprio == 0xff) {
- /* No currently running interrupt so we can preempt */
- return true;
- }
-
- mask = icc_gprio_mask(cs, cs->hppi.grp);
-
- /* We only preempt a running interrupt if the pending interrupt's
- * group priority is sufficient (the subpriorities are not considered).
- */
- if ((cs->hppi.prio & mask) < (rprio & mask)) {
- return true;
- }
-
- return false;
-}
-
-void gicv3_cpuif_update(GICv3CPUState *cs)
-{
- /* Tell the CPU about its highest priority pending interrupt */
- int irqlevel = 0;
- int fiqlevel = 0;
- ARMCPU *cpu = ARM_CPU(cs->cpu);
- CPUARMState *env = &cpu->env;
-
- trace_gicv3_cpuif_update(gicv3_redist_affid(cs), cs->hppi.irq,
- cs->hppi.grp, cs->hppi.prio);
-
- if (cs->hppi.grp == GICV3_G1 && !arm_feature(env, ARM_FEATURE_EL3)) {
- /* If a Security-enabled GIC sends a G1S interrupt to a
- * Security-disabled CPU, we must treat it as if it were G0.
- */
- cs->hppi.grp = GICV3_G0;
- }
-
- if (icc_hppi_can_preempt(cs)) {
- /* We have an interrupt: should we signal it as IRQ or FIQ?
- * This is described in the GICv3 spec section 4.6.2.
- */
- bool isfiq;
-
- switch (cs->hppi.grp) {
- case GICV3_G0:
- isfiq = true;
- break;
- case GICV3_G1:
- isfiq = (!arm_is_secure(env) ||
- (arm_current_el(env) == 3 && arm_el_is_aa64(env, 3)));
- break;
- case GICV3_G1NS:
- isfiq = arm_is_secure(env);
- break;
- default:
- g_assert_not_reached();
- }
-
- if (isfiq) {
- fiqlevel = 1;
- } else {
- irqlevel = 1;
- }
- }
-
- trace_gicv3_cpuif_set_irqs(gicv3_redist_affid(cs), fiqlevel, irqlevel);
-
- qemu_set_irq(cs->parent_fiq, fiqlevel);
- qemu_set_irq(cs->parent_irq, irqlevel);
-}
-
-static uint64_t icc_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- uint32_t value = cs->icc_pmr_el1;
-
- if (arm_feature(env, ARM_FEATURE_EL3) && !arm_is_secure(env) &&
- (env->cp15.scr_el3 & SCR_FIQ)) {
- /* NS access and Group 0 is inaccessible to NS: return the
- * NS view of the current priority
- */
- if (value & 0x80) {
- /* Secure priorities not visible to NS */
- value = 0;
- } else if (value != 0xff) {
- value = (value << 1) & 0xff;
- }
- }
-
- trace_gicv3_icc_pmr_read(gicv3_redist_affid(cs), value);
-
- return value;
-}
-
-static void icc_pmr_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
-
- trace_gicv3_icc_pmr_write(gicv3_redist_affid(cs), value);
-
- value &= 0xff;
-
- if (arm_feature(env, ARM_FEATURE_EL3) && !arm_is_secure(env) &&
- (env->cp15.scr_el3 & SCR_FIQ)) {
- /* NS access and Group 0 is inaccessible to NS: return the
- * NS view of the current priority
- */
- if (!(cs->icc_pmr_el1 & 0x80)) {
- /* Current PMR in the secure range, don't allow NS to change it */
- return;
- }
- value = (value >> 1) & 0x80;
- }
- cs->icc_pmr_el1 = value;
- gicv3_cpuif_update(cs);
-}
-
-static void icc_activate_irq(GICv3CPUState *cs, int irq)
-{
- /* Move the interrupt from the Pending state to Active, and update
- * the Active Priority Registers
- */
- uint32_t mask = icc_gprio_mask(cs, cs->hppi.grp);
- int prio = cs->hppi.prio & mask;
- int aprbit = prio >> 1;
- int regno = aprbit / 32;
- int regbit = aprbit % 32;
-
- cs->icc_apr[cs->hppi.grp][regno] |= (1 << regbit);
-
- if (irq < GIC_INTERNAL) {
- cs->gicr_iactiver0 = deposit32(cs->gicr_iactiver0, irq, 1, 1);
- cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 0);
- gicv3_redist_update(cs);
- } else {
- gicv3_gicd_active_set(cs->gic, irq);
- gicv3_gicd_pending_clear(cs->gic, irq);
- gicv3_update(cs->gic, irq, 1);
- }
-}
-
-static uint64_t icc_hppir0_value(GICv3CPUState *cs, CPUARMState *env)
-{
- /* Return the highest priority pending interrupt register value
- * for group 0.
- */
- bool irq_is_secure;
-
- if (cs->hppi.prio == 0xff) {
- return INTID_SPURIOUS;
- }
-
- /* Check whether we can return the interrupt or if we should return
- * a special identifier, as per the CheckGroup0ForSpecialIdentifiers
- * pseudocode. (We can simplify a little because for us ICC_SRE_EL1.RM
- * is always zero.)
- */
- irq_is_secure = (!(cs->gic->gicd_ctlr & GICD_CTLR_DS) &&
- (cs->hppi.grp != GICV3_G1NS));
-
- if (cs->hppi.grp != GICV3_G0 && !arm_is_el3_or_mon(env)) {
- return INTID_SPURIOUS;
- }
- if (irq_is_secure && !arm_is_secure(env)) {
- /* Secure interrupts not visible to Nonsecure */
- return INTID_SPURIOUS;
- }
-
- if (cs->hppi.grp != GICV3_G0) {
- /* Indicate to EL3 that there's a Group 1 interrupt for the other
- * state pending.
- */
- return irq_is_secure ? INTID_SECURE : INTID_NONSECURE;
- }
-
- return cs->hppi.irq;
-}
-
-static uint64_t icc_hppir1_value(GICv3CPUState *cs, CPUARMState *env)
-{
- /* Return the highest priority pending interrupt register value
- * for group 1.
- */
- bool irq_is_secure;
-
- if (cs->hppi.prio == 0xff) {
- return INTID_SPURIOUS;
- }
-
- /* Check whether we can return the interrupt or if we should return
- * a special identifier, as per the CheckGroup1ForSpecialIdentifiers
- * pseudocode. (We can simplify a little because for us ICC_SRE_EL1.RM
- * is always zero.)
- */
- irq_is_secure = (!(cs->gic->gicd_ctlr & GICD_CTLR_DS) &&
- (cs->hppi.grp != GICV3_G1NS));
-
- if (cs->hppi.grp == GICV3_G0) {
- /* Group 0 interrupts not visible via HPPIR1 */
- return INTID_SPURIOUS;
- }
- if (irq_is_secure) {
- if (!arm_is_secure(env)) {
- /* Secure interrupts not visible in Non-secure */
- return INTID_SPURIOUS;
- }
- } else if (!arm_is_el3_or_mon(env) && arm_is_secure(env)) {
- /* Group 1 non-secure interrupts not visible in Secure EL1 */
- return INTID_SPURIOUS;
- }
-
- return cs->hppi.irq;
-}
-
-static uint64_t icc_iar0_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- uint64_t intid;
-
- if (!icc_hppi_can_preempt(cs)) {
- intid = INTID_SPURIOUS;
- } else {
- intid = icc_hppir0_value(cs, env);
- }
-
- if (!(intid >= INTID_SECURE && intid <= INTID_SPURIOUS)) {
- icc_activate_irq(cs, intid);
- }
-
- trace_gicv3_icc_iar0_read(gicv3_redist_affid(cs), intid);
- return intid;
-}
-
-static uint64_t icc_iar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- uint64_t intid;
-
- if (!icc_hppi_can_preempt(cs)) {
- intid = INTID_SPURIOUS;
- } else {
- intid = icc_hppir1_value(cs, env);
- }
-
- if (!(intid >= INTID_SECURE && intid <= INTID_SPURIOUS)) {
- icc_activate_irq(cs, intid);
- }
-
- trace_gicv3_icc_iar1_read(gicv3_redist_affid(cs), intid);
- return intid;
-}
-
-static void icc_drop_prio(GICv3CPUState *cs, int grp)
-{
- /* Drop the priority of the currently active interrupt in
- * the specified group.
- *
- * Note that we can guarantee (because of the requirement to nest
- * ICC_IAR reads [which activate an interrupt and raise priority]
- * with ICC_EOIR writes [which drop the priority for the interrupt])
- * that the interrupt we're being called for is the highest priority
- * active interrupt, meaning that it has the lowest set bit in the
- * APR registers.
- *
- * If the guest does not honour the ordering constraints then the
- * behaviour of the GIC is UNPREDICTABLE, which for us means that
- * the values of the APR registers might become incorrect and the
- * running priority will be wrong, so interrupts that should preempt
- * might not do so, and interrupts that should not preempt might do so.
- */
- int i;
-
- for (i = 0; i < ARRAY_SIZE(cs->icc_apr[grp]); i++) {
- uint64_t *papr = &cs->icc_apr[grp][i];
-
- if (!*papr) {
- continue;
- }
- /* Clear the lowest set bit */
- *papr &= *papr - 1;
- break;
- }
-
- /* running priority change means we need an update for this cpu i/f */
- gicv3_cpuif_update(cs);
-}
-
-static bool icc_eoi_split(CPUARMState *env, GICv3CPUState *cs)
-{
- /* Return true if we should split priority drop and interrupt
- * deactivation, ie whether the relevant EOIMode bit is set.
- */
- if (arm_is_el3_or_mon(env)) {
- return cs->icc_ctlr_el3 & ICC_CTLR_EL3_EOIMODE_EL3;
- }
- if (arm_is_secure_below_el3(env)) {
- return cs->icc_ctlr_el1[GICV3_S] & ICC_CTLR_EL1_EOIMODE;
- } else {
- return cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_EOIMODE;
- }
-}
-
-static int icc_highest_active_group(GICv3CPUState *cs)
-{
- /* Return the group with the highest priority active interrupt.
- * We can do this by just comparing the APRs to see which one
- * has the lowest set bit.
- * (If more than one group is active at the same priority then
- * we're in UNPREDICTABLE territory.)
- */
- int i;
-
- for (i = 0; i < ARRAY_SIZE(cs->icc_apr[0]); i++) {
- int g0ctz = ctz32(cs->icc_apr[GICV3_G0][i]);
- int g1ctz = ctz32(cs->icc_apr[GICV3_G1][i]);
- int g1nsctz = ctz32(cs->icc_apr[GICV3_G1NS][i]);
-
- if (g1nsctz < g0ctz && g1nsctz < g1ctz) {
- return GICV3_G1NS;
- }
- if (g1ctz < g0ctz) {
- return GICV3_G1;
- }
- if (g0ctz < 32) {
- return GICV3_G0;
- }
- }
- /* No set active bits? UNPREDICTABLE; return -1 so the caller
- * ignores the spurious EOI attempt.
- */
- return -1;
-}
-
-static void icc_deactivate_irq(GICv3CPUState *cs, int irq)
-{
- if (irq < GIC_INTERNAL) {
- cs->gicr_iactiver0 = deposit32(cs->gicr_iactiver0, irq, 1, 0);
- gicv3_redist_update(cs);
- } else {
- gicv3_gicd_active_clear(cs->gic, irq);
- gicv3_update(cs->gic, irq, 1);
- }
-}
-
-static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- /* End of Interrupt */
- GICv3CPUState *cs = icc_cs_from_env(env);
- int irq = value & 0xffffff;
- int grp;
-
- trace_gicv3_icc_eoir_write(gicv3_redist_affid(cs), value);
-
- if (ri->crm == 8) {
- /* EOIR0 */
- grp = GICV3_G0;
- } else {
- /* EOIR1 */
- if (arm_is_secure(env)) {
- grp = GICV3_G1;
- } else {
- grp = GICV3_G1NS;
- }
- }
-
- if (irq >= cs->gic->num_irq) {
- /* This handles two cases:
- * 1. If software writes the ID of a spurious interrupt [ie 1020-1023]
- * to the GICC_EOIR, the GIC ignores that write.
- * 2. If software writes the number of a non-existent interrupt
- * this must be a subcase of "value written does not match the last
- * valid interrupt value read from the Interrupt Acknowledge
- * register" and so this is UNPREDICTABLE. We choose to ignore it.
- */
- return;
- }
-
- if (icc_highest_active_group(cs) != grp) {
- return;
- }
-
- icc_drop_prio(cs, grp);
-
- if (!icc_eoi_split(env, cs)) {
- /* Priority drop and deactivate not split: deactivate irq now */
- icc_deactivate_irq(cs, irq);
- }
-}
-
-static uint64_t icc_hppir0_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- uint64_t value = icc_hppir0_value(cs, env);
-
- trace_gicv3_icc_hppir0_read(gicv3_redist_affid(cs), value);
- return value;
-}
-
-static uint64_t icc_hppir1_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- uint64_t value = icc_hppir1_value(cs, env);
-
- trace_gicv3_icc_hppir1_read(gicv3_redist_affid(cs), value);
- return value;
-}
-
-static uint64_t icc_bpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- int grp = (ri->crm == 8) ? GICV3_G0 : GICV3_G1;
- bool satinc = false;
- uint64_t bpr;
-
- if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
- grp = GICV3_G1NS;
- }
-
- if (grp == GICV3_G1 && !arm_is_el3_or_mon(env) &&
- (cs->icc_ctlr_el1[GICV3_S] & ICC_CTLR_EL1_CBPR)) {
- /* CBPR_EL1S means secure EL1 or AArch32 EL3 !Mon BPR1 accesses
- * modify BPR0
- */
- grp = GICV3_G0;
- }
-
- if (grp == GICV3_G1NS && arm_current_el(env) < 3 &&
- (cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_CBPR)) {
- /* reads return bpr0 + 1 sat to 7, writes ignored */
- grp = GICV3_G0;
- satinc = true;
- }
-
- bpr = cs->icc_bpr[grp];
- if (satinc) {
- bpr++;
- bpr = MIN(bpr, 7);
- }
-
- trace_gicv3_icc_bpr_read(gicv3_redist_affid(cs), bpr);
-
- return bpr;
-}
-
-static void icc_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- int grp = (ri->crm == 8) ? GICV3_G0 : GICV3_G1;
-
- trace_gicv3_icc_pmr_write(gicv3_redist_affid(cs), value);
-
- if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
- grp = GICV3_G1NS;
- }
-
- if (grp == GICV3_G1 && !arm_is_el3_or_mon(env) &&
- (cs->icc_ctlr_el1[GICV3_S] & ICC_CTLR_EL1_CBPR)) {
- /* CBPR_EL1S means secure EL1 or AArch32 EL3 !Mon BPR1 accesses
- * modify BPR0
- */
- grp = GICV3_G0;
- }
-
- if (grp == GICV3_G1NS && arm_current_el(env) < 3 &&
- (cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_CBPR)) {
- /* reads return bpr0 + 1 sat to 7, writes ignored */
- return;
- }
-
- cs->icc_bpr[grp] = value & 7;
- gicv3_cpuif_update(cs);
-}
-
-static uint64_t icc_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- uint64_t value;
-
- int regno = ri->opc2 & 3;
- int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1;
-
- if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
- grp = GICV3_G1NS;
- }
-
- value = cs->icc_apr[grp][regno];
-
- trace_gicv3_icc_ap_read(regno, gicv3_redist_affid(cs), value);
- return value;
-}
-
-static void icc_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
-
- int regno = ri->opc2 & 3;
- int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1;
-
- trace_gicv3_icc_ap_write(regno, gicv3_redist_affid(cs), value);
-
- if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
- grp = GICV3_G1NS;
- }
-
- /* It's not possible to claim that a Non-secure interrupt is active
- * at a priority outside the Non-secure range (128..255), since this
- * would otherwise allow malicious NS code to block delivery of S interrupts
- * by writing a bad value to these registers.
- */
- if (grp == GICV3_G1NS && regno < 2 && arm_feature(env, ARM_FEATURE_EL3)) {
- return;
- }
-
- cs->icc_apr[grp][regno] = value & 0xFFFFFFFFU;
- gicv3_cpuif_update(cs);
-}
-
-static void icc_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- /* Deactivate interrupt */
- GICv3CPUState *cs = icc_cs_from_env(env);
- int irq = value & 0xffffff;
- bool irq_is_secure, single_sec_state, irq_is_grp0;
- bool route_fiq_to_el3, route_irq_to_el3, route_fiq_to_el2, route_irq_to_el2;
-
- trace_gicv3_icc_dir_write(gicv3_redist_affid(cs), value);
-
- if (irq >= cs->gic->num_irq) {
- /* Also catches special interrupt numbers and LPIs */
- return;
- }
-
- if (!icc_eoi_split(env, cs)) {
- return;
- }
-
- int grp = gicv3_irq_group(cs->gic, cs, irq);
-
- single_sec_state = cs->gic->gicd_ctlr & GICD_CTLR_DS;
- irq_is_secure = !single_sec_state && (grp != GICV3_G1NS);
- irq_is_grp0 = grp == GICV3_G0;
-
- /* Check whether we're allowed to deactivate this interrupt based
- * on its group and the current CPU state.
- * These checks are laid out to correspond to the spec's pseudocode.
- */
- route_fiq_to_el3 = env->cp15.scr_el3 & SCR_FIQ;
- route_irq_to_el3 = env->cp15.scr_el3 & SCR_IRQ;
- /* No need to include !IsSecure in route_*_to_el2 as it's only
- * tested in cases where we know !IsSecure is true.
- */
- route_fiq_to_el2 = env->cp15.hcr_el2 & HCR_FMO;
- route_irq_to_el2 = env->cp15.hcr_el2 & HCR_FMO;
-
- switch (arm_current_el(env)) {
- case 3:
- break;
- case 2:
- if (single_sec_state && irq_is_grp0 && !route_fiq_to_el3) {
- break;
- }
- if (!irq_is_secure && !irq_is_grp0 && !route_irq_to_el3) {
- break;
- }
- return;
- case 1:
- if (!arm_is_secure_below_el3(env)) {
- if (single_sec_state && irq_is_grp0 &&
- !route_fiq_to_el3 && !route_fiq_to_el2) {
- break;
- }
- if (!irq_is_secure && !irq_is_grp0 &&
- !route_irq_to_el3 && !route_irq_to_el2) {
- break;
- }
- } else {
- if (irq_is_grp0 && !route_fiq_to_el3) {
- break;
- }
- if (!irq_is_grp0 &&
- (!irq_is_secure || !single_sec_state) &&
- !route_irq_to_el3) {
- break;
- }
- }
- return;
- default:
- g_assert_not_reached();
- }
-
- icc_deactivate_irq(cs, irq);
-}
-
-static uint64_t icc_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- int prio = icc_highest_active_prio(cs);
-
- if (arm_feature(env, ARM_FEATURE_EL3) &&
- !arm_is_secure(env) && (env->cp15.scr_el3 & SCR_FIQ)) {
- /* NS GIC access and Group 0 is inaccessible to NS */
- if (prio & 0x80) {
- /* NS mustn't see priorities in the Secure half of the range */
- prio = 0;
- } else if (prio != 0xff) {
- /* Non-idle priority: show the Non-secure view of it */
- prio = (prio << 1) & 0xff;
- }
- }
-
- trace_gicv3_icc_rpr_read(gicv3_redist_affid(cs), prio);
- return prio;
-}
-
-static void icc_generate_sgi(CPUARMState *env, GICv3CPUState *cs,
- uint64_t value, int grp, bool ns)
-{
- GICv3State *s = cs->gic;
-
- /* Extract Aff3/Aff2/Aff1 and shift into the bottom 24 bits */
- uint64_t aff = extract64(value, 48, 8) << 16 |
- extract64(value, 32, 8) << 8 |
- extract64(value, 16, 8);
- uint32_t targetlist = extract64(value, 0, 16);
- uint32_t irq = extract64(value, 24, 4);
- bool irm = extract64(value, 40, 1);
- int i;
-
- if (grp == GICV3_G1 && s->gicd_ctlr & GICD_CTLR_DS) {
- /* If GICD_CTLR.DS == 1, the Distributor treats Secure Group 1
- * interrupts as Group 0 interrupts and must send Secure Group 0
- * interrupts to the target CPUs.
- */
- grp = GICV3_G0;
- }
-
- trace_gicv3_icc_generate_sgi(gicv3_redist_affid(cs), irq, irm,
- aff, targetlist);
-
- for (i = 0; i < s->num_cpu; i++) {
- GICv3CPUState *ocs = &s->cpu[i];
-
- if (irm) {
- /* IRM == 1 : route to all CPUs except self */
- if (cs == ocs) {
- continue;
- }
- } else {
- /* IRM == 0 : route to Aff3.Aff2.Aff1.n for all n in [0..15]
- * where the corresponding bit is set in targetlist
- */
- int aff0;
-
- if (ocs->gicr_typer >> 40 != aff) {
- continue;
- }
- aff0 = extract64(ocs->gicr_typer, 32, 8);
- if (aff0 > 15 || extract32(targetlist, aff0, 1) == 0) {
- continue;
- }
- }
-
- /* The redistributor will check against its own GICR_NSACR as needed */
- gicv3_redist_send_sgi(ocs, grp, irq, ns);
- }
-}
-
-static void icc_sgi0r_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- /* Generate Secure Group 0 SGI. */
- GICv3CPUState *cs = icc_cs_from_env(env);
- bool ns = !arm_is_secure(env);
-
- icc_generate_sgi(env, cs, value, GICV3_G0, ns);
-}
-
-static void icc_sgi1r_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- /* Generate Group 1 SGI for the current Security state */
- GICv3CPUState *cs = icc_cs_from_env(env);
- int grp;
- bool ns = !arm_is_secure(env);
-
- grp = ns ? GICV3_G1NS : GICV3_G1;
- icc_generate_sgi(env, cs, value, grp, ns);
-}
-
-static void icc_asgi1r_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- /* Generate Group 1 SGI for the Security state that is not
- * the current state
- */
- GICv3CPUState *cs = icc_cs_from_env(env);
- int grp;
- bool ns = !arm_is_secure(env);
-
- grp = ns ? GICV3_G1 : GICV3_G1NS;
- icc_generate_sgi(env, cs, value, grp, ns);
-}
-
-static uint64_t icc_igrpen_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- int grp = ri->opc2 & 1 ? GICV3_G1 : GICV3_G0;
- uint64_t value;
-
- if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
- grp = GICV3_G1NS;
- }
-
- value = cs->icc_igrpen[grp];
- trace_gicv3_icc_igrpen_read(gicv3_redist_affid(cs), value);
- return value;
-}
-
-static void icc_igrpen_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- int grp = ri->opc2 & 1 ? GICV3_G1 : GICV3_G0;
-
- trace_gicv3_icc_igrpen_write(gicv3_redist_affid(cs), value);
-
- if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
- grp = GICV3_G1NS;
- }
-
- cs->icc_igrpen[grp] = value & ICC_IGRPEN_ENABLE;
- gicv3_cpuif_update(cs);
-}
-
-static uint64_t icc_igrpen1_el3_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
-
- /* IGRPEN1_EL3 bits 0 and 1 are r/w aliases into IGRPEN1_EL1 NS and S */
- return cs->icc_igrpen[GICV3_G1NS] | (cs->icc_igrpen[GICV3_G1] << 1);
-}
-
-static void icc_igrpen1_el3_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
-
- trace_gicv3_icc_igrpen1_el3_write(gicv3_redist_affid(cs), value);
-
- /* IGRPEN1_EL3 bits 0 and 1 are r/w aliases into IGRPEN1_EL1 NS and S */
- cs->icc_igrpen[GICV3_G1NS] = extract32(value, 0, 1);
- cs->icc_igrpen[GICV3_G1] = extract32(value, 1, 1);
- gicv3_cpuif_update(cs);
-}
-
-static uint64_t icc_ctlr_el1_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- int bank = gicv3_use_ns_bank(env) ? GICV3_NS : GICV3_S;
- uint64_t value;
-
- value = cs->icc_ctlr_el1[bank];
- trace_gicv3_icc_ctlr_read(gicv3_redist_affid(cs), value);
- return value;
-}
-
-static void icc_ctlr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- int bank = gicv3_use_ns_bank(env) ? GICV3_NS : GICV3_S;
- uint64_t mask;
-
- trace_gicv3_icc_ctlr_write(gicv3_redist_affid(cs), value);
-
- /* Only CBPR and EOIMODE can be RW;
- * for us PMHE is RAZ/WI (we don't implement 1-of-N interrupts or
- * the asseciated priority-based routing of them);
- * if EL3 is implemented and GICD_CTLR.DS == 0, then PMHE and CBPR are RO.
- */
- if (arm_feature(env, ARM_FEATURE_EL3) &&
- ((cs->gic->gicd_ctlr & GICD_CTLR_DS) == 0)) {
- mask = ICC_CTLR_EL1_EOIMODE;
- } else {
- mask = ICC_CTLR_EL1_CBPR | ICC_CTLR_EL1_EOIMODE;
- }
-
- cs->icc_ctlr_el1[bank] &= ~mask;
- cs->icc_ctlr_el1[bank] |= (value & mask);
- gicv3_cpuif_update(cs);
-}
-
-
-static uint64_t icc_ctlr_el3_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- uint64_t value;
-
- value = cs->icc_ctlr_el3;
- if (cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_EOIMODE) {
- value |= ICC_CTLR_EL3_EOIMODE_EL1NS;
- }
- if (cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_CBPR) {
- value |= ICC_CTLR_EL3_CBPR_EL1NS;
- }
- if (cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_EOIMODE) {
- value |= ICC_CTLR_EL3_EOIMODE_EL1S;
- }
- if (cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_CBPR) {
- value |= ICC_CTLR_EL3_CBPR_EL1S;
- }
-
- trace_gicv3_icc_ctlr_el3_read(gicv3_redist_affid(cs), value);
- return value;
-}
-
-static void icc_ctlr_el3_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
- uint64_t mask;
-
- trace_gicv3_icc_ctlr_el3_write(gicv3_redist_affid(cs), value);
-
- /* *_EL1NS and *_EL1S bits are aliases into the ICC_CTLR_EL1 bits. */
- cs->icc_ctlr_el1[GICV3_NS] &= (ICC_CTLR_EL1_CBPR | ICC_CTLR_EL1_EOIMODE);
- if (value & ICC_CTLR_EL3_EOIMODE_EL1NS) {
- cs->icc_ctlr_el1[GICV3_NS] |= ICC_CTLR_EL1_EOIMODE;
- }
- if (value & ICC_CTLR_EL3_CBPR_EL1NS) {
- cs->icc_ctlr_el1[GICV3_NS] |= ICC_CTLR_EL1_CBPR;
- }
-
- cs->icc_ctlr_el1[GICV3_S] &= (ICC_CTLR_EL1_CBPR | ICC_CTLR_EL1_EOIMODE);
- if (value & ICC_CTLR_EL3_EOIMODE_EL1S) {
- cs->icc_ctlr_el1[GICV3_S] |= ICC_CTLR_EL1_EOIMODE;
- }
- if (value & ICC_CTLR_EL3_CBPR_EL1S) {
- cs->icc_ctlr_el1[GICV3_S] |= ICC_CTLR_EL1_CBPR;
- }
-
- /* The only bit stored in icc_ctlr_el3 which is writeable is EOIMODE_EL3: */
- mask = ICC_CTLR_EL3_EOIMODE_EL3;
-
- cs->icc_ctlr_el3 &= ~mask;
- cs->icc_ctlr_el3 |= (value & mask);
- gicv3_cpuif_update(cs);
-}
-
-static CPAccessResult gicv3_irqfiq_access(CPUARMState *env,
- const ARMCPRegInfo *ri, bool isread)
-{
- CPAccessResult r = CP_ACCESS_OK;
-
- if ((env->cp15.scr_el3 & (SCR_FIQ | SCR_IRQ)) == (SCR_FIQ | SCR_IRQ)) {
- switch (arm_current_el(env)) {
- case 1:
- if (arm_is_secure_below_el3(env) ||
- ((env->cp15.hcr_el2 & (HCR_IMO | HCR_FMO)) == 0)) {
- r = CP_ACCESS_TRAP_EL3;
- }
- break;
- case 2:
- r = CP_ACCESS_TRAP_EL3;
- break;
- case 3:
- if (!is_a64(env) && !arm_is_el3_or_mon(env)) {
- r = CP_ACCESS_TRAP_EL3;
- }
- break;
- default:
- g_assert_not_reached();
- }
- }
-
- if (r == CP_ACCESS_TRAP_EL3 && !arm_el_is_aa64(env, 3)) {
- r = CP_ACCESS_TRAP;
- }
- return r;
-}
-
-static CPAccessResult gicv3_fiq_access(CPUARMState *env,
- const ARMCPRegInfo *ri, bool isread)
-{
- CPAccessResult r = CP_ACCESS_OK;
-
- if (env->cp15.scr_el3 & SCR_FIQ) {
- switch (arm_current_el(env)) {
- case 1:
- if (arm_is_secure_below_el3(env) ||
- ((env->cp15.hcr_el2 & HCR_FMO) == 0)) {
- r = CP_ACCESS_TRAP_EL3;
- }
- break;
- case 2:
- r = CP_ACCESS_TRAP_EL3;
- break;
- case 3:
- if (!is_a64(env) && !arm_is_el3_or_mon(env)) {
- r = CP_ACCESS_TRAP_EL3;
- }
- break;
- default:
- g_assert_not_reached();
- }
- }
-
- if (r == CP_ACCESS_TRAP_EL3 && !arm_el_is_aa64(env, 3)) {
- r = CP_ACCESS_TRAP;
- }
- return r;
-}
-
-static CPAccessResult gicv3_irq_access(CPUARMState *env,
- const ARMCPRegInfo *ri, bool isread)
-{
- CPAccessResult r = CP_ACCESS_OK;
-
- if (env->cp15.scr_el3 & SCR_IRQ) {
- switch (arm_current_el(env)) {
- case 1:
- if (arm_is_secure_below_el3(env) ||
- ((env->cp15.hcr_el2 & HCR_IMO) == 0)) {
- r = CP_ACCESS_TRAP_EL3;
- }
- break;
- case 2:
- r = CP_ACCESS_TRAP_EL3;
- break;
- case 3:
- if (!is_a64(env) && !arm_is_el3_or_mon(env)) {
- r = CP_ACCESS_TRAP_EL3;
- }
- break;
- default:
- g_assert_not_reached();
- }
- }
-
- if (r == CP_ACCESS_TRAP_EL3 && !arm_el_is_aa64(env, 3)) {
- r = CP_ACCESS_TRAP;
- }
- return r;
-}
-
-static void icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- GICv3CPUState *cs = icc_cs_from_env(env);
-
- cs->icc_ctlr_el1[GICV3_S] = ICC_CTLR_EL1_A3V |
- (1 << ICC_CTLR_EL1_IDBITS_SHIFT) |
- (7 << ICC_CTLR_EL1_PRIBITS_SHIFT);
- cs->icc_ctlr_el1[GICV3_NS] = ICC_CTLR_EL1_A3V |
- (1 << ICC_CTLR_EL1_IDBITS_SHIFT) |
- (7 << ICC_CTLR_EL1_PRIBITS_SHIFT);
- cs->icc_pmr_el1 = 0;
- cs->icc_bpr[GICV3_G0] = GIC_MIN_BPR;
- cs->icc_bpr[GICV3_G1] = GIC_MIN_BPR;
- if (arm_feature(env, ARM_FEATURE_EL3)) {
- cs->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR_NS;
- } else {
- cs->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR;
- }
- memset(cs->icc_apr, 0, sizeof(cs->icc_apr));
- memset(cs->icc_igrpen, 0, sizeof(cs->icc_igrpen));
- cs->icc_ctlr_el3 = ICC_CTLR_EL3_NDS | ICC_CTLR_EL3_A3V |
- (1 << ICC_CTLR_EL3_IDBITS_SHIFT) |
- (7 << ICC_CTLR_EL3_PRIBITS_SHIFT);
-}
-
-static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
- { .name = "ICC_PMR_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 6, .opc2 = 0,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_irqfiq_access,
- .readfn = icc_pmr_read,
- .writefn = icc_pmr_write,
- /* We hang the whole cpu interface reset routine off here
- * rather than parcelling it out into one little function
- * per register
- */
- .resetfn = icc_reset,
- },
- { .name = "ICC_IAR0_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 0,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_R, .accessfn = gicv3_fiq_access,
- .readfn = icc_iar0_read,
- },
- { .name = "ICC_EOIR0_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 1,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_W, .accessfn = gicv3_fiq_access,
- .writefn = icc_eoir_write,
- },
- { .name = "ICC_HPPIR0_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 2,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_R, .accessfn = gicv3_fiq_access,
- .readfn = icc_hppir0_read,
- },
- { .name = "ICC_BPR0_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 3,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_fiq_access,
- .fieldoffset = offsetof(GICv3CPUState, icc_bpr[GICV3_G0]),
- .writefn = icc_bpr_write,
- },
- { .name = "ICC_AP0R0_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 4,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_fiq_access,
- .fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][0]),
- .writefn = icc_ap_write,
- },
- { .name = "ICC_AP0R1_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 5,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_fiq_access,
- .fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][1]),
- .writefn = icc_ap_write,
- },
- { .name = "ICC_AP0R2_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 6,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_fiq_access,
- .fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][2]),
- .writefn = icc_ap_write,
- },
- { .name = "ICC_AP0R3_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 7,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_fiq_access,
- .fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][3]),
- .writefn = icc_ap_write,
- },
- /* All the ICC_AP1R*_EL1 registers are banked */
- { .name = "ICC_AP1R0_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 9, .opc2 = 0,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_irq_access,
- .readfn = icc_ap_read,
- .writefn = icc_ap_write,
- },
- { .name = "ICC_AP1R1_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 9, .opc2 = 1,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_irq_access,
- .readfn = icc_ap_read,
- .writefn = icc_ap_write,
- },
- { .name = "ICC_AP1R2_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 9, .opc2 = 2,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_irq_access,
- .readfn = icc_ap_read,
- .writefn = icc_ap_write,
- },
- { .name = "ICC_AP1R3_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 9, .opc2 = 3,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_irq_access,
- .readfn = icc_ap_read,
- .writefn = icc_ap_write,
- },
- { .name = "ICC_DIR_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 1,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_W, .accessfn = gicv3_irqfiq_access,
- .writefn = icc_dir_write,
- },
- { .name = "ICC_RPR_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 3,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_R, .accessfn = gicv3_irqfiq_access,
- .readfn = icc_rpr_read,
- },
- { .name = "ICC_SGI1R_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 5,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_W, .accessfn = gicv3_irqfiq_access,
- .writefn = icc_sgi1r_write,
- },
- { .name = "ICC_SGI1R",
- .cp = 15, .opc1 = 0, .crm = 12,
- .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_W, .accessfn = gicv3_irqfiq_access,
- .writefn = icc_sgi1r_write,
- },
- { .name = "ICC_ASGI1R_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 6,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_W, .accessfn = gicv3_irqfiq_access,
- .writefn = icc_asgi1r_write,
- },
- { .name = "ICC_ASGI1R",
- .cp = 15, .opc1 = 1, .crm = 12,
- .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_W, .accessfn = gicv3_irqfiq_access,
- .writefn = icc_asgi1r_write,
- },
- { .name = "ICC_SGI0R_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 11, .opc2 = 7,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_W, .accessfn = gicv3_irqfiq_access,
- .writefn = icc_sgi0r_write,
- },
- { .name = "ICC_SGI0R",
- .cp = 15, .opc1 = 2, .crm = 12,
- .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_W, .accessfn = gicv3_irqfiq_access,
- .writefn = icc_sgi0r_write,
- },
- { .name = "ICC_IAR1_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 0,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_R, .accessfn = gicv3_irq_access,
- .readfn = icc_iar1_read,
- },
- { .name = "ICC_EOIR1_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 1,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_W, .accessfn = gicv3_irq_access,
- .writefn = icc_eoir_write,
- },
- { .name = "ICC_HPPIR1_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 2,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_R, .accessfn = gicv3_irq_access,
- .readfn = icc_hppir1_read,
- },
- /* This register is banked */
- { .name = "ICC_BPR1_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 3,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_irq_access,
- .readfn = icc_bpr_read,
- .writefn = icc_bpr_write,
- },
- /* This register is banked */
- { .name = "ICC_CTLR_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 4,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_irqfiq_access,
- .readfn = icc_ctlr_el1_read,
- .writefn = icc_ctlr_el1_write,
- },
- { .name = "ICC_SRE_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 5,
- .type = ARM_CP_NO_RAW | ARM_CP_CONST,
- .access = PL1_RW,
- /* We don't support IRQ/FIQ bypass and system registers are
- * always enabled, so all our bits are RAZ/WI or RAO/WI.
- * This register is banked but since it's constant we don't
- * need to do anything special.
- */
- .resetvalue = 0x7,
- },
- { .name = "ICC_IGRPEN0_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 6,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_fiq_access,
- .fieldoffset = offsetof(GICv3CPUState, icc_igrpen[GICV3_G0]),
- .writefn = icc_igrpen_write,
- },
- /* This register is banked */
- { .name = "ICC_IGRPEN1_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 7,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL1_RW, .accessfn = gicv3_irq_access,
- .readfn = icc_igrpen_read,
- .writefn = icc_igrpen_write,
- },
- { .name = "ICC_SRE_EL2", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 9, .opc2 = 5,
- .type = ARM_CP_NO_RAW | ARM_CP_CONST,
- .access = PL2_RW,
- /* We don't support IRQ/FIQ bypass and system registers are
- * always enabled, so all our bits are RAZ/WI or RAO/WI.
- */
- .resetvalue = 0xf,
- },
- { .name = "ICC_CTLR_EL3", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 12, .opc2 = 4,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL3_RW,
- .fieldoffset = offsetof(GICv3CPUState, icc_ctlr_el3),
- .readfn = icc_ctlr_el3_read,
- .writefn = icc_ctlr_el3_write,
- },
- { .name = "ICC_SRE_EL3", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 12, .opc2 = 5,
- .type = ARM_CP_NO_RAW | ARM_CP_CONST,
- .access = PL3_RW,
- /* We don't support IRQ/FIQ bypass and system registers are
- * always enabled, so all our bits are RAZ/WI or RAO/WI.
- */
- .resetvalue = 0xf,
- },
- { .name = "ICC_IGRPEN1_EL3", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 12, .opc2 = 7,
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
- .access = PL3_RW,
- .readfn = icc_igrpen1_el3_read,
- .writefn = icc_igrpen1_el3_write,
- },
- REGINFO_SENTINEL
-};
-
-static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
-{
- GICv3CPUState *cs = opaque;
-
- gicv3_cpuif_update(cs);
-}
-
-void gicv3_init_cpuif(GICv3State *s)
-{
- /* Called from the GICv3 realize function; register our system
- * registers with the CPU
- */
- int i;
-
- for (i = 0; i < s->num_cpu; i++) {
- ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
- GICv3CPUState *cs = &s->cpu[i];
-
- /* Note that we can't just use the GICv3CPUState as an opaque pointer
- * in define_arm_cp_regs_with_opaque(), because when we're called back
- * it might be with code translated by CPU 0 but run by CPU 1, in
- * which case we'd get the wrong value.
- * So instead we define the regs with no ri->opaque info, and
- * get back to the GICv3CPUState from the ARMCPU by reading back
- * the opaque pointer from the el_change_hook, which we're going
- * to need to register anyway.
- */
- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
- arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs);
- }
-}
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
deleted file mode 100644
index 3ea3dd0d4..000000000
--- a/hw/intc/arm_gicv3_dist.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
- * ARM GICv3 emulation: Distributor
- *
- * 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.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "trace.h"
-#include "gicv3_internal.h"
-
-/* The GICD_NSACR registers contain a two bit field for each interrupt which
- * allows the guest to give NonSecure code access to registers controlling
- * Secure interrupts:
- * 0b00: no access (NS accesses to bits for Secure interrupts will RAZ/WI)
- * 0b01: NS r/w accesses permitted to ISPENDR, SETSPI_NSR, SGIR
- * 0b10: as 0b01, and also r/w to ICPENDR, r/o to ISACTIVER/ICACTIVER,
- * and w/o to CLRSPI_NSR
- * 0b11: as 0b10, and also r/w to IROUTER and ITARGETSR
- *
- * Given a (multiple-of-32) interrupt number, these mask functions return
- * a mask word where each bit is 1 if the NSACR settings permit access
- * to the interrupt. The mask returned can then be ORed with the GICD_GROUP
- * word for this set of interrupts to give an overall mask.
- */
-
-typedef uint32_t maskfn(GICv3State *s, int irq);
-
-static uint32_t mask_nsacr_ge1(GICv3State *s, int irq)
-{
- /* Return a mask where each bit is set if the NSACR field is >= 1 */
- uint64_t raw_nsacr = s->gicd_nsacr[irq / 16 + 1];
-
- raw_nsacr = raw_nsacr << 32 | s->gicd_nsacr[irq / 16];
- raw_nsacr = (raw_nsacr >> 1) | raw_nsacr;
- return half_unshuffle64(raw_nsacr);
-}
-
-static uint32_t mask_nsacr_ge2(GICv3State *s, int irq)
-{
- /* Return a mask where each bit is set if the NSACR field is >= 2 */
- uint64_t raw_nsacr = s->gicd_nsacr[irq / 16 + 1];
-
- raw_nsacr = raw_nsacr << 32 | s->gicd_nsacr[irq / 16];
- raw_nsacr = raw_nsacr >> 1;
- return half_unshuffle64(raw_nsacr);
-}
-
-/* We don't need a mask_nsacr_ge3() because IROUTER<n> isn't a bitmap register,
- * but it would be implemented using:
- * raw_nsacr = (raw_nsacr >> 1) & raw_nsacr;
- */
-
-static uint32_t mask_group_and_nsacr(GICv3State *s, MemTxAttrs attrs,
- maskfn *maskfn, int irq)
-{
- /* Return a 32-bit mask which should be applied for this set of 32
- * interrupts; each bit is 1 if access is permitted by the
- * combination of attrs.secure, GICD_GROUPR and GICD_NSACR.
- */
- uint32_t mask;
-
- if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
- /* bits for Group 0 or Secure Group 1 interrupts are RAZ/WI
- * unless the NSACR bits permit access.
- */
- mask = *gic_bmp_ptr32(s->group, irq);
- if (maskfn) {
- mask |= maskfn(s, irq);
- }
- return mask;
- }
- return 0xFFFFFFFFU;
-}
-
-static int gicd_ns_access(GICv3State *s, int irq)
-{
- /* Return the 2 bit NS_access<x> field from GICD_NSACR<n> for the
- * specified interrupt.
- */
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return 0;
- }
- return extract32(s->gicd_nsacr[irq / 16], (irq % 16) * 2, 2);
-}
-
-static void gicd_write_set_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
- uint32_t *bmp,
- maskfn *maskfn,
- int offset, uint32_t val)
-{
- /* Helper routine to implement writing to a "set-bitmap" register
- * (GICD_ISENABLER, GICD_ISPENDR, etc).
- * Semantics implemented here:
- * RAZ/WI for SGIs, PPIs, unimplemented IRQs
- * Bits corresponding to Group 0 or Secure Group 1 interrupts RAZ/WI.
- * Writing 1 means "set bit in bitmap"; writing 0 is ignored.
- * offset should be the offset in bytes of the register from the start
- * of its group.
- */
- int irq = offset * 8;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return;
- }
- val &= mask_group_and_nsacr(s, attrs, maskfn, irq);
- *gic_bmp_ptr32(bmp, irq) |= val;
- gicv3_update(s, irq, 32);
-}
-
-static void gicd_write_clear_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
- uint32_t *bmp,
- maskfn *maskfn,
- int offset, uint32_t val)
-{
- /* Helper routine to implement writing to a "clear-bitmap" register
- * (GICD_ICENABLER, GICD_ICPENDR, etc).
- * Semantics implemented here:
- * RAZ/WI for SGIs, PPIs, unimplemented IRQs
- * Bits corresponding to Group 0 or Secure Group 1 interrupts RAZ/WI.
- * Writing 1 means "clear bit in bitmap"; writing 0 is ignored.
- * offset should be the offset in bytes of the register from the start
- * of its group.
- */
- int irq = offset * 8;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return;
- }
- val &= mask_group_and_nsacr(s, attrs, maskfn, irq);
- *gic_bmp_ptr32(bmp, irq) &= ~val;
- gicv3_update(s, irq, 32);
-}
-
-static uint32_t gicd_read_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
- uint32_t *bmp,
- maskfn *maskfn,
- int offset)
-{
- /* Helper routine to implement reading a "set/clear-bitmap" register
- * (GICD_ICENABLER, GICD_ISENABLER, GICD_ICPENDR, etc).
- * Semantics implemented here:
- * RAZ/WI for SGIs, PPIs, unimplemented IRQs
- * Bits corresponding to Group 0 or Secure Group 1 interrupts RAZ/WI.
- * offset should be the offset in bytes of the register from the start
- * of its group.
- */
- int irq = offset * 8;
- uint32_t val;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return 0;
- }
- val = *gic_bmp_ptr32(bmp, irq);
- if (bmp == s->pending) {
- /* The PENDING register is a special case -- for level triggered
- * interrupts, the PENDING state is the logical OR of the state of
- * the PENDING latch with the input line level.
- */
- uint32_t edge = *gic_bmp_ptr32(s->edge_trigger, irq);
- uint32_t level = *gic_bmp_ptr32(s->level, irq);
- val |= (~edge & level);
- }
- val &= mask_group_and_nsacr(s, attrs, maskfn, irq);
- return val;
-}
-
-static uint8_t gicd_read_ipriorityr(GICv3State *s, MemTxAttrs attrs, int irq)
-{
- /* Read the value of GICD_IPRIORITYR<n> for the specified interrupt,
- * honouring security state (these are RAZ/WI for Group 0 or Secure
- * Group 1 interrupts).
- */
- uint32_t prio;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return 0;
- }
-
- prio = s->gicd_ipriority[irq];
-
- if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
- if (!gicv3_gicd_group_test(s, irq)) {
- /* Fields for Group 0 or Secure Group 1 interrupts are RAZ/WI */
- return 0;
- }
- /* NS view of the interrupt priority */
- prio = (prio << 1) & 0xff;
- }
- return prio;
-}
-
-static void gicd_write_ipriorityr(GICv3State *s, MemTxAttrs attrs, int irq,
- uint8_t value)
-{
- /* Write the value of GICD_IPRIORITYR<n> for the specified interrupt,
- * honouring security state (these are RAZ/WI for Group 0 or Secure
- * Group 1 interrupts).
- */
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return;
- }
-
- if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
- if (!gicv3_gicd_group_test(s, irq)) {
- /* Fields for Group 0 or Secure Group 1 interrupts are RAZ/WI */
- return;
- }
- /* NS view of the interrupt priority */
- value = 0x80 | (value >> 1);
- }
- s->gicd_ipriority[irq] = value;
-}
-
-static uint64_t gicd_read_irouter(GICv3State *s, MemTxAttrs attrs, int irq)
-{
- /* Read the value of GICD_IROUTER<n> for the specified interrupt,
- * honouring security state.
- */
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return 0;
- }
-
- if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
- /* RAZ/WI for NS accesses to secure interrupts */
- if (!gicv3_gicd_group_test(s, irq)) {
- if (gicd_ns_access(s, irq) != 3) {
- return 0;
- }
- }
- }
-
- return s->gicd_irouter[irq];
-}
-
-static void gicd_write_irouter(GICv3State *s, MemTxAttrs attrs, int irq,
- uint64_t val)
-{
- /* Write the value of GICD_IROUTER<n> for the specified interrupt,
- * honouring security state.
- */
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return;
- }
-
- if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
- /* RAZ/WI for NS accesses to secure interrupts */
- if (!gicv3_gicd_group_test(s, irq)) {
- if (gicd_ns_access(s, irq) != 3) {
- return;
- }
- }
- }
-
- s->gicd_irouter[irq] = val;
- gicv3_cache_target_cpustate(s, irq);
- gicv3_update(s, irq, 1);
-}
-
-static MemTxResult gicd_readb(GICv3State *s, hwaddr offset,
- uint64_t *data, MemTxAttrs attrs)
-{
- /* Most GICv3 distributor registers do not support byte accesses. */
- switch (offset) {
- case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
- case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
- case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
- /* This GIC implementation always has affinity routing enabled,
- * so these registers are all RAZ/WI.
- */
- return MEMTX_OK;
- case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
- *data = gicd_read_ipriorityr(s, attrs, offset - GICD_IPRIORITYR);
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicd_writeb(GICv3State *s, hwaddr offset,
- uint64_t value, MemTxAttrs attrs)
-{
- /* Most GICv3 distributor registers do not support byte accesses. */
- switch (offset) {
- case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
- case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
- case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
- /* This GIC implementation always has affinity routing enabled,
- * so these registers are all RAZ/WI.
- */
- return MEMTX_OK;
- case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
- {
- int irq = offset - GICD_IPRIORITYR;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return MEMTX_OK;
- }
- gicd_write_ipriorityr(s, attrs, irq, value);
- gicv3_update(s, irq, 1);
- return MEMTX_OK;
- }
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicd_readw(GICv3State *s, hwaddr offset,
- uint64_t *data, MemTxAttrs attrs)
-{
- /* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR
- * support 16 bit accesses, and those registers are all part of the
- * optional message-based SPI feature which this GIC does not currently
- * implement (ie for us GICD_TYPER.MBIS == 0), so for us they are
- * reserved.
- */
- return MEMTX_ERROR;
-}
-
-static MemTxResult gicd_writew(GICv3State *s, hwaddr offset,
- uint64_t value, MemTxAttrs attrs)
-{
- /* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR
- * support 16 bit accesses, and those registers are all part of the
- * optional message-based SPI feature which this GIC does not currently
- * implement (ie for us GICD_TYPER.MBIS == 0), so for us they are
- * reserved.
- */
- return MEMTX_ERROR;
-}
-
-static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
- uint64_t *data, MemTxAttrs attrs)
-{
- /* Almost all GICv3 distributor registers are 32-bit.
- * Note that WO registers must return an UNKNOWN value on reads,
- * not an abort.
- */
-
- switch (offset) {
- case GICD_CTLR:
- if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
- /* The NS view of the GICD_CTLR sees only certain bits:
- * + bit [31] (RWP) is an alias of the Secure bit [31]
- * + bit [4] (ARE_NS) is an alias of Secure bit [5]
- * + bit [1] (EnableGrp1A) is an alias of Secure bit [1] if
- * NS affinity routing is enabled, otherwise RES0
- * + bit [0] (EnableGrp1) is an alias of Secure bit [1] if
- * NS affinity routing is not enabled, otherwise RES0
- * Since for QEMU affinity routing is always enabled
- * for both S and NS this means that bits [4] and [5] are
- * both always 1, and we can simply make the NS view
- * be bits 31, 4 and 1 of the S view.
- */
- *data = s->gicd_ctlr & (GICD_CTLR_ARE_S |
- GICD_CTLR_EN_GRP1NS |
- GICD_CTLR_RWP);
- } else {
- *data = s->gicd_ctlr;
- }
- return MEMTX_OK;
- case GICD_TYPER:
- {
- /* For this implementation:
- * No1N == 1 (1-of-N SPI interrupts not supported)
- * A3V == 1 (non-zero values of Affinity level 3 supported)
- * IDbits == 0xf (we support 16-bit interrupt identifiers)
- * DVIS == 0 (Direct virtual LPI injection not supported)
- * LPIS == 0 (LPIs not supported)
- * MBIS == 0 (message-based SPIs not supported)
- * SecurityExtn == 1 if security extns supported
- * CPUNumber == 0 since for us ARE is always 1
- * ITLinesNumber == (num external irqs / 32) - 1
- */
- int itlinesnumber = ((s->num_irq - GIC_INTERNAL) / 32) - 1;
-
- *data = (1 << 25) | (1 << 24) | (s->security_extn << 10) |
- (0xf << 19) | itlinesnumber;
- return MEMTX_OK;
- }
- case GICD_IIDR:
- /* We claim to be an ARM r0p0 with a zero ProductID.
- * This is the same as an r0p0 GIC-500.
- */
- *data = gicv3_iidr();
- return MEMTX_OK;
- case GICD_STATUSR:
- /* RAZ/WI for us (this is an optional register and our implementation
- * does not track RO/WO/reserved violations to report them to the guest)
- */
- *data = 0;
- return MEMTX_OK;
- case GICD_IGROUPR ... GICD_IGROUPR + 0x7f:
- {
- int irq;
-
- if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
- *data = 0;
- return MEMTX_OK;
- }
- /* RAZ/WI for SGIs, PPIs, unimplemented irqs */
- irq = (offset - GICD_IGROUPR) * 8;
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- *data = 0;
- return MEMTX_OK;
- }
- *data = *gic_bmp_ptr32(s->group, irq);
- return MEMTX_OK;
- }
- case GICD_ISENABLER ... GICD_ISENABLER + 0x7f:
- *data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL,
- offset - GICD_ISENABLER);
- return MEMTX_OK;
- case GICD_ICENABLER ... GICD_ICENABLER + 0x7f:
- *data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL,
- offset - GICD_ICENABLER);
- return MEMTX_OK;
- case GICD_ISPENDR ... GICD_ISPENDR + 0x7f:
- *data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1,
- offset - GICD_ISPENDR);
- return MEMTX_OK;
- case GICD_ICPENDR ... GICD_ICPENDR + 0x7f:
- *data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2,
- offset - GICD_ICPENDR);
- return MEMTX_OK;
- case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f:
- *data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2,
- offset - GICD_ISACTIVER);
- return MEMTX_OK;
- case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f:
- *data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2,
- offset - GICD_ICACTIVER);
- return MEMTX_OK;
- case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
- {
- int i, irq = offset - GICD_IPRIORITYR;
- uint32_t value = 0;
-
- for (i = irq + 3; i >= irq; i--, value <<= 8) {
- value |= gicd_read_ipriorityr(s, attrs, i);
- }
- *data = value;
- return MEMTX_OK;
- }
- case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
- /* RAZ/WI since affinity routing is always enabled */
- *data = 0;
- return MEMTX_OK;
- case GICD_ICFGR ... GICD_ICFGR + 0xff:
- {
- /* Here only the even bits are used; odd bits are RES0 */
- int irq = (offset - GICD_ICFGR) * 4;
- uint32_t value = 0;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- *data = 0;
- return MEMTX_OK;
- }
-
- /* Since our edge_trigger bitmap is one bit per irq, we only need
- * half of the 32-bit word, which we can then spread out
- * into the odd bits.
- */
- value = *gic_bmp_ptr32(s->edge_trigger, irq & ~0x1f);
- value &= mask_group_and_nsacr(s, attrs, NULL, irq & ~0x1f);
- value = extract32(value, (irq & 0x1f) ? 16 : 0, 16);
- value = half_shuffle32(value) << 1;
- *data = value;
- return MEMTX_OK;
- }
- case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff:
- {
- int irq;
-
- if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
- /* RAZ/WI if security disabled, or if
- * security enabled and this is an NS access
- */
- *data = 0;
- return MEMTX_OK;
- }
- /* RAZ/WI for SGIs, PPIs, unimplemented irqs */
- irq = (offset - GICD_IGRPMODR) * 8;
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- *data = 0;
- return MEMTX_OK;
- }
- *data = *gic_bmp_ptr32(s->grpmod, irq);
- return MEMTX_OK;
- }
- case GICD_NSACR ... GICD_NSACR + 0xff:
- {
- /* Two bits per interrupt */
- int irq = (offset - GICD_NSACR) * 4;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- *data = 0;
- return MEMTX_OK;
- }
-
- if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
- /* RAZ/WI if security disabled, or if
- * security enabled and this is an NS access
- */
- *data = 0;
- return MEMTX_OK;
- }
-
- *data = s->gicd_nsacr[irq / 16];
- return MEMTX_OK;
- }
- case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
- case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
- /* RAZ/WI since affinity routing is always enabled */
- *data = 0;
- return MEMTX_OK;
- case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
- {
- uint64_t r;
- int irq = (offset - GICD_IROUTER) / 8;
-
- r = gicd_read_irouter(s, attrs, irq);
- if (offset & 7) {
- *data = r >> 32;
- } else {
- *data = (uint32_t)r;
- }
- return MEMTX_OK;
- }
- case GICD_IDREGS ... GICD_IDREGS + 0x1f:
- /* ID registers */
- *data = gicv3_idreg(offset - GICD_IDREGS);
- return MEMTX_OK;
- case GICD_SGIR:
- /* WO registers, return unknown value */
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: invalid guest read from WO register at offset "
- TARGET_FMT_plx "\n", __func__, offset);
- *data = 0;
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
- uint64_t value, MemTxAttrs attrs)
-{
- /* Almost all GICv3 distributor registers are 32-bit. Note that
- * RO registers must ignore writes, not abort.
- */
-
- switch (offset) {
- case GICD_CTLR:
- {
- uint32_t mask;
- /* GICv3 5.3.20 */
- if (s->gicd_ctlr & GICD_CTLR_DS) {
- /* With only one security state, E1NWF is RAZ/WI, DS is RAO/WI,
- * ARE is RAO/WI (affinity routing always on), and only
- * bits 0 and 1 (group enables) are writable.
- */
- mask = GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1NS;
- } else {
- if (attrs.secure) {
- /* for secure access:
- * ARE_NS and ARE_S are RAO/WI (affinity routing always on)
- * E1NWF is RAZ/WI (we don't support enable-1-of-n-wakeup)
- *
- * We can only modify bits[2:0] (the group enables).
- */
- mask = GICD_CTLR_DS | GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1_ALL;
- } else {
- /* For non secure access ARE_NS is RAO/WI and EnableGrp1
- * is RES0. The only writable bit is [1] (EnableGrp1A), which
- * is an alias of the Secure bit [1].
- */
- mask = GICD_CTLR_EN_GRP1NS;
- }
- }
- s->gicd_ctlr = (s->gicd_ctlr & ~mask) | (value & mask);
- if (value & mask & GICD_CTLR_DS) {
- /* We just set DS, so the ARE_NS and EnG1S bits are now RES0.
- * Note that this is a one-way transition because if DS is set
- * then it's not writeable, so it can only go back to 0 with a
- * hardware reset.
- */
- s->gicd_ctlr &= ~(GICD_CTLR_EN_GRP1S | GICD_CTLR_ARE_NS);
- }
- gicv3_full_update(s);
- return MEMTX_OK;
- }
- case GICD_STATUSR:
- /* RAZ/WI for our implementation */
- return MEMTX_OK;
- case GICD_IGROUPR ... GICD_IGROUPR + 0x7f:
- {
- int irq;
-
- if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
- return MEMTX_OK;
- }
- /* RAZ/WI for SGIs, PPIs, unimplemented irqs */
- irq = (offset - GICD_IGROUPR) * 8;
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return MEMTX_OK;
- }
- *gic_bmp_ptr32(s->group, irq) = value;
- gicv3_update(s, irq, 32);
- return MEMTX_OK;
- }
- case GICD_ISENABLER ... GICD_ISENABLER + 0x7f:
- gicd_write_set_bitmap_reg(s, attrs, s->enabled, NULL,
- offset - GICD_ISENABLER, value);
- return MEMTX_OK;
- case GICD_ICENABLER ... GICD_ICENABLER + 0x7f:
- gicd_write_clear_bitmap_reg(s, attrs, s->enabled, NULL,
- offset - GICD_ICENABLER, value);
- return MEMTX_OK;
- case GICD_ISPENDR ... GICD_ISPENDR + 0x7f:
- gicd_write_set_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1,
- offset - GICD_ISPENDR, value);
- return MEMTX_OK;
- case GICD_ICPENDR ... GICD_ICPENDR + 0x7f:
- gicd_write_clear_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2,
- offset - GICD_ICPENDR, value);
- return MEMTX_OK;
- case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f:
- gicd_write_set_bitmap_reg(s, attrs, s->active, NULL,
- offset - GICD_ISACTIVER, value);
- return MEMTX_OK;
- case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f:
- gicd_write_clear_bitmap_reg(s, attrs, s->active, NULL,
- offset - GICD_ICACTIVER, value);
- return MEMTX_OK;
- case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
- {
- int i, irq = offset - GICD_IPRIORITYR;
-
- if (irq < GIC_INTERNAL || irq + 3 >= s->num_irq) {
- return MEMTX_OK;
- }
-
- for (i = irq; i < irq + 4; i++, value >>= 8) {
- gicd_write_ipriorityr(s, attrs, i, value);
- }
- gicv3_update(s, irq, 4);
- return MEMTX_OK;
- }
- case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
- /* RAZ/WI since affinity routing is always enabled */
- return MEMTX_OK;
- case GICD_ICFGR ... GICD_ICFGR + 0xff:
- {
- /* Here only the odd bits are used; even bits are RES0 */
- int irq = (offset - GICD_ICFGR) * 4;
- uint32_t mask, oldval;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return MEMTX_OK;
- }
-
- /* Since our edge_trigger bitmap is one bit per irq, our input
- * 32-bits will compress down into 16 bits which we need
- * to write into the bitmap.
- */
- value = half_unshuffle32(value >> 1);
- mask = mask_group_and_nsacr(s, attrs, NULL, irq & ~0x1f);
- if (irq & 0x1f) {
- value <<= 16;
- mask &= 0xffff0000U;
- } else {
- mask &= 0xffff;
- }
- oldval = *gic_bmp_ptr32(s->edge_trigger, (irq & ~0x1f));
- value = (oldval & ~mask) | (value & mask);
- *gic_bmp_ptr32(s->edge_trigger, irq & ~0x1f) = value;
- return MEMTX_OK;
- }
- case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff:
- {
- int irq;
-
- if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
- /* RAZ/WI if security disabled, or if
- * security enabled and this is an NS access
- */
- return MEMTX_OK;
- }
- /* RAZ/WI for SGIs, PPIs, unimplemented irqs */
- irq = (offset - GICD_IGRPMODR) * 8;
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return MEMTX_OK;
- }
- *gic_bmp_ptr32(s->grpmod, irq) = value;
- gicv3_update(s, irq, 32);
- return MEMTX_OK;
- }
- case GICD_NSACR ... GICD_NSACR + 0xff:
- {
- /* Two bits per interrupt */
- int irq = (offset - GICD_NSACR) * 4;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return MEMTX_OK;
- }
-
- if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
- /* RAZ/WI if security disabled, or if
- * security enabled and this is an NS access
- */
- return MEMTX_OK;
- }
-
- s->gicd_nsacr[irq / 16] = value;
- /* No update required as this only affects access permission checks */
- return MEMTX_OK;
- }
- case GICD_SGIR:
- /* RES0 if affinity routing is enabled */
- return MEMTX_OK;
- case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
- case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
- /* RAZ/WI since affinity routing is always enabled */
- return MEMTX_OK;
- case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
- {
- uint64_t r;
- int irq = (offset - GICD_IROUTER) / 8;
-
- if (irq < GIC_INTERNAL || irq >= s->num_irq) {
- return MEMTX_OK;
- }
-
- /* Write half of the 64-bit register */
- r = gicd_read_irouter(s, attrs, irq);
- r = deposit64(r, (offset & 7) ? 32 : 0, 32, value);
- gicd_write_irouter(s, attrs, irq, r);
- return MEMTX_OK;
- }
- case GICD_IDREGS ... GICD_IDREGS + 0x1f:
- case GICD_TYPER:
- case GICD_IIDR:
- /* RO registers, ignore the write */
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: invalid guest write to RO register at offset "
- TARGET_FMT_plx "\n", __func__, offset);
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicd_writell(GICv3State *s, hwaddr offset,
- uint64_t value, MemTxAttrs attrs)
-{
- /* Our only 64-bit registers are GICD_IROUTER<n> */
- int irq;
-
- switch (offset) {
- case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
- irq = (offset - GICD_IROUTER) / 8;
- gicd_write_irouter(s, attrs, irq, value);
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicd_readll(GICv3State *s, hwaddr offset,
- uint64_t *data, MemTxAttrs attrs)
-{
- /* Our only 64-bit registers are GICD_IROUTER<n> */
- int irq;
-
- switch (offset) {
- case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
- irq = (offset - GICD_IROUTER) / 8;
- *data = gicd_read_irouter(s, attrs, irq);
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
- unsigned size, MemTxAttrs attrs)
-{
- GICv3State *s = (GICv3State *)opaque;
- MemTxResult r;
-
- switch (size) {
- case 1:
- r = gicd_readb(s, offset, data, attrs);
- break;
- case 2:
- r = gicd_readw(s, offset, data, attrs);
- break;
- case 4:
- r = gicd_readl(s, offset, data, attrs);
- break;
- case 8:
- r = gicd_readll(s, offset, data, attrs);
- break;
- default:
- r = MEMTX_ERROR;
- break;
- }
-
- if (r == MEMTX_ERROR) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: invalid guest read at offset " TARGET_FMT_plx
- "size %u\n", __func__, offset, size);
- trace_gicv3_dist_badread(offset, size, attrs.secure);
- } else {
- trace_gicv3_dist_read(offset, *data, size, attrs.secure);
- }
- return r;
-}
-
-MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
- unsigned size, MemTxAttrs attrs)
-{
- GICv3State *s = (GICv3State *)opaque;
- MemTxResult r;
-
- switch (size) {
- case 1:
- r = gicd_writeb(s, offset, data, attrs);
- break;
- case 2:
- r = gicd_writew(s, offset, data, attrs);
- break;
- case 4:
- r = gicd_writel(s, offset, data, attrs);
- break;
- case 8:
- r = gicd_writell(s, offset, data, attrs);
- break;
- default:
- r = MEMTX_ERROR;
- break;
- }
-
- if (r == MEMTX_ERROR) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: invalid guest write at offset " TARGET_FMT_plx
- "size %u\n", __func__, offset, size);
- trace_gicv3_dist_badwrite(offset, data, size, attrs.secure);
- } else {
- trace_gicv3_dist_write(offset, data, size, attrs.secure);
- }
- return r;
-}
-
-void gicv3_dist_set_irq(GICv3State *s, int irq, int level)
-{
- /* Update distributor state for a change in an external SPI input line */
- if (level == gicv3_gicd_level_test(s, irq)) {
- return;
- }
-
- trace_gicv3_dist_set_irq(irq, level);
-
- gicv3_gicd_level_replace(s, irq, level);
-
- if (level) {
- /* 0->1 edges latch the pending bit for edge-triggered interrupts */
- if (gicv3_gicd_edge_trigger_test(s, irq)) {
- gicv3_gicd_pending_set(s, irq);
- }
- }
-
- gicv3_update(s, irq, 1);
-}
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 711fde38f..acc173004 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -26,7 +26,6 @@
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "vgic_common.h"
-#include "migration/migration.h"
#ifdef DEBUG_GICV3_KVM
#define DPRINTF(fmt, ...) \
@@ -120,13 +119,6 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd);
kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd);
-
- /* Block migration of a KVM GICv3 device: the API for saving and restoring
- * the state in the kernel is not yet finalised in the kernel or
- * implemented in QEMU.
- */
- error_setg(&s->migration_blocker, "vGICv3 migration is not implemented");
- migrate_add_blocker(s->migration_blocker);
}
static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
deleted file mode 100644
index 77e5cfa32..000000000
--- a/hw/intc/arm_gicv3_redist.c
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * ARM GICv3 emulation: Redistributor
- *
- * 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.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "trace.h"
-#include "gicv3_internal.h"
-
-static uint32_t mask_group(GICv3CPUState *cs, MemTxAttrs attrs)
-{
- /* Return a 32-bit mask which should be applied for this set of 32
- * interrupts; each bit is 1 if access is permitted by the
- * combination of attrs.secure and GICR_GROUPR. (GICR_NSACR does
- * not affect config register accesses, unlike GICD_NSACR.)
- */
- if (!attrs.secure && !(cs->gic->gicd_ctlr & GICD_CTLR_DS)) {
- /* bits for Group 0 or Secure Group 1 interrupts are RAZ/WI */
- return cs->gicr_igroupr0;
- }
- return 0xFFFFFFFFU;
-}
-
-static int gicr_ns_access(GICv3CPUState *cs, int irq)
-{
- /* Return the 2 bit NSACR.NS_access field for this SGI */
- assert(irq < 16);
- return extract32(cs->gicr_nsacr, irq * 2, 2);
-}
-
-static void gicr_write_set_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
- uint32_t *reg, uint32_t val)
-{
- /* Helper routine to implement writing to a "set-bitmap" register */
- val &= mask_group(cs, attrs);
- *reg |= val;
- gicv3_redist_update(cs);
-}
-
-static void gicr_write_clear_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
- uint32_t *reg, uint32_t val)
-{
- /* Helper routine to implement writing to a "clear-bitmap" register */
- val &= mask_group(cs, attrs);
- *reg &= ~val;
- gicv3_redist_update(cs);
-}
-
-static uint32_t gicr_read_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
- uint32_t reg)
-{
- reg &= mask_group(cs, attrs);
- return reg;
-}
-
-static uint8_t gicr_read_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs,
- int irq)
-{
- /* Read the value of GICR_IPRIORITYR<n> for the specified interrupt,
- * honouring security state (these are RAZ/WI for Group 0 or Secure
- * Group 1 interrupts).
- */
- uint32_t prio;
-
- prio = cs->gicr_ipriorityr[irq];
-
- if (!attrs.secure && !(cs->gic->gicd_ctlr & GICD_CTLR_DS)) {
- if (!(cs->gicr_igroupr0 & (1U << irq))) {
- /* Fields for Group 0 or Secure Group 1 interrupts are RAZ/WI */
- return 0;
- }
- /* NS view of the interrupt priority */
- prio = (prio << 1) & 0xff;
- }
- return prio;
-}
-
-static void gicr_write_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs, int irq,
- uint8_t value)
-{
- /* Write the value of GICD_IPRIORITYR<n> for the specified interrupt,
- * honouring security state (these are RAZ/WI for Group 0 or Secure
- * Group 1 interrupts).
- */
- if (!attrs.secure && !(cs->gic->gicd_ctlr & GICD_CTLR_DS)) {
- if (!(cs->gicr_igroupr0 & (1U << irq))) {
- /* Fields for Group 0 or Secure Group 1 interrupts are RAZ/WI */
- return;
- }
- /* NS view of the interrupt priority */
- value = 0x80 | (value >> 1);
- }
- cs->gicr_ipriorityr[irq] = value;
-}
-
-static MemTxResult gicr_readb(GICv3CPUState *cs, hwaddr offset,
- uint64_t *data, MemTxAttrs attrs)
-{
- switch (offset) {
- case GICR_IPRIORITYR ... GICR_IPRIORITYR + 0x1f:
- *data = gicr_read_ipriorityr(cs, attrs, offset - GICR_IPRIORITYR);
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicr_writeb(GICv3CPUState *cs, hwaddr offset,
- uint64_t value, MemTxAttrs attrs)
-{
- switch (offset) {
- case GICR_IPRIORITYR ... GICR_IPRIORITYR + 0x1f:
- gicr_write_ipriorityr(cs, attrs, offset - GICR_IPRIORITYR, value);
- gicv3_redist_update(cs);
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
- uint64_t *data, MemTxAttrs attrs)
-{
- switch (offset) {
- case GICR_CTLR:
- *data = cs->gicr_ctlr;
- return MEMTX_OK;
- case GICR_IIDR:
- *data = gicv3_iidr();
- return MEMTX_OK;
- case GICR_TYPER:
- *data = extract64(cs->gicr_typer, 0, 32);
- return MEMTX_OK;
- case GICR_TYPER + 4:
- *data = extract64(cs->gicr_typer, 32, 32);
- return MEMTX_OK;
- case GICR_STATUSR:
- /* RAZ/WI for us (this is an optional register and our implementation
- * does not track RO/WO/reserved violations to report them to the guest)
- */
- *data = 0;
- return MEMTX_OK;
- case GICR_WAKER:
- *data = cs->gicr_waker;
- return MEMTX_OK;
- case GICR_PROPBASER:
- *data = extract64(cs->gicr_propbaser, 0, 32);
- return MEMTX_OK;
- case GICR_PROPBASER + 4:
- *data = extract64(cs->gicr_propbaser, 32, 32);
- return MEMTX_OK;
- case GICR_PENDBASER:
- *data = extract64(cs->gicr_pendbaser, 0, 32);
- return MEMTX_OK;
- case GICR_PENDBASER + 4:
- *data = extract64(cs->gicr_pendbaser, 32, 32);
- return MEMTX_OK;
- case GICR_IGROUPR0:
- if (!attrs.secure && !(cs->gic->gicd_ctlr & GICD_CTLR_DS)) {
- *data = 0;
- return MEMTX_OK;
- }
- *data = cs->gicr_igroupr0;
- return MEMTX_OK;
- case GICR_ISENABLER0:
- case GICR_ICENABLER0:
- *data = gicr_read_bitmap_reg(cs, attrs, cs->gicr_ienabler0);
- return MEMTX_OK;
- case GICR_ISPENDR0:
- case GICR_ICPENDR0:
- {
- /* The pending register reads as the logical OR of the pending
- * latch and the input line level for level-triggered interrupts.
- */
- uint32_t val = cs->gicr_ipendr0 | (~cs->edge_trigger & cs->level);
- *data = gicr_read_bitmap_reg(cs, attrs, val);
- return MEMTX_OK;
- }
- case GICR_ISACTIVER0:
- case GICR_ICACTIVER0:
- *data = gicr_read_bitmap_reg(cs, attrs, cs->gicr_iactiver0);
- return MEMTX_OK;
- case GICR_IPRIORITYR ... GICR_IPRIORITYR + 0x1f:
- {
- int i, irq = offset - GICR_IPRIORITYR;
- uint32_t value = 0;
-
- for (i = irq + 3; i >= irq; i--, value <<= 8) {
- value |= gicr_read_ipriorityr(cs, attrs, i);
- }
- *data = value;
- return MEMTX_OK;
- }
- case GICR_ICFGR0:
- case GICR_ICFGR1:
- {
- /* Our edge_trigger bitmap is one bit per irq; take the correct
- * half of it, and spread it out into the odd bits.
- */
- uint32_t value;
-
- value = cs->edge_trigger & mask_group(cs, attrs);
- value = extract32(value, (offset == GICR_ICFGR1) ? 16 : 0, 16);
- value = half_shuffle32(value) << 1;
- *data = value;
- return MEMTX_OK;
- }
- case GICR_IGRPMODR0:
- if ((cs->gic->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
- /* RAZ/WI if security disabled, or if
- * security enabled and this is an NS access
- */
- *data = 0;
- return MEMTX_OK;
- }
- *data = cs->gicr_igrpmodr0;
- return MEMTX_OK;
- case GICR_NSACR:
- if ((cs->gic->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
- /* RAZ/WI if security disabled, or if
- * security enabled and this is an NS access
- */
- *data = 0;
- return MEMTX_OK;
- }
- *data = cs->gicr_nsacr;
- return MEMTX_OK;
- case GICR_IDREGS ... GICR_IDREGS + 0x1f:
- *data = gicv3_idreg(offset - GICR_IDREGS);
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
- uint64_t value, MemTxAttrs attrs)
-{
- switch (offset) {
- case GICR_CTLR:
- /* For our implementation, GICR_TYPER.DPGS is 0 and so all
- * the DPG bits are RAZ/WI. We don't do anything asynchronously,
- * so UWP and RWP are RAZ/WI. And GICR_TYPER.LPIS is 0 (we don't
- * implement LPIs) so Enable_LPIs is RES0. So there are no writable
- * bits for us.
- */
- return MEMTX_OK;
- case GICR_STATUSR:
- /* RAZ/WI for our implementation */
- return MEMTX_OK;
- case GICR_WAKER:
- /* Only the ProcessorSleep bit is writeable. When the guest sets
- * it it requests that we transition the channel between the
- * redistributor and the cpu interface to quiescent, and that
- * we set the ChildrenAsleep bit once the inteface has reached the
- * quiescent state.
- * Setting the ProcessorSleep to 0 reverses the quiescing, and
- * ChildrenAsleep is cleared once the transition is complete.
- * Since our interface is not asynchronous, we complete these
- * transitions instantaneously, so we set ChildrenAsleep to the
- * same value as ProcessorSleep here.
- */
- value &= GICR_WAKER_ProcessorSleep;
- if (value & GICR_WAKER_ProcessorSleep) {
- value |= GICR_WAKER_ChildrenAsleep;
- }
- cs->gicr_waker = value;
- return MEMTX_OK;
- case GICR_PROPBASER:
- cs->gicr_propbaser = deposit64(cs->gicr_propbaser, 0, 32, value);
- return MEMTX_OK;
- case GICR_PROPBASER + 4:
- cs->gicr_propbaser = deposit64(cs->gicr_propbaser, 32, 32, value);
- return MEMTX_OK;
- case GICR_PENDBASER:
- cs->gicr_pendbaser = deposit64(cs->gicr_pendbaser, 0, 32, value);
- return MEMTX_OK;
- case GICR_PENDBASER + 4:
- cs->gicr_pendbaser = deposit64(cs->gicr_pendbaser, 32, 32, value);
- return MEMTX_OK;
- case GICR_IGROUPR0:
- if (!attrs.secure && !(cs->gic->gicd_ctlr & GICD_CTLR_DS)) {
- return MEMTX_OK;
- }
- cs->gicr_igroupr0 = value;
- gicv3_redist_update(cs);
- return MEMTX_OK;
- case GICR_ISENABLER0:
- gicr_write_set_bitmap_reg(cs, attrs, &cs->gicr_ienabler0, value);
- return MEMTX_OK;
- case GICR_ICENABLER0:
- gicr_write_clear_bitmap_reg(cs, attrs, &cs->gicr_ienabler0, value);
- return MEMTX_OK;
- case GICR_ISPENDR0:
- gicr_write_set_bitmap_reg(cs, attrs, &cs->gicr_ipendr0, value);
- return MEMTX_OK;
- case GICR_ICPENDR0:
- gicr_write_clear_bitmap_reg(cs, attrs, &cs->gicr_ipendr0, value);
- return MEMTX_OK;
- case GICR_ISACTIVER0:
- gicr_write_set_bitmap_reg(cs, attrs, &cs->gicr_iactiver0, value);
- return MEMTX_OK;
- case GICR_ICACTIVER0:
- gicr_write_clear_bitmap_reg(cs, attrs, &cs->gicr_iactiver0, value);
- return MEMTX_OK;
- case GICR_IPRIORITYR ... GICR_IPRIORITYR + 0x1f:
- {
- int i, irq = offset - GICR_IPRIORITYR;
-
- for (i = irq; i < irq + 4; i++, value >>= 8) {
- gicr_write_ipriorityr(cs, attrs, i, value);
- }
- gicv3_redist_update(cs);
- return MEMTX_OK;
- }
- case GICR_ICFGR0:
- /* Register is all RAZ/WI or RAO/WI bits */
- return MEMTX_OK;
- case GICR_ICFGR1:
- {
- uint32_t mask;
-
- /* Since our edge_trigger bitmap is one bit per irq, our input
- * 32-bits will compress down into 16 bits which we need
- * to write into the bitmap.
- */
- value = half_unshuffle32(value >> 1) << 16;
- mask = mask_group(cs, attrs) & 0xffff0000U;
-
- cs->edge_trigger &= ~mask;
- cs->edge_trigger |= (value & mask);
-
- gicv3_redist_update(cs);
- return MEMTX_OK;
- }
- case GICR_IGRPMODR0:
- if ((cs->gic->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
- /* RAZ/WI if security disabled, or if
- * security enabled and this is an NS access
- */
- return MEMTX_OK;
- }
- cs->gicr_igrpmodr0 = value;
- gicv3_redist_update(cs);
- return MEMTX_OK;
- case GICR_NSACR:
- if ((cs->gic->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
- /* RAZ/WI if security disabled, or if
- * security enabled and this is an NS access
- */
- return MEMTX_OK;
- }
- cs->gicr_nsacr = value;
- /* no update required as this only affects access permission checks */
- return MEMTX_OK;
- case GICR_IIDR:
- case GICR_TYPER:
- case GICR_IDREGS ... GICR_IDREGS + 0x1f:
- /* RO registers, ignore the write */
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: invalid guest write to RO register at offset "
- TARGET_FMT_plx "\n", __func__, offset);
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicr_readll(GICv3CPUState *cs, hwaddr offset,
- uint64_t *data, MemTxAttrs attrs)
-{
- switch (offset) {
- case GICR_TYPER:
- *data = cs->gicr_typer;
- return MEMTX_OK;
- case GICR_PROPBASER:
- *data = cs->gicr_propbaser;
- return MEMTX_OK;
- case GICR_PENDBASER:
- *data = cs->gicr_pendbaser;
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-static MemTxResult gicr_writell(GICv3CPUState *cs, hwaddr offset,
- uint64_t value, MemTxAttrs attrs)
-{
- switch (offset) {
- case GICR_PROPBASER:
- cs->gicr_propbaser = value;
- return MEMTX_OK;
- case GICR_PENDBASER:
- cs->gicr_pendbaser = value;
- return MEMTX_OK;
- case GICR_TYPER:
- /* RO register, ignore the write */
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: invalid guest write to RO register at offset "
- TARGET_FMT_plx "\n", __func__, offset);
- return MEMTX_OK;
- default:
- return MEMTX_ERROR;
- }
-}
-
-MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
- unsigned size, MemTxAttrs attrs)
-{
- GICv3State *s = opaque;
- GICv3CPUState *cs;
- MemTxResult r;
- int cpuidx;
-
- assert((offset & (size - 1)) == 0);
-
- /* This region covers all the redistributor pages; there are
- * (for GICv3) two 64K pages per CPU. At the moment they are
- * all contiguous (ie in this one region), though we might later
- * want to allow splitting of redistributor pages into several
- * blocks so we can support more CPUs.
- */
- cpuidx = offset / 0x20000;
- offset %= 0x20000;
- assert(cpuidx < s->num_cpu);
-
- cs = &s->cpu[cpuidx];
-
- switch (size) {
- case 1:
- r = gicr_readb(cs, offset, data, attrs);
- break;
- case 4:
- r = gicr_readl(cs, offset, data, attrs);
- break;
- case 8:
- r = gicr_readll(cs, offset, data, attrs);
- break;
- default:
- r = MEMTX_ERROR;
- break;
- }
-
- if (r == MEMTX_ERROR) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: invalid guest read at offset " TARGET_FMT_plx
- "size %u\n", __func__, offset, size);
- trace_gicv3_redist_badread(gicv3_redist_affid(cs), offset,
- size, attrs.secure);
- } else {
- trace_gicv3_redist_read(gicv3_redist_affid(cs), offset, *data,
- size, attrs.secure);
- }
- return r;
-}
-
-MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
- unsigned size, MemTxAttrs attrs)
-{
- GICv3State *s = opaque;
- GICv3CPUState *cs;
- MemTxResult r;
- int cpuidx;
-
- assert((offset & (size - 1)) == 0);
-
- /* This region covers all the redistributor pages; there are
- * (for GICv3) two 64K pages per CPU. At the moment they are
- * all contiguous (ie in this one region), though we might later
- * want to allow splitting of redistributor pages into several
- * blocks so we can support more CPUs.
- */
- cpuidx = offset / 0x20000;
- offset %= 0x20000;
- assert(cpuidx < s->num_cpu);
-
- cs = &s->cpu[cpuidx];
-
- switch (size) {
- case 1:
- r = gicr_writeb(cs, offset, data, attrs);
- break;
- case 4:
- r = gicr_writel(cs, offset, data, attrs);
- break;
- case 8:
- r = gicr_writell(cs, offset, data, attrs);
- break;
- default:
- r = MEMTX_ERROR;
- break;
- }
-
- if (r == MEMTX_ERROR) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: invalid guest write at offset " TARGET_FMT_plx
- "size %u\n", __func__, offset, size);
- trace_gicv3_redist_badwrite(gicv3_redist_affid(cs), offset, data,
- size, attrs.secure);
- } else {
- trace_gicv3_redist_write(gicv3_redist_affid(cs), offset, data,
- size, attrs.secure);
- }
- return r;
-}
-
-void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
-{
- /* Update redistributor state for a change in an external PPI input line */
- if (level == extract32(cs->level, irq, 1)) {
- return;
- }
-
- trace_gicv3_redist_set_irq(gicv3_redist_affid(cs), irq, level);
-
- cs->level = deposit32(cs->level, irq, 1, level);
-
- if (level) {
- /* 0->1 edges latch the pending bit for edge-triggered interrupts */
- if (extract32(cs->edge_trigger, irq, 1)) {
- cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 1);
- }
- }
-
- gicv3_redist_update(cs);
-}
-
-void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns)
-{
- /* Update redistributor state for a generated SGI */
- int irqgrp = gicv3_irq_group(cs->gic, cs, irq);
-
- /* If we are asked for a Secure Group 1 SGI and it's actually
- * configured as Secure Group 0 this is OK (subject to the usual
- * NSACR checks).
- */
- if (grp == GICV3_G1 && irqgrp == GICV3_G0) {
- grp = GICV3_G0;
- }
-
- if (grp != irqgrp) {
- return;
- }
-
- if (ns && !(cs->gic->gicd_ctlr & GICD_CTLR_DS)) {
- /* If security is enabled we must test the NSACR bits */
- int nsaccess = gicr_ns_access(cs, irq);
-
- if ((irqgrp == GICV3_G0 && nsaccess < 1) ||
- (irqgrp == GICV3_G1 && nsaccess < 2)) {
- return;
- }
- }
-
- /* OK, we can accept the SGI */
- trace_gicv3_redist_send_sgi(gicv3_redist_affid(cs), irq);
- cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 1);
- gicv3_redist_update(cs);
-}
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 06d8db6bd..669e82adf 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -13,13 +13,11 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
-#include "cpu.h"
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "hw/arm/arm.h"
#include "exec/address-spaces.h"
#include "gic_internal.h"
-#include "qemu/log.h"
typedef struct {
GICState gic;
@@ -187,11 +185,11 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
case 0x1c: /* SysTick Calibration Value. */
return 10000;
case 0xd00: /* CPUID Base. */
- cpu = ARM_CPU(qemu_get_cpu(0));
+ cpu = ARM_CPU(current_cpu);
return cpu->midr;
case 0xd04: /* Interrupt Control State. */
/* VECTACTIVE */
- cpu = ARM_CPU(qemu_get_cpu(0));
+ cpu = ARM_CPU(current_cpu);
val = cpu->env.v7m.exception;
if (val == 1023) {
val = 0;
@@ -222,7 +220,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
val |= (1 << 31);
return val;
case 0xd08: /* Vector Table Offset. */
- cpu = ARM_CPU(qemu_get_cpu(0));
+ cpu = ARM_CPU(current_cpu);
return cpu->env.v7m.vecbase;
case 0xd0c: /* Application Interrupt/Reset Control. */
return 0xfa050000;
@@ -349,7 +347,7 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
}
break;
case 0xd08: /* Vector Table Offset. */
- cpu = ARM_CPU(qemu_get_cpu(0));
+ cpu = ARM_CPU(current_cpu);
cpu->env.v7m.vecbase = value & 0xffffff80;
break;
case 0xd0c: /* Application Interrupt/Reset Control. */
diff --git a/hw/intc/aspeed_vic.c b/hw/intc/aspeed_vic.c
index 2370e7485..19a0ff748 100644
--- a/hw/intc/aspeed_vic.c
+++ b/hw/intc/aspeed_vic.c
@@ -28,9 +28,9 @@
*/
#include "qemu/osdep.h"
+#include <inttypes.h>
#include "hw/intc/aspeed_vic.h"
#include "qemu/bitops.h"
-#include "qemu/log.h"
#include "trace.h"
#define AVIC_NEW_BASE_OFFSET 0x80
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
index 00d25306f..80513b28f 100644
--- a/hw/intc/bcm2835_ic.c
+++ b/hw/intc/bcm2835_ic.c
@@ -14,7 +14,6 @@
#include "qemu/osdep.h"
#include "hw/intc/bcm2835_ic.h"
-#include "qemu/log.h"
#define GPU_IRQS 64
#define ARM_IRQS 8
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
index cfa5bc736..d0271810c 100644
--- a/hw/intc/bcm2836_control.c
+++ b/hw/intc/bcm2836_control.c
@@ -15,7 +15,6 @@
#include "qemu/osdep.h"
#include "hw/intc/bcm2836_control.h"
-#include "qemu/log.h"
#define REG_GPU_ROUTE 0x0c
#define REG_TIMERCONTROL 0x40
diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c
index 64a6f4b4b..48f947706 100644
--- a/hw/intc/etraxfs_pic.c
+++ b/hw/intc/etraxfs_pic.c
@@ -146,19 +146,19 @@ static void irq_handler(void *opaque, int irq, int level)
pic_update(fs);
}
-static void etraxfs_pic_init(Object *obj)
+static int etraxfs_pic_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- struct etrax_pic *s = ETRAX_FS_PIC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ struct etrax_pic *s = ETRAX_FS_PIC(dev);
qdev_init_gpio_in(dev, irq_handler, 32);
sysbus_init_irq(sbd, &s->parent_irq);
sysbus_init_irq(sbd, &s->parent_nmi);
- memory_region_init_io(&s->mmio, obj, &pic_ops, s,
+ memory_region_init_io(&s->mmio, OBJECT(s), &pic_ops, s,
"etraxfs-pic", R_MAX * 4);
sysbus_init_mmio(sbd, &s->mmio);
+ return 0;
}
static Property etraxfs_pic_properties[] = {
@@ -169,7 +169,9 @@ static Property etraxfs_pic_properties[] = {
static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = etraxfs_pic_init;
dc->props = etraxfs_pic_properties;
/*
* Note: pointer property "interrupt_vector" may remain null, thus
@@ -181,7 +183,6 @@ static const TypeInfo etraxfs_pic_info = {
.name = TYPE_ETRAX_FS_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct etrax_pic),
- .instance_init = etraxfs_pic_init,
.class_init = etraxfs_pic_class_init,
};
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
index f19a7062b..dc0c90326 100644
--- a/hw/intc/exynos4210_combiner.c
+++ b/hw/intc/exynos4210_combiner.c
@@ -406,11 +406,10 @@ static const MemoryRegionOps exynos4210_combiner_ops = {
/*
* Internal Combiner initialization.
*/
-static void exynos4210_combiner_init(Object *obj)
+static int exynos4210_combiner_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- Exynos4210CombinerState *s = EXYNOS4210_COMBINER(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ Exynos4210CombinerState *s = EXYNOS4210_COMBINER(dev);
unsigned int i;
/* Allocate general purpose input signals and connect a handler to each of
@@ -422,9 +421,11 @@ static void exynos4210_combiner_init(Object *obj)
sysbus_init_irq(sbd, &s->output_irq[i]);
}
- memory_region_init_io(&s->iomem, obj, &exynos4210_combiner_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_combiner_ops, s,
"exynos4210-combiner", IIC_REGION_SIZE);
sysbus_init_mmio(sbd, &s->iomem);
+
+ return 0;
}
static Property exynos4210_combiner_properties[] = {
@@ -435,7 +436,9 @@ static Property exynos4210_combiner_properties[] = {
static void exynos4210_combiner_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = exynos4210_combiner_init;
dc->reset = exynos4210_combiner_reset;
dc->props = exynos4210_combiner_properties;
dc->vmsd = &vmstate_exynos4210_combiner;
@@ -445,7 +448,6 @@ static const TypeInfo exynos4210_combiner_info = {
.name = TYPE_EXYNOS4210_COMBINER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210CombinerState),
- .instance_init = exynos4210_combiner_init,
.class_init = exynos4210_combiner_class_init,
};
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
index fd7a8f305..4f7e89f7b 100644
--- a/hw/intc/exynos4210_gic.c
+++ b/hw/intc/exynos4210_gic.c
@@ -281,11 +281,10 @@ static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
}
-static void exynos4210_gic_init(Object *obj)
+static int exynos4210_gic_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- Exynos4210GicState *s = EXYNOS4210_GIC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ Exynos4210GicState *s = EXYNOS4210_GIC(dev);
uint32_t i;
const char cpu_prefix[] = "exynos4210-gic-alias_cpu";
const char dist_prefix[] = "exynos4210-gic-alias_dist";
@@ -306,15 +305,15 @@ static void exynos4210_gic_init(Object *obj)
qdev_init_gpio_in(dev, exynos4210_gic_set_irq,
EXYNOS4210_GIC_NIRQ - 32);
- memory_region_init(&s->cpu_container, obj, "exynos4210-cpu-container",
+ memory_region_init(&s->cpu_container, OBJECT(s), "exynos4210-cpu-container",
EXYNOS4210_EXT_GIC_CPU_REGION_SIZE);
- memory_region_init(&s->dist_container, obj, "exynos4210-dist-container",
+ memory_region_init(&s->dist_container, OBJECT(s), "exynos4210-dist-container",
EXYNOS4210_EXT_GIC_DIST_REGION_SIZE);
for (i = 0; i < s->num_cpu; i++) {
/* Map CPU interface per SMP Core */
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
- memory_region_init_alias(&s->cpu_alias[i], obj,
+ memory_region_init_alias(&s->cpu_alias[i], OBJECT(s),
cpu_alias_name,
sysbus_mmio_get_region(busdev, 1),
0,
@@ -324,7 +323,7 @@ static void exynos4210_gic_init(Object *obj)
/* Map Distributor per SMP Core */
sprintf(dist_alias_name, "%s%x", dist_prefix, i);
- memory_region_init_alias(&s->dist_alias[i], obj,
+ memory_region_init_alias(&s->dist_alias[i], OBJECT(s),
dist_alias_name,
sysbus_mmio_get_region(busdev, 0),
0,
@@ -335,6 +334,8 @@ static void exynos4210_gic_init(Object *obj)
sysbus_init_mmio(sbd, &s->cpu_container);
sysbus_init_mmio(sbd, &s->dist_container);
+
+ return 0;
}
static Property exynos4210_gic_properties[] = {
@@ -345,7 +346,9 @@ static Property exynos4210_gic_properties[] = {
static void exynos4210_gic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = exynos4210_gic_init;
dc->props = exynos4210_gic_properties;
}
@@ -353,7 +356,6 @@ static const TypeInfo exynos4210_gic_info = {
.name = TYPE_EXYNOS4210_GIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210GicState),
- .instance_init = exynos4210_gic_init,
.class_init = exynos4210_gic_class_init,
};
@@ -428,16 +430,9 @@ static void exynos4210_irq_gate_reset(DeviceState *d)
/*
* IRQ Gate initialization.
*/
-static void exynos4210_irq_gate_init(Object *obj)
-{
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-
- sysbus_init_irq(sbd, &s->out);
-}
-
-static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
+static int exynos4210_irq_gate_init(SysBusDevice *sbd)
{
+ DeviceState *dev = DEVICE(sbd);
Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
/* Allocate general purpose input signals and connect a handler to each of
@@ -445,23 +440,27 @@ static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
s->level = g_malloc0(s->n_in * sizeof(*s->level));
+
+ sysbus_init_irq(sbd, &s->out);
+
+ return 0;
}
static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = exynos4210_irq_gate_init;
dc->reset = exynos4210_irq_gate_reset;
dc->vmsd = &vmstate_exynos4210_irq_gate;
dc->props = exynos4210_irq_gate_properties;
- dc->realize = exynos4210_irq_gate_realize;
}
static const TypeInfo exynos4210_irq_gate_info = {
.name = TYPE_EXYNOS4210_IRQ_GATE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210IRQGateState),
- .instance_init = exynos4210_irq_gate_init,
.class_init = exynos4210_irq_gate_class_init,
};
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 3f311740d..20c1e8a24 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -100,4 +100,4 @@ static inline bool gic_test_pending(GICState *s, int irq, int cm)
}
}
-#endif /* QEMU_ARM_GIC_INTERNAL_H */
+#endif /* !QEMU_ARM_GIC_INTERNAL_H */
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
deleted file mode 100644
index 8f3567eda..000000000
--- a/hw/intc/gicv3_internal.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * ARM GICv3 support - internal interfaces
- *
- * 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 QEMU_ARM_GICV3_INTERNAL_H
-#define QEMU_ARM_GICV3_INTERNAL_H
-
-#include "hw/intc/arm_gicv3_common.h"
-
-/* Distributor registers, as offsets from the distributor base address */
-#define GICD_CTLR 0x0000
-#define GICD_TYPER 0x0004
-#define GICD_IIDR 0x0008
-#define GICD_STATUSR 0x0010
-#define GICD_SETSPI_NSR 0x0040
-#define GICD_CLRSPI_NSR 0x0048
-#define GICD_SETSPI_SR 0x0050
-#define GICD_CLRSPI_SR 0x0058
-#define GICD_SEIR 0x0068
-#define GICD_IGROUPR 0x0080
-#define GICD_ISENABLER 0x0100
-#define GICD_ICENABLER 0x0180
-#define GICD_ISPENDR 0x0200
-#define GICD_ICPENDR 0x0280
-#define GICD_ISACTIVER 0x0300
-#define GICD_ICACTIVER 0x0380
-#define GICD_IPRIORITYR 0x0400
-#define GICD_ITARGETSR 0x0800
-#define GICD_ICFGR 0x0C00
-#define GICD_IGRPMODR 0x0D00
-#define GICD_NSACR 0x0E00
-#define GICD_SGIR 0x0F00
-#define GICD_CPENDSGIR 0x0F10
-#define GICD_SPENDSGIR 0x0F20
-#define GICD_IROUTER 0x6000
-#define GICD_IDREGS 0xFFD0
-
-/* GICD_CTLR fields */
-#define GICD_CTLR_EN_GRP0 (1U << 0)
-#define GICD_CTLR_EN_GRP1NS (1U << 1) /* GICv3 5.3.20 */
-#define GICD_CTLR_EN_GRP1S (1U << 2)
-#define GICD_CTLR_EN_GRP1_ALL (GICD_CTLR_EN_GRP1NS | GICD_CTLR_EN_GRP1S)
-/* Bit 4 is ARE if the system doesn't support TrustZone, ARE_S otherwise */
-#define GICD_CTLR_ARE (1U << 4)
-#define GICD_CTLR_ARE_S (1U << 4)
-#define GICD_CTLR_ARE_NS (1U << 5)
-#define GICD_CTLR_DS (1U << 6)
-#define GICD_CTLR_E1NWF (1U << 7)
-#define GICD_CTLR_RWP (1U << 31)
-
-/*
- * Redistributor frame offsets from RD_base
- */
-#define GICR_SGI_OFFSET 0x10000
-
-/*
- * Redistributor registers, offsets from RD_base
- */
-#define GICR_CTLR 0x0000
-#define GICR_IIDR 0x0004
-#define GICR_TYPER 0x0008
-#define GICR_STATUSR 0x0010
-#define GICR_WAKER 0x0014
-#define GICR_SETLPIR 0x0040
-#define GICR_CLRLPIR 0x0048
-#define GICR_PROPBASER 0x0070
-#define GICR_PENDBASER 0x0078
-#define GICR_INVLPIR 0x00A0
-#define GICR_INVALLR 0x00B0
-#define GICR_SYNCR 0x00C0
-#define GICR_IDREGS 0xFFD0
-
-/* SGI and PPI Redistributor registers, offsets from RD_base */
-#define GICR_IGROUPR0 (GICR_SGI_OFFSET + 0x0080)
-#define GICR_ISENABLER0 (GICR_SGI_OFFSET + 0x0100)
-#define GICR_ICENABLER0 (GICR_SGI_OFFSET + 0x0180)
-#define GICR_ISPENDR0 (GICR_SGI_OFFSET + 0x0200)
-#define GICR_ICPENDR0 (GICR_SGI_OFFSET + 0x0280)
-#define GICR_ISACTIVER0 (GICR_SGI_OFFSET + 0x0300)
-#define GICR_ICACTIVER0 (GICR_SGI_OFFSET + 0x0380)
-#define GICR_IPRIORITYR (GICR_SGI_OFFSET + 0x0400)
-#define GICR_ICFGR0 (GICR_SGI_OFFSET + 0x0C00)
-#define GICR_ICFGR1 (GICR_SGI_OFFSET + 0x0C04)
-#define GICR_IGRPMODR0 (GICR_SGI_OFFSET + 0x0D00)
-#define GICR_NSACR (GICR_SGI_OFFSET + 0x0E00)
-
-#define GICR_CTLR_ENABLE_LPIS (1U << 0)
-#define GICR_CTLR_RWP (1U << 3)
-#define GICR_CTLR_DPG0 (1U << 24)
-#define GICR_CTLR_DPG1NS (1U << 25)
-#define GICR_CTLR_DPG1S (1U << 26)
-#define GICR_CTLR_UWP (1U << 31)
-
-#define GICR_TYPER_PLPIS (1U << 0)
-#define GICR_TYPER_VLPIS (1U << 1)
-#define GICR_TYPER_DIRECTLPI (1U << 3)
-#define GICR_TYPER_LAST (1U << 4)
-#define GICR_TYPER_DPGS (1U << 5)
-#define GICR_TYPER_PROCNUM (0xFFFFU << 8)
-#define GICR_TYPER_COMMONLPIAFF (0x3 << 24)
-#define GICR_TYPER_AFFINITYVALUE (0xFFFFFFFFULL << 32)
-
-#define GICR_WAKER_ProcessorSleep (1U << 1)
-#define GICR_WAKER_ChildrenAsleep (1U << 2)
-
-#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK (7ULL << 56)
-#define GICR_PROPBASER_ADDR_MASK (0xfffffffffULL << 12)
-#define GICR_PROPBASER_SHAREABILITY_MASK (3U << 10)
-#define GICR_PROPBASER_CACHEABILITY_MASK (7U << 7)
-#define GICR_PROPBASER_IDBITS_MASK (0x1f)
-
-#define GICR_PENDBASER_PTZ (1ULL << 62)
-#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK (7ULL << 56)
-#define GICR_PENDBASER_ADDR_MASK (0xffffffffULL << 16)
-#define GICR_PENDBASER_SHAREABILITY_MASK (3U << 10)
-#define GICR_PENDBASER_CACHEABILITY_MASK (7U << 7)
-
-#define ICC_CTLR_EL1_CBPR (1U << 0)
-#define ICC_CTLR_EL1_EOIMODE (1U << 1)
-#define ICC_CTLR_EL1_PMHE (1U << 6)
-#define ICC_CTLR_EL1_PRIBITS_SHIFT 8
-#define ICC_CTLR_EL1_IDBITS_SHIFT 11
-#define ICC_CTLR_EL1_SEIS (1U << 14)
-#define ICC_CTLR_EL1_A3V (1U << 15)
-
-#define ICC_PMR_PRIORITY_MASK 0xff
-#define ICC_BPR_BINARYPOINT_MASK 0x07
-#define ICC_IGRPEN_ENABLE 0x01
-
-#define ICC_CTLR_EL3_CBPR_EL1S (1U << 0)
-#define ICC_CTLR_EL3_CBPR_EL1NS (1U << 1)
-#define ICC_CTLR_EL3_EOIMODE_EL3 (1U << 2)
-#define ICC_CTLR_EL3_EOIMODE_EL1S (1U << 3)
-#define ICC_CTLR_EL3_EOIMODE_EL1NS (1U << 4)
-#define ICC_CTLR_EL3_RM (1U << 5)
-#define ICC_CTLR_EL3_PMHE (1U << 6)
-#define ICC_CTLR_EL3_PRIBITS_SHIFT 8
-#define ICC_CTLR_EL3_IDBITS_SHIFT 11
-#define ICC_CTLR_EL3_SEIS (1U << 14)
-#define ICC_CTLR_EL3_A3V (1U << 15)
-#define ICC_CTLR_EL3_NDS (1U << 17)
-
-/* Special interrupt IDs */
-#define INTID_SECURE 1020
-#define INTID_NONSECURE 1021
-#define INTID_SPURIOUS 1023
-
-/* Functions internal to the emulated GICv3 */
-
-/**
- * gicv3_redist_update:
- * @cs: GICv3CPUState for this redistributor
- *
- * Recalculate the highest priority pending interrupt after a
- * change to redistributor state, and inform the CPU accordingly.
- */
-void gicv3_redist_update(GICv3CPUState *cs);
-
-/**
- * gicv3_update:
- * @s: GICv3State
- * @start: first interrupt whose state changed
- * @len: length of the range of interrupts whose state changed
- *
- * Recalculate the highest priority pending interrupts after a
- * change to the distributor state affecting @len interrupts
- * starting at @start, and inform the CPUs accordingly.
- */
-void gicv3_update(GICv3State *s, int start, int len);
-
-/**
- * gicv3_full_update_noirqset:
- * @s: GICv3State
- *
- * Recalculate the cached information about highest priority
- * pending interrupts, but don't inform the CPUs. This should be
- * called after an incoming migration has loaded new state.
- */
-void gicv3_full_update_noirqset(GICv3State *s);
-
-/**
- * gicv3_full_update:
- * @s: GICv3State
- *
- * Recalculate the highest priority pending interrupts after
- * a change that could affect the status of all interrupts,
- * and inform the CPUs accordingly.
- */
-void gicv3_full_update(GICv3State *s);
-MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
- unsigned size, MemTxAttrs attrs);
-MemTxResult gicv3_dist_write(void *opaque, hwaddr addr, uint64_t data,
- unsigned size, MemTxAttrs attrs);
-MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
- unsigned size, MemTxAttrs attrs);
-MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
- unsigned size, MemTxAttrs attrs);
-void gicv3_dist_set_irq(GICv3State *s, int irq, int level);
-void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level);
-void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
-void gicv3_init_cpuif(GICv3State *s);
-
-/**
- * gicv3_cpuif_update:
- * @cs: GICv3CPUState for the CPU to update
- *
- * Recalculate whether to assert the IRQ or FIQ lines after a change
- * to the current highest priority pending interrupt, the CPU's
- * current running priority or the CPU's current exception level or
- * security state.
- */
-void gicv3_cpuif_update(GICv3CPUState *cs);
-
-static inline uint32_t gicv3_iidr(void)
-{
- /* Return the Implementer Identification Register value
- * for the emulated GICv3, as reported in GICD_IIDR and GICR_IIDR.
- *
- * We claim to be an ARM r0p0 with a zero ProductID.
- * This is the same as an r0p0 GIC-500.
- */
- return 0x43b;
-}
-
-static inline uint32_t gicv3_idreg(int regoffset)
-{
- /* Return the value of the CoreSight ID register at the specified
- * offset from the first ID register (as found in the distributor
- * and redistributor register banks).
- * These values indicate an ARM implementation of a GICv3.
- */
- static const uint8_t gicd_ids[] = {
- 0x44, 0x00, 0x00, 0x00, 0x92, 0xB4, 0x3B, 0x00, 0x0D, 0xF0, 0x05, 0xB1
- };
- return gicd_ids[regoffset / 4];
-}
-
-/**
- * gicv3_irq_group:
- *
- * Return the group which this interrupt is configured as (GICV3_G0,
- * GICV3_G1 or GICV3_G1NS).
- */
-static inline int gicv3_irq_group(GICv3State *s, GICv3CPUState *cs, int irq)
-{
- bool grpbit, grpmodbit;
-
- if (irq < GIC_INTERNAL) {
- grpbit = extract32(cs->gicr_igroupr0, irq, 1);
- grpmodbit = extract32(cs->gicr_igrpmodr0, irq, 1);
- } else {
- grpbit = gicv3_gicd_group_test(s, irq);
- grpmodbit = gicv3_gicd_grpmod_test(s, irq);
- }
- if (grpbit) {
- return GICV3_G1NS;
- }
- if (s->gicd_ctlr & GICD_CTLR_DS) {
- return GICV3_G0;
- }
- return grpmodbit ? GICV3_G1 : GICV3_G0;
-}
-
-/**
- * gicv3_redist_affid:
- *
- * Return the 32-bit affinity ID of the CPU connected to this redistributor
- */
-static inline uint32_t gicv3_redist_affid(GICv3CPUState *cs)
-{
- return cs->gicr_typer >> 32;
-}
-
-/**
- * gicv3_cache_target_cpustate:
- *
- * Update the cached CPU state corresponding to the target for this interrupt
- * (which is kept in s->gicd_irouter_target[]).
- */
-static inline void gicv3_cache_target_cpustate(GICv3State *s, int irq)
-{
- GICv3CPUState *cs = NULL;
- int i;
- uint32_t tgtaff = extract64(s->gicd_irouter[irq], 0, 24) |
- extract64(s->gicd_irouter[irq], 32, 8) << 24;
-
- for (i = 0; i < s->num_cpu; i++) {
- if (s->cpu[i].gicr_typer >> 32 == tgtaff) {
- cs = &s->cpu[i];
- break;
- }
- }
-
- s->gicd_irouter_target[irq] = cs;
-}
-
-/**
- * gicv3_cache_all_target_cpustates:
- *
- * Populate the entire cache of CPU state pointers for interrupt targets
- * (eg after inbound migration or CPU reset)
- */
-static inline void gicv3_cache_all_target_cpustates(GICv3State *s)
-{
- int irq;
-
- for (irq = GIC_INTERNAL; irq < GICV3_MAXIRQ; irq++) {
- gicv3_cache_target_cpustate(s, irq);
- }
-}
-
-#endif /* QEMU_ARM_GICV3_INTERNAL_H */
diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index ac7e63f38..f5ca8f752 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -31,7 +31,6 @@
#include "hw/sparc/grlib.h"
#include "trace.h"
-#include "qapi/error.h"
#define IRQMP_MAX_CPU 16
#define IRQMP_REG_SIZE 256 /* Size of memory mapped registers */
@@ -324,27 +323,23 @@ static void grlib_irqmp_reset(DeviceState *d)
irqmp->state->parent = irqmp;
}
-static void grlib_irqmp_init(Object *obj)
+static int grlib_irqmp_init(SysBusDevice *dev)
{
- IRQMP *irqmp = GRLIB_IRQMP(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ IRQMP *irqmp = GRLIB_IRQMP(dev);
+
+ /* Check parameters */
+ if (irqmp->set_pil_in == NULL) {
+ return -1;
+ }
- memory_region_init_io(&irqmp->iomem, obj, &grlib_irqmp_ops, irqmp,
+ memory_region_init_io(&irqmp->iomem, OBJECT(dev), &grlib_irqmp_ops, irqmp,
"irqmp", IRQMP_REG_SIZE);
irqmp->state = g_malloc0(sizeof *irqmp->state);
sysbus_init_mmio(dev, &irqmp->iomem);
-}
-static void grlib_irqmp_realize(DeviceState *dev, Error **errp)
-{
- IRQMP *irqmp = GRLIB_IRQMP(dev);
-
- /* Check parameters */
- if (irqmp->set_pil_in == NULL) {
- error_setg(errp, "set_pil_in cannot be NULL.");
- }
+ return 0;
}
static Property grlib_irqmp_properties[] = {
@@ -356,19 +351,19 @@ static Property grlib_irqmp_properties[] = {
static void grlib_irqmp_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = grlib_irqmp_init;
dc->reset = grlib_irqmp_reset;
dc->props = grlib_irqmp_properties;
/* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */
dc->cannot_instantiate_with_device_add_yet = true;
- dc->realize = grlib_irqmp_realize;
}
static const TypeInfo grlib_irqmp_info = {
.name = TYPE_GRLIB_IRQMP,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IRQMP),
- .instance_init = grlib_irqmp_init,
.class_init = grlib_irqmp_class_init,
};
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index c2607a586..bb43669b9 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -27,7 +27,6 @@
#include "hw/isa/isa.h"
#include "monitor/monitor.h"
#include "qemu/timer.h"
-#include "qemu/log.h"
#include "hw/isa/i8259_internal.h"
/* debug PIC */
diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c
index 813e587a6..702765577 100644
--- a/hw/intc/imx_avic.c
+++ b/hw/intc/imx_avic.c
@@ -17,7 +17,6 @@
#include "qemu/osdep.h"
#include "hw/intc/imx_avic.h"
-#include "qemu/log.h"
#ifndef DEBUG_IMX_AVIC
#define DEBUG_IMX_AVIC 0
@@ -322,26 +321,28 @@ static void imx_avic_reset(DeviceState *dev)
memset(s->prio, 0, sizeof s->prio);
}
-static void imx_avic_init(Object *obj)
+static int imx_avic_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- IMXAVICState *s = IMX_AVIC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ IMXAVICState *s = IMX_AVIC(dev);
- memory_region_init_io(&s->iomem, obj, &imx_avic_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s,
TYPE_IMX_AVIC, 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
qdev_init_gpio_in(dev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS);
sysbus_init_irq(sbd, &s->irq);
sysbus_init_irq(sbd, &s->fiq);
+
+ return 0;
}
static void imx_avic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
-
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = imx_avic_init;
dc->vmsd = &vmstate_imx_avic;
dc->reset = imx_avic_reset;
dc->desc = "i.MX Advanced Vector Interrupt Controller";
@@ -351,7 +352,6 @@ static const TypeInfo imx_avic_info = {
.name = TYPE_IMX_AVIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMXAVICState),
- .instance_init = imx_avic_init,
.class_init = imx_avic_class_init,
};
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
index 31791b098..378e663f6 100644
--- a/hw/intc/ioapic.c
+++ b/hw/intc/ioapic.c
@@ -21,18 +21,13 @@
*/
#include "qemu/osdep.h"
-#include "qemu/error-report.h"
#include "monitor/monitor.h"
#include "hw/hw.h"
#include "hw/i386/pc.h"
-#include "hw/i386/apic.h"
#include "hw/i386/ioapic.h"
#include "hw/i386/ioapic_internal.h"
#include "include/hw/pci/msi.h"
#include "sysemu/kvm.h"
-#include "target-i386/cpu.h"
-#include "hw/i386/apic-msidef.h"
-#include "hw/i386/x86-iommu.h"
//#define DEBUG_IOAPIC
@@ -52,56 +47,16 @@ static IOAPICCommonState *ioapics[MAX_IOAPICS];
/* global variable from ioapic_common.c */
extern int ioapic_no;
-struct ioapic_entry_info {
- /* fields parsed from IOAPIC entries */
- uint8_t masked;
- uint8_t trig_mode;
- uint16_t dest_idx;
- uint8_t dest_mode;
- uint8_t delivery_mode;
- uint8_t vector;
-
- /* MSI message generated from above parsed fields */
- uint32_t addr;
- uint32_t data;
-};
-
-static void ioapic_entry_parse(uint64_t entry, struct ioapic_entry_info *info)
-{
- memset(info, 0, sizeof(*info));
- info->masked = (entry >> IOAPIC_LVT_MASKED_SHIFT) & 1;
- info->trig_mode = (entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1;
- /*
- * By default, this would be dest_id[8] + reserved[8]. When IR
- * is enabled, this would be interrupt_index[15] +
- * interrupt_format[1]. This field never means anything, but
- * only used to generate corresponding MSI.
- */
- info->dest_idx = (entry >> IOAPIC_LVT_DEST_IDX_SHIFT) & 0xffff;
- info->dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1;
- info->delivery_mode = (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) \
- & IOAPIC_DM_MASK;
- if (info->delivery_mode == IOAPIC_DM_EXTINT) {
- info->vector = pic_read_irq(isa_pic);
- } else {
- info->vector = entry & IOAPIC_VECTOR_MASK;
- }
-
- info->addr = APIC_DEFAULT_ADDRESS | \
- (info->dest_idx << MSI_ADDR_DEST_IDX_SHIFT) | \
- (info->dest_mode << MSI_ADDR_DEST_MODE_SHIFT);
- info->data = (info->vector << MSI_DATA_VECTOR_SHIFT) | \
- (info->trig_mode << MSI_DATA_TRIGGER_SHIFT) | \
- (info->delivery_mode << MSI_DATA_DELIVERY_MODE_SHIFT);
-}
-
static void ioapic_service(IOAPICCommonState *s)
{
- AddressSpace *ioapic_as = PC_MACHINE(qdev_get_machine())->ioapic_as;
- struct ioapic_entry_info info;
uint8_t i;
+ uint8_t trig_mode;
+ uint8_t vector;
+ uint8_t delivery_mode;
uint32_t mask;
uint64_t entry;
+ uint8_t dest;
+ uint8_t dest_mode;
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
mask = 1 << i;
@@ -109,39 +64,40 @@ static void ioapic_service(IOAPICCommonState *s)
int coalesce = 0;
entry = s->ioredtbl[i];
- ioapic_entry_parse(entry, &info);
- if (!info.masked) {
- if (info.trig_mode == IOAPIC_TRIGGER_EDGE) {
+ if (!(entry & IOAPIC_LVT_MASKED)) {
+ trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1);
+ dest = entry >> IOAPIC_LVT_DEST_SHIFT;
+ dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1;
+ delivery_mode =
+ (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) & IOAPIC_DM_MASK;
+ if (trig_mode == IOAPIC_TRIGGER_EDGE) {
s->irr &= ~mask;
} else {
coalesce = s->ioredtbl[i] & IOAPIC_LVT_REMOTE_IRR;
s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
}
-
- if (coalesce) {
- /* We are level triggered interrupts, and the
- * guest should be still working on previous one,
- * so skip it. */
- continue;
+ if (delivery_mode == IOAPIC_DM_EXTINT) {
+ vector = pic_read_irq(isa_pic);
+ } else {
+ vector = entry & IOAPIC_VECTOR_MASK;
}
-
#ifdef CONFIG_KVM
if (kvm_irqchip_is_split()) {
- if (info.trig_mode == IOAPIC_TRIGGER_EDGE) {
+ if (trig_mode == IOAPIC_TRIGGER_EDGE) {
kvm_set_irq(kvm_state, i, 1);
kvm_set_irq(kvm_state, i, 0);
} else {
- kvm_set_irq(kvm_state, i, 1);
+ if (!coalesce) {
+ kvm_set_irq(kvm_state, i, 1);
+ }
}
continue;
}
+#else
+ (void)coalesce;
#endif
-
- /* No matter whether IR is enabled, we translate
- * the IOAPIC message into a MSI one, and its
- * address space will decide whether we need a
- * translation. */
- stl_le_phys(ioapic_as, info.addr, info.data);
+ apic_deliver_irq(dest, dest_mode, delivery_mode, vector,
+ trig_mode);
}
}
}
@@ -192,11 +148,30 @@ static void ioapic_update_kvm_routes(IOAPICCommonState *s)
if (kvm_irqchip_is_split()) {
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ uint64_t entry = s->ioredtbl[i];
+ uint8_t trig_mode;
+ uint8_t delivery_mode;
+ uint8_t dest;
+ uint8_t dest_mode;
+ uint64_t pin_polarity;
MSIMessage msg;
- struct ioapic_entry_info info;
- ioapic_entry_parse(s->ioredtbl[i], &info);
- msg.address = info.addr;
- msg.data = info.data;
+
+ trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1);
+ dest = entry >> IOAPIC_LVT_DEST_SHIFT;
+ dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1;
+ pin_polarity = (entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1;
+ delivery_mode =
+ (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) & IOAPIC_DM_MASK;
+
+ msg.address = APIC_DEFAULT_ADDRESS;
+ msg.address |= dest_mode << 2;
+ msg.address |= dest << 12;
+
+ msg.data = entry & IOAPIC_VECTOR_MASK;
+ msg.data |= delivery_mode << APIC_DELIVERY_MODE_SHIFT;
+ msg.data |= pin_polarity << APIC_POLARITY_SHIFT;
+ msg.data |= trig_mode << APIC_TRIG_MODE_SHIFT;
+
kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL);
}
kvm_irqchip_commit_routes(kvm_state);
@@ -204,16 +179,6 @@ static void ioapic_update_kvm_routes(IOAPICCommonState *s)
#endif
}
-#ifdef CONFIG_KVM
-static void ioapic_iec_notifier(void *private, bool global,
- uint32_t index, uint32_t mask)
-{
- IOAPICCommonState *s = (IOAPICCommonState *)private;
- /* For simplicity, we just update all the routes */
- ioapic_update_kvm_routes(s);
-}
-#endif
-
void ioapic_eoi_broadcast(int vector)
{
IOAPICCommonState *s;
@@ -270,7 +235,7 @@ ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size)
val = s->id << IOAPIC_ID_SHIFT;
break;
case IOAPIC_REG_VER:
- val = s->version |
+ val = IOAPIC_VERSION |
((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT);
break;
default:
@@ -289,34 +254,6 @@ ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size)
return val;
}
-/*
- * This is to satisfy the hack in Linux kernel. One hack of it is to
- * simulate clearing the Remote IRR bit of IOAPIC entry using the
- * following:
- *
- * "For IO-APIC's with EOI register, we use that to do an explicit EOI.
- * Otherwise, we simulate the EOI message manually by changing the trigger
- * mode to edge and then back to level, with RTE being masked during
- * this."
- *
- * (See linux kernel __eoi_ioapic_pin() comment in commit c0205701)
- *
- * This is based on the assumption that, Remote IRR bit will be
- * cleared by IOAPIC hardware when configured as edge-triggered
- * interrupts.
- *
- * Without this, level-triggered interrupts in IR mode might fail to
- * work correctly.
- */
-static inline void
-ioapic_fix_edge_remote_irr(uint64_t *entry)
-{
- if (!(*entry & IOAPIC_LVT_TRIGGER_MODE)) {
- /* Edge-triggered interrupts, make sure remote IRR is zero */
- *entry &= ~((uint64_t)IOAPIC_LVT_REMOTE_IRR);
- }
-}
-
static void
ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val,
unsigned int size)
@@ -343,7 +280,6 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val,
default:
index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1;
if (index >= 0 && index < IOAPIC_NUM_PINS) {
- uint64_t ro_bits = s->ioredtbl[index] & IOAPIC_RO_BITS;
if (s->ioregsel & 1) {
s->ioredtbl[index] &= 0xffffffff;
s->ioredtbl[index] |= (uint64_t)val << 32;
@@ -351,21 +287,10 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val,
s->ioredtbl[index] &= ~0xffffffffULL;
s->ioredtbl[index] |= val;
}
- /* restore RO bits */
- s->ioredtbl[index] &= IOAPIC_RW_BITS;
- s->ioredtbl[index] |= ro_bits;
- ioapic_fix_edge_remote_irr(&s->ioredtbl[index]);
ioapic_service(s);
}
}
break;
- case IOAPIC_EOI:
- /* Explicit EOI is only supported for IOAPIC version 0x20 */
- if (size != 4 || s->version != 0x20) {
- break;
- }
- ioapic_eoi_broadcast(val);
- break;
}
ioapic_update_kvm_routes(s);
@@ -377,49 +302,18 @@ static const MemoryRegionOps ioapic_io_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void ioapic_machine_done_notify(Notifier *notifier, void *data)
-{
-#ifdef CONFIG_KVM
- IOAPICCommonState *s = container_of(notifier, IOAPICCommonState,
- machine_done);
-
- if (kvm_irqchip_is_split()) {
- X86IOMMUState *iommu = x86_iommu_get_default();
- if (iommu) {
- /* Register this IOAPIC with IOMMU IEC notifier, so that
- * when there are IR invalidates, we can be notified to
- * update kernel IR cache. */
- x86_iommu_iec_register_notifier(iommu, ioapic_iec_notifier, s);
- }
- }
-#endif
-}
-
static void ioapic_realize(DeviceState *dev, Error **errp)
{
IOAPICCommonState *s = IOAPIC_COMMON(dev);
- if (s->version != 0x11 && s->version != 0x20) {
- error_report("IOAPIC only supports version 0x11 or 0x20 "
- "(default: 0x11).");
- exit(1);
- }
-
memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s,
"ioapic", 0x1000);
qdev_init_gpio_in(dev, ioapic_set_irq, IOAPIC_NUM_PINS);
ioapics[ioapic_no] = s;
- s->machine_done.notify = ioapic_machine_done_notify;
- qemu_add_machine_init_done_notifier(&s->machine_done);
}
-static Property ioapic_properties[] = {
- DEFINE_PROP_UINT8("version", IOAPICCommonState, version, 0x11),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void ioapic_class_init(ObjectClass *klass, void *data)
{
IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
@@ -427,7 +321,6 @@ static void ioapic_class_init(ObjectClass *klass, void *data)
k->realize = ioapic_realize;
dc->reset = ioapic_reset_common;
- dc->props = ioapic_properties;
}
static const TypeInfo ioapic_info = {
diff --git a/hw/intc/lm32_pic.c b/hw/intc/lm32_pic.c
index 3dad01c5b..edc08f184 100644
--- a/hw/intc/lm32_pic.c
+++ b/hw/intc/lm32_pic.c
@@ -152,16 +152,17 @@ static void pic_reset(DeviceState *d)
}
}
-static void lm32_pic_init(Object *obj)
+static int lm32_pic_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- LM32PicState *s = LM32_PIC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ LM32PicState *s = LM32_PIC(dev);
qdev_init_gpio_in(dev, irq_handler, 32);
sysbus_init_irq(sbd, &s->parent_irq);
pic = s;
+
+ return 0;
}
static const VMStateDescription vmstate_lm32_pic = {
@@ -180,7 +181,9 @@ static const VMStateDescription vmstate_lm32_pic = {
static void lm32_pic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = lm32_pic_init;
dc->reset = pic_reset;
dc->vmsd = &vmstate_lm32_pic;
}
@@ -189,7 +192,6 @@ static const TypeInfo lm32_pic_info = {
.name = TYPE_LM32_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LM32PicState),
- .instance_init = lm32_pic_init,
.class_init = lm32_pic_class_init,
};
diff --git a/hw/intc/mips_gic.c b/hw/intc/mips_gic.c
deleted file mode 100644
index 6e257730f..000000000
--- a/hw/intc/mips_gic.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * 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) 2012 MIPS Technologies, Inc. All rights reserved.
- * Authors: Sanjay Lal <sanjayl@kymasys.com>
- *
- * Copyright (C) 2016 Imagination Technologies
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "qapi/error.h"
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "exec/memory.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/kvm.h"
-#include "kvm_mips.h"
-#include "hw/intc/mips_gic.h"
-
-static void mips_gic_set_vp_irq(MIPSGICState *gic, int vp, int pin, int level)
-{
- int ored_level = level;
- int i;
-
- /* ORing pending registers sharing same pin */
- if (!ored_level) {
- for (i = 0; i < gic->num_irq; i++) {
- if ((gic->irq_state[i].map_pin & GIC_MAP_MSK) == pin &&
- gic->irq_state[i].map_vp == vp &&
- gic->irq_state[i].enabled) {
- ored_level |= gic->irq_state[i].pending;
- }
- if (ored_level) {
- /* no need to iterate all interrupts */
- break;
- }
- }
- if (((gic->vps[vp].compare_map & GIC_MAP_MSK) == pin) &&
- (gic->vps[vp].mask & GIC_VP_MASK_CMP_MSK)) {
- /* ORing with local pending register (count/compare) */
- ored_level |= (gic->vps[vp].pend & GIC_VP_MASK_CMP_MSK) >>
- GIC_VP_MASK_CMP_SHF;
- }
- }
- if (kvm_enabled()) {
- kvm_mips_set_ipi_interrupt(mips_env_get_cpu(gic->vps[vp].env),
- pin + GIC_CPU_PIN_OFFSET,
- ored_level);
- } else {
- qemu_set_irq(gic->vps[vp].env->irq[pin + GIC_CPU_PIN_OFFSET],
- ored_level);
- }
-}
-
-static void gic_set_irq(void *opaque, int n_IRQ, int level)
-{
- MIPSGICState *gic = (MIPSGICState *) opaque;
- int vp = gic->irq_state[n_IRQ].map_vp;
- int pin = gic->irq_state[n_IRQ].map_pin & GIC_MAP_MSK;
-
- gic->irq_state[n_IRQ].pending = (uint8_t) level;
- if (!gic->irq_state[n_IRQ].enabled) {
- /* GIC interrupt source disabled */
- return;
- }
- if (vp < 0 || vp >= gic->num_vps) {
- return;
- }
- mips_gic_set_vp_irq(gic, vp, pin, level);
-}
-
-#define OFFSET_CHECK(c) \
- do { \
- if (!(c)) { \
- goto bad_offset; \
- } \
- } while (0)
-
-/* GIC Read VP Local/Other Registers */
-static uint64_t gic_read_vp(MIPSGICState *gic, uint32_t vp_index, hwaddr addr,
- unsigned size)
-{
- switch (addr) {
- case GIC_VP_CTL_OFS:
- return gic->vps[vp_index].ctl;
- case GIC_VP_PEND_OFS:
- mips_gictimer_get_sh_count(gic->gic_timer);
- return gic->vps[vp_index].pend;
- case GIC_VP_MASK_OFS:
- return gic->vps[vp_index].mask;
- case GIC_VP_COMPARE_MAP_OFS:
- return gic->vps[vp_index].compare_map;
- case GIC_VP_OTHER_ADDR_OFS:
- return gic->vps[vp_index].other_addr;
- case GIC_VP_IDENT_OFS:
- return vp_index;
- case GIC_VP_COMPARE_LO_OFS:
- return mips_gictimer_get_vp_compare(gic->gic_timer, vp_index);
- case GIC_VP_COMPARE_HI_OFS:
- return 0;
- default:
- qemu_log_mask(LOG_UNIMP, "Read %d bytes at GIC offset LOCAL/OTHER 0x%"
- PRIx64 "\n", size, addr);
- break;
- }
- return 0;
-}
-
-static uint64_t gic_read(void *opaque, hwaddr addr, unsigned size)
-{
- MIPSGICState *gic = (MIPSGICState *) opaque;
- uint32_t vp_index = current_cpu->cpu_index;
- uint64_t ret = 0;
- int i, base, irq_src;
- uint32_t other_index;
-
- switch (addr) {
- case GIC_SH_CONFIG_OFS:
- ret = gic->sh_config | (mips_gictimer_get_countstop(gic->gic_timer) <<
- GIC_SH_CONFIG_COUNTSTOP_SHF);
- break;
- case GIC_SH_COUNTERLO_OFS:
- ret = mips_gictimer_get_sh_count(gic->gic_timer);
- break;
- case GIC_SH_COUNTERHI_OFS:
- ret = 0;
- break;
- case GIC_SH_PEND_OFS ... GIC_SH_PEND_LAST_OFS:
- /* each bit represents pending status for an interrupt pin */
- base = (addr - GIC_SH_PEND_OFS) * 8;
- OFFSET_CHECK((base + size * 8) <= gic->num_irq);
- for (i = 0; i < size * 8; i++) {
- ret |= (uint64_t) (gic->irq_state[base + i].pending) << i;
- }
- break;
- case GIC_SH_MASK_OFS ... GIC_SH_MASK_LAST_OFS:
- /* each bit represents status for an interrupt pin */
- base = (addr - GIC_SH_MASK_OFS) * 8;
- OFFSET_CHECK((base + size * 8) <= gic->num_irq);
- for (i = 0; i < size * 8; i++) {
- ret |= (uint64_t) (gic->irq_state[base + i].enabled) << i;
- }
- break;
- case GIC_SH_MAP0_PIN_OFS ... GIC_SH_MAP255_PIN_OFS:
- /* 32 bits per a pin */
- irq_src = (addr - GIC_SH_MAP0_PIN_OFS) / 4;
- OFFSET_CHECK(irq_src < gic->num_irq);
- ret = gic->irq_state[irq_src].map_pin;
- break;
- case GIC_SH_MAP0_VP_OFS ... GIC_SH_MAP255_VP_LAST_OFS:
- /* up to 32 bytes per a pin */
- irq_src = (addr - GIC_SH_MAP0_VP_OFS) / 32;
- OFFSET_CHECK(irq_src < gic->num_irq);
- if ((gic->irq_state[irq_src].map_vp) >= 0) {
- ret = (uint64_t) 1 << (gic->irq_state[irq_src].map_vp);
- } else {
- ret = 0;
- }
- break;
- /* VP-Local Register */
- case VP_LOCAL_SECTION_OFS ... (VP_LOCAL_SECTION_OFS + GIC_VL_BRK_GROUP):
- ret = gic_read_vp(gic, vp_index, addr - VP_LOCAL_SECTION_OFS, size);
- break;
- /* VP-Other Register */
- case VP_OTHER_SECTION_OFS ... (VP_OTHER_SECTION_OFS + GIC_VL_BRK_GROUP):
- other_index = gic->vps[vp_index].other_addr;
- ret = gic_read_vp(gic, other_index, addr - VP_OTHER_SECTION_OFS, size);
- break;
- /* User-Mode Visible section */
- case USM_VISIBLE_SECTION_OFS + GIC_USER_MODE_COUNTERLO:
- ret = mips_gictimer_get_sh_count(gic->gic_timer);
- break;
- case USM_VISIBLE_SECTION_OFS + GIC_USER_MODE_COUNTERHI:
- ret = 0;
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "Read %d bytes at GIC offset 0x%" PRIx64 "\n",
- size, addr);
- break;
- }
- return ret;
-bad_offset:
- qemu_log_mask(LOG_GUEST_ERROR, "Wrong GIC offset at 0x%" PRIx64 "\n", addr);
- return 0;
-}
-
-static void gic_timer_expire_cb(void *opaque, uint32_t vp_index)
-{
- MIPSGICState *gic = opaque;
-
- gic->vps[vp_index].pend |= (1 << GIC_LOCAL_INT_COMPARE);
- if (gic->vps[vp_index].pend &
- (gic->vps[vp_index].mask & GIC_VP_MASK_CMP_MSK)) {
- if (gic->vps[vp_index].compare_map & GIC_MAP_TO_PIN_MSK) {
- /* it is safe to set the irq high regardless of other GIC IRQs */
- uint32_t pin = (gic->vps[vp_index].compare_map & GIC_MAP_MSK);
- qemu_irq_raise(gic->vps[vp_index].env->irq
- [pin + GIC_CPU_PIN_OFFSET]);
- }
- }
-}
-
-static void gic_timer_store_vp_compare(MIPSGICState *gic, uint32_t vp_index,
- uint64_t compare)
-{
- gic->vps[vp_index].pend &= ~(1 << GIC_LOCAL_INT_COMPARE);
- if (gic->vps[vp_index].compare_map & GIC_MAP_TO_PIN_MSK) {
- uint32_t pin = (gic->vps[vp_index].compare_map & GIC_MAP_MSK);
- mips_gic_set_vp_irq(gic, vp_index, pin, 0);
- }
- mips_gictimer_store_vp_compare(gic->gic_timer, vp_index, compare);
-}
-
-/* GIC Write VP Local/Other Registers */
-static void gic_write_vp(MIPSGICState *gic, uint32_t vp_index, hwaddr addr,
- uint64_t data, unsigned size)
-{
- switch (addr) {
- case GIC_VP_CTL_OFS:
- /* EIC isn't supported */
- break;
- case GIC_VP_RMASK_OFS:
- gic->vps[vp_index].mask &= ~(data & GIC_VP_SET_RESET_MSK) &
- GIC_VP_SET_RESET_MSK;
- break;
- case GIC_VP_SMASK_OFS:
- gic->vps[vp_index].mask |= data & GIC_VP_SET_RESET_MSK;
- break;
- case GIC_VP_COMPARE_MAP_OFS:
- /* EIC isn't supported */
- OFFSET_CHECK((data & GIC_MAP_MSK) <= GIC_CPU_INT_MAX);
- gic->vps[vp_index].compare_map = data & GIC_MAP_TO_PIN_REG_MSK;
- break;
- case GIC_VP_OTHER_ADDR_OFS:
- OFFSET_CHECK(data < gic->num_vps);
- gic->vps[vp_index].other_addr = data;
- break;
- case GIC_VP_COMPARE_LO_OFS:
- gic_timer_store_vp_compare(gic, vp_index, data);
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "Write %d bytes at GIC offset LOCAL/OTHER "
- "0x%" PRIx64" 0x%08" PRIx64 "\n", size, addr, data);
- break;
- }
- return;
-bad_offset:
- qemu_log_mask(LOG_GUEST_ERROR, "Wrong GIC offset at 0x%" PRIx64 "\n", addr);
- return;
-}
-
-static void gic_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
-{
- int intr;
- MIPSGICState *gic = (MIPSGICState *) opaque;
- uint32_t vp_index = current_cpu->cpu_index;
- int i, base, irq_src;
- uint32_t other_index;
-
- switch (addr) {
- case GIC_SH_CONFIG_OFS:
- {
- uint32_t pre_cntstop = mips_gictimer_get_countstop(gic->gic_timer);
- uint32_t new_cntstop = (data & GIC_SH_CONFIG_COUNTSTOP_MSK) >>
- GIC_SH_CONFIG_COUNTSTOP_SHF;
- if (pre_cntstop != new_cntstop) {
- if (new_cntstop == 1) {
- mips_gictimer_stop_count(gic->gic_timer);
- } else {
- mips_gictimer_start_count(gic->gic_timer);
- }
- }
- }
- break;
- case GIC_SH_COUNTERLO_OFS:
- if (mips_gictimer_get_countstop(gic->gic_timer)) {
- mips_gictimer_store_sh_count(gic->gic_timer, data);
- }
- break;
- case GIC_SH_RMASK_OFS ... GIC_SH_RMASK_LAST_OFS:
- /* up to 64 bits per a pin */
- base = (addr - GIC_SH_RMASK_OFS) * 8;
- OFFSET_CHECK((base + size * 8) <= gic->num_irq);
- for (i = 0; i < size * 8; i++) {
- gic->irq_state[base + i].enabled &= !((data >> i) & 1);
- }
- break;
- case GIC_SH_WEDGE_OFS:
- /* Figure out which VP/HW Interrupt this maps to */
- intr = data & ~GIC_SH_WEDGE_RW_MSK;
- /* Mask/Enabled Checks */
- OFFSET_CHECK(intr < gic->num_irq);
- if (data & GIC_SH_WEDGE_RW_MSK) {
- gic_set_irq(gic, intr, 1);
- } else {
- gic_set_irq(gic, intr, 0);
- }
- break;
- case GIC_SH_SMASK_OFS ... GIC_SH_SMASK_LAST_OFS:
- /* up to 64 bits per a pin */
- base = (addr - GIC_SH_SMASK_OFS) * 8;
- OFFSET_CHECK((base + size * 8) <= gic->num_irq);
- for (i = 0; i < size * 8; i++) {
- gic->irq_state[base + i].enabled |= (data >> i) & 1;
- }
- break;
- case GIC_SH_MAP0_PIN_OFS ... GIC_SH_MAP255_PIN_OFS:
- /* 32 bits per a pin */
- irq_src = (addr - GIC_SH_MAP0_PIN_OFS) / 4;
- OFFSET_CHECK(irq_src < gic->num_irq);
- /* EIC isn't supported */
- OFFSET_CHECK((data & GIC_MAP_MSK) <= GIC_CPU_INT_MAX);
- gic->irq_state[irq_src].map_pin = data & GIC_MAP_TO_PIN_REG_MSK;
- break;
- case GIC_SH_MAP0_VP_OFS ... GIC_SH_MAP255_VP_LAST_OFS:
- /* up to 32 bytes per a pin */
- irq_src = (addr - GIC_SH_MAP0_VP_OFS) / 32;
- OFFSET_CHECK(irq_src < gic->num_irq);
- data = data ? ctz64(data) : -1;
- OFFSET_CHECK(data < gic->num_vps);
- gic->irq_state[irq_src].map_vp = data;
- break;
- case VP_LOCAL_SECTION_OFS ... (VP_LOCAL_SECTION_OFS + GIC_VL_BRK_GROUP):
- gic_write_vp(gic, vp_index, addr - VP_LOCAL_SECTION_OFS, data, size);
- break;
- case VP_OTHER_SECTION_OFS ... (VP_OTHER_SECTION_OFS + GIC_VL_BRK_GROUP):
- other_index = gic->vps[vp_index].other_addr;
- gic_write_vp(gic, other_index, addr - VP_OTHER_SECTION_OFS, data, size);
- break;
- case USM_VISIBLE_SECTION_OFS + GIC_USER_MODE_COUNTERLO:
- case USM_VISIBLE_SECTION_OFS + GIC_USER_MODE_COUNTERHI:
- /* do nothing. Read-only section */
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "Write %d bytes at GIC offset 0x%" PRIx64
- " 0x%08" PRIx64 "\n", size, addr, data);
- break;
- }
- return;
-bad_offset:
- qemu_log_mask(LOG_GUEST_ERROR, "Wrong GIC offset at 0x%" PRIx64 "\n", addr);
-}
-
-static void gic_reset(void *opaque)
-{
- int i;
- MIPSGICState *gic = (MIPSGICState *) opaque;
- int numintrs = (gic->num_irq / 8) - 1;
-
- gic->sh_config = /* COUNTSTOP = 0 it is accessible via MIPSGICTimer*/
- /* CounterHi not implemented */
- (0 << GIC_SH_CONFIG_COUNTBITS_SHF) |
- (numintrs << GIC_SH_CONFIG_NUMINTRS_SHF) |
- (gic->num_vps << GIC_SH_CONFIG_PVPS_SHF);
- for (i = 0; i < gic->num_vps; i++) {
- gic->vps[i].ctl = 0x0;
- gic->vps[i].pend = 0x0;
- /* PERFCNT, TIMER and WD not implemented */
- gic->vps[i].mask = 0x32;
- gic->vps[i].compare_map = GIC_MAP_TO_PIN_MSK;
- mips_gictimer_store_vp_compare(gic->gic_timer, i, 0xffffffff);
- gic->vps[i].other_addr = 0x0;
- }
- for (i = 0; i < gic->num_irq; i++) {
- gic->irq_state[i].enabled = 0;
- gic->irq_state[i].pending = 0;
- gic->irq_state[i].map_pin = GIC_MAP_TO_PIN_MSK;
- gic->irq_state[i].map_vp = -1;
- }
- mips_gictimer_store_sh_count(gic->gic_timer, 0);
- /* COUNTSTOP = 0 */
- mips_gictimer_start_count(gic->gic_timer);
-}
-
-static const MemoryRegionOps gic_ops = {
- .read = gic_read,
- .write = gic_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .impl = {
- .max_access_size = 8,
- },
-};
-
-static void mips_gic_init(Object *obj)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- MIPSGICState *s = MIPS_GIC(obj);
-
- memory_region_init_io(&s->mr, OBJECT(s), &gic_ops, s,
- "mips-gic", GIC_ADDRSPACE_SZ);
- sysbus_init_mmio(sbd, &s->mr);
- qemu_register_reset(gic_reset, s);
-}
-
-static void mips_gic_realize(DeviceState *dev, Error **errp)
-{
- MIPSGICState *s = MIPS_GIC(dev);
- CPUState *cs = first_cpu;
- int i;
-
- if (s->num_vps > GIC_MAX_VPS) {
- error_setg(errp, "Exceeded maximum CPUs %d", s->num_vps);
- return;
- }
- if ((s->num_irq > GIC_MAX_INTRS) || (s->num_irq % 8) || (s->num_irq <= 0)) {
- error_setg(errp, "GIC supports up to %d external interrupts in "
- "multiples of 8 : %d", GIC_MAX_INTRS, s->num_irq);
- return;
- }
- s->vps = g_new(MIPSGICVPState, s->num_vps);
- s->irq_state = g_new(MIPSGICIRQState, s->num_irq);
- /* Register the env for all VPs with the GIC */
- for (i = 0; i < s->num_vps; i++) {
- if (cs != NULL) {
- s->vps[i].env = cs->env_ptr;
- cs = CPU_NEXT(cs);
- } else {
- error_setg(errp,
- "Unable to initialize GIC, CPUState for CPU#%d not valid.", i);
- return;
- }
- }
- s->gic_timer = mips_gictimer_init(s, s->num_vps, gic_timer_expire_cb);
- qdev_init_gpio_in(dev, gic_set_irq, s->num_irq);
- for (i = 0; i < s->num_irq; i++) {
- s->irq_state[i].irq = qdev_get_gpio_in(dev, i);
- }
-}
-
-static Property mips_gic_properties[] = {
- DEFINE_PROP_INT32("num-vp", MIPSGICState, num_vps, 1),
- DEFINE_PROP_INT32("num-irq", MIPSGICState, num_irq, 256),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void mips_gic_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->props = mips_gic_properties;
- dc->realize = mips_gic_realize;
-}
-
-static const TypeInfo mips_gic_info = {
- .name = TYPE_MIPS_GIC,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(MIPSGICState),
- .instance_init = mips_gic_init,
- .class_init = mips_gic_class_init,
-};
-
-static void mips_gic_register_types(void)
-{
- type_register_static(&mips_gic_info);
-}
-
-type_init(mips_gic_register_types)
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index 877be6797..336882510 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -22,7 +22,6 @@
#include "hw/arm/omap.h"
#include "hw/sysbus.h"
#include "qemu/error-report.h"
-#include "qapi/error.h"
/* Interrupt Handlers */
struct omap_intr_handler_bank_s {
@@ -364,28 +363,23 @@ static void omap_inth_reset(DeviceState *dev)
qemu_set_irq(s->parent_intr[1], 0);
}
-static void omap_intc_init(Object *obj)
+static int omap_intc_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- struct omap_intr_handler_s *s = OMAP_INTC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ struct omap_intr_handler_s *s = OMAP_INTC(dev);
+ if (!s->iclk) {
+ error_report("omap-intc: clk not connected");
+ return -1;
+ }
s->nbanks = 1;
sysbus_init_irq(sbd, &s->parent_intr[0]);
sysbus_init_irq(sbd, &s->parent_intr[1]);
qdev_init_gpio_in(dev, omap_set_intr, s->nbanks * 32);
- memory_region_init_io(&s->mmio, obj, &omap_inth_mem_ops, s,
+ memory_region_init_io(&s->mmio, OBJECT(s), &omap_inth_mem_ops, s,
"omap-intc", s->size);
sysbus_init_mmio(sbd, &s->mmio);
-}
-
-static void omap_intc_realize(DeviceState *dev, Error **errp)
-{
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
-
- if (!s->iclk) {
- error_setg(errp, "omap-intc: clk not connected");
- }
+ return 0;
}
static Property omap_intc_properties[] = {
@@ -397,18 +391,18 @@ static Property omap_intc_properties[] = {
static void omap_intc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = omap_intc_init;
dc->reset = omap_inth_reset;
dc->props = omap_intc_properties;
/* Reason: pointer property "clk" */
dc->cannot_instantiate_with_device_add_yet = true;
- dc->realize = omap_intc_realize;
}
static const TypeInfo omap_intc_info = {
.name = "omap-intc",
.parent = TYPE_OMAP_INTC,
- .instance_init = omap_intc_init,
.class_init = omap_intc_class_init,
};
@@ -611,34 +605,28 @@ static const MemoryRegionOps omap2_inth_mem_ops = {
},
};
-static void omap2_intc_init(Object *obj)
+static int omap2_intc_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- struct omap_intr_handler_s *s = OMAP_INTC(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ struct omap_intr_handler_s *s = OMAP_INTC(dev);
+ if (!s->iclk) {
+ error_report("omap2-intc: iclk not connected");
+ return -1;
+ }
+ if (!s->fclk) {
+ error_report("omap2-intc: fclk not connected");
+ return -1;
+ }
s->level_only = 1;
s->nbanks = 3;
sysbus_init_irq(sbd, &s->parent_intr[0]);
sysbus_init_irq(sbd, &s->parent_intr[1]);
qdev_init_gpio_in(dev, omap_set_intr_noedge, s->nbanks * 32);
- memory_region_init_io(&s->mmio, obj, &omap2_inth_mem_ops, s,
+ memory_region_init_io(&s->mmio, OBJECT(s), &omap2_inth_mem_ops, s,
"omap2-intc", 0x1000);
sysbus_init_mmio(sbd, &s->mmio);
-}
-
-static void omap2_intc_realize(DeviceState *dev, Error **errp)
-{
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
-
- if (!s->iclk) {
- error_setg(errp, "omap2-intc: iclk not connected");
- return;
- }
- if (!s->fclk) {
- error_setg(errp, "omap2-intc: fclk not connected");
- return;
- }
+ return 0;
}
static Property omap2_intc_properties[] = {
@@ -652,18 +640,18 @@ static Property omap2_intc_properties[] = {
static void omap2_intc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = omap2_intc_init;
dc->reset = omap_inth_reset;
dc->props = omap2_intc_properties;
/* Reason: pointer property "iclk", "fclk" */
dc->cannot_instantiate_with_device_add_yet = true;
- dc->realize = omap2_intc_realize;
}
static const TypeInfo omap2_intc_info = {
.name = "omap2-intc",
.parent = TYPE_OMAP_INTC,
- .instance_init = omap2_intc_init,
.class_init = omap2_intc_class_init,
};
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index 4349e45e0..2d3769310 100644
--- a/hw/intc/openpic.c
+++ b/hw/intc/openpic.c
@@ -44,7 +44,6 @@
#include "qapi/error.h"
#include "qemu/bitops.h"
#include "qapi/qmp/qerror.h"
-#include "qemu/log.h"
//#define DEBUG_OPENPIC
diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c
index 0518e017c..e47e94f2c 100644
--- a/hw/intc/openpic_kvm.c
+++ b/hw/intc/openpic_kvm.c
@@ -24,8 +24,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu-common.h"
-#include "cpu.h"
#include <sys/ioctl.h>
#include "exec/address-spaces.h"
#include "hw/hw.h"
diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c
index 55ea15de7..5ecbc4a48 100644
--- a/hw/intc/pl190.c
+++ b/hw/intc/pl190.c
@@ -9,7 +9,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
-#include "qemu/log.h"
/* The number of virtual priority levels. 16 user vectors plus the
unvectored IRQ. Chained interrupts would require an additional level
@@ -237,17 +236,17 @@ static void pl190_reset(DeviceState *d)
pl190_update_vectors(s);
}
-static void pl190_init(Object *obj)
+static int pl190_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- PL190State *s = PL190(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ PL190State *s = PL190(dev);
- memory_region_init_io(&s->iomem, obj, &pl190_ops, s, "pl190", 0x1000);
+ memory_region_init_io(&s->iomem, OBJECT(s), &pl190_ops, s, "pl190", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
qdev_init_gpio_in(dev, pl190_set_irq, 32);
sysbus_init_irq(sbd, &s->irq);
sysbus_init_irq(sbd, &s->fiq);
+ return 0;
}
static const VMStateDescription vmstate_pl190 = {
@@ -272,7 +271,9 @@ static const VMStateDescription vmstate_pl190 = {
static void pl190_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = pl190_init;
dc->reset = pl190_reset;
dc->vmsd = &vmstate_pl190;
}
@@ -281,7 +282,6 @@ static const TypeInfo pl190_info = {
.name = TYPE_PL190,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PL190State),
- .instance_init = pl190_init,
.class_init = pl190_class_init,
};
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index 6ab29efc6..bc75fa7d9 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -67,13 +67,6 @@ static void qemu_s390_release_adapter_routes(S390FLICState *fs,
{
}
-static int qemu_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
- uint16_t subchannel_nr)
-{
- /* Fixme TCG */
- return -ENOSYS;
-}
-
static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
{
S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
@@ -82,7 +75,6 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
fsc->io_adapter_map = qemu_s390_io_adapter_map;
fsc->add_adapter_routes = qemu_s390_add_adapter_routes;
fsc->release_adapter_routes = qemu_s390_release_adapter_routes;
- fsc->clear_io_irq = qemu_s390_clear_io_flic;
}
static const TypeInfo qemu_s390_flic_info = {
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index fef808011..02449b390 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -11,8 +11,6 @@
*/
#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "cpu.h"
#include <sys/ioctl.h>
#include "qemu/error-report.h"
#include "hw/sysbus.h"
@@ -30,7 +28,6 @@ typedef struct KVMS390FLICState {
S390FLICState parent_obj;
uint32_t fd;
- bool clear_io_supported;
} KVMS390FLICState;
DeviceState *s390_flic_kvm_create(void)
@@ -131,24 +128,6 @@ int kvm_s390_inject_flic(struct kvm_s390_irq *irq)
return flic_enqueue_irqs(irq, sizeof(*irq), flic);
}
-static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
- uint16_t subchannel_nr)
-{
- KVMS390FLICState *flic = KVM_S390_FLIC(fs);
- int rc;
- uint32_t sid = subchannel_id << 16 | subchannel_nr;
- struct kvm_device_attr attr = {
- .group = KVM_DEV_FLIC_CLEAR_IO_IRQ,
- .addr = (uint64_t) &sid,
- .attr = sizeof(sid),
- };
- if (unlikely(!flic->clear_io_supported)) {
- return -ENOSYS;
- }
- rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
- return rc ? -errno : 0;
-}
-
/**
* __get_all_irqs - store all pending irqs in buffer
* @flic: pointer to flic device state
@@ -195,7 +174,7 @@ static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
.swap = swap,
};
KVMS390FLICState *flic = KVM_S390_FLIC(fs);
- int r;
+ int r, ret;
struct kvm_device_attr attr = {
.group = KVM_DEV_FLIC_ADAPTER_REGISTER,
.addr = (uint64_t)&adapter,
@@ -208,7 +187,8 @@ static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
- return r ? -errno : 0;
+ ret = r ? -errno : 0;
+ return ret;
}
static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
@@ -376,7 +356,6 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
{
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
struct kvm_create_device cd = {0};
- struct kvm_device_attr test_attr = {0};
int ret;
flic_state->fd = -1;
@@ -393,11 +372,6 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
}
flic_state->fd = cd.fd;
- /* Check clear_io_irq support */
- test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ;
- flic_state->clear_io_supported = !ioctl(flic_state->fd,
- KVM_HAS_DEVICE_ATTR, test_attr);
-
/* Register savevm handler for floating interrupts */
register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
kvm_flic_load, (void *) flic_state);
@@ -444,7 +418,6 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
fsc->io_adapter_map = kvm_s390_io_adapter_map;
fsc->add_adapter_routes = kvm_s390_add_adapter_routes;
fsc->release_adapter_routes = kvm_s390_release_adapter_routes;
- fsc->clear_io_irq = kvm_s390_clear_io_flic;
}
static const TypeInfo kvm_s390_flic_info = {
diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c
index e82e89362..c9486ed99 100644
--- a/hw/intc/slavio_intctl.c
+++ b/hw/intc/slavio_intctl.c
@@ -418,16 +418,15 @@ static void slavio_intctl_reset(DeviceState *d)
slavio_check_interrupts(s, 0);
}
-static void slavio_intctl_init(Object *obj)
+static int slavio_intctl_init1(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ SLAVIO_INTCTLState *s = SLAVIO_INTCTL(dev);
unsigned int i, j;
char slave_name[45];
qdev_init_gpio_in(dev, slavio_set_irq_all, 32 + MAX_CPUS);
- memory_region_init_io(&s->iomem, obj, &slavio_intctlm_mem_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &slavio_intctlm_mem_ops, s,
"master-interrupt-controller", INTCTLM_SIZE);
sysbus_init_mmio(sbd, &s->iomem);
@@ -444,12 +443,16 @@ static void slavio_intctl_init(Object *obj)
s->slaves[i].cpu = i;
s->slaves[i].master = s;
}
+
+ return 0;
}
static void slavio_intctl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = slavio_intctl_init1;
dc->reset = slavio_intctl_reset;
dc->vmsd = &vmstate_intctl;
}
@@ -458,7 +461,6 @@ static const TypeInfo slavio_intctl_info = {
.name = TYPE_SLAVIO_INTCTL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SLAVIO_INTCTLState),
- .instance_init = slavio_intctl_init,
.class_init = slavio_intctl_class_init,
};
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
deleted file mode 100644
index f12192c08..000000000
--- a/hw/intc/trace-events
+++ /dev/null
@@ -1,123 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/intc/apic_common.c
-cpu_set_apic_base(uint64_t val) "%016"PRIx64
-cpu_get_apic_base(uint64_t val) "%016"PRIx64
-# coalescing
-apic_report_irq_delivered(int apic_irq_delivered) "coalescing %d"
-apic_reset_irq_delivered(int apic_irq_delivered) "old coalescing %d"
-apic_get_irq_delivered(int apic_irq_delivered) "returning coalescing %d"
-
-# hw/intc/apic.c
-apic_local_deliver(int vector, uint32_t lvt) "vector %d delivery mode %d"
-apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) "dest %d dest_mode %d delivery_mode %d vector %d trigger_mode %d"
-apic_mem_readl(uint64_t addr, uint32_t val) "%"PRIx64" = %08x"
-apic_mem_writel(uint64_t addr, uint32_t val) "%"PRIx64" = %08x"
-
-# hw/intc/slavio_intctl.c
-slavio_intctl_mem_readl(uint32_t cpu, uint64_t addr, uint32_t ret) "read cpu %d reg 0x%"PRIx64" = %x"
-slavio_intctl_mem_writel(uint32_t cpu, uint64_t addr, uint32_t val) "write cpu %d reg 0x%"PRIx64" = %x"
-slavio_intctl_mem_writel_clear(uint32_t cpu, uint32_t val, uint32_t intreg_pending) "Cleared cpu %d irq mask %x, curmask %x"
-slavio_intctl_mem_writel_set(uint32_t cpu, uint32_t val, uint32_t intreg_pending) "Set cpu %d irq mask %x, curmask %x"
-slavio_intctlm_mem_readl(uint64_t addr, uint32_t ret) "read system reg 0x%"PRIx64" = %x"
-slavio_intctlm_mem_writel(uint64_t addr, uint32_t val) "write system reg 0x%"PRIx64" = %x"
-slavio_intctlm_mem_writel_enable(uint32_t val, uint32_t intregm_disabled) "Enabled master irq mask %x, curmask %x"
-slavio_intctlm_mem_writel_disable(uint32_t val, uint32_t intregm_disabled) "Disabled master irq mask %x, curmask %x"
-slavio_intctlm_mem_writel_target(uint32_t cpu) "Set master irq cpu %d"
-slavio_check_interrupts(uint32_t pending, uint32_t intregm_disabled) "pending %x disabled %x"
-slavio_set_irq(uint32_t target_cpu, int irq, uint32_t pil, int level) "Set cpu %d irq %d -> pil %d level %d"
-slavio_set_timer_irq_cpu(int cpu, int level) "Set cpu %d local timer level %d"
-
-# hw/intc/grlib_irqmp.c
-grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x"
-grlib_irqmp_ack(int intno) "interrupt:%d"
-grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d"
-grlib_irqmp_readl_unknown(uint64_t addr) "addr 0x%"PRIx64
-grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x"
-
-# hw/intc/lm32_pic.c
-lm32_pic_raise_irq(void) "Raise CPU interrupt"
-lm32_pic_lower_irq(void) "Lower CPU interrupt"
-lm32_pic_interrupt(int irq, int level) "Set IRQ%d %d"
-lm32_pic_set_im(uint32_t im) "im 0x%08x"
-lm32_pic_set_ip(uint32_t ip) "ip 0x%08x"
-lm32_pic_get_im(uint32_t im) "im 0x%08x"
-lm32_pic_get_ip(uint32_t ip) "ip 0x%08x"
-
-# hw/intc/xics.c
-xics_icp_check_ipi(int server, uint8_t mfrr) "CPU %d can take IPI mfrr=%#x"
-xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx32"->%#"PRIx32
-xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
-xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
-xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
-xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
-xics_masked_pending(void) "set_irq_msi: masked pending"
-xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
-xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
-xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
-xics_ics_eoi(int nr) "ics_eoi: irq %#x"
-xics_alloc(int src, int irq) "source#%d, irq %d"
-xics_alloc_block(int src, int first, int num, bool lsi, int align) "source#%d, first irq %d, %d irqs, lsi=%d, alignnum %d"
-xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
-xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free"
-
-# hw/intc/s390_flic_kvm.c
-flic_create_device(int err) "flic: create device failed %d"
-flic_no_device_api(int err) "flic: no Device Contral API support %d"
-flic_reset_failed(int err) "flic: reset failed %d"
-
-# hw/intc/aspeed_vic.c
-aspeed_vic_set_irq(int irq, int level) "Enabling IRQ %d: %d"
-aspeed_vic_update_fiq(int flags) "Raising FIQ: %d"
-aspeed_vic_update_irq(int flags) "Raising IRQ: %d"
-aspeed_vic_read(uint64_t offset, unsigned size, uint32_t value) "From 0x%" PRIx64 " of size %u: 0x%" PRIx32
-aspeed_vic_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
-
-# hw/intc/arm_gic.c
-gic_enable_irq(int irq) "irq %d enabled"
-gic_disable_irq(int irq) "irq %d disabled"
-gic_set_irq(int irq, int level, int cpumask, int target) "irq %d level %d cpumask 0x%x target 0x%x"
-gic_update_bestirq(int cpu, int irq, int prio, int priority_mask, int running_priority) "cpu %d irq %d priority %d cpu priority mask %d cpu running priority %d"
-gic_update_set_irq(int cpu, const char *name, int level) "cpu[%d]: %s = %d"
-gic_acknowledge_irq(int cpu, int irq) "cpu %d acknowledged irq %d"
-
-# hw/intc/arm_gicv3_cpuif.c
-gicv3_icc_pmr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_PMR read cpu %x value 0x%" PRIx64
-gicv3_icc_pmr_write(uint32_t cpu, uint64_t val) "GICv3 ICC_PMR write cpu %x value 0x%" PRIx64
-gicv3_icc_bpr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_BPR read cpu %x value 0x%" PRIx64
-gicv3_icc_bpr_write(uint32_t cpu, uint64_t val) "GICv3 ICC_BPR write cpu %x value 0x%" PRIx64
-gicv3_icc_ap_read(int regno, uint32_t cpu, uint64_t val) "GICv3 ICC_AP%dR read cpu %x value 0x%" PRIx64
-gicv3_icc_ap_write(int regno, uint32_t cpu, uint64_t val) "GICv3 ICC_AP%dR write cpu %x value 0x%" PRIx64
-gicv3_icc_igrpen_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN read cpu %x value 0x%" PRIx64
-gicv3_icc_igrpen_write(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN write cpu %x value 0x%" PRIx64
-gicv3_icc_igrpen1_el3_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN1_EL3 read cpu %x value 0x%" PRIx64
-gicv3_icc_igrpen1_el3_write(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN1_EL3 write cpu %x value 0x%" PRIx64
-gicv3_icc_ctlr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR read cpu %x value 0x%" PRIx64
-gicv3_icc_ctlr_write(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR write cpu %x value 0x%" PRIx64
-gicv3_icc_ctlr_el3_read(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR_EL3 read cpu %x value 0x%" PRIx64
-gicv3_icc_ctlr_el3_write(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR_EL3 write cpu %x value 0x%" PRIx64
-gicv3_cpuif_update(uint32_t cpuid, int irq, int grp, int prio) "GICv3 CPU i/f %x HPPI update: irq %d group %d prio %d"
-gicv3_cpuif_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel) "GICv3 CPU i/f %x HPPI update: setting FIQ %d IRQ %d"
-gicv3_icc_generate_sgi(uint32_t cpuid, int irq, int irm, uint32_t aff, uint32_t targetlist) "GICv3 CPU i/f %x generating SGI %d IRM %d target affinity 0x%xxx targetlist 0x%x"
-gicv3_icc_iar0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR0 read cpu %x value 0x%" PRIx64
-gicv3_icc_iar1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR1 read cpu %x value 0x%" PRIx64
-gicv3_icc_eoir_write(uint32_t cpu, uint64_t val) "GICv3 ICC_EOIR write cpu %x value 0x%" PRIx64
-gicv3_icc_hppir0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR0 read cpu %x value 0x%" PRIx64
-gicv3_icc_hppir1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR1 read cpu %x value 0x%" PRIx64
-gicv3_icc_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICC_DIR write cpu %x value 0x%" PRIx64
-gicv3_icc_rpr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_RPR read cpu %x value 0x%" PRIx64
-
-# hw/intc/arm_gicv3_dist.c
-gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
-gicv3_dist_badread(uint64_t offset, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " size %u secure %d: error"
-gicv3_dist_write(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
-gicv3_dist_badwrite(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error"
-gicv3_dist_set_irq(int irq, int level) "GICv3 distributor interrupt %d level changed to %d"
-
-# hw/intc/arm_gicv3_redist.c
-gicv3_redist_read(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
-gicv3_redist_badread(uint32_t cpu, uint64_t offset, unsigned size, bool secure) "GICv3 redistributor %x read: offset 0x%" PRIx64 " size %u secure %d: error"
-gicv3_redist_write(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
-gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error"
-gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor %x interrupt %d level changed to %d"
-gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor %x pending SGI %d"
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index cd48f4204..8659be017 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -32,11 +32,12 @@
#include "hw/hw.h"
#include "trace.h"
#include "qemu/timer.h"
+#include "hw/ppc/spapr.h"
#include "hw/ppc/xics.h"
#include "qemu/error-report.h"
#include "qapi/visitor.h"
-int xics_get_cpu_index_by_dt_id(int cpu_dt_id)
+static int get_cpu_index_by_dt_id(int cpu_dt_id)
{
PowerPCCPU *cpu = ppc_get_vcpu_by_dt_id(cpu_dt_id);
@@ -47,31 +48,17 @@ int xics_get_cpu_index_by_dt_id(int cpu_dt_id)
return -1;
}
-void xics_cpu_destroy(XICSState *xics, PowerPCCPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- ICPState *ss = &xics->ss[cs->cpu_index];
-
- assert(cs->cpu_index < xics->nr_servers);
- assert(cs == ss->cs);
-
- ss->output = NULL;
- ss->cs = NULL;
-}
-
-void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
+void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- ICPState *ss = &xics->ss[cs->cpu_index];
- XICSStateClass *info = XICS_COMMON_GET_CLASS(xics);
+ ICPState *ss = &icp->ss[cs->cpu_index];
+ XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
- assert(cs->cpu_index < xics->nr_servers);
-
- ss->cs = cs;
+ assert(cs->cpu_index < icp->nr_servers);
if (info->cpu_setup) {
- info->cpu_setup(xics, cpu);
+ info->cpu_setup(icp, cpu);
}
switch (PPC_INPUT(env)) {
@@ -95,21 +82,21 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
*/
static void xics_common_reset(DeviceState *d)
{
- XICSState *xics = XICS_COMMON(d);
+ XICSState *icp = XICS_COMMON(d);
int i;
- for (i = 0; i < xics->nr_servers; i++) {
- device_reset(DEVICE(&xics->ss[i]));
+ for (i = 0; i < icp->nr_servers; i++) {
+ device_reset(DEVICE(&icp->ss[i]));
}
- device_reset(DEVICE(xics->ics));
+ device_reset(DEVICE(icp->ics));
}
static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
- XICSState *xics = XICS_COMMON(obj);
- int64_t value = xics->nr_irqs;
+ XICSState *icp = XICS_COMMON(obj);
+ int64_t value = icp->nr_irqs;
visit_type_int(v, name, &value, errp);
}
@@ -117,8 +104,8 @@ static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
- XICSState *xics = XICS_COMMON(obj);
- XICSStateClass *info = XICS_COMMON_GET_CLASS(xics);
+ XICSState *icp = XICS_COMMON(obj);
+ XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
Error *error = NULL;
int64_t value;
@@ -127,23 +114,23 @@ static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name,
error_propagate(errp, error);
return;
}
- if (xics->nr_irqs) {
+ if (icp->nr_irqs) {
error_setg(errp, "Number of interrupts is already set to %u",
- xics->nr_irqs);
+ icp->nr_irqs);
return;
}
assert(info->set_nr_irqs);
- assert(xics->ics);
- info->set_nr_irqs(xics, value, errp);
+ assert(icp->ics);
+ info->set_nr_irqs(icp, value, errp);
}
static void xics_prop_get_nr_servers(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
- XICSState *xics = XICS_COMMON(obj);
- int64_t value = xics->nr_servers;
+ XICSState *icp = XICS_COMMON(obj);
+ int64_t value = icp->nr_servers;
visit_type_int(v, name, &value, errp);
}
@@ -152,8 +139,8 @@ static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
- XICSState *xics = XICS_COMMON(obj);
- XICSStateClass *info = XICS_COMMON_GET_CLASS(xics);
+ XICSState *icp = XICS_COMMON(obj);
+ XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
Error *error = NULL;
int64_t value;
@@ -162,14 +149,14 @@ static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
error_propagate(errp, error);
return;
}
- if (xics->nr_servers) {
+ if (icp->nr_servers) {
error_setg(errp, "Number of servers is already set to %u",
- xics->nr_servers);
+ icp->nr_servers);
return;
}
assert(info->set_nr_servers);
- info->set_nr_servers(xics, value, errp);
+ info->set_nr_servers(icp, value, errp);
}
static void xics_common_initfn(Object *obj)
@@ -212,9 +199,9 @@ static void ics_reject(ICSState *ics, int nr);
static void ics_resend(ICSState *ics);
static void ics_eoi(ICSState *ics, int nr);
-static void icp_check_ipi(XICSState *xics, int server)
+static void icp_check_ipi(XICSState *icp, int server)
{
- ICPState *ss = xics->ss + server;
+ ICPState *ss = icp->ss + server;
if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
return;
@@ -223,7 +210,7 @@ static void icp_check_ipi(XICSState *xics, int server)
trace_xics_icp_check_ipi(server, ss->mfrr);
if (XISR(ss)) {
- ics_reject(xics->ics, XISR(ss));
+ ics_reject(icp->ics, XISR(ss));
}
ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
@@ -231,19 +218,19 @@ static void icp_check_ipi(XICSState *xics, int server)
qemu_irq_raise(ss->output);
}
-static void icp_resend(XICSState *xics, int server)
+static void icp_resend(XICSState *icp, int server)
{
- ICPState *ss = xics->ss + server;
+ ICPState *ss = icp->ss + server;
if (ss->mfrr < CPPR(ss)) {
- icp_check_ipi(xics, server);
+ icp_check_ipi(icp, server);
}
- ics_resend(xics->ics);
+ ics_resend(icp->ics);
}
-void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
+static void icp_set_cppr(XICSState *icp, int server, uint8_t cppr)
{
- ICPState *ss = xics->ss + server;
+ ICPState *ss = icp->ss + server;
uint8_t old_cppr;
uint32_t old_xisr;
@@ -256,26 +243,26 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
ss->xirr &= ~XISR_MASK; /* Clear XISR */
ss->pending_priority = 0xff;
qemu_irq_lower(ss->output);
- ics_reject(xics->ics, old_xisr);
+ ics_reject(icp->ics, old_xisr);
}
} else {
if (!XISR(ss)) {
- icp_resend(xics, server);
+ icp_resend(icp, server);
}
}
}
-void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
+static void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr)
{
- ICPState *ss = xics->ss + server;
+ ICPState *ss = icp->ss + server;
ss->mfrr = mfrr;
if (mfrr < CPPR(ss)) {
- icp_check_ipi(xics, server);
+ icp_check_ipi(icp, server);
}
}
-uint32_t icp_accept(ICPState *ss)
+static uint32_t icp_accept(ICPState *ss)
{
uint32_t xirr = ss->xirr;
@@ -288,39 +275,31 @@ uint32_t icp_accept(ICPState *ss)
return xirr;
}
-uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
-{
- if (mfrr) {
- *mfrr = ss->mfrr;
- }
- return ss->xirr;
-}
-
-void icp_eoi(XICSState *xics, int server, uint32_t xirr)
+static void icp_eoi(XICSState *icp, int server, uint32_t xirr)
{
- ICPState *ss = xics->ss + server;
+ ICPState *ss = icp->ss + server;
/* Send EOI -> ICS */
ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
trace_xics_icp_eoi(server, xirr, ss->xirr);
- ics_eoi(xics->ics, xirr & XISR_MASK);
+ ics_eoi(icp->ics, xirr & XISR_MASK);
if (!XISR(ss)) {
- icp_resend(xics, server);
+ icp_resend(icp, server);
}
}
-static void icp_irq(XICSState *xics, int server, int nr, uint8_t priority)
+static void icp_irq(XICSState *icp, int server, int nr, uint8_t priority)
{
- ICPState *ss = xics->ss + server;
+ ICPState *ss = icp->ss + server;
trace_xics_icp_irq(server, nr, priority);
if ((priority >= CPPR(ss))
|| (XISR(ss) && (ss->pending_priority <= priority))) {
- ics_reject(xics->ics, nr);
+ ics_reject(icp->ics, nr);
} else {
if (XISR(ss)) {
- ics_reject(xics->ics, XISR(ss));
+ ics_reject(icp->ics, XISR(ss));
}
ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
ss->pending_priority = priority;
@@ -397,6 +376,12 @@ static const TypeInfo icp_info = {
/*
* ICS: Source layer
*/
+static int ics_valid_irq(ICSState *ics, uint32_t nr)
+{
+ return (nr >= ics->offset)
+ && (nr < (ics->offset + ics->nr_irqs));
+}
+
static void resend_msi(ICSState *ics, int srcno)
{
ICSIRQState *irq = ics->irqs + srcno;
@@ -405,7 +390,7 @@ static void resend_msi(ICSState *ics, int srcno)
if (irq->status & XICS_STATUS_REJECTED) {
irq->status &= ~XICS_STATUS_REJECTED;
if (irq->priority != 0xff) {
- icp_irq(ics->xics, irq->server, srcno + ics->offset,
+ icp_irq(ics->icp, irq->server, srcno + ics->offset,
irq->priority);
}
}
@@ -419,7 +404,7 @@ static void resend_lsi(ICSState *ics, int srcno)
&& (irq->status & XICS_STATUS_ASSERTED)
&& !(irq->status & XICS_STATUS_SENT)) {
irq->status |= XICS_STATUS_SENT;
- icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
+ icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
}
}
@@ -434,7 +419,7 @@ static void set_irq_msi(ICSState *ics, int srcno, int val)
irq->status |= XICS_STATUS_MASKED_PENDING;
trace_xics_masked_pending();
} else {
- icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
+ icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
}
}
}
@@ -473,7 +458,7 @@ static void write_xive_msi(ICSState *ics, int srcno)
}
irq->status &= ~XICS_STATUS_MASKED_PENDING;
- icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
+ icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
}
static void write_xive_lsi(ICSState *ics, int srcno)
@@ -481,8 +466,8 @@ static void write_xive_lsi(ICSState *ics, int srcno)
resend_lsi(ics, srcno);
}
-void ics_write_xive(ICSState *ics, int nr, int server,
- uint8_t priority, uint8_t saved_priority)
+static void ics_write_xive(ICSState *ics, int nr, int server,
+ uint8_t priority, uint8_t saved_priority)
{
int srcno = nr - ics->offset;
ICSIRQState *irq = ics->irqs + srcno;
@@ -558,8 +543,8 @@ static int ics_post_load(ICSState *ics, int version_id)
{
int i;
- for (i = 0; i < ics->xics->nr_servers; i++) {
- icp_resend(ics->xics, i);
+ for (i = 0; i < ics->icp->nr_servers; i++) {
+ icp_resend(ics->icp, i);
}
return 0;
@@ -659,14 +644,14 @@ static const TypeInfo ics_info = {
/*
* Exported functions
*/
-int xics_find_source(XICSState *xics, int irq)
+static int xics_find_source(XICSState *icp, int irq)
{
int sources = 1;
int src;
/* FIXME: implement multiple sources */
for (src = 0; src < sources; ++src) {
- ICSState *ics = &xics->ics[src];
+ ICSState *ics = &icp->ics[src];
if (ics_valid_irq(ics, irq)) {
return src;
}
@@ -675,19 +660,19 @@ int xics_find_source(XICSState *xics, int irq)
return -1;
}
-qemu_irq xics_get_qirq(XICSState *xics, int irq)
+qemu_irq xics_get_qirq(XICSState *icp, int irq)
{
- int src = xics_find_source(xics, irq);
+ int src = xics_find_source(icp, irq);
if (src >= 0) {
- ICSState *ics = &xics->ics[src];
+ ICSState *ics = &icp->ics[src];
return ics->qirqs[irq - ics->offset];
}
return NULL;
}
-void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
+static void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
{
assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK));
@@ -695,9 +680,412 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
}
+void xics_set_irq_type(XICSState *icp, int irq, bool lsi)
+{
+ int src = xics_find_source(icp, irq);
+ ICSState *ics;
+
+ assert(src >= 0);
+
+ ics = &icp->ics[src];
+ ics_set_irq_type(ics, irq - ics->offset, lsi);
+}
+
+#define ICS_IRQ_FREE(ics, srcno) \
+ (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK)))
+
+static int ics_find_free_block(ICSState *ics, int num, int alignnum)
+{
+ int first, i;
+
+ for (first = 0; first < ics->nr_irqs; first += alignnum) {
+ if (num > (ics->nr_irqs - first)) {
+ return -1;
+ }
+ for (i = first; i < first + num; ++i) {
+ if (!ICS_IRQ_FREE(ics, i)) {
+ break;
+ }
+ }
+ if (i == (first + num)) {
+ return first;
+ }
+ }
+
+ return -1;
+}
+
+int xics_alloc(XICSState *icp, int src, int irq_hint, bool lsi, Error **errp)
+{
+ ICSState *ics = &icp->ics[src];
+ int irq;
+
+ if (irq_hint) {
+ assert(src == xics_find_source(icp, irq_hint));
+ if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
+ error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
+ return -1;
+ }
+ irq = irq_hint;
+ } else {
+ irq = ics_find_free_block(ics, 1, 1);
+ if (irq < 0) {
+ error_setg(errp, "can't allocate IRQ: no IRQ left");
+ return -1;
+ }
+ irq += ics->offset;
+ }
+
+ ics_set_irq_type(ics, irq - ics->offset, lsi);
+ trace_xics_alloc(src, irq);
+
+ return irq;
+}
+
+/*
+ * Allocate block of consecutive IRQs, and return the number of the first IRQ in the block.
+ * If align==true, aligns the first IRQ number to num.
+ */
+int xics_alloc_block(XICSState *icp, int src, int num, bool lsi, bool align,
+ Error **errp)
+{
+ int i, first = -1;
+ ICSState *ics = &icp->ics[src];
+
+ assert(src == 0);
+ /*
+ * MSIMesage::data is used for storing VIRQ so
+ * it has to be aligned to num to support multiple
+ * MSI vectors. MSI-X is not affected by this.
+ * The hint is used for the first IRQ, the rest should
+ * be allocated continuously.
+ */
+ if (align) {
+ assert((num == 1) || (num == 2) || (num == 4) ||
+ (num == 8) || (num == 16) || (num == 32));
+ first = ics_find_free_block(ics, num, num);
+ } else {
+ first = ics_find_free_block(ics, num, 1);
+ }
+ if (first < 0) {
+ error_setg(errp, "can't find a free %d-IRQ block", num);
+ return -1;
+ }
+
+ if (first >= 0) {
+ for (i = first; i < first + num; ++i) {
+ ics_set_irq_type(ics, i, lsi);
+ }
+ }
+ first += ics->offset;
+
+ trace_xics_alloc_block(src, first, num, lsi, align);
+
+ return first;
+}
+
+static void ics_free(ICSState *ics, int srcno, int num)
+{
+ int i;
+
+ for (i = srcno; i < srcno + num; ++i) {
+ if (ICS_IRQ_FREE(ics, i)) {
+ trace_xics_ics_free_warn(ics - ics->icp->ics, i + ics->offset);
+ }
+ memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
+ }
+}
+
+void xics_free(XICSState *icp, int irq, int num)
+{
+ int src = xics_find_source(icp, irq);
+
+ if (src >= 0) {
+ ICSState *ics = &icp->ics[src];
+
+ /* FIXME: implement multiple sources */
+ assert(src == 0);
+
+ trace_xics_ics_free(ics - icp->ics, irq, num);
+ ics_free(ics, irq - ics->offset, num);
+ }
+}
+
+/*
+ * Guest interfaces
+ */
+
+static target_ulong h_cppr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ CPUState *cs = CPU(cpu);
+ target_ulong cppr = args[0];
+
+ icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
+ return H_SUCCESS;
+}
+
+static target_ulong h_ipi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ target_ulong server = get_cpu_index_by_dt_id(args[0]);
+ target_ulong mfrr = args[1];
+
+ if (server >= spapr->icp->nr_servers) {
+ return H_PARAMETER;
+ }
+
+ icp_set_mfrr(spapr->icp, server, mfrr);
+ return H_SUCCESS;
+}
+
+static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ CPUState *cs = CPU(cpu);
+ uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
+
+ args[0] = xirr;
+ return H_SUCCESS;
+}
+
+static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ CPUState *cs = CPU(cpu);
+ ICPState *ss = &spapr->icp->ss[cs->cpu_index];
+ uint32_t xirr = icp_accept(ss);
+
+ args[0] = xirr;
+ args[1] = cpu_get_host_ticks();
+ return H_SUCCESS;
+}
+
+static target_ulong h_eoi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ CPUState *cs = CPU(cpu);
+ target_ulong xirr = args[0];
+
+ icp_eoi(spapr->icp, cs->cpu_index, xirr);
+ return H_SUCCESS;
+}
+
+static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ CPUState *cs = CPU(cpu);
+ ICPState *ss = &spapr->icp->ss[cs->cpu_index];
+
+ args[0] = ss->xirr;
+ args[1] = ss->mfrr;
+
+ return H_SUCCESS;
+}
+
+static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ uint32_t token,
+ uint32_t nargs, target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ ICSState *ics = spapr->icp->ics;
+ uint32_t nr, server, priority;
+
+ if ((nargs != 3) || (nret != 1)) {
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ nr = rtas_ld(args, 0);
+ server = get_cpu_index_by_dt_id(rtas_ld(args, 1));
+ priority = rtas_ld(args, 2);
+
+ if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
+ || (priority > 0xff)) {
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ ics_write_xive(ics, nr, server, priority, priority);
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+}
+
+static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ uint32_t token,
+ uint32_t nargs, target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ ICSState *ics = spapr->icp->ics;
+ uint32_t nr;
+
+ if ((nargs != 1) || (nret != 3)) {
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ nr = rtas_ld(args, 0);
+
+ if (!ics_valid_irq(ics, nr)) {
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+ rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
+ rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
+}
+
+static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ uint32_t token,
+ uint32_t nargs, target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ ICSState *ics = spapr->icp->ics;
+ uint32_t nr;
+
+ if ((nargs != 1) || (nret != 1)) {
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ nr = rtas_ld(args, 0);
+
+ if (!ics_valid_irq(ics, nr)) {
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
+ ics->irqs[nr - ics->offset].priority);
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+}
+
+static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+ uint32_t token,
+ uint32_t nargs, target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ ICSState *ics = spapr->icp->ics;
+ uint32_t nr;
+
+ if ((nargs != 1) || (nret != 1)) {
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ nr = rtas_ld(args, 0);
+
+ if (!ics_valid_irq(ics, nr)) {
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
+ ics->irqs[nr - ics->offset].saved_priority,
+ ics->irqs[nr - ics->offset].saved_priority);
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+}
+
+/*
+ * XICS
+ */
+
+static void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp)
+{
+ icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
+}
+
+static void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers,
+ Error **errp)
+{
+ int i;
+
+ icp->nr_servers = nr_servers;
+
+ icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
+ for (i = 0; i < icp->nr_servers; i++) {
+ char buffer[32];
+ object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_ICP);
+ snprintf(buffer, sizeof(buffer), "icp[%d]", i);
+ object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
+ errp);
+ }
+}
+
+static void xics_realize(DeviceState *dev, Error **errp)
+{
+ XICSState *icp = XICS(dev);
+ Error *error = NULL;
+ int i;
+
+ if (!icp->nr_servers) {
+ error_setg(errp, "Number of servers needs to be greater 0");
+ return;
+ }
+
+ /* Registration of global state belongs into realize */
+ spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive);
+ spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive);
+ spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_int_off);
+ spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_int_on);
+
+ spapr_register_hypercall(H_CPPR, h_cppr);
+ spapr_register_hypercall(H_IPI, h_ipi);
+ spapr_register_hypercall(H_XIRR, h_xirr);
+ spapr_register_hypercall(H_XIRR_X, h_xirr_x);
+ spapr_register_hypercall(H_EOI, h_eoi);
+ spapr_register_hypercall(H_IPOLL, h_ipoll);
+
+ object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
+ if (error) {
+ error_propagate(errp, error);
+ return;
+ }
+
+ for (i = 0; i < icp->nr_servers; i++) {
+ object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized", &error);
+ if (error) {
+ error_propagate(errp, error);
+ return;
+ }
+ }
+}
+
+static void xics_initfn(Object *obj)
+{
+ XICSState *xics = XICS(obj);
+
+ xics->ics = ICS(object_new(TYPE_ICS));
+ object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
+ xics->ics->icp = xics;
+}
+
+static void xics_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ XICSStateClass *xsc = XICS_CLASS(oc);
+
+ dc->realize = xics_realize;
+ xsc->set_nr_irqs = xics_set_nr_irqs;
+ xsc->set_nr_servers = xics_set_nr_servers;
+}
+
+static const TypeInfo xics_info = {
+ .name = TYPE_XICS,
+ .parent = TYPE_XICS_COMMON,
+ .instance_size = sizeof(XICSState),
+ .class_size = sizeof(XICSStateClass),
+ .class_init = xics_class_init,
+ .instance_init = xics_initfn,
+};
+
static void xics_register_types(void)
{
type_register_static(&xics_common_info);
+ type_register_static(&xics_info);
type_register_static(&ics_info);
type_register_static(&icp_info);
}
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index edbd62fd1..9029d9ee0 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -31,7 +31,6 @@
#include "cpu.h"
#include "hw/hw.h"
#include "trace.h"
-#include "sysemu/kvm.h"
#include "hw/ppc/spapr.h"
#include "hw/ppc/xics.h"
#include "kvm_ppc.h"
@@ -114,10 +113,8 @@ static void icp_kvm_reset(DeviceState *dev)
icp->pending_priority = 0xff;
icp->mfrr = 0xff;
- /* Make all outputs as deasserted only if the CPU thread is in use */
- if (icp->output) {
- qemu_set_irq(icp->output, 0);
- }
+ /* Make all outputs are deasserted */
+ qemu_set_irq(icp->output, 0);
icp_set_kvm_state(icp, 1);
}
@@ -145,7 +142,7 @@ static const TypeInfo icp_kvm_info = {
*/
static void ics_get_kvm_state(ICSState *ics)
{
- KVMXICSState *xicskvm = XICS_SPAPR_KVM(ics->xics);
+ KVMXICSState *icpkvm = KVM_XICS(ics->icp);
uint64_t state;
struct kvm_device_attr attr = {
.flags = 0,
@@ -160,7 +157,7 @@ static void ics_get_kvm_state(ICSState *ics)
attr.attr = i + ics->offset;
- ret = ioctl(xicskvm->kernel_xics_fd, KVM_GET_DEVICE_ATTR, &attr);
+ ret = ioctl(icpkvm->kernel_xics_fd, KVM_GET_DEVICE_ATTR, &attr);
if (ret != 0) {
error_report("Unable to retrieve KVM interrupt controller state"
" for IRQ %d: %s", i + ics->offset, strerror(errno));
@@ -204,7 +201,7 @@ static void ics_get_kvm_state(ICSState *ics)
static int ics_set_kvm_state(ICSState *ics, int version_id)
{
- KVMXICSState *xicskvm = XICS_SPAPR_KVM(ics->xics);
+ KVMXICSState *icpkvm = KVM_XICS(ics->icp);
uint64_t state;
struct kvm_device_attr attr = {
.flags = 0,
@@ -238,7 +235,7 @@ static int ics_set_kvm_state(ICSState *ics, int version_id)
}
}
- ret = ioctl(xicskvm->kernel_xics_fd, KVM_SET_DEVICE_ATTR, &attr);
+ ret = ioctl(icpkvm->kernel_xics_fd, KVM_SET_DEVICE_ATTR, &attr);
if (ret != 0) {
error_report("Unable to restore KVM interrupt controller state"
" for IRQs %d: %s", i + ics->offset, strerror(errno));
@@ -324,17 +321,17 @@ static const TypeInfo ics_kvm_info = {
/*
* XICS-KVM
*/
-static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
+static void xics_kvm_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
{
CPUState *cs;
ICPState *ss;
- KVMXICSState *xicskvm = XICS_SPAPR_KVM(xics);
+ KVMXICSState *icpkvm = KVM_XICS(icp);
cs = CPU(cpu);
- ss = &xics->ss[cs->cpu_index];
+ ss = &icp->ss[cs->cpu_index];
- assert(cs->cpu_index < xics->nr_servers);
- if (xicskvm->kernel_xics_fd == -1) {
+ assert(cs->cpu_index < icp->nr_servers);
+ if (icpkvm->kernel_xics_fd == -1) {
abort();
}
@@ -347,12 +344,13 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
return;
}
- if (xicskvm->kernel_xics_fd != -1) {
+ if (icpkvm->kernel_xics_fd != -1) {
int ret;
+ ss->cs = cs;
+
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0,
- xicskvm->kernel_xics_fd,
- kvm_arch_vcpu_id(cs));
+ icpkvm->kernel_xics_fd, kvm_arch_vcpu_id(cs));
if (ret < 0) {
error_report("Unable to connect CPU%ld to kernel XICS: %s",
kvm_arch_vcpu_id(cs), strerror(errno));
@@ -362,25 +360,24 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
}
}
-static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
- Error **errp)
+static void xics_kvm_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp)
{
- xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
+ icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
}
-static void xics_kvm_set_nr_servers(XICSState *xics, uint32_t nr_servers,
+static void xics_kvm_set_nr_servers(XICSState *icp, uint32_t nr_servers,
Error **errp)
{
int i;
- xics->nr_servers = nr_servers;
+ icp->nr_servers = nr_servers;
- xics->ss = g_malloc0(xics->nr_servers * sizeof(ICPState));
- for (i = 0; i < xics->nr_servers; i++) {
+ icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
+ for (i = 0; i < icp->nr_servers; i++) {
char buffer[32];
- object_initialize(&xics->ss[i], sizeof(xics->ss[i]), TYPE_KVM_ICP);
+ object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_KVM_ICP);
snprintf(buffer, sizeof(buffer), "icp[%d]", i);
- object_property_add_child(OBJECT(xics), buffer, OBJECT(&xics->ss[i]),
+ object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
errp);
}
}
@@ -396,8 +393,8 @@ static void rtas_dummy(PowerPCCPU *cpu, sPAPRMachineState *spapr,
static void xics_kvm_realize(DeviceState *dev, Error **errp)
{
- KVMXICSState *xicskvm = XICS_SPAPR_KVM(dev);
- XICSState *xics = XICS_COMMON(dev);
+ KVMXICSState *icpkvm = KVM_XICS(dev);
+ XICSState *icp = XICS_COMMON(dev);
int i, rc;
Error *error = NULL;
struct kvm_create_device xics_create_device = {
@@ -447,18 +444,17 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
goto fail;
}
- xicskvm->kernel_xics_fd = xics_create_device.fd;
+ icpkvm->kernel_xics_fd = xics_create_device.fd;
- object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
+ object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
if (error) {
error_propagate(errp, error);
goto fail;
}
- assert(xics->nr_servers);
- for (i = 0; i < xics->nr_servers; i++) {
- object_property_set_bool(OBJECT(&xics->ss[i]), true, "realized",
- &error);
+ assert(icp->nr_servers);
+ for (i = 0; i < icp->nr_servers; i++) {
+ object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized", &error);
if (error) {
error_propagate(errp, error);
goto fail;
@@ -484,7 +480,7 @@ static void xics_kvm_initfn(Object *obj)
xics->ics = ICS(object_new(TYPE_KVM_ICS));
object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
- xics->ics->xics = xics;
+ xics->ics->icp = xics;
}
static void xics_kvm_class_init(ObjectClass *oc, void *data)
@@ -498,8 +494,8 @@ static void xics_kvm_class_init(ObjectClass *oc, void *data)
xsc->set_nr_servers = xics_kvm_set_nr_servers;
}
-static const TypeInfo xics_spapr_kvm_info = {
- .name = TYPE_XICS_SPAPR_KVM,
+static const TypeInfo xics_kvm_info = {
+ .name = TYPE_KVM_XICS,
.parent = TYPE_XICS_COMMON,
.instance_size = sizeof(KVMXICSState),
.class_init = xics_kvm_class_init,
@@ -508,7 +504,7 @@ static const TypeInfo xics_spapr_kvm_info = {
static void xics_kvm_register_types(void)
{
- type_register_static(&xics_spapr_kvm_info);
+ type_register_static(&xics_kvm_info);
type_register_static(&ics_kvm_info);
type_register_static(&icp_kvm_info);
}
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
deleted file mode 100644
index 618826dac..000000000
--- a/hw/intc/xics_spapr.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * 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.
- *
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "hw/hw.h"
-#include "trace.h"
-#include "qemu/timer.h"
-#include "hw/ppc/spapr.h"
-#include "hw/ppc/xics.h"
-#include "qapi/visitor.h"
-#include "qapi/error.h"
-
-/*
- * Guest interfaces
- */
-
-static target_ulong h_cppr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- target_ulong opcode, target_ulong *args)
-{
- CPUState *cs = CPU(cpu);
- target_ulong cppr = args[0];
-
- icp_set_cppr(spapr->xics, cs->cpu_index, cppr);
- return H_SUCCESS;
-}
-
-static target_ulong h_ipi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- target_ulong opcode, target_ulong *args)
-{
- target_ulong server = xics_get_cpu_index_by_dt_id(args[0]);
- target_ulong mfrr = args[1];
-
- if (server >= spapr->xics->nr_servers) {
- return H_PARAMETER;
- }
-
- icp_set_mfrr(spapr->xics, server, mfrr);
- return H_SUCCESS;
-}
-
-static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- target_ulong opcode, target_ulong *args)
-{
- CPUState *cs = CPU(cpu);
- uint32_t xirr = icp_accept(spapr->xics->ss + cs->cpu_index);
-
- args[0] = xirr;
- return H_SUCCESS;
-}
-
-static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- target_ulong opcode, target_ulong *args)
-{
- CPUState *cs = CPU(cpu);
- ICPState *ss = &spapr->xics->ss[cs->cpu_index];
- uint32_t xirr = icp_accept(ss);
-
- args[0] = xirr;
- args[1] = cpu_get_host_ticks();
- return H_SUCCESS;
-}
-
-static target_ulong h_eoi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- target_ulong opcode, target_ulong *args)
-{
- CPUState *cs = CPU(cpu);
- target_ulong xirr = args[0];
-
- icp_eoi(spapr->xics, cs->cpu_index, xirr);
- return H_SUCCESS;
-}
-
-static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- target_ulong opcode, target_ulong *args)
-{
- CPUState *cs = CPU(cpu);
- uint32_t mfrr;
- uint32_t xirr = icp_ipoll(spapr->xics->ss + cs->cpu_index, &mfrr);
-
- args[0] = xirr;
- args[1] = mfrr;
-
- return H_SUCCESS;
-}
-
-static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- uint32_t token,
- uint32_t nargs, target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- ICSState *ics = spapr->xics->ics;
- uint32_t nr, server, priority;
-
- if ((nargs != 3) || (nret != 1)) {
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- nr = rtas_ld(args, 0);
- server = xics_get_cpu_index_by_dt_id(rtas_ld(args, 1));
- priority = rtas_ld(args, 2);
-
- if (!ics_valid_irq(ics, nr) || (server >= ics->xics->nr_servers)
- || (priority > 0xff)) {
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- ics_write_xive(ics, nr, server, priority, priority);
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-}
-
-static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- uint32_t token,
- uint32_t nargs, target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- ICSState *ics = spapr->xics->ics;
- uint32_t nr;
-
- if ((nargs != 1) || (nret != 3)) {
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- nr = rtas_ld(args, 0);
-
- if (!ics_valid_irq(ics, nr)) {
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
- rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
- rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
-}
-
-static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- uint32_t token,
- uint32_t nargs, target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- ICSState *ics = spapr->xics->ics;
- uint32_t nr;
-
- if ((nargs != 1) || (nret != 1)) {
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- nr = rtas_ld(args, 0);
-
- if (!ics_valid_irq(ics, nr)) {
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
- ics->irqs[nr - ics->offset].priority);
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-}
-
-static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- uint32_t token,
- uint32_t nargs, target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- ICSState *ics = spapr->xics->ics;
- uint32_t nr;
-
- if ((nargs != 1) || (nret != 1)) {
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- nr = rtas_ld(args, 0);
-
- if (!ics_valid_irq(ics, nr)) {
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
- ics->irqs[nr - ics->offset].saved_priority,
- ics->irqs[nr - ics->offset].saved_priority);
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-}
-
-static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
- Error **errp)
-{
- xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
-}
-
-static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
- Error **errp)
-{
- int i;
-
- xics->nr_servers = nr_servers;
-
- xics->ss = g_malloc0(xics->nr_servers * sizeof(ICPState));
- for (i = 0; i < xics->nr_servers; i++) {
- char buffer[32];
- object_initialize(&xics->ss[i], sizeof(xics->ss[i]), TYPE_ICP);
- snprintf(buffer, sizeof(buffer), "icp[%d]", i);
- object_property_add_child(OBJECT(xics), buffer, OBJECT(&xics->ss[i]),
- errp);
- }
-}
-
-static void xics_spapr_realize(DeviceState *dev, Error **errp)
-{
- XICSState *xics = XICS_SPAPR(dev);
- Error *error = NULL;
- int i;
-
- if (!xics->nr_servers) {
- error_setg(errp, "Number of servers needs to be greater 0");
- return;
- }
-
- /* Registration of global state belongs into realize */
- spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive);
- spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive);
- spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_int_off);
- spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_int_on);
-
- spapr_register_hypercall(H_CPPR, h_cppr);
- spapr_register_hypercall(H_IPI, h_ipi);
- spapr_register_hypercall(H_XIRR, h_xirr);
- spapr_register_hypercall(H_XIRR_X, h_xirr_x);
- spapr_register_hypercall(H_EOI, h_eoi);
- spapr_register_hypercall(H_IPOLL, h_ipoll);
-
- object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
- if (error) {
- error_propagate(errp, error);
- return;
- }
-
- for (i = 0; i < xics->nr_servers; i++) {
- object_property_set_bool(OBJECT(&xics->ss[i]), true, "realized",
- &error);
- if (error) {
- error_propagate(errp, error);
- return;
- }
- }
-}
-
-static void xics_spapr_initfn(Object *obj)
-{
- XICSState *xics = XICS_SPAPR(obj);
-
- xics->ics = ICS(object_new(TYPE_ICS));
- object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
- xics->ics->xics = xics;
-}
-
-static void xics_spapr_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- XICSStateClass *xsc = XICS_SPAPR_CLASS(oc);
-
- dc->realize = xics_spapr_realize;
- xsc->set_nr_irqs = xics_spapr_set_nr_irqs;
- xsc->set_nr_servers = xics_spapr_set_nr_servers;
-}
-
-static const TypeInfo xics_spapr_info = {
- .name = TYPE_XICS_SPAPR,
- .parent = TYPE_XICS_COMMON,
- .instance_size = sizeof(XICSState),
- .class_size = sizeof(XICSStateClass),
- .class_init = xics_spapr_class_init,
- .instance_init = xics_spapr_initfn,
-};
-
-#define ICS_IRQ_FREE(ics, srcno) \
- (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK)))
-
-static int ics_find_free_block(ICSState *ics, int num, int alignnum)
-{
- int first, i;
-
- for (first = 0; first < ics->nr_irqs; first += alignnum) {
- if (num > (ics->nr_irqs - first)) {
- return -1;
- }
- for (i = first; i < first + num; ++i) {
- if (!ICS_IRQ_FREE(ics, i)) {
- break;
- }
- }
- if (i == (first + num)) {
- return first;
- }
- }
-
- return -1;
-}
-
-int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
- Error **errp)
-{
- ICSState *ics = &xics->ics[src];
- int irq;
-
- if (irq_hint) {
- assert(src == xics_find_source(xics, irq_hint));
- if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
- error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
- return -1;
- }
- irq = irq_hint;
- } else {
- irq = ics_find_free_block(ics, 1, 1);
- if (irq < 0) {
- error_setg(errp, "can't allocate IRQ: no IRQ left");
- return -1;
- }
- irq += ics->offset;
- }
-
- ics_set_irq_type(ics, irq - ics->offset, lsi);
- trace_xics_alloc(src, irq);
-
- return irq;
-}
-
-/*
- * Allocate block of consecutive IRQs, and return the number of the first IRQ in
- * the block. If align==true, aligns the first IRQ number to num.
- */
-int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi,
- bool align, Error **errp)
-{
- int i, first = -1;
- ICSState *ics = &xics->ics[src];
-
- assert(src == 0);
- /*
- * MSIMesage::data is used for storing VIRQ so
- * it has to be aligned to num to support multiple
- * MSI vectors. MSI-X is not affected by this.
- * The hint is used for the first IRQ, the rest should
- * be allocated continuously.
- */
- if (align) {
- assert((num == 1) || (num == 2) || (num == 4) ||
- (num == 8) || (num == 16) || (num == 32));
- first = ics_find_free_block(ics, num, num);
- } else {
- first = ics_find_free_block(ics, num, 1);
- }
- if (first < 0) {
- error_setg(errp, "can't find a free %d-IRQ block", num);
- return -1;
- }
-
- if (first >= 0) {
- for (i = first; i < first + num; ++i) {
- ics_set_irq_type(ics, i, lsi);
- }
- }
- first += ics->offset;
-
- trace_xics_alloc_block(src, first, num, lsi, align);
-
- return first;
-}
-
-static void ics_free(ICSState *ics, int srcno, int num)
-{
- int i;
-
- for (i = srcno; i < srcno + num; ++i) {
- if (ICS_IRQ_FREE(ics, i)) {
- trace_xics_ics_free_warn(ics - ics->xics->ics, i + ics->offset);
- }
- memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
- }
-}
-
-void xics_spapr_free(XICSState *xics, int irq, int num)
-{
- int src = xics_find_source(xics, irq);
-
- if (src >= 0) {
- ICSState *ics = &xics->ics[src];
-
- /* FIXME: implement multiple sources */
- assert(src == 0);
-
- trace_xics_ics_free(ics - xics->ics, irq, num);
- ics_free(ics, irq - ics->offset, num);
- }
-}
-
-static void xics_spapr_register_types(void)
-{
- type_register_static(&xics_spapr_info);
-}
-
-type_init(xics_spapr_register_types)
diff --git a/hw/ipack/ipack.c b/hw/ipack/ipack.c
index 6021e6d13..5f99ed9a7 100644
--- a/hw/ipack/ipack.c
+++ b/hw/ipack/ipack.c
@@ -2,7 +2,7 @@
* QEMU IndustryPack emulation
*
* Copyright (C) 2012 Igalia, S.L.
- * Author: Alberto Garcia <berto@igalia.com>
+ * Author: Alberto Garcia <agarcia@igalia.com>
*
* This code is licensed under the GNU GPL v2 or (at your option) any
* later version.
diff --git a/hw/ipack/tpci200.c b/hw/ipack/tpci200.c
index 4dfa6b33f..fdda6f414 100644
--- a/hw/ipack/tpci200.c
+++ b/hw/ipack/tpci200.c
@@ -2,7 +2,7 @@
* QEMU TEWS TPCI200 IndustryPack carrier emulation
*
* Copyright (C) 2012 Igalia, S.L.
- * Author: Alberto Garcia <berto@igalia.com>
+ * Author: Alberto Garcia <agarcia@igalia.com>
*
* This code is licensed under the GNU GPL v2 or (at your option) any
* later version.
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
index f09f217e7..6adec1e99 100644
--- a/hw/ipmi/ipmi.c
+++ b/hw/ipmi/ipmi.c
@@ -30,13 +30,6 @@
#include "qom/object_interfaces.h"
#include "qapi/visitor.h"
-static uint32_t ipmi_current_uuid = 1;
-
-uint32_t ipmi_next_uuid(void)
-{
- return ipmi_current_uuid++;
-}
-
static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
{
switch (op) {
@@ -129,3 +122,30 @@ static void ipmi_register_types(void)
}
type_init(ipmi_register_types)
+
+static IPMIFwInfo *ipmi_fw_info;
+static unsigned int ipmi_fw_info_len;
+
+static uint32_t current_uuid = 1;
+
+void ipmi_add_fwinfo(IPMIFwInfo *info, Error **errp)
+{
+ info->uuid = current_uuid++;
+ ipmi_fw_info = g_realloc(ipmi_fw_info,
+ sizeof(*ipmi_fw_info) * (ipmi_fw_info_len + 1));
+ ipmi_fw_info[ipmi_fw_info_len] = *info;
+}
+
+IPMIFwInfo *ipmi_first_fwinfo(void)
+{
+ return ipmi_fw_info;
+}
+
+IPMIFwInfo *ipmi_next_fwinfo(IPMIFwInfo *current)
+{
+ current++;
+ if (current >= &ipmi_fw_info[ipmi_fw_info_len]) {
+ return NULL;
+ }
+ return current;
+}
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index 157879e17..fe12112a2 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -190,7 +190,7 @@ static void ipmi_bmc_extern_handle_command(IPMIBmc *b,
if (ibe->outlen) {
/* We already have a command queued. Shouldn't ever happen. */
fprintf(stderr, "IPMI KCS: Got command when not finished with the"
- " previous command\n");
+ " previous commmand\n");
abort();
}
diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c
index f03661715..aaea12ecd 100644
--- a/hw/ipmi/isa_ipmi_bt.c
+++ b/hw/ipmi/isa_ipmi_bt.c
@@ -390,6 +390,16 @@ static void ipmi_bt_init(IPMIInterface *ii, Error **errp)
memory_region_init_io(&ib->io, NULL, &ipmi_bt_io_ops, ii, "ipmi-bt", 3);
}
+static void ipmi_bt_class_init(IPMIInterfaceClass *iic)
+{
+ iic->init = ipmi_bt_init;
+ iic->set_atn = ipmi_bt_set_atn;
+ iic->handle_rsp = ipmi_bt_handle_rsp;
+ iic->handle_if_event = ipmi_bt_handle_event;
+ iic->set_irq_enable = ipmi_bt_set_irq_enable;
+ iic->reset = ipmi_bt_handle_reset;
+}
+
#define TYPE_ISA_IPMI_BT "isa-ipmi-bt"
#define ISA_IPMI_BT(obj) OBJECT_CHECK(ISAIPMIBTDevice, (obj), \
@@ -399,38 +409,9 @@ typedef struct ISAIPMIBTDevice {
ISADevice dev;
int32_t isairq;
IPMIBT bt;
- uint32_t uuid;
+ IPMIFwInfo fwinfo;
} ISAIPMIBTDevice;
-static void ipmi_bt_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info)
-{
- ISAIPMIBTDevice *iib = ISA_IPMI_BT(ii);
-
- info->interface_name = "bt";
- info->interface_type = IPMI_SMBIOS_BT;
- info->ipmi_spec_major_revision = 2;
- info->ipmi_spec_minor_revision = 0;
- info->base_address = iib->bt.io_base;
- info->register_length = iib->bt.io_length;
- info->register_spacing = 1;
- info->memspace = IPMI_MEMSPACE_IO;
- info->irq_type = IPMI_LEVEL_IRQ;
- info->interrupt_number = iib->isairq;
- info->i2c_slave_address = iib->bt.bmc->slave_addr;
- info->uuid = iib->uuid;
-}
-
-static void ipmi_bt_class_init(IPMIInterfaceClass *iic)
-{
- iic->init = ipmi_bt_init;
- iic->set_atn = ipmi_bt_set_atn;
- iic->handle_rsp = ipmi_bt_handle_rsp;
- iic->handle_if_event = ipmi_bt_handle_event;
- iic->set_irq_enable = ipmi_bt_set_irq_enable;
- iic->reset = ipmi_bt_handle_reset;
- iic->get_fwinfo = ipmi_bt_get_fwinfo;
-}
-
static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp)
{
ISADevice *isadev = ISA_DEVICE(dev);
@@ -443,8 +424,6 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp)
return;
}
- iib->uuid = ipmi_next_uuid();
-
iib->bt.bmc->intf = ii;
iic->init(ii, errp);
@@ -459,6 +438,20 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp)
qdev_set_legacy_instance_id(dev, iib->bt.io_base, iib->bt.io_length);
isa_register_ioport(isadev, &iib->bt.io, iib->bt.io_base);
+
+ iib->fwinfo.interface_name = "bt";
+ iib->fwinfo.interface_type = IPMI_SMBIOS_BT;
+ iib->fwinfo.ipmi_spec_major_revision = 2;
+ iib->fwinfo.ipmi_spec_minor_revision = 0;
+ iib->fwinfo.base_address = iib->bt.io_base;
+ iib->fwinfo.register_length = iib->bt.io_length;
+ iib->fwinfo.register_spacing = 1;
+ iib->fwinfo.memspace = IPMI_MEMSPACE_IO;
+ iib->fwinfo.irq_type = IPMI_LEVEL_IRQ;
+ iib->fwinfo.interrupt_number = iib->isairq;
+ iib->fwinfo.acpi_parent = "\\_SB.PCI0.ISA";
+ iib->fwinfo.i2c_slave_address = iib->bt.bmc->slave_addr;
+ ipmi_add_fwinfo(&iib->fwinfo, errp);
}
static const VMStateDescription vmstate_ISAIPMIBTDevice = {
diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c
index 9a38f8a28..2742ce06c 100644
--- a/hw/ipmi/isa_ipmi_kcs.c
+++ b/hw/ipmi/isa_ipmi_kcs.c
@@ -354,6 +354,16 @@ static void ipmi_kcs_init(IPMIInterface *ii, Error **errp)
memory_region_init_io(&ik->io, NULL, &ipmi_kcs_io_ops, ii, "ipmi-kcs", 2);
}
+static void ipmi_kcs_class_init(IPMIInterfaceClass *iic)
+{
+ iic->init = ipmi_kcs_init;
+ iic->set_atn = ipmi_kcs_set_atn;
+ iic->handle_rsp = ipmi_kcs_handle_rsp;
+ iic->handle_if_event = ipmi_kcs_handle_event;
+ iic->set_irq_enable = ipmi_kcs_set_irq_enable;
+}
+
+
#define TYPE_ISA_IPMI_KCS "isa-ipmi-kcs"
#define ISA_IPMI_KCS(obj) OBJECT_CHECK(ISAIPMIKCSDevice, (obj), \
TYPE_ISA_IPMI_KCS)
@@ -362,37 +372,9 @@ typedef struct ISAIPMIKCSDevice {
ISADevice dev;
int32_t isairq;
IPMIKCS kcs;
- uint32_t uuid;
+ IPMIFwInfo fwinfo;
} ISAIPMIKCSDevice;
-static void ipmi_kcs_get_fwinfo(IPMIInterface *ii, IPMIFwInfo *info)
-{
- ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(ii);
-
- info->interface_name = "kcs";
- info->interface_type = IPMI_SMBIOS_KCS;
- info->ipmi_spec_major_revision = 2;
- info->ipmi_spec_minor_revision = 0;
- info->base_address = iik->kcs.io_base;
- info->i2c_slave_address = iik->kcs.bmc->slave_addr;
- info->register_length = iik->kcs.io_length;
- info->register_spacing = 1;
- info->memspace = IPMI_MEMSPACE_IO;
- info->irq_type = IPMI_LEVEL_IRQ;
- info->interrupt_number = iik->isairq;
- info->uuid = iik->uuid;
-}
-
-static void ipmi_kcs_class_init(IPMIInterfaceClass *iic)
-{
- iic->init = ipmi_kcs_init;
- iic->set_atn = ipmi_kcs_set_atn;
- iic->handle_rsp = ipmi_kcs_handle_rsp;
- iic->handle_if_event = ipmi_kcs_handle_event;
- iic->set_irq_enable = ipmi_kcs_set_irq_enable;
- iic->get_fwinfo = ipmi_kcs_get_fwinfo;
-}
-
static void ipmi_isa_realize(DeviceState *dev, Error **errp)
{
ISADevice *isadev = ISA_DEVICE(dev);
@@ -405,8 +387,6 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp)
return;
}
- iik->uuid = ipmi_next_uuid();
-
iik->kcs.bmc->intf = ii;
iic->init(ii, errp);
@@ -421,6 +401,20 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp)
qdev_set_legacy_instance_id(dev, iik->kcs.io_base, iik->kcs.io_length);
isa_register_ioport(isadev, &iik->kcs.io, iik->kcs.io_base);
+
+ iik->fwinfo.interface_name = "kcs";
+ iik->fwinfo.interface_type = IPMI_SMBIOS_KCS;
+ iik->fwinfo.ipmi_spec_major_revision = 2;
+ iik->fwinfo.ipmi_spec_minor_revision = 0;
+ iik->fwinfo.base_address = iik->kcs.io_base;
+ iik->fwinfo.i2c_slave_address = iik->kcs.bmc->slave_addr;
+ iik->fwinfo.register_length = iik->kcs.io_length;
+ iik->fwinfo.register_spacing = 1;
+ iik->fwinfo.memspace = IPMI_MEMSPACE_IO;
+ iik->fwinfo.irq_type = IPMI_LEVEL_IRQ;
+ iik->fwinfo.interrupt_number = iik->isairq;
+ iik->fwinfo.acpi_parent = "\\_SB.PCI0.ISA";
+ ipmi_add_fwinfo(&iik->fwinfo, errp);
}
const VMStateDescription vmstate_ISAIPMIKCSDevice = {
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index ce74db232..7aa115caf 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -97,13 +97,6 @@ void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
dev->nirqs++;
}
-void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, int isairq)
-{
- qemu_irq irq;
- isa_init_irq(isadev, &irq, isairq);
- qdev_connect_gpio_out(DEVICE(isadev), gpioirq, irq);
-}
-
void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16)
{
assert(bus && dma8 && dma16);
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 10d1ee8b9..99cd3ba9e 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -47,7 +47,8 @@
#include "hw/pci/pci_bus.h"
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"
-#include "qom/cpu.h"
+
+static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
/*****************************************************************************/
/* ICH9 LPC PCI to ISA bridge */
@@ -95,8 +96,8 @@ static void ich9_cc_update(ICH9LPCState *lpc)
/*
* D30: DMI2PCI bridge
- * It is arbitrarily decided how INTx lines of PCI devices behind
- * the bridge are connected to pirq lines. Our choice is PIRQ[E-H].
+ * It is arbitrarily decided how INTx lines of PCI devicesbehind the bridge
+ * are connected to pirq lines. Our choice is PIRQ[E-H].
* INT[A-D] are connected to PIRQ[E-H]
*/
for (pci_intx = 0; pci_intx < PCI_NUM_PINS; pci_intx++) {
@@ -202,28 +203,41 @@ static void ich9_lpc_pic_irq(ICH9LPCState *lpc, int pirq_num,
abort();
}
-/* gsi: i8259+ioapic irq 0-15, otherwise assert */
-static void ich9_lpc_update_pic(ICH9LPCState *lpc, int gsi)
+/* pic_irq: i8254 irq 0-15 */
+static void ich9_lpc_update_pic(ICH9LPCState *lpc, int pic_irq)
{
int i, pic_level;
- assert(gsi < ICH9_LPC_PIC_NUM_PINS);
-
/* The pic level is the logical OR of all the PCI irqs mapped to it */
pic_level = 0;
for (i = 0; i < ICH9_LPC_NB_PIRQS; i++) {
int tmp_irq;
int tmp_dis;
ich9_lpc_pic_irq(lpc, i, &tmp_irq, &tmp_dis);
- if (!tmp_dis && tmp_irq == gsi) {
+ if (!tmp_dis && pic_irq == tmp_irq) {
pic_level |= pci_bus_get_irq_level(lpc->d.bus, i);
}
}
- if (gsi == lpc->sci_gsi) {
+ if (pic_irq == ich9_lpc_sci_irq(lpc)) {
pic_level |= lpc->sci_level;
}
- qemu_set_irq(lpc->gsi[gsi], pic_level);
+ qemu_set_irq(lpc->pic[pic_irq], pic_level);
+}
+
+/* pirq: pirq[A-H] 0-7*/
+static void ich9_lpc_update_by_pirq(ICH9LPCState *lpc, int pirq)
+{
+ int pic_irq;
+ int pic_dis;
+
+ ich9_lpc_pic_irq(lpc, pirq, &pic_irq, &pic_dis);
+ assert(pic_irq < ICH9_LPC_PIC_NUM_PINS);
+ if (pic_dis) {
+ return;
+ }
+
+ ich9_lpc_update_pic(lpc, pic_irq);
}
/* APIC mode: GSIx: PIRQ[A-H] -> GSI 16, ... no pirq shares same APIC pins. */
@@ -237,32 +251,29 @@ static int ich9_gsi_to_pirq(int gsi)
return gsi - ICH9_LPC_PIC_NUM_PINS;
}
-/* gsi: ioapic irq 16-23, otherwise assert */
static void ich9_lpc_update_apic(ICH9LPCState *lpc, int gsi)
{
int level = 0;
- assert(gsi >= ICH9_LPC_PIC_NUM_PINS);
-
- level |= pci_bus_get_irq_level(lpc->d.bus, ich9_gsi_to_pirq(gsi));
- if (gsi == lpc->sci_gsi) {
+ if (gsi >= ICH9_LPC_PIC_NUM_PINS) {
+ level |= pci_bus_get_irq_level(lpc->d.bus, ich9_gsi_to_pirq(gsi));
+ }
+ if (gsi == ich9_lpc_sci_irq(lpc)) {
level |= lpc->sci_level;
}
- qemu_set_irq(lpc->gsi[gsi], level);
+ qemu_set_irq(lpc->ioapic[gsi], level);
}
void ich9_lpc_set_irq(void *opaque, int pirq, int level)
{
ICH9LPCState *lpc = opaque;
- int pic_irq, pic_dis;
assert(0 <= pirq);
assert(pirq < ICH9_LPC_NB_PIRQS);
ich9_lpc_update_apic(lpc, ich9_pirq_to_gsi(pirq));
- ich9_lpc_pic_irq(lpc, pirq, &pic_irq, &pic_dis);
- ich9_lpc_update_pic(lpc, pic_irq);
+ ich9_lpc_update_by_pirq(lpc, pirq);
}
/* return the pirq number (PIRQ[A-H]:0-7) corresponding to
@@ -348,14 +359,13 @@ static void ich9_set_sci(void *opaque, int irq_num, int level)
}
lpc->sci_level = level;
- irq = lpc->sci_gsi;
+ irq = ich9_lpc_sci_irq(lpc);
if (irq < 0) {
return;
}
- if (irq >= ICH9_LPC_PIC_NUM_PINS) {
- ich9_lpc_update_apic(lpc, irq);
- } else {
+ ich9_lpc_update_apic(lpc, irq);
+ if (irq < ICH9_LPC_PIC_NUM_PINS) {
ich9_lpc_update_pic(lpc, irq);
}
}
@@ -392,27 +402,12 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
/* config:PMBASE */
static void
-ich9_lpc_pmbase_sci_update(ICH9LPCState *lpc)
+ich9_lpc_pmbase_update(ICH9LPCState *lpc)
{
uint32_t pm_io_base = pci_get_long(lpc->d.config + ICH9_LPC_PMBASE);
- uint8_t acpi_cntl = pci_get_long(lpc->d.config + ICH9_LPC_ACPI_CTRL);
- uint8_t new_gsi;
-
- if (acpi_cntl & ICH9_LPC_ACPI_CTRL_ACPI_EN) {
- pm_io_base &= ICH9_LPC_PMBASE_BASE_ADDRESS_MASK;
- } else {
- pm_io_base = 0;
- }
+ pm_io_base &= ICH9_LPC_PMBASE_BASE_ADDRESS_MASK;
ich9_pm_iospace_update(&lpc->pm, pm_io_base);
-
- new_gsi = ich9_lpc_sci_irq(lpc);
- if (lpc->sci_level && new_gsi != lpc->sci_gsi) {
- qemu_set_irq(lpc->pm.irq, 0);
- lpc->sci_gsi = new_gsi;
- qemu_set_irq(lpc->pm.irq, 1);
- }
- lpc->sci_gsi = new_gsi;
}
/* config:RCBA */
@@ -449,7 +444,7 @@ static int ich9_lpc_post_load(void *opaque, int version_id)
{
ICH9LPCState *lpc = opaque;
- ich9_lpc_pmbase_sci_update(lpc);
+ ich9_lpc_pmbase_update(lpc);
ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RCBA_EN */);
ich9_lpc_pmcon_update(lpc);
return 0;
@@ -462,9 +457,8 @@ static void ich9_lpc_config_write(PCIDevice *d,
uint32_t rcba_old = pci_get_long(d->config + ICH9_LPC_RCBA);
pci_default_write_config(d, addr, val, len);
- if (ranges_overlap(addr, len, ICH9_LPC_PMBASE, 4) ||
- ranges_overlap(addr, len, ICH9_LPC_ACPI_CTRL, 1)) {
- ich9_lpc_pmbase_sci_update(lpc);
+ if (ranges_overlap(addr, len, ICH9_LPC_PMBASE, 4)) {
+ ich9_lpc_pmbase_update(lpc);
}
if (ranges_overlap(addr, len, ICH9_LPC_RCBA, 4)) {
ich9_lpc_rcba_update(lpc, rcba_old);
@@ -502,7 +496,7 @@ static void ich9_lpc_reset(DeviceState *qdev)
ich9_cc_reset(lpc);
- ich9_lpc_pmbase_sci_update(lpc);
+ ich9_lpc_pmbase_update(lpc);
ich9_lpc_rcba_update(lpc, rcba_old);
lpc->sci_level = 0;
@@ -582,7 +576,7 @@ static void ich9_lpc_get_sci_int(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj);
- uint32_t value = lpc->sci_gsi;
+ uint32_t value = ich9_lpc_sci_irq(lpc);
visit_type_uint32(v, name, &value, errp);
}
@@ -613,7 +607,6 @@ static void ich9_lpc_initfn(Object *obj)
static void ich9_lpc_realize(PCIDevice *d, Error **errp)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
- DeviceState *dev = DEVICE(d);
ISABus *isa_bus;
isa_bus = isa_bus_new(DEVICE(d), get_system_memory(), get_system_io(),
@@ -624,9 +617,6 @@ static void ich9_lpc_realize(PCIDevice *d, Error **errp)
pci_set_long(d->wmask + ICH9_LPC_PMBASE,
ICH9_LPC_PMBASE_BASE_ADDRESS_MASK);
- pci_set_byte(d->wmask + ICH9_LPC_PMBASE,
- ICH9_LPC_ACPI_CTRL_ACPI_EN |
- ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK);
memory_region_init_io(&lpc->rcrb_mem, OBJECT(d), &rcrb_mmio_ops, lpc,
"lpc-rcrb-mmio", ICH9_CC_SIZE);
@@ -644,10 +634,30 @@ static void ich9_lpc_realize(PCIDevice *d, Error **errp)
memory_region_add_subregion_overlap(pci_address_space_io(d),
ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem,
1);
+}
+
+static void ich9_device_plug_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
+
+ ich9_pm_device_plug_cb(&lpc->pm, dev, errp);
+}
- qdev_init_gpio_out_named(dev, lpc->gsi, ICH9_GPIO_GSI, GSI_NUM_PINS);
+static void ich9_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
+
+ ich9_pm_device_unplug_request_cb(&lpc->pm, dev, errp);
+}
+
+static void ich9_device_unplug_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
- isa_bus_irqs(isa_bus, lpc->gsi);
+ ich9_pm_device_unplug_cb(&lpc->pm, dev, errp);
}
static bool ich9_rst_cnt_needed(void *opaque)
@@ -692,13 +702,6 @@ static Property ich9_lpc_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-static void ich9_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
-{
- ICH9LPCState *s = ICH9_LPC_DEVICE(adev);
-
- acpi_send_gpe_event(&s->pm.acpi_regs, s->pm.irq, ev);
-}
-
static void ich9_lpc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -722,12 +725,10 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)
* pc_q35_init()
*/
dc->cannot_instantiate_with_device_add_yet = true;
- hc->plug = ich9_pm_device_plug_cb;
- hc->unplug_request = ich9_pm_device_unplug_request_cb;
- hc->unplug = ich9_pm_device_unplug_cb;
+ hc->plug = ich9_device_plug_cb;
+ hc->unplug_request = ich9_device_unplug_request_cb;
+ hc->unplug = ich9_device_unplug_cb;
adevc->ospm_status = ich9_pm_ospm_status;
- adevc->send_event = ich9_send_gpe;
- adevc->madt_cpu = pc_madt_cpu_entry;
}
static const TypeInfo ich9_lpc_info = {
diff --git a/hw/isa/trace-events b/hw/isa/trace-events
deleted file mode 100644
index 9faca41a9..000000000
--- a/hw/isa/trace-events
+++ /dev/null
@@ -1,9 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/isa/pc87312.c
-pc87312_io_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
-pc87312_io_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
-pc87312_info_floppy(uint32_t base) "base 0x%x"
-pc87312_info_ide(uint32_t base) "base 0x%x"
-pc87312_info_parallel(uint32_t base, uint32_t irq) "base 0x%x, irq %u"
-pc87312_info_serial(int n, uint32_t base, uint32_t irq) "id=%d, base 0x%x, irq %u"
diff --git a/hw/lm32/lm32.h b/hw/lm32/lm32.h
index db9eb29ea..18aa6fdc1 100644
--- a/hw/lm32/lm32.h
+++ b/hw/lm32/lm32.h
@@ -1,5 +1,5 @@
#ifndef HW_LM32_H
-#define HW_LM32_H
+#define HW_LM32_H 1
#include "hw/char/lm32_juart.h"
@@ -16,31 +16,14 @@ static inline DeviceState *lm32_pic_init(qemu_irq cpu_irq)
return dev;
}
-static inline DeviceState *lm32_juart_init(CharDriverState *chr)
+static inline DeviceState *lm32_juart_init(void)
{
DeviceState *dev;
dev = qdev_create(NULL, TYPE_LM32_JUART);
- qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
return dev;
}
-static inline DeviceState *lm32_uart_create(hwaddr addr,
- qemu_irq irq,
- CharDriverState *chr)
-{
- DeviceState *dev;
- SysBusDevice *s;
-
- dev = qdev_create(NULL, "lm32-uart");
- s = SYS_BUS_DEVICE(dev);
- qdev_prop_set_chr(dev, "chardev", chr);
- qdev_init_nofail(dev);
- sysbus_mmio_map(s, 0, addr);
- sysbus_connect_irq(s, 0, irq);
- return dev;
-}
-
#endif
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
index 8f0c3079d..c0290560f 100644
--- a/hw/lm32/lm32_boards.c
+++ b/hw/lm32/lm32_boards.c
@@ -31,7 +31,6 @@
#include "lm32_hwsetup.h"
#include "lm32.h"
#include "exec/address-spaces.h"
-#include "sysemu/sysemu.h"
typedef struct {
LM32CPU *cpu;
@@ -132,12 +131,12 @@ static void lm32_evr_init(MachineState *machine)
irq[i] = qdev_get_gpio_in(env->pic_state, i);
}
- lm32_uart_create(uart0_base, irq[uart0_irq], serial_hds[0]);
+ sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
/* make sure juart isn't the first chardev */
- env->juart_state = lm32_juart_init(serial_hds[1]);
+ env->juart_state = lm32_juart_init();
reset_info->bootstrap_pc = flash_base;
@@ -233,13 +232,13 @@ static void lm32_uclinux_init(MachineState *machine)
irq[i] = qdev_get_gpio_in(env->pic_state, i);
}
- lm32_uart_create(uart0_base, irq[uart0_irq], serial_hds[0]);
+ sysbus_create_simple("lm32-uart", uart0_base, irq[uart0_irq]);
sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]);
sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]);
sysbus_create_simple("lm32-timer", timer2_base, irq[timer2_irq]);
/* make sure juart isn't the first chardev */
- env->juart_state = lm32_juart_init(serial_hds[1]);
+ env->juart_state = lm32_juart_init();
reset_info->bootstrap_pc = flash_base;
diff --git a/hw/lm32/milkymist-hw.h b/hw/lm32/milkymist-hw.h
index 4418b44ca..c8dfb4d2d 100644
--- a/hw/lm32/milkymist-hw.h
+++ b/hw/lm32/milkymist-hw.h
@@ -1,17 +1,15 @@
-#ifndef QEMU_HW_MILKYMIST_HW_H
-#define QEMU_HW_MILKYMIST_HW_H
+#ifndef QEMU_HW_MILKYMIST_H
+#define QEMU_HW_MILKYMIST_H
#include "hw/qdev.h"
#include "net/net.h"
static inline DeviceState *milkymist_uart_create(hwaddr base,
- qemu_irq irq,
- CharDriverState *chr)
+ qemu_irq irq)
{
DeviceState *dev;
dev = qdev_create(NULL, "milkymist-uart");
- qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
@@ -110,6 +108,10 @@ static inline DeviceState *milkymist_tmu2_create(hwaddr base,
int nelements;
int ver_major, ver_minor;
+ if (display_type == DT_NOGRAPHIC) {
+ return NULL;
+ }
+
/* check that GLX will work */
d = XOpenDisplay(NULL);
if (d == NULL) {
@@ -203,4 +205,4 @@ static inline DeviceState *milkymist_softusb_create(hwaddr base,
return dev;
}
-#endif /* QEMU_HW_MILKYMIST_HW_H */
+#endif /* QEMU_HW_MILKYMIST_H */
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 5cae0f19d..96e6f4dc2 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -159,7 +159,7 @@ milkymist_init(MachineState *machine)
}
g_free(bios_filename);
- milkymist_uart_create(0x60000000, irq[0], serial_hds[0]);
+ milkymist_uart_create(0x60000000, irq[0]);
milkymist_sysctl_create(0x60001000, irq[1], irq[2], irq[3],
80000000, 0x10014d31, 0x0000041f, 0x00000001);
milkymist_hpdmc_create(0x60002000);
@@ -167,15 +167,13 @@ milkymist_init(MachineState *machine)
milkymist_memcard_create(0x60004000);
milkymist_ac97_create(0x60005000, irq[4], irq[5], irq[6], irq[7]);
milkymist_pfpu_create(0x60006000, irq[8]);
- if (machine->enable_graphics) {
- milkymist_tmu2_create(0x60007000, irq[9]);
- }
+ milkymist_tmu2_create(0x60007000, irq[9]);
milkymist_minimac2_create(0x60008000, 0x30000000, irq[10], irq[11]);
milkymist_softusb_create(0x6000f000, irq[15],
0x20000000, 0x1000, 0x20020000, 0x2000);
/* make sure juart isn't the first chardev */
- env->juart_state = lm32_juart_init(serial_hds[1]);
+ env->juart_state = lm32_juart_init();
if (kernel_filename) {
uint64_t entry;
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 7895805a2..0a602f28b 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -23,153 +23,20 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qapi/visitor.h"
#include "hw/mem/nvdimm.h"
-static void nvdimm_get_label_size(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- NVDIMMDevice *nvdimm = NVDIMM(obj);
- uint64_t value = nvdimm->label_size;
-
- visit_type_size(v, name, &value, errp);
-}
-
-static void nvdimm_set_label_size(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- NVDIMMDevice *nvdimm = NVDIMM(obj);
- Error *local_err = NULL;
- uint64_t value;
-
- if (memory_region_size(&nvdimm->nvdimm_mr)) {
- error_setg(&local_err, "cannot change property value");
- goto out;
- }
-
- visit_type_size(v, name, &value, &local_err);
- if (local_err) {
- goto out;
- }
- if (value < MIN_NAMESPACE_LABEL_SIZE) {
- error_setg(&local_err, "Property '%s.%s' (0x%" PRIx64 ") is required"
- " at least 0x%lx", object_get_typename(obj),
- name, value, MIN_NAMESPACE_LABEL_SIZE);
- goto out;
- }
-
- nvdimm->label_size = value;
-out:
- error_propagate(errp, local_err);
-}
-
-static void nvdimm_init(Object *obj)
-{
- object_property_add(obj, "label-size", "int",
- nvdimm_get_label_size, nvdimm_set_label_size, NULL,
- NULL, NULL);
-}
-
-static MemoryRegion *nvdimm_get_memory_region(PCDIMMDevice *dimm)
-{
- NVDIMMDevice *nvdimm = NVDIMM(dimm);
-
- return &nvdimm->nvdimm_mr;
-}
-
-static void nvdimm_realize(PCDIMMDevice *dimm, Error **errp)
-{
- MemoryRegion *mr = host_memory_backend_get_memory(dimm->hostmem, errp);
- NVDIMMDevice *nvdimm = NVDIMM(dimm);
- uint64_t align, pmem_size, size = memory_region_size(mr);
-
- align = memory_region_get_alignment(mr);
-
- pmem_size = size - nvdimm->label_size;
- nvdimm->label_data = memory_region_get_ram_ptr(mr) + pmem_size;
- pmem_size = QEMU_ALIGN_DOWN(pmem_size, align);
-
- if (size <= nvdimm->label_size || !pmem_size) {
- HostMemoryBackend *hostmem = dimm->hostmem;
- char *path = object_get_canonical_path_component(OBJECT(hostmem));
-
- error_setg(errp, "the size of memdev %s (0x%" PRIx64 ") is too "
- "small to contain nvdimm label (0x%" PRIx64 ") and "
- "aligned PMEM (0x%" PRIx64 ")",
- path, memory_region_size(mr), nvdimm->label_size, align);
- g_free(path);
- return;
- }
-
- memory_region_init_alias(&nvdimm->nvdimm_mr, OBJECT(dimm),
- "nvdimm-memory", mr, 0, pmem_size);
- nvdimm->nvdimm_mr.align = align;
-}
-
-/*
- * the caller should check the input parameters before calling
- * label read/write functions.
- */
-static void nvdimm_validate_rw_label_data(NVDIMMDevice *nvdimm, uint64_t size,
- uint64_t offset)
-{
- assert((nvdimm->label_size >= size + offset) && (offset + size > offset));
-}
-
-static void nvdimm_read_label_data(NVDIMMDevice *nvdimm, void *buf,
- uint64_t size, uint64_t offset)
-{
- nvdimm_validate_rw_label_data(nvdimm, size, offset);
-
- memcpy(buf, nvdimm->label_data + offset, size);
-}
-
-static void nvdimm_write_label_data(NVDIMMDevice *nvdimm, const void *buf,
- uint64_t size, uint64_t offset)
-{
- MemoryRegion *mr;
- PCDIMMDevice *dimm = PC_DIMM(nvdimm);
- uint64_t backend_offset;
-
- nvdimm_validate_rw_label_data(nvdimm, size, offset);
-
- memcpy(nvdimm->label_data + offset, buf, size);
-
- mr = host_memory_backend_get_memory(dimm->hostmem, &error_abort);
- backend_offset = memory_region_size(mr) - nvdimm->label_size + offset;
- memory_region_set_dirty(mr, backend_offset, size);
-}
-
-static MemoryRegion *nvdimm_get_vmstate_memory_region(PCDIMMDevice *dimm)
-{
- return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
-}
-
static void nvdimm_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
- PCDIMMDeviceClass *ddc = PC_DIMM_CLASS(oc);
- NVDIMMClass *nvc = NVDIMM_CLASS(oc);
/* nvdimm hotplug has not been supported yet. */
dc->hotpluggable = false;
-
- ddc->realize = nvdimm_realize;
- ddc->get_memory_region = nvdimm_get_memory_region;
- ddc->get_vmstate_memory_region = nvdimm_get_vmstate_memory_region;
-
- nvc->read_label_data = nvdimm_read_label_data;
- nvc->write_label_data = nvdimm_write_label_data;
}
static TypeInfo nvdimm_info = {
.name = TYPE_NVDIMM,
.parent = TYPE_PC_DIMM,
- .class_size = sizeof(NVDIMMClass),
.class_init = nvdimm_class_init,
- .instance_size = sizeof(NVDIMMDevice),
- .instance_init = nvdimm_init,
};
static void nvdimm_register_types(void)
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 9e8dab0e8..9e7de5682 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -40,8 +40,6 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
int slot;
MachineState *machine = MACHINE(qdev_get_machine());
PCDIMMDevice *dimm = PC_DIMM(dev);
- PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm);
Error *local_err = NULL;
uint64_t existing_dimms_capacity = 0;
uint64_t addr;
@@ -107,7 +105,7 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
}
memory_region_add_subregion(&hpms->mr, addr - hpms->base, mr);
- vmstate_register_ram(vmstate_mr, dev);
+ vmstate_register_ram(mr, dev);
numa_set_mem_node_id(addr, memory_region_size(mr), dimm->node);
out:
@@ -118,12 +116,10 @@ void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,
MemoryRegion *mr)
{
PCDIMMDevice *dimm = PC_DIMM(dev);
- PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm);
numa_unset_mem_node_id(dimm->addr, memory_region_size(mr), dimm->node);
memory_region_del_subregion(&hpms->mr, mr);
- vmstate_unregister_ram(vmstate_mr, dev);
+ vmstate_unregister_ram(mr, dev);
}
static int pc_existing_dimms_capacity_internal(Object *obj, void *opaque)
@@ -358,9 +354,8 @@ static void pc_dimm_get_size(Object *obj, Visitor *v, const char *name,
int64_t value;
MemoryRegion *mr;
PCDIMMDevice *dimm = PC_DIMM(obj);
- PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(obj);
- mr = ddc->get_memory_region(dimm);
+ mr = host_memory_backend_get_memory(dimm->hostmem, errp);
value = memory_region_size(mr);
visit_type_int(v, name, &value, errp);
@@ -369,9 +364,14 @@ static void pc_dimm_get_size(Object *obj, Visitor *v, const char *name,
static void pc_dimm_check_memdev_is_busy(Object *obj, const char *name,
Object *val, Error **errp)
{
+ MemoryRegion *mr;
Error *local_err = NULL;
- if (host_memory_backend_is_mapped(MEMORY_BACKEND(val))) {
+ mr = host_memory_backend_get_memory(MEMORY_BACKEND(val), &local_err);
+ if (local_err) {
+ goto out;
+ }
+ if (memory_region_is_mapped(mr)) {
char *path = object_get_canonical_path_component(val);
error_setg(&local_err, "can't use already busy memdev: %s", path);
g_free(path);
@@ -379,6 +379,7 @@ static void pc_dimm_check_memdev_is_busy(Object *obj, const char *name,
qdev_prop_allow_set_link_before_realize(obj, name, val, &local_err);
}
+out:
error_propagate(errp, local_err);
}
@@ -398,7 +399,6 @@ static void pc_dimm_init(Object *obj)
static void pc_dimm_realize(DeviceState *dev, Error **errp)
{
PCDIMMDevice *dimm = PC_DIMM(dev);
- PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
if (!dimm->hostmem) {
error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
@@ -411,19 +411,6 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
return;
}
-
- if (ddc->realize) {
- ddc->realize(dimm, errp);
- }
-
- host_memory_backend_set_mapped(dimm->hostmem, true);
-}
-
-static void pc_dimm_unrealize(DeviceState *dev, Error **errp)
-{
- PCDIMMDevice *dimm = PC_DIMM(dev);
-
- host_memory_backend_set_mapped(dimm->hostmem, false);
}
static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm)
@@ -431,23 +418,16 @@ static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm)
return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
}
-static MemoryRegion *pc_dimm_get_vmstate_memory_region(PCDIMMDevice *dimm)
-{
- return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
-}
-
static void pc_dimm_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
PCDIMMDeviceClass *ddc = PC_DIMM_CLASS(oc);
dc->realize = pc_dimm_realize;
- dc->unrealize = pc_dimm_unrealize;
dc->props = pc_dimm_properties;
dc->desc = "DIMM memory module";
ddc->get_memory_region = pc_dimm_get_memory_region;
- ddc->get_vmstate_memory_region = pc_dimm_get_vmstate_memory_region;
}
static TypeInfo pc_dimm_info = {
diff --git a/hw/microblaze/boot.h b/hw/microblaze/boot.h
index dd1090d8b..0eb7f8e4f 100644
--- a/hw/microblaze/boot.h
+++ b/hw/microblaze/boot.h
@@ -1,5 +1,5 @@
-#ifndef MICROBLAZE_BOOT_H
-#define MICROBLAZE_BOOT_H
+#ifndef __MICROBLAZE_BOOT__
+#define __MICROBLAZE_BOOT__
#include "hw/hw.h"
@@ -9,4 +9,4 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
const char *dtb_filename,
void (*machine_cpu_reset)(MicroBlazeCPU *));
-#endif /* MICROBLAZE_BOOT_H */
+#endif /* __MICROBLAZE_BOOT __ */
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 4968bdbb2..07527b677 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -191,16 +191,9 @@ petalogix_ml605_init(MachineState *machine)
spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
for (i = 0; i < NUM_SPI_FLASHES; i++) {
- DriveInfo *dinfo = drive_get_next(IF_MTD);
qemu_irq cs_line;
- dev = ssi_create_slave_no_init(spi, "n25q128");
- if (dinfo) {
- qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
- &error_fatal);
- }
- qdev_init_nofail(dev);
-
+ dev = ssi_create_slave(spi, "n25q128");
cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0);
sysbus_connect_irq(busdev, i+1, cs_line);
}
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index 423bcd7f6..f821e1cfe 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -36,7 +36,6 @@
#include "hw/boards.h"
#include "sysemu/block-backend.h"
#include "exec/address-spaces.h"
-#include "hw/char/xilinx_uartlite.h"
#include "boot.h"
@@ -104,8 +103,8 @@ petalogix_s3adsp1800_init(MachineState *machine)
irq[i] = qdev_get_gpio_in(dev, i);
}
- xilinx_uartlite_create(UARTLITE_BASEADDR, irq[UARTLITE_IRQ],
- serial_hds[0]);
+ sysbus_create_simple("xlnx.xps-uartlite", UARTLITE_BASEADDR,
+ irq[UARTLITE_IRQ]);
/* 2 timers at irq 2 @ 62 Mhz. */
dev = qdev_create(NULL, "xlnx.xps-timer");
diff --git a/hw/mips/cps.c b/hw/mips/cps.c
index 4ef337d5c..1bafbbb27 100644
--- a/hw/mips/cps.c
+++ b/hw/mips/cps.c
@@ -26,8 +26,13 @@
qemu_irq get_cps_irq(MIPSCPSState *s, int pin_number)
{
+ MIPSCPU *cpu = MIPS_CPU(first_cpu);
+ CPUMIPSState *env = &cpu->env;
+
assert(pin_number < s->num_irq);
- return s->gic.irq_state[pin_number].irq;
+
+ /* TODO: return GIC pins once implemented */
+ return env->irq[pin_number];
}
static void mips_cps_init(Object *obj)
@@ -73,15 +78,14 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
for (i = 0; i < s->num_vp; i++) {
cpu = cpu_mips_init(s->cpu_model);
if (cpu == NULL) {
- error_setg(errp, "%s: CPU initialization failed", __func__);
+ error_setg(errp, "%s: CPU initialization failed\n", __func__);
return;
}
+ env = &cpu->env;
/* Init internal devices */
- cpu_mips_irq_init_cpu(cpu);
- cpu_mips_clock_init(cpu);
-
- env = &cpu->env;
+ cpu_mips_irq_init_cpu(env);
+ cpu_mips_clock_init(env);
if (cpu_mips_itu_supported(env)) {
itu_present = true;
/* Attach ITC Tag to the VP */
@@ -125,21 +129,6 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(&s->container, 0,
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpc), 0));
- /* Global Interrupt Controller */
- object_initialize(&s->gic, sizeof(s->gic), TYPE_MIPS_GIC);
- qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
-
- object_property_set_int(OBJECT(&s->gic), s->num_vp, "num-vp", &err);
- object_property_set_int(OBJECT(&s->gic), 128, "num-irq", &err);
- object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
- if (err != NULL) {
- error_propagate(errp, err);
- return;
- }
-
- memory_region_add_subregion(&s->container, 0,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gic), 0));
-
/* Global Configuration Registers */
gcr_base = env->CP0_CMGCRBase << 4;
@@ -149,7 +138,6 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
object_property_set_int(OBJECT(&s->gcr), s->num_vp, "num-vp", &err);
object_property_set_int(OBJECT(&s->gcr), 0x800, "gcr-rev", &err);
object_property_set_int(OBJECT(&s->gcr), gcr_base, "gcr-base", &err);
- object_property_set_link(OBJECT(&s->gcr), OBJECT(&s->gic.mr), "gic", &err);
object_property_set_link(OBJECT(&s->gcr), OBJECT(&s->cpc.mr), "cpc", &err);
object_property_set_bool(OBJECT(&s->gcr), true, "realized", &err);
if (err != NULL) {
@@ -163,7 +151,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
static Property mips_cps_properties[] = {
DEFINE_PROP_UINT32("num-vp", MIPSCPSState, num_vp, 1),
- DEFINE_PROP_UINT32("num-irq", MIPSCPSState, num_irq, 256),
+ DEFINE_PROP_UINT32("num-irq", MIPSCPSState, num_irq, 8),
DEFINE_PROP_STRING("cpu-model", MIPSCPSState, cpu_model),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
index 8a166b3ea..efb227d06 100644
--- a/hw/mips/cputimer.c
+++ b/hw/mips/cputimer.c
@@ -151,10 +151,8 @@ static void mips_timer_cb (void *opaque)
env->CP0_Count--;
}
-void cpu_mips_clock_init (MIPSCPU *cpu)
+void cpu_mips_clock_init (CPUMIPSState *env)
{
- CPUMIPSState *env = &cpu->env;
-
/*
* If we're in KVM mode, don't create the periodic timer, that is handled in
* kernel.
diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c
index 4811843ab..3f4523df2 100644
--- a/hw/mips/gt64xxx_pci.c
+++ b/hw/mips/gt64xxx_pci.c
@@ -1167,6 +1167,7 @@ PCIBus *gt64120_register(qemu_irq *pic)
DeviceState *dev;
dev = qdev_create(NULL, TYPE_GT64120_PCI_HOST_BRIDGE);
+ qdev_init_nofail(dev);
d = GT64120_PCI_HOST_BRIDGE(dev);
phb = PCI_HOST_BRIDGE(dev);
memory_region_init(&d->pci0_mem, OBJECT(dev), "pci0-mem", UINT32_MAX);
@@ -1177,7 +1178,6 @@ PCIBus *gt64120_register(qemu_irq *pic)
&d->pci0_mem,
get_system_io(),
PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
- qdev_init_nofail(dev);
memory_region_init_io(&d->ISD_mem, OBJECT(dev), &isd_mem_ops, d, "isd-mem", 0x1000);
pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index 889cdc7ca..bdb716e72 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -334,8 +334,8 @@ static void mips_fulong2e_init(MachineState *machine)
}
/* Init internal devices */
- cpu_mips_irq_init_cpu(cpu);
- cpu_mips_clock_init(cpu);
+ cpu_mips_irq_init_cpu(env);
+ cpu_mips_clock_init(env);
/* North bridge, Bonito --> IP2 */
pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index 48192d22f..59081f9d1 100644
--- a/hw/mips/mips_int.c
+++ b/hw/mips/mips_int.c
@@ -58,9 +58,8 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
}
}
-void cpu_mips_irq_init_cpu(MIPSCPU *cpu)
+void cpu_mips_irq_init_cpu(CPUMIPSState *env)
{
- CPUMIPSState *env = &cpu->env;
qemu_irq *qi;
int i;
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 73f6c9fac..ac7c64125 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -201,8 +201,8 @@ static void mips_jazz_init(MachineState *machine,
}
/* Init CPU internal devices */
- cpu_mips_irq_init_cpu(cpu);
- cpu_mips_clock_init(cpu);
+ cpu_mips_irq_init_cpu(env);
+ cpu_mips_clock_init(env);
/* Chipset */
rc4030 = rc4030_init(&dmas, &rc4030_dma_mr);
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index e90857ee0..fa769e5c0 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -727,7 +727,7 @@ static void write_bootloader(uint8_t *base, int64_t run_addr,
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x0ff0021c); /* jal 870 */
stl_p(p++, 0x00000000); /* nop */
- stl_p(p++, 0x1000fff9); /* b 814 */
+ stl_p(p++, 0x08000205); /* j 814 */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x01a00009); /* jalr t5 */
stl_p(p++, 0x01602021); /* move a0,t3 */
@@ -923,10 +923,11 @@ static void create_cpu_without_cps(const char *cpu_model,
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
/* Init internal devices */
- cpu_mips_irq_init_cpu(cpu);
- cpu_mips_clock_init(cpu);
+ cpu_mips_irq_init_cpu(env);
+ cpu_mips_clock_init(env);
qemu_register_reset(main_cpu_reset, cpu);
}
@@ -955,7 +956,9 @@ static void create_cps(MaltaState *s, const char *cpu_model,
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->cps), 0, 0, 1);
- *i8259_irq = get_cps_irq(s->cps, 3);
+ /* FIXME: When GIC is present then we should use GIC's IRQ 3.
+ Until then CPS exposes CPU's IRQs thus use the default IRQ 2. */
+ *i8259_irq = get_cps_irq(s->cps, 2);
*cbus_irq = NULL;
}
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c
index 1b9119500..a2c2a1646 100644
--- a/hw/mips/mips_mipssim.c
+++ b/hw/mips/mips_mipssim.c
@@ -216,8 +216,8 @@ mips_mipssim_init(MachineState *machine)
}
/* Init CPU internal devices. */
- cpu_mips_irq_init_cpu(cpu);
- cpu_mips_clock_init(cpu);
+ cpu_mips_irq_init_cpu(env);
+ cpu_mips_clock_init(env);
/* Register 64 KB of ISA IO space at 0x1fd00000. */
memory_region_init_alias(isa, NULL, "isa_mmio",
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index 16a59c779..21aca981c 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -267,8 +267,8 @@ void mips_r4k_init(MachineState *machine)
}
/* Init CPU internal devices */
- cpu_mips_irq_init_cpu(cpu);
- cpu_mips_clock_init(cpu);
+ cpu_mips_irq_init_cpu(env);
+ cpu_mips_clock_init(env);
/* ISA bus: IO space at 0x14000000, mem space at 0x10000000 */
memory_region_init_alias(isa_io, NULL, "isa-io",
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4cfbd1024..93f952880 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -29,7 +29,6 @@ obj-$(CONFIG_IMX) += imx_ccm.o
obj-$(CONFIG_IMX) += imx31_ccm.o
obj-$(CONFIG_IMX) += imx25_ccm.o
obj-$(CONFIG_IMX) += imx6_ccm.o
-obj-$(CONFIG_IMX) += imx6_src.o
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
@@ -51,5 +50,3 @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
obj-$(CONFIG_EDU) += edu.o
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
-obj-$(CONFIG_AUX) += auxbus.o
-obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o
diff --git a/hw/misc/arm11scu.c b/hw/misc/arm11scu.c
index 7042ce11e..5e54b494b 100644
--- a/hw/misc/arm11scu.c
+++ b/hw/misc/arm11scu.c
@@ -10,7 +10,6 @@
#include "qemu/osdep.h"
#include "hw/misc/arm11scu.h"
-#include "qemu/log.h"
static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
unsigned size)
diff --git a/hw/misc/arm_integrator_debug.c b/hw/misc/arm_integrator_debug.c
index 8a5f29559..902605fef 100644
--- a/hw/misc/arm_integrator_debug.c
+++ b/hw/misc/arm_integrator_debug.c
@@ -19,7 +19,6 @@
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
#include "hw/misc/arm_integrator_debug.h"
-#include "qemu/log.h"
#define INTEGRATOR_DEBUG(obj) \
OBJECT_CHECK(IntegratorDebugState, (obj), TYPE_INTEGRATOR_DEBUG)
diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c
index 66a0787c4..7e179f1a4 100644
--- a/hw/misc/arm_l2x0.c
+++ b/hw/misc/arm_l2x0.c
@@ -20,7 +20,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
-#include "qemu/log.h"
/* L2C-310 r3p2 */
#define CACHE_ID 0x410000c8
@@ -159,14 +158,14 @@ static const MemoryRegionOps l2x0_mem_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void l2x0_priv_init(Object *obj)
+static int l2x0_priv_init(SysBusDevice *dev)
{
- L2x0State *s = ARM_L2X0(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ L2x0State *s = ARM_L2X0(dev);
- memory_region_init_io(&s->iomem, obj, &l2x0_mem_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(dev), &l2x0_mem_ops, s,
"l2x0_cc", 0x1000);
sysbus_init_mmio(dev, &s->iomem);
+ return 0;
}
static Property l2x0_properties[] = {
@@ -176,8 +175,10 @@ static Property l2x0_properties[] = {
static void l2x0_class_init(ObjectClass *klass, void *data)
{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
+ k->init = l2x0_priv_init;
dc->vmsd = &vmstate_l2x0;
dc->props = l2x0_properties;
dc->reset = l2x0_priv_reset;
@@ -187,7 +188,6 @@ static const TypeInfo l2x0_info = {
.name = TYPE_ARM_L2X0,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(L2x0State),
- .instance_init = l2x0_priv_init,
.class_init = l2x0_class_init,
};
diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c
index 852400870..34d90d523 100644
--- a/hw/misc/arm_sysctl.c
+++ b/hw/misc/arm_sysctl.c
@@ -14,7 +14,6 @@
#include "hw/sysbus.h"
#include "hw/arm/primecell.h"
#include "sysemu/sysemu.h"
-#include "qemu/log.h"
#define LOCK_VALUE 0xa05f
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
deleted file mode 100644
index c7e2c8263..000000000
--- a/hw/misc/aspeed_scu.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * 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.
- */
-
-#include "qemu/osdep.h"
-#include "hw/misc/aspeed_scu.h"
-#include "hw/qdev-properties.h"
-#include "qapi/error.h"
-#include "qapi/visitor.h"
-#include "qemu/bitops.h"
-#include "qemu/log.h"
-#include "trace.h"
-
-#define TO_REG(offset) ((offset) >> 2)
-
-#define PROT_KEY TO_REG(0x00)
-#define SYS_RST_CTRL TO_REG(0x04)
-#define CLK_SEL TO_REG(0x08)
-#define CLK_STOP_CTRL TO_REG(0x0C)
-#define FREQ_CNTR_CTRL TO_REG(0x10)
-#define FREQ_CNTR_EVAL TO_REG(0x14)
-#define IRQ_CTRL TO_REG(0x18)
-#define D2PLL_PARAM TO_REG(0x1C)
-#define MPLL_PARAM TO_REG(0x20)
-#define HPLL_PARAM TO_REG(0x24)
-#define FREQ_CNTR_RANGE TO_REG(0x28)
-#define MISC_CTRL1 TO_REG(0x2C)
-#define PCI_CTRL1 TO_REG(0x30)
-#define PCI_CTRL2 TO_REG(0x34)
-#define PCI_CTRL3 TO_REG(0x38)
-#define SYS_RST_STATUS TO_REG(0x3C)
-#define SOC_SCRATCH1 TO_REG(0x40)
-#define SOC_SCRATCH2 TO_REG(0x44)
-#define MAC_CLK_DELAY TO_REG(0x48)
-#define MISC_CTRL2 TO_REG(0x4C)
-#define VGA_SCRATCH1 TO_REG(0x50)
-#define VGA_SCRATCH2 TO_REG(0x54)
-#define VGA_SCRATCH3 TO_REG(0x58)
-#define VGA_SCRATCH4 TO_REG(0x5C)
-#define VGA_SCRATCH5 TO_REG(0x60)
-#define VGA_SCRATCH6 TO_REG(0x64)
-#define VGA_SCRATCH7 TO_REG(0x68)
-#define VGA_SCRATCH8 TO_REG(0x6C)
-#define HW_STRAP1 TO_REG(0x70)
-#define RNG_CTRL TO_REG(0x74)
-#define RNG_DATA TO_REG(0x78)
-#define SILICON_REV TO_REG(0x7C)
-#define PINMUX_CTRL1 TO_REG(0x80)
-#define PINMUX_CTRL2 TO_REG(0x84)
-#define PINMUX_CTRL3 TO_REG(0x88)
-#define PINMUX_CTRL4 TO_REG(0x8C)
-#define PINMUX_CTRL5 TO_REG(0x90)
-#define PINMUX_CTRL6 TO_REG(0x94)
-#define WDT_RST_CTRL TO_REG(0x9C)
-#define PINMUX_CTRL7 TO_REG(0xA0)
-#define PINMUX_CTRL8 TO_REG(0xA4)
-#define PINMUX_CTRL9 TO_REG(0xA8)
-#define WAKEUP_EN TO_REG(0xC0)
-#define WAKEUP_CTRL TO_REG(0xC4)
-#define HW_STRAP2 TO_REG(0xD0)
-#define FREE_CNTR4 TO_REG(0xE0)
-#define FREE_CNTR4_EXT TO_REG(0xE4)
-#define CPU2_CTRL TO_REG(0x100)
-#define CPU2_BASE_SEG1 TO_REG(0x104)
-#define CPU2_BASE_SEG2 TO_REG(0x108)
-#define CPU2_BASE_SEG3 TO_REG(0x10C)
-#define CPU2_BASE_SEG4 TO_REG(0x110)
-#define CPU2_BASE_SEG5 TO_REG(0x114)
-#define CPU2_CACHE_CTRL TO_REG(0x118)
-#define UART_HPLL_CLK TO_REG(0x160)
-#define PCIE_CTRL TO_REG(0x180)
-#define BMC_MMIO_CTRL TO_REG(0x184)
-#define RELOC_DECODE_BASE1 TO_REG(0x188)
-#define RELOC_DECODE_BASE2 TO_REG(0x18C)
-#define MAILBOX_DECODE_BASE TO_REG(0x190)
-#define SRAM_DECODE_BASE1 TO_REG(0x194)
-#define SRAM_DECODE_BASE2 TO_REG(0x198)
-#define BMC_REV TO_REG(0x19C)
-#define BMC_DEV_ID TO_REG(0x1A4)
-
-#define PROT_KEY_UNLOCK 0x1688A8A8
-#define SCU_IO_REGION_SIZE 0x20000
-
-static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
- [SYS_RST_CTRL] = 0xFFCFFEDCU,
- [CLK_SEL] = 0xF3F40000U,
- [CLK_STOP_CTRL] = 0x19FC3E8BU,
- [D2PLL_PARAM] = 0x00026108U,
- [MPLL_PARAM] = 0x00030291U,
- [HPLL_PARAM] = 0x00000291U,
- [MISC_CTRL1] = 0x00000010U,
- [PCI_CTRL1] = 0x20001A03U,
- [PCI_CTRL2] = 0x20001A03U,
- [PCI_CTRL3] = 0x04000030U,
- [SYS_RST_STATUS] = 0x00000001U,
- [SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
- [MISC_CTRL2] = 0x00000023U,
- [RNG_CTRL] = 0x0000000EU,
- [PINMUX_CTRL2] = 0x0000F000U,
- [PINMUX_CTRL3] = 0x01000000U,
- [PINMUX_CTRL4] = 0x000000FFU,
- [PINMUX_CTRL5] = 0x0000A000U,
- [WDT_RST_CTRL] = 0x003FFFF3U,
- [PINMUX_CTRL8] = 0xFFFF0000U,
- [PINMUX_CTRL9] = 0x000FFFFFU,
- [FREE_CNTR4] = 0x000000FFU,
- [FREE_CNTR4_EXT] = 0x000000FFU,
- [CPU2_BASE_SEG1] = 0x80000000U,
- [CPU2_BASE_SEG4] = 0x1E600000U,
- [CPU2_BASE_SEG5] = 0xC0000000U,
- [UART_HPLL_CLK] = 0x00001903U,
- [PCIE_CTRL] = 0x0000007BU,
- [BMC_DEV_ID] = 0x00002402U
-};
-
-static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
-{
- AspeedSCUState *s = ASPEED_SCU(opaque);
- int reg = TO_REG(offset);
-
- if (reg >= ARRAY_SIZE(s->regs)) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- return 0;
- }
-
- switch (reg) {
- case WAKEUP_EN:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Read of write-only offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- break;
- }
-
- return s->regs[reg];
-}
-
-static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data,
- unsigned size)
-{
- AspeedSCUState *s = ASPEED_SCU(opaque);
- int reg = TO_REG(offset);
-
- if (reg >= ARRAY_SIZE(s->regs)) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- return;
- }
-
- if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
- s->regs[PROT_KEY] != PROT_KEY_UNLOCK) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
- return;
- }
-
- trace_aspeed_scu_write(offset, size, data);
-
- switch (reg) {
- case FREQ_CNTR_EVAL:
- case VGA_SCRATCH1 ... VGA_SCRATCH8:
- case RNG_DATA:
- case SILICON_REV:
- case FREE_CNTR4:
- case FREE_CNTR4_EXT:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- return;
- }
-
- s->regs[reg] = data;
-}
-
-static const MemoryRegionOps aspeed_scu_ops = {
- .read = aspeed_scu_read,
- .write = aspeed_scu_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid.min_access_size = 4,
- .valid.max_access_size = 4,
- .valid.unaligned = false,
-};
-
-static void aspeed_scu_reset(DeviceState *dev)
-{
- AspeedSCUState *s = ASPEED_SCU(dev);
- const uint32_t *reset;
-
- switch (s->silicon_rev) {
- case AST2400_A0_SILICON_REV:
- reset = ast2400_a0_resets;
- break;
- default:
- g_assert_not_reached();
- }
-
- memcpy(s->regs, reset, sizeof(s->regs));
- s->regs[SILICON_REV] = s->silicon_rev;
- s->regs[HW_STRAP1] = s->hw_strap1;
- s->regs[HW_STRAP2] = s->hw_strap2;
-}
-
-static uint32_t aspeed_silicon_revs[] = { AST2400_A0_SILICON_REV, };
-
-bool is_supported_silicon_rev(uint32_t silicon_rev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(aspeed_silicon_revs); i++) {
- if (silicon_rev == aspeed_silicon_revs[i]) {
- return true;
- }
- }
-
- return false;
-}
-
-static void aspeed_scu_realize(DeviceState *dev, Error **errp)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- AspeedSCUState *s = ASPEED_SCU(dev);
-
- if (!is_supported_silicon_rev(s->silicon_rev)) {
- error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
- s->silicon_rev);
- return;
- }
-
- memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_scu_ops, s,
- TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE);
-
- sysbus_init_mmio(sbd, &s->iomem);
-}
-
-static const VMStateDescription vmstate_aspeed_scu = {
- .name = "aspeed.scu",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_SCU_NR_REGS),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static Property aspeed_scu_properties[] = {
- DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
- DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
- DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void aspeed_scu_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = aspeed_scu_realize;
- dc->reset = aspeed_scu_reset;
- dc->desc = "ASPEED System Control Unit";
- dc->vmsd = &vmstate_aspeed_scu;
- dc->props = aspeed_scu_properties;
-}
-
-static const TypeInfo aspeed_scu_info = {
- .name = TYPE_ASPEED_SCU,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(AspeedSCUState),
- .class_init = aspeed_scu_class_init,
-};
-
-static void aspeed_scu_register_types(void)
-{
- type_register_static(&aspeed_scu_info);
-}
-
-type_init(aspeed_scu_register_types);
diff --git a/hw/misc/auxbus.c b/hw/misc/auxbus.c
deleted file mode 100644
index e4a7ba41d..000000000
--- a/hw/misc/auxbus.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * auxbus.c
- *
- * Copyright 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/>.
- *
- */
-
-/*
- * This is an implementation of the AUX bus for VESA Display Port v1.1a.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "hw/misc/auxbus.h"
-#include "hw/i2c/i2c.h"
-#include "monitor/monitor.h"
-
-#ifndef DEBUG_AUX
-#define DEBUG_AUX 0
-#endif
-
-#define DPRINTF(fmt, ...) do { \
- if (DEBUG_AUX) { \
- qemu_log("aux: " fmt , ## __VA_ARGS__); \
- } \
-} while (0);
-
-#define TYPE_AUXTOI2C "aux-to-i2c-bridge"
-#define AUXTOI2C(obj) OBJECT_CHECK(AUXTOI2CState, (obj), TYPE_AUXTOI2C)
-
-static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent);
-static inline I2CBus *aux_bridge_get_i2c_bus(AUXTOI2CState *bridge);
-
-/* aux-bus implementation (internal not public) */
-static void aux_bus_class_init(ObjectClass *klass, void *data)
-{
- BusClass *k = BUS_CLASS(klass);
-
- /* AUXSlave has an MMIO so we need to change the way we print information
- * in monitor.
- */
- k->print_dev = aux_slave_dev_print;
-}
-
-AUXBus *aux_init_bus(DeviceState *parent, const char *name)
-{
- AUXBus *bus;
-
- bus = AUX_BUS(qbus_create(TYPE_AUX_BUS, parent, name));
- bus->bridge = AUXTOI2C(qdev_create(BUS(bus), TYPE_AUXTOI2C));
-
- /* Memory related. */
- bus->aux_io = g_malloc(sizeof(*bus->aux_io));
- memory_region_init(bus->aux_io, OBJECT(bus), "aux-io", (1 << 20));
- address_space_init(&bus->aux_addr_space, bus->aux_io, "aux-io");
- return bus;
-}
-
-static void aux_bus_map_device(AUXBus *bus, AUXSlave *dev, hwaddr addr)
-{
- memory_region_add_subregion(bus->aux_io, addr, dev->mmio);
-}
-
-static bool aux_bus_is_bridge(AUXBus *bus, DeviceState *dev)
-{
- return (dev == DEVICE(bus->bridge));
-}
-
-I2CBus *aux_get_i2c_bus(AUXBus *bus)
-{
- return aux_bridge_get_i2c_bus(bus->bridge);
-}
-
-AUXReply aux_request(AUXBus *bus, AUXCommand cmd, uint32_t address,
- uint8_t len, uint8_t *data)
-{
- AUXReply ret = AUX_NACK;
- I2CBus *i2c_bus = aux_get_i2c_bus(bus);
- size_t i;
- bool is_write = false;
-
- DPRINTF("request at address 0x%" PRIX32 ", command %u, len %u\n", address,
- cmd, len);
-
- switch (cmd) {
- /*
- * Forward the request on the AUX bus..
- */
- case WRITE_AUX:
- case READ_AUX:
- is_write = cmd == READ_AUX ? false : true;
- for (i = 0; i < len; i++) {
- if (!address_space_rw(&bus->aux_addr_space, address++,
- MEMTXATTRS_UNSPECIFIED, data++, 1,
- is_write)) {
- ret = AUX_I2C_ACK;
- } else {
- ret = AUX_NACK;
- break;
- }
- }
- break;
- /*
- * Classic I2C transactions..
- */
- case READ_I2C:
- case WRITE_I2C:
- is_write = cmd == READ_I2C ? false : true;
- if (i2c_bus_busy(i2c_bus)) {
- i2c_end_transfer(i2c_bus);
- }
-
- if (i2c_start_transfer(i2c_bus, address, is_write)) {
- ret = AUX_I2C_NACK;
- break;
- }
-
- ret = AUX_I2C_ACK;
- while (len > 0) {
- if (i2c_send_recv(i2c_bus, data++, is_write) < 0) {
- ret = AUX_I2C_NACK;
- break;
- }
- len--;
- }
- i2c_end_transfer(i2c_bus);
- break;
- /*
- * I2C MOT transactions.
- *
- * Here we send a start when:
- * - We didn't start transaction yet.
- * - We had a READ and we do a WRITE.
- * - We changed the address.
- */
- case WRITE_I2C_MOT:
- case READ_I2C_MOT:
- is_write = cmd == READ_I2C_MOT ? false : true;
- ret = AUX_I2C_NACK;
- if (!i2c_bus_busy(i2c_bus)) {
- /*
- * No transactions started..
- */
- if (i2c_start_transfer(i2c_bus, address, is_write)) {
- break;
- }
- } else if ((address != bus->last_i2c_address) ||
- (bus->last_transaction != cmd)) {
- /*
- * Transaction started but we need to restart..
- */
- i2c_end_transfer(i2c_bus);
- if (i2c_start_transfer(i2c_bus, address, is_write)) {
- break;
- }
- }
-
- bus->last_transaction = cmd;
- bus->last_i2c_address = address;
- while (len > 0) {
- if (i2c_send_recv(i2c_bus, data++, is_write) < 0) {
- i2c_end_transfer(i2c_bus);
- break;
- }
- len--;
- }
- if (len == 0) {
- ret = AUX_I2C_ACK;
- }
- break;
- default:
- DPRINTF("Not implemented!\n");
- return AUX_NACK;
- }
-
- DPRINTF("reply: %u\n", ret);
- return ret;
-}
-
-static const TypeInfo aux_bus_info = {
- .name = TYPE_AUX_BUS,
- .parent = TYPE_BUS,
- .instance_size = sizeof(AUXBus),
- .class_init = aux_bus_class_init
-};
-
-/* aux-i2c implementation (internal not public) */
-struct AUXTOI2CState {
- /*< private >*/
- DeviceState parent_obj;
-
- /*< public >*/
- I2CBus *i2c_bus;
-};
-
-static void aux_bridge_init(Object *obj)
-{
- AUXTOI2CState *s = AUXTOI2C(obj);
-
- s->i2c_bus = i2c_init_bus(DEVICE(obj), "aux-i2c");
-}
-
-static inline I2CBus *aux_bridge_get_i2c_bus(AUXTOI2CState *bridge)
-{
- return bridge->i2c_bus;
-}
-
-static const TypeInfo aux_to_i2c_type_info = {
- .name = TYPE_AUXTOI2C,
- .parent = TYPE_DEVICE,
- .instance_size = sizeof(AUXTOI2CState),
- .instance_init = aux_bridge_init
-};
-
-/* aux-slave implementation */
-static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent)
-{
- AUXBus *bus = AUX_BUS(qdev_get_parent_bus(dev));
- AUXSlave *s;
-
- /* Don't print anything if the device is I2C "bridge". */
- if (aux_bus_is_bridge(bus, dev)) {
- return;
- }
-
- s = AUX_SLAVE(dev);
-
- monitor_printf(mon, "%*smemory " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
- indent, "",
- object_property_get_int(OBJECT(s->mmio), "addr", NULL),
- memory_region_size(s->mmio));
-}
-
-DeviceState *aux_create_slave(AUXBus *bus, const char *type, uint32_t addr)
-{
- DeviceState *dev;
-
- dev = DEVICE(object_new(type));
- assert(dev);
- qdev_set_parent_bus(dev, &bus->qbus);
- qdev_init_nofail(dev);
- aux_bus_map_device(AUX_BUS(qdev_get_parent_bus(dev)), AUX_SLAVE(dev), addr);
- return dev;
-}
-
-void aux_init_mmio(AUXSlave *aux_slave, MemoryRegion *mmio)
-{
- assert(!aux_slave->mmio);
- aux_slave->mmio = mmio;
-}
-
-static void aux_slave_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *k = DEVICE_CLASS(klass);
-
- set_bit(DEVICE_CATEGORY_MISC, k->categories);
- k->bus_type = TYPE_AUX_BUS;
-}
-
-static const TypeInfo aux_slave_type_info = {
- .name = TYPE_AUX_SLAVE,
- .parent = TYPE_DEVICE,
- .instance_size = sizeof(AUXSlave),
- .abstract = true,
- .class_init = aux_slave_class_init,
-};
-
-static void aux_register_types(void)
-{
- type_register_static(&aux_bus_info);
- type_register_static(&aux_slave_type_info);
- type_register_static(&aux_to_i2c_type_info);
-}
-
-type_init(aux_register_types)
diff --git a/hw/misc/bcm2835_mbox.c b/hw/misc/bcm2835_mbox.c
index e97cc814a..263280fd4 100644
--- a/hw/misc/bcm2835_mbox.c
+++ b/hw/misc/bcm2835_mbox.c
@@ -11,7 +11,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/misc/bcm2835_mbox.h"
-#include "qemu/log.h"
#define MAIL0_PEEK 0x90
#define MAIL0_SENDER 0x94
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index 70eaafd32..530411f84 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -8,7 +8,6 @@
#include "hw/misc/bcm2835_property.h"
#include "hw/misc/bcm2835_mbox_defs.h"
#include "sysemu/dma.h"
-#include "qemu/log.h"
/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
@@ -22,8 +21,6 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
int n;
uint32_t offset, length, color;
uint32_t xres, yres, xoffset, yoffset, bpp, pixo, alpha;
- uint32_t tmp_xres, tmp_yres, tmp_xoffset, tmp_yoffset;
- uint32_t tmp_bpp, tmp_pixo, tmp_alpha;
uint32_t *newxres = NULL, *newyres = NULL, *newxoffset = NULL,
*newyoffset = NULL, *newbpp = NULL, *newpixo = NULL, *newalpha = NULL;
@@ -142,11 +139,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
case 0x00040001: /* Allocate buffer */
stl_le_phys(&s->dma_as, value + 12, s->fbdev->base);
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres;
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
- stl_le_phys(&s->dma_as, value + 16,
- tmp_xres * tmp_yres * tmp_bpp / 8);
+ stl_le_phys(&s->dma_as, value + 16, s->fbdev->size);
resplen = 8;
break;
case 0x00048001: /* Release buffer */
@@ -157,10 +150,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
break;
case 0x00040003: /* Get display width/height */
case 0x00040004:
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
- tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres;
- stl_le_phys(&s->dma_as, value + 12, tmp_xres);
- stl_le_phys(&s->dma_as, value + 16, tmp_yres);
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->xres);
+ stl_le_phys(&s->dma_as, value + 16, s->fbdev->yres);
resplen = 8;
break;
case 0x00044003: /* Test display width/height */
@@ -176,8 +167,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 8;
break;
case 0x00040005: /* Get depth */
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
- stl_le_phys(&s->dma_as, value + 12, tmp_bpp);
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->bpp);
resplen = 4;
break;
case 0x00044005: /* Test depth */
@@ -189,8 +179,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 4;
break;
case 0x00040006: /* Get pixel order */
- tmp_pixo = newpixo != NULL ? *newpixo : s->fbdev->pixo;
- stl_le_phys(&s->dma_as, value + 12, tmp_pixo);
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->pixo);
resplen = 4;
break;
case 0x00044006: /* Test pixel order */
@@ -202,8 +191,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 4;
break;
case 0x00040007: /* Get alpha */
- tmp_alpha = newalpha != NULL ? *newalpha : s->fbdev->alpha;
- stl_le_phys(&s->dma_as, value + 12, tmp_alpha);
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->alpha);
resplen = 4;
break;
case 0x00044007: /* Test pixel alpha */
@@ -215,16 +203,12 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 4;
break;
case 0x00040008: /* Get pitch */
- tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres;
- tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp;
- stl_le_phys(&s->dma_as, value + 12, tmp_xres * tmp_bpp / 8);
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->pitch);
resplen = 4;
break;
case 0x00040009: /* Get virtual offset */
- tmp_xoffset = newxoffset != NULL ? *newxoffset : s->fbdev->xoffset;
- tmp_yoffset = newyoffset != NULL ? *newyoffset : s->fbdev->yoffset;
- stl_le_phys(&s->dma_as, value + 12, tmp_xoffset);
- stl_le_phys(&s->dma_as, value + 16, tmp_yoffset);
+ stl_le_phys(&s->dma_as, value + 12, s->fbdev->xoffset);
+ stl_le_phys(&s->dma_as, value + 16, s->fbdev->yoffset);
resplen = 8;
break;
case 0x00044009: /* Test virtual offset */
diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
index e30dbc7d3..889abadfe 100644
--- a/hw/misc/exynos4210_pmu.c
+++ b/hw/misc/exynos4210_pmu.c
@@ -457,15 +457,15 @@ static void exynos4210_pmu_reset(DeviceState *dev)
}
}
-static void exynos4210_pmu_init(Object *obj)
+static int exynos4210_pmu_init(SysBusDevice *dev)
{
- Exynos4210PmuState *s = EXYNOS4210_PMU(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ Exynos4210PmuState *s = EXYNOS4210_PMU(dev);
/* memory mapping */
- memory_region_init_io(&s->iomem, obj, &exynos4210_pmu_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(dev), &exynos4210_pmu_ops, s,
"exynos4210.pmu", EXYNOS4210_PMU_REGS_MEM_SIZE);
sysbus_init_mmio(dev, &s->iomem);
+ return 0;
}
static const VMStateDescription exynos4210_pmu_vmstate = {
@@ -481,7 +481,9 @@ static const VMStateDescription exynos4210_pmu_vmstate = {
static void exynos4210_pmu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = exynos4210_pmu_init;
dc->reset = exynos4210_pmu_reset;
dc->vmsd = &exynos4210_pmu_vmstate;
}
@@ -490,7 +492,6 @@ static const TypeInfo exynos4210_pmu_info = {
.name = TYPE_EXYNOS4210_PMU,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210PmuState),
- .instance_init = exynos4210_pmu_init,
.class_init = exynos4210_pmu_class_init,
};
diff --git a/hw/misc/hyperv_testdev.c b/hw/misc/hyperv_testdev.c
index 6cae9e901..1883fd7f2 100644
--- a/hw/misc/hyperv_testdev.c
+++ b/hw/misc/hyperv_testdev.c
@@ -12,11 +12,11 @@
*/
#include "qemu/osdep.h"
-#include <linux/kvm.h>
#include "hw/hw.h"
#include "hw/qdev.h"
#include "hw/isa/isa.h"
#include "sysemu/kvm.h"
+#include "linux/kvm.h"
#include "target-i386/hyperv.h"
#include "kvm_i386.h"
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
index 5cd8c0a9a..225604d82 100644
--- a/hw/misc/imx25_ccm.c
+++ b/hw/misc/imx25_ccm.c
@@ -13,7 +13,6 @@
#include "qemu/osdep.h"
#include "hw/misc/imx25_ccm.h"
-#include "qemu/log.h"
#ifndef DEBUG_IMX25_CCM
#define DEBUG_IMX25_CCM 0
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
index 1c03e52c4..80c164716 100644
--- a/hw/misc/imx31_ccm.c
+++ b/hw/misc/imx31_ccm.c
@@ -13,7 +13,6 @@
#include "qemu/osdep.h"
#include "hw/misc/imx31_ccm.h"
-#include "qemu/log.h"
#define CKIH_FREQ 26000000 /* 26MHz crystal input */
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
index 17e15d4c9..4e1d49da6 100644
--- a/hw/misc/imx6_ccm.c
+++ b/hw/misc/imx6_ccm.c
@@ -12,7 +12,6 @@
#include "qemu/osdep.h"
#include "hw/misc/imx6_ccm.h"
-#include "qemu/log.h"
#ifndef DEBUG_IMX6_CCM
#define DEBUG_IMX6_CCM 0
@@ -371,12 +370,6 @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
case CLK_32k:
freq = CKIL_FREQ;
break;
- case CLK_HIGH:
- freq = 24000000;
- break;
- case CLK_HIGH_DIV:
- freq = 24000000 / 8;
- break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
TYPE_IMX6_CCM, __func__, clock);
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
deleted file mode 100644
index 8bb682957..000000000
--- a/hw/misc/imx6_src.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * IMX6 System Reset Controller
- *
- * Copyright (c) 2015 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.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/misc/imx6_src.h"
-#include "sysemu/sysemu.h"
-#include "qemu/bitops.h"
-#include "qemu/log.h"
-#include "arm-powerctl.h"
-
-#ifndef DEBUG_IMX6_SRC
-#define DEBUG_IMX6_SRC 0
-#endif
-
-#define DPRINTF(fmt, args...) \
- do { \
- if (DEBUG_IMX6_SRC) { \
- fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX6_SRC, \
- __func__, ##args); \
- } \
- } while (0)
-
-static char const *imx6_src_reg_name(uint32_t reg)
-{
- static char unknown[20];
-
- switch (reg) {
- case SRC_SCR:
- return "SRC_SCR";
- case SRC_SBMR1:
- return "SRC_SBMR1";
- case SRC_SRSR:
- return "SRC_SRSR";
- case SRC_SISR:
- return "SRC_SISR";
- case SRC_SIMR:
- return "SRC_SIMR";
- case SRC_SBMR2:
- return "SRC_SBMR2";
- case SRC_GPR1:
- return "SRC_GPR1";
- case SRC_GPR2:
- return "SRC_GPR2";
- case SRC_GPR3:
- return "SRC_GPR3";
- case SRC_GPR4:
- return "SRC_GPR4";
- case SRC_GPR5:
- return "SRC_GPR5";
- case SRC_GPR6:
- return "SRC_GPR6";
- case SRC_GPR7:
- return "SRC_GPR7";
- case SRC_GPR8:
- return "SRC_GPR8";
- case SRC_GPR9:
- return "SRC_GPR9";
- case SRC_GPR10:
- return "SRC_GPR10";
- default:
- sprintf(unknown, "%d ?", reg);
- return unknown;
- }
-}
-
-static const VMStateDescription vmstate_imx6_src = {
- .name = TYPE_IMX6_SRC,
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(regs, IMX6SRCState, SRC_MAX),
- VMSTATE_END_OF_LIST()
- },
-};
-
-static void imx6_src_reset(DeviceState *dev)
-{
- IMX6SRCState *s = IMX6_SRC(dev);
-
- DPRINTF("\n");
-
- memset(s->regs, 0, sizeof(s->regs));
-
- /* Set reset values */
- s->regs[SRC_SCR] = 0x521;
- s->regs[SRC_SRSR] = 0x1;
- s->regs[SRC_SIMR] = 0x1F;
-}
-
-static uint64_t imx6_src_read(void *opaque, hwaddr offset, unsigned size)
-{
- uint32_t value = 0;
- IMX6SRCState *s = (IMX6SRCState *)opaque;
- uint32_t index = offset >> 2;
-
- if (index < SRC_MAX) {
- value = s->regs[index];
- } else {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset);
-
- }
-
- DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx6_src_reg_name(index), value);
-
- return value;
-}
-
-static void imx6_src_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- IMX6SRCState *s = (IMX6SRCState *)opaque;
- uint32_t index = offset >> 2;
- unsigned long change_mask;
- unsigned long current_value = value;
-
- if (index >= SRC_MAX) {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset);
- return;
- }
-
- DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx6_src_reg_name(index),
- (uint32_t)current_value);
-
- change_mask = s->regs[index] ^ (uint32_t)current_value;
-
- switch (index) {
- case SRC_SCR:
- /*
- * On real hardware when the system reset controller starts a
- * secondary CPU it runs through some boot ROM code which reads
- * the SRC_GPRX registers controlling the start address and branches
- * to it.
- * Here we are taking a short cut and branching directly to the
- * requested address (we don't want to run the boot ROM code inside
- * QEMU)
- */
- if (EXTRACT(change_mask, CORE3_ENABLE)) {
- if (EXTRACT(current_value, CORE3_ENABLE)) {
- /* CORE 3 is brought up */
- arm_set_cpu_on(3, s->regs[SRC_GPR7], s->regs[SRC_GPR8],
- 3, false);
- } else {
- /* CORE 3 is shut down */
- arm_set_cpu_off(3);
- }
- /* We clear the reset bits as the processor changed state */
- clear_bit(CORE3_RST_SHIFT, &current_value);
- clear_bit(CORE3_RST_SHIFT, &change_mask);
- }
- if (EXTRACT(change_mask, CORE2_ENABLE)) {
- if (EXTRACT(current_value, CORE2_ENABLE)) {
- /* CORE 2 is brought up */
- arm_set_cpu_on(2, s->regs[SRC_GPR5], s->regs[SRC_GPR6],
- 3, false);
- } else {
- /* CORE 3 is shut down */
- arm_set_cpu_off(2);
- }
- /* We clear the reset bits as the processor changed state */
- clear_bit(CORE2_RST_SHIFT, &current_value);
- clear_bit(CORE2_RST_SHIFT, &change_mask);
- }
- if (EXTRACT(change_mask, CORE1_ENABLE)) {
- if (EXTRACT(current_value, CORE1_ENABLE)) {
- /* CORE 1 is brought up */
- arm_set_cpu_on(1, s->regs[SRC_GPR3], s->regs[SRC_GPR4],
- 3, false);
- } else {
- /* CORE 3 is shut down */
- arm_set_cpu_off(1);
- }
- /* We clear the reset bits as the processor changed state */
- clear_bit(CORE1_RST_SHIFT, &current_value);
- clear_bit(CORE1_RST_SHIFT, &change_mask);
- }
- if (EXTRACT(change_mask, CORE0_RST)) {
- arm_reset_cpu(0);
- clear_bit(CORE0_RST_SHIFT, &current_value);
- }
- if (EXTRACT(change_mask, CORE1_RST)) {
- arm_reset_cpu(1);
- clear_bit(CORE1_RST_SHIFT, &current_value);
- }
- if (EXTRACT(change_mask, CORE2_RST)) {
- arm_reset_cpu(2);
- clear_bit(CORE2_RST_SHIFT, &current_value);
- }
- if (EXTRACT(change_mask, CORE3_RST)) {
- arm_reset_cpu(3);
- clear_bit(CORE3_RST_SHIFT, &current_value);
- }
- if (EXTRACT(change_mask, SW_IPU2_RST)) {
- /* We pretend the IPU2 is reset */
- clear_bit(SW_IPU2_RST_SHIFT, &current_value);
- }
- if (EXTRACT(change_mask, SW_IPU1_RST)) {
- /* We pretend the IPU1 is reset */
- clear_bit(SW_IPU1_RST_SHIFT, &current_value);
- }
- s->regs[index] = current_value;
- break;
- default:
- s->regs[index] = current_value;
- break;
- }
-}
-
-static const struct MemoryRegionOps imx6_src_ops = {
- .read = imx6_src_read,
- .write = imx6_src_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- /*
- * Our device would not work correctly if the guest was doing
- * unaligned access. This might not be a limitation on the real
- * device but in practice there is no reason for a guest to access
- * this device unaligned.
- */
- .min_access_size = 4,
- .max_access_size = 4,
- .unaligned = false,
- },
-};
-
-static void imx6_src_realize(DeviceState *dev, Error **errp)
-{
- IMX6SRCState *s = IMX6_SRC(dev);
-
- memory_region_init_io(&s->iomem, OBJECT(dev), &imx6_src_ops, s,
- TYPE_IMX6_SRC, 0x1000);
- sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
-}
-
-static void imx6_src_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = imx6_src_realize;
- dc->reset = imx6_src_reset;
- dc->vmsd = &vmstate_imx6_src;
- dc->desc = "i.MX6 System Reset Controller";
-}
-
-static const TypeInfo imx6_src_info = {
- .name = TYPE_IMX6_SRC,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(IMX6SRCState),
- .class_init = imx6_src_class_init,
-};
-
-static void imx6_src_register_types(void)
-{
- type_register_static(&imx6_src_info);
-}
-
-type_init(imx6_src_register_types)
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
index 7f239a41d..986d890ca 100644
--- a/hw/misc/imx_ccm.c
+++ b/hw/misc/imx_ccm.c
@@ -13,7 +13,6 @@
#include "qemu/osdep.h"
#include "hw/misc/imx_ccm.h"
-#include "qemu/log.h"
#ifndef DEBUG_IMX_CCM
#define DEBUG_IMX_CCM 0
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 40a2ebca2..e40f23bfc 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -33,9 +33,12 @@
#include "sysemu/hostmem.h"
#include "sysemu/qtest.h"
#include "qapi/visitor.h"
+#include "exec/ram_addr.h"
#include "hw/misc/ivshmem.h"
+#include <sys/mman.h>
+
#define PCI_VENDOR_ID_IVSHMEM PCI_VENDOR_ID_REDHAT_QUMRANET
#define PCI_DEVICE_ID_IVSHMEM 0x1110
@@ -322,7 +325,6 @@ static int ivshmem_vector_unmask(PCIDevice *dev, unsigned vector,
if (ret < 0) {
return ret;
}
- kvm_irqchip_commit_routes(kvm_state);
return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, v->virq);
}
@@ -442,12 +444,13 @@ static void ivshmem_add_kvm_msi_virq(IVShmemState *s, int vector,
Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(s);
+ MSIMessage msg = msix_get_message(pdev, vector);
int ret;
IVSHMEM_DPRINTF("ivshmem_add_kvm_msi_virq vector:%d\n", vector);
assert(!s->msi_vectors[vector].pdev);
- ret = kvm_irqchip_add_msi_route(kvm_state, vector, pdev);
+ ret = kvm_irqchip_add_msi_route(kvm_state, msg, pdev);
if (ret < 0) {
error_setg(errp, "kvm_irqchip_add_msi_route failed");
return;
@@ -530,7 +533,7 @@ static void process_msg_shmem(IVShmemState *s, int fd, Error **errp)
}
memory_region_init_ram_ptr(&s->server_bar2, OBJECT(s),
"ivshmem.bar2", size, ptr);
- memory_region_set_fd(&s->server_bar2, fd);
+ qemu_set_ram_fd(memory_region_get_ram_addr(&s->server_bar2), fd);
s->ivshmem_bar2 = &s->server_bar2;
}
@@ -937,7 +940,7 @@ static void ivshmem_exit(PCIDevice *dev)
strerror(errno));
}
- fd = memory_region_get_fd(s->ivshmem_bar2);
+ fd = qemu_get_ram_fd(memory_region_get_ram_addr(s->ivshmem_bar2));
close(fd);
}
@@ -1008,7 +1011,10 @@ static const TypeInfo ivshmem_common_info = {
static void ivshmem_check_memdev_is_busy(Object *obj, const char *name,
Object *val, Error **errp)
{
- if (host_memory_backend_is_mapped(MEMORY_BACKEND(val))) {
+ MemoryRegion *mr;
+
+ mr = host_memory_backend_get_memory(MEMORY_BACKEND(val), &error_abort);
+ if (memory_region_is_mapped(mr)) {
char *path = object_get_canonical_path_component(val);
error_setg(errp, "can't use already busy memdev: %s", path);
g_free(path);
@@ -1057,14 +1063,6 @@ static void ivshmem_plain_realize(PCIDevice *dev, Error **errp)
}
ivshmem_common_realize(dev, errp);
- host_memory_backend_set_mapped(s->hostmem, true);
-}
-
-static void ivshmem_plain_exit(PCIDevice *pci_dev)
-{
- IVShmemState *s = IVSHMEM_COMMON(pci_dev);
-
- host_memory_backend_set_mapped(s->hostmem, false);
}
static void ivshmem_plain_class_init(ObjectClass *klass, void *data)
@@ -1073,7 +1071,6 @@ static void ivshmem_plain_class_init(ObjectClass *klass, void *data)
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->realize = ivshmem_plain_realize;
- k->exit = ivshmem_plain_exit;
dc->props = ivshmem_plain_properties;
dc->vmsd = &ivshmem_plain_vmsd;
}
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index 05c02fb3a..f15f30110 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -29,7 +29,6 @@
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
#include "qemu/cutils.h"
-#include "qemu/log.h"
/* XXX: implement all timer modes */
diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
index 15452b9a2..6051f17db 100644
--- a/hw/misc/macio/mac_dbdma.c
+++ b/hw/misc/macio/mac_dbdma.c
@@ -41,26 +41,16 @@
#include "hw/isa/isa.h"
#include "hw/ppc/mac_dbdma.h"
#include "qemu/main-loop.h"
-#include "qemu/log.h"
-#include "sysemu/dma.h"
/* debug DBDMA */
-#define DEBUG_DBDMA 0
-#define DEBUG_DBDMA_CHANMASK ((1ull << DBDMA_CHANNELS) - 1)
-
-#define DBDMA_DPRINTF(fmt, ...) do { \
- if (DEBUG_DBDMA) { \
- printf("DBDMA: " fmt , ## __VA_ARGS__); \
- } \
-} while (0);
-
-#define DBDMA_DPRINTFCH(ch, fmt, ...) do { \
- if (DEBUG_DBDMA) { \
- if ((1ul << (ch)->channel) & DEBUG_DBDMA_CHANMASK) { \
- printf("DBDMA[%02x]: " fmt , (ch)->channel, ## __VA_ARGS__); \
- } \
- } \
-} while (0);
+//#define DEBUG_DBDMA
+
+#ifdef DEBUG_DBDMA
+#define DBDMA_DPRINTF(fmt, ...) \
+ do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DBDMA_DPRINTF(fmt, ...)
+#endif
/*
*/
@@ -70,7 +60,7 @@ static DBDMAState *dbdma_from_ch(DBDMA_channel *ch)
return container_of(ch, DBDMAState, channels[ch->channel]);
}
-#if DEBUG_DBDMA
+#ifdef DEBUG_DBDMA
static void dump_dbdma_cmd(dbdma_cmd *cmd)
{
printf("dbdma_cmd %p\n", cmd);
@@ -88,26 +78,26 @@ static void dump_dbdma_cmd(dbdma_cmd *cmd)
#endif
static void dbdma_cmdptr_load(DBDMA_channel *ch)
{
- DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_load 0x%08x\n",
- ch->regs[DBDMA_CMDPTR_LO]);
- dma_memory_read(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
- &ch->current, sizeof(dbdma_cmd));
+ DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
+ ch->regs[DBDMA_CMDPTR_LO]);
+ cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO],
+ &ch->current, sizeof(dbdma_cmd));
}
static void dbdma_cmdptr_save(DBDMA_channel *ch)
{
- DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_save 0x%08x\n",
- ch->regs[DBDMA_CMDPTR_LO]);
- DBDMA_DPRINTFCH(ch, "xfer_status 0x%08x res_count 0x%04x\n",
- le16_to_cpu(ch->current.xfer_status),
- le16_to_cpu(ch->current.res_count));
- dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
- &ch->current, sizeof(dbdma_cmd));
+ DBDMA_DPRINTF("dbdma_cmdptr_save 0x%08x\n",
+ ch->regs[DBDMA_CMDPTR_LO]);
+ DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n",
+ le16_to_cpu(ch->current.xfer_status),
+ le16_to_cpu(ch->current.res_count));
+ cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO],
+ &ch->current, sizeof(dbdma_cmd));
}
static void kill_channel(DBDMA_channel *ch)
{
- DBDMA_DPRINTFCH(ch, "kill_channel\n");
+ DBDMA_DPRINTF("kill_channel\n");
ch->regs[DBDMA_STATUS] |= DEAD;
ch->regs[DBDMA_STATUS] &= ~ACTIVE;
@@ -123,7 +113,7 @@ static void conditional_interrupt(DBDMA_channel *ch)
uint32_t status;
int cond;
- DBDMA_DPRINTFCH(ch, "%s\n", __func__);
+ DBDMA_DPRINTF("%s\n", __func__);
intr = le16_to_cpu(current->command) & INTR_MASK;
@@ -132,7 +122,7 @@ static void conditional_interrupt(DBDMA_channel *ch)
return;
case INTR_ALWAYS: /* always interrupt */
qemu_irq_raise(ch->irq);
- DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__);
+ DBDMA_DPRINTF("%s: raise\n", __func__);
return;
}
@@ -147,13 +137,13 @@ static void conditional_interrupt(DBDMA_channel *ch)
case INTR_IFSET: /* intr if condition bit is 1 */
if (cond) {
qemu_irq_raise(ch->irq);
- DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__);
+ DBDMA_DPRINTF("%s: raise\n", __func__);
}
return;
case INTR_IFCLR: /* intr if condition bit is 0 */
if (!cond) {
qemu_irq_raise(ch->irq);
- DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__);
+ DBDMA_DPRINTF("%s: raise\n", __func__);
}
return;
}
@@ -167,7 +157,7 @@ static int conditional_wait(DBDMA_channel *ch)
uint32_t status;
int cond;
- DBDMA_DPRINTFCH(ch, "conditional_wait\n");
+ DBDMA_DPRINTF("conditional_wait\n");
wait = le16_to_cpu(current->command) & WAIT_MASK;
@@ -213,7 +203,7 @@ static void branch(DBDMA_channel *ch)
{
dbdma_cmd *current = &ch->current;
- ch->regs[DBDMA_CMDPTR_LO] = le32_to_cpu(current->cmd_dep);
+ ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep;
ch->regs[DBDMA_STATUS] |= BT;
dbdma_cmdptr_load(ch);
}
@@ -226,7 +216,7 @@ static void conditional_branch(DBDMA_channel *ch)
uint32_t status;
int cond;
- DBDMA_DPRINTFCH(ch, "conditional_branch\n");
+ DBDMA_DPRINTF("conditional_branch\n");
/* check if we must branch */
@@ -271,7 +261,7 @@ static void dbdma_end(DBDMA_io *io)
DBDMA_channel *ch = io->channel;
dbdma_cmd *current = &ch->current;
- DBDMA_DPRINTFCH(ch, "%s\n", __func__);
+ DBDMA_DPRINTF("%s\n", __func__);
if (conditional_wait(ch))
goto wait;
@@ -297,13 +287,13 @@ wait:
static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
uint16_t req_count, int is_last)
{
- DBDMA_DPRINTFCH(ch, "start_output\n");
+ DBDMA_DPRINTF("start_output\n");
/* KEY_REGS, KEY_DEVICE and KEY_STREAM
* are not implemented in the mac-io chip
*/
- DBDMA_DPRINTFCH(ch, "addr 0x%x key 0x%x\n", addr, key);
+ DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
if (!addr || key > KEY_STREAM3) {
kill_channel(ch);
return;
@@ -323,13 +313,13 @@ static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
uint16_t req_count, int is_last)
{
- DBDMA_DPRINTFCH(ch, "start_input\n");
+ DBDMA_DPRINTF("start_input\n");
/* KEY_REGS, KEY_DEVICE and KEY_STREAM
* are not implemented in the mac-io chip
*/
- DBDMA_DPRINTFCH(ch, "addr 0x%x key 0x%x\n", addr, key);
+ DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
if (!addr || key > KEY_STREAM3) {
kill_channel(ch);
return;
@@ -350,8 +340,9 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
uint16_t len)
{
dbdma_cmd *current = &ch->current;
+ uint32_t val;
- DBDMA_DPRINTFCH(ch, "load_word %d bytes, addr=%08x\n", len, addr);
+ DBDMA_DPRINTF("load_word\n");
/* only implements KEY_SYSTEM */
@@ -361,7 +352,14 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
return;
}
- dma_memory_read(&address_space_memory, addr, &current->cmd_dep, len);
+ cpu_physical_memory_read(addr, &val, len);
+
+ if (len == 2)
+ val = (val << 16) | (current->cmd_dep & 0x0000ffff);
+ else if (len == 1)
+ val = (val << 24) | (current->cmd_dep & 0x00ffffff);
+
+ current->cmd_dep = val;
if (conditional_wait(ch))
goto wait;
@@ -381,9 +379,9 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
uint16_t len)
{
dbdma_cmd *current = &ch->current;
+ uint32_t val;
- DBDMA_DPRINTFCH(ch, "store_word %d bytes, addr=%08x pa=%x\n",
- len, addr, le32_to_cpu(current->cmd_dep));
+ DBDMA_DPRINTF("store_word\n");
/* only implements KEY_SYSTEM */
@@ -393,7 +391,13 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
return;
}
- dma_memory_write(&address_space_memory, addr, &current->cmd_dep, len);
+ val = current->cmd_dep;
+ if (len == 2)
+ val >>= 16;
+ else if (len == 1)
+ val >>= 24;
+
+ cpu_physical_memory_write(addr, &val, len);
if (conditional_wait(ch))
goto wait;
@@ -440,7 +444,7 @@ static void channel_run(DBDMA_channel *ch)
uint16_t req_count;
uint32_t phy_addr;
- DBDMA_DPRINTFCH(ch, "channel_run\n");
+ DBDMA_DPRINTF("channel_run\n");
dump_dbdma_cmd(current);
/* clear WAKE flag at command fetch */
@@ -534,9 +538,9 @@ static void DBDMA_run_bh(void *opaque)
{
DBDMAState *s = opaque;
- DBDMA_DPRINTF("-> DBDMA_run_bh\n");
+ DBDMA_DPRINTF("DBDMA_run_bh\n");
+
DBDMA_run(s);
- DBDMA_DPRINTF("<- DBDMA_run_bh\n");
}
void DBDMA_kick(DBDMAState *dbdma)
@@ -551,7 +555,7 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
DBDMAState *s = dbdma;
DBDMA_channel *ch = &s->channels[nchan];
- DBDMA_DPRINTFCH(ch, "DBDMA_register_channel 0x%x\n", nchan);
+ DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
assert(rw);
assert(flush);
@@ -595,7 +599,7 @@ dbdma_control_write(DBDMA_channel *ch)
status &= ~FLUSH;
}
- DBDMA_DPRINTFCH(ch, " status 0x%08x\n", status);
+ DBDMA_DPRINTF(" status 0x%08x\n", status);
ch->regs[DBDMA_STATUS] = status;
@@ -612,10 +616,10 @@ static void dbdma_write(void *opaque, hwaddr addr,
DBDMA_channel *ch = &s->channels[channel];
int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
- DBDMA_DPRINTFCH(ch, "writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n",
- addr, value);
- DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
- (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
+ DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n",
+ addr, value);
+ DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
+ (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
/* cmdptr cannot be modified if channel is ACTIVE */
@@ -666,9 +670,9 @@ static uint64_t dbdma_read(void *opaque, hwaddr addr,
value = ch->regs[reg];
- DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
- DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
- (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
+ DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
+ DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
+ (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
switch(reg) {
case DBDMA_CONTROL:
@@ -778,24 +782,13 @@ static void dbdma_unassigned_rw(DBDMA_io *io)
DBDMA_channel *ch = io->channel;
qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
__func__, ch->channel);
- ch->io.processing = false;
}
static void dbdma_unassigned_flush(DBDMA_io *io)
{
DBDMA_channel *ch = io->channel;
- dbdma_cmd *current = &ch->current;
- uint16_t cmd;
qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
__func__, ch->channel);
-
- cmd = le16_to_cpu(current->command) & COMMAND_MASK;
- if (cmd == OUTPUT_MORE || cmd == OUTPUT_LAST ||
- cmd == INPUT_MORE || cmd == INPUT_LAST) {
- current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS] | FLUSH);
- current->res_count = cpu_to_le16(io->len);
- dbdma_cmdptr_save(ch);
- }
}
void* DBDMA_init (MemoryRegion **dbdma_mem)
diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c
index 2a277bdb8..9014f0f70 100644
--- a/hw/misc/max111x.c
+++ b/hw/misc/max111x.c
@@ -147,14 +147,14 @@ static int max111x_init(SSISlave *d, int inputs)
return 0;
}
-static void max1110_realize(SSISlave *dev, Error **errp)
+static int max1110_init(SSISlave *dev)
{
- max111x_init(dev, 8);
+ return max111x_init(dev, 8);
}
-static void max1111_realize(SSISlave *dev, Error **errp)
+static int max1111_init(SSISlave *dev)
{
- max111x_init(dev, 4);
+ return max111x_init(dev, 4);
}
void max111x_set_input(DeviceState *dev, int line, uint8_t value)
@@ -183,7 +183,7 @@ static void max1110_class_init(ObjectClass *klass, void *data)
{
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
- k->realize = max1110_realize;
+ k->init = max1110_init;
}
static const TypeInfo max1110_info = {
@@ -196,7 +196,7 @@ static void max1111_class_init(ObjectClass *klass, void *data)
{
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
- k->realize = max1111_realize;
+ k->init = max1111_init;
}
static const TypeInfo max1111_info = {
diff --git a/hw/misc/milkymist-hpdmc.c b/hw/misc/milkymist-hpdmc.c
index e6140eec6..b97000fc4 100644
--- a/hw/misc/milkymist-hpdmc.c
+++ b/hw/misc/milkymist-hpdmc.c
@@ -18,7 +18,7 @@
*
*
* Specification available at:
- * http://milkymist.walle.cc/socdoc/hpdmc.pdf
+ * http://www.milkymist.org/socdoc/hpdmc.pdf
*/
#include "qemu/osdep.h"
diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c
index 1da21a643..57acd7b36 100644
--- a/hw/misc/milkymist-pfpu.c
+++ b/hw/misc/milkymist-pfpu.c
@@ -18,7 +18,7 @@
*
*
* Specification available at:
- * http://milkymist.walle.cc/socdoc/pfpu.pdf
+ * http://www.milkymist.org/socdoc/pfpu.pdf
*
*/
diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c
index b3ba16694..37be23995 100644
--- a/hw/misc/mips_cmgcr.c
+++ b/hw/misc/mips_cmgcr.c
@@ -11,24 +11,17 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu/log.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
#include "hw/misc/mips_cmgcr.h"
#include "hw/misc/mips_cpc.h"
-#include "hw/intc/mips_gic.h"
static inline bool is_cpc_connected(MIPSGCRState *s)
{
return s->cpc_mr != NULL;
}
-static inline bool is_gic_connected(MIPSGCRState *s)
-{
- return s->gic_mr != NULL;
-}
-
static inline void update_cpc_base(MIPSGCRState *gcr, uint64_t val)
{
if (is_cpc_connected(gcr)) {
@@ -42,25 +35,10 @@ static inline void update_cpc_base(MIPSGCRState *gcr, uint64_t val)
}
}
-static inline void update_gic_base(MIPSGCRState *gcr, uint64_t val)
-{
- if (is_gic_connected(gcr)) {
- gcr->gic_base = val & GCR_GIC_BASE_MSK;
- memory_region_transaction_begin();
- memory_region_set_address(gcr->gic_mr,
- gcr->gic_base & GCR_GIC_BASE_GICBASE_MSK);
- memory_region_set_enabled(gcr->gic_mr,
- gcr->gic_base & GCR_GIC_BASE_GICEN_MSK);
- memory_region_transaction_commit();
- }
-}
-
/* Read GCR registers */
static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size)
{
MIPSGCRState *gcr = (MIPSGCRState *) opaque;
- MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index];
- MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other];
switch (addr) {
/* Global Control Block Register */
@@ -71,12 +49,8 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size)
return gcr->gcr_base;
case GCR_REV_OFS:
return gcr->gcr_rev;
- case GCR_GIC_BASE_OFS:
- return gcr->gic_base;
case GCR_CPC_BASE_OFS:
return gcr->cpc_base;
- case GCR_GIC_STATUS_OFS:
- return is_gic_connected(gcr);
case GCR_CPC_STATUS_OFS:
return is_cpc_connected(gcr);
case GCR_L2_CONFIG_OFS:
@@ -87,14 +61,8 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size)
case MIPS_COCB_OFS + GCR_CL_CONFIG_OFS:
/* Set PVP to # of VPs - 1 */
return gcr->num_vps - 1;
- case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS:
- return current_vps->reset_base;
- case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS:
- return other_vps->reset_base;
case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS:
- return current_vps->other;
- case MIPS_COCB_OFS + GCR_CL_OTHER_OFS:
- return other_vps->other;
+ return 0;
default:
qemu_log_mask(LOG_UNIMP, "Read %d bytes at GCR offset 0x%" HWADDR_PRIx
"\n", size, addr);
@@ -103,46 +71,15 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size)
return 0;
}
-static inline target_ulong get_exception_base(MIPSGCRVPState *vps)
-{
- /* TODO: BEV_BASE and SELECT_BEV */
- return (int32_t)(vps->reset_base & GCR_CL_RESET_BASE_RESETBASE_MSK);
-}
-
/* Write GCR registers */
static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
{
MIPSGCRState *gcr = (MIPSGCRState *)opaque;
- MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index];
- MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other];
switch (addr) {
- case GCR_GIC_BASE_OFS:
- update_gic_base(gcr, data);
- break;
case GCR_CPC_BASE_OFS:
update_cpc_base(gcr, data);
break;
- case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS:
- current_vps->reset_base = data & GCR_CL_RESET_BASE_MSK;
- cpu_set_exception_base(current_cpu->cpu_index,
- get_exception_base(current_vps));
- break;
- case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS:
- other_vps->reset_base = data & GCR_CL_RESET_BASE_MSK;
- cpu_set_exception_base(current_vps->other,
- get_exception_base(other_vps));
- break;
- case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS:
- if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) {
- current_vps->other = data & GCR_CL_OTHER_MSK;
- }
- break;
- case MIPS_COCB_OFS + GCR_CL_OTHER_OFS:
- if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) {
- other_vps->other = data & GCR_CL_OTHER_MSK;
- }
- break;
default:
qemu_log_mask(LOG_UNIMP, "Write %d bytes at GCR offset 0x%" HWADDR_PRIx
" 0x%" PRIx64 "\n", size, addr, data);
@@ -164,12 +101,6 @@ static void mips_gcr_init(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
MIPSGCRState *s = MIPS_GCR(obj);
- object_property_add_link(obj, "gic", TYPE_MEMORY_REGION,
- (Object **)&s->gic_mr,
- qdev_prop_allow_set_link_before_realize,
- OBJ_PROP_LINK_UNREF_ON_RELEASE,
- &error_abort);
-
object_property_add_link(obj, "cpc", TYPE_MEMORY_REGION,
(Object **)&s->cpc_mr,
qdev_prop_allow_set_link_before_realize,
@@ -184,16 +115,8 @@ static void mips_gcr_init(Object *obj)
static void mips_gcr_reset(DeviceState *dev)
{
MIPSGCRState *s = MIPS_GCR(dev);
- int i;
- update_gic_base(s, 0);
update_cpc_base(s, 0);
-
- for (i = 0; i < s->num_vps; i++) {
- s->vps[i].other = 0;
- s->vps[i].reset_base = 0xBFC00000 & GCR_CL_RESET_BASE_MSK;
- cpu_set_exception_base(i, get_exception_base(&s->vps[i]));
- }
}
static const VMStateDescription vmstate_mips_gcr = {
@@ -213,21 +136,12 @@ static Property mips_gcr_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-static void mips_gcr_realize(DeviceState *dev, Error **errp)
-{
- MIPSGCRState *s = MIPS_GCR(dev);
-
- /* Create local set of registers for each VP */
- s->vps = g_new(MIPSGCRVPState, s->num_vps);
-}
-
static void mips_gcr_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->props = mips_gcr_properties;
dc->vmsd = &vmstate_mips_gcr;
dc->reset = mips_gcr_reset;
- dc->realize = mips_gcr_realize;
}
static const TypeInfo mips_gcr_info = {
diff --git a/hw/misc/mips_cpc.c b/hw/misc/mips_cpc.c
index 6d345745f..d2b8e42da 100644
--- a/hw/misc/mips_cpc.c
+++ b/hw/misc/mips_cpc.c
@@ -19,8 +19,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "cpu.h"
-#include "qemu/log.h"
#include "hw/sysbus.h"
#include "hw/misc/mips_cpc.h"
@@ -37,7 +35,7 @@ static void cpc_run_vp(MIPSCPCState *cpc, uint64_t vp_run)
CPU_FOREACH(cs) {
uint64_t i = 1ULL << cs->cpu_index;
if (i & vp_run & ~cpc->vp_running) {
- cpu_reset(cs);
+ cpu_interrupt(cs, CPU_INTERRUPT_WAKE);
cpc->vp_running |= i;
}
}
@@ -50,7 +48,8 @@ static void cpc_stop_vp(MIPSCPCState *cpc, uint64_t vp_stop)
CPU_FOREACH(cs) {
uint64_t i = 1ULL << cs->cpu_index;
if (i & vp_stop & cpc->vp_running) {
- cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+ cs->halted = 1;
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
cpc->vp_running &= ~i;
}
}
diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
index ef935b51a..da5455062 100644
--- a/hw/misc/mips_itu.c
+++ b/hw/misc/mips_itu.c
@@ -19,9 +19,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "cpu.h"
-#include "qemu/log.h"
-#include "exec/exec-all.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
diff --git a/hw/misc/mst_fpga.c b/hw/misc/mst_fpga.c
index a10f0496f..48d7dfb2d 100644
--- a/hw/misc/mst_fpga.c
+++ b/hw/misc/mst_fpga.c
@@ -200,11 +200,10 @@ static int mst_fpga_post_load(void *opaque, int version_id)
return 0;
}
-static void mst_fpga_init(Object *obj)
+static int mst_fpga_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- mst_irq_state *s = MAINSTONE_FPGA(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ mst_irq_state *s = MAINSTONE_FPGA(dev);
s->pcmcia0 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
s->pcmcia1 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
@@ -214,9 +213,10 @@ static void mst_fpga_init(Object *obj)
/* alloc the external 16 irqs */
qdev_init_gpio_in(dev, mst_fpga_set_irq, MST_NUM_IRQS);
- memory_region_init_io(&s->iomem, obj, &mst_fpga_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &mst_fpga_ops, s,
"fpga", 0x00100000);
sysbus_init_mmio(sbd, &s->iomem);
+ return 0;
}
static VMStateDescription vmstate_mst_fpga_regs = {
@@ -245,7 +245,9 @@ static VMStateDescription vmstate_mst_fpga_regs = {
static void mst_fpga_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = mst_fpga_init;
dc->desc = "Mainstone II FPGA";
dc->vmsd = &vmstate_mst_fpga_regs;
}
@@ -254,7 +256,6 @@ static const TypeInfo mst_fpga_info = {
.name = TYPE_MAINSTONE_FPGA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(mst_irq_state),
- .instance_init = mst_fpga_init,
.class_init = mst_fpga_class_init,
};
diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c
index b81d82008..086893dcc 100644
--- a/hw/misc/pc-testdev.c
+++ b/hw/misc/pc-testdev.c
@@ -36,6 +36,9 @@
*/
#include "qemu/osdep.h"
+#if defined(CONFIG_POSIX)
+#include <sys/mman.h>
+#endif
#include "hw/hw.h"
#include "hw/qdev.h"
#include "hw/isa/isa.h"
diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c
index 7d5990213..2f2e98977 100644
--- a/hw/misc/pci-testdev.c
+++ b/hw/misc/pci-testdev.c
@@ -21,7 +21,6 @@
#include "hw/hw.h"
#include "hw/pci/pci.h"
#include "qemu/event_notifier.h"
-#include "sysemu/kvm.h"
typedef struct PCITestDevHdr {
uint8_t test;
diff --git a/hw/misc/stm32f2xx_syscfg.c b/hw/misc/stm32f2xx_syscfg.c
index 7c45833d0..d0d7076ef 100644
--- a/hw/misc/stm32f2xx_syscfg.c
+++ b/hw/misc/stm32f2xx_syscfg.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
#include "hw/misc/stm32f2xx_syscfg.h"
-#include "qemu/log.h"
#ifndef STM_SYSCFG_ERR_DEBUG
#define STM_SYSCFG_ERR_DEBUG 0
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
deleted file mode 100644
index 0cc556ca9..000000000
--- a/hw/misc/trace-events
+++ /dev/null
@@ -1,55 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/misc/eccmemctl.c
-ecc_mem_writel_mer(uint32_t val) "Write memory enable %08x"
-ecc_mem_writel_mdr(uint32_t val) "Write memory delay %08x"
-ecc_mem_writel_mfsr(uint32_t val) "Write memory fault status %08x"
-ecc_mem_writel_vcr(uint32_t val) "Write slot configuration %08x"
-ecc_mem_writel_dr(uint32_t val) "Write diagnostic %08x"
-ecc_mem_writel_ecr0(uint32_t val) "Write event count 1 %08x"
-ecc_mem_writel_ecr1(uint32_t val) "Write event count 2 %08x"
-ecc_mem_readl_mer(uint32_t ret) "Read memory enable %08x"
-ecc_mem_readl_mdr(uint32_t ret) "Read memory delay %08x"
-ecc_mem_readl_mfsr(uint32_t ret) "Read memory fault status %08x"
-ecc_mem_readl_vcr(uint32_t ret) "Read slot configuration %08x"
-ecc_mem_readl_mfar0(uint32_t ret) "Read memory fault address 0 %08x"
-ecc_mem_readl_mfar1(uint32_t ret) "Read memory fault address 1 %08x"
-ecc_mem_readl_dr(uint32_t ret) "Read diagnostic %08x"
-ecc_mem_readl_ecr0(uint32_t ret) "Read event count 1 %08x"
-ecc_mem_readl_ecr1(uint32_t ret) "Read event count 2 %08x"
-ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = %02x"
-ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= %02x"
-
-# hw/misc/slavio_misc.c
-slavio_misc_update_irq_raise(void) "Raise IRQ"
-slavio_misc_update_irq_lower(void) "Lower IRQ"
-slavio_set_power_fail(int power_failing, uint8_t config) "Power fail: %d, config: %d"
-slavio_cfg_mem_writeb(uint32_t val) "Write config %02x"
-slavio_cfg_mem_readb(uint32_t ret) "Read config %02x"
-slavio_diag_mem_writeb(uint32_t val) "Write diag %02x"
-slavio_diag_mem_readb(uint32_t ret) "Read diag %02x"
-slavio_mdm_mem_writeb(uint32_t val) "Write modem control %02x"
-slavio_mdm_mem_readb(uint32_t ret) "Read modem control %02x"
-slavio_aux1_mem_writeb(uint32_t val) "Write aux1 %02x"
-slavio_aux1_mem_readb(uint32_t ret) "Read aux1 %02x"
-slavio_aux2_mem_writeb(uint32_t val) "Write aux2 %02x"
-slavio_aux2_mem_readb(uint32_t ret) "Read aux2 %02x"
-apc_mem_writeb(uint32_t val) "Write power management %02x"
-apc_mem_readb(uint32_t ret) "Read power management %02x"
-slavio_sysctrl_mem_writel(uint32_t val) "Write system control %08x"
-slavio_sysctrl_mem_readl(uint32_t ret) "Read system control %08x"
-slavio_led_mem_writew(uint32_t val) "Write diagnostic LED %04x"
-slavio_led_mem_readw(uint32_t ret) "Read diagnostic LED %04x"
-
-# hw/misc/milkymist-hpdmc.c
-milkymist_hpdmc_memory_read(uint32_t addr, uint32_t value) "addr=%08x value=%08x"
-milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr=%08x value=%08x"
-
-# hw/misc/milkymist-pfpu.c
-milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_pfpu_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_pfpu_vectout(uint32_t a, uint32_t b, uint32_t dma_ptr) "a %08x b %08x dma_ptr %08x"
-milkymist_pfpu_pulse_irq(void) "Pulse IRQ"
-
-# hw/misc/aspeed_scu.c
-aspeed_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index c763811a9..689678980 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -36,6 +36,7 @@
#define VMPORT_ENTRIES 0x2c
#define VMPORT_MAGIC 0x564D5868
+#define TYPE_VMPORT "vmport"
#define VMPORT(obj) OBJECT_CHECK(VMPortState, (obj), TYPE_VMPORT)
typedef struct VMPortState
diff --git a/hw/misc/zynq-xadc.c b/hw/misc/zynq-xadc.c
index 14906103c..71fbccd79 100644
--- a/hw/misc/zynq-xadc.c
+++ b/hw/misc/zynq-xadc.c
@@ -18,7 +18,6 @@
#include "hw/misc/zynq-xadc.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
-#include "qemu/log.h"
enum {
CFG = 0x000 / 4,
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index 789121900..b1b7591ef 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -19,7 +19,6 @@
#include "qemu/timer.h"
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
-#include "qemu/log.h"
#ifndef ZYNQ_SLCR_ERR_DEBUG
#define ZYNQ_SLCR_ERR_DEBUG 0
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
index 610ed3e7a..64d044923 100644
--- a/hw/net/Makefile.objs
+++ b/hw/net/Makefile.objs
@@ -6,11 +6,9 @@ common-obj-$(CONFIG_NE2000_PCI) += ne2000.o
common-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
common-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
-common-obj-$(CONFIG_E1000_PCI) += e1000.o e1000x_common.o
-common-obj-$(CONFIG_E1000E_PCI) += net_tx_pkt.o net_rx_pkt.o
-common-obj-$(CONFIG_E1000E_PCI) += e1000e.o e1000e_core.o e1000x_common.o
+common-obj-$(CONFIG_E1000_PCI) += e1000.o
common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
-common-obj-$(CONFIG_VMXNET3_PCI) += net_tx_pkt.o net_rx_pkt.o
+common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet_tx_pkt.o vmxnet_rx_pkt.o
common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet3.o
common-obj-$(CONFIG_SMC91C111) += smc91c111.o
diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c
index 50e8361e5..16d4b63ba 100644
--- a/hw/net/allwinner_emac.c
+++ b/hw/net/allwinner_emac.c
@@ -21,7 +21,6 @@
#include "net/net.h"
#include "qemu/fifo8.h"
#include "hw/net/allwinner_emac.h"
-#include "qemu/log.h"
#include <zlib.h>
static uint8_t padding[60];
@@ -424,7 +423,7 @@ static const MemoryRegionOps aw_emac_mem_ops = {
};
static NetClientInfo net_aw_emac_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = aw_emac_can_receive,
.receive = aw_emac_receive,
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index db1b301e7..0346f3e33 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -274,11 +274,6 @@ static inline unsigned tx_desc_get_last(unsigned *desc)
return (desc[1] & DESC_1_TX_LAST) ? 1 : 0;
}
-static inline void tx_desc_set_last(unsigned *desc)
-{
- desc[1] |= DESC_1_TX_LAST;
-}
-
static inline unsigned tx_desc_get_length(unsigned *desc)
{
return desc[1] & DESC_1_LENGTH;
@@ -669,13 +664,6 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL;
bytes_to_copy = size;
- /* Hardware allows a zero value here but warns against it. To avoid QEMU
- * indefinite loops we enforce a minimum value here
- */
- if (rxbufsize < GEM_DMACFG_RBUFSZ_MUL) {
- rxbufsize = GEM_DMACFG_RBUFSZ_MUL;
- }
-
/* Pad to minimum length. Assume FCS field is stripped, logic
* below will increment it to the real minimum of 64 when
* not FCS stripping
@@ -944,7 +932,6 @@ static void gem_transmit(CadenceGEMState *s)
/* read next descriptor */
if (tx_desc_get_wrap(desc)) {
- tx_desc_set_last(desc);
packet_desc_addr = s->regs[GEM_TXQBASE];
} else {
packet_desc_addr += 8;
@@ -1207,7 +1194,7 @@ static void gem_set_link(NetClientState *nc)
}
static NetClientInfo net_gem_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = gem_can_receive,
.receive = gem_receive,
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 17f0338d1..0fa652c39 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -812,7 +812,7 @@ static void dp8393x_reset(DeviceState *dev)
}
static NetClientInfo net_dp83932_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = dp8393x_can_receive,
.receive = dp8393x_receive,
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 93249497f..8e79b550e 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -36,7 +36,7 @@
#include "qemu/iov.h"
#include "qemu/range.h"
-#include "e1000x_common.h"
+#include "e1000_regs.h"
static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
@@ -64,6 +64,11 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
#define PNPMMIO_SIZE 0x20000
#define MIN_BUF_SIZE 60 /* Min. octets in an ethernet frame sans FCS */
+/* this is the size past which hardware will drop packets when setting LPE=0 */
+#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
+/* this is the size past which hardware will drop packets when setting LPE=1 */
+#define MAXIMUM_ETHERNET_LPE_SIZE 16384
+
#define MAXIMUM_ETHERNET_HDR_LEN (14+4)
/*
@@ -97,9 +102,22 @@ typedef struct E1000State_st {
unsigned char vlan[4];
unsigned char data[0x10000];
uint16_t size;
+ unsigned char sum_needed;
unsigned char vlan_needed;
- e1000x_txd_props props;
+ uint8_t ipcss;
+ uint8_t ipcso;
+ uint16_t ipcse;
+ uint8_t tucss;
+ uint8_t tucso;
+ uint16_t tucse;
+ uint8_t hdr_len;
+ uint16_t mss;
+ uint32_t paylen;
uint16_t tso_frames;
+ char tse;
+ int8_t ip;
+ int8_t tcp;
+ char cptse; // current packet tse bit
} tx;
struct {
@@ -144,19 +162,52 @@ typedef struct E1000BaseClass {
#define E1000_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(E1000BaseClass, (obj), TYPE_E1000_BASE)
+#define defreg(x) x = (E1000_##x>>2)
+enum {
+ defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC),
+ defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC),
+ defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC),
+ defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH),
+ defreg(RDBAL), defreg(RDH), defreg(RDLEN), defreg(RDT),
+ defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH),
+ defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT),
+ defreg(TORH), defreg(TORL), defreg(TOTH), defreg(TOTL),
+ defreg(TPR), defreg(TPT), defreg(TXDCTL), defreg(WUFC),
+ defreg(RA), defreg(MTA), defreg(CRCERRS), defreg(VFTA),
+ defreg(VET), defreg(RDTR), defreg(RADV), defreg(TADV),
+ defreg(ITR), defreg(FCRUC), defreg(TDFH), defreg(TDFT),
+ defreg(TDFHS), defreg(TDFTS), defreg(TDFPC), defreg(RDFH),
+ defreg(RDFT), defreg(RDFHS), defreg(RDFTS), defreg(RDFPC),
+ defreg(IPAV), defreg(WUC), defreg(WUS), defreg(AIT),
+ defreg(IP6AT), defreg(IP4AT), defreg(FFLT), defreg(FFMT),
+ defreg(FFVT), defreg(WUPM), defreg(PBM), defreg(SCC),
+ defreg(ECOL), defreg(MCC), defreg(LATECOL), defreg(COLC),
+ defreg(DC), defreg(TNCRS), defreg(SEC), defreg(CEXTERR),
+ defreg(RLEC), defreg(XONRXC), defreg(XONTXC), defreg(XOFFRXC),
+ defreg(XOFFTXC), defreg(RFC), defreg(RJC), defreg(RNBC),
+ defreg(TSCTFC), defreg(MGTPRC), defreg(MGTPDC), defreg(MGTPTC),
+ defreg(RUC), defreg(ROC), defreg(GORCL), defreg(GORCH),
+ defreg(GOTCL), defreg(GOTCH), defreg(BPRC), defreg(MPRC),
+ defreg(TSCTC), defreg(PRC64), defreg(PRC127), defreg(PRC255),
+ defreg(PRC511), defreg(PRC1023), defreg(PRC1522), defreg(PTC64),
+ defreg(PTC127), defreg(PTC255), defreg(PTC511), defreg(PTC1023),
+ defreg(PTC1522), defreg(MPTC), defreg(BPTC)
+};
+
static void
-e1000_link_up(E1000State *s)
+e1000_link_down(E1000State *s)
{
- e1000x_update_regs_on_link_up(s->mac_reg, s->phy_reg);
-
- /* E1000_STATUS_LU is tested by e1000_can_receive() */
- qemu_flush_queued_packets(qemu_get_queue(s->nic));
+ s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
+ s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+ s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
+ s->phy_reg[PHY_LP_ABILITY] &= ~MII_LPAR_LPACK;
}
static void
-e1000_autoneg_done(E1000State *s)
+e1000_link_up(E1000State *s)
{
- e1000x_update_regs_on_autoneg_done(s->mac_reg, s->phy_reg);
+ s->mac_reg[STATUS] |= E1000_STATUS_LU;
+ s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
/* E1000_STATUS_LU is tested by e1000_can_receive() */
qemu_flush_queued_packets(qemu_get_queue(s->nic));
@@ -182,7 +233,10 @@ set_phy_ctrl(E1000State *s, int index, uint16_t val)
* down.
*/
if (have_autoneg(s) && (val & MII_CR_RESTART_AUTO_NEG)) {
- e1000x_restart_autoneg(s->mac_reg, s->phy_reg, s->autoneg_timer);
+ e1000_link_down(s);
+ DBGOUT(PHY, "Start link auto negotiation\n");
+ timer_mod(s->autoneg_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
}
}
@@ -311,9 +365,11 @@ set_interrupt_cause(E1000State *s, int index, uint32_t val)
*/
mit_delay = (mit_delay < 500) ? 500 : mit_delay;
- s->mit_timer_on = 1;
- timer_mod(s->mit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
- mit_delay * 256);
+ if (mit_delay) {
+ s->mit_timer_on = 1;
+ timer_mod(s->mit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ mit_delay * 256);
+ }
s->mit_ide = 0;
}
}
@@ -345,16 +401,43 @@ e1000_autoneg_timer(void *opaque)
{
E1000State *s = opaque;
if (!qemu_get_queue(s->nic)->link_down) {
- e1000_autoneg_done(s);
+ e1000_link_up(s);
+ s->phy_reg[PHY_LP_ABILITY] |= MII_LPAR_LPACK;
+ s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
+ DBGOUT(PHY, "Auto negotiation is completed\n");
set_ics(s, 0, E1000_ICS_LSC); /* signal link status change to guest */
}
}
+static int
+rxbufsize(uint32_t v)
+{
+ v &= E1000_RCTL_BSEX | E1000_RCTL_SZ_16384 | E1000_RCTL_SZ_8192 |
+ E1000_RCTL_SZ_4096 | E1000_RCTL_SZ_2048 | E1000_RCTL_SZ_1024 |
+ E1000_RCTL_SZ_512 | E1000_RCTL_SZ_256;
+ switch (v) {
+ case E1000_RCTL_BSEX | E1000_RCTL_SZ_16384:
+ return 16384;
+ case E1000_RCTL_BSEX | E1000_RCTL_SZ_8192:
+ return 8192;
+ case E1000_RCTL_BSEX | E1000_RCTL_SZ_4096:
+ return 4096;
+ case E1000_RCTL_SZ_1024:
+ return 1024;
+ case E1000_RCTL_SZ_512:
+ return 512;
+ case E1000_RCTL_SZ_256:
+ return 256;
+ }
+ return 2048;
+}
+
static void e1000_reset(void *opaque)
{
E1000State *d = opaque;
E1000BaseClass *edc = E1000_DEVICE_GET_CLASS(d);
uint8_t *macaddr = d->conf.macaddr.a;
+ int i;
timer_del(d->autoneg_timer);
timer_del(d->mit_timer);
@@ -370,10 +453,17 @@ static void e1000_reset(void *opaque)
memset(&d->tx, 0, sizeof d->tx);
if (qemu_get_queue(d->nic)->link_down) {
- e1000x_update_regs_on_link_down(d->mac_reg, d->phy_reg);
+ e1000_link_down(d);
}
- e1000x_reset_mac_addr(d->nic, d->mac_reg, macaddr);
+ /* Some guests expect pre-initialized RAH/RAL (AddrValid flag + MACaddr) */
+ d->mac_reg[RA] = 0;
+ d->mac_reg[RA + 1] = E1000_RAH_AV;
+ for (i = 0; i < 4; i++) {
+ d->mac_reg[RA] |= macaddr[i] << (8 * i);
+ d->mac_reg[RA + 1] |= (i < 2) ? macaddr[i + 4] << (8 * i) : 0;
+ }
+ qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);
}
static void
@@ -387,7 +477,7 @@ static void
set_rx_control(E1000State *s, int index, uint32_t val)
{
s->mac_reg[RCTL] = val;
- s->rxbuf_size = e1000x_rxbufsize(val);
+ s->rxbuf_size = rxbufsize(val);
s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1;
DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT],
s->mac_reg[RCTL]);
@@ -508,15 +598,89 @@ putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse)
}
static inline void
+inc_reg_if_not_full(E1000State *s, int index)
+{
+ if (s->mac_reg[index] != 0xffffffff) {
+ s->mac_reg[index]++;
+ }
+}
+
+static inline void
inc_tx_bcast_or_mcast_count(E1000State *s, const unsigned char *arr)
{
if (!memcmp(arr, bcast, sizeof bcast)) {
- e1000x_inc_reg_if_not_full(s->mac_reg, BPTC);
+ inc_reg_if_not_full(s, BPTC);
} else if (arr[0] & 1) {
- e1000x_inc_reg_if_not_full(s->mac_reg, MPTC);
+ inc_reg_if_not_full(s, MPTC);
+ }
+}
+
+static void
+grow_8reg_if_not_full(E1000State *s, int index, int size)
+{
+ uint64_t sum = s->mac_reg[index] | (uint64_t)s->mac_reg[index+1] << 32;
+
+ if (sum + size < sum) {
+ sum = ~0ULL;
+ } else {
+ sum += size;
+ }
+ s->mac_reg[index] = sum;
+ s->mac_reg[index+1] = sum >> 32;
+}
+
+static void
+increase_size_stats(E1000State *s, const int *size_regs, int size)
+{
+ if (size > 1023) {
+ inc_reg_if_not_full(s, size_regs[5]);
+ } else if (size > 511) {
+ inc_reg_if_not_full(s, size_regs[4]);
+ } else if (size > 255) {
+ inc_reg_if_not_full(s, size_regs[3]);
+ } else if (size > 127) {
+ inc_reg_if_not_full(s, size_regs[2]);
+ } else if (size > 64) {
+ inc_reg_if_not_full(s, size_regs[1]);
+ } else if (size == 64) {
+ inc_reg_if_not_full(s, size_regs[0]);
}
}
+static inline int
+vlan_enabled(E1000State *s)
+{
+ return ((s->mac_reg[CTRL] & E1000_CTRL_VME) != 0);
+}
+
+static inline int
+vlan_rx_filter_enabled(E1000State *s)
+{
+ return ((s->mac_reg[RCTL] & E1000_RCTL_VFE) != 0);
+}
+
+static inline int
+is_vlan_packet(E1000State *s, const uint8_t *buf)
+{
+ return (be16_to_cpup((uint16_t *)(buf + 12)) ==
+ le16_to_cpu(s->mac_reg[VET]));
+}
+
+static inline int
+is_vlan_txd(uint32_t txd_lower)
+{
+ return ((txd_lower & E1000_TXD_CMD_VLE) != 0);
+}
+
+/* FCS aka Ethernet CRC-32. We don't get it from backends and can't
+ * fill it in, just pad descriptor length by 4 bytes unless guest
+ * told us to strip it off the packet. */
+static inline int
+fcs_len(E1000State *s)
+{
+ return (s->mac_reg[RCTL] & E1000_RCTL_SECRC) ? 0 : 4;
+}
+
static void
e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
{
@@ -530,60 +694,55 @@ e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
qemu_send_packet(nc, buf, size);
}
inc_tx_bcast_or_mcast_count(s, buf);
- e1000x_increase_size_stats(s->mac_reg, PTCregs, size);
+ increase_size_stats(s, PTCregs, size);
}
static void
xmit_seg(E1000State *s)
{
- uint16_t len;
+ uint16_t len, *sp;
unsigned int frames = s->tx.tso_frames, css, sofar;
struct e1000_tx *tp = &s->tx;
- if (tp->props.tse && tp->props.cptse) {
- css = tp->props.ipcss;
+ if (tp->tse && tp->cptse) {
+ css = tp->ipcss;
DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
frames, tp->size, css);
- if (tp->props.ip) { /* IPv4 */
+ if (tp->ip) { /* IPv4 */
stw_be_p(tp->data+css+2, tp->size - css);
stw_be_p(tp->data+css+4,
- lduw_be_p(tp->data + css + 4) + frames);
+ be16_to_cpup((uint16_t *)(tp->data+css+4))+frames);
} else { /* IPv6 */
stw_be_p(tp->data+css+4, tp->size - css);
}
- css = tp->props.tucss;
+ css = tp->tucss;
len = tp->size - css;
- DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->props.tcp, css, len);
- if (tp->props.tcp) {
- sofar = frames * tp->props.mss;
+ DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->tcp, css, len);
+ if (tp->tcp) {
+ sofar = frames * tp->mss;
stl_be_p(tp->data+css+4, ldl_be_p(tp->data+css+4)+sofar); /* seq */
- if (tp->props.paylen - sofar > tp->props.mss) {
+ if (tp->paylen - sofar > tp->mss) {
tp->data[css + 13] &= ~9; /* PSH, FIN */
} else if (frames) {
- e1000x_inc_reg_if_not_full(s->mac_reg, TSCTC);
+ inc_reg_if_not_full(s, TSCTC);
}
} else /* UDP */
stw_be_p(tp->data+css+4, len);
- if (tp->props.sum_needed & E1000_TXD_POPTS_TXSM) {
+ if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
unsigned int phsum;
// add pseudo-header length before checksum calculation
- void *sp = tp->data + tp->props.tucso;
-
- phsum = lduw_be_p(sp) + len;
+ sp = (uint16_t *)(tp->data + tp->tucso);
+ phsum = be16_to_cpup(sp) + len;
phsum = (phsum >> 16) + (phsum & 0xffff);
stw_be_p(sp, phsum);
}
tp->tso_frames++;
}
- if (tp->props.sum_needed & E1000_TXD_POPTS_TXSM) {
- putsum(tp->data, tp->size, tp->props.tucso,
- tp->props.tucss, tp->props.tucse);
- }
- if (tp->props.sum_needed & E1000_TXD_POPTS_IXSM) {
- putsum(tp->data, tp->size, tp->props.ipcso,
- tp->props.ipcss, tp->props.ipcse);
- }
+ if (tp->sum_needed & E1000_TXD_POPTS_TXSM)
+ putsum(tp->data, tp->size, tp->tucso, tp->tucss, tp->tucse);
+ if (tp->sum_needed & E1000_TXD_POPTS_IXSM)
+ putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse);
if (tp->vlan_needed) {
memmove(tp->vlan, tp->data, 4);
memmove(tp->data, tp->data + 4, 8);
@@ -593,8 +752,8 @@ xmit_seg(E1000State *s)
e1000_send_packet(s, tp->data, tp->size);
}
- e1000x_inc_reg_if_not_full(s->mac_reg, TPT);
- e1000x_grow_8reg_if_not_full(s->mac_reg, TOTL, s->tx.size);
+ inc_reg_if_not_full(s, TPT);
+ grow_8reg_if_not_full(s, TOTL, s->tx.size);
s->mac_reg[GPTC] = s->mac_reg[TPT];
s->mac_reg[GOTCL] = s->mac_reg[TOTL];
s->mac_reg[GOTCH] = s->mac_reg[TOTH];
@@ -606,7 +765,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
PCIDevice *d = PCI_DEVICE(s);
uint32_t txd_lower = le32_to_cpu(dp->lower.data);
uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);
- unsigned int split_size = txd_lower & 0xffff, bytes, sz;
+ unsigned int split_size = txd_lower & 0xffff, bytes, sz, op;
unsigned int msh = 0xfffff;
uint64_t addr;
struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;
@@ -614,27 +773,38 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
s->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE);
if (dtype == E1000_TXD_CMD_DEXT) { /* context descriptor */
- e1000x_read_tx_ctx_descr(xp, &tp->props);
+ op = le32_to_cpu(xp->cmd_and_length);
+ tp->ipcss = xp->lower_setup.ip_fields.ipcss;
+ tp->ipcso = xp->lower_setup.ip_fields.ipcso;
+ tp->ipcse = le16_to_cpu(xp->lower_setup.ip_fields.ipcse);
+ tp->tucss = xp->upper_setup.tcp_fields.tucss;
+ tp->tucso = xp->upper_setup.tcp_fields.tucso;
+ tp->tucse = le16_to_cpu(xp->upper_setup.tcp_fields.tucse);
+ tp->paylen = op & 0xfffff;
+ tp->hdr_len = xp->tcp_seg_setup.fields.hdr_len;
+ tp->mss = le16_to_cpu(xp->tcp_seg_setup.fields.mss);
+ tp->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0;
+ tp->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0;
+ tp->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0;
tp->tso_frames = 0;
- if (tp->props.tucso == 0) { /* this is probably wrong */
+ if (tp->tucso == 0) { /* this is probably wrong */
DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");
- tp->props.tucso = tp->props.tucss + (tp->props.tcp ? 16 : 6);
+ tp->tucso = tp->tucss + (tp->tcp ? 16 : 6);
}
return;
} else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
// data descriptor
if (tp->size == 0) {
- tp->props.sum_needed = le32_to_cpu(dp->upper.data) >> 8;
+ tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
}
- tp->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
+ tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;
} else {
// legacy descriptor
- tp->props.cptse = 0;
+ tp->cptse = 0;
}
- if (e1000x_vlan_enabled(s->mac_reg) &&
- e1000x_is_vlan_txd(txd_lower) &&
- (tp->props.cptse || txd_lower & E1000_TXD_CMD_EOP)) {
+ if (vlan_enabled(s) && is_vlan_txd(txd_lower) &&
+ (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
tp->vlan_needed = 1;
stw_be_p(tp->vlan_header,
le16_to_cpu(s->mac_reg[VET]));
@@ -643,8 +813,8 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
}
addr = le64_to_cpu(dp->buffer_addr);
- if (tp->props.tse && tp->props.cptse) {
- msh = tp->props.hdr_len + tp->props.mss;
+ if (tp->tse && tp->cptse) {
+ msh = tp->hdr_len + tp->mss;
do {
bytes = split_size;
if (tp->size + bytes > msh)
@@ -653,19 +823,19 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
bytes = MIN(sizeof(tp->data) - tp->size, bytes);
pci_dma_read(d, addr, tp->data + tp->size, bytes);
sz = tp->size + bytes;
- if (sz >= tp->props.hdr_len && tp->size < tp->props.hdr_len) {
- memmove(tp->header, tp->data, tp->props.hdr_len);
+ if (sz >= tp->hdr_len && tp->size < tp->hdr_len) {
+ memmove(tp->header, tp->data, tp->hdr_len);
}
tp->size = sz;
addr += bytes;
if (sz == msh) {
xmit_seg(s);
- memmove(tp->data, tp->header, tp->props.hdr_len);
- tp->size = tp->props.hdr_len;
+ memmove(tp->data, tp->header, tp->hdr_len);
+ tp->size = tp->hdr_len;
}
split_size -= bytes;
} while (bytes && split_size);
- } else if (!tp->props.tse && tp->props.cptse) {
+ } else if (!tp->tse && tp->cptse) {
// context descriptor TSE is not set, while data descriptor TSE is set
DBGOUT(TXERR, "TCP segmentation error\n");
} else {
@@ -676,14 +846,14 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
if (!(txd_lower & E1000_TXD_CMD_EOP))
return;
- if (!(tp->props.tse && tp->props.cptse && tp->size < tp->props.hdr_len)) {
+ if (!(tp->tse && tp->cptse && tp->size < tp->hdr_len)) {
xmit_seg(s);
}
tp->tso_frames = 0;
- tp->props.sum_needed = 0;
+ tp->sum_needed = 0;
tp->vlan_needed = 0;
tp->size = 0;
- tp->props.cptse = 0;
+ tp->cptse = 0;
}
static uint32_t
@@ -755,14 +925,14 @@ start_xmit(E1000State *s)
static int
receive_filter(E1000State *s, const uint8_t *buf, int size)
{
- uint32_t rctl = s->mac_reg[RCTL];
+ static const int mta_shift[] = {4, 3, 2, 0};
+ uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp;
int isbcast = !memcmp(buf, bcast, sizeof bcast), ismcast = (buf[0] & 1);
- if (e1000x_is_vlan_packet(buf, le16_to_cpu(s->mac_reg[VET])) &&
- e1000x_vlan_rx_filter_enabled(s->mac_reg)) {
- uint16_t vid = lduw_be_p(buf + 14);
- uint32_t vfta = ldl_le_p((uint32_t*)(s->mac_reg + VFTA) +
- ((vid >> 5) & 0x7f));
+ if (is_vlan_packet(s, buf) && vlan_rx_filter_enabled(s)) {
+ uint16_t vid = be16_to_cpup((uint16_t *)(buf + 14));
+ uint32_t vfta = le32_to_cpup((uint32_t *)(s->mac_reg + VFTA) +
+ ((vid >> 5) & 0x7f));
if ((vfta & (1 << (vid & 0x1f))) == 0)
return 0;
}
@@ -772,16 +942,44 @@ receive_filter(E1000State *s, const uint8_t *buf, int size)
}
if (ismcast && (rctl & E1000_RCTL_MPE)) { /* promiscuous mcast */
- e1000x_inc_reg_if_not_full(s->mac_reg, MPRC);
+ inc_reg_if_not_full(s, MPRC);
return 1;
}
if (isbcast && (rctl & E1000_RCTL_BAM)) { /* broadcast enabled */
- e1000x_inc_reg_if_not_full(s->mac_reg, BPRC);
+ inc_reg_if_not_full(s, BPRC);
+ return 1;
+ }
+
+ for (rp = s->mac_reg + RA; rp < s->mac_reg + RA + 32; rp += 2) {
+ if (!(rp[1] & E1000_RAH_AV))
+ continue;
+ ra[0] = cpu_to_le32(rp[0]);
+ ra[1] = cpu_to_le32(rp[1]);
+ if (!memcmp(buf, (uint8_t *)ra, 6)) {
+ DBGOUT(RXFILTER,
+ "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ (int)(rp - s->mac_reg - RA)/2,
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+ return 1;
+ }
+ }
+ DBGOUT(RXFILTER, "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+ f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
+ f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff;
+ if (s->mac_reg[MTA + (f >> 5)] & (1 << (f & 0x1f))) {
+ inc_reg_if_not_full(s, MPRC);
return 1;
}
+ DBGOUT(RXFILTER,
+ "dropping, inexact filter mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x\n",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
+ (rctl >> E1000_RCTL_MO_SHIFT) & 3, f >> 5,
+ s->mac_reg[MTA + (f >> 5)]);
- return e1000x_rx_group_filter(s->mac_reg, buf);
+ return 0;
}
static void
@@ -791,11 +989,13 @@ e1000_set_link_status(NetClientState *nc)
uint32_t old_status = s->mac_reg[STATUS];
if (nc->link_down) {
- e1000x_update_regs_on_link_down(s->mac_reg, s->phy_reg);
+ e1000_link_down(s);
} else {
if (have_autoneg(s) &&
!(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
- e1000x_restart_autoneg(s->mac_reg, s->phy_reg, s->autoneg_timer);
+ /* emulate auto-negotiation if supported */
+ timer_mod(s->autoneg_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
} else {
e1000_link_up(s);
}
@@ -828,7 +1028,9 @@ e1000_can_receive(NetClientState *nc)
{
E1000State *s = qemu_get_nic_opaque(nc);
- return e1000x_rx_ready(&s->parent_obj, s->mac_reg) &&
+ return (s->mac_reg[STATUS] & E1000_STATUS_LU) &&
+ (s->mac_reg[RCTL] & E1000_RCTL_EN) &&
+ (s->parent_obj.config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
e1000_has_rxbufs(s, 1);
}
@@ -859,8 +1061,14 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
size_t desc_offset;
size_t desc_size;
size_t total_size;
+ static const int PRCregs[6] = { PRC64, PRC127, PRC255, PRC511,
+ PRC1023, PRC1522 };
+
+ if (!(s->mac_reg[STATUS] & E1000_STATUS_LU)) {
+ return -1;
+ }
- if (!e1000x_hw_rx_enabled(s->mac_reg)) {
+ if (!(s->mac_reg[RCTL] & E1000_RCTL_EN)) {
return -1;
}
@@ -868,7 +1076,7 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
if (size < sizeof(min_buf)) {
iov_to_buf(iov, iovcnt, 0, min_buf, size);
memset(&min_buf[size], 0, sizeof(min_buf) - size);
- e1000x_inc_reg_if_not_full(s->mac_reg, RUC);
+ inc_reg_if_not_full(s, RUC);
min_iov.iov_base = filter_buf = min_buf;
min_iov.iov_len = size = sizeof(min_buf);
iovcnt = 1;
@@ -880,7 +1088,11 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
}
/* Discard oversized packets if !LPE and !SBP. */
- if (e1000x_is_oversized(s->mac_reg, size)) {
+ if ((size > MAXIMUM_ETHERNET_LPE_SIZE ||
+ (size > MAXIMUM_ETHERNET_VLAN_SIZE
+ && !(s->mac_reg[RCTL] & E1000_RCTL_LPE)))
+ && !(s->mac_reg[RCTL] & E1000_RCTL_SBP)) {
+ inc_reg_if_not_full(s, ROC);
return size;
}
@@ -888,9 +1100,9 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
return size;
}
- if (e1000x_vlan_enabled(s->mac_reg) &&
- e1000x_is_vlan_packet(filter_buf, le16_to_cpu(s->mac_reg[VET]))) {
- vlan_special = cpu_to_le16(lduw_be_p(filter_buf + 14));
+ if (vlan_enabled(s) && is_vlan_packet(s, filter_buf)) {
+ vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(filter_buf
+ + 14)));
iov_ofs = 4;
if (filter_buf == iov->iov_base) {
memmove(filter_buf + 4, filter_buf, 12);
@@ -907,7 +1119,7 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
rdh_start = s->mac_reg[RDH];
desc_offset = 0;
- total_size = size + e1000x_fcs_len(s->mac_reg);
+ total_size = size + fcs_len(s);
if (!e1000_has_rxbufs(s, total_size)) {
set_ics(s, 0, E1000_ICS_RXO);
return -1;
@@ -967,7 +1179,17 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
}
} while (desc_offset < total_size);
- e1000x_update_rx_total_stats(s->mac_reg, size, total_size);
+ increase_size_stats(s, PRCregs, total_size);
+ inc_reg_if_not_full(s, TPR);
+ s->mac_reg[GPRC] = s->mac_reg[TPR];
+ /* TOR - Total Octets Received:
+ * This register includes bytes received in a packet from the <Destination
+ * Address> field through the <CRC> field, inclusively.
+ * Always include FCS length (4) in size.
+ */
+ grow_8reg_if_not_full(s, TORL, size+4);
+ s->mac_reg[GORCL] = s->mac_reg[TORL];
+ s->mac_reg[GORCH] = s->mac_reg[TORH];
n = E1000_ICS_RXT0;
if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])
@@ -1448,20 +1670,20 @@ static const VMStateDescription vmstate_e1000 = {
VMSTATE_UINT16(eecd_state.bitnum_out, E1000State),
VMSTATE_UINT16(eecd_state.reading, E1000State),
VMSTATE_UINT32(eecd_state.old_eecd, E1000State),
- VMSTATE_UINT8(tx.props.ipcss, E1000State),
- VMSTATE_UINT8(tx.props.ipcso, E1000State),
- VMSTATE_UINT16(tx.props.ipcse, E1000State),
- VMSTATE_UINT8(tx.props.tucss, E1000State),
- VMSTATE_UINT8(tx.props.tucso, E1000State),
- VMSTATE_UINT16(tx.props.tucse, E1000State),
- VMSTATE_UINT32(tx.props.paylen, E1000State),
- VMSTATE_UINT8(tx.props.hdr_len, E1000State),
- VMSTATE_UINT16(tx.props.mss, E1000State),
+ VMSTATE_UINT8(tx.ipcss, E1000State),
+ VMSTATE_UINT8(tx.ipcso, E1000State),
+ VMSTATE_UINT16(tx.ipcse, E1000State),
+ VMSTATE_UINT8(tx.tucss, E1000State),
+ VMSTATE_UINT8(tx.tucso, E1000State),
+ VMSTATE_UINT16(tx.tucse, E1000State),
+ VMSTATE_UINT32(tx.paylen, E1000State),
+ VMSTATE_UINT8(tx.hdr_len, E1000State),
+ VMSTATE_UINT16(tx.mss, E1000State),
VMSTATE_UINT16(tx.size, E1000State),
VMSTATE_UINT16(tx.tso_frames, E1000State),
- VMSTATE_UINT8(tx.props.sum_needed, E1000State),
- VMSTATE_INT8(tx.props.ip, E1000State),
- VMSTATE_INT8(tx.props.tcp, E1000State),
+ VMSTATE_UINT8(tx.sum_needed, E1000State),
+ VMSTATE_INT8(tx.ip, E1000State),
+ VMSTATE_INT8(tx.tcp, E1000State),
VMSTATE_BUFFER(tx.header, E1000State),
VMSTATE_BUFFER(tx.data, E1000State),
VMSTATE_UINT16_ARRAY(eeprom_data, E1000State, 64),
@@ -1563,7 +1785,7 @@ pci_e1000_uninit(PCIDevice *dev)
}
static NetClientInfo net_e1000_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = e1000_can_receive,
.receive = e1000_receive,
@@ -1584,11 +1806,15 @@ static void e1000_write_config(PCIDevice *pci_dev, uint32_t address,
}
}
+
static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp)
{
DeviceState *dev = DEVICE(pci_dev);
E1000State *d = E1000(pci_dev);
+ PCIDeviceClass *pdc = PCI_DEVICE_GET_CLASS(pci_dev);
uint8_t *pci_conf;
+ uint16_t checksum = 0;
+ int i;
uint8_t *macaddr;
pci_dev->config_write = e1000_write_config;
@@ -1606,14 +1832,17 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp)
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
+ memmove(d->eeprom_data, e1000_eeprom_template,
+ sizeof e1000_eeprom_template);
qemu_macaddr_default_if_unset(&d->conf.macaddr);
macaddr = d->conf.macaddr.a;
-
- e1000x_core_prepare_eeprom(d->eeprom_data,
- e1000_eeprom_template,
- sizeof(e1000_eeprom_template),
- PCI_DEVICE_GET_CLASS(pci_dev)->device_id,
- macaddr);
+ for (i = 0; i < 3; i++)
+ d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i];
+ d->eeprom_data[11] = d->eeprom_data[13] = pdc->device_id;
+ for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
+ checksum += d->eeprom_data[i];
+ checksum = (uint16_t) EEPROM_SUM - checksum;
+ d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
object_get_typename(OBJECT(d)), dev->id, d);
diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h
index 23eed50b9..1c40244ab 100644
--- a/hw/net/e1000_regs.h
+++ b/hw/net/e1000_regs.h
@@ -29,8 +29,9 @@
* Structures, enums, and macros for the MAC
*/
-#ifndef HW_E1000_REGS_H
-#define HW_E1000_REGS_H
+#ifndef _E1000_HW_H_
+#define _E1000_HW_H_
+
/* PCI Device IDs */
#define E1000_DEV_ID_82542 0x1000
@@ -84,7 +85,6 @@
#define E1000_DEV_ID_82573E 0x108B
#define E1000_DEV_ID_82573E_IAMT 0x108C
#define E1000_DEV_ID_82573L 0x109A
-#define E1000_DEV_ID_82574L 0x10D3
#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096
#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098
@@ -104,7 +104,6 @@
#define E1000_PHY_ID2_82544x 0xC30
#define E1000_PHY_ID2_8254xx_DEFAULT 0xC20 /* 82540x, 82545x, and 82546x */
#define E1000_PHY_ID2_82573x 0xCC0
-#define E1000_PHY_ID2_82574x 0xCB1
/* Register Set. (82543, 82544)
*
@@ -136,11 +135,8 @@
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
-#define E1000_EIAC 0x000DC /* Ext. Interrupt Auto Clear - RW */
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
-#define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */
-#define E1000_EITR 0x000E8 /* Extended Interrupt Throttling Rate - RW */
#define E1000_RCTL 0x00100 /* RX Control - RW */
#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */
#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */
@@ -149,7 +145,6 @@
#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */
#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
-#define E1000_FCRTV 0x05F40 /* Flow Control Refresh Timer Value - RW */
#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */
#define E1000_TCTL 0x00400 /* TX Control - RW */
@@ -166,10 +161,6 @@
#define E1000_PBM 0x10000 /* Packet Buffer Memory - RW */
#define E1000_PBS 0x01008 /* Packet Buffer Size - RW */
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
-#define E1000_EEMNGDATA 0x01014 /* MNG EEPROM Read/Write data */
-#define E1000_FLMNGCTL 0x01018 /* MNG Flash Control */
-#define E1000_FLMNGDATA 0x0101C /* MNG FLASH Read data */
-#define E1000_FLMNGCNT 0x01020 /* MNG FLASH Read Counter */
#define E1000_FLASH_UPDATES 1000
#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
@@ -178,12 +169,9 @@
#define E1000_FLSWDATA 0x01034 /* FLASH data register */
#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
-#define E1000_FLOL 0x01050 /* FEEP Auto Load */
#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
-#define E1000_FCRTL_A 0x00168 /* Alias to FCRTL */
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
-#define E1000_FCRTH_A 0x00160 /* Alias to FCRTH */
#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */
#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */
@@ -191,17 +179,11 @@
#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */
#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */
#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */
-#define E1000_RDTR_A 0x00108 /* Alias to RDTR */
#define E1000_RDBAL0 E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
-#define E1000_RDBAL0_A 0x00110 /* Alias to RDBAL0 */
#define E1000_RDBAH0 E1000_RDBAH /* RX Desc Base Address High (0) - RW */
-#define E1000_RDBAH0_A 0x00114 /* Alias to RDBAH0 */
#define E1000_RDLEN0 E1000_RDLEN /* RX Desc Length (0) - RW */
-#define E1000_RDLEN0_A 0x00118 /* Alias to RDLEN0 */
#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */
-#define E1000_RDH0_A 0x00120 /* Alias to RDH0 */
#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */
-#define E1000_RDT0_A 0x00128 /* Alias to RDT0 */
#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */
#define E1000_RXDCTL 0x02828 /* RX Descriptor Control queue 0 - RW */
#define E1000_RXDCTL1 0x02928 /* RX Descriptor Control queue 1 - RW */
@@ -210,33 +192,22 @@
#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */
#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
-#define E1000_POEMB 0x00F10 /* PHY OEM Bits Register - RW */
#define E1000_RDFH 0x02410 /* Receive Data FIFO Head Register - RW */
-#define E1000_RDFH_A 0x08000 /* Alias to RDFH */
#define E1000_RDFT 0x02418 /* Receive Data FIFO Tail Register - RW */
-#define E1000_RDFT_A 0x08008 /* Alias to RDFT */
#define E1000_RDFHS 0x02420 /* Receive Data FIFO Head Saved Register - RW */
#define E1000_RDFTS 0x02428 /* Receive Data FIFO Tail Saved Register - RW */
#define E1000_RDFPC 0x02430 /* Receive Data FIFO Packet Count - RW */
#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */
-#define E1000_TDFH_A 0x08010 /* Alias to TDFH */
#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */
-#define E1000_TDFT_A 0x08018 /* Alias to TDFT */
#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */
#define E1000_TDFTS 0x03428 /* TX Data FIFO Tail Saved - RW */
#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */
#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */
-#define E1000_TDBAL_A 0x00420 /* Alias to TDBAL */
#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */
-#define E1000_TDBAH_A 0x00424 /* Alias to TDBAH */
#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */
-#define E1000_TDLEN_A 0x00428 /* Alias to TDLEN */
#define E1000_TDH 0x03810 /* TX Descriptor Head - RW */
-#define E1000_TDH_A 0x00430 /* Alias to TDH */
#define E1000_TDT 0x03818 /* TX Descripotr Tail - RW */
-#define E1000_TDT_A 0x00438 /* Alias to TDT */
#define E1000_TIDV 0x03820 /* TX Interrupt Delay Value - RW */
-#define E1000_TIDV_A 0x00440 /* Alias to TIDV */
#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */
#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
@@ -317,15 +288,9 @@
#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
-#define E1000_MAVTV0 0x05010 /* Management VLAN TAG Value 0 */
-#define E1000_MAVTV1 0x05014 /* Management VLAN TAG Value 1 */
-#define E1000_MAVTV2 0x05018 /* Management VLAN TAG Value 2 */
-#define E1000_MAVTV3 0x0501c /* Management VLAN TAG Value 3 */
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
#define E1000_RA 0x05400 /* Receive Address - RW Array */
-#define E1000_RA_A 0x00040 /* Alias to RA */
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
-#define E1000_VFTA_A 0x00600 /* Alias to VFTA */
#define E1000_WUC 0x05800 /* Wakeup Control - RW */
#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
#define E1000_WUS 0x05810 /* Wakeup Status - RO */
@@ -335,57 +300,27 @@
#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
-#define E1000_MFUTP01 0x05828 /* Management Flex UDP/TCP Ports 0/1 - RW */
-#define E1000_MFUTP23 0x05830 /* Management Flex UDP/TCP Ports 2/3 - RW */
-#define E1000_MFVAL 0x05824 /* Manageability Filters Valid - RW */
-#define E1000_MDEF 0x05890 /* Manageability Decision Filters - RW Array */
#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
#define E1000_HOST_IF 0x08800 /* Host Interface */
#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
-#define E1000_FTFT 0x09400 /* Flexible TCO Filter Table - RW Array */
#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */
-#define E1000_MDPHYA 0x0003C /* PHY address - RW */
-#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
+#define E1000_MDPHYA 0x0003C /* PHY address - RW */
+#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
#define E1000_GCR 0x05B00 /* PCI-Ex Control */
-#define E1000_FUNCTAG 0x05B08 /* Function-Tag Register */
#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
-#define E1000_GSCN_0 0x05B20 /* 3GIO Statistic Counter Register #0 */
-#define E1000_GSCN_1 0x05B24 /* 3GIO Statistic Counter Register #1 */
-#define E1000_GSCN_2 0x05B28 /* 3GIO Statistic Counter Register #2 */
-#define E1000_GSCN_3 0x05B2C /* 3GIO Statistic Counter Register #3 */
#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
#define E1000_SWSM 0x05B50 /* SW Semaphore */
-#define E1000_GCR2 0x05B64 /* 3GIO Control Register 2 */
#define E1000_FWSM 0x05B54 /* FW Semaphore */
-#define E1000_PBACLR 0x05B68 /* MSI-X PBA Clear */
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
#define E1000_HICR 0x08F00 /* Host Inteface Control */
-#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
-#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
-#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */
-#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */
-#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */
-#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */
-#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */
-#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */
-#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */
-#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */
-#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */
-#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */
-#define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */
-#define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */
-#define E1000_TIMADJL 0x0B60C /* Time Adjustment Offset register Low - RW */
-#define E1000_TIMADJH 0x0B610 /* Time Adjustment Offset register High - RW */
-#define E1000_RXCFGL 0x0B634 /* RX Ethertype and Message Type - RW*/
-
/* RSS registers */
#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
@@ -394,85 +329,6 @@
#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
-#define E1000_MRQC_ENABLED(mrqc) (((mrqc) & (BIT(0) | BIT(1))) == BIT(0))
-
-#define E1000_RETA_IDX(hash) ((hash) & (BIT(7) - 1))
-#define E1000_RETA_VAL(reta, hash) (((uint8_t *)(reta))[E1000_RETA_IDX(hash)])
-#define E1000_RSS_QUEUE(reta, hash) ((E1000_RETA_VAL(reta, hash) & BIT(7)) >> 7)
-
-#define E1000_MRQC_EN_TCPIPV4(mrqc) ((mrqc) & BIT(16))
-#define E1000_MRQC_EN_IPV4(mrqc) ((mrqc) & BIT(17))
-#define E1000_MRQC_EN_TCPIPV6(mrqc) ((mrqc) & BIT(18))
-#define E1000_MRQC_EN_IPV6EX(mrqc) ((mrqc) & BIT(19))
-#define E1000_MRQC_EN_IPV6(mrqc) ((mrqc) & BIT(20))
-
-#define E1000_MRQ_RSS_TYPE_NONE (0)
-#define E1000_MRQ_RSS_TYPE_IPV4TCP (1)
-#define E1000_MRQ_RSS_TYPE_IPV4 (2)
-#define E1000_MRQ_RSS_TYPE_IPV6TCP (3)
-#define E1000_MRQ_RSS_TYPE_IPV6EX (4)
-#define E1000_MRQ_RSS_TYPE_IPV6 (5)
-
-#define E1000_ICR_ASSERTED BIT(31)
-#define E1000_EIAC_MASK 0x01F00000
-
-/* [TR]DBAL and [TR]DLEN masks */
-#define E1000_XDBAL_MASK (~(BIT(4) - 1))
-#define E1000_XDLEN_MASK ((BIT(20) - 1) & (~(BIT(7) - 1)))
-
-/* IVAR register parsing helpers */
-#define E1000_IVAR_INT_ALLOC_VALID (0x8)
-
-#define E1000_IVAR_RXQ0_SHIFT (0)
-#define E1000_IVAR_RXQ1_SHIFT (4)
-#define E1000_IVAR_TXQ0_SHIFT (8)
-#define E1000_IVAR_TXQ1_SHIFT (12)
-#define E1000_IVAR_OTHER_SHIFT (16)
-
-#define E1000_IVAR_ENTRY_MASK (0xF)
-#define E1000_IVAR_ENTRY_VALID_MASK E1000_IVAR_INT_ALLOC_VALID
-#define E1000_IVAR_ENTRY_VEC_MASK (0x7)
-
-#define E1000_IVAR_RXQ0(x) ((x) >> E1000_IVAR_RXQ0_SHIFT)
-#define E1000_IVAR_RXQ1(x) ((x) >> E1000_IVAR_RXQ1_SHIFT)
-#define E1000_IVAR_TXQ0(x) ((x) >> E1000_IVAR_TXQ0_SHIFT)
-#define E1000_IVAR_TXQ1(x) ((x) >> E1000_IVAR_TXQ1_SHIFT)
-#define E1000_IVAR_OTHER(x) ((x) >> E1000_IVAR_OTHER_SHIFT)
-
-#define E1000_IVAR_ENTRY_VALID(x) ((x) & E1000_IVAR_ENTRY_VALID_MASK)
-#define E1000_IVAR_ENTRY_VEC(x) ((x) & E1000_IVAR_ENTRY_VEC_MASK)
-
-#define E1000_IVAR_TX_INT_EVERY_WB BIT(31)
-
-/* RFCTL register bits */
-#define E1000_RFCTL_ISCSI_DIS 0x00000001
-#define E1000_RFCTL_NFSW_DIS 0x00000040
-#define E1000_RFCTL_NFSR_DIS 0x00000080
-#define E1000_RFCTL_IPV6_DIS 0x00000400
-#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800
-#define E1000_RFCTL_ACK_DIS 0x00001000
-#define E1000_RFCTL_ACK_DATA_DIS 0x00002000
-#define E1000_RFCTL_IPFRSP_DIS 0x00004000
-#define E1000_RFCTL_EXTEN 0x00008000
-#define E1000_RFCTL_IPV6_EX_DIS 0x00010000
-#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000
-
-/* PSRCTL parsing */
-#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F
-#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00
-#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000
-#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000
-
-#define E1000_PSRCTL_BSIZE0_SHIFT 0
-#define E1000_PSRCTL_BSIZE1_SHIFT 8
-#define E1000_PSRCTL_BSIZE2_SHIFT 16
-#define E1000_PSRCTL_BSIZE3_SHIFT 24
-
-#define E1000_PSRCTL_BUFFS_PER_DESC 4
-
-/* TARC* parsing */
-#define E1000_TARC_ENABLE BIT(10)
-
/* PHY 1000 MII Register/Bit Definitions */
/* PHY Registers defined by IEEE */
#define PHY_CTRL 0x00 /* Control Register */
@@ -488,40 +344,6 @@
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
-/* 82574-specific registers */
-#define PHY_COPPER_CTRL1 0x10 /* Copper Specific Control Register 1 */
-#define PHY_COPPER_STAT1 0x11 /* Copper Specific Status Register 1 */
-#define PHY_COPPER_INT_ENABLE 0x12 /* Interrupt Enable Register */
-#define PHY_COPPER_STAT2 0x13 /* Copper Specific Status Register 2 */
-#define PHY_COPPER_CTRL3 0x14 /* Copper Specific Control Register 3 */
-#define PHY_COPPER_CTRL2 0x1A /* Copper Specific Control Register 2 */
-#define PHY_RX_ERR_CNTR 0x15 /* Receive Error Counter */
-#define PHY_PAGE 0x16 /* Page Address (Any page) */
-#define PHY_OEM_BITS 0x19 /* OEM Bits (Page 0) */
-#define PHY_BIAS_1 0x1d /* Bias Setting Register */
-#define PHY_BIAS_2 0x1e /* Bias Setting Register */
-
-/* 82574-specific registers - page 2 */
-#define PHY_MAC_CTRL1 0x10 /* MAC Specific Control Register 1 */
-#define PHY_MAC_INT_ENABLE 0x12 /* MAC Interrupt Enable Register */
-#define PHY_MAC_STAT 0x13 /* MAC Specific Status Register */
-#define PHY_MAC_CTRL2 0x15 /* MAC Specific Control Register 2 */
-
-/* 82574-specific registers - page 3 */
-#define PHY_LED_03_FUNC_CTRL1 0x10 /* LED[3:0] Function Control */
-#define PHY_LED_03_POL_CTRL 0x11 /* LED[3:0] Polarity Control */
-#define PHY_LED_TIMER_CTRL 0x12 /* LED Timer Control */
-#define PHY_LED_45_CTRL 0x13 /* LED[5:4] Function Control and Polarity */
-
-/* 82574-specific registers - page 5 */
-#define PHY_1000T_SKEW 0x14 /* 1000 BASE - T Pair Skew Register */
-#define PHY_1000T_SWAP 0x15 /* 1000 BASE - T Pair Swap and Polarity */
-
-/* 82574-specific registers - page 6 */
-#define PHY_CRC_COUNTERS 0x11 /* CRC Counters */
-
-#define PHY_PAGE_RW_MASK 0x7F /* R/W part of page address register */
-
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
#define MAX_PHY_MULTI_PAGE_REG 0xF /* Registers equal on all pages */
@@ -601,18 +423,6 @@
#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */
#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */
#define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */
-#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */
-#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */
-#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */
-#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */
-#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */
-
-#define E1000_ICR_OTHER_CAUSES (E1000_ICR_LSC | \
- E1000_ICR_RXO | \
- E1000_ICR_MDAC | \
- E1000_ICR_SRPD | \
- E1000_ICR_ACK | \
- E1000_ICR_MNG)
/* Interrupt Cause Set */
#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
@@ -661,11 +471,6 @@
#define E1000_IMS_SRPD E1000_ICR_SRPD
#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */
#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */
-#define E1000_IMS_RXQ0 E1000_ICR_RXQ0
-#define E1000_IMS_RXQ1 E1000_ICR_RXQ1
-#define E1000_IMS_TXQ0 E1000_ICR_TXQ0
-#define E1000_IMS_TXQ1 E1000_ICR_TXQ1
-#define E1000_IMS_OTHER E1000_ICR_OTHER
#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */
#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
@@ -757,15 +562,6 @@
#define E1000_EEPROM_RW_ADDR_SHIFT 8 /* Shift to the address bits */
#define E1000_EEPROM_POLL_WRITE 1 /* Flag for polling for write complete */
#define E1000_EEPROM_POLL_READ 0 /* Flag for polling for read complete */
-
-/* 82574 EERD/EEWR registers layout */
-#define E1000_EERW_START BIT(0)
-#define E1000_EERW_DONE BIT(1)
-#define E1000_EERW_ADDR_SHIFT 2
-#define E1000_EERW_ADDR_MASK ((1L << 14) - 1)
-#define E1000_EERW_DATA_SHIFT 16
-#define E1000_EERW_DATA_MASK ((1L << 16) - 1)
-
/* Register Bit Masks */
/* Device Control */
#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
@@ -788,17 +584,7 @@
#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */
-#define E1000_CTRL_SPD_SHIFT 8 /* Speed Select Shift */
-
-#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* auto speed detection check */
-#define E1000_CTRL_EXT_EE_RST 0x00002000 /* EEPROM reset */
#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */
-#define E1000_CTRL_EXT_EIAME 0x01000000
-#define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */
-#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */
-#define E1000_CTRL_EXT_INT_TIMERS_CLEAR_ENA 0x20000000
-#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
-
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
@@ -807,7 +593,6 @@
#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */
#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */
#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */
-#define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */
#define E1000_CTRL_RST 0x04000000 /* Global reset */
#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
@@ -832,13 +617,9 @@
#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion
by EEPROM/Flash */
#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */
-#define E1000_STATUS_ASDV_10 0x00000000 /* ASDV 10Mb */
-#define E1000_STATUS_ASDV_100 0x00000100 /* ASDV 100Mb */
-#define E1000_STATUS_ASDV_1000 0x00000200 /* ASDV 1Gb */
#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */
#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */
-#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */
#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */
#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */
#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */
@@ -853,8 +634,6 @@
#define E1000_STATUS_FUSE_9 0x08000000
#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */
#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */
-#define E1000_STATUS_SPEED_SHIFT 6
-#define E1000_STATUS_ASDV_SHIFT 8
/* EEPROM/Flash Control */
#define E1000_EECD_SK 0x00000001 /* EEPROM Clock */
@@ -885,8 +664,6 @@
#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
-
-
#define E1000_EECD_SECVAL_SHIFT 22
#define E1000_STM_OPCODE 0xDB00
#define E1000_HICR_FW_RESET 0xC0
@@ -907,18 +684,6 @@
#define E1000_MDIC_INT_EN 0x20000000
#define E1000_MDIC_ERROR 0x40000000
-/* Rx Interrupt Delay Timer */
-#define E1000_RDTR_FPD BIT(31)
-
-/* Tx Interrupt Delay Timer */
-#define E1000_TIDV_FPD BIT(31)
-
-/* Delay increments in nanoseconds for delayed interrupts registers */
-#define E1000_INTR_DELAY_NS_RES (1024)
-
-/* Delay increments in nanoseconds for interrupt throttling registers */
-#define E1000_INTR_THROTTLING_NS_RES (256)
-
/* EEPROM Commands - Microwire */
#define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */
#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */
@@ -946,21 +711,6 @@
#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */
#define E1000_EEPROM_CFG_DONE_PORT_1 0x00080000 /* ...for second port */
-/* PCI Express Control */
-/* 3GIO Control Register - GCR (0x05B00; RW) */
-#define E1000_L0S_ADJUST (1 << 9)
-#define E1000_L1_ENTRY_LATENCY_MSB (1 << 23)
-#define E1000_L1_ENTRY_LATENCY_LSB (1 << 25 | 1 << 26)
-
-#define E1000_L0S_ADJUST (1 << 9)
-#define E1000_L1_ENTRY_LATENCY_MSB (1 << 23)
-#define E1000_L1_ENTRY_LATENCY_LSB (1 << 25 | 1 << 26)
-
-#define E1000_GCR_RO_BITS (1 << 23 | 1 << 25 | 1 << 26)
-
-/* MSI-X PBA Clear register */
-#define E1000_PBACLR_VALID_MASK (BIT(5) - 1)
-
/* Transmit Descriptor */
struct e1000_tx_desc {
uint64_t buffer_addr; /* Address of the descriptor's data buffer */
@@ -1002,9 +752,7 @@ struct e1000_tx_desc {
#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */
#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */
#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
-#define E1000_TXD_CMD_SNAP 0x40000000 /* Update SNAP header */
#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
-#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
/* Transmit Control */
#define E1000_TCTL_RST 0x00000001 /* software reset */
@@ -1019,7 +767,7 @@ struct e1000_tx_desc {
#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */
#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */
-/* Legacy Receive Descriptor */
+/* Receive Descriptor */
struct e1000_rx_desc {
uint64_t buffer_addr; /* Address of the descriptor's data buffer */
uint16_t length; /* Length of data DMAed into data buffer */
@@ -1029,78 +777,6 @@ struct e1000_rx_desc {
uint16_t special;
};
-/* Extended Receive Descriptor */
-union e1000_rx_desc_extended {
- struct {
- uint64_t buffer_addr;
- uint64_t reserved;
- } read;
- struct {
- struct {
- uint32_t mrq; /* Multiple Rx Queues */
- union {
- uint32_t rss; /* RSS Hash */
- struct {
- uint16_t ip_id; /* IP id */
- uint16_t csum; /* Packet Checksum */
- } csum_ip;
- } hi_dword;
- } lower;
- struct {
- uint32_t status_error; /* ext status/error */
- uint16_t length;
- uint16_t vlan; /* VLAN tag */
- } upper;
- } wb; /* writeback */
-};
-
-#define MAX_PS_BUFFERS 4
-
-/* Number of packet split data buffers (not including the header buffer) */
-#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
-
-/* Receive Descriptor - Packet Split */
-union e1000_rx_desc_packet_split {
- struct {
- /* one buffer for protocol header(s), three data buffers */
- uint64_t buffer_addr[MAX_PS_BUFFERS];
- } read;
- struct {
- struct {
- uint32_t mrq; /* Multiple Rx Queues */
- union {
- uint32_t rss; /* RSS Hash */
- struct {
- uint16_t ip_id; /* IP id */
- uint16_t csum; /* Packet Checksum */
- } csum_ip;
- } hi_dword;
- } lower;
- struct {
- uint32_t status_error; /* ext status/error */
- uint16_t length0; /* length of buffer 0 */
- uint16_t vlan; /* VLAN tag */
- } middle;
- struct {
- uint16_t header_status;
- /* length of buffers 1-3 */
- uint16_t length[PS_PAGE_BUFFERS];
- } upper;
- uint64_t reserved;
- } wb; /* writeback */
-};
-
-/* Receive Checksum Control bits */
-#define E1000_RXCSUM_IPOFLD 0x100 /* IP Checksum Offload Enable */
-#define E1000_RXCSUM_TUOFLD 0x200 /* TCP/UDP Checksum Offload Enable */
-#define E1000_RXCSUM_PCSD 0x2000 /* Packet Checksum Disable */
-
-#define E1000_RING_DESC_LEN (16)
-#define E1000_RING_DESC_LEN_SHIFT (4)
-
-#define E1000_MIN_RX_DESC_LEN E1000_RING_DESC_LEN
-#define E1000_MAX_RX_DESC_LEN (sizeof(union e1000_rx_desc_packet_split))
-
/* Receive Descriptor bit definitions */
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
@@ -1126,15 +802,6 @@ union e1000_rx_desc_packet_split {
#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */
#define E1000_RXD_SPC_CFI_SHIFT 12
-/* RX packet types */
-#define E1000_RXD_PKT_MAC (0)
-#define E1000_RXD_PKT_IP4 (1)
-#define E1000_RXD_PKT_IP4_XDP (2)
-#define E1000_RXD_PKT_IP6 (5)
-#define E1000_RXD_PKT_IP6_XDP (6)
-
-#define E1000_RXD_PKT_TYPE(t) ((t) << 16)
-
#define E1000_RXDEXT_STATERR_CE 0x01000000
#define E1000_RXDEXT_STATERR_SE 0x02000000
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
@@ -1212,8 +879,6 @@ struct e1000_data_desc {
#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery
* Filtering */
#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */
-#define E1000_MANC_DIS_IP_CHK_ARP 0x10000000 /* Disable IP address chacking */
- /*for ARP packets - in 82574 */
#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */
#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
@@ -1237,14 +902,7 @@ struct e1000_data_desc {
#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */
#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */
-/* FACTPS Control */
-#define E1000_FACTPS_LAN0_ON 0x00000004 /* Lan 0 enable */
-
/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
#define EEPROM_SUM 0xBABA
-/* I/O-Mapped Access to Internal Registers, Memories, and Flash */
-#define E1000_IOADDR 0x00
-#define E1000_IODATA 0x04
-
-#endif /* HW_E1000_REGS_H */
+#endif /* _E1000_HW_H_ */
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
deleted file mode 100644
index bad43f474..000000000
--- a/hw/net/e1000e.c
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
-* QEMU INTEL 82574 GbE NIC emulation
-*
-* Software developer's manuals:
-* http://www.intel.com/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
-*
-* Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com)
-* Developed by Daynix Computing LTD (http://www.daynix.com)
-*
-* Authors:
-* Dmitry Fleytman <dmitry@daynix.com>
-* Leonid Bloch <leonid@daynix.com>
-* Yan Vugenfirer <yan@daynix.com>
-*
-* Based on work done by:
-* Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
-* Copyright (c) 2008 Qumranet
-* Based on work done by:
-* Copyright (c) 2007 Dan Aloni
-* Copyright (c) 2004 Antony T Curtis
-*
-* 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 "net/net.h"
-#include "net/tap.h"
-#include "qemu/range.h"
-#include "sysemu/sysemu.h"
-#include "hw/pci/msi.h"
-#include "hw/pci/msix.h"
-
-#include "hw/net/e1000_regs.h"
-
-#include "e1000x_common.h"
-#include "e1000e_core.h"
-
-#include "trace.h"
-
-#define TYPE_E1000E "e1000e"
-#define E1000E(obj) OBJECT_CHECK(E1000EState, (obj), TYPE_E1000E)
-
-typedef struct E1000EState {
- PCIDevice parent_obj;
- NICState *nic;
- NICConf conf;
-
- MemoryRegion mmio;
- MemoryRegion flash;
- MemoryRegion io;
- MemoryRegion msix;
-
- uint32_t ioaddr;
-
- uint16_t subsys_ven;
- uint16_t subsys;
-
- uint16_t subsys_ven_used;
- uint16_t subsys_used;
-
- bool disable_vnet;
-
- E1000ECore core;
-
-} E1000EState;
-
-#define E1000E_MMIO_IDX 0
-#define E1000E_FLASH_IDX 1
-#define E1000E_IO_IDX 2
-#define E1000E_MSIX_IDX 3
-
-#define E1000E_MMIO_SIZE (128 * 1024)
-#define E1000E_FLASH_SIZE (128 * 1024)
-#define E1000E_IO_SIZE (32)
-#define E1000E_MSIX_SIZE (16 * 1024)
-
-#define E1000E_MSIX_TABLE (0x0000)
-#define E1000E_MSIX_PBA (0x2000)
-
-static uint64_t
-e1000e_mmio_read(void *opaque, hwaddr addr, unsigned size)
-{
- E1000EState *s = opaque;
- return e1000e_core_read(&s->core, addr, size);
-}
-
-static void
-e1000e_mmio_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- E1000EState *s = opaque;
- e1000e_core_write(&s->core, addr, val, size);
-}
-
-static bool
-e1000e_io_get_reg_index(E1000EState *s, uint32_t *idx)
-{
- if (s->ioaddr < 0x1FFFF) {
- *idx = s->ioaddr;
- return true;
- }
-
- if (s->ioaddr < 0x7FFFF) {
- trace_e1000e_wrn_io_addr_undefined(s->ioaddr);
- return false;
- }
-
- if (s->ioaddr < 0xFFFFF) {
- trace_e1000e_wrn_io_addr_flash(s->ioaddr);
- return false;
- }
-
- trace_e1000e_wrn_io_addr_unknown(s->ioaddr);
- return false;
-}
-
-static uint64_t
-e1000e_io_read(void *opaque, hwaddr addr, unsigned size)
-{
- E1000EState *s = opaque;
- uint32_t idx = 0;
- uint64_t val;
-
- switch (addr) {
- case E1000_IOADDR:
- trace_e1000e_io_read_addr(s->ioaddr);
- return s->ioaddr;
- case E1000_IODATA:
- if (e1000e_io_get_reg_index(s, &idx)) {
- val = e1000e_core_read(&s->core, idx, sizeof(val));
- trace_e1000e_io_read_data(idx, val);
- return val;
- }
- return 0;
- default:
- trace_e1000e_wrn_io_read_unknown(addr);
- return 0;
- }
-}
-
-static void
-e1000e_io_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- E1000EState *s = opaque;
- uint32_t idx = 0;
-
- switch (addr) {
- case E1000_IOADDR:
- trace_e1000e_io_write_addr(val);
- s->ioaddr = (uint32_t) val;
- return;
- case E1000_IODATA:
- if (e1000e_io_get_reg_index(s, &idx)) {
- trace_e1000e_io_write_data(idx, val);
- e1000e_core_write(&s->core, idx, val, sizeof(val));
- }
- return;
- default:
- trace_e1000e_wrn_io_write_unknown(addr);
- return;
- }
-}
-
-static const MemoryRegionOps mmio_ops = {
- .read = e1000e_mmio_read,
- .write = e1000e_mmio_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .impl = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-static const MemoryRegionOps io_ops = {
- .read = e1000e_io_read,
- .write = e1000e_io_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .impl = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-static int
-e1000e_nc_can_receive(NetClientState *nc)
-{
- E1000EState *s = qemu_get_nic_opaque(nc);
- return e1000e_can_receive(&s->core);
-}
-
-static ssize_t
-e1000e_nc_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
-{
- E1000EState *s = qemu_get_nic_opaque(nc);
- return e1000e_receive_iov(&s->core, iov, iovcnt);
-}
-
-static ssize_t
-e1000e_nc_receive(NetClientState *nc, const uint8_t *buf, size_t size)
-{
- E1000EState *s = qemu_get_nic_opaque(nc);
- return e1000e_receive(&s->core, buf, size);
-}
-
-static void
-e1000e_set_link_status(NetClientState *nc)
-{
- E1000EState *s = qemu_get_nic_opaque(nc);
- e1000e_core_set_link_status(&s->core);
-}
-
-static NetClientInfo net_e1000e_info = {
- .type = NET_CLIENT_DRIVER_NIC,
- .size = sizeof(NICState),
- .can_receive = e1000e_nc_can_receive,
- .receive = e1000e_nc_receive,
- .receive_iov = e1000e_nc_receive_iov,
- .link_status_changed = e1000e_set_link_status,
-};
-
-/*
-* EEPROM (NVM) contents documented in Table 36, section 6.1
-* and generally 6.1.2 Software accessed words.
-*/
-static const uint16_t e1000e_eeprom_template[64] = {
- /* Address | Compat. | ImVer | Compat. */
- 0x0000, 0x0000, 0x0000, 0x0420, 0xf746, 0x2010, 0xffff, 0xffff,
- /* PBA |ICtrl1 | SSID | SVID | DevID |-------|ICtrl2 */
- 0x0000, 0x0000, 0x026b, 0x0000, 0x8086, 0x0000, 0x0000, 0x8058,
- /* NVM words 1,2,3 |-------------------------------|PCI-EID*/
- 0x0000, 0x2001, 0x7e7c, 0xffff, 0x1000, 0x00c8, 0x0000, 0x2704,
- /* PCIe Init. Conf 1,2,3 |PCICtrl|PHY|LD1|-------| RevID | LD0,2 */
- 0x6cc9, 0x3150, 0x070e, 0x460b, 0x2d84, 0x0100, 0xf000, 0x0706,
- /* FLPAR |FLANADD|LAN-PWR|FlVndr |ICtrl3 |APTSMBA|APTRxEP|APTSMBC*/
- 0x6000, 0x0080, 0x0f04, 0x7fff, 0x4f01, 0xc600, 0x0000, 0x20ff,
- /* APTIF | APTMC |APTuCP |LSWFWID|MSWFWID|NC-SIMC|NC-SIC | VPDP */
- 0x0028, 0x0003, 0x0000, 0x0000, 0x0000, 0x0003, 0x0000, 0xffff,
- /* SW Section */
- 0x0100, 0xc000, 0x121c, 0xc007, 0xffff, 0xffff, 0xffff, 0xffff,
- /* SW Section |CHKSUM */
- 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0120, 0xffff, 0x0000,
-};
-
-static void e1000e_core_realize(E1000EState *s)
-{
- s->core.owner = &s->parent_obj;
- s->core.owner_nic = s->nic;
-}
-
-static void
-e1000e_unuse_msix_vectors(E1000EState *s, int num_vectors)
-{
- int i;
- for (i = 0; i < num_vectors; i++) {
- msix_vector_unuse(PCI_DEVICE(s), i);
- }
-}
-
-static bool
-e1000e_use_msix_vectors(E1000EState *s, int num_vectors)
-{
- int i;
- for (i = 0; i < num_vectors; i++) {
- int res = msix_vector_use(PCI_DEVICE(s), i);
- if (res < 0) {
- trace_e1000e_msix_use_vector_fail(i, res);
- e1000e_unuse_msix_vectors(s, i);
- return false;
- }
- }
- return true;
-}
-
-static void
-e1000e_init_msix(E1000EState *s)
-{
- PCIDevice *d = PCI_DEVICE(s);
- int res = msix_init(PCI_DEVICE(s), E1000E_MSIX_VEC_NUM,
- &s->msix,
- E1000E_MSIX_IDX, E1000E_MSIX_TABLE,
- &s->msix,
- E1000E_MSIX_IDX, E1000E_MSIX_PBA,
- 0xA0);
-
- if (res < 0) {
- trace_e1000e_msix_init_fail(res);
- } else {
- if (!e1000e_use_msix_vectors(s, E1000E_MSIX_VEC_NUM)) {
- msix_uninit(d, &s->msix, &s->msix);
- }
- }
-}
-
-static void
-e1000e_cleanup_msix(E1000EState *s)
-{
- if (msix_enabled(PCI_DEVICE(s))) {
- e1000e_unuse_msix_vectors(s, E1000E_MSIX_VEC_NUM);
- msix_uninit(PCI_DEVICE(s), &s->msix, &s->msix);
- }
-}
-
-static void
-e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr)
-{
- DeviceState *dev = DEVICE(pci_dev);
- NetClientState *nc;
- int i;
-
- s->nic = qemu_new_nic(&net_e1000e_info, &s->conf,
- object_get_typename(OBJECT(s)), dev->id, s);
-
- s->core.max_queue_num = s->conf.peers.queues - 1;
-
- trace_e1000e_mac_set_permanent(MAC_ARG(macaddr));
- memcpy(s->core.permanent_mac, macaddr, sizeof(s->core.permanent_mac));
-
- qemu_format_nic_info_str(qemu_get_queue(s->nic), macaddr);
-
- /* Setup virtio headers */
- if (s->disable_vnet) {
- s->core.has_vnet = false;
- trace_e1000e_cfg_support_virtio(false);
- return;
- } else {
- s->core.has_vnet = true;
- }
-
- for (i = 0; i < s->conf.peers.queues; i++) {
- nc = qemu_get_subqueue(s->nic, i);
- if (!nc->peer || !qemu_has_vnet_hdr(nc->peer)) {
- s->core.has_vnet = false;
- trace_e1000e_cfg_support_virtio(false);
- return;
- }
- }
-
- trace_e1000e_cfg_support_virtio(true);
-
- for (i = 0; i < s->conf.peers.queues; i++) {
- nc = qemu_get_subqueue(s->nic, i);
- qemu_set_vnet_hdr_len(nc->peer, sizeof(struct virtio_net_hdr));
- qemu_using_vnet_hdr(nc->peer, true);
- }
-}
-
-static inline uint64_t
-e1000e_gen_dsn(uint8_t *mac)
-{
- return (uint64_t)(mac[5]) |
- (uint64_t)(mac[4]) << 8 |
- (uint64_t)(mac[3]) << 16 |
- (uint64_t)(0x00FF) << 24 |
- (uint64_t)(0x00FF) << 32 |
- (uint64_t)(mac[2]) << 40 |
- (uint64_t)(mac[1]) << 48 |
- (uint64_t)(mac[0]) << 56;
-}
-
-static int
-e1000e_add_pm_capability(PCIDevice *pdev, uint8_t offset, uint16_t pmc)
-{
- int ret = pci_add_capability(pdev, PCI_CAP_ID_PM, offset, PCI_PM_SIZEOF);
-
- if (ret >= 0) {
- pci_set_word(pdev->config + offset + PCI_PM_PMC,
- PCI_PM_CAP_VER_1_1 |
- pmc);
-
- pci_set_word(pdev->wmask + offset + PCI_PM_CTRL,
- PCI_PM_CTRL_STATE_MASK |
- PCI_PM_CTRL_PME_ENABLE |
- PCI_PM_CTRL_DATA_SEL_MASK);
-
- pci_set_word(pdev->w1cmask + offset + PCI_PM_CTRL,
- PCI_PM_CTRL_PME_STATUS);
- }
-
- return ret;
-}
-
-static void e1000e_write_config(PCIDevice *pci_dev, uint32_t address,
- uint32_t val, int len)
-{
- E1000EState *s = E1000E(pci_dev);
-
- pci_default_write_config(pci_dev, address, val, len);
-
- if (range_covers_byte(address, len, PCI_COMMAND) &&
- (pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
- qemu_flush_queued_packets(qemu_get_queue(s->nic));
- }
-}
-
-static void e1000e_pci_realize(PCIDevice *pci_dev, Error **errp)
-{
- static const uint16_t e1000e_pmrb_offset = 0x0C8;
- static const uint16_t e1000e_pcie_offset = 0x0E0;
- static const uint16_t e1000e_aer_offset = 0x100;
- static const uint16_t e1000e_dsn_offset = 0x140;
- E1000EState *s = E1000E(pci_dev);
- uint8_t *macaddr;
- int ret;
-
- trace_e1000e_cb_pci_realize();
-
- pci_dev->config_write = e1000e_write_config;
-
- pci_dev->config[PCI_CACHE_LINE_SIZE] = 0x10;
- pci_dev->config[PCI_INTERRUPT_PIN] = 1;
-
- pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, s->subsys_ven);
- pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID, s->subsys);
-
- s->subsys_ven_used = s->subsys_ven;
- s->subsys_used = s->subsys;
-
- /* Define IO/MMIO regions */
- memory_region_init_io(&s->mmio, OBJECT(s), &mmio_ops, s,
- "e1000e-mmio", E1000E_MMIO_SIZE);
- pci_register_bar(pci_dev, E1000E_MMIO_IDX,
- PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
-
- /*
- * We provide a dummy implementation for the flash BAR
- * for drivers that may theoretically probe for its presence.
- */
- memory_region_init(&s->flash, OBJECT(s),
- "e1000e-flash", E1000E_FLASH_SIZE);
- pci_register_bar(pci_dev, E1000E_FLASH_IDX,
- PCI_BASE_ADDRESS_SPACE_MEMORY, &s->flash);
-
- memory_region_init_io(&s->io, OBJECT(s), &io_ops, s,
- "e1000e-io", E1000E_IO_SIZE);
- pci_register_bar(pci_dev, E1000E_IO_IDX,
- PCI_BASE_ADDRESS_SPACE_IO, &s->io);
-
- memory_region_init(&s->msix, OBJECT(s), "e1000e-msix",
- E1000E_MSIX_SIZE);
- pci_register_bar(pci_dev, E1000E_MSIX_IDX,
- PCI_BASE_ADDRESS_SPACE_MEMORY, &s->msix);
-
- /* Create networking backend */
- qemu_macaddr_default_if_unset(&s->conf.macaddr);
- macaddr = s->conf.macaddr.a;
-
- e1000e_init_msix(s);
-
- if (pcie_endpoint_cap_v1_init(pci_dev, e1000e_pcie_offset) < 0) {
- hw_error("Failed to initialize PCIe capability");
- }
-
- ret = msi_init(PCI_DEVICE(s), 0xD0, 1, true, false, NULL);
- if (ret) {
- trace_e1000e_msi_init_fail(ret);
- }
-
- if (e1000e_add_pm_capability(pci_dev, e1000e_pmrb_offset,
- PCI_PM_CAP_DSI) < 0) {
- hw_error("Failed to initialize PM capability");
- }
-
- if (pcie_aer_init(pci_dev, e1000e_aer_offset, PCI_ERR_SIZEOF) < 0) {
- hw_error("Failed to initialize AER capability");
- }
-
- pcie_dev_ser_num_init(pci_dev, e1000e_dsn_offset,
- e1000e_gen_dsn(macaddr));
-
- e1000e_init_net_peer(s, pci_dev, macaddr);
-
- /* Initialize core */
- e1000e_core_realize(s);
-
- e1000e_core_pci_realize(&s->core,
- e1000e_eeprom_template,
- sizeof(e1000e_eeprom_template),
- macaddr);
-}
-
-static void e1000e_pci_uninit(PCIDevice *pci_dev)
-{
- E1000EState *s = E1000E(pci_dev);
-
- trace_e1000e_cb_pci_uninit();
-
- e1000e_core_pci_uninit(&s->core);
-
- pcie_aer_exit(pci_dev);
- pcie_cap_exit(pci_dev);
-
- qemu_del_nic(s->nic);
-
- e1000e_cleanup_msix(s);
- msi_uninit(pci_dev);
-}
-
-static void e1000e_qdev_reset(DeviceState *dev)
-{
- E1000EState *s = E1000E(dev);
-
- trace_e1000e_cb_qdev_reset();
-
- e1000e_core_reset(&s->core);
-}
-
-static void e1000e_pre_save(void *opaque)
-{
- E1000EState *s = opaque;
-
- trace_e1000e_cb_pre_save();
-
- e1000e_core_pre_save(&s->core);
-}
-
-static int e1000e_post_load(void *opaque, int version_id)
-{
- E1000EState *s = opaque;
-
- trace_e1000e_cb_post_load();
-
- if ((s->subsys != s->subsys_used) ||
- (s->subsys_ven != s->subsys_ven_used)) {
- fprintf(stderr,
- "ERROR: Cannot migrate while device properties "
- "(subsys/subsys_ven) differ");
- return -1;
- }
-
- return e1000e_core_post_load(&s->core);
-}
-
-static const VMStateDescription e1000e_vmstate_tx = {
- .name = "e1000e-tx",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(props.sum_needed, struct e1000e_tx),
- VMSTATE_UINT8(props.ipcss, struct e1000e_tx),
- VMSTATE_UINT8(props.ipcso, struct e1000e_tx),
- VMSTATE_UINT16(props.ipcse, struct e1000e_tx),
- VMSTATE_UINT8(props.tucss, struct e1000e_tx),
- VMSTATE_UINT8(props.tucso, struct e1000e_tx),
- VMSTATE_UINT16(props.tucse, struct e1000e_tx),
- VMSTATE_UINT8(props.hdr_len, struct e1000e_tx),
- VMSTATE_UINT16(props.mss, struct e1000e_tx),
- VMSTATE_UINT32(props.paylen, struct e1000e_tx),
- VMSTATE_INT8(props.ip, struct e1000e_tx),
- VMSTATE_INT8(props.tcp, struct e1000e_tx),
- VMSTATE_BOOL(props.tse, struct e1000e_tx),
- VMSTATE_BOOL(props.cptse, struct e1000e_tx),
- VMSTATE_BOOL(skip_cp, struct e1000e_tx),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription e1000e_vmstate_intr_timer = {
- .name = "e1000e-intr-timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_TIMER_PTR(timer, E1000IntrDelayTimer),
- VMSTATE_BOOL(running, E1000IntrDelayTimer),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define VMSTATE_E1000E_INTR_DELAY_TIMER(_f, _s) \
- VMSTATE_STRUCT(_f, _s, 0, \
- e1000e_vmstate_intr_timer, E1000IntrDelayTimer)
-
-#define VMSTATE_E1000E_INTR_DELAY_TIMER_ARRAY(_f, _s, _num) \
- VMSTATE_STRUCT_ARRAY(_f, _s, _num, 0, \
- e1000e_vmstate_intr_timer, E1000IntrDelayTimer)
-
-static const VMStateDescription e1000e_vmstate = {
- .name = "e1000e",
- .version_id = 1,
- .minimum_version_id = 1,
- .pre_save = e1000e_pre_save,
- .post_load = e1000e_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(parent_obj, E1000EState),
- VMSTATE_MSIX(parent_obj, E1000EState),
-
- VMSTATE_UINT32(ioaddr, E1000EState),
- VMSTATE_UINT32(core.rxbuf_min_shift, E1000EState),
- VMSTATE_UINT8(core.rx_desc_len, E1000EState),
- VMSTATE_UINT32_ARRAY(core.rxbuf_sizes, E1000EState,
- E1000_PSRCTL_BUFFS_PER_DESC),
- VMSTATE_UINT32(core.rx_desc_buf_size, E1000EState),
- VMSTATE_UINT16_ARRAY(core.eeprom, E1000EState, E1000E_EEPROM_SIZE),
- VMSTATE_UINT16_2DARRAY(core.phy, E1000EState,
- E1000E_PHY_PAGES, E1000E_PHY_PAGE_SIZE),
- VMSTATE_UINT32_ARRAY(core.mac, E1000EState, E1000E_MAC_SIZE),
- VMSTATE_UINT8_ARRAY(core.permanent_mac, E1000EState, ETH_ALEN),
-
- VMSTATE_UINT32(core.delayed_causes, E1000EState),
-
- VMSTATE_UINT16(subsys, E1000EState),
- VMSTATE_UINT16(subsys_ven, E1000EState),
-
- VMSTATE_E1000E_INTR_DELAY_TIMER(core.rdtr, E1000EState),
- VMSTATE_E1000E_INTR_DELAY_TIMER(core.radv, E1000EState),
- VMSTATE_E1000E_INTR_DELAY_TIMER(core.raid, E1000EState),
- VMSTATE_E1000E_INTR_DELAY_TIMER(core.tadv, E1000EState),
- VMSTATE_E1000E_INTR_DELAY_TIMER(core.tidv, E1000EState),
-
- VMSTATE_E1000E_INTR_DELAY_TIMER(core.itr, E1000EState),
- VMSTATE_BOOL(core.itr_intr_pending, E1000EState),
-
- VMSTATE_E1000E_INTR_DELAY_TIMER_ARRAY(core.eitr, E1000EState,
- E1000E_MSIX_VEC_NUM),
- VMSTATE_BOOL_ARRAY(core.eitr_intr_pending, E1000EState,
- E1000E_MSIX_VEC_NUM),
-
- VMSTATE_UINT32(core.itr_guest_value, E1000EState),
- VMSTATE_UINT32_ARRAY(core.eitr_guest_value, E1000EState,
- E1000E_MSIX_VEC_NUM),
-
- VMSTATE_UINT16(core.vet, E1000EState),
-
- VMSTATE_STRUCT_ARRAY(core.tx, E1000EState, E1000E_NUM_QUEUES, 0,
- e1000e_vmstate_tx, struct e1000e_tx),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static PropertyInfo e1000e_prop_disable_vnet,
- e1000e_prop_subsys_ven,
- e1000e_prop_subsys;
-
-static Property e1000e_properties[] = {
- DEFINE_NIC_PROPERTIES(E1000EState, conf),
- DEFINE_PROP_DEFAULT("disable_vnet_hdr", E1000EState, disable_vnet, false,
- e1000e_prop_disable_vnet, bool),
- DEFINE_PROP_DEFAULT("subsys_ven", E1000EState, subsys_ven,
- PCI_VENDOR_ID_INTEL,
- e1000e_prop_subsys_ven, uint16_t),
- DEFINE_PROP_DEFAULT("subsys", E1000EState, subsys, 0,
- e1000e_prop_subsys, uint16_t),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void e1000e_class_init(ObjectClass *class, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(class);
- PCIDeviceClass *c = PCI_DEVICE_CLASS(class);
-
- c->realize = e1000e_pci_realize;
- c->exit = e1000e_pci_uninit;
- c->vendor_id = PCI_VENDOR_ID_INTEL;
- c->device_id = E1000_DEV_ID_82574L;
- c->revision = 0;
- c->romfile = "efi-e1000e.rom";
- c->class_id = PCI_CLASS_NETWORK_ETHERNET;
- c->is_express = 1;
-
- dc->desc = "Intel 82574L GbE Controller";
- dc->reset = e1000e_qdev_reset;
- dc->vmsd = &e1000e_vmstate;
- dc->props = e1000e_properties;
-
- e1000e_prop_disable_vnet = qdev_prop_uint8;
- e1000e_prop_disable_vnet.description = "Do not use virtio headers, "
- "perform SW offloads emulation "
- "instead";
-
- e1000e_prop_subsys_ven = qdev_prop_uint16;
- e1000e_prop_subsys_ven.description = "PCI device Subsystem Vendor ID";
-
- e1000e_prop_subsys = qdev_prop_uint16;
- e1000e_prop_subsys.description = "PCI device Subsystem ID";
-
- set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
-}
-
-static void e1000e_instance_init(Object *obj)
-{
- E1000EState *s = E1000E(obj);
- device_add_bootindex_property(obj, &s->conf.bootindex,
- "bootindex", "/ethernet-phy@0",
- DEVICE(obj), NULL);
-}
-
-static const TypeInfo e1000e_info = {
- .name = TYPE_E1000E,
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(E1000EState),
- .class_init = e1000e_class_init,
- .instance_init = e1000e_instance_init,
-};
-
-static void e1000e_register_types(void)
-{
- type_register_static(&e1000e_info);
-}
-
-type_init(e1000e_register_types)
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
deleted file mode 100644
index badb1feb7..000000000
--- a/hw/net/e1000e_core.c
+++ /dev/null
@@ -1,3483 +0,0 @@
-/*
-* Core code for QEMU e1000e emulation
-*
-* Software developer's manuals:
-* http://www.intel.com/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
-*
-* Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com)
-* Developed by Daynix Computing LTD (http://www.daynix.com)
-*
-* Authors:
-* Dmitry Fleytman <dmitry@daynix.com>
-* Leonid Bloch <leonid@daynix.com>
-* Yan Vugenfirer <yan@daynix.com>
-*
-* Based on work done by:
-* Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
-* Copyright (c) 2008 Qumranet
-* Based on work done by:
-* Copyright (c) 2007 Dan Aloni
-* Copyright (c) 2004 Antony T Curtis
-*
-* 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 "sysemu/sysemu.h"
-#include "net/net.h"
-#include "net/tap.h"
-#include "hw/pci/msi.h"
-#include "hw/pci/msix.h"
-
-#include "net_tx_pkt.h"
-#include "net_rx_pkt.h"
-
-#include "e1000x_common.h"
-#include "e1000e_core.h"
-
-#include "trace.h"
-
-#define E1000E_MIN_XITR (500) /* No more then 7813 interrupts per
- second according to spec 10.2.4.2 */
-#define E1000E_MAX_TX_FRAGS (64)
-
-static void
-e1000e_set_interrupt_cause(E1000ECore *core, uint32_t val);
-
-static inline void
-e1000e_process_ts_option(E1000ECore *core, struct e1000_tx_desc *dp)
-{
- if (le32_to_cpu(dp->upper.data) & E1000_TXD_EXTCMD_TSTAMP) {
- trace_e1000e_wrn_no_ts_support();
- }
-}
-
-static inline void
-e1000e_process_snap_option(E1000ECore *core, uint32_t cmd_and_length)
-{
- if (cmd_and_length & E1000_TXD_CMD_SNAP) {
- trace_e1000e_wrn_no_snap_support();
- }
-}
-
-static inline void
-e1000e_raise_legacy_irq(E1000ECore *core)
-{
- trace_e1000e_irq_legacy_notify(true);
- e1000x_inc_reg_if_not_full(core->mac, IAC);
- pci_set_irq(core->owner, 1);
-}
-
-static inline void
-e1000e_lower_legacy_irq(E1000ECore *core)
-{
- trace_e1000e_irq_legacy_notify(false);
- pci_set_irq(core->owner, 0);
-}
-
-static inline void
-e1000e_intrmgr_rearm_timer(E1000IntrDelayTimer *timer)
-{
- int64_t delay_ns = (int64_t) timer->core->mac[timer->delay_reg] *
- timer->delay_resolution_ns;
-
- trace_e1000e_irq_rearm_timer(timer->delay_reg << 2, delay_ns);
-
- timer_mod(timer->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + delay_ns);
-
- timer->running = true;
-}
-
-static void
-e1000e_intmgr_timer_resume(E1000IntrDelayTimer *timer)
-{
- if (timer->running) {
- e1000e_intrmgr_rearm_timer(timer);
- }
-}
-
-static void
-e1000e_intmgr_timer_pause(E1000IntrDelayTimer *timer)
-{
- if (timer->running) {
- timer_del(timer->timer);
- }
-}
-
-static inline void
-e1000e_intrmgr_stop_timer(E1000IntrDelayTimer *timer)
-{
- if (timer->running) {
- timer_del(timer->timer);
- timer->running = false;
- }
-}
-
-static inline void
-e1000e_intrmgr_fire_delayed_interrupts(E1000ECore *core)
-{
- trace_e1000e_irq_fire_delayed_interrupts();
- e1000e_set_interrupt_cause(core, 0);
-}
-
-static void
-e1000e_intrmgr_on_timer(void *opaque)
-{
- E1000IntrDelayTimer *timer = opaque;
-
- trace_e1000e_irq_throttling_timer(timer->delay_reg << 2);
-
- timer->running = false;
- e1000e_intrmgr_fire_delayed_interrupts(timer->core);
-}
-
-static void
-e1000e_intrmgr_on_throttling_timer(void *opaque)
-{
- E1000IntrDelayTimer *timer = opaque;
-
- assert(!msix_enabled(timer->core->owner));
-
- timer->running = false;
-
- if (!timer->core->itr_intr_pending) {
- trace_e1000e_irq_throttling_no_pending_interrupts();
- return;
- }
-
- if (msi_enabled(timer->core->owner)) {
- trace_e1000e_irq_msi_notify_postponed();
- e1000e_set_interrupt_cause(timer->core, 0);
- } else {
- trace_e1000e_irq_legacy_notify_postponed();
- e1000e_set_interrupt_cause(timer->core, 0);
- }
-}
-
-static void
-e1000e_intrmgr_on_msix_throttling_timer(void *opaque)
-{
- E1000IntrDelayTimer *timer = opaque;
- int idx = timer - &timer->core->eitr[0];
-
- assert(msix_enabled(timer->core->owner));
-
- timer->running = false;
-
- if (!timer->core->eitr_intr_pending[idx]) {
- trace_e1000e_irq_throttling_no_pending_vec(idx);
- return;
- }
-
- trace_e1000e_irq_msix_notify_postponed_vec(idx);
- msix_notify(timer->core->owner, idx);
-}
-
-static void
-e1000e_intrmgr_initialize_all_timers(E1000ECore *core, bool create)
-{
- int i;
-
- core->radv.delay_reg = RADV;
- core->rdtr.delay_reg = RDTR;
- core->raid.delay_reg = RAID;
- core->tadv.delay_reg = TADV;
- core->tidv.delay_reg = TIDV;
-
- core->radv.delay_resolution_ns = E1000_INTR_DELAY_NS_RES;
- core->rdtr.delay_resolution_ns = E1000_INTR_DELAY_NS_RES;
- core->raid.delay_resolution_ns = E1000_INTR_DELAY_NS_RES;
- core->tadv.delay_resolution_ns = E1000_INTR_DELAY_NS_RES;
- core->tidv.delay_resolution_ns = E1000_INTR_DELAY_NS_RES;
-
- core->radv.core = core;
- core->rdtr.core = core;
- core->raid.core = core;
- core->tadv.core = core;
- core->tidv.core = core;
-
- core->itr.core = core;
- core->itr.delay_reg = ITR;
- core->itr.delay_resolution_ns = E1000_INTR_THROTTLING_NS_RES;
-
- for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
- core->eitr[i].core = core;
- core->eitr[i].delay_reg = EITR + i;
- core->eitr[i].delay_resolution_ns = E1000_INTR_THROTTLING_NS_RES;
- }
-
- if (!create) {
- return;
- }
-
- core->radv.timer =
- timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000e_intrmgr_on_timer, &core->radv);
- core->rdtr.timer =
- timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000e_intrmgr_on_timer, &core->rdtr);
- core->raid.timer =
- timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000e_intrmgr_on_timer, &core->raid);
-
- core->tadv.timer =
- timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000e_intrmgr_on_timer, &core->tadv);
- core->tidv.timer =
- timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000e_intrmgr_on_timer, &core->tidv);
-
- core->itr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- e1000e_intrmgr_on_throttling_timer,
- &core->itr);
-
- for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
- core->eitr[i].timer =
- timer_new_ns(QEMU_CLOCK_VIRTUAL,
- e1000e_intrmgr_on_msix_throttling_timer,
- &core->eitr[i]);
- }
-}
-
-static inline void
-e1000e_intrmgr_stop_delay_timers(E1000ECore *core)
-{
- e1000e_intrmgr_stop_timer(&core->radv);
- e1000e_intrmgr_stop_timer(&core->rdtr);
- e1000e_intrmgr_stop_timer(&core->raid);
- e1000e_intrmgr_stop_timer(&core->tidv);
- e1000e_intrmgr_stop_timer(&core->tadv);
-}
-
-static bool
-e1000e_intrmgr_delay_rx_causes(E1000ECore *core, uint32_t *causes)
-{
- uint32_t delayable_causes;
- uint32_t rdtr = core->mac[RDTR];
- uint32_t radv = core->mac[RADV];
- uint32_t raid = core->mac[RAID];
-
- if (msix_enabled(core->owner)) {
- return false;
- }
-
- delayable_causes = E1000_ICR_RXQ0 |
- E1000_ICR_RXQ1 |
- E1000_ICR_RXT0;
-
- if (!(core->mac[RFCTL] & E1000_RFCTL_ACK_DIS)) {
- delayable_causes |= E1000_ICR_ACK;
- }
-
- /* Clean up all causes that may be delayed */
- core->delayed_causes |= *causes & delayable_causes;
- *causes &= ~delayable_causes;
-
- /* Check if delayed RX interrupts disabled by client
- or if there are causes that cannot be delayed */
- if ((rdtr == 0) || (*causes != 0)) {
- return false;
- }
-
- /* Check if delayed RX ACK interrupts disabled by client
- and there is an ACK packet received */
- if ((raid == 0) && (core->delayed_causes & E1000_ICR_ACK)) {
- return false;
- }
-
- /* All causes delayed */
- e1000e_intrmgr_rearm_timer(&core->rdtr);
-
- if (!core->radv.running && (radv != 0)) {
- e1000e_intrmgr_rearm_timer(&core->radv);
- }
-
- if (!core->raid.running && (core->delayed_causes & E1000_ICR_ACK)) {
- e1000e_intrmgr_rearm_timer(&core->raid);
- }
-
- return true;
-}
-
-static bool
-e1000e_intrmgr_delay_tx_causes(E1000ECore *core, uint32_t *causes)
-{
- static const uint32_t delayable_causes = E1000_ICR_TXQ0 |
- E1000_ICR_TXQ1 |
- E1000_ICR_TXQE |
- E1000_ICR_TXDW;
-
- if (msix_enabled(core->owner)) {
- return false;
- }
-
- /* Clean up all causes that may be delayed */
- core->delayed_causes |= *causes & delayable_causes;
- *causes &= ~delayable_causes;
-
- /* If there are causes that cannot be delayed */
- if (*causes != 0) {
- return false;
- }
-
- /* All causes delayed */
- e1000e_intrmgr_rearm_timer(&core->tidv);
-
- if (!core->tadv.running && (core->mac[TADV] != 0)) {
- e1000e_intrmgr_rearm_timer(&core->tadv);
- }
-
- return true;
-}
-
-static uint32_t
-e1000e_intmgr_collect_delayed_causes(E1000ECore *core)
-{
- uint32_t res;
-
- if (msix_enabled(core->owner)) {
- assert(core->delayed_causes == 0);
- return 0;
- }
-
- res = core->delayed_causes;
- core->delayed_causes = 0;
-
- e1000e_intrmgr_stop_delay_timers(core);
-
- return res;
-}
-
-static void
-e1000e_intrmgr_fire_all_timers(E1000ECore *core)
-{
- int i;
- uint32_t val = e1000e_intmgr_collect_delayed_causes(core);
-
- trace_e1000e_irq_adding_delayed_causes(val, core->mac[ICR]);
- core->mac[ICR] |= val;
-
- if (core->itr.running) {
- timer_del(core->itr.timer);
- e1000e_intrmgr_on_throttling_timer(&core->itr);
- }
-
- for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
- if (core->eitr[i].running) {
- timer_del(core->eitr[i].timer);
- e1000e_intrmgr_on_msix_throttling_timer(&core->eitr[i]);
- }
- }
-}
-
-static void
-e1000e_intrmgr_resume(E1000ECore *core)
-{
- int i;
-
- e1000e_intmgr_timer_resume(&core->radv);
- e1000e_intmgr_timer_resume(&core->rdtr);
- e1000e_intmgr_timer_resume(&core->raid);
- e1000e_intmgr_timer_resume(&core->tidv);
- e1000e_intmgr_timer_resume(&core->tadv);
-
- e1000e_intmgr_timer_resume(&core->itr);
-
- for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
- e1000e_intmgr_timer_resume(&core->eitr[i]);
- }
-}
-
-static void
-e1000e_intrmgr_pause(E1000ECore *core)
-{
- int i;
-
- e1000e_intmgr_timer_pause(&core->radv);
- e1000e_intmgr_timer_pause(&core->rdtr);
- e1000e_intmgr_timer_pause(&core->raid);
- e1000e_intmgr_timer_pause(&core->tidv);
- e1000e_intmgr_timer_pause(&core->tadv);
-
- e1000e_intmgr_timer_pause(&core->itr);
-
- for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
- e1000e_intmgr_timer_pause(&core->eitr[i]);
- }
-}
-
-static void
-e1000e_intrmgr_reset(E1000ECore *core)
-{
- int i;
-
- core->delayed_causes = 0;
-
- e1000e_intrmgr_stop_delay_timers(core);
-
- e1000e_intrmgr_stop_timer(&core->itr);
-
- for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
- e1000e_intrmgr_stop_timer(&core->eitr[i]);
- }
-}
-
-static void
-e1000e_intrmgr_pci_unint(E1000ECore *core)
-{
- int i;
-
- timer_del(core->radv.timer);
- timer_free(core->radv.timer);
- timer_del(core->rdtr.timer);
- timer_free(core->rdtr.timer);
- timer_del(core->raid.timer);
- timer_free(core->raid.timer);
-
- timer_del(core->tadv.timer);
- timer_free(core->tadv.timer);
- timer_del(core->tidv.timer);
- timer_free(core->tidv.timer);
-
- timer_del(core->itr.timer);
- timer_free(core->itr.timer);
-
- for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
- timer_del(core->eitr[i].timer);
- timer_free(core->eitr[i].timer);
- }
-}
-
-static void
-e1000e_intrmgr_pci_realize(E1000ECore *core)
-{
- e1000e_intrmgr_initialize_all_timers(core, true);
-}
-
-static inline bool
-e1000e_rx_csum_enabled(E1000ECore *core)
-{
- return (core->mac[RXCSUM] & E1000_RXCSUM_PCSD) ? false : true;
-}
-
-static inline bool
-e1000e_rx_use_legacy_descriptor(E1000ECore *core)
-{
- return (core->mac[RFCTL] & E1000_RFCTL_EXTEN) ? false : true;
-}
-
-static inline bool
-e1000e_rx_use_ps_descriptor(E1000ECore *core)
-{
- return !e1000e_rx_use_legacy_descriptor(core) &&
- (core->mac[RCTL] & E1000_RCTL_DTYP_PS);
-}
-
-static inline bool
-e1000e_rss_enabled(E1000ECore *core)
-{
- return E1000_MRQC_ENABLED(core->mac[MRQC]) &&
- !e1000e_rx_csum_enabled(core) &&
- !e1000e_rx_use_legacy_descriptor(core);
-}
-
-typedef struct E1000E_RSSInfo_st {
- bool enabled;
- uint32_t hash;
- uint32_t queue;
- uint32_t type;
-} E1000E_RSSInfo;
-
-static uint32_t
-e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt)
-{
- bool isip4, isip6, isudp, istcp;
-
- assert(e1000e_rss_enabled(core));
-
- net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
-
- if (isip4) {
- bool fragment = net_rx_pkt_get_ip4_info(pkt)->fragment;
-
- trace_e1000e_rx_rss_ip4(fragment, istcp, core->mac[MRQC],
- E1000_MRQC_EN_TCPIPV4(core->mac[MRQC]),
- E1000_MRQC_EN_IPV4(core->mac[MRQC]));
-
- if (!fragment && istcp && E1000_MRQC_EN_TCPIPV4(core->mac[MRQC])) {
- return E1000_MRQ_RSS_TYPE_IPV4TCP;
- }
-
- if (E1000_MRQC_EN_IPV4(core->mac[MRQC])) {
- return E1000_MRQ_RSS_TYPE_IPV4;
- }
- } else if (isip6) {
- eth_ip6_hdr_info *ip6info = net_rx_pkt_get_ip6_info(pkt);
-
- bool ex_dis = core->mac[RFCTL] & E1000_RFCTL_IPV6_EX_DIS;
- bool new_ex_dis = core->mac[RFCTL] & E1000_RFCTL_NEW_IPV6_EXT_DIS;
-
- /*
- * Following two traces must not be combined because resulting
- * event will have 11 arguments totally and some trace backends
- * (at least "ust") have limitation of maximum 10 arguments per
- * event. Events with more arguments fail to compile for
- * backends like these.
- */
- trace_e1000e_rx_rss_ip6_rfctl(core->mac[RFCTL]);
- trace_e1000e_rx_rss_ip6(ex_dis, new_ex_dis, istcp,
- ip6info->has_ext_hdrs,
- ip6info->rss_ex_dst_valid,
- ip6info->rss_ex_src_valid,
- core->mac[MRQC],
- E1000_MRQC_EN_TCPIPV6(core->mac[MRQC]),
- E1000_MRQC_EN_IPV6EX(core->mac[MRQC]),
- E1000_MRQC_EN_IPV6(core->mac[MRQC]));
-
- if ((!ex_dis || !ip6info->has_ext_hdrs) &&
- (!new_ex_dis || !(ip6info->rss_ex_dst_valid ||
- ip6info->rss_ex_src_valid))) {
-
- if (istcp && !ip6info->fragment &&
- E1000_MRQC_EN_TCPIPV6(core->mac[MRQC])) {
- return E1000_MRQ_RSS_TYPE_IPV6TCP;
- }
-
- if (E1000_MRQC_EN_IPV6EX(core->mac[MRQC])) {
- return E1000_MRQ_RSS_TYPE_IPV6EX;
- }
-
- }
-
- if (E1000_MRQC_EN_IPV6(core->mac[MRQC])) {
- return E1000_MRQ_RSS_TYPE_IPV6;
- }
-
- }
-
- return E1000_MRQ_RSS_TYPE_NONE;
-}
-
-static uint32_t
-e1000e_rss_calc_hash(E1000ECore *core,
- struct NetRxPkt *pkt,
- E1000E_RSSInfo *info)
-{
- NetRxPktRssType type;
-
- assert(e1000e_rss_enabled(core));
-
- switch (info->type) {
- case E1000_MRQ_RSS_TYPE_IPV4:
- type = NetPktRssIpV4;
- break;
- case E1000_MRQ_RSS_TYPE_IPV4TCP:
- type = NetPktRssIpV4Tcp;
- break;
- case E1000_MRQ_RSS_TYPE_IPV6TCP:
- type = NetPktRssIpV6Tcp;
- break;
- case E1000_MRQ_RSS_TYPE_IPV6:
- type = NetPktRssIpV6;
- break;
- case E1000_MRQ_RSS_TYPE_IPV6EX:
- type = NetPktRssIpV6Ex;
- break;
- default:
- assert(false);
- return 0;
- }
-
- return net_rx_pkt_calc_rss_hash(pkt, type, (uint8_t *) &core->mac[RSSRK]);
-}
-
-static void
-e1000e_rss_parse_packet(E1000ECore *core,
- struct NetRxPkt *pkt,
- E1000E_RSSInfo *info)
-{
- trace_e1000e_rx_rss_started();
-
- if (!e1000e_rss_enabled(core)) {
- info->enabled = false;
- info->hash = 0;
- info->queue = 0;
- info->type = 0;
- trace_e1000e_rx_rss_disabled();
- return;
- }
-
- info->enabled = true;
-
- info->type = e1000e_rss_get_hash_type(core, pkt);
-
- trace_e1000e_rx_rss_type(info->type);
-
- if (info->type == E1000_MRQ_RSS_TYPE_NONE) {
- info->hash = 0;
- info->queue = 0;
- return;
- }
-
- info->hash = e1000e_rss_calc_hash(core, pkt, info);
- info->queue = E1000_RSS_QUEUE(&core->mac[RETA], info->hash);
-}
-
-static void
-e1000e_setup_tx_offloads(E1000ECore *core, struct e1000e_tx *tx)
-{
- if (tx->props.tse && tx->props.cptse) {
- net_tx_pkt_build_vheader(tx->tx_pkt, true, true, tx->props.mss);
- net_tx_pkt_update_ip_checksums(tx->tx_pkt);
- e1000x_inc_reg_if_not_full(core->mac, TSCTC);
- return;
- }
-
- if (tx->props.sum_needed & E1000_TXD_POPTS_TXSM) {
- net_tx_pkt_build_vheader(tx->tx_pkt, false, true, 0);
- }
-
- if (tx->props.sum_needed & E1000_TXD_POPTS_IXSM) {
- net_tx_pkt_update_ip_hdr_checksum(tx->tx_pkt);
- }
-}
-
-static bool
-e1000e_tx_pkt_send(E1000ECore *core, struct e1000e_tx *tx, int queue_index)
-{
- int target_queue = MIN(core->max_queue_num, queue_index);
- NetClientState *queue = qemu_get_subqueue(core->owner_nic, target_queue);
-
- e1000e_setup_tx_offloads(core, tx);
-
- net_tx_pkt_dump(tx->tx_pkt);
-
- if ((core->phy[0][PHY_CTRL] & MII_CR_LOOPBACK) ||
- ((core->mac[RCTL] & E1000_RCTL_LBM_MAC) == E1000_RCTL_LBM_MAC)) {
- return net_tx_pkt_send_loopback(tx->tx_pkt, queue);
- } else {
- return net_tx_pkt_send(tx->tx_pkt, queue);
- }
-}
-
-static void
-e1000e_on_tx_done_update_stats(E1000ECore *core, struct NetTxPkt *tx_pkt)
-{
- static const int PTCregs[6] = { PTC64, PTC127, PTC255, PTC511,
- PTC1023, PTC1522 };
-
- size_t tot_len = net_tx_pkt_get_total_len(tx_pkt);
-
- e1000x_increase_size_stats(core->mac, PTCregs, tot_len);
- e1000x_inc_reg_if_not_full(core->mac, TPT);
- e1000x_grow_8reg_if_not_full(core->mac, TOTL, tot_len);
-
- switch (net_tx_pkt_get_packet_type(tx_pkt)) {
- case ETH_PKT_BCAST:
- e1000x_inc_reg_if_not_full(core->mac, BPTC);
- break;
- case ETH_PKT_MCAST:
- e1000x_inc_reg_if_not_full(core->mac, MPTC);
- break;
- case ETH_PKT_UCAST:
- break;
- default:
- g_assert_not_reached();
- }
-
- core->mac[GPTC] = core->mac[TPT];
- core->mac[GOTCL] = core->mac[TOTL];
- core->mac[GOTCH] = core->mac[TOTH];
-}
-
-static void
-e1000e_process_tx_desc(E1000ECore *core,
- struct e1000e_tx *tx,
- struct e1000_tx_desc *dp,
- int queue_index)
-{
- uint32_t txd_lower = le32_to_cpu(dp->lower.data);
- uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);
- unsigned int split_size = txd_lower & 0xffff;
- uint64_t addr;
- struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;
- bool eop = txd_lower & E1000_TXD_CMD_EOP;
-
- if (dtype == E1000_TXD_CMD_DEXT) { /* context descriptor */
- e1000x_read_tx_ctx_descr(xp, &tx->props);
- e1000e_process_snap_option(core, le32_to_cpu(xp->cmd_and_length));
- return;
- } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
- /* data descriptor */
- tx->props.sum_needed = le32_to_cpu(dp->upper.data) >> 8;
- tx->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;
- e1000e_process_ts_option(core, dp);
- } else {
- /* legacy descriptor */
- e1000e_process_ts_option(core, dp);
- tx->props.cptse = 0;
- }
-
- addr = le64_to_cpu(dp->buffer_addr);
-
- if (!tx->skip_cp) {
- if (!net_tx_pkt_add_raw_fragment(tx->tx_pkt, addr, split_size)) {
- tx->skip_cp = true;
- }
- }
-
- if (eop) {
- if (!tx->skip_cp && net_tx_pkt_parse(tx->tx_pkt)) {
- if (e1000x_vlan_enabled(core->mac) &&
- e1000x_is_vlan_txd(txd_lower)) {
- net_tx_pkt_setup_vlan_header_ex(tx->tx_pkt,
- le16_to_cpu(dp->upper.fields.special), core->vet);
- }
- if (e1000e_tx_pkt_send(core, tx, queue_index)) {
- e1000e_on_tx_done_update_stats(core, tx->tx_pkt);
- }
- }
-
- tx->skip_cp = false;
- net_tx_pkt_reset(tx->tx_pkt);
-
- tx->props.sum_needed = 0;
- tx->props.cptse = 0;
- }
-}
-
-static inline uint32_t
-e1000e_tx_wb_interrupt_cause(E1000ECore *core, int queue_idx)
-{
- if (!msix_enabled(core->owner)) {
- return E1000_ICR_TXDW;
- }
-
- return (queue_idx == 0) ? E1000_ICR_TXQ0 : E1000_ICR_TXQ1;
-}
-
-static inline uint32_t
-e1000e_rx_wb_interrupt_cause(E1000ECore *core, int queue_idx,
- bool min_threshold_hit)
-{
- if (!msix_enabled(core->owner)) {
- return E1000_ICS_RXT0 | (min_threshold_hit ? E1000_ICS_RXDMT0 : 0);
- }
-
- return (queue_idx == 0) ? E1000_ICR_RXQ0 : E1000_ICR_RXQ1;
-}
-
-static uint32_t
-e1000e_txdesc_writeback(E1000ECore *core, dma_addr_t base,
- struct e1000_tx_desc *dp, bool *ide, int queue_idx)
-{
- uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data);
-
- if (!(txd_lower & E1000_TXD_CMD_RS) &&
- !(core->mac[IVAR] & E1000_IVAR_TX_INT_EVERY_WB)) {
- return 0;
- }
-
- *ide = (txd_lower & E1000_TXD_CMD_IDE) ? true : false;
-
- txd_upper = le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD;
-
- dp->upper.data = cpu_to_le32(txd_upper);
- pci_dma_write(core->owner, base + ((char *)&dp->upper - (char *)dp),
- &dp->upper, sizeof(dp->upper));
- return e1000e_tx_wb_interrupt_cause(core, queue_idx);
-}
-
-typedef struct E1000E_RingInfo_st {
- int dbah;
- int dbal;
- int dlen;
- int dh;
- int dt;
- int idx;
-} E1000E_RingInfo;
-
-static inline bool
-e1000e_ring_empty(E1000ECore *core, const E1000E_RingInfo *r)
-{
- return core->mac[r->dh] == core->mac[r->dt];
-}
-
-static inline uint64_t
-e1000e_ring_base(E1000ECore *core, const E1000E_RingInfo *r)
-{
- uint64_t bah = core->mac[r->dbah];
- uint64_t bal = core->mac[r->dbal];
-
- return (bah << 32) + bal;
-}
-
-static inline uint64_t
-e1000e_ring_head_descr(E1000ECore *core, const E1000E_RingInfo *r)
-{
- return e1000e_ring_base(core, r) + E1000_RING_DESC_LEN * core->mac[r->dh];
-}
-
-static inline void
-e1000e_ring_advance(E1000ECore *core, const E1000E_RingInfo *r, uint32_t count)
-{
- core->mac[r->dh] += count;
-
- if (core->mac[r->dh] * E1000_RING_DESC_LEN >= core->mac[r->dlen]) {
- core->mac[r->dh] = 0;
- }
-}
-
-static inline uint32_t
-e1000e_ring_free_descr_num(E1000ECore *core, const E1000E_RingInfo *r)
-{
- trace_e1000e_ring_free_space(r->idx, core->mac[r->dlen],
- core->mac[r->dh], core->mac[r->dt]);
-
- if (core->mac[r->dh] <= core->mac[r->dt]) {
- return core->mac[r->dt] - core->mac[r->dh];
- }
-
- if (core->mac[r->dh] > core->mac[r->dt]) {
- return core->mac[r->dlen] / E1000_RING_DESC_LEN +
- core->mac[r->dt] - core->mac[r->dh];
- }
-
- g_assert_not_reached();
- return 0;
-}
-
-static inline bool
-e1000e_ring_enabled(E1000ECore *core, const E1000E_RingInfo *r)
-{
- return core->mac[r->dlen] > 0;
-}
-
-static inline uint32_t
-e1000e_ring_len(E1000ECore *core, const E1000E_RingInfo *r)
-{
- return core->mac[r->dlen];
-}
-
-typedef struct E1000E_TxRing_st {
- const E1000E_RingInfo *i;
- struct e1000e_tx *tx;
-} E1000E_TxRing;
-
-static inline int
-e1000e_mq_queue_idx(int base_reg_idx, int reg_idx)
-{
- return (reg_idx - base_reg_idx) / (0x100 >> 2);
-}
-
-static inline void
-e1000e_tx_ring_init(E1000ECore *core, E1000E_TxRing *txr, int idx)
-{
- static const E1000E_RingInfo i[E1000E_NUM_QUEUES] = {
- { TDBAH, TDBAL, TDLEN, TDH, TDT, 0 },
- { TDBAH1, TDBAL1, TDLEN1, TDH1, TDT1, 1 }
- };
-
- assert(idx < ARRAY_SIZE(i));
-
- txr->i = &i[idx];
- txr->tx = &core->tx[idx];
-}
-
-typedef struct E1000E_RxRing_st {
- const E1000E_RingInfo *i;
-} E1000E_RxRing;
-
-static inline void
-e1000e_rx_ring_init(E1000ECore *core, E1000E_RxRing *rxr, int idx)
-{
- static const E1000E_RingInfo i[E1000E_NUM_QUEUES] = {
- { RDBAH0, RDBAL0, RDLEN0, RDH0, RDT0, 0 },
- { RDBAH1, RDBAL1, RDLEN1, RDH1, RDT1, 1 }
- };
-
- assert(idx < ARRAY_SIZE(i));
-
- rxr->i = &i[idx];
-}
-
-static void
-e1000e_start_xmit(E1000ECore *core, const E1000E_TxRing *txr)
-{
- dma_addr_t base;
- struct e1000_tx_desc desc;
- bool ide = false;
- const E1000E_RingInfo *txi = txr->i;
- uint32_t cause = E1000_ICS_TXQE;
-
- if (!(core->mac[TCTL] & E1000_TCTL_EN)) {
- trace_e1000e_tx_disabled();
- return;
- }
-
- while (!e1000e_ring_empty(core, txi)) {
- base = e1000e_ring_head_descr(core, txi);
-
- pci_dma_read(core->owner, base, &desc, sizeof(desc));
-
- trace_e1000e_tx_descr((void *)(intptr_t)desc.buffer_addr,
- desc.lower.data, desc.upper.data);
-
- e1000e_process_tx_desc(core, txr->tx, &desc, txi->idx);
- cause |= e1000e_txdesc_writeback(core, base, &desc, &ide, txi->idx);
-
- e1000e_ring_advance(core, txi, 1);
- }
-
- if (!ide || !e1000e_intrmgr_delay_tx_causes(core, &cause)) {
- e1000e_set_interrupt_cause(core, cause);
- }
-}
-
-static bool
-e1000e_has_rxbufs(E1000ECore *core, const E1000E_RingInfo *r,
- size_t total_size)
-{
- uint32_t bufs = e1000e_ring_free_descr_num(core, r);
-
- trace_e1000e_rx_has_buffers(r->idx, bufs, total_size,
- core->rx_desc_buf_size);
-
- return total_size <= bufs / (core->rx_desc_len / E1000_MIN_RX_DESC_LEN) *
- core->rx_desc_buf_size;
-}
-
-static inline void
-e1000e_start_recv(E1000ECore *core)
-{
- int i;
-
- trace_e1000e_rx_start_recv();
-
- for (i = 0; i <= core->max_queue_num; i++) {
- qemu_flush_queued_packets(qemu_get_subqueue(core->owner_nic, i));
- }
-}
-
-int
-e1000e_can_receive(E1000ECore *core)
-{
- int i;
-
- if (!e1000x_rx_ready(core->owner, core->mac)) {
- return false;
- }
-
- for (i = 0; i < E1000E_NUM_QUEUES; i++) {
- E1000E_RxRing rxr;
-
- e1000e_rx_ring_init(core, &rxr, i);
- if (e1000e_ring_enabled(core, rxr.i) &&
- e1000e_has_rxbufs(core, rxr.i, 1)) {
- trace_e1000e_rx_can_recv();
- return true;
- }
- }
-
- trace_e1000e_rx_can_recv_rings_full();
- return false;
-}
-
-ssize_t
-e1000e_receive(E1000ECore *core, const uint8_t *buf, size_t size)
-{
- const struct iovec iov = {
- .iov_base = (uint8_t *)buf,
- .iov_len = size
- };
-
- return e1000e_receive_iov(core, &iov, 1);
-}
-
-static inline bool
-e1000e_rx_l3_cso_enabled(E1000ECore *core)
-{
- return !!(core->mac[RXCSUM] & E1000_RXCSUM_IPOFLD);
-}
-
-static inline bool
-e1000e_rx_l4_cso_enabled(E1000ECore *core)
-{
- return !!(core->mac[RXCSUM] & E1000_RXCSUM_TUOFLD);
-}
-
-static bool
-e1000e_receive_filter(E1000ECore *core, const uint8_t *buf, int size)
-{
- uint32_t rctl = core->mac[RCTL];
-
- if (e1000x_is_vlan_packet(buf, core->vet) &&
- e1000x_vlan_rx_filter_enabled(core->mac)) {
- uint16_t vid = lduw_be_p(buf + 14);
- uint32_t vfta = ldl_le_p((uint32_t *)(core->mac + VFTA) +
- ((vid >> 5) & 0x7f));
- if ((vfta & (1 << (vid & 0x1f))) == 0) {
- trace_e1000e_rx_flt_vlan_mismatch(vid);
- return false;
- } else {
- trace_e1000e_rx_flt_vlan_match(vid);
- }
- }
-
- switch (net_rx_pkt_get_packet_type(core->rx_pkt)) {
- case ETH_PKT_UCAST:
- if (rctl & E1000_RCTL_UPE) {
- return true; /* promiscuous ucast */
- }
- break;
-
- case ETH_PKT_BCAST:
- if (rctl & E1000_RCTL_BAM) {
- return true; /* broadcast enabled */
- }
- break;
-
- case ETH_PKT_MCAST:
- if (rctl & E1000_RCTL_MPE) {
- return true; /* promiscuous mcast */
- }
- break;
-
- default:
- g_assert_not_reached();
- }
-
- return e1000x_rx_group_filter(core->mac, buf);
-}
-
-static inline void
-e1000e_read_lgcy_rx_descr(E1000ECore *core, uint8_t *desc, hwaddr *buff_addr)
-{
- struct e1000_rx_desc *d = (struct e1000_rx_desc *) desc;
- *buff_addr = le64_to_cpu(d->buffer_addr);
-}
-
-static inline void
-e1000e_read_ext_rx_descr(E1000ECore *core, uint8_t *desc, hwaddr *buff_addr)
-{
- union e1000_rx_desc_extended *d = (union e1000_rx_desc_extended *) desc;
- *buff_addr = le64_to_cpu(d->read.buffer_addr);
-}
-
-static inline void
-e1000e_read_ps_rx_descr(E1000ECore *core, uint8_t *desc,
- hwaddr (*buff_addr)[MAX_PS_BUFFERS])
-{
- int i;
- union e1000_rx_desc_packet_split *d =
- (union e1000_rx_desc_packet_split *) desc;
-
- for (i = 0; i < MAX_PS_BUFFERS; i++) {
- (*buff_addr)[i] = le64_to_cpu(d->read.buffer_addr[i]);
- }
-
- trace_e1000e_rx_desc_ps_read((*buff_addr)[0], (*buff_addr)[1],
- (*buff_addr)[2], (*buff_addr)[3]);
-}
-
-static inline void
-e1000e_read_rx_descr(E1000ECore *core, uint8_t *desc,
- hwaddr (*buff_addr)[MAX_PS_BUFFERS])
-{
- if (e1000e_rx_use_legacy_descriptor(core)) {
- e1000e_read_lgcy_rx_descr(core, desc, &(*buff_addr)[0]);
- (*buff_addr)[1] = (*buff_addr)[2] = (*buff_addr)[3] = 0;
- } else {
- if (core->mac[RCTL] & E1000_RCTL_DTYP_PS) {
- e1000e_read_ps_rx_descr(core, desc, buff_addr);
- } else {
- e1000e_read_ext_rx_descr(core, desc, &(*buff_addr)[0]);
- (*buff_addr)[1] = (*buff_addr)[2] = (*buff_addr)[3] = 0;
- }
- }
-}
-
-static void
-e1000e_verify_csum_in_sw(E1000ECore *core,
- struct NetRxPkt *pkt,
- uint32_t *status_flags,
- bool istcp, bool isudp)
-{
- bool csum_valid;
- uint32_t csum_error;
-
- if (e1000e_rx_l3_cso_enabled(core)) {
- if (!net_rx_pkt_validate_l3_csum(pkt, &csum_valid)) {
- trace_e1000e_rx_metadata_l3_csum_validation_failed();
- } else {
- csum_error = csum_valid ? 0 : E1000_RXDEXT_STATERR_IPE;
- *status_flags |= E1000_RXD_STAT_IPCS | csum_error;
- }
- } else {
- trace_e1000e_rx_metadata_l3_cso_disabled();
- }
-
- if (!e1000e_rx_l4_cso_enabled(core)) {
- trace_e1000e_rx_metadata_l4_cso_disabled();
- return;
- }
-
- if (!net_rx_pkt_validate_l4_csum(pkt, &csum_valid)) {
- trace_e1000e_rx_metadata_l4_csum_validation_failed();
- return;
- }
-
- csum_error = csum_valid ? 0 : E1000_RXDEXT_STATERR_TCPE;
-
- if (istcp) {
- *status_flags |= E1000_RXD_STAT_TCPCS |
- csum_error;
- } else if (isudp) {
- *status_flags |= E1000_RXD_STAT_TCPCS |
- E1000_RXD_STAT_UDPCS |
- csum_error;
- }
-}
-
-static inline bool
-e1000e_is_tcp_ack(E1000ECore *core, struct NetRxPkt *rx_pkt)
-{
- if (!net_rx_pkt_is_tcp_ack(rx_pkt)) {
- return false;
- }
-
- if (core->mac[RFCTL] & E1000_RFCTL_ACK_DATA_DIS) {
- return !net_rx_pkt_has_tcp_data(rx_pkt);
- }
-
- return true;
-}
-
-static void
-e1000e_build_rx_metadata(E1000ECore *core,
- struct NetRxPkt *pkt,
- bool is_eop,
- const E1000E_RSSInfo *rss_info,
- uint32_t *rss, uint32_t *mrq,
- uint32_t *status_flags,
- uint16_t *ip_id,
- uint16_t *vlan_tag)
-{
- struct virtio_net_hdr *vhdr;
- bool isip4, isip6, istcp, isudp;
- uint32_t pkt_type;
-
- *status_flags = E1000_RXD_STAT_DD;
-
- /* No additional metadata needed for non-EOP descriptors */
- if (!is_eop) {
- goto func_exit;
- }
-
- *status_flags |= E1000_RXD_STAT_EOP;
-
- net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
- trace_e1000e_rx_metadata_protocols(isip4, isip6, isudp, istcp);
-
- /* VLAN state */
- if (net_rx_pkt_is_vlan_stripped(pkt)) {
- *status_flags |= E1000_RXD_STAT_VP;
- *vlan_tag = cpu_to_le16(net_rx_pkt_get_vlan_tag(pkt));
- trace_e1000e_rx_metadata_vlan(*vlan_tag);
- }
-
- /* Packet parsing results */
- if ((core->mac[RXCSUM] & E1000_RXCSUM_PCSD) != 0) {
- if (rss_info->enabled) {
- *rss = cpu_to_le32(rss_info->hash);
- *mrq = cpu_to_le32(rss_info->type | (rss_info->queue << 8));
- trace_e1000e_rx_metadata_rss(*rss, *mrq);
- }
- } else if (isip4) {
- *status_flags |= E1000_RXD_STAT_IPIDV;
- *ip_id = cpu_to_le16(net_rx_pkt_get_ip_id(pkt));
- trace_e1000e_rx_metadata_ip_id(*ip_id);
- }
-
- if (istcp && e1000e_is_tcp_ack(core, pkt)) {
- *status_flags |= E1000_RXD_STAT_ACK;
- trace_e1000e_rx_metadata_ack();
- }
-
- if (isip6 && (core->mac[RFCTL] & E1000_RFCTL_IPV6_DIS)) {
- trace_e1000e_rx_metadata_ipv6_filtering_disabled();
- pkt_type = E1000_RXD_PKT_MAC;
- } else if (istcp || isudp) {
- pkt_type = isip4 ? E1000_RXD_PKT_IP4_XDP : E1000_RXD_PKT_IP6_XDP;
- } else if (isip4 || isip6) {
- pkt_type = isip4 ? E1000_RXD_PKT_IP4 : E1000_RXD_PKT_IP6;
- } else {
- pkt_type = E1000_RXD_PKT_MAC;
- }
-
- *status_flags |= E1000_RXD_PKT_TYPE(pkt_type);
- trace_e1000e_rx_metadata_pkt_type(pkt_type);
-
- /* RX CSO information */
- if (isip6 && (core->mac[RFCTL] & E1000_RFCTL_IPV6_XSUM_DIS)) {
- trace_e1000e_rx_metadata_ipv6_sum_disabled();
- goto func_exit;
- }
-
- if (!net_rx_pkt_has_virt_hdr(pkt)) {
- trace_e1000e_rx_metadata_no_virthdr();
- e1000e_verify_csum_in_sw(core, pkt, status_flags, istcp, isudp);
- goto func_exit;
- }
-
- vhdr = net_rx_pkt_get_vhdr(pkt);
-
- if (!(vhdr->flags & VIRTIO_NET_HDR_F_DATA_VALID) &&
- !(vhdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM)) {
- trace_e1000e_rx_metadata_virthdr_no_csum_info();
- e1000e_verify_csum_in_sw(core, pkt, status_flags, istcp, isudp);
- goto func_exit;
- }
-
- if (e1000e_rx_l3_cso_enabled(core)) {
- *status_flags |= isip4 ? E1000_RXD_STAT_IPCS : 0;
- } else {
- trace_e1000e_rx_metadata_l3_cso_disabled();
- }
-
- if (e1000e_rx_l4_cso_enabled(core)) {
- if (istcp) {
- *status_flags |= E1000_RXD_STAT_TCPCS;
- } else if (isudp) {
- *status_flags |= E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS;
- }
- } else {
- trace_e1000e_rx_metadata_l4_cso_disabled();
- }
-
- trace_e1000e_rx_metadata_status_flags(*status_flags);
-
-func_exit:
- *status_flags = cpu_to_le32(*status_flags);
-}
-
-static inline void
-e1000e_write_lgcy_rx_descr(E1000ECore *core, uint8_t *desc,
- struct NetRxPkt *pkt,
- const E1000E_RSSInfo *rss_info,
- uint16_t length)
-{
- uint32_t status_flags, rss, mrq;
- uint16_t ip_id;
-
- struct e1000_rx_desc *d = (struct e1000_rx_desc *) desc;
-
- memset(d, 0, sizeof(*d));
-
- assert(!rss_info->enabled);
-
- d->length = cpu_to_le16(length);
-
- e1000e_build_rx_metadata(core, pkt, pkt != NULL,
- rss_info,
- &rss, &mrq,
- &status_flags, &ip_id,
- &d->special);
- d->errors = (uint8_t) (le32_to_cpu(status_flags) >> 24);
- d->status = (uint8_t) le32_to_cpu(status_flags);
-}
-
-static inline void
-e1000e_write_ext_rx_descr(E1000ECore *core, uint8_t *desc,
- struct NetRxPkt *pkt,
- const E1000E_RSSInfo *rss_info,
- uint16_t length)
-{
- union e1000_rx_desc_extended *d = (union e1000_rx_desc_extended *) desc;
-
- memset(d, 0, sizeof(*d));
-
- d->wb.upper.length = cpu_to_le16(length);
-
- e1000e_build_rx_metadata(core, pkt, pkt != NULL,
- rss_info,
- &d->wb.lower.hi_dword.rss,
- &d->wb.lower.mrq,
- &d->wb.upper.status_error,
- &d->wb.lower.hi_dword.csum_ip.ip_id,
- &d->wb.upper.vlan);
-}
-
-static inline void
-e1000e_write_ps_rx_descr(E1000ECore *core, uint8_t *desc,
- struct NetRxPkt *pkt,
- const E1000E_RSSInfo *rss_info,
- size_t ps_hdr_len,
- uint16_t(*written)[MAX_PS_BUFFERS])
-{
- int i;
- union e1000_rx_desc_packet_split *d =
- (union e1000_rx_desc_packet_split *) desc;
-
- memset(d, 0, sizeof(*d));
-
- d->wb.middle.length0 = cpu_to_le16((*written)[0]);
-
- for (i = 0; i < PS_PAGE_BUFFERS; i++) {
- d->wb.upper.length[i] = cpu_to_le16((*written)[i + 1]);
- }
-
- e1000e_build_rx_metadata(core, pkt, pkt != NULL,
- rss_info,
- &d->wb.lower.hi_dword.rss,
- &d->wb.lower.mrq,
- &d->wb.middle.status_error,
- &d->wb.lower.hi_dword.csum_ip.ip_id,
- &d->wb.middle.vlan);
-
- d->wb.upper.header_status =
- cpu_to_le16(ps_hdr_len | (ps_hdr_len ? E1000_RXDPS_HDRSTAT_HDRSP : 0));
-
- trace_e1000e_rx_desc_ps_write((*written)[0], (*written)[1],
- (*written)[2], (*written)[3]);
-}
-
-static inline void
-e1000e_write_rx_descr(E1000ECore *core, uint8_t *desc,
-struct NetRxPkt *pkt, const E1000E_RSSInfo *rss_info,
- size_t ps_hdr_len, uint16_t(*written)[MAX_PS_BUFFERS])
-{
- if (e1000e_rx_use_legacy_descriptor(core)) {
- assert(ps_hdr_len == 0);
- e1000e_write_lgcy_rx_descr(core, desc, pkt, rss_info, (*written)[0]);
- } else {
- if (core->mac[RCTL] & E1000_RCTL_DTYP_PS) {
- e1000e_write_ps_rx_descr(core, desc, pkt, rss_info,
- ps_hdr_len, written);
- } else {
- assert(ps_hdr_len == 0);
- e1000e_write_ext_rx_descr(core, desc, pkt, rss_info,
- (*written)[0]);
- }
- }
-}
-
-typedef struct e1000e_ba_state_st {
- uint16_t written[MAX_PS_BUFFERS];
- uint8_t cur_idx;
-} e1000e_ba_state;
-
-static inline void
-e1000e_write_hdr_to_rx_buffers(E1000ECore *core,
- hwaddr (*ba)[MAX_PS_BUFFERS],
- e1000e_ba_state *bastate,
- const char *data,
- dma_addr_t data_len)
-{
- assert(data_len <= core->rxbuf_sizes[0] - bastate->written[0]);
-
- pci_dma_write(core->owner, (*ba)[0] + bastate->written[0], data, data_len);
- bastate->written[0] += data_len;
-
- bastate->cur_idx = 1;
-}
-
-static void
-e1000e_write_to_rx_buffers(E1000ECore *core,
- hwaddr (*ba)[MAX_PS_BUFFERS],
- e1000e_ba_state *bastate,
- const char *data,
- dma_addr_t data_len)
-{
- while (data_len > 0) {
- uint32_t cur_buf_len = core->rxbuf_sizes[bastate->cur_idx];
- uint32_t cur_buf_bytes_left = cur_buf_len -
- bastate->written[bastate->cur_idx];
- uint32_t bytes_to_write = MIN(data_len, cur_buf_bytes_left);
-
- trace_e1000e_rx_desc_buff_write(bastate->cur_idx,
- (*ba)[bastate->cur_idx],
- bastate->written[bastate->cur_idx],
- data,
- bytes_to_write);
-
- pci_dma_write(core->owner,
- (*ba)[bastate->cur_idx] + bastate->written[bastate->cur_idx],
- data, bytes_to_write);
-
- bastate->written[bastate->cur_idx] += bytes_to_write;
- data += bytes_to_write;
- data_len -= bytes_to_write;
-
- if (bastate->written[bastate->cur_idx] == cur_buf_len) {
- bastate->cur_idx++;
- }
-
- assert(bastate->cur_idx < MAX_PS_BUFFERS);
- }
-}
-
-static void
-e1000e_update_rx_stats(E1000ECore *core,
- size_t data_size,
- size_t data_fcs_size)
-{
- e1000x_update_rx_total_stats(core->mac, data_size, data_fcs_size);
-
- switch (net_rx_pkt_get_packet_type(core->rx_pkt)) {
- case ETH_PKT_BCAST:
- e1000x_inc_reg_if_not_full(core->mac, BPRC);
- break;
-
- case ETH_PKT_MCAST:
- e1000x_inc_reg_if_not_full(core->mac, MPRC);
- break;
-
- default:
- break;
- }
-}
-
-static inline bool
-e1000e_rx_descr_threshold_hit(E1000ECore *core, const E1000E_RingInfo *rxi)
-{
- return e1000e_ring_free_descr_num(core, rxi) ==
- e1000e_ring_len(core, rxi) >> core->rxbuf_min_shift;
-}
-
-static bool
-e1000e_do_ps(E1000ECore *core, struct NetRxPkt *pkt, size_t *hdr_len)
-{
- bool isip4, isip6, isudp, istcp;
- bool fragment;
-
- if (!e1000e_rx_use_ps_descriptor(core)) {
- return false;
- }
-
- net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
-
- if (isip4) {
- fragment = net_rx_pkt_get_ip4_info(pkt)->fragment;
- } else if (isip6) {
- fragment = net_rx_pkt_get_ip6_info(pkt)->fragment;
- } else {
- return false;
- }
-
- if (fragment && (core->mac[RFCTL] & E1000_RFCTL_IPFRSP_DIS)) {
- return false;
- }
-
- if (!fragment && (isudp || istcp)) {
- *hdr_len = net_rx_pkt_get_l5_hdr_offset(pkt);
- } else {
- *hdr_len = net_rx_pkt_get_l4_hdr_offset(pkt);
- }
-
- if ((*hdr_len > core->rxbuf_sizes[0]) ||
- (*hdr_len > net_rx_pkt_get_total_len(pkt))) {
- return false;
- }
-
- return true;
-}
-
-static void
-e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
- const E1000E_RxRing *rxr,
- const E1000E_RSSInfo *rss_info)
-{
- PCIDevice *d = core->owner;
- dma_addr_t base;
- uint8_t desc[E1000_MAX_RX_DESC_LEN];
- size_t desc_size;
- size_t desc_offset = 0;
- size_t iov_ofs = 0;
-
- struct iovec *iov = net_rx_pkt_get_iovec(pkt);
- size_t size = net_rx_pkt_get_total_len(pkt);
- size_t total_size = size + e1000x_fcs_len(core->mac);
- const E1000E_RingInfo *rxi;
- size_t ps_hdr_len = 0;
- bool do_ps = e1000e_do_ps(core, pkt, &ps_hdr_len);
-
- rxi = rxr->i;
-
- do {
- hwaddr ba[MAX_PS_BUFFERS];
- e1000e_ba_state bastate = { { 0 } };
- bool is_last = false;
- bool is_first = true;
-
- desc_size = total_size - desc_offset;
-
- if (desc_size > core->rx_desc_buf_size) {
- desc_size = core->rx_desc_buf_size;
- }
-
- base = e1000e_ring_head_descr(core, rxi);
-
- pci_dma_read(d, base, &desc, core->rx_desc_len);
-
- trace_e1000e_rx_descr(rxi->idx, base, core->rx_desc_len);
-
- e1000e_read_rx_descr(core, desc, &ba);
-
- if (ba[0]) {
- if (desc_offset < size) {
- static const uint32_t fcs_pad;
- size_t iov_copy;
- size_t copy_size = size - desc_offset;
- if (copy_size > core->rx_desc_buf_size) {
- copy_size = core->rx_desc_buf_size;
- }
-
- /* For PS mode copy the packet header first */
- if (do_ps) {
- if (is_first) {
- size_t ps_hdr_copied = 0;
- do {
- iov_copy = MIN(ps_hdr_len - ps_hdr_copied,
- iov->iov_len - iov_ofs);
-
- e1000e_write_hdr_to_rx_buffers(core, &ba, &bastate,
- iov->iov_base, iov_copy);
-
- copy_size -= iov_copy;
- ps_hdr_copied += iov_copy;
-
- iov_ofs += iov_copy;
- if (iov_ofs == iov->iov_len) {
- iov++;
- iov_ofs = 0;
- }
- } while (ps_hdr_copied < ps_hdr_len);
-
- is_first = false;
- } else {
- /* Leave buffer 0 of each descriptor except first */
- /* empty as per spec 7.1.5.1 */
- e1000e_write_hdr_to_rx_buffers(core, &ba, &bastate,
- NULL, 0);
- }
- }
-
- /* Copy packet payload */
- while (copy_size) {
- iov_copy = MIN(copy_size, iov->iov_len - iov_ofs);
-
- e1000e_write_to_rx_buffers(core, &ba, &bastate,
- iov->iov_base + iov_ofs, iov_copy);
-
- copy_size -= iov_copy;
- iov_ofs += iov_copy;
- if (iov_ofs == iov->iov_len) {
- iov++;
- iov_ofs = 0;
- }
- }
-
- if (desc_offset + desc_size >= total_size) {
- /* Simulate FCS checksum presence in the last descriptor */
- e1000e_write_to_rx_buffers(core, &ba, &bastate,
- (const char *) &fcs_pad, e1000x_fcs_len(core->mac));
- }
- }
- desc_offset += desc_size;
- if (desc_offset >= total_size) {
- is_last = true;
- }
- } else { /* as per intel docs; skip descriptors with null buf addr */
- trace_e1000e_rx_null_descriptor();
- }
-
- e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL,
- rss_info, do_ps ? ps_hdr_len : 0, &bastate.written);
- pci_dma_write(d, base, &desc, core->rx_desc_len);
-
- e1000e_ring_advance(core, rxi,
- core->rx_desc_len / E1000_MIN_RX_DESC_LEN);
-
- } while (desc_offset < total_size);
-
- e1000e_update_rx_stats(core, size, total_size);
-}
-
-static inline void
-e1000e_rx_fix_l4_csum(E1000ECore *core, struct NetRxPkt *pkt)
-{
- if (net_rx_pkt_has_virt_hdr(pkt)) {
- struct virtio_net_hdr *vhdr = net_rx_pkt_get_vhdr(pkt);
-
- if (vhdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
- net_rx_pkt_fix_l4_csum(pkt);
- }
- }
-}
-
-ssize_t
-e1000e_receive_iov(E1000ECore *core, const struct iovec *iov, int iovcnt)
-{
- static const int maximum_ethernet_hdr_len = (14 + 4);
- /* Min. octets in an ethernet frame sans FCS */
- static const int min_buf_size = 60;
-
- uint32_t n = 0;
- uint8_t min_buf[min_buf_size];
- struct iovec min_iov;
- uint8_t *filter_buf;
- size_t size, orig_size;
- size_t iov_ofs = 0;
- E1000E_RxRing rxr;
- E1000E_RSSInfo rss_info;
- size_t total_size;
- ssize_t retval;
- bool rdmts_hit;
-
- trace_e1000e_rx_receive_iov(iovcnt);
-
- if (!e1000x_hw_rx_enabled(core->mac)) {
- return -1;
- }
-
- /* Pull virtio header in */
- if (core->has_vnet) {
- net_rx_pkt_set_vhdr_iovec(core->rx_pkt, iov, iovcnt);
- iov_ofs = sizeof(struct virtio_net_hdr);
- }
-
- filter_buf = iov->iov_base + iov_ofs;
- orig_size = iov_size(iov, iovcnt);
- size = orig_size - iov_ofs;
-
- /* Pad to minimum Ethernet frame length */
- if (size < sizeof(min_buf)) {
- iov_to_buf(iov, iovcnt, iov_ofs, min_buf, size);
- memset(&min_buf[size], 0, sizeof(min_buf) - size);
- e1000x_inc_reg_if_not_full(core->mac, RUC);
- min_iov.iov_base = filter_buf = min_buf;
- min_iov.iov_len = size = sizeof(min_buf);
- iovcnt = 1;
- iov = &min_iov;
- iov_ofs = 0;
- } else if (iov->iov_len < maximum_ethernet_hdr_len) {
- /* This is very unlikely, but may happen. */
- iov_to_buf(iov, iovcnt, iov_ofs, min_buf, maximum_ethernet_hdr_len);
- filter_buf = min_buf;
- }
-
- /* Discard oversized packets if !LPE and !SBP. */
- if (e1000x_is_oversized(core->mac, size)) {
- return orig_size;
- }
-
- net_rx_pkt_set_packet_type(core->rx_pkt,
- get_eth_packet_type(PKT_GET_ETH_HDR(filter_buf)));
-
- if (!e1000e_receive_filter(core, filter_buf, size)) {
- trace_e1000e_rx_flt_dropped();
- return orig_size;
- }
-
- net_rx_pkt_attach_iovec_ex(core->rx_pkt, iov, iovcnt, iov_ofs,
- e1000x_vlan_enabled(core->mac), core->vet);
-
- e1000e_rss_parse_packet(core, core->rx_pkt, &rss_info);
- e1000e_rx_ring_init(core, &rxr, rss_info.queue);
-
- trace_e1000e_rx_rss_dispatched_to_queue(rxr.i->idx);
-
- total_size = net_rx_pkt_get_total_len(core->rx_pkt) +
- e1000x_fcs_len(core->mac);
-
- if (e1000e_has_rxbufs(core, rxr.i, total_size)) {
- e1000e_rx_fix_l4_csum(core, core->rx_pkt);
-
- e1000e_write_packet_to_guest(core, core->rx_pkt, &rxr, &rss_info);
-
- retval = orig_size;
-
- /* Perform small receive detection (RSRPD) */
- if (total_size < core->mac[RSRPD]) {
- n |= E1000_ICS_SRPD;
- }
-
- /* Perform ACK receive detection */
- if (e1000e_is_tcp_ack(core, core->rx_pkt)) {
- n |= E1000_ICS_ACK;
- }
-
- /* Check if receive descriptor minimum threshold hit */
- rdmts_hit = e1000e_rx_descr_threshold_hit(core, rxr.i);
- n |= e1000e_rx_wb_interrupt_cause(core, rxr.i->idx, rdmts_hit);
-
- trace_e1000e_rx_written_to_guest(n);
- } else {
- n |= E1000_ICS_RXO;
- retval = 0;
-
- trace_e1000e_rx_not_written_to_guest(n);
- }
-
- if (!e1000e_intrmgr_delay_rx_causes(core, &n)) {
- trace_e1000e_rx_interrupt_set(n);
- e1000e_set_interrupt_cause(core, n);
- } else {
- trace_e1000e_rx_interrupt_delayed(n);
- }
-
- return retval;
-}
-
-static inline bool
-e1000e_have_autoneg(E1000ECore *core)
-{
- return core->phy[0][PHY_CTRL] & MII_CR_AUTO_NEG_EN;
-}
-
-static void e1000e_update_flowctl_status(E1000ECore *core)
-{
- if (e1000e_have_autoneg(core) &&
- core->phy[0][PHY_STATUS] & MII_SR_AUTONEG_COMPLETE) {
- trace_e1000e_link_autoneg_flowctl(true);
- core->mac[CTRL] |= E1000_CTRL_TFCE | E1000_CTRL_RFCE;
- } else {
- trace_e1000e_link_autoneg_flowctl(false);
- }
-}
-
-static inline void
-e1000e_link_down(E1000ECore *core)
-{
- e1000x_update_regs_on_link_down(core->mac, core->phy[0]);
- e1000e_update_flowctl_status(core);
-}
-
-static inline void
-e1000e_set_phy_ctrl(E1000ECore *core, int index, uint16_t val)
-{
- /* bits 0-5 reserved; MII_CR_[RESTART_AUTO_NEG,RESET] are self clearing */
- core->phy[0][PHY_CTRL] = val & ~(0x3f |
- MII_CR_RESET |
- MII_CR_RESTART_AUTO_NEG);
-
- if ((val & MII_CR_RESTART_AUTO_NEG) &&
- e1000e_have_autoneg(core)) {
- e1000x_restart_autoneg(core->mac, core->phy[0], core->autoneg_timer);
- }
-}
-
-static void
-e1000e_set_phy_oem_bits(E1000ECore *core, int index, uint16_t val)
-{
- core->phy[0][PHY_OEM_BITS] = val & ~BIT(10);
-
- if (val & BIT(10)) {
- e1000x_restart_autoneg(core->mac, core->phy[0], core->autoneg_timer);
- }
-}
-
-static void
-e1000e_set_phy_page(E1000ECore *core, int index, uint16_t val)
-{
- core->phy[0][PHY_PAGE] = val & PHY_PAGE_RW_MASK;
-}
-
-void
-e1000e_core_set_link_status(E1000ECore *core)
-{
- NetClientState *nc = qemu_get_queue(core->owner_nic);
- uint32_t old_status = core->mac[STATUS];
-
- trace_e1000e_link_status_changed(nc->link_down ? false : true);
-
- if (nc->link_down) {
- e1000x_update_regs_on_link_down(core->mac, core->phy[0]);
- } else {
- if (e1000e_have_autoneg(core) &&
- !(core->phy[0][PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
- e1000x_restart_autoneg(core->mac, core->phy[0],
- core->autoneg_timer);
- } else {
- e1000x_update_regs_on_link_up(core->mac, core->phy[0]);
- }
- }
-
- if (core->mac[STATUS] != old_status) {
- e1000e_set_interrupt_cause(core, E1000_ICR_LSC);
- }
-}
-
-static void
-e1000e_set_ctrl(E1000ECore *core, int index, uint32_t val)
-{
- trace_e1000e_core_ctrl_write(index, val);
-
- /* RST is self clearing */
- core->mac[CTRL] = val & ~E1000_CTRL_RST;
- core->mac[CTRL_DUP] = core->mac[CTRL];
-
- trace_e1000e_link_set_params(
- !!(val & E1000_CTRL_ASDE),
- (val & E1000_CTRL_SPD_SEL) >> E1000_CTRL_SPD_SHIFT,
- !!(val & E1000_CTRL_FRCSPD),
- !!(val & E1000_CTRL_FRCDPX),
- !!(val & E1000_CTRL_RFCE),
- !!(val & E1000_CTRL_TFCE));
-
- if (val & E1000_CTRL_RST) {
- trace_e1000e_core_ctrl_sw_reset();
- e1000x_reset_mac_addr(core->owner_nic, core->mac, core->permanent_mac);
- }
-
- if (val & E1000_CTRL_PHY_RST) {
- trace_e1000e_core_ctrl_phy_reset();
- core->mac[STATUS] |= E1000_STATUS_PHYRA;
- }
-}
-
-static void
-e1000e_set_rfctl(E1000ECore *core, int index, uint32_t val)
-{
- trace_e1000e_rx_set_rfctl(val);
-
- if (!(val & E1000_RFCTL_ISCSI_DIS)) {
- trace_e1000e_wrn_iscsi_filtering_not_supported();
- }
-
- if (!(val & E1000_RFCTL_NFSW_DIS)) {
- trace_e1000e_wrn_nfsw_filtering_not_supported();
- }
-
- if (!(val & E1000_RFCTL_NFSR_DIS)) {
- trace_e1000e_wrn_nfsr_filtering_not_supported();
- }
-
- core->mac[RFCTL] = val;
-}
-
-static void
-e1000e_calc_per_desc_buf_size(E1000ECore *core)
-{
- int i;
- core->rx_desc_buf_size = 0;
-
- for (i = 0; i < ARRAY_SIZE(core->rxbuf_sizes); i++) {
- core->rx_desc_buf_size += core->rxbuf_sizes[i];
- }
-}
-
-static void
-e1000e_parse_rxbufsize(E1000ECore *core)
-{
- uint32_t rctl = core->mac[RCTL];
-
- memset(core->rxbuf_sizes, 0, sizeof(core->rxbuf_sizes));
-
- if (rctl & E1000_RCTL_DTYP_MASK) {
- uint32_t bsize;
-
- bsize = core->mac[PSRCTL] & E1000_PSRCTL_BSIZE0_MASK;
- core->rxbuf_sizes[0] = (bsize >> E1000_PSRCTL_BSIZE0_SHIFT) * 128;
-
- bsize = core->mac[PSRCTL] & E1000_PSRCTL_BSIZE1_MASK;
- core->rxbuf_sizes[1] = (bsize >> E1000_PSRCTL_BSIZE1_SHIFT) * 1024;
-
- bsize = core->mac[PSRCTL] & E1000_PSRCTL_BSIZE2_MASK;
- core->rxbuf_sizes[2] = (bsize >> E1000_PSRCTL_BSIZE2_SHIFT) * 1024;
-
- bsize = core->mac[PSRCTL] & E1000_PSRCTL_BSIZE3_MASK;
- core->rxbuf_sizes[3] = (bsize >> E1000_PSRCTL_BSIZE3_SHIFT) * 1024;
- } else if (rctl & E1000_RCTL_FLXBUF_MASK) {
- int flxbuf = rctl & E1000_RCTL_FLXBUF_MASK;
- core->rxbuf_sizes[0] = (flxbuf >> E1000_RCTL_FLXBUF_SHIFT) * 1024;
- } else {
- core->rxbuf_sizes[0] = e1000x_rxbufsize(rctl);
- }
-
- trace_e1000e_rx_desc_buff_sizes(core->rxbuf_sizes[0], core->rxbuf_sizes[1],
- core->rxbuf_sizes[2], core->rxbuf_sizes[3]);
-
- e1000e_calc_per_desc_buf_size(core);
-}
-
-static void
-e1000e_calc_rxdesclen(E1000ECore *core)
-{
- if (e1000e_rx_use_legacy_descriptor(core)) {
- core->rx_desc_len = sizeof(struct e1000_rx_desc);
- } else {
- if (core->mac[RCTL] & E1000_RCTL_DTYP_PS) {
- core->rx_desc_len = sizeof(union e1000_rx_desc_packet_split);
- } else {
- core->rx_desc_len = sizeof(union e1000_rx_desc_extended);
- }
- }
- trace_e1000e_rx_desc_len(core->rx_desc_len);
-}
-
-static void
-e1000e_set_rx_control(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[RCTL] = val;
- trace_e1000e_rx_set_rctl(core->mac[RCTL]);
-
- if (val & E1000_RCTL_EN) {
- e1000e_parse_rxbufsize(core);
- e1000e_calc_rxdesclen(core);
- core->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1 +
- E1000_RING_DESC_LEN_SHIFT;
-
- e1000e_start_recv(core);
- }
-}
-
-static
-void(*e1000e_phyreg_writeops[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE])
-(E1000ECore *, int, uint16_t) = {
- [0] = {
- [PHY_CTRL] = e1000e_set_phy_ctrl,
- [PHY_PAGE] = e1000e_set_phy_page,
- [PHY_OEM_BITS] = e1000e_set_phy_oem_bits
- }
-};
-
-static inline void
-e1000e_clear_ims_bits(E1000ECore *core, uint32_t bits)
-{
- trace_e1000e_irq_clear_ims(bits, core->mac[IMS], core->mac[IMS] & ~bits);
- core->mac[IMS] &= ~bits;
-}
-
-static inline bool
-e1000e_postpone_interrupt(bool *interrupt_pending,
- E1000IntrDelayTimer *timer)
-{
- if (timer->running) {
- trace_e1000e_irq_postponed_by_xitr(timer->delay_reg << 2);
-
- *interrupt_pending = true;
- return true;
- }
-
- if (timer->core->mac[timer->delay_reg] != 0) {
- e1000e_intrmgr_rearm_timer(timer);
- }
-
- return false;
-}
-
-static inline bool
-e1000e_itr_should_postpone(E1000ECore *core)
-{
- return e1000e_postpone_interrupt(&core->itr_intr_pending, &core->itr);
-}
-
-static inline bool
-e1000e_eitr_should_postpone(E1000ECore *core, int idx)
-{
- return e1000e_postpone_interrupt(&core->eitr_intr_pending[idx],
- &core->eitr[idx]);
-}
-
-static void
-e1000e_msix_notify_one(E1000ECore *core, uint32_t cause, uint32_t int_cfg)
-{
- uint32_t effective_eiac;
-
- if (E1000_IVAR_ENTRY_VALID(int_cfg)) {
- uint32_t vec = E1000_IVAR_ENTRY_VEC(int_cfg);
- if (vec < E1000E_MSIX_VEC_NUM) {
- if (!e1000e_eitr_should_postpone(core, vec)) {
- trace_e1000e_irq_msix_notify_vec(vec);
- msix_notify(core->owner, vec);
- }
- } else {
- trace_e1000e_wrn_msix_vec_wrong(cause, int_cfg);
- }
- } else {
- trace_e1000e_wrn_msix_invalid(cause, int_cfg);
- }
-
- if (core->mac[CTRL_EXT] & E1000_CTRL_EXT_EIAME) {
- trace_e1000e_irq_ims_clear_eiame(core->mac[IAM], cause);
- e1000e_clear_ims_bits(core, core->mac[IAM] & cause);
- }
-
- trace_e1000e_irq_icr_clear_eiac(core->mac[ICR], core->mac[EIAC]);
-
- if (core->mac[EIAC] & E1000_ICR_OTHER) {
- effective_eiac = (core->mac[EIAC] & E1000_EIAC_MASK) |
- E1000_ICR_OTHER_CAUSES;
- } else {
- effective_eiac = core->mac[EIAC] & E1000_EIAC_MASK;
- }
- core->mac[ICR] &= ~effective_eiac;
-}
-
-static void
-e1000e_msix_notify(E1000ECore *core, uint32_t causes)
-{
- if (causes & E1000_ICR_RXQ0) {
- e1000e_msix_notify_one(core, E1000_ICR_RXQ0,
- E1000_IVAR_RXQ0(core->mac[IVAR]));
- }
-
- if (causes & E1000_ICR_RXQ1) {
- e1000e_msix_notify_one(core, E1000_ICR_RXQ1,
- E1000_IVAR_RXQ1(core->mac[IVAR]));
- }
-
- if (causes & E1000_ICR_TXQ0) {
- e1000e_msix_notify_one(core, E1000_ICR_TXQ0,
- E1000_IVAR_TXQ0(core->mac[IVAR]));
- }
-
- if (causes & E1000_ICR_TXQ1) {
- e1000e_msix_notify_one(core, E1000_ICR_TXQ1,
- E1000_IVAR_TXQ1(core->mac[IVAR]));
- }
-
- if (causes & E1000_ICR_OTHER) {
- e1000e_msix_notify_one(core, E1000_ICR_OTHER,
- E1000_IVAR_OTHER(core->mac[IVAR]));
- }
-}
-
-static void
-e1000e_msix_clear_one(E1000ECore *core, uint32_t cause, uint32_t int_cfg)
-{
- if (E1000_IVAR_ENTRY_VALID(int_cfg)) {
- uint32_t vec = E1000_IVAR_ENTRY_VEC(int_cfg);
- if (vec < E1000E_MSIX_VEC_NUM) {
- trace_e1000e_irq_msix_pending_clearing(cause, int_cfg, vec);
- msix_clr_pending(core->owner, vec);
- } else {
- trace_e1000e_wrn_msix_vec_wrong(cause, int_cfg);
- }
- } else {
- trace_e1000e_wrn_msix_invalid(cause, int_cfg);
- }
-}
-
-static void
-e1000e_msix_clear(E1000ECore *core, uint32_t causes)
-{
- if (causes & E1000_ICR_RXQ0) {
- e1000e_msix_clear_one(core, E1000_ICR_RXQ0,
- E1000_IVAR_RXQ0(core->mac[IVAR]));
- }
-
- if (causes & E1000_ICR_RXQ1) {
- e1000e_msix_clear_one(core, E1000_ICR_RXQ1,
- E1000_IVAR_RXQ1(core->mac[IVAR]));
- }
-
- if (causes & E1000_ICR_TXQ0) {
- e1000e_msix_clear_one(core, E1000_ICR_TXQ0,
- E1000_IVAR_TXQ0(core->mac[IVAR]));
- }
-
- if (causes & E1000_ICR_TXQ1) {
- e1000e_msix_clear_one(core, E1000_ICR_TXQ1,
- E1000_IVAR_TXQ1(core->mac[IVAR]));
- }
-
- if (causes & E1000_ICR_OTHER) {
- e1000e_msix_clear_one(core, E1000_ICR_OTHER,
- E1000_IVAR_OTHER(core->mac[IVAR]));
- }
-}
-
-static inline void
-e1000e_fix_icr_asserted(E1000ECore *core)
-{
- core->mac[ICR] &= ~E1000_ICR_ASSERTED;
- if (core->mac[ICR]) {
- core->mac[ICR] |= E1000_ICR_ASSERTED;
- }
-
- trace_e1000e_irq_fix_icr_asserted(core->mac[ICR]);
-}
-
-static void
-e1000e_send_msi(E1000ECore *core, bool msix)
-{
- uint32_t causes = core->mac[ICR] & core->mac[IMS] & ~E1000_ICR_ASSERTED;
-
- if (msix) {
- e1000e_msix_notify(core, causes);
- } else {
- if (!e1000e_itr_should_postpone(core)) {
- trace_e1000e_irq_msi_notify(causes);
- msi_notify(core->owner, 0);
- }
- }
-}
-
-static void
-e1000e_update_interrupt_state(E1000ECore *core)
-{
- bool interrupts_pending;
- bool is_msix = msix_enabled(core->owner);
-
- /* Set ICR[OTHER] for MSI-X */
- if (is_msix) {
- if (core->mac[ICR] & core->mac[IMS] & E1000_ICR_OTHER_CAUSES) {
- core->mac[ICR] |= E1000_ICR_OTHER;
- trace_e1000e_irq_add_msi_other(core->mac[ICR]);
- }
- }
-
- e1000e_fix_icr_asserted(core);
-
- /*
- * Make sure ICR and ICS registers have the same value.
- * The spec says that the ICS register is write-only. However in practice,
- * on real hardware ICS is readable, and for reads it has the same value as
- * ICR (except that ICS does not have the clear on read behaviour of ICR).
- *
- * The VxWorks PRO/1000 driver uses this behaviour.
- */
- core->mac[ICS] = core->mac[ICR];
-
- interrupts_pending = (core->mac[IMS] & core->mac[ICR]) ? true : false;
-
- trace_e1000e_irq_pending_interrupts(core->mac[ICR] & core->mac[IMS],
- core->mac[ICR], core->mac[IMS]);
-
- if (is_msix || msi_enabled(core->owner)) {
- if (interrupts_pending) {
- e1000e_send_msi(core, is_msix);
- }
- } else {
- if (interrupts_pending) {
- if (!e1000e_itr_should_postpone(core)) {
- e1000e_raise_legacy_irq(core);
- }
- } else {
- e1000e_lower_legacy_irq(core);
- }
- }
-}
-
-static inline void
-e1000e_set_interrupt_cause(E1000ECore *core, uint32_t val)
-{
- trace_e1000e_irq_set_cause_entry(val, core->mac[ICR]);
-
- val |= e1000e_intmgr_collect_delayed_causes(core);
- core->mac[ICR] |= val;
-
- trace_e1000e_irq_set_cause_exit(val, core->mac[ICR]);
-
- e1000e_update_interrupt_state(core);
-}
-
-static inline void
-e1000e_autoneg_timer(void *opaque)
-{
- E1000ECore *core = opaque;
- if (!qemu_get_queue(core->owner_nic)->link_down) {
- e1000x_update_regs_on_autoneg_done(core->mac, core->phy[0]);
- e1000e_update_flowctl_status(core);
- /* signal link status change to the guest */
- e1000e_set_interrupt_cause(core, E1000_ICR_LSC);
- }
-}
-
-static inline uint16_t
-e1000e_get_reg_index_with_offset(const uint16_t *mac_reg_access, hwaddr addr)
-{
- uint16_t index = (addr & 0x1ffff) >> 2;
- return index + (mac_reg_access[index] & 0xfffe);
-}
-
-static const char e1000e_phy_regcap[E1000E_PHY_PAGES][0x20] = {
- [0] = {
- [PHY_CTRL] = PHY_ANYPAGE | PHY_RW,
- [PHY_STATUS] = PHY_ANYPAGE | PHY_R,
- [PHY_ID1] = PHY_ANYPAGE | PHY_R,
- [PHY_ID2] = PHY_ANYPAGE | PHY_R,
- [PHY_AUTONEG_ADV] = PHY_ANYPAGE | PHY_RW,
- [PHY_LP_ABILITY] = PHY_ANYPAGE | PHY_R,
- [PHY_AUTONEG_EXP] = PHY_ANYPAGE | PHY_R,
- [PHY_NEXT_PAGE_TX] = PHY_ANYPAGE | PHY_RW,
- [PHY_LP_NEXT_PAGE] = PHY_ANYPAGE | PHY_R,
- [PHY_1000T_CTRL] = PHY_ANYPAGE | PHY_RW,
- [PHY_1000T_STATUS] = PHY_ANYPAGE | PHY_R,
- [PHY_EXT_STATUS] = PHY_ANYPAGE | PHY_R,
- [PHY_PAGE] = PHY_ANYPAGE | PHY_RW,
-
- [PHY_COPPER_CTRL1] = PHY_RW,
- [PHY_COPPER_STAT1] = PHY_R,
- [PHY_COPPER_CTRL3] = PHY_RW,
- [PHY_RX_ERR_CNTR] = PHY_R,
- [PHY_OEM_BITS] = PHY_RW,
- [PHY_BIAS_1] = PHY_RW,
- [PHY_BIAS_2] = PHY_RW,
- [PHY_COPPER_INT_ENABLE] = PHY_RW,
- [PHY_COPPER_STAT2] = PHY_R,
- [PHY_COPPER_CTRL2] = PHY_RW
- },
- [2] = {
- [PHY_MAC_CTRL1] = PHY_RW,
- [PHY_MAC_INT_ENABLE] = PHY_RW,
- [PHY_MAC_STAT] = PHY_R,
- [PHY_MAC_CTRL2] = PHY_RW
- },
- [3] = {
- [PHY_LED_03_FUNC_CTRL1] = PHY_RW,
- [PHY_LED_03_POL_CTRL] = PHY_RW,
- [PHY_LED_TIMER_CTRL] = PHY_RW,
- [PHY_LED_45_CTRL] = PHY_RW
- },
- [5] = {
- [PHY_1000T_SKEW] = PHY_R,
- [PHY_1000T_SWAP] = PHY_R
- },
- [6] = {
- [PHY_CRC_COUNTERS] = PHY_R
- }
-};
-
-static bool
-e1000e_phy_reg_check_cap(E1000ECore *core, uint32_t addr,
- char cap, uint8_t *page)
-{
- *page =
- (e1000e_phy_regcap[0][addr] & PHY_ANYPAGE) ? 0
- : core->phy[0][PHY_PAGE];
-
- if (*page >= E1000E_PHY_PAGES) {
- return false;
- }
-
- return e1000e_phy_regcap[*page][addr] & cap;
-}
-
-static void
-e1000e_phy_reg_write(E1000ECore *core, uint8_t page,
- uint32_t addr, uint16_t data)
-{
- assert(page < E1000E_PHY_PAGES);
- assert(addr < E1000E_PHY_PAGE_SIZE);
-
- if (e1000e_phyreg_writeops[page][addr]) {
- e1000e_phyreg_writeops[page][addr](core, addr, data);
- } else {
- core->phy[page][addr] = data;
- }
-}
-
-static void
-e1000e_set_mdic(E1000ECore *core, int index, uint32_t val)
-{
- uint32_t data = val & E1000_MDIC_DATA_MASK;
- uint32_t addr = ((val & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
- uint8_t page;
-
- if ((val & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) { /* phy # */
- val = core->mac[MDIC] | E1000_MDIC_ERROR;
- } else if (val & E1000_MDIC_OP_READ) {
- if (!e1000e_phy_reg_check_cap(core, addr, PHY_R, &page)) {
- trace_e1000e_core_mdic_read_unhandled(page, addr);
- val |= E1000_MDIC_ERROR;
- } else {
- val = (val ^ data) | core->phy[page][addr];
- trace_e1000e_core_mdic_read(page, addr, val);
- }
- } else if (val & E1000_MDIC_OP_WRITE) {
- if (!e1000e_phy_reg_check_cap(core, addr, PHY_W, &page)) {
- trace_e1000e_core_mdic_write_unhandled(page, addr);
- val |= E1000_MDIC_ERROR;
- } else {
- trace_e1000e_core_mdic_write(page, addr, data);
- e1000e_phy_reg_write(core, page, addr, data);
- }
- }
- core->mac[MDIC] = val | E1000_MDIC_READY;
-
- if (val & E1000_MDIC_INT_EN) {
- e1000e_set_interrupt_cause(core, E1000_ICR_MDAC);
- }
-}
-
-static void
-e1000e_set_rdt(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[index] = val & 0xffff;
- trace_e1000e_rx_set_rdt(e1000e_mq_queue_idx(RDT0, index), val);
- e1000e_start_recv(core);
-}
-
-static void
-e1000e_set_status(E1000ECore *core, int index, uint32_t val)
-{
- if ((val & E1000_STATUS_PHYRA) == 0) {
- core->mac[index] &= ~E1000_STATUS_PHYRA;
- }
-}
-
-static void
-e1000e_set_ctrlext(E1000ECore *core, int index, uint32_t val)
-{
- trace_e1000e_link_set_ext_params(!!(val & E1000_CTRL_EXT_ASDCHK),
- !!(val & E1000_CTRL_EXT_SPD_BYPS));
-
- /* Zero self-clearing bits */
- val &= ~(E1000_CTRL_EXT_ASDCHK | E1000_CTRL_EXT_EE_RST);
- core->mac[CTRL_EXT] = val;
-}
-
-static void
-e1000e_set_pbaclr(E1000ECore *core, int index, uint32_t val)
-{
- int i;
-
- core->mac[PBACLR] = val & E1000_PBACLR_VALID_MASK;
-
- if (msix_enabled(core->owner)) {
- return;
- }
-
- for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
- if (core->mac[PBACLR] & BIT(i)) {
- msix_clr_pending(core->owner, i);
- }
- }
-}
-
-static void
-e1000e_set_fcrth(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[FCRTH] = val & 0xFFF8;
-}
-
-static void
-e1000e_set_fcrtl(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[FCRTL] = val & 0x8000FFF8;
-}
-
-static inline void
-e1000e_set_16bit(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[index] = val & 0xffff;
-}
-
-static void
-e1000e_set_12bit(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[index] = val & 0xfff;
-}
-
-static void
-e1000e_set_vet(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[VET] = val & 0xffff;
- core->vet = le16_to_cpu(core->mac[VET]);
- trace_e1000e_vlan_vet(core->vet);
-}
-
-static void
-e1000e_set_dlen(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[index] = val & E1000_XDLEN_MASK;
-}
-
-static void
-e1000e_set_dbal(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[index] = val & E1000_XDBAL_MASK;
-}
-
-static void
-e1000e_set_tctl(E1000ECore *core, int index, uint32_t val)
-{
- E1000E_TxRing txr;
- core->mac[index] = val;
-
- if (core->mac[TARC0] & E1000_TARC_ENABLE) {
- e1000e_tx_ring_init(core, &txr, 0);
- e1000e_start_xmit(core, &txr);
- }
-
- if (core->mac[TARC1] & E1000_TARC_ENABLE) {
- e1000e_tx_ring_init(core, &txr, 1);
- e1000e_start_xmit(core, &txr);
- }
-}
-
-static void
-e1000e_set_tdt(E1000ECore *core, int index, uint32_t val)
-{
- E1000E_TxRing txr;
- int qidx = e1000e_mq_queue_idx(TDT, index);
- uint32_t tarc_reg = (qidx == 0) ? TARC0 : TARC1;
-
- core->mac[index] = val & 0xffff;
-
- if (core->mac[tarc_reg] & E1000_TARC_ENABLE) {
- e1000e_tx_ring_init(core, &txr, qidx);
- e1000e_start_xmit(core, &txr);
- }
-}
-
-static void
-e1000e_set_ics(E1000ECore *core, int index, uint32_t val)
-{
- trace_e1000e_irq_write_ics(val);
- e1000e_set_interrupt_cause(core, val);
-}
-
-static void
-e1000e_set_icr(E1000ECore *core, int index, uint32_t val)
-{
- if ((core->mac[ICR] & E1000_ICR_ASSERTED) &&
- (core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) {
- trace_e1000e_irq_icr_process_iame();
- e1000e_clear_ims_bits(core, core->mac[IAM]);
- }
-
- trace_e1000e_irq_icr_write(val, core->mac[ICR], core->mac[ICR] & ~val);
- core->mac[ICR] &= ~val;
- e1000e_update_interrupt_state(core);
-}
-
-static void
-e1000e_set_imc(E1000ECore *core, int index, uint32_t val)
-{
- trace_e1000e_irq_ims_clear_set_imc(val);
- e1000e_clear_ims_bits(core, val);
- e1000e_update_interrupt_state(core);
-}
-
-static void
-e1000e_set_ims(E1000ECore *core, int index, uint32_t val)
-{
- static const uint32_t ims_ext_mask =
- E1000_IMS_RXQ0 | E1000_IMS_RXQ1 |
- E1000_IMS_TXQ0 | E1000_IMS_TXQ1 |
- E1000_IMS_OTHER;
-
- static const uint32_t ims_valid_mask =
- E1000_IMS_TXDW | E1000_IMS_TXQE | E1000_IMS_LSC |
- E1000_IMS_RXDMT0 | E1000_IMS_RXO | E1000_IMS_RXT0 |
- E1000_IMS_MDAC | E1000_IMS_TXD_LOW | E1000_IMS_SRPD |
- E1000_IMS_ACK | E1000_IMS_MNG | E1000_IMS_RXQ0 |
- E1000_IMS_RXQ1 | E1000_IMS_TXQ0 | E1000_IMS_TXQ1 |
- E1000_IMS_OTHER;
-
- uint32_t valid_val = val & ims_valid_mask;
-
- trace_e1000e_irq_set_ims(val, core->mac[IMS], core->mac[IMS] | valid_val);
- core->mac[IMS] |= valid_val;
-
- if ((valid_val & ims_ext_mask) &&
- (core->mac[CTRL_EXT] & E1000_CTRL_EXT_PBA_CLR) &&
- msix_enabled(core->owner)) {
- e1000e_msix_clear(core, valid_val);
- }
-
- if ((valid_val == ims_valid_mask) &&
- (core->mac[CTRL_EXT] & E1000_CTRL_EXT_INT_TIMERS_CLEAR_ENA)) {
- trace_e1000e_irq_fire_all_timers(val);
- e1000e_intrmgr_fire_all_timers(core);
- }
-
- e1000e_update_interrupt_state(core);
-}
-
-static void
-e1000e_set_rdtr(E1000ECore *core, int index, uint32_t val)
-{
- e1000e_set_16bit(core, index, val);
-
- if ((val & E1000_RDTR_FPD) && (core->rdtr.running)) {
- trace_e1000e_irq_rdtr_fpd_running();
- e1000e_intrmgr_fire_delayed_interrupts(core);
- } else {
- trace_e1000e_irq_rdtr_fpd_not_running();
- }
-}
-
-static void
-e1000e_set_tidv(E1000ECore *core, int index, uint32_t val)
-{
- e1000e_set_16bit(core, index, val);
-
- if ((val & E1000_TIDV_FPD) && (core->tidv.running)) {
- trace_e1000e_irq_tidv_fpd_running();
- e1000e_intrmgr_fire_delayed_interrupts(core);
- } else {
- trace_e1000e_irq_tidv_fpd_not_running();
- }
-}
-
-static uint32_t
-e1000e_mac_readreg(E1000ECore *core, int index)
-{
- return core->mac[index];
-}
-
-static uint32_t
-e1000e_mac_ics_read(E1000ECore *core, int index)
-{
- trace_e1000e_irq_read_ics(core->mac[ICS]);
- return core->mac[ICS];
-}
-
-static uint32_t
-e1000e_mac_ims_read(E1000ECore *core, int index)
-{
- trace_e1000e_irq_read_ims(core->mac[IMS]);
- return core->mac[IMS];
-}
-
-#define E1000E_LOW_BITS_READ_FUNC(num) \
- static uint32_t \
- e1000e_mac_low##num##_read(E1000ECore *core, int index) \
- { \
- return core->mac[index] & (BIT(num) - 1); \
- } \
-
-#define E1000E_LOW_BITS_READ(num) \
- e1000e_mac_low##num##_read
-
-E1000E_LOW_BITS_READ_FUNC(4);
-E1000E_LOW_BITS_READ_FUNC(6);
-E1000E_LOW_BITS_READ_FUNC(11);
-E1000E_LOW_BITS_READ_FUNC(13);
-E1000E_LOW_BITS_READ_FUNC(16);
-
-static uint32_t
-e1000e_mac_swsm_read(E1000ECore *core, int index)
-{
- uint32_t val = core->mac[SWSM];
- core->mac[SWSM] = val | 1;
- return val;
-}
-
-static uint32_t
-e1000e_mac_itr_read(E1000ECore *core, int index)
-{
- return core->itr_guest_value;
-}
-
-static uint32_t
-e1000e_mac_eitr_read(E1000ECore *core, int index)
-{
- return core->eitr_guest_value[index - EITR];
-}
-
-static uint32_t
-e1000e_mac_icr_read(E1000ECore *core, int index)
-{
- uint32_t ret = core->mac[ICR];
- trace_e1000e_irq_icr_read_entry(ret);
-
- if (core->mac[IMS] == 0) {
- trace_e1000e_irq_icr_clear_zero_ims();
- core->mac[ICR] = 0;
- }
-
- if ((core->mac[ICR] & E1000_ICR_ASSERTED) &&
- (core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) {
- trace_e1000e_irq_icr_clear_iame();
- core->mac[ICR] = 0;
- trace_e1000e_irq_icr_process_iame();
- e1000e_clear_ims_bits(core, core->mac[IAM]);
- }
-
- trace_e1000e_irq_icr_read_exit(core->mac[ICR]);
- e1000e_update_interrupt_state(core);
- return ret;
-}
-
-static uint32_t
-e1000e_mac_read_clr4(E1000ECore *core, int index)
-{
- uint32_t ret = core->mac[index];
-
- core->mac[index] = 0;
- return ret;
-}
-
-static uint32_t
-e1000e_mac_read_clr8(E1000ECore *core, int index)
-{
- uint32_t ret = core->mac[index];
-
- core->mac[index] = 0;
- core->mac[index - 1] = 0;
- return ret;
-}
-
-static uint32_t
-e1000e_get_ctrl(E1000ECore *core, int index)
-{
- uint32_t val = core->mac[CTRL];
-
- trace_e1000e_link_read_params(
- !!(val & E1000_CTRL_ASDE),
- (val & E1000_CTRL_SPD_SEL) >> E1000_CTRL_SPD_SHIFT,
- !!(val & E1000_CTRL_FRCSPD),
- !!(val & E1000_CTRL_FRCDPX),
- !!(val & E1000_CTRL_RFCE),
- !!(val & E1000_CTRL_TFCE));
-
- return val;
-}
-
-static uint32_t
-e1000e_get_status(E1000ECore *core, int index)
-{
- uint32_t res = core->mac[STATUS];
-
- if (!(core->mac[CTRL] & E1000_CTRL_GIO_MASTER_DISABLE)) {
- res |= E1000_STATUS_GIO_MASTER_ENABLE;
- }
-
- if (core->mac[CTRL] & E1000_CTRL_FRCDPX) {
- res |= (core->mac[CTRL] & E1000_CTRL_FD) ? E1000_STATUS_FD : 0;
- } else {
- res |= E1000_STATUS_FD;
- }
-
- if ((core->mac[CTRL] & E1000_CTRL_FRCSPD) ||
- (core->mac[CTRL_EXT] & E1000_CTRL_EXT_SPD_BYPS)) {
- switch (core->mac[CTRL] & E1000_CTRL_SPD_SEL) {
- case E1000_CTRL_SPD_10:
- res |= E1000_STATUS_SPEED_10;
- break;
- case E1000_CTRL_SPD_100:
- res |= E1000_STATUS_SPEED_100;
- break;
- case E1000_CTRL_SPD_1000:
- default:
- res |= E1000_STATUS_SPEED_1000;
- break;
- }
- } else {
- res |= E1000_STATUS_SPEED_1000;
- }
-
- trace_e1000e_link_status(
- !!(res & E1000_STATUS_LU),
- !!(res & E1000_STATUS_FD),
- (res & E1000_STATUS_SPEED_MASK) >> E1000_STATUS_SPEED_SHIFT,
- (res & E1000_STATUS_ASDV) >> E1000_STATUS_ASDV_SHIFT);
-
- return res;
-}
-
-static uint32_t
-e1000e_get_tarc(E1000ECore *core, int index)
-{
- return core->mac[index] & ((BIT(11) - 1) |
- BIT(27) |
- BIT(28) |
- BIT(29) |
- BIT(30));
-}
-
-static void
-e1000e_mac_writereg(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[index] = val;
-}
-
-static void
-e1000e_mac_setmacaddr(E1000ECore *core, int index, uint32_t val)
-{
- uint32_t macaddr[2];
-
- core->mac[index] = val;
-
- macaddr[0] = cpu_to_le32(core->mac[RA]);
- macaddr[1] = cpu_to_le32(core->mac[RA + 1]);
- qemu_format_nic_info_str(qemu_get_queue(core->owner_nic),
- (uint8_t *) macaddr);
-
- trace_e1000e_mac_set_sw(MAC_ARG(macaddr));
-}
-
-static void
-e1000e_set_eecd(E1000ECore *core, int index, uint32_t val)
-{
- static const uint32_t ro_bits = E1000_EECD_PRES |
- E1000_EECD_AUTO_RD |
- E1000_EECD_SIZE_EX_MASK;
-
- core->mac[EECD] = (core->mac[EECD] & ro_bits) | (val & ~ro_bits);
-}
-
-static void
-e1000e_set_eerd(E1000ECore *core, int index, uint32_t val)
-{
- uint32_t addr = (val >> E1000_EERW_ADDR_SHIFT) & E1000_EERW_ADDR_MASK;
- uint32_t flags = 0;
- uint32_t data = 0;
-
- if ((addr < E1000E_EEPROM_SIZE) && (val & E1000_EERW_START)) {
- data = core->eeprom[addr];
- flags = E1000_EERW_DONE;
- }
-
- core->mac[EERD] = flags |
- (addr << E1000_EERW_ADDR_SHIFT) |
- (data << E1000_EERW_DATA_SHIFT);
-}
-
-static void
-e1000e_set_eewr(E1000ECore *core, int index, uint32_t val)
-{
- uint32_t addr = (val >> E1000_EERW_ADDR_SHIFT) & E1000_EERW_ADDR_MASK;
- uint32_t data = (val >> E1000_EERW_DATA_SHIFT) & E1000_EERW_DATA_MASK;
- uint32_t flags = 0;
-
- if ((addr < E1000E_EEPROM_SIZE) && (val & E1000_EERW_START)) {
- core->eeprom[addr] = data;
- flags = E1000_EERW_DONE;
- }
-
- core->mac[EERD] = flags |
- (addr << E1000_EERW_ADDR_SHIFT) |
- (data << E1000_EERW_DATA_SHIFT);
-}
-
-static void
-e1000e_set_rxdctl(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[RXDCTL] = core->mac[RXDCTL1] = val;
-}
-
-static void
-e1000e_set_itr(E1000ECore *core, int index, uint32_t val)
-{
- uint32_t interval = val & 0xffff;
-
- trace_e1000e_irq_itr_set(val);
-
- core->itr_guest_value = interval;
- core->mac[index] = MAX(interval, E1000E_MIN_XITR);
-}
-
-static void
-e1000e_set_eitr(E1000ECore *core, int index, uint32_t val)
-{
- uint32_t interval = val & 0xffff;
- uint32_t eitr_num = index - EITR;
-
- trace_e1000e_irq_eitr_set(eitr_num, val);
-
- core->eitr_guest_value[eitr_num] = interval;
- core->mac[index] = MAX(interval, E1000E_MIN_XITR);
-}
-
-static void
-e1000e_set_psrctl(E1000ECore *core, int index, uint32_t val)
-{
- if ((val & E1000_PSRCTL_BSIZE0_MASK) == 0) {
- hw_error("e1000e: PSRCTL.BSIZE0 cannot be zero");
- }
-
- if ((val & E1000_PSRCTL_BSIZE1_MASK) == 0) {
- hw_error("e1000e: PSRCTL.BSIZE1 cannot be zero");
- }
-
- core->mac[PSRCTL] = val;
-}
-
-static void
-e1000e_update_rx_offloads(E1000ECore *core)
-{
- int cso_state = e1000e_rx_l4_cso_enabled(core);
-
- trace_e1000e_rx_set_cso(cso_state);
-
- if (core->has_vnet) {
- qemu_set_offload(qemu_get_queue(core->owner_nic)->peer,
- cso_state, 0, 0, 0, 0);
- }
-}
-
-static void
-e1000e_set_rxcsum(E1000ECore *core, int index, uint32_t val)
-{
- core->mac[RXCSUM] = val;
- e1000e_update_rx_offloads(core);
-}
-
-static void
-e1000e_set_gcr(E1000ECore *core, int index, uint32_t val)
-{
- uint32_t ro_bits = core->mac[GCR] & E1000_GCR_RO_BITS;
- core->mac[GCR] = (val & ~E1000_GCR_RO_BITS) | ro_bits;
-}
-
-#define e1000e_getreg(x) [x] = e1000e_mac_readreg
-static uint32_t (*e1000e_macreg_readops[])(E1000ECore *, int) = {
- e1000e_getreg(PBA),
- e1000e_getreg(WUFC),
- e1000e_getreg(MANC),
- e1000e_getreg(TOTL),
- e1000e_getreg(RDT0),
- e1000e_getreg(RDBAH0),
- e1000e_getreg(TDBAL1),
- e1000e_getreg(RDLEN0),
- e1000e_getreg(RDH1),
- e1000e_getreg(LATECOL),
- e1000e_getreg(SEC),
- e1000e_getreg(XONTXC),
- e1000e_getreg(WUS),
- e1000e_getreg(GORCL),
- e1000e_getreg(MGTPRC),
- e1000e_getreg(EERD),
- e1000e_getreg(EIAC),
- e1000e_getreg(PSRCTL),
- e1000e_getreg(MANC2H),
- e1000e_getreg(RXCSUM),
- e1000e_getreg(GSCL_3),
- e1000e_getreg(GSCN_2),
- e1000e_getreg(RSRPD),
- e1000e_getreg(RDBAL1),
- e1000e_getreg(FCAH),
- e1000e_getreg(FCRTH),
- e1000e_getreg(FLOP),
- e1000e_getreg(FLASHT),
- e1000e_getreg(RXSTMPH),
- e1000e_getreg(TXSTMPL),
- e1000e_getreg(TIMADJL),
- e1000e_getreg(TXDCTL),
- e1000e_getreg(RDH0),
- e1000e_getreg(TDT1),
- e1000e_getreg(TNCRS),
- e1000e_getreg(RJC),
- e1000e_getreg(IAM),
- e1000e_getreg(GSCL_2),
- e1000e_getreg(RDBAH1),
- e1000e_getreg(FLSWDATA),
- e1000e_getreg(RXSATRH),
- e1000e_getreg(TIPG),
- e1000e_getreg(FLMNGCTL),
- e1000e_getreg(FLMNGCNT),
- e1000e_getreg(TSYNCTXCTL),
- e1000e_getreg(EXTCNF_SIZE),
- e1000e_getreg(EXTCNF_CTRL),
- e1000e_getreg(EEMNGDATA),
- e1000e_getreg(CTRL_EXT),
- e1000e_getreg(SYSTIMH),
- e1000e_getreg(EEMNGCTL),
- e1000e_getreg(FLMNGDATA),
- e1000e_getreg(TSYNCRXCTL),
- e1000e_getreg(TDH),
- e1000e_getreg(LEDCTL),
- e1000e_getreg(STATUS),
- e1000e_getreg(TCTL),
- e1000e_getreg(TDBAL),
- e1000e_getreg(TDLEN),
- e1000e_getreg(TDH1),
- e1000e_getreg(RADV),
- e1000e_getreg(ECOL),
- e1000e_getreg(DC),
- e1000e_getreg(RLEC),
- e1000e_getreg(XOFFTXC),
- e1000e_getreg(RFC),
- e1000e_getreg(RNBC),
- e1000e_getreg(MGTPTC),
- e1000e_getreg(TIMINCA),
- e1000e_getreg(RXCFGL),
- e1000e_getreg(MFUTP01),
- e1000e_getreg(FACTPS),
- e1000e_getreg(GSCL_1),
- e1000e_getreg(GSCN_0),
- e1000e_getreg(GCR2),
- e1000e_getreg(RDT1),
- e1000e_getreg(PBACLR),
- e1000e_getreg(FCTTV),
- e1000e_getreg(EEWR),
- e1000e_getreg(FLSWCTL),
- e1000e_getreg(RXDCTL1),
- e1000e_getreg(RXSATRL),
- e1000e_getreg(SYSTIML),
- e1000e_getreg(RXUDP),
- e1000e_getreg(TORL),
- e1000e_getreg(TDLEN1),
- e1000e_getreg(MCC),
- e1000e_getreg(WUC),
- e1000e_getreg(EECD),
- e1000e_getreg(MFUTP23),
- e1000e_getreg(RAID),
- e1000e_getreg(FCRTV),
- e1000e_getreg(TXDCTL1),
- e1000e_getreg(RCTL),
- e1000e_getreg(TDT),
- e1000e_getreg(MDIC),
- e1000e_getreg(FCRUC),
- e1000e_getreg(VET),
- e1000e_getreg(RDBAL0),
- e1000e_getreg(TDBAH1),
- e1000e_getreg(RDTR),
- e1000e_getreg(SCC),
- e1000e_getreg(COLC),
- e1000e_getreg(CEXTERR),
- e1000e_getreg(XOFFRXC),
- e1000e_getreg(IPAV),
- e1000e_getreg(GOTCL),
- e1000e_getreg(MGTPDC),
- e1000e_getreg(GCR),
- e1000e_getreg(IVAR),
- e1000e_getreg(POEMB),
- e1000e_getreg(MFVAL),
- e1000e_getreg(FUNCTAG),
- e1000e_getreg(GSCL_4),
- e1000e_getreg(GSCN_3),
- e1000e_getreg(MRQC),
- e1000e_getreg(RDLEN1),
- e1000e_getreg(FCT),
- e1000e_getreg(FLA),
- e1000e_getreg(FLOL),
- e1000e_getreg(RXDCTL),
- e1000e_getreg(RXSTMPL),
- e1000e_getreg(TXSTMPH),
- e1000e_getreg(TIMADJH),
- e1000e_getreg(FCRTL),
- e1000e_getreg(TDBAH),
- e1000e_getreg(TADV),
- e1000e_getreg(XONRXC),
- e1000e_getreg(TSCTFC),
- e1000e_getreg(RFCTL),
- e1000e_getreg(GSCN_1),
- e1000e_getreg(FCAL),
- e1000e_getreg(FLSWCNT),
-
- [TOTH] = e1000e_mac_read_clr8,
- [GOTCH] = e1000e_mac_read_clr8,
- [PRC64] = e1000e_mac_read_clr4,
- [PRC255] = e1000e_mac_read_clr4,
- [PRC1023] = e1000e_mac_read_clr4,
- [PTC64] = e1000e_mac_read_clr4,
- [PTC255] = e1000e_mac_read_clr4,
- [PTC1023] = e1000e_mac_read_clr4,
- [GPRC] = e1000e_mac_read_clr4,
- [TPT] = e1000e_mac_read_clr4,
- [RUC] = e1000e_mac_read_clr4,
- [BPRC] = e1000e_mac_read_clr4,
- [MPTC] = e1000e_mac_read_clr4,
- [IAC] = e1000e_mac_read_clr4,
- [ICR] = e1000e_mac_icr_read,
- [RDFH] = E1000E_LOW_BITS_READ(13),
- [RDFHS] = E1000E_LOW_BITS_READ(13),
- [RDFPC] = E1000E_LOW_BITS_READ(13),
- [TDFH] = E1000E_LOW_BITS_READ(13),
- [TDFHS] = E1000E_LOW_BITS_READ(13),
- [STATUS] = e1000e_get_status,
- [TARC0] = e1000e_get_tarc,
- [PBS] = E1000E_LOW_BITS_READ(6),
- [ICS] = e1000e_mac_ics_read,
- [AIT] = E1000E_LOW_BITS_READ(16),
- [TORH] = e1000e_mac_read_clr8,
- [GORCH] = e1000e_mac_read_clr8,
- [PRC127] = e1000e_mac_read_clr4,
- [PRC511] = e1000e_mac_read_clr4,
- [PRC1522] = e1000e_mac_read_clr4,
- [PTC127] = e1000e_mac_read_clr4,
- [PTC511] = e1000e_mac_read_clr4,
- [PTC1522] = e1000e_mac_read_clr4,
- [GPTC] = e1000e_mac_read_clr4,
- [TPR] = e1000e_mac_read_clr4,
- [ROC] = e1000e_mac_read_clr4,
- [MPRC] = e1000e_mac_read_clr4,
- [BPTC] = e1000e_mac_read_clr4,
- [TSCTC] = e1000e_mac_read_clr4,
- [ITR] = e1000e_mac_itr_read,
- [RDFT] = E1000E_LOW_BITS_READ(13),
- [RDFTS] = E1000E_LOW_BITS_READ(13),
- [TDFPC] = E1000E_LOW_BITS_READ(13),
- [TDFT] = E1000E_LOW_BITS_READ(13),
- [TDFTS] = E1000E_LOW_BITS_READ(13),
- [CTRL] = e1000e_get_ctrl,
- [TARC1] = e1000e_get_tarc,
- [SWSM] = e1000e_mac_swsm_read,
- [IMS] = e1000e_mac_ims_read,
-
- [CRCERRS ... MPC] = e1000e_mac_readreg,
- [IP6AT ... IP6AT + 3] = e1000e_mac_readreg,
- [IP4AT ... IP4AT + 6] = e1000e_mac_readreg,
- [RA ... RA + 31] = e1000e_mac_readreg,
- [WUPM ... WUPM + 31] = e1000e_mac_readreg,
- [MTA ... MTA + 127] = e1000e_mac_readreg,
- [VFTA ... VFTA + 127] = e1000e_mac_readreg,
- [FFMT ... FFMT + 254] = E1000E_LOW_BITS_READ(4),
- [FFVT ... FFVT + 254] = e1000e_mac_readreg,
- [MDEF ... MDEF + 7] = e1000e_mac_readreg,
- [FFLT ... FFLT + 10] = E1000E_LOW_BITS_READ(11),
- [FTFT ... FTFT + 254] = e1000e_mac_readreg,
- [PBM ... PBM + 10239] = e1000e_mac_readreg,
- [RETA ... RETA + 31] = e1000e_mac_readreg,
- [RSSRK ... RSSRK + 31] = e1000e_mac_readreg,
- [MAVTV0 ... MAVTV3] = e1000e_mac_readreg,
- [EITR...EITR + E1000E_MSIX_VEC_NUM - 1] = e1000e_mac_eitr_read
-};
-enum { E1000E_NREADOPS = ARRAY_SIZE(e1000e_macreg_readops) };
-
-#define e1000e_putreg(x) [x] = e1000e_mac_writereg
-static void (*e1000e_macreg_writeops[])(E1000ECore *, int, uint32_t) = {
- e1000e_putreg(PBA),
- e1000e_putreg(SWSM),
- e1000e_putreg(WUFC),
- e1000e_putreg(RDBAH1),
- e1000e_putreg(TDBAH),
- e1000e_putreg(TXDCTL),
- e1000e_putreg(RDBAH0),
- e1000e_putreg(LEDCTL),
- e1000e_putreg(FCAL),
- e1000e_putreg(FCRUC),
- e1000e_putreg(AIT),
- e1000e_putreg(TDFH),
- e1000e_putreg(TDFT),
- e1000e_putreg(TDFHS),
- e1000e_putreg(TDFTS),
- e1000e_putreg(TDFPC),
- e1000e_putreg(WUC),
- e1000e_putreg(WUS),
- e1000e_putreg(RDFH),
- e1000e_putreg(RDFT),
- e1000e_putreg(RDFHS),
- e1000e_putreg(RDFTS),
- e1000e_putreg(RDFPC),
- e1000e_putreg(IPAV),
- e1000e_putreg(TDBAH1),
- e1000e_putreg(TIMINCA),
- e1000e_putreg(IAM),
- e1000e_putreg(EIAC),
- e1000e_putreg(IVAR),
- e1000e_putreg(TARC0),
- e1000e_putreg(TARC1),
- e1000e_putreg(FLSWDATA),
- e1000e_putreg(POEMB),
- e1000e_putreg(PBS),
- e1000e_putreg(MFUTP01),
- e1000e_putreg(MFUTP23),
- e1000e_putreg(MANC),
- e1000e_putreg(MANC2H),
- e1000e_putreg(MFVAL),
- e1000e_putreg(EXTCNF_CTRL),
- e1000e_putreg(FACTPS),
- e1000e_putreg(FUNCTAG),
- e1000e_putreg(GSCL_1),
- e1000e_putreg(GSCL_2),
- e1000e_putreg(GSCL_3),
- e1000e_putreg(GSCL_4),
- e1000e_putreg(GSCN_0),
- e1000e_putreg(GSCN_1),
- e1000e_putreg(GSCN_2),
- e1000e_putreg(GSCN_3),
- e1000e_putreg(GCR2),
- e1000e_putreg(MRQC),
- e1000e_putreg(FLOP),
- e1000e_putreg(FLOL),
- e1000e_putreg(FLSWCTL),
- e1000e_putreg(FLSWCNT),
- e1000e_putreg(FLA),
- e1000e_putreg(RXDCTL1),
- e1000e_putreg(TXDCTL1),
- e1000e_putreg(TIPG),
- e1000e_putreg(RXSTMPH),
- e1000e_putreg(RXSTMPL),
- e1000e_putreg(RXSATRL),
- e1000e_putreg(RXSATRH),
- e1000e_putreg(TXSTMPL),
- e1000e_putreg(TXSTMPH),
- e1000e_putreg(SYSTIML),
- e1000e_putreg(SYSTIMH),
- e1000e_putreg(TIMADJL),
- e1000e_putreg(TIMADJH),
- e1000e_putreg(RXUDP),
- e1000e_putreg(RXCFGL),
- e1000e_putreg(TSYNCRXCTL),
- e1000e_putreg(TSYNCTXCTL),
- e1000e_putreg(FLSWDATA),
- e1000e_putreg(EXTCNF_SIZE),
- e1000e_putreg(EEMNGCTL),
- e1000e_putreg(RA),
-
- [TDH1] = e1000e_set_16bit,
- [TDT1] = e1000e_set_tdt,
- [TCTL] = e1000e_set_tctl,
- [TDT] = e1000e_set_tdt,
- [MDIC] = e1000e_set_mdic,
- [ICS] = e1000e_set_ics,
- [TDH] = e1000e_set_16bit,
- [RDH0] = e1000e_set_16bit,
- [RDT0] = e1000e_set_rdt,
- [IMC] = e1000e_set_imc,
- [IMS] = e1000e_set_ims,
- [ICR] = e1000e_set_icr,
- [EECD] = e1000e_set_eecd,
- [RCTL] = e1000e_set_rx_control,
- [CTRL] = e1000e_set_ctrl,
- [RDTR] = e1000e_set_rdtr,
- [RADV] = e1000e_set_16bit,
- [TADV] = e1000e_set_16bit,
- [ITR] = e1000e_set_itr,
- [EERD] = e1000e_set_eerd,
- [GCR] = e1000e_set_gcr,
- [PSRCTL] = e1000e_set_psrctl,
- [RXCSUM] = e1000e_set_rxcsum,
- [RAID] = e1000e_set_16bit,
- [RSRPD] = e1000e_set_12bit,
- [TIDV] = e1000e_set_tidv,
- [TDLEN1] = e1000e_set_dlen,
- [TDLEN] = e1000e_set_dlen,
- [RDLEN0] = e1000e_set_dlen,
- [RDLEN1] = e1000e_set_dlen,
- [TDBAL] = e1000e_set_dbal,
- [TDBAL1] = e1000e_set_dbal,
- [RDBAL0] = e1000e_set_dbal,
- [RDBAL1] = e1000e_set_dbal,
- [RDH1] = e1000e_set_16bit,
- [RDT1] = e1000e_set_rdt,
- [STATUS] = e1000e_set_status,
- [PBACLR] = e1000e_set_pbaclr,
- [CTRL_EXT] = e1000e_set_ctrlext,
- [FCAH] = e1000e_set_16bit,
- [FCT] = e1000e_set_16bit,
- [FCTTV] = e1000e_set_16bit,
- [FCRTV] = e1000e_set_16bit,
- [FCRTH] = e1000e_set_fcrth,
- [FCRTL] = e1000e_set_fcrtl,
- [VET] = e1000e_set_vet,
- [RXDCTL] = e1000e_set_rxdctl,
- [FLASHT] = e1000e_set_16bit,
- [EEWR] = e1000e_set_eewr,
- [CTRL_DUP] = e1000e_set_ctrl,
- [RFCTL] = e1000e_set_rfctl,
- [RA + 1] = e1000e_mac_setmacaddr,
-
- [IP6AT ... IP6AT + 3] = e1000e_mac_writereg,
- [IP4AT ... IP4AT + 6] = e1000e_mac_writereg,
- [RA + 2 ... RA + 31] = e1000e_mac_writereg,
- [WUPM ... WUPM + 31] = e1000e_mac_writereg,
- [MTA ... MTA + 127] = e1000e_mac_writereg,
- [VFTA ... VFTA + 127] = e1000e_mac_writereg,
- [FFMT ... FFMT + 254] = e1000e_mac_writereg,
- [FFVT ... FFVT + 254] = e1000e_mac_writereg,
- [PBM ... PBM + 10239] = e1000e_mac_writereg,
- [MDEF ... MDEF + 7] = e1000e_mac_writereg,
- [FFLT ... FFLT + 10] = e1000e_mac_writereg,
- [FTFT ... FTFT + 254] = e1000e_mac_writereg,
- [RETA ... RETA + 31] = e1000e_mac_writereg,
- [RSSRK ... RSSRK + 31] = e1000e_mac_writereg,
- [MAVTV0 ... MAVTV3] = e1000e_mac_writereg,
- [EITR...EITR + E1000E_MSIX_VEC_NUM - 1] = e1000e_set_eitr
-};
-enum { E1000E_NWRITEOPS = ARRAY_SIZE(e1000e_macreg_writeops) };
-
-enum { MAC_ACCESS_PARTIAL = 1 };
-
-/* The array below combines alias offsets of the index values for the
- * MAC registers that have aliases, with the indication of not fully
- * implemented registers (lowest bit). This combination is possible
- * because all of the offsets are even. */
-static const uint16_t mac_reg_access[E1000E_MAC_SIZE] = {
- /* Alias index offsets */
- [FCRTL_A] = 0x07fe, [FCRTH_A] = 0x0802,
- [RDH0_A] = 0x09bc, [RDT0_A] = 0x09bc, [RDTR_A] = 0x09c6,
- [RDFH_A] = 0xe904, [RDFT_A] = 0xe904,
- [TDH_A] = 0x0cf8, [TDT_A] = 0x0cf8, [TIDV_A] = 0x0cf8,
- [TDFH_A] = 0xed00, [TDFT_A] = 0xed00,
- [RA_A ... RA_A + 31] = 0x14f0,
- [VFTA_A ... VFTA_A + 127] = 0x1400,
- [RDBAL0_A ... RDLEN0_A] = 0x09bc,
- [TDBAL_A ... TDLEN_A] = 0x0cf8,
- /* Access options */
- [RDFH] = MAC_ACCESS_PARTIAL, [RDFT] = MAC_ACCESS_PARTIAL,
- [RDFHS] = MAC_ACCESS_PARTIAL, [RDFTS] = MAC_ACCESS_PARTIAL,
- [RDFPC] = MAC_ACCESS_PARTIAL,
- [TDFH] = MAC_ACCESS_PARTIAL, [TDFT] = MAC_ACCESS_PARTIAL,
- [TDFHS] = MAC_ACCESS_PARTIAL, [TDFTS] = MAC_ACCESS_PARTIAL,
- [TDFPC] = MAC_ACCESS_PARTIAL, [EECD] = MAC_ACCESS_PARTIAL,
- [PBM] = MAC_ACCESS_PARTIAL, [FLA] = MAC_ACCESS_PARTIAL,
- [FCAL] = MAC_ACCESS_PARTIAL, [FCAH] = MAC_ACCESS_PARTIAL,
- [FCT] = MAC_ACCESS_PARTIAL, [FCTTV] = MAC_ACCESS_PARTIAL,
- [FCRTV] = MAC_ACCESS_PARTIAL, [FCRTL] = MAC_ACCESS_PARTIAL,
- [FCRTH] = MAC_ACCESS_PARTIAL, [TXDCTL] = MAC_ACCESS_PARTIAL,
- [TXDCTL1] = MAC_ACCESS_PARTIAL,
- [MAVTV0 ... MAVTV3] = MAC_ACCESS_PARTIAL
-};
-
-void
-e1000e_core_write(E1000ECore *core, hwaddr addr, uint64_t val, unsigned size)
-{
- uint16_t index = e1000e_get_reg_index_with_offset(mac_reg_access, addr);
-
- if (index < E1000E_NWRITEOPS && e1000e_macreg_writeops[index]) {
- if (mac_reg_access[index] & MAC_ACCESS_PARTIAL) {
- trace_e1000e_wrn_regs_write_trivial(index << 2);
- }
- trace_e1000e_core_write(index << 2, size, val);
- e1000e_macreg_writeops[index](core, index, val);
- } else if (index < E1000E_NREADOPS && e1000e_macreg_readops[index]) {
- trace_e1000e_wrn_regs_write_ro(index << 2, size, val);
- } else {
- trace_e1000e_wrn_regs_write_unknown(index << 2, size, val);
- }
-}
-
-uint64_t
-e1000e_core_read(E1000ECore *core, hwaddr addr, unsigned size)
-{
- uint64_t val;
- uint16_t index = e1000e_get_reg_index_with_offset(mac_reg_access, addr);
-
- if (index < E1000E_NREADOPS && e1000e_macreg_readops[index]) {
- if (mac_reg_access[index] & MAC_ACCESS_PARTIAL) {
- trace_e1000e_wrn_regs_read_trivial(index << 2);
- }
- val = e1000e_macreg_readops[index](core, index);
- trace_e1000e_core_read(index << 2, size, val);
- return val;
- } else {
- trace_e1000e_wrn_regs_read_unknown(index << 2, size);
- }
- return 0;
-}
-
-static inline void
-e1000e_autoneg_pause(E1000ECore *core)
-{
- timer_del(core->autoneg_timer);
-}
-
-static void
-e1000e_autoneg_resume(E1000ECore *core)
-{
- if (e1000e_have_autoneg(core) &&
- !(core->phy[0][PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
- qemu_get_queue(core->owner_nic)->link_down = false;
- timer_mod(core->autoneg_timer,
- qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
- }
-}
-
-static void
-e1000e_vm_state_change(void *opaque, int running, RunState state)
-{
- E1000ECore *core = opaque;
-
- if (running) {
- trace_e1000e_vm_state_running();
- e1000e_intrmgr_resume(core);
- e1000e_autoneg_resume(core);
- } else {
- trace_e1000e_vm_state_stopped();
- e1000e_autoneg_pause(core);
- e1000e_intrmgr_pause(core);
- }
-}
-
-void
-e1000e_core_pci_realize(E1000ECore *core,
- const uint16_t *eeprom_templ,
- uint32_t eeprom_size,
- const uint8_t *macaddr)
-{
- int i;
-
- core->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
- e1000e_autoneg_timer, core);
- e1000e_intrmgr_pci_realize(core);
-
- core->vmstate =
- qemu_add_vm_change_state_handler(e1000e_vm_state_change, core);
-
- for (i = 0; i < E1000E_NUM_QUEUES; i++) {
- net_tx_pkt_init(&core->tx[i].tx_pkt, core->owner,
- E1000E_MAX_TX_FRAGS, core->has_vnet);
- }
-
- net_rx_pkt_init(&core->rx_pkt, core->has_vnet);
-
- e1000x_core_prepare_eeprom(core->eeprom,
- eeprom_templ,
- eeprom_size,
- PCI_DEVICE_GET_CLASS(core->owner)->device_id,
- macaddr);
- e1000e_update_rx_offloads(core);
-}
-
-void
-e1000e_core_pci_uninit(E1000ECore *core)
-{
- int i;
-
- timer_del(core->autoneg_timer);
- timer_free(core->autoneg_timer);
-
- e1000e_intrmgr_pci_unint(core);
-
- qemu_del_vm_change_state_handler(core->vmstate);
-
- for (i = 0; i < E1000E_NUM_QUEUES; i++) {
- net_tx_pkt_reset(core->tx[i].tx_pkt);
- net_tx_pkt_uninit(core->tx[i].tx_pkt);
- }
-
- net_rx_pkt_uninit(core->rx_pkt);
-}
-
-static const uint16_t
-e1000e_phy_reg_init[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE] = {
- [0] = {
- [PHY_CTRL] = MII_CR_SPEED_SELECT_MSB |
- MII_CR_FULL_DUPLEX |
- MII_CR_AUTO_NEG_EN,
-
- [PHY_STATUS] = MII_SR_EXTENDED_CAPS |
- MII_SR_LINK_STATUS |
- MII_SR_AUTONEG_CAPS |
- MII_SR_PREAMBLE_SUPPRESS |
- MII_SR_EXTENDED_STATUS |
- MII_SR_10T_HD_CAPS |
- MII_SR_10T_FD_CAPS |
- MII_SR_100X_HD_CAPS |
- MII_SR_100X_FD_CAPS,
-
- [PHY_ID1] = 0x141,
- [PHY_ID2] = E1000_PHY_ID2_82574x,
- [PHY_AUTONEG_ADV] = 0xde1,
- [PHY_LP_ABILITY] = 0x7e0,
- [PHY_AUTONEG_EXP] = BIT(2),
- [PHY_NEXT_PAGE_TX] = BIT(0) | BIT(13),
- [PHY_1000T_CTRL] = BIT(8) | BIT(9) | BIT(10) | BIT(11),
- [PHY_1000T_STATUS] = 0x3c00,
- [PHY_EXT_STATUS] = BIT(12) | BIT(13),
-
- [PHY_COPPER_CTRL1] = BIT(5) | BIT(6) | BIT(8) | BIT(9) |
- BIT(12) | BIT(13),
- [PHY_COPPER_STAT1] = BIT(3) | BIT(10) | BIT(11) | BIT(13) | BIT(15)
- },
- [2] = {
- [PHY_MAC_CTRL1] = BIT(3) | BIT(7),
- [PHY_MAC_CTRL2] = BIT(1) | BIT(2) | BIT(6) | BIT(12)
- },
- [3] = {
- [PHY_LED_TIMER_CTRL] = BIT(0) | BIT(2) | BIT(14)
- }
-};
-
-static const uint32_t e1000e_mac_reg_init[] = {
- [PBA] = 0x00140014,
- [LEDCTL] = BIT(1) | BIT(8) | BIT(9) | BIT(15) | BIT(17) | BIT(18),
- [EXTCNF_CTRL] = BIT(3),
- [EEMNGCTL] = BIT(31),
- [FLASHT] = 0x2,
- [FLSWCTL] = BIT(30) | BIT(31),
- [FLOL] = BIT(0),
- [RXDCTL] = BIT(16),
- [RXDCTL1] = BIT(16),
- [TIPG] = 0x8 | (0x8 << 10) | (0x6 << 20),
- [RXCFGL] = 0x88F7,
- [RXUDP] = 0x319,
- [CTRL] = E1000_CTRL_FD | E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
- E1000_CTRL_SPD_1000 | E1000_CTRL_SLU |
- E1000_CTRL_ADVD3WUC,
- [STATUS] = E1000_STATUS_ASDV_1000 | E1000_STATUS_LU,
- [PSRCTL] = (2 << E1000_PSRCTL_BSIZE0_SHIFT) |
- (4 << E1000_PSRCTL_BSIZE1_SHIFT) |
- (4 << E1000_PSRCTL_BSIZE2_SHIFT),
- [TARC0] = 0x3 | E1000_TARC_ENABLE,
- [TARC1] = 0x3 | E1000_TARC_ENABLE,
- [EECD] = E1000_EECD_AUTO_RD | E1000_EECD_PRES,
- [EERD] = E1000_EERW_DONE,
- [EEWR] = E1000_EERW_DONE,
- [GCR] = E1000_L0S_ADJUST |
- E1000_L1_ENTRY_LATENCY_MSB |
- E1000_L1_ENTRY_LATENCY_LSB,
- [TDFH] = 0x600,
- [TDFT] = 0x600,
- [TDFHS] = 0x600,
- [TDFTS] = 0x600,
- [POEMB] = 0x30D,
- [PBS] = 0x028,
- [MANC] = E1000_MANC_DIS_IP_CHK_ARP,
- [FACTPS] = E1000_FACTPS_LAN0_ON | 0x20000000,
- [SWSM] = 1,
- [RXCSUM] = E1000_RXCSUM_IPOFLD | E1000_RXCSUM_TUOFLD,
- [ITR] = E1000E_MIN_XITR,
- [EITR...EITR + E1000E_MSIX_VEC_NUM - 1] = E1000E_MIN_XITR,
-};
-
-void
-e1000e_core_reset(E1000ECore *core)
-{
- int i;
-
- timer_del(core->autoneg_timer);
-
- e1000e_intrmgr_reset(core);
-
- memset(core->phy, 0, sizeof core->phy);
- memmove(core->phy, e1000e_phy_reg_init, sizeof e1000e_phy_reg_init);
- memset(core->mac, 0, sizeof core->mac);
- memmove(core->mac, e1000e_mac_reg_init, sizeof e1000e_mac_reg_init);
-
- core->rxbuf_min_shift = 1 + E1000_RING_DESC_LEN_SHIFT;
-
- if (qemu_get_queue(core->owner_nic)->link_down) {
- e1000e_link_down(core);
- }
-
- e1000x_reset_mac_addr(core->owner_nic, core->mac, core->permanent_mac);
-
- for (i = 0; i < ARRAY_SIZE(core->tx); i++) {
- net_tx_pkt_reset(core->tx[i].tx_pkt);
- memset(&core->tx[i].props, 0, sizeof(core->tx[i].props));
- core->tx[i].skip_cp = false;
- }
-}
-
-void e1000e_core_pre_save(E1000ECore *core)
-{
- int i;
- NetClientState *nc = qemu_get_queue(core->owner_nic);
-
- /*
- * If link is down and auto-negotiation is supported and ongoing,
- * complete auto-negotiation immediately. This allows us to look
- * at MII_SR_AUTONEG_COMPLETE to infer link status on load.
- */
- if (nc->link_down && e1000e_have_autoneg(core)) {
- core->phy[0][PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
- e1000e_update_flowctl_status(core);
- }
-
- for (i = 0; i < ARRAY_SIZE(core->tx); i++) {
- if (net_tx_pkt_has_fragments(core->tx[i].tx_pkt)) {
- core->tx[i].skip_cp = true;
- }
- }
-}
-
-int
-e1000e_core_post_load(E1000ECore *core)
-{
- NetClientState *nc = qemu_get_queue(core->owner_nic);
-
- /* nc.link_down can't be migrated, so infer link_down according
- * to link status bit in core.mac[STATUS].
- */
- nc->link_down = (core->mac[STATUS] & E1000_STATUS_LU) == 0;
-
- return 0;
-}
diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h
deleted file mode 100644
index 5f413a9e0..000000000
--- a/hw/net/e1000e_core.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-* Core code for QEMU e1000e emulation
-*
-* Software developer's manuals:
-* http://www.intel.com/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
-*
-* Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com)
-* Developed by Daynix Computing LTD (http://www.daynix.com)
-*
-* Authors:
-* Dmitry Fleytman <dmitry@daynix.com>
-* Leonid Bloch <leonid@daynix.com>
-* Yan Vugenfirer <yan@daynix.com>
-*
-* Based on work done by:
-* Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
-* Copyright (c) 2008 Qumranet
-* Based on work done by:
-* Copyright (c) 2007 Dan Aloni
-* Copyright (c) 2004 Antony T Curtis
-*
-* 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/>.
-*/
-
-#define E1000E_PHY_PAGE_SIZE (0x20)
-#define E1000E_PHY_PAGES (0x07)
-#define E1000E_MAC_SIZE (0x8000)
-#define E1000E_EEPROM_SIZE (64)
-#define E1000E_MSIX_VEC_NUM (5)
-#define E1000E_NUM_QUEUES (2)
-
-typedef struct E1000Core E1000ECore;
-
-enum { PHY_R = BIT(0),
- PHY_W = BIT(1),
- PHY_RW = PHY_R | PHY_W,
- PHY_ANYPAGE = BIT(2) };
-
-typedef struct E1000IntrDelayTimer_st {
- QEMUTimer *timer;
- bool running;
- uint32_t delay_reg;
- uint32_t delay_resolution_ns;
- E1000ECore *core;
-} E1000IntrDelayTimer;
-
-struct E1000Core {
- uint32_t mac[E1000E_MAC_SIZE];
- uint16_t phy[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE];
- uint16_t eeprom[E1000E_EEPROM_SIZE];
-
- uint32_t rxbuf_sizes[E1000_PSRCTL_BUFFS_PER_DESC];
- uint32_t rx_desc_buf_size;
- uint32_t rxbuf_min_shift;
- uint8_t rx_desc_len;
-
- QEMUTimer *autoneg_timer;
-
- struct e1000e_tx {
- e1000x_txd_props props;
-
- bool skip_cp;
- struct NetTxPkt *tx_pkt;
- } tx[E1000E_NUM_QUEUES];
-
- struct NetRxPkt *rx_pkt;
-
- bool has_vnet;
- int max_queue_num;
-
- /* Interrupt moderation management */
- uint32_t delayed_causes;
-
- E1000IntrDelayTimer radv;
- E1000IntrDelayTimer rdtr;
- E1000IntrDelayTimer raid;
-
- E1000IntrDelayTimer tadv;
- E1000IntrDelayTimer tidv;
-
- E1000IntrDelayTimer itr;
- bool itr_intr_pending;
-
- E1000IntrDelayTimer eitr[E1000E_MSIX_VEC_NUM];
- bool eitr_intr_pending[E1000E_MSIX_VEC_NUM];
-
- VMChangeStateEntry *vmstate;
-
- uint32_t itr_guest_value;
- uint32_t eitr_guest_value[E1000E_MSIX_VEC_NUM];
-
- uint16_t vet;
-
- uint8_t permanent_mac[ETH_ALEN];
-
- NICState *owner_nic;
- PCIDevice *owner;
- void (*owner_start_recv)(PCIDevice *d);
-};
-
-void
-e1000e_core_write(E1000ECore *core, hwaddr addr, uint64_t val, unsigned size);
-
-uint64_t
-e1000e_core_read(E1000ECore *core, hwaddr addr, unsigned size);
-
-void
-e1000e_core_pci_realize(E1000ECore *regs,
- const uint16_t *eeprom_templ,
- uint32_t eeprom_size,
- const uint8_t *macaddr);
-
-void
-e1000e_core_reset(E1000ECore *core);
-
-void
-e1000e_core_pre_save(E1000ECore *core);
-
-int
-e1000e_core_post_load(E1000ECore *core);
-
-void
-e1000e_core_set_link_status(E1000ECore *core);
-
-void
-e1000e_core_pci_uninit(E1000ECore *core);
-
-int
-e1000e_can_receive(E1000ECore *core);
-
-ssize_t
-e1000e_receive(E1000ECore *core, const uint8_t *buf, size_t size);
-
-ssize_t
-e1000e_receive_iov(E1000ECore *core, const struct iovec *iov, int iovcnt);
diff --git a/hw/net/e1000x_common.c b/hw/net/e1000x_common.c
deleted file mode 100644
index eb0e09713..000000000
--- a/hw/net/e1000x_common.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
-* QEMU e1000(e) emulation - shared code
-*
-* Copyright (c) 2008 Qumranet
-*
-* Based on work done by:
-* Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
-* Copyright (c) 2007 Dan Aloni
-* Copyright (c) 2004 Antony T Curtis
-*
-* 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 "hw/hw.h"
-#include "hw/pci/pci.h"
-#include "net/net.h"
-
-#include "e1000x_common.h"
-
-#include "trace.h"
-
-bool e1000x_rx_ready(PCIDevice *d, uint32_t *mac)
-{
- bool link_up = mac[STATUS] & E1000_STATUS_LU;
- bool rx_enabled = mac[RCTL] & E1000_RCTL_EN;
- bool pci_master = d->config[PCI_COMMAND] & PCI_COMMAND_MASTER;
-
- if (!link_up || !rx_enabled || !pci_master) {
- trace_e1000x_rx_can_recv_disabled(link_up, rx_enabled, pci_master);
- return false;
- }
-
- return true;
-}
-
-bool e1000x_is_vlan_packet(const uint8_t *buf, uint16_t vet)
-{
- uint16_t eth_proto = lduw_be_p(buf + 12);
- bool res = (eth_proto == vet);
-
- trace_e1000x_vlan_is_vlan_pkt(res, eth_proto, vet);
-
- return res;
-}
-
-bool e1000x_rx_group_filter(uint32_t *mac, const uint8_t *buf)
-{
- static const int mta_shift[] = { 4, 3, 2, 0 };
- uint32_t f, ra[2], *rp, rctl = mac[RCTL];
-
- for (rp = mac + RA; rp < mac + RA + 32; rp += 2) {
- if (!(rp[1] & E1000_RAH_AV)) {
- continue;
- }
- ra[0] = cpu_to_le32(rp[0]);
- ra[1] = cpu_to_le32(rp[1]);
- if (!memcmp(buf, (uint8_t *)ra, 6)) {
- trace_e1000x_rx_flt_ucast_match((int)(rp - mac - RA) / 2,
- MAC_ARG(buf));
- return true;
- }
- }
- trace_e1000x_rx_flt_ucast_mismatch(MAC_ARG(buf));
-
- f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
- f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff;
- if (mac[MTA + (f >> 5)] & (1 << (f & 0x1f))) {
- e1000x_inc_reg_if_not_full(mac, MPRC);
- return true;
- }
-
- trace_e1000x_rx_flt_inexact_mismatch(MAC_ARG(buf),
- (rctl >> E1000_RCTL_MO_SHIFT) & 3,
- f >> 5,
- mac[MTA + (f >> 5)]);
-
- return false;
-}
-
-bool e1000x_hw_rx_enabled(uint32_t *mac)
-{
- if (!(mac[STATUS] & E1000_STATUS_LU)) {
- trace_e1000x_rx_link_down(mac[STATUS]);
- return false;
- }
-
- if (!(mac[RCTL] & E1000_RCTL_EN)) {
- trace_e1000x_rx_disabled(mac[RCTL]);
- return false;
- }
-
- return true;
-}
-
-bool e1000x_is_oversized(uint32_t *mac, size_t size)
-{
- /* this is the size past which hardware will
- drop packets when setting LPE=0 */
- static const int maximum_ethernet_vlan_size = 1522;
- /* this is the size past which hardware will
- drop packets when setting LPE=1 */
- static const int maximum_ethernet_lpe_size = 16384;
-
- if ((size > maximum_ethernet_lpe_size ||
- (size > maximum_ethernet_vlan_size
- && !(mac[RCTL] & E1000_RCTL_LPE)))
- && !(mac[RCTL] & E1000_RCTL_SBP)) {
- e1000x_inc_reg_if_not_full(mac, ROC);
- trace_e1000x_rx_oversized(size);
- return true;
- }
-
- return false;
-}
-
-void e1000x_restart_autoneg(uint32_t *mac, uint16_t *phy, QEMUTimer *timer)
-{
- e1000x_update_regs_on_link_down(mac, phy);
- trace_e1000x_link_negotiation_start();
- timer_mod(timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
-}
-
-void e1000x_reset_mac_addr(NICState *nic, uint32_t *mac_regs,
- uint8_t *mac_addr)
-{
- int i;
-
- mac_regs[RA] = 0;
- mac_regs[RA + 1] = E1000_RAH_AV;
- for (i = 0; i < 4; i++) {
- mac_regs[RA] |= mac_addr[i] << (8 * i);
- mac_regs[RA + 1] |=
- (i < 2) ? mac_addr[i + 4] << (8 * i) : 0;
- }
-
- qemu_format_nic_info_str(qemu_get_queue(nic), mac_addr);
- trace_e1000x_mac_indicate(MAC_ARG(mac_addr));
-}
-
-void e1000x_update_regs_on_autoneg_done(uint32_t *mac, uint16_t *phy)
-{
- e1000x_update_regs_on_link_up(mac, phy);
- phy[PHY_LP_ABILITY] |= MII_LPAR_LPACK;
- phy[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
- trace_e1000x_link_negotiation_done();
-}
-
-void
-e1000x_core_prepare_eeprom(uint16_t *eeprom,
- const uint16_t *templ,
- uint32_t templ_size,
- uint16_t dev_id,
- const uint8_t *macaddr)
-{
- uint16_t checksum = 0;
- int i;
-
- memmove(eeprom, templ, templ_size);
-
- for (i = 0; i < 3; i++) {
- eeprom[i] = (macaddr[2 * i + 1] << 8) | macaddr[2 * i];
- }
-
- eeprom[11] = eeprom[13] = dev_id;
-
- for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
- checksum += eeprom[i];
- }
-
- checksum = (uint16_t) EEPROM_SUM - checksum;
-
- eeprom[EEPROM_CHECKSUM_REG] = checksum;
-}
-
-uint32_t
-e1000x_rxbufsize(uint32_t rctl)
-{
- rctl &= E1000_RCTL_BSEX | E1000_RCTL_SZ_16384 | E1000_RCTL_SZ_8192 |
- E1000_RCTL_SZ_4096 | E1000_RCTL_SZ_2048 | E1000_RCTL_SZ_1024 |
- E1000_RCTL_SZ_512 | E1000_RCTL_SZ_256;
- switch (rctl) {
- case E1000_RCTL_BSEX | E1000_RCTL_SZ_16384:
- return 16384;
- case E1000_RCTL_BSEX | E1000_RCTL_SZ_8192:
- return 8192;
- case E1000_RCTL_BSEX | E1000_RCTL_SZ_4096:
- return 4096;
- case E1000_RCTL_SZ_1024:
- return 1024;
- case E1000_RCTL_SZ_512:
- return 512;
- case E1000_RCTL_SZ_256:
- return 256;
- }
- return 2048;
-}
-
-void
-e1000x_update_rx_total_stats(uint32_t *mac,
- size_t data_size,
- size_t data_fcs_size)
-{
- static const int PRCregs[6] = { PRC64, PRC127, PRC255, PRC511,
- PRC1023, PRC1522 };
-
- e1000x_increase_size_stats(mac, PRCregs, data_fcs_size);
- e1000x_inc_reg_if_not_full(mac, TPR);
- mac[GPRC] = mac[TPR];
- /* TOR - Total Octets Received:
- * This register includes bytes received in a packet from the <Destination
- * Address> field through the <CRC> field, inclusively.
- * Always include FCS length (4) in size.
- */
- e1000x_grow_8reg_if_not_full(mac, TORL, data_size + 4);
- mac[GORCL] = mac[TORL];
- mac[GORCH] = mac[TORH];
-}
-
-void
-e1000x_increase_size_stats(uint32_t *mac, const int *size_regs, int size)
-{
- if (size > 1023) {
- e1000x_inc_reg_if_not_full(mac, size_regs[5]);
- } else if (size > 511) {
- e1000x_inc_reg_if_not_full(mac, size_regs[4]);
- } else if (size > 255) {
- e1000x_inc_reg_if_not_full(mac, size_regs[3]);
- } else if (size > 127) {
- e1000x_inc_reg_if_not_full(mac, size_regs[2]);
- } else if (size > 64) {
- e1000x_inc_reg_if_not_full(mac, size_regs[1]);
- } else if (size == 64) {
- e1000x_inc_reg_if_not_full(mac, size_regs[0]);
- }
-}
-
-void
-e1000x_read_tx_ctx_descr(struct e1000_context_desc *d,
- e1000x_txd_props *props)
-{
- uint32_t op = le32_to_cpu(d->cmd_and_length);
-
- props->ipcss = d->lower_setup.ip_fields.ipcss;
- props->ipcso = d->lower_setup.ip_fields.ipcso;
- props->ipcse = le16_to_cpu(d->lower_setup.ip_fields.ipcse);
- props->tucss = d->upper_setup.tcp_fields.tucss;
- props->tucso = d->upper_setup.tcp_fields.tucso;
- props->tucse = le16_to_cpu(d->upper_setup.tcp_fields.tucse);
- props->paylen = op & 0xfffff;
- props->hdr_len = d->tcp_seg_setup.fields.hdr_len;
- props->mss = le16_to_cpu(d->tcp_seg_setup.fields.mss);
- props->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0;
- props->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0;
- props->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0;
-}
diff --git a/hw/net/e1000x_common.h b/hw/net/e1000x_common.h
deleted file mode 100644
index 21bf28e0c..000000000
--- a/hw/net/e1000x_common.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
-* QEMU e1000(e) emulation - shared code
-*
-* Copyright (c) 2008 Qumranet
-*
-* Based on work done by:
-* Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
-* Copyright (c) 2007 Dan Aloni
-* Copyright (c) 2004 Antony T Curtis
-*
-* 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 "e1000_regs.h"
-
-#define defreg(x) x = (E1000_##x >> 2)
-enum {
- defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC),
- defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC),
- defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC),
- defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH0),
- defreg(RDBAL0), defreg(RDH0), defreg(RDLEN0), defreg(RDT0),
- defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH),
- defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT),
- defreg(TDLEN1), defreg(TDBAL1), defreg(TDBAH1), defreg(TDH1),
- defreg(TDT1), defreg(TORH), defreg(TORL), defreg(TOTH),
- defreg(TOTL), defreg(TPR), defreg(TPT), defreg(TXDCTL),
- defreg(WUFC), defreg(RA), defreg(MTA), defreg(CRCERRS),
- defreg(VFTA), defreg(VET), defreg(RDTR), defreg(RADV),
- defreg(TADV), defreg(ITR), defreg(SCC), defreg(ECOL),
- defreg(MCC), defreg(LATECOL), defreg(COLC), defreg(DC),
- defreg(TNCRS), defreg(SEC), defreg(CEXTERR), defreg(RLEC),
- defreg(XONRXC), defreg(XONTXC), defreg(XOFFRXC), defreg(XOFFTXC),
- defreg(FCRUC), defreg(AIT), defreg(TDFH), defreg(TDFT),
- defreg(TDFHS), defreg(TDFTS), defreg(TDFPC), defreg(WUC),
- defreg(WUS), defreg(POEMB), defreg(PBS), defreg(RDFH),
- defreg(RDFT), defreg(RDFHS), defreg(RDFTS), defreg(RDFPC),
- defreg(PBM), defreg(IPAV), defreg(IP4AT), defreg(IP6AT),
- defreg(WUPM), defreg(FFLT), defreg(FFMT), defreg(FFVT),
- defreg(TARC0), defreg(TARC1), defreg(IAM), defreg(EXTCNF_CTRL),
- defreg(GCR), defreg(TIMINCA), defreg(EIAC), defreg(CTRL_EXT),
- defreg(IVAR), defreg(MFUTP01), defreg(MFUTP23), defreg(MANC2H),
- defreg(MFVAL), defreg(MDEF), defreg(FACTPS), defreg(FTFT),
- defreg(RUC), defreg(ROC), defreg(RFC), defreg(RJC),
- defreg(PRC64), defreg(PRC127), defreg(PRC255), defreg(PRC511),
- defreg(PRC1023), defreg(PRC1522), defreg(PTC64), defreg(PTC127),
- defreg(PTC255), defreg(PTC511), defreg(PTC1023), defreg(PTC1522),
- defreg(GORCL), defreg(GORCH), defreg(GOTCL), defreg(GOTCH),
- defreg(RNBC), defreg(BPRC), defreg(MPRC), defreg(RFCTL),
- defreg(PSRCTL), defreg(MPTC), defreg(BPTC), defreg(TSCTFC),
- defreg(IAC), defreg(MGTPRC), defreg(MGTPDC), defreg(MGTPTC),
- defreg(TSCTC), defreg(RXCSUM), defreg(FUNCTAG), defreg(GSCL_1),
- defreg(GSCL_2), defreg(GSCL_3), defreg(GSCL_4), defreg(GSCN_0),
- defreg(GSCN_1), defreg(GSCN_2), defreg(GSCN_3), defreg(GCR2),
- defreg(RAID), defreg(RSRPD), defreg(TIDV), defreg(EITR),
- defreg(MRQC), defreg(RETA), defreg(RSSRK), defreg(RDBAH1),
- defreg(RDBAL1), defreg(RDLEN1), defreg(RDH1), defreg(RDT1),
- defreg(PBACLR), defreg(FCAL), defreg(FCAH), defreg(FCT),
- defreg(FCRTH), defreg(FCRTL), defreg(FCTTV), defreg(FCRTV),
- defreg(FLA), defreg(EEWR), defreg(FLOP), defreg(FLOL),
- defreg(FLSWCTL), defreg(FLSWCNT), defreg(RXDCTL), defreg(RXDCTL1),
- defreg(MAVTV0), defreg(MAVTV1), defreg(MAVTV2), defreg(MAVTV3),
- defreg(TXSTMPL), defreg(TXSTMPH), defreg(SYSTIML), defreg(SYSTIMH),
- defreg(RXCFGL), defreg(RXUDP), defreg(TIMADJL), defreg(TIMADJH),
- defreg(RXSTMPH), defreg(RXSTMPL), defreg(RXSATRL), defreg(RXSATRH),
- defreg(FLASHT), defreg(TIPG), defreg(RDH), defreg(RDT),
- defreg(RDLEN), defreg(RDBAH), defreg(RDBAL),
- defreg(TXDCTL1),
- defreg(FLSWDATA),
- defreg(CTRL_DUP),
- defreg(EXTCNF_SIZE),
- defreg(EEMNGCTL),
- defreg(EEMNGDATA),
- defreg(FLMNGCTL),
- defreg(FLMNGDATA),
- defreg(FLMNGCNT),
- defreg(TSYNCRXCTL),
- defreg(TSYNCTXCTL),
-
- /* Aliases */
- defreg(RDH0_A), defreg(RDT0_A), defreg(RDTR_A), defreg(RDFH_A),
- defreg(RDFT_A), defreg(TDH_A), defreg(TDT_A), defreg(TIDV_A),
- defreg(TDFH_A), defreg(TDFT_A), defreg(RA_A), defreg(RDBAL0_A),
- defreg(TDBAL_A), defreg(TDLEN_A), defreg(VFTA_A), defreg(RDLEN0_A),
- defreg(FCRTL_A), defreg(FCRTH_A)
-};
-
-static inline void
-e1000x_inc_reg_if_not_full(uint32_t *mac, int index)
-{
- if (mac[index] != 0xffffffff) {
- mac[index]++;
- }
-}
-
-static inline void
-e1000x_grow_8reg_if_not_full(uint32_t *mac, int index, int size)
-{
- uint64_t sum = mac[index] | (uint64_t)mac[index + 1] << 32;
-
- if (sum + size < sum) {
- sum = ~0ULL;
- } else {
- sum += size;
- }
- mac[index] = sum;
- mac[index + 1] = sum >> 32;
-}
-
-static inline int
-e1000x_vlan_enabled(uint32_t *mac)
-{
- return ((mac[CTRL] & E1000_CTRL_VME) != 0);
-}
-
-static inline int
-e1000x_is_vlan_txd(uint32_t txd_lower)
-{
- return ((txd_lower & E1000_TXD_CMD_VLE) != 0);
-}
-
-static inline int
-e1000x_vlan_rx_filter_enabled(uint32_t *mac)
-{
- return ((mac[RCTL] & E1000_RCTL_VFE) != 0);
-}
-
-static inline int
-e1000x_fcs_len(uint32_t *mac)
-{
- /* FCS aka Ethernet CRC-32. We don't get it from backends and can't
- * fill it in, just pad descriptor length by 4 bytes unless guest
- * told us to strip it off the packet. */
- return (mac[RCTL] & E1000_RCTL_SECRC) ? 0 : 4;
-}
-
-static inline void
-e1000x_update_regs_on_link_down(uint32_t *mac, uint16_t *phy)
-{
- mac[STATUS] &= ~E1000_STATUS_LU;
- phy[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
- phy[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
- phy[PHY_LP_ABILITY] &= ~MII_LPAR_LPACK;
-}
-
-static inline void
-e1000x_update_regs_on_link_up(uint32_t *mac, uint16_t *phy)
-{
- mac[STATUS] |= E1000_STATUS_LU;
- phy[PHY_STATUS] |= MII_SR_LINK_STATUS;
-}
-
-void e1000x_update_rx_total_stats(uint32_t *mac,
- size_t data_size,
- size_t data_fcs_size);
-
-void e1000x_core_prepare_eeprom(uint16_t *eeprom,
- const uint16_t *templ,
- uint32_t templ_size,
- uint16_t dev_id,
- const uint8_t *macaddr);
-
-uint32_t e1000x_rxbufsize(uint32_t rctl);
-
-bool e1000x_rx_ready(PCIDevice *d, uint32_t *mac);
-
-bool e1000x_is_vlan_packet(const uint8_t *buf, uint16_t vet);
-
-bool e1000x_rx_group_filter(uint32_t *mac, const uint8_t *buf);
-
-bool e1000x_hw_rx_enabled(uint32_t *mac);
-
-bool e1000x_is_oversized(uint32_t *mac, size_t size);
-
-void e1000x_restart_autoneg(uint32_t *mac, uint16_t *phy, QEMUTimer *timer);
-
-void e1000x_reset_mac_addr(NICState *nic, uint32_t *mac_regs,
- uint8_t *mac_addr);
-
-void e1000x_update_regs_on_autoneg_done(uint32_t *mac, uint16_t *phy);
-
-void e1000x_increase_size_stats(uint32_t *mac, const int *size_regs, int size);
-
-typedef struct e1000x_txd_props {
- unsigned char sum_needed;
- uint8_t ipcss;
- uint8_t ipcso;
- uint16_t ipcse;
- uint8_t tucss;
- uint8_t tucso;
- uint16_t tucse;
- uint32_t paylen;
- uint8_t hdr_len;
- uint16_t mss;
- int8_t ip;
- int8_t tcp;
- bool tse;
- bool cptse;
-} e1000x_txd_props;
-
-void e1000x_read_tx_ctx_descr(struct e1000_context_desc *d,
- e1000x_txd_props *props);
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index bab4dbfc9..9b4b9b59d 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -352,14 +352,14 @@ static unsigned e100_compute_mcast_idx(const uint8_t *ep)
static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
{
assert(!((uintptr_t)&s->mem[addr] & 1));
- return lduw_le_p(&s->mem[addr]);
+ return le16_to_cpup((uint16_t *)&s->mem[addr]);
}
/* Read a 32 bit control/status (CSR) register. */
static uint32_t e100_read_reg4(EEPRO100State *s, E100RegisterOffset addr)
{
assert(!((uintptr_t)&s->mem[addr] & 3));
- return ldl_le_p(&s->mem[addr]);
+ return le32_to_cpup((uint32_t *)&s->mem[addr]);
}
/* Write a 16 bit control/status (CSR) register. */
@@ -367,7 +367,7 @@ static void e100_write_reg2(EEPRO100State *s, E100RegisterOffset addr,
uint16_t val)
{
assert(!((uintptr_t)&s->mem[addr] & 1));
- stw_le_p(&s->mem[addr], val);
+ cpu_to_le16w((uint16_t *)&s->mem[addr], val);
}
/* Read a 32 bit control/status (CSR) register. */
@@ -375,7 +375,7 @@ static void e100_write_reg4(EEPRO100State *s, E100RegisterOffset addr,
uint32_t val)
{
assert(!((uintptr_t)&s->mem[addr] & 3));
- stl_le_p(&s->mem[addr], val);
+ cpu_to_le32w((uint32_t *)&s->mem[addr], val);
}
#if defined(DEBUG_EEPRO100)
@@ -1848,7 +1848,7 @@ static void pci_nic_uninit(PCIDevice *pci_dev)
}
static NetClientInfo net_eepro100_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = nic_receive,
};
diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
index efaa49faa..05495ec40 100644
--- a/hw/net/etraxfs_eth.c
+++ b/hw/net/etraxfs_eth.c
@@ -578,7 +578,7 @@ static const MemoryRegionOps eth_ops = {
};
static NetClientInfo net_etraxfs_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = eth_receive,
.link_status_changed = eth_set_link,
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
index b5c777fbf..1e35f7f8c 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -33,7 +33,6 @@
#include "hw/ptimer.h"
#include "etsec.h"
#include "registers.h"
-#include "qemu/log.h"
/* #define HEX_DUMP */
/* #define DEBUG_REGISTER */
@@ -371,7 +370,7 @@ static void etsec_set_link_status(NetClientState *nc)
}
static NetClientInfo net_etsec_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = etsec_receive,
.link_status_changed = etsec_set_link_status,
diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h
index 30c828e24..e7dc0a4b9 100644
--- a/hw/net/fsl_etsec/etsec.h
+++ b/hw/net/fsl_etsec/etsec.h
@@ -21,9 +21,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-
-#ifndef ETSEC_H
-#define ETSEC_H
+#ifndef _ETSEC_H_
+#define _ETSEC_H_
#include "hw/qdev.h"
#include "hw/sysbus.h"
@@ -174,4 +173,4 @@ void etsec_write_miim(eTSEC *etsec,
void etsec_miim_link_status(eTSEC *etsec, NetClientState *nc);
-#endif /* ETSEC_H */
+#endif /* ! _ETSEC_H_ */
diff --git a/hw/net/fsl_etsec/registers.h b/hw/net/fsl_etsec/registers.h
index c4ed2b9d6..6fb96842b 100644
--- a/hw/net/fsl_etsec/registers.h
+++ b/hw/net/fsl_etsec/registers.h
@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#ifndef _ETSEC_REGISTERS_H_
+#define _ETSEC_REGISTERS_H_
-#ifndef ETSEC_REGISTERS_H
-#define ETSEC_REGISTERS_H
enum eTSEC_Register_Access_Type {
ACC_RW = 1, /* Read/Write */
@@ -316,4 +316,4 @@ extern const eTSEC_Register_Definition eTSEC_registers_def[];
#define TMR_ETTS2_H (0xEA8 / 4)
#define TMR_ETTS2_L (0xEAC / 4)
-#endif /* ETSEC_REGISTERS_H */
+#endif /* ! _ETSEC_REGISTERS_H_ */
diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c
index 79d2f14dd..ed1de7da9 100644
--- a/hw/net/fsl_etsec/rings.c
+++ b/hw/net/fsl_etsec/rings.c
@@ -23,7 +23,7 @@
*/
#include "qemu/osdep.h"
#include "net/checksum.h"
-#include "qemu/log.h"
+
#include "etsec.h"
#include "registers.h"
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 1c415ab3b..e60e3380e 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -24,9 +24,6 @@
#include "qemu/osdep.h"
#include "hw/net/imx_fec.h"
#include "sysemu/dma.h"
-#include "qemu/log.h"
-#include "net/checksum.h"
-#include "net/eth.h"
/* For crc32 */
#include <zlib.h>
@@ -55,153 +52,30 @@
} \
} while (0)
-static const char *imx_default_reg_name(IMXFECState *s, uint32_t index)
-{
- static char tmp[20];
- sprintf(tmp, "index %d", index);
- return tmp;
-}
-
-static const char *imx_fec_reg_name(IMXFECState *s, uint32_t index)
-{
- switch (index) {
- case ENET_FRBR:
- return "FRBR";
- case ENET_FRSR:
- return "FRSR";
- case ENET_MIIGSK_CFGR:
- return "MIIGSK_CFGR";
- case ENET_MIIGSK_ENR:
- return "MIIGSK_ENR";
- default:
- return imx_default_reg_name(s, index);
- }
-}
-
-static const char *imx_enet_reg_name(IMXFECState *s, uint32_t index)
-{
- switch (index) {
- case ENET_RSFL:
- return "RSFL";
- case ENET_RSEM:
- return "RSEM";
- case ENET_RAEM:
- return "RAEM";
- case ENET_RAFL:
- return "RAFL";
- case ENET_TSEM:
- return "TSEM";
- case ENET_TAEM:
- return "TAEM";
- case ENET_TAFL:
- return "TAFL";
- case ENET_TIPG:
- return "TIPG";
- case ENET_FTRL:
- return "FTRL";
- case ENET_TACC:
- return "TACC";
- case ENET_RACC:
- return "RACC";
- case ENET_ATCR:
- return "ATCR";
- case ENET_ATVR:
- return "ATVR";
- case ENET_ATOFF:
- return "ATOFF";
- case ENET_ATPER:
- return "ATPER";
- case ENET_ATCOR:
- return "ATCOR";
- case ENET_ATINC:
- return "ATINC";
- case ENET_ATSTMP:
- return "ATSTMP";
- case ENET_TGSR:
- return "TGSR";
- case ENET_TCSR0:
- return "TCSR0";
- case ENET_TCCR0:
- return "TCCR0";
- case ENET_TCSR1:
- return "TCSR1";
- case ENET_TCCR1:
- return "TCCR1";
- case ENET_TCSR2:
- return "TCSR2";
- case ENET_TCCR2:
- return "TCCR2";
- case ENET_TCSR3:
- return "TCSR3";
- case ENET_TCCR3:
- return "TCCR3";
- default:
- return imx_default_reg_name(s, index);
- }
-}
-
-static const char *imx_eth_reg_name(IMXFECState *s, uint32_t index)
-{
- switch (index) {
- case ENET_EIR:
- return "EIR";
- case ENET_EIMR:
- return "EIMR";
- case ENET_RDAR:
- return "RDAR";
- case ENET_TDAR:
- return "TDAR";
- case ENET_ECR:
- return "ECR";
- case ENET_MMFR:
- return "MMFR";
- case ENET_MSCR:
- return "MSCR";
- case ENET_MIBC:
- return "MIBC";
- case ENET_RCR:
- return "RCR";
- case ENET_TCR:
- return "TCR";
- case ENET_PALR:
- return "PALR";
- case ENET_PAUR:
- return "PAUR";
- case ENET_OPD:
- return "OPD";
- case ENET_IAUR:
- return "IAUR";
- case ENET_IALR:
- return "IALR";
- case ENET_GAUR:
- return "GAUR";
- case ENET_GALR:
- return "GALR";
- case ENET_TFWR:
- return "TFWR";
- case ENET_RDSR:
- return "RDSR";
- case ENET_TDSR:
- return "TDSR";
- case ENET_MRBR:
- return "MRBR";
- default:
- if (s->is_fec) {
- return imx_fec_reg_name(s, index);
- } else {
- return imx_enet_reg_name(s, index);
- }
- }
-}
-
-static const VMStateDescription vmstate_imx_eth = {
+static const VMStateDescription vmstate_imx_fec = {
.name = TYPE_IMX_FEC,
- .version_id = 2,
- .minimum_version_id = 2,
+ .version_id = 1,
+ .minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
+ VMSTATE_UINT32(irq_state, IMXFECState),
+ VMSTATE_UINT32(eir, IMXFECState),
+ VMSTATE_UINT32(eimr, IMXFECState),
+ VMSTATE_UINT32(rx_enabled, IMXFECState),
VMSTATE_UINT32(rx_descriptor, IMXFECState),
VMSTATE_UINT32(tx_descriptor, IMXFECState),
+ VMSTATE_UINT32(ecr, IMXFECState),
+ VMSTATE_UINT32(mmfr, IMXFECState),
+ VMSTATE_UINT32(mscr, IMXFECState),
+ VMSTATE_UINT32(mibc, IMXFECState),
+ VMSTATE_UINT32(rcr, IMXFECState),
+ VMSTATE_UINT32(tcr, IMXFECState),
+ VMSTATE_UINT32(tfwr, IMXFECState),
+ VMSTATE_UINT32(frsr, IMXFECState),
+ VMSTATE_UINT32(erdsr, IMXFECState),
+ VMSTATE_UINT32(etdsr, IMXFECState),
+ VMSTATE_UINT32(emrbr, IMXFECState),
+ VMSTATE_UINT32(miigsk_cfgr, IMXFECState),
+ VMSTATE_UINT32(miigsk_enr, IMXFECState),
VMSTATE_UINT32(phy_status, IMXFECState),
VMSTATE_UINT32(phy_control, IMXFECState),
@@ -220,7 +94,7 @@ static const VMStateDescription vmstate_imx_eth = {
#define PHY_INT_PARFAULT (1 << 2)
#define PHY_INT_AUTONEG_PAGE (1 << 1)
-static void imx_eth_update(IMXFECState *s);
+static void imx_fec_update(IMXFECState *s);
/*
* The MII phy could raise a GPIO to the processor which in turn
@@ -230,7 +104,7 @@ static void imx_eth_update(IMXFECState *s);
*/
static void phy_update_irq(IMXFECState *s)
{
- imx_eth_update(s);
+ imx_fec_update(s);
}
static void phy_update_link(IMXFECState *s)
@@ -249,7 +123,7 @@ static void phy_update_link(IMXFECState *s)
phy_update_irq(s);
}
-static void imx_eth_set_link(NetClientState *nc)
+static void imx_fec_set_link(NetClientState *nc)
{
phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
}
@@ -375,35 +249,23 @@ static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr)
dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd));
}
-static void imx_enet_read_bd(IMXENETBufDesc *bd, dma_addr_t addr)
+static void imx_fec_update(IMXFECState *s)
{
- dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd));
-}
+ uint32_t active;
+ uint32_t changed;
-static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr)
-{
- dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd));
-}
-
-static void imx_eth_update(IMXFECState *s)
-{
- if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & ENET_INT_TS_TIMER) {
- qemu_set_irq(s->irq[1], 1);
- } else {
- qemu_set_irq(s->irq[1], 0);
- }
-
- if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & ENET_INT_MAC) {
- qemu_set_irq(s->irq[0], 1);
- } else {
- qemu_set_irq(s->irq[0], 0);
+ active = s->eir & s->eimr;
+ changed = active ^ s->irq_state;
+ if (changed) {
+ qemu_set_irq(s->irq, active);
}
+ s->irq_state = active;
}
static void imx_fec_do_tx(IMXFECState *s)
{
int frame_size = 0;
- uint8_t frame[ENET_MAX_FRAME_SIZE];
+ uint8_t frame[FEC_MAX_FRAME_SIZE];
uint8_t *ptr = frame;
uint32_t addr = s->tx_descriptor;
@@ -414,521 +276,272 @@ static void imx_fec_do_tx(IMXFECState *s)
imx_fec_read_bd(&bd, addr);
FEC_PRINTF("tx_bd %x flags %04x len %d data %08x\n",
addr, bd.flags, bd.length, bd.data);
- if ((bd.flags & ENET_BD_R) == 0) {
+ if ((bd.flags & FEC_BD_R) == 0) {
/* Run out of descriptors to transmit. */
- FEC_PRINTF("tx_bd ran out of descriptors to transmit\n");
break;
}
len = bd.length;
- if (frame_size + len > ENET_MAX_FRAME_SIZE) {
- len = ENET_MAX_FRAME_SIZE - frame_size;
- s->regs[ENET_EIR] |= ENET_INT_BABT;
+ if (frame_size + len > FEC_MAX_FRAME_SIZE) {
+ len = FEC_MAX_FRAME_SIZE - frame_size;
+ s->eir |= FEC_INT_BABT;
}
dma_memory_read(&address_space_memory, bd.data, ptr, len);
ptr += len;
frame_size += len;
- if (bd.flags & ENET_BD_L) {
+ if (bd.flags & FEC_BD_L) {
/* Last buffer in frame. */
qemu_send_packet(qemu_get_queue(s->nic), frame, len);
ptr = frame;
frame_size = 0;
- s->regs[ENET_EIR] |= ENET_INT_TXF;
+ s->eir |= FEC_INT_TXF;
}
- s->regs[ENET_EIR] |= ENET_INT_TXB;
- bd.flags &= ~ENET_BD_R;
+ s->eir |= FEC_INT_TXB;
+ bd.flags &= ~FEC_BD_R;
/* Write back the modified descriptor. */
imx_fec_write_bd(&bd, addr);
/* Advance to the next descriptor. */
- if ((bd.flags & ENET_BD_W) != 0) {
- addr = s->regs[ENET_TDSR];
+ if ((bd.flags & FEC_BD_W) != 0) {
+ addr = s->etdsr;
} else {
- addr += sizeof(bd);
+ addr += 8;
}
}
s->tx_descriptor = addr;
- imx_eth_update(s);
+ imx_fec_update(s);
}
-static void imx_enet_do_tx(IMXFECState *s)
-{
- int frame_size = 0;
- uint8_t frame[ENET_MAX_FRAME_SIZE];
- uint8_t *ptr = frame;
- uint32_t addr = s->tx_descriptor;
-
- while (1) {
- IMXENETBufDesc bd;
- int len;
-
- imx_enet_read_bd(&bd, addr);
- FEC_PRINTF("tx_bd %x flags %04x len %d data %08x option %04x "
- "status %04x\n", addr, bd.flags, bd.length, bd.data,
- bd.option, bd.status);
- if ((bd.flags & ENET_BD_R) == 0) {
- /* Run out of descriptors to transmit. */
- break;
- }
- len = bd.length;
- if (frame_size + len > ENET_MAX_FRAME_SIZE) {
- len = ENET_MAX_FRAME_SIZE - frame_size;
- s->regs[ENET_EIR] |= ENET_INT_BABT;
- }
- dma_memory_read(&address_space_memory, bd.data, ptr, len);
- ptr += len;
- frame_size += len;
- if (bd.flags & ENET_BD_L) {
- if (bd.option & ENET_BD_PINS) {
- struct ip_header *ip_hd = PKT_GET_IP_HDR(frame);
- if (IP_HEADER_VERSION(ip_hd) == 4) {
- net_checksum_calculate(frame, frame_size);
- }
- }
- if (bd.option & ENET_BD_IINS) {
- struct ip_header *ip_hd = PKT_GET_IP_HDR(frame);
- /* We compute checksum only for IPv4 frames */
- if (IP_HEADER_VERSION(ip_hd) == 4) {
- uint16_t csum;
- ip_hd->ip_sum = 0;
- csum = net_raw_checksum((uint8_t *)ip_hd, sizeof(*ip_hd));
- ip_hd->ip_sum = cpu_to_be16(csum);
- }
- }
- /* Last buffer in frame. */
- qemu_send_packet(qemu_get_queue(s->nic), frame, len);
- ptr = frame;
- frame_size = 0;
- if (bd.option & ENET_BD_TX_INT) {
- s->regs[ENET_EIR] |= ENET_INT_TXF;
- }
- }
- if (bd.option & ENET_BD_TX_INT) {
- s->regs[ENET_EIR] |= ENET_INT_TXB;
- }
- bd.flags &= ~ENET_BD_R;
- /* Write back the modified descriptor. */
- imx_enet_write_bd(&bd, addr);
- /* Advance to the next descriptor. */
- if ((bd.flags & ENET_BD_W) != 0) {
- addr = s->regs[ENET_TDSR];
- } else {
- addr += sizeof(bd);
- }
- }
-
- s->tx_descriptor = addr;
-
- imx_eth_update(s);
-}
-
-static void imx_eth_do_tx(IMXFECState *s)
-{
- if (!s->is_fec && (s->regs[ENET_ECR] & ENET_ECR_EN1588)) {
- imx_enet_do_tx(s);
- } else {
- imx_fec_do_tx(s);
- }
-}
-
-static void imx_eth_enable_rx(IMXFECState *s)
+static void imx_fec_enable_rx(IMXFECState *s)
{
IMXFECBufDesc bd;
- bool tmp;
+ uint32_t tmp;
imx_fec_read_bd(&bd, s->rx_descriptor);
- tmp = ((bd.flags & ENET_BD_E) != 0);
+ tmp = ((bd.flags & FEC_BD_E) != 0);
if (!tmp) {
FEC_PRINTF("RX buffer full\n");
- } else if (!s->regs[ENET_RDAR]) {
+ } else if (!s->rx_enabled) {
qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
- s->regs[ENET_RDAR] = tmp ? ENET_RDAR_RDAR : 0;
+ s->rx_enabled = tmp;
}
-static void imx_eth_reset(DeviceState *d)
+static void imx_fec_reset(DeviceState *d)
{
IMXFECState *s = IMX_FEC(d);
- /* Reset the Device */
- memset(s->regs, 0, sizeof(s->regs));
- s->regs[ENET_ECR] = 0xf0000000;
- s->regs[ENET_MIBC] = 0xc0000000;
- s->regs[ENET_RCR] = 0x05ee0001;
- s->regs[ENET_OPD] = 0x00010000;
-
- s->regs[ENET_PALR] = (s->conf.macaddr.a[0] << 24)
- | (s->conf.macaddr.a[1] << 16)
- | (s->conf.macaddr.a[2] << 8)
- | s->conf.macaddr.a[3];
- s->regs[ENET_PAUR] = (s->conf.macaddr.a[4] << 24)
- | (s->conf.macaddr.a[5] << 16)
- | 0x8808;
-
- if (s->is_fec) {
- s->regs[ENET_FRBR] = 0x00000600;
- s->regs[ENET_FRSR] = 0x00000500;
- s->regs[ENET_MIIGSK_ENR] = 0x00000006;
- } else {
- s->regs[ENET_RAEM] = 0x00000004;
- s->regs[ENET_RAFL] = 0x00000004;
- s->regs[ENET_TAEM] = 0x00000004;
- s->regs[ENET_TAFL] = 0x00000008;
- s->regs[ENET_TIPG] = 0x0000000c;
- s->regs[ENET_FTRL] = 0x000007ff;
- s->regs[ENET_ATPER] = 0x3b9aca00;
- }
-
- s->rx_descriptor = 0;
- s->tx_descriptor = 0;
+ /* Reset the FEC */
+ s->eir = 0;
+ s->eimr = 0;
+ s->rx_enabled = 0;
+ s->ecr = 0;
+ s->mscr = 0;
+ s->mibc = 0xc0000000;
+ s->rcr = 0x05ee0001;
+ s->tcr = 0;
+ s->tfwr = 0;
+ s->frsr = 0x500;
+ s->miigsk_cfgr = 0;
+ s->miigsk_enr = 0x6;
/* We also reset the PHY */
phy_reset(s);
}
-static uint32_t imx_default_read(IMXFECState *s, uint32_t index)
-{
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- PRIx32 "\n", TYPE_IMX_FEC, __func__, index * 4);
- return 0;
-}
-
-static uint32_t imx_fec_read(IMXFECState *s, uint32_t index)
-{
- switch (index) {
- case ENET_FRBR:
- case ENET_FRSR:
- case ENET_MIIGSK_CFGR:
- case ENET_MIIGSK_ENR:
- return s->regs[index];
- default:
- return imx_default_read(s, index);
- }
-}
-
-static uint32_t imx_enet_read(IMXFECState *s, uint32_t index)
+static uint64_t imx_fec_read(void *opaque, hwaddr addr, unsigned size)
{
- switch (index) {
- case ENET_RSFL:
- case ENET_RSEM:
- case ENET_RAEM:
- case ENET_RAFL:
- case ENET_TSEM:
- case ENET_TAEM:
- case ENET_TAFL:
- case ENET_TIPG:
- case ENET_FTRL:
- case ENET_TACC:
- case ENET_RACC:
- case ENET_ATCR:
- case ENET_ATVR:
- case ENET_ATOFF:
- case ENET_ATPER:
- case ENET_ATCOR:
- case ENET_ATINC:
- case ENET_ATSTMP:
- case ENET_TGSR:
- case ENET_TCSR0:
- case ENET_TCCR0:
- case ENET_TCSR1:
- case ENET_TCCR1:
- case ENET_TCSR2:
- case ENET_TCCR2:
- case ENET_TCSR3:
- case ENET_TCCR3:
- return s->regs[index];
- default:
- return imx_default_read(s, index);
- }
-}
-
-static uint64_t imx_eth_read(void *opaque, hwaddr offset, unsigned size)
-{
- uint32_t value = 0;
IMXFECState *s = IMX_FEC(opaque);
- uint32_t index = offset >> 2;
-
- switch (index) {
- case ENET_EIR:
- case ENET_EIMR:
- case ENET_RDAR:
- case ENET_TDAR:
- case ENET_ECR:
- case ENET_MMFR:
- case ENET_MSCR:
- case ENET_MIBC:
- case ENET_RCR:
- case ENET_TCR:
- case ENET_PALR:
- case ENET_PAUR:
- case ENET_OPD:
- case ENET_IAUR:
- case ENET_IALR:
- case ENET_GAUR:
- case ENET_GALR:
- case ENET_TFWR:
- case ENET_RDSR:
- case ENET_TDSR:
- case ENET_MRBR:
- value = s->regs[index];
- break;
- default:
- if (s->is_fec) {
- value = imx_fec_read(s, index);
- } else {
- value = imx_enet_read(s, index);
- }
- break;
- }
-
- FEC_PRINTF("reg[%s] => 0x%" PRIx32 "\n", imx_eth_reg_name(s, index),
- value);
-
- return value;
-}
-
-static void imx_default_write(IMXFECState *s, uint32_t index, uint32_t value)
-{
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
- PRIx32 "\n", TYPE_IMX_FEC, __func__, index * 4);
- return;
-}
-
-static void imx_fec_write(IMXFECState *s, uint32_t index, uint32_t value)
-{
- switch (index) {
- case ENET_FRBR:
- /* FRBR is read only */
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Register FRBR is read only\n",
- TYPE_IMX_FEC, __func__);
- break;
- case ENET_FRSR:
- s->regs[index] = (value & 0x000003fc) | 0x00000400;
- break;
- case ENET_MIIGSK_CFGR:
- s->regs[index] = value & 0x00000053;
- break;
- case ENET_MIIGSK_ENR:
- s->regs[index] = (value & 0x00000002) ? 0x00000006 : 0;
- break;
- default:
- imx_default_write(s, index, value);
- break;
- }
-}
-static void imx_enet_write(IMXFECState *s, uint32_t index, uint32_t value)
-{
- switch (index) {
- case ENET_RSFL:
- case ENET_RSEM:
- case ENET_RAEM:
- case ENET_RAFL:
- case ENET_TSEM:
- case ENET_TAEM:
- case ENET_TAFL:
- s->regs[index] = value & 0x000001ff;
- break;
- case ENET_TIPG:
- s->regs[index] = value & 0x0000001f;
- break;
- case ENET_FTRL:
- s->regs[index] = value & 0x00003fff;
- break;
- case ENET_TACC:
- s->regs[index] = value & 0x00000019;
- break;
- case ENET_RACC:
- s->regs[index] = value & 0x000000C7;
- break;
- case ENET_ATCR:
- s->regs[index] = value & 0x00002a9d;
- break;
- case ENET_ATVR:
- case ENET_ATOFF:
- case ENET_ATPER:
- s->regs[index] = value;
- break;
- case ENET_ATSTMP:
- /* ATSTMP is read only */
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Register ATSTMP is read only\n",
- TYPE_IMX_FEC, __func__);
- break;
- case ENET_ATCOR:
- s->regs[index] = value & 0x7fffffff;
- break;
- case ENET_ATINC:
- s->regs[index] = value & 0x00007f7f;
- break;
- case ENET_TGSR:
- /* implement clear timer flag */
- value = value & 0x0000000f;
- break;
- case ENET_TCSR0:
- case ENET_TCSR1:
- case ENET_TCSR2:
- case ENET_TCSR3:
- value = value & 0x000000fd;
- break;
- case ENET_TCCR0:
- case ENET_TCCR1:
- case ENET_TCCR2:
- case ENET_TCCR3:
- s->regs[index] = value;
- break;
+ FEC_PRINTF("reading from @ 0x%" HWADDR_PRIx "\n", addr);
+
+ switch (addr & 0x3ff) {
+ case 0x004:
+ return s->eir;
+ case 0x008:
+ return s->eimr;
+ case 0x010:
+ return s->rx_enabled ? (1 << 24) : 0; /* RDAR */
+ case 0x014:
+ return 0; /* TDAR */
+ case 0x024:
+ return s->ecr;
+ case 0x040:
+ return s->mmfr;
+ case 0x044:
+ return s->mscr;
+ case 0x064:
+ return s->mibc; /* MIBC */
+ case 0x084:
+ return s->rcr;
+ case 0x0c4:
+ return s->tcr;
+ case 0x0e4: /* PALR */
+ return (s->conf.macaddr.a[0] << 24)
+ | (s->conf.macaddr.a[1] << 16)
+ | (s->conf.macaddr.a[2] << 8)
+ | s->conf.macaddr.a[3];
+ break;
+ case 0x0e8: /* PAUR */
+ return (s->conf.macaddr.a[4] << 24)
+ | (s->conf.macaddr.a[5] << 16)
+ | 0x8808;
+ case 0x0ec:
+ return 0x10000; /* OPD */
+ case 0x118:
+ return 0;
+ case 0x11c:
+ return 0;
+ case 0x120:
+ return 0;
+ case 0x124:
+ return 0;
+ case 0x144:
+ return s->tfwr;
+ case 0x14c:
+ return 0x600;
+ case 0x150:
+ return s->frsr;
+ case 0x180:
+ return s->erdsr;
+ case 0x184:
+ return s->etdsr;
+ case 0x188:
+ return s->emrbr;
+ case 0x300:
+ return s->miigsk_cfgr;
+ case 0x308:
+ return s->miigsk_enr;
default:
- imx_default_write(s, index, value);
- break;
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_FEC, __func__, addr);
+ return 0;
}
}
-static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
+static void imx_fec_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size)
{
IMXFECState *s = IMX_FEC(opaque);
- uint32_t index = offset >> 2;
- FEC_PRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_eth_reg_name(s, index),
- (uint32_t)value);
+ FEC_PRINTF("writing 0x%08x @ 0x%" HWADDR_PRIx "\n", (int)value, addr);
- switch (index) {
- case ENET_EIR:
- s->regs[index] &= ~value;
+ switch (addr & 0x3ff) {
+ case 0x004: /* EIR */
+ s->eir &= ~value;
break;
- case ENET_EIMR:
- s->regs[index] = value;
+ case 0x008: /* EIMR */
+ s->eimr = value;
break;
- case ENET_RDAR:
- if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
- if (!s->regs[index]) {
- s->regs[index] = ENET_RDAR_RDAR;
- imx_eth_enable_rx(s);
- }
- } else {
- s->regs[index] = 0;
+ case 0x010: /* RDAR */
+ if ((s->ecr & FEC_EN) && !s->rx_enabled) {
+ imx_fec_enable_rx(s);
}
break;
- case ENET_TDAR:
- if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
- s->regs[index] = ENET_TDAR_TDAR;
- imx_eth_do_tx(s);
+ case 0x014: /* TDAR */
+ if (s->ecr & FEC_EN) {
+ imx_fec_do_tx(s);
}
- s->regs[index] = 0;
break;
- case ENET_ECR:
- if (value & ENET_ECR_RESET) {
- return imx_eth_reset(DEVICE(s));
+ case 0x024: /* ECR */
+ s->ecr = value;
+ if (value & FEC_RESET) {
+ imx_fec_reset(DEVICE(s));
}
- s->regs[index] = value;
- if ((s->regs[index] & ENET_ECR_ETHEREN) == 0) {
- s->regs[ENET_RDAR] = 0;
- s->rx_descriptor = s->regs[ENET_RDSR];
- s->regs[ENET_TDAR] = 0;
- s->tx_descriptor = s->regs[ENET_TDSR];
+ if ((s->ecr & FEC_EN) == 0) {
+ s->rx_enabled = 0;
}
break;
- case ENET_MMFR:
- s->regs[index] = value;
- if (extract32(value, 29, 1)) {
- /* This is a read operation */
- s->regs[ENET_MMFR] = deposit32(s->regs[ENET_MMFR], 0, 16,
- do_phy_read(s,
- extract32(value,
- 18, 10)));
+ case 0x040: /* MMFR */
+ /* store the value */
+ s->mmfr = value;
+ if (extract32(value, 28, 1)) {
+ do_phy_write(s, extract32(value, 18, 9), extract32(value, 0, 16));
} else {
- /* This a write operation */
- do_phy_write(s, extract32(value, 18, 10), extract32(value, 0, 16));
+ s->mmfr = do_phy_read(s, extract32(value, 18, 9));
}
/* raise the interrupt as the PHY operation is done */
- s->regs[ENET_EIR] |= ENET_INT_MII;
+ s->eir |= FEC_INT_MII;
break;
- case ENET_MSCR:
- s->regs[index] = value & 0xfe;
+ case 0x044: /* MSCR */
+ s->mscr = value & 0xfe;
break;
- case ENET_MIBC:
+ case 0x064: /* MIBC */
/* TODO: Implement MIB. */
- s->regs[index] = (value & 0x80000000) ? 0xc0000000 : 0;
+ s->mibc = (value & 0x80000000) ? 0xc0000000 : 0;
break;
- case ENET_RCR:
- s->regs[index] = value & 0x07ff003f;
+ case 0x084: /* RCR */
+ s->rcr = value & 0x07ff003f;
/* TODO: Implement LOOP mode. */
break;
- case ENET_TCR:
+ case 0x0c4: /* TCR */
/* We transmit immediately, so raise GRA immediately. */
- s->regs[index] = value;
+ s->tcr = value;
if (value & 1) {
- s->regs[ENET_EIR] |= ENET_INT_GRA;
+ s->eir |= FEC_INT_GRA;
}
break;
- case ENET_PALR:
- s->regs[index] = value;
+ case 0x0e4: /* PALR */
s->conf.macaddr.a[0] = value >> 24;
s->conf.macaddr.a[1] = value >> 16;
s->conf.macaddr.a[2] = value >> 8;
s->conf.macaddr.a[3] = value;
break;
- case ENET_PAUR:
- s->regs[index] = (value | 0x0000ffff) & 0xffff8808;
+ case 0x0e8: /* PAUR */
s->conf.macaddr.a[4] = value >> 24;
s->conf.macaddr.a[5] = value >> 16;
break;
- case ENET_OPD:
- s->regs[index] = (value & 0x0000ffff) | 0x00010000;
+ case 0x0ec: /* OPDR */
break;
- case ENET_IAUR:
- case ENET_IALR:
- case ENET_GAUR:
- case ENET_GALR:
+ case 0x118: /* IAUR */
+ case 0x11c: /* IALR */
+ case 0x120: /* GAUR */
+ case 0x124: /* GALR */
/* TODO: implement MAC hash filtering. */
break;
- case ENET_TFWR:
- if (s->is_fec) {
- s->regs[index] = value & 0x3;
- } else {
- s->regs[index] = value & 0x13f;
- }
+ case 0x144: /* TFWR */
+ s->tfwr = value & 3;
break;
- case ENET_RDSR:
- if (s->is_fec) {
- s->regs[index] = value & ~3;
- } else {
- s->regs[index] = value & ~7;
- }
- s->rx_descriptor = s->regs[index];
+ case 0x14c: /* FRBR */
+ /* FRBR writes ignored. */
break;
- case ENET_TDSR:
- if (s->is_fec) {
- s->regs[index] = value & ~3;
- } else {
- s->regs[index] = value & ~7;
- }
- s->tx_descriptor = s->regs[index];
+ case 0x150: /* FRSR */
+ s->frsr = (value & 0x3fc) | 0x400;
+ break;
+ case 0x180: /* ERDSR */
+ s->erdsr = value & ~3;
+ s->rx_descriptor = s->erdsr;
break;
- case ENET_MRBR:
- s->regs[index] = value & 0x00003ff0;
+ case 0x184: /* ETDSR */
+ s->etdsr = value & ~3;
+ s->tx_descriptor = s->etdsr;
+ break;
+ case 0x188: /* EMRBR */
+ s->emrbr = value & 0x7f0;
+ break;
+ case 0x300: /* MIIGSK_CFGR */
+ s->miigsk_cfgr = value & 0x53;
+ break;
+ case 0x308: /* MIIGSK_ENR */
+ s->miigsk_enr = (value & 0x2) ? 0x6 : 0;
break;
default:
- if (s->is_fec) {
- imx_fec_write(s, index, value);
- } else {
- imx_enet_write(s, index, value);
- }
- return;
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_FEC, __func__, addr);
+ break;
}
- imx_eth_update(s);
+ imx_fec_update(s);
}
-static int imx_eth_can_receive(NetClientState *nc)
+static int imx_fec_can_receive(NetClientState *nc)
{
IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
- FEC_PRINTF("\n");
-
- return s->regs[ENET_RDAR] ? 1 : 0;
+ return s->rx_enabled;
}
static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
@@ -946,7 +559,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
FEC_PRINTF("len %d\n", (int)size);
- if (!s->regs[ENET_RDAR]) {
+ if (!s->rx_enabled) {
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n",
TYPE_IMX_FEC, __func__);
return 0;
@@ -957,21 +570,21 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
crc = cpu_to_be32(crc32(~0, buf, size));
crc_ptr = (uint8_t *) &crc;
- /* Huge frames are truncated. */
- if (size > ENET_MAX_FRAME_SIZE) {
- size = ENET_MAX_FRAME_SIZE;
- flags |= ENET_BD_TR | ENET_BD_LG;
+ /* Huge frames are truncted. */
+ if (size > FEC_MAX_FRAME_SIZE) {
+ size = FEC_MAX_FRAME_SIZE;
+ flags |= FEC_BD_TR | FEC_BD_LG;
}
/* Frames larger than the user limit just set error flags. */
- if (size > (s->regs[ENET_RCR] >> 16)) {
- flags |= ENET_BD_LG;
+ if (size > (s->rcr >> 16)) {
+ flags |= FEC_BD_LG;
}
addr = s->rx_descriptor;
while (size > 0) {
imx_fec_read_bd(&bd, addr);
- if ((bd.flags & ENET_BD_E) == 0) {
+ if ((bd.flags & FEC_BD_E) == 0) {
/* No descriptors available. Bail out. */
/*
* FIXME: This is wrong. We should probably either
@@ -982,7 +595,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
TYPE_IMX_FEC, __func__);
break;
}
- buf_len = (size <= s->regs[ENET_MRBR]) ? size : s->regs[ENET_MRBR];
+ buf_len = (size <= s->emrbr) ? size : s->emrbr;
bd.length = buf_len;
size -= buf_len;
@@ -1000,232 +613,99 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
crc_ptr, 4 - size);
crc_ptr += 4 - size;
}
- bd.flags &= ~ENET_BD_E;
+ bd.flags &= ~FEC_BD_E;
if (size == 0) {
/* Last buffer in frame. */
- bd.flags |= flags | ENET_BD_L;
+ bd.flags |= flags | FEC_BD_L;
FEC_PRINTF("rx frame flags %04x\n", bd.flags);
- s->regs[ENET_EIR] |= ENET_INT_RXF;
+ s->eir |= FEC_INT_RXF;
} else {
- s->regs[ENET_EIR] |= ENET_INT_RXB;
+ s->eir |= FEC_INT_RXB;
}
imx_fec_write_bd(&bd, addr);
/* Advance to the next descriptor. */
- if ((bd.flags & ENET_BD_W) != 0) {
- addr = s->regs[ENET_RDSR];
- } else {
- addr += sizeof(bd);
- }
- }
- s->rx_descriptor = addr;
- imx_eth_enable_rx(s);
- imx_eth_update(s);
- return len;
-}
-
-static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
- size_t len)
-{
- IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
- IMXENETBufDesc bd;
- uint32_t flags = 0;
- uint32_t addr;
- uint32_t crc;
- uint32_t buf_addr;
- uint8_t *crc_ptr;
- unsigned int buf_len;
- size_t size = len;
-
- FEC_PRINTF("len %d\n", (int)size);
-
- if (!s->regs[ENET_RDAR]) {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n",
- TYPE_IMX_FEC, __func__);
- return 0;
- }
-
- /* 4 bytes for the CRC. */
- size += 4;
- crc = cpu_to_be32(crc32(~0, buf, size));
- crc_ptr = (uint8_t *) &crc;
-
- /* Huge frames are truncted. */
- if (size > ENET_MAX_FRAME_SIZE) {
- size = ENET_MAX_FRAME_SIZE;
- flags |= ENET_BD_TR | ENET_BD_LG;
- }
-
- /* Frames larger than the user limit just set error flags. */
- if (size > (s->regs[ENET_RCR] >> 16)) {
- flags |= ENET_BD_LG;
- }
-
- addr = s->rx_descriptor;
- while (size > 0) {
- imx_enet_read_bd(&bd, addr);
- if ((bd.flags & ENET_BD_E) == 0) {
- /* No descriptors available. Bail out. */
- /*
- * FIXME: This is wrong. We should probably either
- * save the remainder for when more RX buffers are
- * available, or flag an error.
- */
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Lost end of frame\n",
- TYPE_IMX_FEC, __func__);
- break;
- }
- buf_len = (size <= s->regs[ENET_MRBR]) ? size : s->regs[ENET_MRBR];
- bd.length = buf_len;
- size -= buf_len;
-
- FEC_PRINTF("rx_bd 0x%x length %d\n", addr, bd.length);
-
- /* The last 4 bytes are the CRC. */
- if (size < 4) {
- buf_len += size - 4;
- }
- buf_addr = bd.data;
- dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
- buf += buf_len;
- if (size < 4) {
- dma_memory_write(&address_space_memory, buf_addr + buf_len,
- crc_ptr, 4 - size);
- crc_ptr += 4 - size;
- }
- bd.flags &= ~ENET_BD_E;
- if (size == 0) {
- /* Last buffer in frame. */
- bd.flags |= flags | ENET_BD_L;
- FEC_PRINTF("rx frame flags %04x\n", bd.flags);
- if (bd.option & ENET_BD_RX_INT) {
- s->regs[ENET_EIR] |= ENET_INT_RXF;
- }
- } else {
- if (bd.option & ENET_BD_RX_INT) {
- s->regs[ENET_EIR] |= ENET_INT_RXB;
- }
- }
- imx_enet_write_bd(&bd, addr);
- /* Advance to the next descriptor. */
- if ((bd.flags & ENET_BD_W) != 0) {
- addr = s->regs[ENET_RDSR];
+ if ((bd.flags & FEC_BD_W) != 0) {
+ addr = s->erdsr;
} else {
- addr += sizeof(bd);
+ addr += 8;
}
}
s->rx_descriptor = addr;
- imx_eth_enable_rx(s);
- imx_eth_update(s);
+ imx_fec_enable_rx(s);
+ imx_fec_update(s);
return len;
}
-static ssize_t imx_eth_receive(NetClientState *nc, const uint8_t *buf,
- size_t len)
-{
- IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
-
- if (!s->is_fec && (s->regs[ENET_ECR] & ENET_ECR_EN1588)) {
- return imx_enet_receive(nc, buf, len);
- } else {
- return imx_fec_receive(nc, buf, len);
- }
-}
-
-static const MemoryRegionOps imx_eth_ops = {
- .read = imx_eth_read,
- .write = imx_eth_write,
+static const MemoryRegionOps imx_fec_ops = {
+ .read = imx_fec_read,
+ .write = imx_fec_write,
.valid.min_access_size = 4,
.valid.max_access_size = 4,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
-static void imx_eth_cleanup(NetClientState *nc)
+static void imx_fec_cleanup(NetClientState *nc)
{
IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
s->nic = NULL;
}
-static NetClientInfo imx_eth_net_info = {
- .type = NET_CLIENT_DRIVER_NIC,
- .size = sizeof(NICState),
- .can_receive = imx_eth_can_receive,
- .receive = imx_eth_receive,
- .cleanup = imx_eth_cleanup,
- .link_status_changed = imx_eth_set_link,
+static NetClientInfo net_imx_fec_info = {
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
+ .size = sizeof(NICState),
+ .can_receive = imx_fec_can_receive,
+ .receive = imx_fec_receive,
+ .cleanup = imx_fec_cleanup,
+ .link_status_changed = imx_fec_set_link,
};
-static void imx_eth_realize(DeviceState *dev, Error **errp)
+static void imx_fec_realize(DeviceState *dev, Error **errp)
{
IMXFECState *s = IMX_FEC(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- memory_region_init_io(&s->iomem, OBJECT(dev), &imx_eth_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(dev), &imx_fec_ops, s,
TYPE_IMX_FEC, 0x400);
sysbus_init_mmio(sbd, &s->iomem);
- sysbus_init_irq(sbd, &s->irq[0]);
- sysbus_init_irq(sbd, &s->irq[1]);
-
+ sysbus_init_irq(sbd, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->conf.peers.ncs[0] = nd_table[0].netdev;
- s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
- object_get_typename(OBJECT(dev)),
- DEVICE(dev)->id, s);
-
+ s->nic = qemu_new_nic(&net_imx_fec_info, &s->conf,
+ object_get_typename(OBJECT(dev)), DEVICE(dev)->id,
+ s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
-static Property imx_eth_properties[] = {
+static Property imx_fec_properties[] = {
DEFINE_NIC_PROPERTIES(IMXFECState, conf),
DEFINE_PROP_END_OF_LIST(),
};
-static void imx_eth_class_init(ObjectClass *klass, void *data)
+static void imx_fec_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- dc->vmsd = &vmstate_imx_eth;
- dc->reset = imx_eth_reset;
- dc->props = imx_eth_properties;
- dc->realize = imx_eth_realize;
- dc->desc = "i.MX FEC/ENET Ethernet Controller";
-}
-
-static void imx_fec_init(Object *obj)
-{
- IMXFECState *s = IMX_FEC(obj);
-
- s->is_fec = true;
-}
-
-static void imx_enet_init(Object *obj)
-{
- IMXFECState *s = IMX_FEC(obj);
-
- s->is_fec = false;
+ dc->vmsd = &vmstate_imx_fec;
+ dc->reset = imx_fec_reset;
+ dc->props = imx_fec_properties;
+ dc->realize = imx_fec_realize;
+ dc->desc = "i.MX FEC Ethernet Controller";
}
static const TypeInfo imx_fec_info = {
- .name = TYPE_IMX_FEC,
- .parent = TYPE_SYS_BUS_DEVICE,
+ .name = TYPE_IMX_FEC,
+ .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMXFECState),
- .instance_init = imx_fec_init,
- .class_init = imx_eth_class_init,
-};
-
-static const TypeInfo imx_enet_info = {
- .name = TYPE_IMX_ENET,
- .parent = TYPE_IMX_FEC,
- .instance_init = imx_enet_init,
+ .class_init = imx_fec_class_init,
};
-static void imx_eth_register_types(void)
+static void imx_fec_register_types(void)
{
type_register_static(&imx_fec_info);
- type_register_static(&imx_enet_info);
}
-type_init(imx_eth_register_types)
+type_init(imx_fec_register_types)
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 4615d873b..08dc474d6 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -16,7 +16,6 @@
#include "hw/devices.h"
#include "sysemu/sysemu.h"
#include "hw/ptimer.h"
-#include "qemu/log.h"
/* For crc32 */
#include <zlib.h>
@@ -1313,7 +1312,7 @@ static const MemoryRegionOps lan9118_16bit_mem_ops = {
};
static NetClientInfo net_lan9118_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = lan9118_receive,
.link_status_changed = lan9118_set_link,
diff --git a/hw/net/lance.c b/hw/net/lance.c
index 573d724bc..6253d2103 100644
--- a/hw/net/lance.c
+++ b/hw/net/lance.c
@@ -93,7 +93,7 @@ static const MemoryRegionOps lance_mem_ops = {
};
static NetClientInfo net_lance_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = pcnet_receive,
.link_status_changed = pcnet_set_link_status,
diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c
index 0ee8ad9d6..7c0398ed9 100644
--- a/hw/net/mcf_fec.c
+++ b/hw/net/mcf_fec.c
@@ -507,7 +507,7 @@ static const MemoryRegionOps mcf_fec_ops = {
};
static NetClientInfo net_mcf_fec_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = mcf_fec_receive,
};
diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c
index c3a12e119..1e147c33c 100644
--- a/hw/net/milkymist-minimac2.c
+++ b/hw/net/milkymist-minimac2.c
@@ -447,7 +447,7 @@ static void milkymist_minimac2_reset(DeviceState *d)
}
static NetClientInfo net_milkymist_minimac2_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = minimac2_rx,
};
diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
index 5a63df7cc..cf8b8236d 100644
--- a/hw/net/mipsnet.c
+++ b/hw/net/mipsnet.c
@@ -183,12 +183,10 @@ static void mipsnet_ioport_write(void *opaque, hwaddr addr,
break;
case MIPSNET_TX_DATA_BUFFER:
s->tx_buffer[s->tx_written++] = val;
- if ((s->tx_written >= MAX_ETH_FRAME_SIZE)
- || (s->tx_written == s->tx_count)) {
+ if (s->tx_written == s->tx_count) {
/* Send buffer. */
- trace_mipsnet_send(s->tx_written);
- qemu_send_packet(qemu_get_queue(s->nic),
- s->tx_buffer, s->tx_written);
+ trace_mipsnet_send(s->tx_count);
+ qemu_send_packet(qemu_get_queue(s->nic), s->tx_buffer, s->tx_count);
s->tx_count = s->tx_written = 0;
s->intctl |= MIPSNET_INTCTL_TXDONE;
s->busy = 1;
@@ -224,7 +222,7 @@ static const VMStateDescription vmstate_mipsnet = {
};
static NetClientInfo net_mipsnet_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = mipsnet_receive,
};
diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
index f3455339e..a7f5a9464 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -44,7 +44,7 @@ typedef struct ISANE2000State {
} ISANE2000State;
static NetClientInfo net_ne2000_isa_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = ne2000_receive,
};
@@ -127,7 +127,9 @@ static void isa_ne2000_set_bootindex(Object *obj, Visitor *v,
s->c.bootindex = boot_index;
out:
- error_propagate(errp, local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ }
}
static void isa_ne2000_instance_init(Object *obj)
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
index 798d681e2..f0feaf96b 100644
--- a/hw/net/ne2000.c
+++ b/hw/net/ne2000.c
@@ -712,7 +712,7 @@ void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size)
}
static NetClientInfo net_ne2000_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = ne2000_receive,
};
diff --git a/hw/net/ne2000.h b/hw/net/ne2000.h
index d213dccae..d022b28fc 100644
--- a/hw/net/ne2000.h
+++ b/hw/net/ne2000.h
@@ -1,5 +1,5 @@
#ifndef HW_NE2000_H
-#define HW_NE2000_H
+#define HW_NE2000_H 1
#define NE2000_PMEM_SIZE (32*1024)
#define NE2000_PMEM_START (16*1024)
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
deleted file mode 100644
index 1019b50c1..000000000
--- a/hw/net/net_rx_pkt.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * QEMU RX packets abstractions
- *
- * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
- *
- * Developed by Daynix Computing LTD (http://www.daynix.com)
- *
- * Authors:
- * Dmitry Fleytman <dmitry@daynix.com>
- * Tamir Shomer <tamirs@daynix.com>
- * Yan Vugenfirer <yan@daynix.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.
- *
- */
-
-#include "qemu/osdep.h"
-#include "trace.h"
-#include "net_rx_pkt.h"
-#include "net/checksum.h"
-#include "net/tap.h"
-
-struct NetRxPkt {
- struct virtio_net_hdr virt_hdr;
- uint8_t ehdr_buf[sizeof(struct eth_header)];
- struct iovec *vec;
- uint16_t vec_len_total;
- uint16_t vec_len;
- uint32_t tot_len;
- uint16_t tci;
- bool vlan_stripped;
- bool has_virt_hdr;
- eth_pkt_types_e packet_type;
-
- /* Analysis results */
- bool isip4;
- bool isip6;
- bool isudp;
- bool istcp;
-
- size_t l3hdr_off;
- size_t l4hdr_off;
- size_t l5hdr_off;
-
- eth_ip6_hdr_info ip6hdr_info;
- eth_ip4_hdr_info ip4hdr_info;
- eth_l4_hdr_info l4hdr_info;
-};
-
-void net_rx_pkt_init(struct NetRxPkt **pkt, bool has_virt_hdr)
-{
- struct NetRxPkt *p = g_malloc0(sizeof *p);
- p->has_virt_hdr = has_virt_hdr;
- p->vec = NULL;
- p->vec_len_total = 0;
- *pkt = p;
-}
-
-void net_rx_pkt_uninit(struct NetRxPkt *pkt)
-{
- if (pkt->vec_len_total != 0) {
- g_free(pkt->vec);
- }
-
- g_free(pkt);
-}
-
-struct virtio_net_hdr *net_rx_pkt_get_vhdr(struct NetRxPkt *pkt)
-{
- assert(pkt);
- return &pkt->virt_hdr;
-}
-
-static inline void
-net_rx_pkt_iovec_realloc(struct NetRxPkt *pkt,
- int new_iov_len)
-{
- if (pkt->vec_len_total < new_iov_len) {
- g_free(pkt->vec);
- pkt->vec = g_malloc(sizeof(*pkt->vec) * new_iov_len);
- pkt->vec_len_total = new_iov_len;
- }
-}
-
-static void
-net_rx_pkt_pull_data(struct NetRxPkt *pkt,
- const struct iovec *iov, int iovcnt,
- size_t ploff)
-{
- if (pkt->vlan_stripped) {
- net_rx_pkt_iovec_realloc(pkt, iovcnt + 1);
-
- pkt->vec[0].iov_base = pkt->ehdr_buf;
- pkt->vec[0].iov_len = sizeof(pkt->ehdr_buf);
-
- pkt->tot_len =
- iov_size(iov, iovcnt) - ploff + sizeof(struct eth_header);
-
- pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
- iov, iovcnt, ploff, pkt->tot_len);
- } else {
- net_rx_pkt_iovec_realloc(pkt, iovcnt);
-
- pkt->tot_len = iov_size(iov, iovcnt) - ploff;
- pkt->vec_len = iov_copy(pkt->vec, pkt->vec_len_total,
- iov, iovcnt, ploff, pkt->tot_len);
- }
-
- eth_get_protocols(pkt->vec, pkt->vec_len, &pkt->isip4, &pkt->isip6,
- &pkt->isudp, &pkt->istcp,
- &pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off,
- &pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info);
-
- trace_net_rx_pkt_parsed(pkt->isip4, pkt->isip6, pkt->isudp, pkt->istcp,
- pkt->l3hdr_off, pkt->l4hdr_off, pkt->l5hdr_off);
-}
-
-void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt,
- const struct iovec *iov, int iovcnt,
- size_t iovoff, bool strip_vlan)
-{
- uint16_t tci = 0;
- uint16_t ploff = iovoff;
- assert(pkt);
- pkt->vlan_stripped = false;
-
- if (strip_vlan) {
- pkt->vlan_stripped = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf,
- &ploff, &tci);
- }
-
- pkt->tci = tci;
-
- net_rx_pkt_pull_data(pkt, iov, iovcnt, ploff);
-}
-
-void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
- const struct iovec *iov, int iovcnt,
- size_t iovoff, bool strip_vlan,
- uint16_t vet)
-{
- uint16_t tci = 0;
- uint16_t ploff = iovoff;
- assert(pkt);
- pkt->vlan_stripped = false;
-
- if (strip_vlan) {
- pkt->vlan_stripped = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
- pkt->ehdr_buf,
- &ploff, &tci);
- }
-
- pkt->tci = tci;
-
- net_rx_pkt_pull_data(pkt, iov, iovcnt, ploff);
-}
-
-void net_rx_pkt_dump(struct NetRxPkt *pkt)
-{
-#ifdef NET_RX_PKT_DEBUG
- NetRxPkt *pkt = (NetRxPkt *)pkt;
- assert(pkt);
-
- printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
- pkt->tot_len, pkt->vlan_stripped, pkt->tci);
-#endif
-}
-
-void net_rx_pkt_set_packet_type(struct NetRxPkt *pkt,
- eth_pkt_types_e packet_type)
-{
- assert(pkt);
-
- pkt->packet_type = packet_type;
-
-}
-
-eth_pkt_types_e net_rx_pkt_get_packet_type(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- return pkt->packet_type;
-}
-
-size_t net_rx_pkt_get_total_len(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- return pkt->tot_len;
-}
-
-void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, const void *data,
- size_t len)
-{
- const struct iovec iov = {
- .iov_base = (void *)data,
- .iov_len = len
- };
-
- assert(pkt);
-
- eth_get_protocols(&iov, 1, &pkt->isip4, &pkt->isip6,
- &pkt->isudp, &pkt->istcp,
- &pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off,
- &pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info);
-}
-
-void net_rx_pkt_get_protocols(struct NetRxPkt *pkt,
- bool *isip4, bool *isip6,
- bool *isudp, bool *istcp)
-{
- assert(pkt);
-
- *isip4 = pkt->isip4;
- *isip6 = pkt->isip6;
- *isudp = pkt->isudp;
- *istcp = pkt->istcp;
-}
-
-size_t net_rx_pkt_get_l3_hdr_offset(struct NetRxPkt *pkt)
-{
- assert(pkt);
- return pkt->l3hdr_off;
-}
-
-size_t net_rx_pkt_get_l4_hdr_offset(struct NetRxPkt *pkt)
-{
- assert(pkt);
- return pkt->l4hdr_off;
-}
-
-size_t net_rx_pkt_get_l5_hdr_offset(struct NetRxPkt *pkt)
-{
- assert(pkt);
- return pkt->l5hdr_off;
-}
-
-eth_ip6_hdr_info *net_rx_pkt_get_ip6_info(struct NetRxPkt *pkt)
-{
- return &pkt->ip6hdr_info;
-}
-
-eth_ip4_hdr_info *net_rx_pkt_get_ip4_info(struct NetRxPkt *pkt)
-{
- return &pkt->ip4hdr_info;
-}
-
-eth_l4_hdr_info *net_rx_pkt_get_l4_info(struct NetRxPkt *pkt)
-{
- return &pkt->l4hdr_info;
-}
-
-static inline void
-_net_rx_rss_add_chunk(uint8_t *rss_input, size_t *bytes_written,
- void *ptr, size_t size)
-{
- memcpy(&rss_input[*bytes_written], ptr, size);
- trace_net_rx_pkt_rss_add_chunk(ptr, size, *bytes_written);
- *bytes_written += size;
-}
-
-static inline void
-_net_rx_rss_prepare_ip4(uint8_t *rss_input,
- struct NetRxPkt *pkt,
- size_t *bytes_written)
-{
- struct ip_header *ip4_hdr = &pkt->ip4hdr_info.ip4_hdr;
-
- _net_rx_rss_add_chunk(rss_input, bytes_written,
- &ip4_hdr->ip_src, sizeof(uint32_t));
-
- _net_rx_rss_add_chunk(rss_input, bytes_written,
- &ip4_hdr->ip_dst, sizeof(uint32_t));
-}
-
-static inline void
-_net_rx_rss_prepare_ip6(uint8_t *rss_input,
- struct NetRxPkt *pkt,
- bool ipv6ex, size_t *bytes_written)
-{
- eth_ip6_hdr_info *ip6info = &pkt->ip6hdr_info;
-
- _net_rx_rss_add_chunk(rss_input, bytes_written,
- (ipv6ex && ip6info->rss_ex_src_valid) ? &ip6info->rss_ex_src
- : &ip6info->ip6_hdr.ip6_src,
- sizeof(struct in6_address));
-
- _net_rx_rss_add_chunk(rss_input, bytes_written,
- (ipv6ex && ip6info->rss_ex_dst_valid) ? &ip6info->rss_ex_dst
- : &ip6info->ip6_hdr.ip6_dst,
- sizeof(struct in6_address));
-}
-
-static inline void
-_net_rx_rss_prepare_tcp(uint8_t *rss_input,
- struct NetRxPkt *pkt,
- size_t *bytes_written)
-{
- struct tcp_header *tcphdr = &pkt->l4hdr_info.hdr.tcp;
-
- _net_rx_rss_add_chunk(rss_input, bytes_written,
- &tcphdr->th_sport, sizeof(uint16_t));
-
- _net_rx_rss_add_chunk(rss_input, bytes_written,
- &tcphdr->th_dport, sizeof(uint16_t));
-}
-
-uint32_t
-net_rx_pkt_calc_rss_hash(struct NetRxPkt *pkt,
- NetRxPktRssType type,
- uint8_t *key)
-{
- uint8_t rss_input[36];
- size_t rss_length = 0;
- uint32_t rss_hash = 0;
- net_toeplitz_key key_data;
-
- switch (type) {
- case NetPktRssIpV4:
- assert(pkt->isip4);
- trace_net_rx_pkt_rss_ip4();
- _net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length);
- break;
- case NetPktRssIpV4Tcp:
- assert(pkt->isip4);
- assert(pkt->istcp);
- trace_net_rx_pkt_rss_ip4_tcp();
- _net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length);
- _net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length);
- break;
- case NetPktRssIpV6Tcp:
- assert(pkt->isip6);
- assert(pkt->istcp);
- trace_net_rx_pkt_rss_ip6_tcp();
- _net_rx_rss_prepare_ip6(&rss_input[0], pkt, true, &rss_length);
- _net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length);
- break;
- case NetPktRssIpV6:
- assert(pkt->isip6);
- trace_net_rx_pkt_rss_ip6();
- _net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &rss_length);
- break;
- case NetPktRssIpV6Ex:
- assert(pkt->isip6);
- trace_net_rx_pkt_rss_ip6_ex();
- _net_rx_rss_prepare_ip6(&rss_input[0], pkt, true, &rss_length);
- break;
- default:
- assert(false);
- break;
- }
-
- net_toeplitz_key_init(&key_data, key);
- net_toeplitz_add(&rss_hash, rss_input, rss_length, &key_data);
-
- trace_net_rx_pkt_rss_hash(rss_length, rss_hash);
-
- return rss_hash;
-}
-
-uint16_t net_rx_pkt_get_ip_id(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- if (pkt->isip4) {
- return be16_to_cpu(pkt->ip4hdr_info.ip4_hdr.ip_id);
- }
-
- return 0;
-}
-
-bool net_rx_pkt_is_tcp_ack(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- if (pkt->istcp) {
- return TCP_HEADER_FLAGS(&pkt->l4hdr_info.hdr.tcp) & TCP_FLAG_ACK;
- }
-
- return false;
-}
-
-bool net_rx_pkt_has_tcp_data(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- if (pkt->istcp) {
- return pkt->l4hdr_info.has_tcp_data;
- }
-
- return false;
-}
-
-struct iovec *net_rx_pkt_get_iovec(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- return pkt->vec;
-}
-
-uint16_t net_rx_pkt_get_iovec_len(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- return pkt->vec_len;
-}
-
-void net_rx_pkt_set_vhdr(struct NetRxPkt *pkt,
- struct virtio_net_hdr *vhdr)
-{
- assert(pkt);
-
- memcpy(&pkt->virt_hdr, vhdr, sizeof pkt->virt_hdr);
-}
-
-void net_rx_pkt_set_vhdr_iovec(struct NetRxPkt *pkt,
- const struct iovec *iov, int iovcnt)
-{
- assert(pkt);
-
- iov_to_buf(iov, iovcnt, 0, &pkt->virt_hdr, sizeof pkt->virt_hdr);
-}
-
-bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- return pkt->vlan_stripped;
-}
-
-bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- return pkt->has_virt_hdr;
-}
-
-uint16_t net_rx_pkt_get_vlan_tag(struct NetRxPkt *pkt)
-{
- assert(pkt);
-
- return pkt->tci;
-}
-
-bool net_rx_pkt_validate_l3_csum(struct NetRxPkt *pkt, bool *csum_valid)
-{
- uint32_t cntr;
- uint16_t csum;
- uint32_t csl;
-
- trace_net_rx_pkt_l3_csum_validate_entry();
-
- if (!pkt->isip4) {
- trace_net_rx_pkt_l3_csum_validate_not_ip4();
- return false;
- }
-
- csl = pkt->l4hdr_off - pkt->l3hdr_off;
-
- cntr = net_checksum_add_iov(pkt->vec, pkt->vec_len,
- pkt->l3hdr_off,
- csl, 0);
-
- csum = net_checksum_finish(cntr);
-
- *csum_valid = (csum == 0);
-
- trace_net_rx_pkt_l3_csum_validate_csum(pkt->l3hdr_off, csl,
- cntr, csum, *csum_valid);
-
- return true;
-}
-
-static uint16_t
-_net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt)
-{
- uint32_t cntr;
- uint16_t csum;
- uint16_t csl;
- uint32_t cso;
-
- trace_net_rx_pkt_l4_csum_calc_entry();
-
- if (pkt->isip4) {
- if (pkt->isudp) {
- csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen);
- trace_net_rx_pkt_l4_csum_calc_ip4_udp();
- } else {
- csl = be16_to_cpu(pkt->ip4hdr_info.ip4_hdr.ip_len) -
- IP_HDR_GET_LEN(&pkt->ip4hdr_info.ip4_hdr);
- trace_net_rx_pkt_l4_csum_calc_ip4_tcp();
- }
-
- cntr = eth_calc_ip4_pseudo_hdr_csum(&pkt->ip4hdr_info.ip4_hdr,
- csl, &cso);
- trace_net_rx_pkt_l4_csum_calc_ph_csum(cntr, csl);
- } else {
- if (pkt->isudp) {
- csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen);
- trace_net_rx_pkt_l4_csum_calc_ip6_udp();
- } else {
- struct ip6_header *ip6hdr = &pkt->ip6hdr_info.ip6_hdr;
- size_t full_ip6hdr_len = pkt->l4hdr_off - pkt->l3hdr_off;
- size_t ip6opts_len = full_ip6hdr_len - sizeof(struct ip6_header);
-
- csl = be16_to_cpu(ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_plen) -
- ip6opts_len;
- trace_net_rx_pkt_l4_csum_calc_ip6_tcp();
- }
-
- cntr = eth_calc_ip6_pseudo_hdr_csum(&pkt->ip6hdr_info.ip6_hdr, csl,
- pkt->ip6hdr_info.l4proto, &cso);
- trace_net_rx_pkt_l4_csum_calc_ph_csum(cntr, csl);
- }
-
- cntr += net_checksum_add_iov(pkt->vec, pkt->vec_len,
- pkt->l4hdr_off, csl, cso);
-
- csum = net_checksum_finish(cntr);
-
- trace_net_rx_pkt_l4_csum_calc_csum(pkt->l4hdr_off, csl, cntr, csum);
-
- return csum;
-}
-
-bool net_rx_pkt_validate_l4_csum(struct NetRxPkt *pkt, bool *csum_valid)
-{
- uint16_t csum;
-
- trace_net_rx_pkt_l4_csum_validate_entry();
-
- if (!pkt->istcp && !pkt->isudp) {
- trace_net_rx_pkt_l4_csum_validate_not_xxp();
- return false;
- }
-
- if (pkt->isudp && (pkt->l4hdr_info.hdr.udp.uh_sum == 0)) {
- trace_net_rx_pkt_l4_csum_validate_udp_with_no_checksum();
- return false;
- }
-
- if (pkt->isip4 && pkt->ip4hdr_info.fragment) {
- trace_net_rx_pkt_l4_csum_validate_ip4_fragment();
- return false;
- }
-
- csum = _net_rx_pkt_calc_l4_csum(pkt);
-
- *csum_valid = ((csum == 0) || (csum == 0xFFFF));
-
- trace_net_rx_pkt_l4_csum_validate_csum(*csum_valid);
-
- return true;
-}
-
-bool net_rx_pkt_fix_l4_csum(struct NetRxPkt *pkt)
-{
- uint16_t csum = 0;
- uint32_t l4_cso;
-
- trace_net_rx_pkt_l4_csum_fix_entry();
-
- if (pkt->istcp) {
- l4_cso = offsetof(struct tcp_header, th_sum);
- trace_net_rx_pkt_l4_csum_fix_tcp(l4_cso);
- } else if (pkt->isudp) {
- if (pkt->l4hdr_info.hdr.udp.uh_sum == 0) {
- trace_net_rx_pkt_l4_csum_fix_udp_with_no_checksum();
- return false;
- }
- l4_cso = offsetof(struct udp_header, uh_sum);
- trace_net_rx_pkt_l4_csum_fix_udp(l4_cso);
- } else {
- trace_net_rx_pkt_l4_csum_fix_not_xxp();
- return false;
- }
-
- if (pkt->isip4 && pkt->ip4hdr_info.fragment) {
- trace_net_rx_pkt_l4_csum_fix_ip4_fragment();
- return false;
- }
-
- /* Set zero to checksum word */
- iov_from_buf(pkt->vec, pkt->vec_len,
- pkt->l4hdr_off + l4_cso,
- &csum, sizeof(csum));
-
- /* Calculate L4 checksum */
- csum = cpu_to_be16(_net_rx_pkt_calc_l4_csum(pkt));
-
- /* Set calculated checksum to checksum word */
- iov_from_buf(pkt->vec, pkt->vec_len,
- pkt->l4hdr_off + l4_cso,
- &csum, sizeof(csum));
-
- trace_net_rx_pkt_l4_csum_fix_csum(pkt->l4hdr_off + l4_cso, csum);
-
- return true;
-}
diff --git a/hw/net/net_rx_pkt.h b/hw/net/net_rx_pkt.h
deleted file mode 100644
index 7adf0fad5..000000000
--- a/hw/net/net_rx_pkt.h
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * QEMU RX packets abstraction
- *
- * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
- *
- * Developed by Daynix Computing LTD (http://www.daynix.com)
- *
- * Authors:
- * Dmitry Fleytman <dmitry@daynix.com>
- * Tamir Shomer <tamirs@daynix.com>
- * Yan Vugenfirer <yan@daynix.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 NET_RX_PKT_H
-#define NET_RX_PKT_H
-
-#include "net/eth.h"
-
-/* defines to enable packet dump functions */
-/*#define NET_RX_PKT_DEBUG*/
-
-struct NetRxPkt;
-
-/**
- * Clean all rx packet resources
- *
- * @pkt: packet
- *
- */
-void net_rx_pkt_uninit(struct NetRxPkt *pkt);
-
-/**
- * Init function for rx packet functionality
- *
- * @pkt: packet pointer
- * @has_virt_hdr: device uses virtio header
- *
- */
-void net_rx_pkt_init(struct NetRxPkt **pkt, bool has_virt_hdr);
-
-/**
- * returns total length of data attached to rx context
- *
- * @pkt: packet
- *
- * Return: nothing
- *
- */
-size_t net_rx_pkt_get_total_len(struct NetRxPkt *pkt);
-
-/**
- * parse and set packet analysis results
- *
- * @pkt: packet
- * @data: pointer to the data buffer to be parsed
- * @len: data length
- *
- */
-void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, const void *data,
- size_t len);
-
-/**
- * fetches packet analysis results
- *
- * @pkt: packet
- * @isip4: whether the packet given is IPv4
- * @isip6: whether the packet given is IPv6
- * @isudp: whether the packet given is UDP
- * @istcp: whether the packet given is TCP
- *
- */
-void net_rx_pkt_get_protocols(struct NetRxPkt *pkt,
- bool *isip4, bool *isip6,
- bool *isudp, bool *istcp);
-
-/**
-* fetches L3 header offset
-*
-* @pkt: packet
-*
-*/
-size_t net_rx_pkt_get_l3_hdr_offset(struct NetRxPkt *pkt);
-
-/**
-* fetches L4 header offset
-*
-* @pkt: packet
-*
-*/
-size_t net_rx_pkt_get_l4_hdr_offset(struct NetRxPkt *pkt);
-
-/**
-* fetches L5 header offset
-*
-* @pkt: packet
-*
-*/
-size_t net_rx_pkt_get_l5_hdr_offset(struct NetRxPkt *pkt);
-
-/**
- * fetches IP6 header analysis results
- *
- * Return: pointer to analysis results structure which is stored in internal
- * packet area.
- *
- */
-eth_ip6_hdr_info *net_rx_pkt_get_ip6_info(struct NetRxPkt *pkt);
-
-/**
- * fetches IP4 header analysis results
- *
- * Return: pointer to analysis results structure which is stored in internal
- * packet area.
- *
- */
-eth_ip4_hdr_info *net_rx_pkt_get_ip4_info(struct NetRxPkt *pkt);
-
-/**
- * fetches L4 header analysis results
- *
- * Return: pointer to analysis results structure which is stored in internal
- * packet area.
- *
- */
-eth_l4_hdr_info *net_rx_pkt_get_l4_info(struct NetRxPkt *pkt);
-
-typedef enum {
- NetPktRssIpV4,
- NetPktRssIpV4Tcp,
- NetPktRssIpV6Tcp,
- NetPktRssIpV6,
- NetPktRssIpV6Ex
-} NetRxPktRssType;
-
-/**
-* calculates RSS hash for packet
-*
-* @pkt: packet
-* @type: RSS hash type
-*
-* Return: Toeplitz RSS hash.
-*
-*/
-uint32_t
-net_rx_pkt_calc_rss_hash(struct NetRxPkt *pkt,
- NetRxPktRssType type,
- uint8_t *key);
-
-/**
-* fetches IP identification for the packet
-*
-* @pkt: packet
-*
-*/
-uint16_t net_rx_pkt_get_ip_id(struct NetRxPkt *pkt);
-
-/**
-* check if given packet is a TCP ACK packet
-*
-* @pkt: packet
-*
-*/
-bool net_rx_pkt_is_tcp_ack(struct NetRxPkt *pkt);
-
-/**
-* check if given packet contains TCP data
-*
-* @pkt: packet
-*
-*/
-bool net_rx_pkt_has_tcp_data(struct NetRxPkt *pkt);
-
-/**
- * returns virtio header stored in rx context
- *
- * @pkt: packet
- * @ret: virtio header
- *
- */
-struct virtio_net_hdr *net_rx_pkt_get_vhdr(struct NetRxPkt *pkt);
-
-/**
- * returns packet type
- *
- * @pkt: packet
- * @ret: packet type
- *
- */
-eth_pkt_types_e net_rx_pkt_get_packet_type(struct NetRxPkt *pkt);
-
-/**
- * returns vlan tag
- *
- * @pkt: packet
- * @ret: VLAN tag
- *
- */
-uint16_t net_rx_pkt_get_vlan_tag(struct NetRxPkt *pkt);
-
-/**
- * tells whether vlan was stripped from the packet
- *
- * @pkt: packet
- * @ret: VLAN stripped sign
- *
- */
-bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt);
-
-/**
- * notifies caller if the packet has virtio header
- *
- * @pkt: packet
- * @ret: true if packet has virtio header, false otherwize
- *
- */
-bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt);
-
-/**
-* attach scatter-gather data to rx packet
-*
-* @pkt: packet
-* @iov: received data scatter-gather list
-* @iovcnt number of elements in iov
-* @iovoff data start offset in the iov
-* @strip_vlan: should the module strip vlan from data
-*
-*/
-void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt,
- const struct iovec *iov,
- int iovcnt, size_t iovoff,
- bool strip_vlan);
-
-/**
-* attach scatter-gather data to rx packet
-*
-* @pkt: packet
-* @iov: received data scatter-gather list
-* @iovcnt number of elements in iov
-* @iovoff data start offset in the iov
-* @strip_vlan: should the module strip vlan from data
-* @vet: VLAN tag Ethernet type
-*
-*/
-void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
- const struct iovec *iov, int iovcnt,
- size_t iovoff, bool strip_vlan,
- uint16_t vet);
-
-/**
- * attach data to rx packet
- *
- * @pkt: packet
- * @data: pointer to the data buffer
- * @len: data length
- * @strip_vlan: should the module strip vlan from data
- *
- */
-static inline void
-net_rx_pkt_attach_data(struct NetRxPkt *pkt, const void *data,
- size_t len, bool strip_vlan)
-{
- const struct iovec iov = {
- .iov_base = (void *) data,
- .iov_len = len
- };
-
- net_rx_pkt_attach_iovec(pkt, &iov, 1, 0, strip_vlan);
-}
-
-/**
- * returns io vector that holds the attached data
- *
- * @pkt: packet
- * @ret: pointer to IOVec
- *
- */
-struct iovec *net_rx_pkt_get_iovec(struct NetRxPkt *pkt);
-
-/**
-* returns io vector length that holds the attached data
-*
-* @pkt: packet
-* @ret: IOVec length
-*
-*/
-uint16_t net_rx_pkt_get_iovec_len(struct NetRxPkt *pkt);
-
-/**
- * prints rx packet data if debug is enabled
- *
- * @pkt: packet
- *
- */
-void net_rx_pkt_dump(struct NetRxPkt *pkt);
-
-/**
- * copy passed vhdr data to packet context
- *
- * @pkt: packet
- * @vhdr: VHDR buffer
- *
- */
-void net_rx_pkt_set_vhdr(struct NetRxPkt *pkt,
- struct virtio_net_hdr *vhdr);
-
-/**
-* copy passed vhdr data to packet context
-*
-* @pkt: packet
-* @iov: VHDR iov
-* @iovcnt: VHDR iov array size
-*
-*/
-void net_rx_pkt_set_vhdr_iovec(struct NetRxPkt *pkt,
- const struct iovec *iov, int iovcnt);
-
-/**
- * save packet type in packet context
- *
- * @pkt: packet
- * @packet_type: the packet type
- *
- */
-void net_rx_pkt_set_packet_type(struct NetRxPkt *pkt,
- eth_pkt_types_e packet_type);
-
-/**
-* validate TCP/UDP checksum of the packet
-*
-* @pkt: packet
-* @csum_valid: checksum validation result
-* @ret: true if validation was performed, false in case packet is
-* not TCP/UDP or checksum validation is not possible
-*
-*/
-bool net_rx_pkt_validate_l4_csum(struct NetRxPkt *pkt, bool *csum_valid);
-
-/**
-* validate IPv4 checksum of the packet
-*
-* @pkt: packet
-* @csum_valid: checksum validation result
-* @ret: true if validation was performed, false in case packet is
-* not TCP/UDP or checksum validation is not possible
-*
-*/
-bool net_rx_pkt_validate_l3_csum(struct NetRxPkt *pkt, bool *csum_valid);
-
-/**
-* fix IPv4 checksum of the packet
-*
-* @pkt: packet
-* @ret: true if checksum was fixed, false in case packet is
-* not TCP/UDP or checksum correction is not possible
-*
-*/
-bool net_rx_pkt_fix_l4_csum(struct NetRxPkt *pkt);
-
-#endif
diff --git a/hw/net/net_tx_pkt.h b/hw/net/net_tx_pkt.h
deleted file mode 100644
index 212ecc62f..000000000
--- a/hw/net/net_tx_pkt.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * QEMU TX packets abstraction
- *
- * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
- *
- * Developed by Daynix Computing LTD (http://www.daynix.com)
- *
- * Authors:
- * Dmitry Fleytman <dmitry@daynix.com>
- * Tamir Shomer <tamirs@daynix.com>
- * Yan Vugenfirer <yan@daynix.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 NET_TX_PKT_H
-#define NET_TX_PKT_H
-
-#include "net/eth.h"
-#include "exec/hwaddr.h"
-
-/* define to enable packet dump functions */
-/*#define NET_TX_PKT_DEBUG*/
-
-struct NetTxPkt;
-
-/**
- * Init function for tx packet functionality
- *
- * @pkt: packet pointer
- * @pci_dev: PCI device processing this packet
- * @max_frags: max tx ip fragments
- * @has_virt_hdr: device uses virtio header.
- */
-void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev,
- uint32_t max_frags, bool has_virt_hdr);
-
-/**
- * Clean all tx packet resources.
- *
- * @pkt: packet.
- */
-void net_tx_pkt_uninit(struct NetTxPkt *pkt);
-
-/**
- * get virtio header
- *
- * @pkt: packet
- * @ret: virtio header
- */
-struct virtio_net_hdr *net_tx_pkt_get_vhdr(struct NetTxPkt *pkt);
-
-/**
- * build virtio header (will be stored in module context)
- *
- * @pkt: packet
- * @tso_enable: TSO enabled
- * @csum_enable: CSO enabled
- * @gso_size: MSS size for TSO
- *
- */
-void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
- bool csum_enable, uint32_t gso_size);
-
-/**
-* updates vlan tag, and adds vlan header with custom ethernet type
-* in case it is missing.
-*
-* @pkt: packet
-* @vlan: VLAN tag
-* @vlan_ethtype: VLAN header Ethernet type
-*
-*/
-void net_tx_pkt_setup_vlan_header_ex(struct NetTxPkt *pkt,
- uint16_t vlan, uint16_t vlan_ethtype);
-
-/**
-* updates vlan tag, and adds vlan header in case it is missing
-*
-* @pkt: packet
-* @vlan: VLAN tag
-*
-*/
-static inline void
-net_tx_pkt_setup_vlan_header(struct NetTxPkt *pkt, uint16_t vlan)
-{
- net_tx_pkt_setup_vlan_header_ex(pkt, vlan, ETH_P_VLAN);
-}
-
-/**
- * populate data fragment into pkt context.
- *
- * @pkt: packet
- * @pa: physical address of fragment
- * @len: length of fragment
- *
- */
-bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa,
- size_t len);
-
-/**
- * Fix ip header fields and calculate IP header and pseudo header checksums.
- *
- * @pkt: packet
- *
- */
-void net_tx_pkt_update_ip_checksums(struct NetTxPkt *pkt);
-
-/**
- * Calculate the IP header checksum.
- *
- * @pkt: packet
- *
- */
-void net_tx_pkt_update_ip_hdr_checksum(struct NetTxPkt *pkt);
-
-/**
- * get length of all populated data.
- *
- * @pkt: packet
- * @ret: total data length
- *
- */
-size_t net_tx_pkt_get_total_len(struct NetTxPkt *pkt);
-
-/**
- * get packet type
- *
- * @pkt: packet
- * @ret: packet type
- *
- */
-eth_pkt_types_e net_tx_pkt_get_packet_type(struct NetTxPkt *pkt);
-
-/**
- * prints packet data if debug is enabled
- *
- * @pkt: packet
- *
- */
-void net_tx_pkt_dump(struct NetTxPkt *pkt);
-
-/**
- * reset tx packet private context (needed to be called between packets)
- *
- * @pkt: packet
- *
- */
-void net_tx_pkt_reset(struct NetTxPkt *pkt);
-
-/**
- * Send packet to qemu. handles sw offloads if vhdr is not supported.
- *
- * @pkt: packet
- * @nc: NetClientState
- * @ret: operation result
- *
- */
-bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState *nc);
-
-/**
-* Redirect packet directly to receive path (emulate loopback phy).
-* Handles sw offloads if vhdr is not supported.
-*
-* @pkt: packet
-* @nc: NetClientState
-* @ret: operation result
-*
-*/
-bool net_tx_pkt_send_loopback(struct NetTxPkt *pkt, NetClientState *nc);
-
-/**
- * parse raw packet data and analyze offload requirements.
- *
- * @pkt: packet
- *
- */
-bool net_tx_pkt_parse(struct NetTxPkt *pkt);
-
-/**
-* indicates if there are data fragments held by this packet object.
-*
-* @pkt: packet
-*
-*/
-bool net_tx_pkt_has_fragments(struct NetTxPkt *pkt);
-
-#endif
diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
index 268d6a789..c6094fbb5 100644
--- a/hw/net/opencores_eth.c
+++ b/hw/net/opencores_eth.c
@@ -33,7 +33,6 @@
#include "qemu/osdep.h"
#include "hw/hw.h"
-#include "hw/net/mii.h"
#include "hw/sysbus.h"
#include "net/net.h"
#include "sysemu/sysemu.h"
@@ -56,6 +55,12 @@
/* PHY MII registers */
enum {
+ MII_BMCR,
+ MII_BMSR,
+ MII_PHYIDR1,
+ MII_PHYIDR2,
+ MII_ANAR,
+ MII_ANLPAR,
MII_REG_MAX = 16,
};
@@ -67,11 +72,10 @@ typedef struct Mii {
static void mii_set_link(Mii *s, bool link_ok)
{
if (link_ok) {
- s->regs[MII_BMSR] |= MII_BMSR_LINK_ST;
- s->regs[MII_ANLPAR] |= MII_ANLPAR_TXFD | MII_ANLPAR_TX |
- MII_ANLPAR_10FD | MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
+ s->regs[MII_BMSR] |= 0x4;
+ s->regs[MII_ANLPAR] |= 0x01e1;
} else {
- s->regs[MII_BMSR] &= ~MII_BMSR_LINK_ST;
+ s->regs[MII_BMSR] &= ~0x4;
s->regs[MII_ANLPAR] &= 0x01ff;
}
s->link_ok = link_ok;
@@ -80,14 +84,11 @@ static void mii_set_link(Mii *s, bool link_ok)
static void mii_reset(Mii *s)
{
memset(s->regs, 0, sizeof(s->regs));
- s->regs[MII_BMCR] = MII_BMCR_AUTOEN;
- s->regs[MII_BMSR] = MII_BMSR_100TX_FD | MII_BMSR_100TX_HD |
- MII_BMSR_10T_FD | MII_BMSR_10T_HD | MII_BMSR_MFPS |
- MII_BMSR_AN_COMP | MII_BMSR_AUTONEG;
- s->regs[MII_PHYID1] = 0x2000;
- s->regs[MII_PHYID2] = 0x5c90;
- s->regs[MII_ANAR] = MII_ANAR_TXFD | MII_ANAR_TX |
- MII_ANAR_10FD | MII_ANAR_10 | MII_ANAR_CSMACD;
+ s->regs[MII_BMCR] = 0x1000;
+ s->regs[MII_BMSR] = 0x7868; /* no ext regs */
+ s->regs[MII_PHYIDR1] = 0x2000;
+ s->regs[MII_PHYIDR2] = 0x5c90;
+ s->regs[MII_ANAR] = 0x01e1;
mii_set_link(s, s->link_ok);
}
@@ -97,7 +98,7 @@ static void mii_ro(Mii *s, uint16_t v)
static void mii_write_bmcr(Mii *s, uint16_t v)
{
- if (v & MII_BMCR_RESET) {
+ if (v & 0x8000) {
mii_reset(s);
} else {
s->regs[MII_BMCR] = v;
@@ -109,8 +110,8 @@ static void mii_write_host(Mii *s, unsigned idx, uint16_t v)
static void (*reg_write[MII_REG_MAX])(Mii *s, uint16_t v) = {
[MII_BMCR] = mii_write_bmcr,
[MII_BMSR] = mii_ro,
- [MII_PHYID1] = mii_ro,
- [MII_PHYID2] = mii_ro,
+ [MII_PHYIDR1] = mii_ro,
+ [MII_PHYIDR2] = mii_ro,
};
if (idx < MII_REG_MAX) {
@@ -473,7 +474,7 @@ static ssize_t open_eth_receive(NetClientState *nc,
}
static NetClientInfo net_open_eth_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = open_eth_can_receive,
.receive = open_eth_receive,
@@ -482,8 +483,7 @@ static NetClientInfo net_open_eth_info = {
static void open_eth_start_xmit(OpenEthState *s, desc *tx)
{
- uint8_t *buf = NULL;
- uint8_t buffer[0x600];
+ uint8_t buf[65536];
unsigned len = GET_FIELD(tx->len_flags, TXD_LEN);
unsigned tx_len = len;
@@ -498,11 +498,6 @@ static void open_eth_start_xmit(OpenEthState *s, desc *tx)
trace_open_eth_start_xmit(tx->buf_ptr, len, tx_len);
- if (tx_len > sizeof(buffer)) {
- buf = g_new(uint8_t, tx_len);
- } else {
- buf = buffer;
- }
if (len > tx_len) {
len = tx_len;
}
@@ -511,9 +506,6 @@ static void open_eth_start_xmit(OpenEthState *s, desc *tx)
memset(buf + len, 0, tx_len - len);
}
qemu_send_packet(qemu_get_queue(s->nic), buf, tx_len);
- if (tx_len > sizeof(buffer)) {
- g_free(buf);
- }
if (tx->len_flags & TXD_WR) {
s->tx_desc = 0;
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
index 0acf8a487..595439a65 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -272,7 +272,7 @@ static void pci_pcnet_uninit(PCIDevice *dev)
}
static NetClientInfo net_pci_pcnet_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = pcnet_receive,
.link_status_changed = pcnet_set_link_status,
diff --git a/hw/net/pcnet.h b/hw/net/pcnet.h
index 40831a784..dec8de834 100644
--- a/hw/net/pcnet.h
+++ b/hw/net/pcnet.h
@@ -1,5 +1,5 @@
#ifndef HW_PCNET_H
-#define HW_PCNET_H
+#define HW_PCNET_H 1
#define PCNET_IOPORT_SIZE 0x20
#define PCNET_PNPMMIO_SIZE 0x20
diff --git a/hw/net/rocker/rocker.h b/hw/net/rocker/rocker.h
index 7ae0495d9..f9c80f801 100644
--- a/hw/net/rocker/rocker.h
+++ b/hw/net/rocker/rocker.h
@@ -16,8 +16,8 @@
* GNU General Public License for more details.
*/
-#ifndef ROCKER_H
-#define ROCKER_H
+#ifndef _ROCKER_H_
+#define _ROCKER_H_
#include "qemu/sockets.h"
@@ -81,4 +81,4 @@ int rx_produce(World *world, uint32_t pport,
int rocker_port_eg(Rocker *r, uint32_t pport,
const struct iovec *iov, int iovcnt);
-#endif /* ROCKER_H */
+#endif /* _ROCKER_H_ */
diff --git a/hw/net/rocker/rocker_desc.h b/hw/net/rocker/rocker_desc.h
index 1dec33561..d4041f5c4 100644
--- a/hw/net/rocker/rocker_desc.h
+++ b/hw/net/rocker/rocker_desc.h
@@ -14,8 +14,9 @@
* GNU General Public License for more details.
*/
-#ifndef ROCKER_DESC_H
-#define ROCKER_DESC_H
+
+#ifndef _ROCKER_DESC_H_
+#define _ROCKER_DESC_H_
#include "rocker_hw.h"
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index 1305ac36c..0149899c6 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -167,7 +167,7 @@ static void fp_port_set_link_status(NetClientState *nc)
}
static NetClientInfo fp_port_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = fp_port_receive,
.receive_iov = fp_port_receive_iov,
diff --git a/hw/net/rocker/rocker_fp.h b/hw/net/rocker/rocker_fp.h
index dbe1dd329..04592bbfd 100644
--- a/hw/net/rocker/rocker_fp.h
+++ b/hw/net/rocker/rocker_fp.h
@@ -14,8 +14,8 @@
* GNU General Public License for more details.
*/
-#ifndef ROCKER_FP_H
-#define ROCKER_FP_H
+#ifndef _ROCKER_FP_H_
+#define _ROCKER_FP_H_
#include "net/net.h"
#include "qemu/iov.h"
@@ -51,4 +51,4 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name,
void fp_port_free(FpPort *port);
void fp_port_reset(FpPort *port);
-#endif /* ROCKER_FP_H */
+#endif /* _ROCKER_FP_H_ */
diff --git a/hw/net/rocker/rocker_hw.h b/hw/net/rocker/rocker_hw.h
index 1786323fa..8c5083032 100644
--- a/hw/net/rocker/rocker_hw.h
+++ b/hw/net/rocker/rocker_hw.h
@@ -6,8 +6,8 @@
*
*/
-#ifndef ROCKER_HW_H
-#define ROCKER_HW_H
+#ifndef _ROCKER_HW_
+#define _ROCKER_HW_
#define __le16 uint16_t
#define __le32 uint32_t
@@ -490,4 +490,4 @@ enum rocker_of_dpa_overlay_type {
*/
#define ROCKER_CONTROL_RESET (1 << 0)
-#endif /* ROCKER_HW_H */
+#endif /* _ROCKER_HW_ */
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
index 9b1e0d244..0a134ebca 100644
--- a/hw/net/rocker/rocker_of_dpa.c
+++ b/hw/net/rocker/rocker_of_dpa.c
@@ -103,8 +103,9 @@ typedef struct of_dpa_flow_key {
/* Width of key which includes field 'f' in u64s, rounded up */
#define FLOW_KEY_WIDTH(f) \
- DIV_ROUND_UP(offsetof(OfDpaFlowKey, f) + sizeof(((OfDpaFlowKey *)0)->f), \
- sizeof(uint64_t))
+ ((offsetof(OfDpaFlowKey, f) + \
+ sizeof(((OfDpaFlowKey *)0)->f) + \
+ sizeof(uint64_t) - 1) / sizeof(uint64_t))
typedef struct of_dpa_flow_action {
uint32_t goto_tbl;
diff --git a/hw/net/rocker/rocker_of_dpa.h b/hw/net/rocker/rocker_of_dpa.h
index 01c7a97d0..f3f6d7780 100644
--- a/hw/net/rocker/rocker_of_dpa.h
+++ b/hw/net/rocker/rocker_of_dpa.h
@@ -14,9 +14,9 @@
* GNU General Public License for more details.
*/
-#ifndef ROCKER_OF_DPA_H
-#define ROCKER_OF_DPA_H
+#ifndef _ROCKER_OF_DPA_H_
+#define _ROCKER_OF_DPA_H_
World *of_dpa_world_alloc(Rocker *r);
-#endif /* ROCKER_OF_DPA_H */
+#endif /* _ROCKER_OF_DPA_H_ */
diff --git a/hw/net/rocker/rocker_tlv.h b/hw/net/rocker/rocker_tlv.h
index dd28d0844..e3c4ab679 100644
--- a/hw/net/rocker/rocker_tlv.h
+++ b/hw/net/rocker/rocker_tlv.h
@@ -14,8 +14,8 @@
* GNU General Public License for more details.
*/
-#ifndef ROCKER_TLV_H
-#define ROCKER_TLV_H
+#ifndef _ROCKER_TLV_H_
+#define _ROCKER_TLV_H_
#define ROCKER_TLV_ALIGNTO 8U
#define ROCKER_TLV_ALIGN(len) \
@@ -106,17 +106,17 @@ static inline uint64_t rocker_tlv_get_u64(const RockerTlv *tlv)
static inline uint16_t rocker_tlv_get_le16(const RockerTlv *tlv)
{
- return lduw_le_p(rocker_tlv_data(tlv));
+ return le16_to_cpup((uint16_t *) rocker_tlv_data(tlv));
}
static inline uint32_t rocker_tlv_get_le32(const RockerTlv *tlv)
{
- return ldl_le_p(rocker_tlv_data(tlv));
+ return le32_to_cpup((uint32_t *) rocker_tlv_data(tlv));
}
static inline uint64_t rocker_tlv_get_le64(const RockerTlv *tlv)
{
- return ldq_le_p(rocker_tlv_data(tlv));
+ return le64_to_cpup((uint64_t *) rocker_tlv_data(tlv));
}
static inline void rocker_tlv_parse(RockerTlv **tb, int maxtype,
diff --git a/hw/net/rocker/rocker_world.h b/hw/net/rocker/rocker_world.h
index 44f1fe3e1..58ade4733 100644
--- a/hw/net/rocker/rocker_world.h
+++ b/hw/net/rocker/rocker_world.h
@@ -14,8 +14,8 @@
* GNU General Public License for more details.
*/
-#ifndef ROCKER_WORLD_H
-#define ROCKER_WORLD_H
+#ifndef _ROCKER_WORLD_H_
+#define _ROCKER_WORLD_H_
#include "rocker_hw.h"
@@ -58,4 +58,4 @@ const char *world_name(World *world);
World *rocker_get_world(Rocker *r, enum rocker_world_type type);
-#endif /* ROCKER_WORLD_H */
+#endif /* _ROCKER_WORLD_H_ */
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 3345bc6b5..1e5ec149f 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -1013,8 +1013,8 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK;
/* write VLAN info to descriptor variables. */
- if (s->CpCmd & CPlusRxVLAN &&
- lduw_be_p(&buf[ETH_ALEN * 2]) == ETH_P_VLAN) {
+ if (s->CpCmd & CPlusRxVLAN && be16_to_cpup((uint16_t *)
+ &buf[ETH_ALEN * 2]) == ETH_P_VLAN) {
dot1q_buf = &buf[ETH_ALEN * 2];
size -= VLAN_HLEN;
/* if too small buffer, use the tailroom added duing expansion */
@@ -1024,10 +1024,11 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
rxdw1 &= ~CP_RX_VLAN_TAG_MASK;
/* BE + ~le_to_cpu()~ + cpu_to_le() = BE */
- rxdw1 |= CP_RX_TAVA | lduw_le_p(&dot1q_buf[ETHER_TYPE_LEN]);
+ rxdw1 |= CP_RX_TAVA | le16_to_cpup((uint16_t *)
+ &dot1q_buf[ETHER_TYPE_LEN]);
DPRINTF("C+ Rx mode : extracted vlan tag with tci: ""%u\n",
- lduw_be_p(&dot1q_buf[ETHER_TYPE_LEN]));
+ be16_to_cpup((uint16_t *)&dot1q_buf[ETHER_TYPE_LEN]));
} else {
/* reset VLAN tag flag */
rxdw1 &= ~CP_RX_TAVA;
@@ -1351,6 +1352,29 @@ static void RTL8139TallyCounters_dma_write(RTL8139State *s, dma_addr_t tc_addr)
pci_dma_write(d, tc_addr + 62, (uint8_t *)&val16, 2);
}
+/* Loads values of tally counters from VM state file */
+
+static const VMStateDescription vmstate_tally_counters = {
+ .name = "tally_counters",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(TxOk, RTL8139TallyCounters),
+ VMSTATE_UINT64(RxOk, RTL8139TallyCounters),
+ VMSTATE_UINT64(TxERR, RTL8139TallyCounters),
+ VMSTATE_UINT32(RxERR, RTL8139TallyCounters),
+ VMSTATE_UINT16(MissPkt, RTL8139TallyCounters),
+ VMSTATE_UINT16(FAE, RTL8139TallyCounters),
+ VMSTATE_UINT32(Tx1Col, RTL8139TallyCounters),
+ VMSTATE_UINT32(TxMCol, RTL8139TallyCounters),
+ VMSTATE_UINT64(RxOkPhy, RTL8139TallyCounters),
+ VMSTATE_UINT64(RxOkBrd, RTL8139TallyCounters),
+ VMSTATE_UINT16(TxAbt, RTL8139TallyCounters),
+ VMSTATE_UINT16(TxUndrn, RTL8139TallyCounters),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val)
{
DeviceState *d = DEVICE(s);
@@ -1843,6 +1867,11 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
return 1;
}
+/* structures and macros for task offloading */
+#define TCP_HEADER_DATA_OFFSET(tcp) (((be16_to_cpu(tcp->th_offset_flags) >> 12)&0xf) << 2)
+#define TCP_FLAGS_ONLY(flags) ((flags)&0x3f)
+#define TCP_HEADER_FLAGS(tcp) TCP_FLAGS_ONLY(be16_to_cpu(tcp->th_offset_flags))
+
#define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off)))
/* produces ones' complement sum of data */
@@ -3198,7 +3227,7 @@ static void rtl8139_pre_save(void *opaque)
static const VMStateDescription vmstate_rtl8139 = {
.name = "rtl8139",
- .version_id = 5,
+ .version_id = 4,
.minimum_version_id = 3,
.post_load = rtl8139_post_load,
.pre_save = rtl8139_pre_save,
@@ -3269,19 +3298,8 @@ static const VMStateDescription vmstate_rtl8139 = {
VMSTATE_UINT32(TimerInt, RTL8139State),
VMSTATE_INT64(TCTR_base, RTL8139State),
- VMSTATE_UINT64(tally_counters.TxOk, RTL8139State),
- VMSTATE_UINT64(tally_counters.RxOk, RTL8139State),
- VMSTATE_UINT64(tally_counters.TxERR, RTL8139State),
- VMSTATE_UINT32(tally_counters.RxERR, RTL8139State),
- VMSTATE_UINT16(tally_counters.MissPkt, RTL8139State),
- VMSTATE_UINT16(tally_counters.FAE, RTL8139State),
- VMSTATE_UINT32(tally_counters.Tx1Col, RTL8139State),
- VMSTATE_UINT32(tally_counters.TxMCol, RTL8139State),
- VMSTATE_UINT64(tally_counters.RxOkPhy, RTL8139State),
- VMSTATE_UINT64(tally_counters.RxOkBrd, RTL8139State),
- VMSTATE_UINT32_V(tally_counters.RxOkMul, RTL8139State, 5),
- VMSTATE_UINT16(tally_counters.TxAbt, RTL8139State),
- VMSTATE_UINT16(tally_counters.TxUndrn, RTL8139State),
+ VMSTATE_STRUCT(tally_counters, RTL8139State, 0,
+ vmstate_tally_counters, RTL8139TallyCounters),
VMSTATE_UINT32_V(cplus_enabled, RTL8139State, 4),
VMSTATE_END_OF_LIST()
@@ -3393,7 +3411,7 @@ static void rtl8139_set_link_status(NetClientState *nc)
}
static NetClientInfo net_rtl8139_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = rtl8139_can_receive,
.receive = rtl8139_receive,
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
index 3b16dcf5a..21c1b8f54 100644
--- a/hw/net/smc91c111.c
+++ b/hw/net/smc91c111.c
@@ -755,7 +755,7 @@ static const MemoryRegionOps smc91c111_mem_ops = {
};
static NetClientInfo net_smc91c111_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = smc91c111_can_receive_nc,
.receive = smc91c111_receive,
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index b273eda93..a647f25d9 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -28,7 +28,6 @@
#include "qemu-common.h"
#include "cpu.h"
#include "hw/hw.h"
-#include "qemu/log.h"
#include "net/net.h"
#include "hw/qdev.h"
#include "hw/ppc/spapr.h"
@@ -107,10 +106,9 @@ typedef struct VIOsPAPRVLANDevice {
NICConf nicconf;
NICState *nic;
bool isopen;
- hwaddr buf_list;
+ target_ulong buf_list;
uint32_t add_buf_ptr, use_buf_ptr, rx_bufs;
- hwaddr rxq_ptr;
- QEMUTimer *rxp_timer;
+ target_ulong rxq_ptr;
uint32_t compat_flags; /* Compatability flags for migration */
RxBufPool *rx_pool[RX_MAX_POOLS]; /* Receive buffer descriptor pools */
} VIOsPAPRVLANDevice;
@@ -123,21 +121,6 @@ static int spapr_vlan_can_receive(NetClientState *nc)
}
/**
- * The last 8 bytes of the receive buffer list page (that has been
- * supplied by the guest with the H_REGISTER_LOGICAL_LAN call) contain
- * a counter for frames that have been dropped because there was no
- * suitable receive buffer available. This function is used to increase
- * this counter by one.
- */
-static void spapr_vlan_record_dropped_rx_frame(VIOsPAPRVLANDevice *dev)
-{
- uint64_t cnt;
-
- cnt = vio_ldq(&dev->sdev, dev->buf_list + 4096 - 8);
- vio_stq(&dev->sdev, dev->buf_list + 4096 - 8, cnt + 1);
-}
-
-/**
* Get buffer descriptor from one of our receive buffer pools
*/
static vlan_bd_t spapr_vlan_get_rx_bd_from_pool(VIOsPAPRVLANDevice *dev,
@@ -222,8 +205,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
}
if (!dev->rx_bufs) {
- spapr_vlan_record_dropped_rx_frame(dev);
- return 0;
+ return -1;
}
if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) {
@@ -232,8 +214,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
bd = spapr_vlan_get_rx_bd_from_page(dev, size);
}
if (!bd) {
- spapr_vlan_record_dropped_rx_frame(dev);
- return 0;
+ return -1;
}
dev->rx_bufs--;
@@ -278,19 +259,12 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
}
static NetClientInfo net_spapr_vlan_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = spapr_vlan_can_receive,
.receive = spapr_vlan_receive,
};
-static void spapr_vlan_flush_rx_queue(void *opaque)
-{
- VIOsPAPRVLANDevice *dev = opaque;
-
- qemu_flush_queued_packets(qemu_get_queue(dev->nic));
-}
-
static void spapr_vlan_reset_rx_pool(RxBufPool *rxp)
{
/*
@@ -327,9 +301,6 @@ static void spapr_vlan_realize(VIOsPAPRDevice *sdev, Error **errp)
dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
-
- dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue,
- dev);
}
static void spapr_vlan_instance_init(Object *obj)
@@ -360,11 +331,6 @@ static void spapr_vlan_instance_finalize(Object *obj)
dev->rx_pool[i] = NULL;
}
}
-
- if (dev->rxp_timer) {
- timer_del(dev->rxp_timer);
- timer_free(dev->rxp_timer);
- }
}
void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
@@ -662,13 +628,7 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
dev->rx_bufs++;
- /*
- * Give guest some more time to add additional RX buffers before we
- * flush the receive queue, so that e.g. fragmented IP packets can
- * be passed to the guest in one go later (instead of passing single
- * fragments if there is only one receive buffer available).
- */
- timer_mod(dev->rxp_timer, qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 500);
+ qemu_flush_queued_packets(qemu_get_queue(dev->nic));
return H_SUCCESS;
}
@@ -805,11 +765,11 @@ static const VMStateDescription vmstate_spapr_llan = {
VMSTATE_SPAPR_VIO(sdev, VIOsPAPRVLANDevice),
/* LLAN state */
VMSTATE_BOOL(isopen, VIOsPAPRVLANDevice),
- VMSTATE_UINT64(buf_list, VIOsPAPRVLANDevice),
+ VMSTATE_UINTTL(buf_list, VIOsPAPRVLANDevice),
VMSTATE_UINT32(add_buf_ptr, VIOsPAPRVLANDevice),
VMSTATE_UINT32(use_buf_ptr, VIOsPAPRVLANDevice),
VMSTATE_UINT32(rx_bufs, VIOsPAPRVLANDevice),
- VMSTATE_UINT64(rxq_ptr, VIOsPAPRVLANDevice),
+ VMSTATE_UINTTL(rxq_ptr, VIOsPAPRVLANDevice),
VMSTATE_END_OF_LIST()
},
diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
index 957730e02..688089494 100644
--- a/hw/net/stellaris_enet.c
+++ b/hw/net/stellaris_enet.c
@@ -460,7 +460,7 @@ static void stellaris_enet_reset(stellaris_enet_state *s)
}
static NetClientInfo net_stellaris_enet_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = stellaris_enet_receive,
};
diff --git a/hw/net/trace-events b/hw/net/trace-events
deleted file mode 100644
index 8d38d7724..000000000
--- a/hw/net/trace-events
+++ /dev/null
@@ -1,272 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/net/lance.c
-lance_mem_readw(uint64_t addr, uint32_t ret) "addr=%"PRIx64"val=0x%04x"
-lance_mem_writew(uint64_t addr, uint32_t val) "addr=%"PRIx64"val=0x%04x"
-
-# hw/net/milkymist-minimac2.c
-milkymist_minimac2_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_minimac2_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_minimac2_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
-milkymist_minimac2_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr %02x addr %02x value %04x"
-milkymist_minimac2_tx_frame(uint32_t length) "length %u"
-milkymist_minimac2_rx_frame(const void *buf, uint32_t length) "buf %p length %u"
-milkymist_minimac2_rx_transfer(const void *buf, uint32_t length) "buf %p length %d"
-milkymist_minimac2_raise_irq_rx(void) "Raise IRQ RX"
-milkymist_minimac2_lower_irq_rx(void) "Lower IRQ RX"
-milkymist_minimac2_pulse_irq_tx(void) "Pulse IRQ TX"
-
-# hw/net/mipsnet.c
-mipsnet_send(uint32_t size) "sending len=%u"
-mipsnet_receive(uint32_t size) "receiving len=%u"
-mipsnet_read(uint64_t addr, uint32_t val) "read addr=0x%" PRIx64 " val=0x%x"
-mipsnet_write(uint64_t addr, uint64_t val) "write addr=0x%" PRIx64 " val=0x%" PRIx64
-mipsnet_irq(uint32_t isr, uint32_t intctl) "set irq to %d (%02x)"
-
-# hw/net/opencores_eth.c
-open_eth_mii_write(unsigned idx, uint16_t v) "MII[%02x] <- %04x"
-open_eth_mii_read(unsigned idx, uint16_t v) "MII[%02x] -> %04x"
-open_eth_update_irq(uint32_t v) "IRQ <- %x"
-open_eth_receive(unsigned len) "RX: len: %u"
-open_eth_receive_mcast(unsigned idx, uint32_t h0, uint32_t h1) "MCAST: idx = %u, hash: %08x:%08x"
-open_eth_receive_reject(void) "RX: rejected"
-open_eth_receive_desc(uint32_t addr, uint32_t len_flags) "RX: %08x, len_flags: %08x"
-open_eth_start_xmit(uint32_t addr, unsigned len, unsigned tx_len) "TX: %08x, len: %u, tx_len: %u"
-open_eth_reg_read(uint32_t addr, uint32_t v) "MAC[%02x] -> %08x"
-open_eth_reg_write(uint32_t addr, uint32_t v) "MAC[%02x] <- %08x"
-open_eth_desc_read(uint32_t addr, uint32_t v) "DESC[%04x] -> %08x"
-open_eth_desc_write(uint32_t addr, uint32_t v) "DESC[%04x] <- %08x"
-
-# hw/net/pcnet.c
-pcnet_s_reset(void *s) "s=%p"
-pcnet_user_int(void *s) "s=%p"
-pcnet_isr_change(void *s, uint32_t isr, uint32_t isr_old) "s=%p INTA=%d<=%d"
-pcnet_init(void *s, uint64_t init_addr) "s=%p init_addr=%#"PRIx64
-pcnet_rlen_tlen(void *s, uint32_t rlen, uint32_t tlen) "s=%p rlen=%d tlen=%d"
-pcnet_ss32_rdra_tdra(void *s, uint32_t ss32, uint32_t rdra, uint32_t rcvrl, uint32_t tdra, uint32_t xmtrl) "s=%p ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]"
-
-# hw/net/pcnet-pci.c
-pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val) "opaque=%p addr=0x%08x val=0x%02x"
-pcnet_aprom_readb(void *opaque, uint32_t addr, uint32_t val) "opaque=%p addr=0x%08x val=0x%02x"
-pcnet_ioport_read(void *opaque, uint64_t addr, unsigned size) "opaque=%p addr=%#"PRIx64" size=%d"
-pcnet_ioport_write(void *opaque, uint64_t addr, uint64_t data, unsigned size) "opaque=%p addr=%#"PRIx64" data=%#"PRIx64" size=%d"
-pcnet_mmio_writeb(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=%#"PRIx64" val=0x%x"
-pcnet_mmio_writew(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=%#"PRIx64" val=0x%x"
-pcnet_mmio_writel(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=%#"PRIx64" val=0x%x"
-pcnet_mmio_readb(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=%#"PRIx64" val=0x%x"
-pcnet_mmio_readw(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=%#"PRIx64" val=0x%x"
-pcnet_mmio_readl(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=%#"PRIx64" val=0x%x"
-
-# hw/net/net_rx_pkt.c
-net_rx_pkt_parsed(bool ip4, bool ip6, bool udp, bool tcp, size_t l3o, size_t l4o, size_t l5o) "RX packet parsed: ip4: %d, ip6: %d, udp: %d, tcp: %d, l3 offset: %zu, l4 offset: %zu, l5 offset: %zu"
-net_rx_pkt_l4_csum_validate_entry(void) "Starting L4 checksum validation"
-net_rx_pkt_l4_csum_validate_not_xxp(void) "Not a TCP/UDP packet"
-net_rx_pkt_l4_csum_validate_udp_with_no_checksum(void) "UDP packet without checksum"
-net_rx_pkt_l4_csum_validate_ip4_fragment(void) "IP4 fragment"
-net_rx_pkt_l4_csum_validate_ip4_udp(void) "IP4/UDP packet"
-net_rx_pkt_l4_csum_validate_ip4_tcp(void) "IP4/TCP packet"
-net_rx_pkt_l4_csum_validate_ip6_udp(void) "IP6/UDP packet"
-net_rx_pkt_l4_csum_validate_ip6_tcp(void) "IP6/TCP packet"
-net_rx_pkt_l4_csum_validate_csum(bool csum_valid) "Checksum valid: %d"
-
-net_rx_pkt_l4_csum_calc_entry(void) "Starting L4 checksum calculation"
-net_rx_pkt_l4_csum_calc_ip4_udp(void) "IP4/UDP packet"
-net_rx_pkt_l4_csum_calc_ip4_tcp(void) "IP4/TCP packet"
-net_rx_pkt_l4_csum_calc_ip6_udp(void) "IP6/UDP packet"
-net_rx_pkt_l4_csum_calc_ip6_tcp(void) "IP6/TCP packet"
-net_rx_pkt_l4_csum_calc_ph_csum(uint32_t cntr, uint16_t csl) "Pseudo-header: checksum counter %u, length %u"
-net_rx_pkt_l4_csum_calc_csum(size_t l4hdr_off, uint16_t csl, uint32_t cntr, uint16_t csum) "L4 Checksum: L4 header offset: %zu, length: %u, counter: 0x%X, final checksum: 0x%X"
-
-net_rx_pkt_l4_csum_fix_entry(void) "Starting L4 checksum correction"
-net_rx_pkt_l4_csum_fix_tcp(uint32_t l4_cso) "TCP packet, L4 cso: %u"
-net_rx_pkt_l4_csum_fix_udp(uint32_t l4_cso) "UDP packet, L4 cso: %u"
-net_rx_pkt_l4_csum_fix_not_xxp(void) "Not an IP4 packet"
-net_rx_pkt_l4_csum_fix_ip4_fragment(void) "IP4 fragment"
-net_rx_pkt_l4_csum_fix_udp_with_no_checksum(void) "UDP packet without checksum"
-net_rx_pkt_l4_csum_fix_csum(uint32_t cso, uint16_t csum) "L4 Checksum: Offset: %u, value 0x%X"
-
-net_rx_pkt_l3_csum_validate_entry(void) "Starting L3 checksum validation"
-net_rx_pkt_l3_csum_validate_not_ip4(void) "Not an IP4 packet"
-net_rx_pkt_l3_csum_validate_csum(size_t l3hdr_off, uint32_t csl, uint32_t cntr, uint16_t csum, bool csum_valid) "L3 Checksum: L3 header offset: %zu, length: %u, counter: 0x%X, final checksum: 0x%X, valid: %d"
-
-net_rx_pkt_rss_ip4(void) "Calculating IPv4 RSS hash"
-net_rx_pkt_rss_ip4_tcp(void) "Calculating IPv4/TCP RSS hash"
-net_rx_pkt_rss_ip6_tcp(void) "Calculating IPv6/TCP RSS hash"
-net_rx_pkt_rss_ip6(void) "Calculating IPv6 RSS hash"
-net_rx_pkt_rss_ip6_ex(void) "Calculating IPv6/EX RSS hash"
-net_rx_pkt_rss_hash(size_t rss_length, uint32_t rss_hash) "RSS hash for %zu bytes: 0x%X"
-net_rx_pkt_rss_add_chunk(void* ptr, size_t size, size_t input_offset) "Add RSS chunk %p, %zu bytes, RSS input offset %zu bytes"
-
-# hw/net/e1000x_common.c
-e1000x_rx_can_recv_disabled(bool link_up, bool rx_enabled, bool pci_master) "link_up: %d, rx_enabled %d, pci_master %d"
-e1000x_vlan_is_vlan_pkt(bool is_vlan_pkt, uint16_t eth_proto, uint16_t vet) "Is VLAN packet: %d, ETH proto: 0x%X, VET: 0x%X"
-e1000x_rx_flt_ucast_match(uint32_t idx, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x"
-e1000x_rx_flt_ucast_mismatch(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x"
-e1000x_rx_flt_inexact_mismatch(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint32_t mo, uint32_t mta, uint32_t mta_val) "inexact mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x"
-e1000x_rx_link_down(uint32_t status_reg) "Received packet dropped because the link is down STATUS = %u"
-e1000x_rx_disabled(uint32_t rctl_reg) "Received packet dropped because receive is disabled RCTL = %u"
-e1000x_rx_oversized(size_t size) "Received packet dropped because it was oversized (%zu bytes)"
-e1000x_mac_indicate(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "Indicating MAC to guest: %02x:%02x:%02x:%02x:%02x:%02x"
-e1000x_link_negotiation_start(void) "Start link auto negotiation"
-e1000x_link_negotiation_done(void) "Auto negotiation is completed"
-
-# hw/net/e1000e_core.c
-e1000e_core_write(uint64_t index, uint32_t size, uint64_t val) "Write to register 0x%"PRIx64", %d byte(s), value: 0x%"PRIx64
-e1000e_core_read(uint64_t index, uint32_t size, uint64_t val) "Read from register 0x%"PRIx64", %d byte(s), value: 0x%"PRIx64
-e1000e_core_mdic_read(uint8_t page, uint32_t addr, uint32_t data) "MDIC READ: PHY[%u][%u] = 0x%x"
-e1000e_core_mdic_read_unhandled(uint8_t page, uint32_t addr) "MDIC READ: PHY[%u][%u] UNHANDLED"
-e1000e_core_mdic_write(uint8_t page, uint32_t addr, uint32_t data) "MDIC WRITE: PHY[%u][%u] = 0x%x"
-e1000e_core_mdic_write_unhandled(uint8_t page, uint32_t addr) "MDIC WRITE: PHY[%u][%u] UNHANDLED"
-e1000e_core_eeeprom_write(uint16_t bit_in, uint16_t bit_out, uint16_t reading) "eeprom bitnum in %d out %d, reading %d"
-e1000e_core_ctrl_write(uint64_t index, uint32_t val) "Write CTRL register 0x%"PRIx64", value: 0x%X"
-e1000e_core_ctrl_sw_reset(void) "Doing SW reset"
-e1000e_core_ctrl_phy_reset(void) "Doing PHY reset"
-
-e1000e_link_autoneg_flowctl(bool enabled) "Auto-negotiated flow control state is %d"
-e1000e_link_set_params(bool autodetect, uint32_t speed, bool force_spd, bool force_dplx, bool rx_fctl, bool tx_fctl) "Set link params: Autodetect: %d, Speed: %d, Force speed: %d, Force duplex: %d, RX flow control %d, TX flow control %d"
-e1000e_link_read_params(bool autodetect, uint32_t speed, bool force_spd, bool force_dplx, bool rx_fctl, bool tx_fctl) "Get link params: Autodetect: %d, Speed: %d, Force speed: %d, Force duplex: %d, RX flow control %d, TX flow control %d"
-e1000e_link_set_ext_params(bool asd_check, bool speed_select_bypass) "Set extended link params: ASD check: %d, Speed select bypass: %d"
-e1000e_link_status(bool link_up, bool full_dplx, uint32_t speed, uint32_t asdv) "Link up: %d, Duplex: %d, Speed: %d, ASDV: %d"
-e1000e_link_status_changed(bool status) "New link status: %d"
-
-e1000e_wrn_regs_write_ro(uint64_t index, uint32_t size, uint64_t val) "WARNING: Write to RO register 0x%"PRIx64", %d byte(s), value: 0x%"PRIx64
-e1000e_wrn_regs_write_unknown(uint64_t index, uint32_t size, uint64_t val) "WARNING: Write to unknown register 0x%"PRIx64", %d byte(s), value: 0x%"PRIx64
-e1000e_wrn_regs_read_unknown(uint64_t index, uint32_t size) "WARNING: Read from unknown register 0x%"PRIx64", %d byte(s)"
-e1000e_wrn_regs_read_trivial(uint32_t index) "WARNING: Reading register at offset: 0x%05x. It is not fully implemented."
-e1000e_wrn_regs_write_trivial(uint32_t index) "WARNING: Writing to register at offset: 0x%05x. It is not fully implemented."
-e1000e_wrn_no_ts_support(void) "WARNING: Guest requested TX timestamping which is not supported"
-e1000e_wrn_no_snap_support(void) "WARNING: Guest requested TX SNAP header update which is not supported"
-e1000e_wrn_iscsi_filtering_not_supported(void) "WARNING: Guest requested iSCSI filtering which is not supported"
-e1000e_wrn_nfsw_filtering_not_supported(void) "WARNING: Guest requested NFS write filtering which is not supported"
-e1000e_wrn_nfsr_filtering_not_supported(void) "WARNING: Guest requested NFS read filtering which is not supported"
-
-e1000e_tx_disabled(void) "TX Disabled"
-e1000e_tx_descr(void *addr, uint32_t lower, uint32_t upper) "%p : %x %x"
-
-e1000e_ring_free_space(int ridx, uint32_t rdlen, uint32_t rdh, uint32_t rdt) "ring #%d: LEN: %u, DH: %u, DT: %u"
-
-e1000e_rx_can_recv_rings_full(void) "Cannot receive: all rings are full"
-e1000e_rx_can_recv(void) "Can receive"
-e1000e_rx_has_buffers(int ridx, uint32_t free_desc, size_t total_size, uint32_t desc_buf_size) "ring #%d: free descr: %u, packet size %zu, descr buffer size %u"
-e1000e_rx_null_descriptor(void) "Null RX descriptor!!"
-e1000e_rx_flt_vlan_mismatch(uint16_t vid) "VID mismatch: 0x%X"
-e1000e_rx_flt_vlan_match(uint16_t vid) "VID match: 0x%X"
-e1000e_rx_desc_ps_read(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) "buffers: [0x%"PRIx64", 0x%"PRIx64", 0x%"PRIx64", 0x%"PRIx64"]"
-e1000e_rx_desc_ps_write(uint16_t a0, uint16_t a1, uint16_t a2, uint16_t a3) "bytes written: [%u, %u, %u, %u]"
-e1000e_rx_desc_buff_sizes(uint32_t b0, uint32_t b1, uint32_t b2, uint32_t b3) "buffer sizes: [%u, %u, %u, %u]"
-e1000e_rx_desc_len(uint8_t rx_desc_len) "RX descriptor length: %u"
-e1000e_rx_desc_buff_write(uint8_t idx, uint64_t addr, uint16_t offset, const void* source, uint32_t len) "buffer #%u, addr: 0x%"PRIx64", offset: %u, from: %p, length: %u"
-e1000e_rx_descr(int ridx, uint64_t base, uint8_t len) "Next RX descriptor: ring #%d, PA: 0x%"PRIx64", length: %u"
-e1000e_rx_set_rctl(uint32_t rctl) "RCTL = 0x%x"
-e1000e_rx_receive_iov(int iovcnt) "Received vector of %d fragments"
-e1000e_rx_packet_size(size_t full, size_t vhdr, size_t data) "Received packet of %zu bytes total, %zu virt header, %zu data"
-e1000e_rx_flt_dropped(void) "Received packet dropped by RX filter"
-e1000e_rx_written_to_guest(uint32_t causes) "Received packet written to guest (ICR causes %u)"
-e1000e_rx_not_written_to_guest(uint32_t causes) "Received packet NOT written to guest (ICR causes %u)"
-e1000e_rx_interrupt_set(uint32_t causes) "Receive interrupt set (ICR causes %u)"
-e1000e_rx_interrupt_delayed(uint32_t causes) "Receive interrupt delayed (ICR causes %u)"
-e1000e_rx_set_cso(int cso_state) "RX CSO state set to %d"
-e1000e_rx_set_rdt(int queue_idx, uint32_t val) "Setting RDT[%d] = %u"
-e1000e_rx_set_rfctl(uint32_t val) "Setting RFCTL = 0x%X"
-e1000e_rx_start_recv(void)
-
-e1000e_rx_rss_started(void) "Starting RSS processing"
-e1000e_rx_rss_disabled(void) "RSS is disabled"
-e1000e_rx_rss_type(uint32_t type) "RSS type is %u"
-e1000e_rx_rss_ip4(bool isfragment, bool istcp, uint32_t mrqc, bool tcpipv4_enabled, bool ipv4_enabled) "RSS IPv4: fragment %d, tcp %d, mrqc 0x%X, tcpipv4 enabled %d, ipv4 enabled %d"
-e1000e_rx_rss_ip6_rfctl(uint32_t rfctl) "RSS IPv6: rfctl 0x%X"
-e1000e_rx_rss_ip6(bool ex_dis, bool new_ex_dis, bool istcp, bool has_ext_headers, bool ex_dst_valid, bool ex_src_valid, uint32_t mrqc, bool tcpipv6_enabled, bool ipv6ex_enabled, bool ipv6_enabled) "RSS IPv6: ex_dis: %d, new_ex_dis: %d, tcp %d, has_ext_headers %d, ex_dst_valid %d, ex_src_valid %d, mrqc 0x%X, tcpipv6 enabled %d, ipv6ex enabled %d, ipv6 enabled %d"
-e1000e_rx_rss_dispatched_to_queue(int queue_idx) "Packet being dispatched to queue %d"
-
-e1000e_rx_metadata_protocols(bool isip4, bool isip6, bool isudp, bool istcp) "protocols: ip4: %d, ip6: %d, udp: %d, tcp: %d"
-e1000e_rx_metadata_vlan(uint16_t vlan_tag) "VLAN tag is 0x%X"
-e1000e_rx_metadata_rss(uint32_t rss, uint32_t mrq) "RSS data: rss: 0x%X, mrq: 0x%X"
-e1000e_rx_metadata_ip_id(uint16_t ip_id) "the IPv4 ID is 0x%X"
-e1000e_rx_metadata_ack(void) "the packet is TCP ACK"
-e1000e_rx_metadata_pkt_type(uint32_t pkt_type) "the packet type is %u"
-e1000e_rx_metadata_no_virthdr(void) "the packet has no virt-header"
-e1000e_rx_metadata_virthdr_no_csum_info(void) "virt-header does not contain checksum info"
-e1000e_rx_metadata_l3_cso_disabled(void) "IP4 CSO is disabled"
-e1000e_rx_metadata_l4_cso_disabled(void) "TCP/UDP CSO is disabled"
-e1000e_rx_metadata_l3_csum_validation_failed(void) "Cannot validate L3 checksum"
-e1000e_rx_metadata_l4_csum_validation_failed(void) "Cannot validate L4 checksum"
-e1000e_rx_metadata_status_flags(uint32_t status_flags) "status_flags is 0x%X"
-e1000e_rx_metadata_ipv6_sum_disabled(void) "IPv6 RX checksummimg disabled by RFCTL"
-e1000e_rx_metadata_ipv6_filtering_disabled(void) "IPv6 RX filtering disabled by RFCTL"
-
-e1000e_vlan_vet(uint16_t vet) "Setting VLAN ethernet type 0x%X"
-
-e1000e_irq_set_cause(uint32_t cause) "IRQ cause set 0x%x"
-e1000e_irq_msi_notify(uint32_t cause) "MSI notify 0x%x"
-e1000e_irq_throttling_no_pending_interrupts(void) "No pending interrupts to notify"
-e1000e_irq_msi_notify_postponed(void) "Sending MSI postponed by ITR"
-e1000e_irq_legacy_notify_postponed(void) "Raising legacy IRQ postponed by ITR"
-e1000e_irq_throttling_no_pending_vec(int idx) "No pending interrupts for vector %d"
-e1000e_irq_msix_notify_postponed_vec(int idx) "Sending MSI-X postponed by EITR[%d]"
-e1000e_irq_msix_notify(uint32_t cause) "MSI-X notify 0x%x"
-e1000e_irq_legacy_notify(bool level) "IRQ line state: %d"
-e1000e_irq_msix_notify_vec(uint32_t vector) "MSI-X notify vector 0x%x"
-e1000e_irq_postponed_by_xitr(uint32_t reg) "Interrupt postponed by [E]ITR register 0x%x"
-e1000e_irq_clear_ims(uint32_t bits, uint32_t old_ims, uint32_t new_ims) "Clearing IMS bits 0x%x: 0x%x --> 0x%x"
-e1000e_irq_set_ims(uint32_t bits, uint32_t old_ims, uint32_t new_ims) "Setting IMS bits 0x%x: 0x%x --> 0x%x"
-e1000e_irq_fix_icr_asserted(uint32_t new_val) "ICR_ASSERTED bit fixed: 0x%x"
-e1000e_irq_add_msi_other(uint32_t new_val) "ICR_OTHER bit added: 0x%x"
-e1000e_irq_pending_interrupts(uint32_t pending, uint32_t icr, uint32_t ims) "ICR PENDING: 0x%x (ICR: 0x%x, IMS: 0x%x)"
-e1000e_irq_set_cause_entry(uint32_t val, uint32_t icr) "Going to set IRQ cause 0x%x, ICR: 0x%x"
-e1000e_irq_set_cause_exit(uint32_t val, uint32_t icr) "Set IRQ cause 0x%x, ICR: 0x%x"
-e1000e_irq_icr_write(uint32_t bits, uint32_t old_icr, uint32_t new_icr) "Clearing ICR bits 0x%x: 0x%x --> 0x%x"
-e1000e_irq_write_ics(uint32_t val) "Adding ICR bits 0x%x"
-e1000e_irq_icr_process_iame(void) "Clearing IMS bits due to IAME"
-e1000e_irq_read_ics(uint32_t ics) "Current ICS: 0x%x"
-e1000e_irq_read_ims(uint32_t ims) "Current IMS: 0x%x"
-e1000e_irq_icr_read_entry(uint32_t icr) "Starting ICR read. Current ICR: 0x%x"
-e1000e_irq_icr_read_exit(uint32_t icr) "Ending ICR read. Current ICR: 0x%x"
-e1000e_irq_icr_clear_zero_ims(void) "Clearing ICR on read due to zero IMS"
-e1000e_irq_icr_clear_iame(void) "Clearing ICR on read due to IAME"
-e1000e_irq_ims_clear_eiame(uint32_t iam, uint32_t cause) "Clearing IMS due to EIAME, IAM: 0x%X, cause: 0x%X"
-e1000e_irq_icr_clear_eiac(uint32_t icr, uint32_t eiac) "Clearing ICR bits due to EIAC, ICR: 0x%X, EIAC: 0x%X"
-e1000e_irq_ims_clear_set_imc(uint32_t val) "Clearing IMS bits due to IMC write 0x%x"
-e1000e_irq_fire_delayed_interrupts(void) "Firing delayed interrupts"
-e1000e_irq_rearm_timer(uint32_t reg, int64_t delay_ns) "Mitigation timer armed for register 0x%X, delay %"PRId64" ns"
-e1000e_irq_throttling_timer(uint32_t reg) "Mitigation timer shot for register 0x%X"
-e1000e_irq_rdtr_fpd_running(void) "FPD written while RDTR was running"
-e1000e_irq_rdtr_fpd_not_running(void) "FPD written while RDTR was not running"
-e1000e_irq_tidv_fpd_running(void) "FPD written while TIDV was running"
-e1000e_irq_tidv_fpd_not_running(void) "FPD written while TIDV was not running"
-e1000e_irq_eitr_set(uint32_t eitr_num, uint32_t val) "EITR[%u] = %u"
-e1000e_irq_itr_set(uint32_t val) "ITR = %u"
-e1000e_irq_fire_all_timers(uint32_t val) "Firing all delay/throttling timers on all interrupts enable (0x%X written to IMS)"
-e1000e_irq_adding_delayed_causes(uint32_t val, uint32_t icr) "Merging delayed causes 0x%X to ICR 0x%X"
-e1000e_irq_msix_pending_clearing(uint32_t cause, uint32_t int_cfg, uint32_t vec) "Clearing MSI-X pending bit for cause 0x%x, IVAR config 0x%x, vector %u"
-
-e1000e_wrn_msix_vec_wrong(uint32_t cause, uint32_t cfg) "Invalid configuration for cause 0x%x: 0x%x"
-e1000e_wrn_msix_invalid(uint32_t cause, uint32_t cfg) "Invalid entry for cause 0x%x: 0x%x"
-
-e1000e_mac_set_permanent(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "Set permanent MAC: %02x:%02x:%02x:%02x:%02x:%02x"
-e1000e_mac_set_sw(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "Set SW MAC: %02x:%02x:%02x:%02x:%02x:%02x"
-
-# hw/net/e1000e.c
-e1000e_cb_pci_realize(void) "E1000E PCI realize entry"
-e1000e_cb_pci_uninit(void) "E1000E PCI unit entry"
-e1000e_cb_qdev_reset(void) "E1000E qdev reset entry"
-e1000e_cb_pre_save(void) "E1000E pre save entry"
-e1000e_cb_post_load(void) "E1000E post load entry"
-
-e1000e_io_write_addr(uint64_t addr) "IOADDR write 0x%"PRIx64
-e1000e_io_write_data(uint64_t addr, uint64_t val) "IODATA write 0x%"PRIx64", value: 0x%"PRIx64
-e1000e_io_read_addr(uint64_t addr) "IOADDR read 0x%"PRIx64
-e1000e_io_read_data(uint64_t addr, uint64_t val) "IODATA read 0x%"PRIx64", value: 0x%"PRIx64
-e1000e_wrn_io_write_unknown(uint64_t addr) "IO write unknown address 0x%"PRIx64
-e1000e_wrn_io_read_unknown(uint64_t addr) "IO read unknown address 0x%"PRIx64
-e1000e_wrn_io_addr_undefined(uint64_t addr) "IO undefined register 0x%"PRIx64
-e1000e_wrn_io_addr_flash(uint64_t addr) "IO flash access (0x%"PRIx64") not implemented"
-e1000e_wrn_io_addr_unknown(uint64_t addr) "IO unknown register 0x%"PRIx64
-
-e1000e_msi_init_fail(int32_t res) "Failed to initialize MSI, error %d"
-e1000e_msix_init_fail(int32_t res) "Failed to initialize MSI-X, error %d"
-e1000e_msix_use_vector_fail(uint32_t vec, int32_t res) "Failed to use MSI-X vector %d, error %d"
-
-e1000e_cfg_support_virtio(bool support) "Virtio header supported: %d"
-
-e1000e_vm_state_running(void) "VM state is running"
-e1000e_vm_state_stopped(void) "VM state is stopped"
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index f2d49ad7e..6e1032fc1 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -88,10 +88,10 @@ static const int *vhost_net_get_feature_bits(struct vhost_net *net)
const int *feature_bits = 0;
switch (net->nc->info->type) {
- case NET_CLIENT_DRIVER_TAP:
+ case NET_CLIENT_OPTIONS_KIND_TAP:
feature_bits = kernel_feature_bits;
break;
- case NET_CLIENT_DRIVER_VHOST_USER:
+ case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
feature_bits = user_feature_bits;
break;
default:
@@ -120,15 +120,10 @@ uint64_t vhost_net_get_max_queues(VHostNetState *net)
return net->dev.max_queues;
}
-uint64_t vhost_net_get_acked_features(VHostNetState *net)
-{
- return net->dev.acked_features;
-}
-
static int vhost_net_get_fd(NetClientState *backend)
{
switch (backend->info->type) {
- case NET_CLIENT_DRIVER_TAP:
+ case NET_CLIENT_OPTIONS_KIND_TAP:
return tap_get_fd(backend);
default:
fprintf(stderr, "vhost-net requires tap backend\n");
@@ -140,8 +135,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
{
int r;
bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL;
- struct vhost_net *net = g_new0(struct vhost_net, 1);
- uint64_t features = 0;
+ struct vhost_net *net = g_malloc(sizeof *net);
if (!options->net_backend) {
fprintf(stderr, "vhost-net requires net backend to be setup\n");
@@ -172,7 +166,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
}
r = vhost_dev_init(&net->dev, options->opaque,
- options->backend_type, options->busyloop_timeout);
+ options->backend_type);
if (r < 0) {
goto fail;
}
@@ -185,27 +179,14 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
fprintf(stderr, "vhost lacks feature mask %" PRIu64
" for backend\n",
(uint64_t)(~net->dev.features & net->dev.backend_features));
+ vhost_dev_cleanup(&net->dev);
goto fail;
}
}
-
/* Set sane init value. Override when guest acks. */
- if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
- features = vhost_user_get_acked_features(net->nc);
- if (~net->dev.features & features) {
- fprintf(stderr, "vhost lacks feature mask %" PRIu64
- " for backend\n",
- (uint64_t)(~net->dev.features & features));
- goto fail;
- }
- }
-
- vhost_net_ack_features(net, features);
-
+ vhost_net_ack_features(net, 0);
return net;
-
fail:
- vhost_dev_cleanup(&net->dev);
g_free(net);
return NULL;
}
@@ -238,11 +219,12 @@ static int vhost_net_start_one(struct vhost_net *net,
net->nc->info->poll(net->nc, false);
}
- if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+ if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
file.fd = net->backend;
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
- r = vhost_net_set_backend(&net->dev, &file);
+ const VhostOps *vhost_ops = net->dev.vhost_ops;
+ r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
if (r < 0) {
r = -errno;
goto fail;
@@ -252,9 +234,10 @@ static int vhost_net_start_one(struct vhost_net *net,
return 0;
fail:
file.fd = -1;
- if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+ if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
while (file.index-- > 0) {
- int r = vhost_net_set_backend(&net->dev, &file);
+ const VhostOps *vhost_ops = net->dev.vhost_ops;
+ int r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
assert(r >= 0);
}
}
@@ -273,9 +256,10 @@ static void vhost_net_stop_one(struct vhost_net *net,
{
struct vhost_vring_file file = { .fd = -1 };
- if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+ if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
- int r = vhost_net_set_backend(&net->dev, &file);
+ const VhostOps *vhost_ops = net->dev.vhost_ops;
+ int r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
assert(r >= 0);
}
}
@@ -309,8 +293,8 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
* because vhost user doesn't interrupt masking/unmasking
* properly.
*/
- if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
- dev->use_guest_notifier_mask = false;
+ if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
+ dev->use_guest_notifier_mask = false;
}
}
@@ -326,15 +310,6 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
if (r < 0) {
goto err_start;
}
-
- if (ncs[i].peer->vring_enable) {
- /* restore vring enable state */
- r = vhost_set_vring_enable(ncs[i].peer, ncs[i].peer->vring_enable);
-
- if (r < 0) {
- goto err_start;
- }
- }
}
return 0;
@@ -375,16 +350,19 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
void vhost_net_cleanup(struct vhost_net *net)
{
vhost_dev_cleanup(&net->dev);
+ g_free(net);
}
int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
{
const VhostOps *vhost_ops = net->dev.vhost_ops;
+ int r = -1;
- assert(vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
- assert(vhost_ops->vhost_migration_done);
+ if (vhost_ops->vhost_migration_done) {
+ r = vhost_ops->vhost_migration_done(&net->dev, mac_addr);
+ }
- return vhost_ops->vhost_migration_done(&net->dev, mac_addr);
+ return r;
}
bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
@@ -407,12 +385,11 @@ VHostNetState *get_vhost_net(NetClientState *nc)
}
switch (nc->info->type) {
- case NET_CLIENT_DRIVER_TAP:
+ case NET_CLIENT_OPTIONS_KIND_TAP:
vhost_net = tap_get_vhost_net(nc);
break;
- case NET_CLIENT_DRIVER_VHOST_USER:
+ case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
vhost_net = vhost_user_get_vhost_net(nc);
- assert(vhost_net);
break;
default:
break;
@@ -426,9 +403,7 @@ int vhost_set_vring_enable(NetClientState *nc, int enable)
VHostNetState *net = get_vhost_net(nc);
const VhostOps *vhost_ops = net->dev.vhost_ops;
- nc->vring_enable = enable;
-
- if (vhost_ops && vhost_ops->vhost_set_vring_enable) {
+ if (vhost_ops->vhost_set_vring_enable) {
return vhost_ops->vhost_set_vring_enable(&net->dev, enable);
}
@@ -467,16 +442,10 @@ uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
{
return features;
}
-
void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
{
}
-uint64_t vhost_net_get_acked_features(VHostNetState *net)
-{
- return 0;
-}
-
bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
{
return false;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 01f135155..8aaa10380 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -468,11 +468,11 @@ static int peer_attach(VirtIONet *n, int index)
return 0;
}
- if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
+ if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
vhost_set_vring_enable(nc->peer, 1);
}
- if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
+ if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
return 0;
}
@@ -487,11 +487,11 @@ static int peer_detach(VirtIONet *n, int index)
return 0;
}
- if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
+ if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
vhost_set_vring_enable(nc->peer, 0);
}
- if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
+ if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
return 0;
}
@@ -1051,7 +1051,7 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
ptr += n->host_hdr_len;
if (!memcmp(&ptr[12], vlan, sizeof(vlan))) {
- int vid = lduw_be_p(ptr + 14) & 0xfff;
+ int vid = be16_to_cpup((uint16_t *)(ptr + 14)) & 0xfff;
if (!(n->vlans[vid >> 5] & (1U << (vid & 0x1f))))
return 0;
}
@@ -1492,7 +1492,7 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
virtio_net_set_queues(n);
}
-static void virtio_net_save(QEMUFile *f, void *opaque, size_t size)
+static void virtio_net_save(QEMUFile *f, void *opaque)
{
VirtIONet *n = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(n);
@@ -1538,12 +1538,15 @@ static void virtio_net_save_device(VirtIODevice *vdev, QEMUFile *f)
}
}
-static int virtio_net_load(QEMUFile *f, void *opaque, size_t size)
+static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIONet *n = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(n);
- return virtio_load(vdev, f, VIRTIO_NET_VM_VERSION);
+ if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
+ return -EINVAL;
+
+ return virtio_load(vdev, f, version_id);
}
static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
@@ -1559,49 +1562,68 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
virtio_vdev_has_feature(vdev,
VIRTIO_F_VERSION_1));
- n->status = qemu_get_be16(f);
-
- n->promisc = qemu_get_byte(f);
- n->allmulti = qemu_get_byte(f);
+ if (version_id >= 3)
+ n->status = qemu_get_be16(f);
- n->mac_table.in_use = qemu_get_be32(f);
- /* MAC_TABLE_ENTRIES may be different from the saved image */
- if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {
- qemu_get_buffer(f, n->mac_table.macs,
- n->mac_table.in_use * ETH_ALEN);
- } else {
- int64_t i;
+ if (version_id >= 4) {
+ if (version_id < 8) {
+ n->promisc = qemu_get_be32(f);
+ n->allmulti = qemu_get_be32(f);
+ } else {
+ n->promisc = qemu_get_byte(f);
+ n->allmulti = qemu_get_byte(f);
+ }
+ }
- /* Overflow detected - can happen if source has a larger MAC table.
- * We simply set overflow flag so there's no need to maintain the
- * table of addresses, discard them all.
- * Note: 64 bit math to avoid integer overflow.
- */
- for (i = 0; i < (int64_t)n->mac_table.in_use * ETH_ALEN; ++i) {
- qemu_get_byte(f);
+ if (version_id >= 5) {
+ n->mac_table.in_use = qemu_get_be32(f);
+ /* MAC_TABLE_ENTRIES may be different from the saved image */
+ if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {
+ qemu_get_buffer(f, n->mac_table.macs,
+ n->mac_table.in_use * ETH_ALEN);
+ } else {
+ int64_t i;
+
+ /* Overflow detected - can happen if source has a larger MAC table.
+ * We simply set overflow flag so there's no need to maintain the
+ * table of addresses, discard them all.
+ * Note: 64 bit math to avoid integer overflow.
+ */
+ for (i = 0; i < (int64_t)n->mac_table.in_use * ETH_ALEN; ++i) {
+ qemu_get_byte(f);
+ }
+ n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1;
+ n->mac_table.in_use = 0;
}
- n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1;
- n->mac_table.in_use = 0;
}
- qemu_get_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3);
+ if (version_id >= 6)
+ qemu_get_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3);
- if (qemu_get_be32(f) && !peer_has_vnet_hdr(n)) {
- error_report("virtio-net: saved image requires vnet_hdr=on");
- return -1;
+ if (version_id >= 7) {
+ if (qemu_get_be32(f) && !peer_has_vnet_hdr(n)) {
+ error_report("virtio-net: saved image requires vnet_hdr=on");
+ return -1;
+ }
}
- n->mac_table.multi_overflow = qemu_get_byte(f);
- n->mac_table.uni_overflow = qemu_get_byte(f);
+ if (version_id >= 9) {
+ n->mac_table.multi_overflow = qemu_get_byte(f);
+ n->mac_table.uni_overflow = qemu_get_byte(f);
+ }
- n->alluni = qemu_get_byte(f);
- n->nomulti = qemu_get_byte(f);
- n->nouni = qemu_get_byte(f);
- n->nobcast = qemu_get_byte(f);
+ if (version_id >= 10) {
+ n->alluni = qemu_get_byte(f);
+ n->nomulti = qemu_get_byte(f);
+ n->nouni = qemu_get_byte(f);
+ n->nobcast = qemu_get_byte(f);
+ }
- if (qemu_get_byte(f) && !peer_has_ufo(n)) {
- error_report("virtio-net: saved image requires TUN_F_UFO support");
- return -1;
+ if (version_id >= 11) {
+ if (qemu_get_byte(f) && !peer_has_ufo(n)) {
+ error_report("virtio-net: saved image requires TUN_F_UFO support");
+ return -1;
+ }
}
if (n->max_queues > 1) {
@@ -1658,7 +1680,7 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
}
static NetClientInfo net_virtio_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = virtio_net_can_receive,
.receive = virtio_net_receive,
@@ -1787,6 +1809,8 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
nc->rxfilter_notify_enabled = 1;
n->qdev = dev;
+ register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
+ virtio_net_save, virtio_net_load, n);
}
static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
@@ -1798,6 +1822,8 @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
/* This will stop vhost backend if appropriate. */
virtio_net_set_status(vdev, 0);
+ unregister_savevm(dev, "virtio-net", n);
+
g_free(n->netclient_name);
n->netclient_name = NULL;
g_free(n->netclient_type);
@@ -1832,9 +1858,6 @@ static void virtio_net_instance_init(Object *obj)
DEVICE(n), NULL);
}
-VMSTATE_VIRTIO_DEVICE(net, VIRTIO_NET_VM_VERSION, virtio_net_load,
- virtio_net_save);
-
static Property virtio_net_properties[] = {
DEFINE_PROP_BIT("csum", VirtIONet, host_features, VIRTIO_NET_F_CSUM, true),
DEFINE_PROP_BIT("guest_csum", VirtIONet, host_features,
@@ -1889,7 +1912,6 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->props = virtio_net_properties;
- dc->vmsd = &vmstate_virtio_net;
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
vdc->realize = virtio_net_device_realize;
vdc->unrealize = virtio_net_device_unrealize;
diff --git a/hw/net/vmware_utils.h b/hw/net/vmware_utils.h
index 550060170..c0dbb2ff4 100644
--- a/hw/net/vmware_utils.h
+++ b/hw/net/vmware_utils.h
@@ -26,104 +26,97 @@
*
*/
static inline void
-vmw_shmem_read(PCIDevice *d, hwaddr addr, void *buf, int len)
+vmw_shmem_read(hwaddr addr, void *buf, int len)
{
VMW_SHPRN("SHMEM r: %" PRIx64 ", len: %d to %p", addr, len, buf);
- pci_dma_read(d, addr, buf, len);
+ cpu_physical_memory_read(addr, buf, len);
}
static inline void
-vmw_shmem_write(PCIDevice *d, hwaddr addr, void *buf, int len)
+vmw_shmem_write(hwaddr addr, void *buf, int len)
{
VMW_SHPRN("SHMEM w: %" PRIx64 ", len: %d to %p", addr, len, buf);
- pci_dma_write(d, addr, buf, len);
+ cpu_physical_memory_write(addr, buf, len);
}
static inline void
-vmw_shmem_rw(PCIDevice *d, hwaddr addr, void *buf, int len, int is_write)
+vmw_shmem_rw(hwaddr addr, void *buf, int len, int is_write)
{
VMW_SHPRN("SHMEM r/w: %" PRIx64 ", len: %d (to %p), is write: %d",
addr, len, buf, is_write);
- if (is_write)
- pci_dma_write(d, addr, buf, len);
- else
- pci_dma_read(d, addr, buf, len);
+ cpu_physical_memory_rw(addr, buf, len, is_write);
}
static inline void
-vmw_shmem_set(PCIDevice *d, hwaddr addr, uint8_t val, int len)
+vmw_shmem_set(hwaddr addr, uint8_t val, int len)
{
int i;
VMW_SHPRN("SHMEM set: %" PRIx64 ", len: %d (value 0x%X)", addr, len, val);
for (i = 0; i < len; i++) {
- pci_dma_write(d, addr + i, &val, 1);
+ cpu_physical_memory_write(addr + i, &val, 1);
}
}
static inline uint32_t
-vmw_shmem_ld8(PCIDevice *d, hwaddr addr)
+vmw_shmem_ld8(hwaddr addr)
{
- uint8_t res;
- pci_dma_read(d, addr, &res, 1);
+ uint8_t res = ldub_phys(&address_space_memory, addr);
VMW_SHPRN("SHMEM load8: %" PRIx64 " (value 0x%X)", addr, res);
return res;
}
static inline void
-vmw_shmem_st8(PCIDevice *d, hwaddr addr, uint8_t value)
+vmw_shmem_st8(hwaddr addr, uint8_t value)
{
VMW_SHPRN("SHMEM store8: %" PRIx64 " (value 0x%X)", addr, value);
- pci_dma_write(d, addr, &value, 1);
+ stb_phys(&address_space_memory, addr, value);
}
static inline uint32_t
-vmw_shmem_ld16(PCIDevice *d, hwaddr addr)
+vmw_shmem_ld16(hwaddr addr)
{
- uint16_t res;
- pci_dma_read(d, addr, &res, 2);
+ uint16_t res = lduw_le_phys(&address_space_memory, addr);
VMW_SHPRN("SHMEM load16: %" PRIx64 " (value 0x%X)", addr, res);
return res;
}
static inline void
-vmw_shmem_st16(PCIDevice *d, hwaddr addr, uint16_t value)
+vmw_shmem_st16(hwaddr addr, uint16_t value)
{
VMW_SHPRN("SHMEM store16: %" PRIx64 " (value 0x%X)", addr, value);
- pci_dma_write(d, addr, &value, 2);
+ stw_le_phys(&address_space_memory, addr, value);
}
static inline uint32_t
-vmw_shmem_ld32(PCIDevice *d, hwaddr addr)
+vmw_shmem_ld32(hwaddr addr)
{
- uint32_t res;
- pci_dma_read(d, addr, &res, 4);
+ uint32_t res = ldl_le_phys(&address_space_memory, addr);
VMW_SHPRN("SHMEM load32: %" PRIx64 " (value 0x%X)", addr, res);
return res;
}
static inline void
-vmw_shmem_st32(PCIDevice *d, hwaddr addr, uint32_t value)
+vmw_shmem_st32(hwaddr addr, uint32_t value)
{
VMW_SHPRN("SHMEM store32: %" PRIx64 " (value 0x%X)", addr, value);
- pci_dma_write(d, addr, &value, 4);
+ stl_le_phys(&address_space_memory, addr, value);
}
static inline uint64_t
-vmw_shmem_ld64(PCIDevice *d, hwaddr addr)
+vmw_shmem_ld64(hwaddr addr)
{
- uint64_t res;
- pci_dma_read(d, addr, &res, 8);
+ uint64_t res = ldq_le_phys(&address_space_memory, addr);
VMW_SHPRN("SHMEM load64: %" PRIx64 " (value %" PRIx64 ")", addr, res);
return res;
}
static inline void
-vmw_shmem_st64(PCIDevice *d, hwaddr addr, uint64_t value)
+vmw_shmem_st64(hwaddr addr, uint64_t value)
{
VMW_SHPRN("SHMEM store64: %" PRIx64 " (value %" PRIx64 ")", addr, value);
- pci_dma_write(d, addr, &value, 8);
+ stq_le_phys(&address_space_memory, addr, value);
}
/* Macros for simplification of operations on array-style registers */
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 90f694366..20f26b7d8 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -30,8 +30,8 @@
#include "vmxnet3.h"
#include "vmxnet_debug.h"
#include "vmware_utils.h"
-#include "net_tx_pkt.h"
-#include "net_rx_pkt.h"
+#include "vmxnet_tx_pkt.h"
+#include "vmxnet_rx_pkt.h"
#define PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION 0x1
#define VMXNET3_MSIX_BAR_SIZE 0x2000
@@ -74,54 +74,54 @@
#define VMXNET3_MAX_NMSIX_INTRS (1)
/* Macros for rings descriptors access */
-#define VMXNET3_READ_TX_QUEUE_DESCR8(_d, dpa, field) \
- (vmw_shmem_ld8(_d, dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
+#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
+ (vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
-#define VMXNET3_WRITE_TX_QUEUE_DESCR8(_d, dpa, field, value) \
- (vmw_shmem_st8(_d, dpa + offsetof(struct Vmxnet3_TxQueueDesc, field, value)))
+#define VMXNET3_WRITE_TX_QUEUE_DESCR8(dpa, field, value) \
+ (vmw_shmem_st8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field, value)))
-#define VMXNET3_READ_TX_QUEUE_DESCR32(_d, dpa, field) \
- (vmw_shmem_ld32(_d, dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
+#define VMXNET3_READ_TX_QUEUE_DESCR32(dpa, field) \
+ (vmw_shmem_ld32(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
-#define VMXNET3_WRITE_TX_QUEUE_DESCR32(_d, dpa, field, value) \
- (vmw_shmem_st32(_d, dpa + offsetof(struct Vmxnet3_TxQueueDesc, field), value))
+#define VMXNET3_WRITE_TX_QUEUE_DESCR32(dpa, field, value) \
+ (vmw_shmem_st32(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field), value))
-#define VMXNET3_READ_TX_QUEUE_DESCR64(_d, dpa, field) \
- (vmw_shmem_ld64(_d, dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
+#define VMXNET3_READ_TX_QUEUE_DESCR64(dpa, field) \
+ (vmw_shmem_ld64(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
-#define VMXNET3_WRITE_TX_QUEUE_DESCR64(_d, dpa, field, value) \
- (vmw_shmem_st64(_d, dpa + offsetof(struct Vmxnet3_TxQueueDesc, field), value))
+#define VMXNET3_WRITE_TX_QUEUE_DESCR64(dpa, field, value) \
+ (vmw_shmem_st64(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field), value))
-#define VMXNET3_READ_RX_QUEUE_DESCR64(_d, dpa, field) \
- (vmw_shmem_ld64(_d, dpa + offsetof(struct Vmxnet3_RxQueueDesc, field)))
+#define VMXNET3_READ_RX_QUEUE_DESCR64(dpa, field) \
+ (vmw_shmem_ld64(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field)))
-#define VMXNET3_READ_RX_QUEUE_DESCR32(_d, dpa, field) \
- (vmw_shmem_ld32(_d, dpa + offsetof(struct Vmxnet3_RxQueueDesc, field)))
+#define VMXNET3_READ_RX_QUEUE_DESCR32(dpa, field) \
+ (vmw_shmem_ld32(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field)))
-#define VMXNET3_WRITE_RX_QUEUE_DESCR64(_d, dpa, field, value) \
- (vmw_shmem_st64(_d, dpa + offsetof(struct Vmxnet3_RxQueueDesc, field), value))
+#define VMXNET3_WRITE_RX_QUEUE_DESCR64(dpa, field, value) \
+ (vmw_shmem_st64(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field), value))
-#define VMXNET3_WRITE_RX_QUEUE_DESCR8(_d, dpa, field, value) \
- (vmw_shmem_st8(_d, dpa + offsetof(struct Vmxnet3_RxQueueDesc, field), value))
+#define VMXNET3_WRITE_RX_QUEUE_DESCR8(dpa, field, value) \
+ (vmw_shmem_st8(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field), value))
/* Macros for guest driver shared area access */
-#define VMXNET3_READ_DRV_SHARED64(_d, shpa, field) \
- (vmw_shmem_ld64(_d, shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+#define VMXNET3_READ_DRV_SHARED64(shpa, field) \
+ (vmw_shmem_ld64(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
-#define VMXNET3_READ_DRV_SHARED32(_d, shpa, field) \
- (vmw_shmem_ld32(_d, shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+#define VMXNET3_READ_DRV_SHARED32(shpa, field) \
+ (vmw_shmem_ld32(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
-#define VMXNET3_WRITE_DRV_SHARED32(_d, shpa, field, val) \
- (vmw_shmem_st32(_d, shpa + offsetof(struct Vmxnet3_DriverShared, field), val))
+#define VMXNET3_WRITE_DRV_SHARED32(shpa, field, val) \
+ (vmw_shmem_st32(shpa + offsetof(struct Vmxnet3_DriverShared, field), val))
-#define VMXNET3_READ_DRV_SHARED16(_d, shpa, field) \
- (vmw_shmem_ld16(_d, shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+#define VMXNET3_READ_DRV_SHARED16(shpa, field) \
+ (vmw_shmem_ld16(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
-#define VMXNET3_READ_DRV_SHARED8(_d, shpa, field) \
- (vmw_shmem_ld8(_d, shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+#define VMXNET3_READ_DRV_SHARED8(shpa, field) \
+ (vmw_shmem_ld8(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
-#define VMXNET3_READ_DRV_SHARED(_d, shpa, field, b, l) \
- (vmw_shmem_read(_d, shpa + offsetof(struct Vmxnet3_DriverShared, field), b, l))
+#define VMXNET3_READ_DRV_SHARED(shpa, field, b, l) \
+ (vmw_shmem_read(shpa + offsetof(struct Vmxnet3_DriverShared, field), b, l))
#define VMXNET_FLAG_IS_SET(field, flag) (((field) & (flag)) == (flag))
@@ -147,8 +147,7 @@ typedef struct {
uint8_t gen;
} Vmxnet3Ring;
-static inline void vmxnet3_ring_init(PCIDevice *d,
- Vmxnet3Ring *ring,
+static inline void vmxnet3_ring_init(Vmxnet3Ring *ring,
hwaddr pa,
size_t size,
size_t cell_size,
@@ -161,7 +160,7 @@ static inline void vmxnet3_ring_init(PCIDevice *d,
ring->next = 0;
if (zero_region) {
- vmw_shmem_set(d, pa, 0, size * cell_size);
+ vmw_shmem_set(pa, 0, size * cell_size);
}
}
@@ -191,16 +190,14 @@ static inline hwaddr vmxnet3_ring_curr_cell_pa(Vmxnet3Ring *ring)
return ring->pa + ring->next * ring->cell_size;
}
-static inline void vmxnet3_ring_read_curr_cell(PCIDevice *d, Vmxnet3Ring *ring,
- void *buff)
+static inline void vmxnet3_ring_read_curr_cell(Vmxnet3Ring *ring, void *buff)
{
- vmw_shmem_read(d, vmxnet3_ring_curr_cell_pa(ring), buff, ring->cell_size);
+ vmw_shmem_read(vmxnet3_ring_curr_cell_pa(ring), buff, ring->cell_size);
}
-static inline void vmxnet3_ring_write_curr_cell(PCIDevice *d, Vmxnet3Ring *ring,
- void *buff)
+static inline void vmxnet3_ring_write_curr_cell(Vmxnet3Ring *ring, void *buff)
{
- vmw_shmem_write(d, vmxnet3_ring_curr_cell_pa(ring), buff, ring->cell_size);
+ vmw_shmem_write(vmxnet3_ring_curr_cell_pa(ring), buff, ring->cell_size);
}
static inline size_t vmxnet3_ring_curr_cell_idx(Vmxnet3Ring *ring)
@@ -283,6 +280,8 @@ typedef struct {
/* Whether MSI-X support was installed successfully */
bool msix_used;
+ /* Whether MSI support was installed successfully */
+ bool msi_used;
hwaddr drv_shmem;
hwaddr temp_shared_guest_driver_memory;
@@ -315,13 +314,13 @@ typedef struct {
bool peer_has_vhdr;
/* TX packets to QEMU interface */
- struct NetTxPkt *tx_pkt;
+ struct VmxnetTxPkt *tx_pkt;
uint32_t offload_mode;
uint32_t cso_or_gso_size;
uint16_t tci;
bool needs_vlan;
- struct NetRxPkt *rx_pkt;
+ struct VmxnetRxPkt *rx_pkt;
bool tx_sop;
bool skip_current_tx_pkt;
@@ -349,7 +348,7 @@ typedef struct {
/* Interrupt management */
/*
- * This function returns sign whether interrupt line is in asserted state
+ *This function returns sign whether interrupt line is in asserted state
* This depends on the type of interrupt used. For INTX interrupt line will
* be asserted until explicit deassertion, for MSI(X) interrupt line will
* be deasserted automatically due to notification semantics of the MSI(X)
@@ -364,7 +363,7 @@ static bool _vmxnet3_assert_interrupt_line(VMXNET3State *s, uint32_t int_idx)
msix_notify(d, int_idx);
return false;
}
- if (msi_enabled(d)) {
+ if (s->msi_used && msi_enabled(d)) {
VMW_IRPRN("Sending MSI notification for vector %u", int_idx);
msi_notify(d, int_idx);
return false;
@@ -388,7 +387,7 @@ static void _vmxnet3_deassert_interrupt_line(VMXNET3State *s, int lidx)
* This function should never be called for MSI(X) interrupts
* because deassertion never required for message interrupts
*/
- assert(!msi_enabled(d));
+ assert(!s->msi_used || !msi_enabled(d));
VMW_IRPRN("Deasserting line for interrupt %u", lidx);
pci_irq_deassert(d);
@@ -425,7 +424,7 @@ static void vmxnet3_trigger_interrupt(VMXNET3State *s, int lidx)
goto do_automask;
}
- if (msi_enabled(d) && s->auto_int_masking) {
+ if (s->msi_used && msi_enabled(d) && s->auto_int_masking) {
goto do_automask;
}
@@ -457,9 +456,9 @@ vmxnet3_on_interrupt_mask_changed(VMXNET3State *s, int lidx, bool is_masked)
vmxnet3_update_interrupt_line_state(s, lidx);
}
-static bool vmxnet3_verify_driver_magic(PCIDevice *d, hwaddr dshmem)
+static bool vmxnet3_verify_driver_magic(hwaddr dshmem)
{
- return (VMXNET3_READ_DRV_SHARED32(d, dshmem, magic) == VMXNET3_REV1_MAGIC);
+ return (VMXNET3_READ_DRV_SHARED32(dshmem, magic) == VMXNET3_REV1_MAGIC);
}
#define VMXNET3_GET_BYTE(x, byte_num) (((x) >> (byte_num)*8) & 0xFF)
@@ -475,7 +474,7 @@ static void vmxnet3_set_variable_mac(VMXNET3State *s, uint32_t h, uint32_t l)
s->conf.macaddr.a[4] = VMXNET3_GET_BYTE(h, 0);
s->conf.macaddr.a[5] = VMXNET3_GET_BYTE(h, 1);
- VMW_CFPRN("Variable MAC: " MAC_FMT, MAC_ARG(s->conf.macaddr.a));
+ VMW_CFPRN("Variable MAC: " VMXNET_MF, VMXNET_MA(s->conf.macaddr.a));
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
@@ -527,14 +526,13 @@ vmxnet3_dec_rx_completion_counter(VMXNET3State *s, int qidx)
static void vmxnet3_complete_packet(VMXNET3State *s, int qidx, uint32_t tx_ridx)
{
struct Vmxnet3_TxCompDesc txcq_descr;
- PCIDevice *d = PCI_DEVICE(s);
VMXNET3_RING_DUMP(VMW_RIPRN, "TXC", qidx, &s->txq_descr[qidx].comp_ring);
txcq_descr.txdIdx = tx_ridx;
txcq_descr.gen = vmxnet3_ring_curr_gen(&s->txq_descr[qidx].comp_ring);
- vmxnet3_ring_write_curr_cell(d, &s->txq_descr[qidx].comp_ring, &txcq_descr);
+ vmxnet3_ring_write_curr_cell(&s->txq_descr[qidx].comp_ring, &txcq_descr);
/* Flush changes in TX descriptor before changing the counter value */
smp_wmb();
@@ -548,18 +546,18 @@ vmxnet3_setup_tx_offloads(VMXNET3State *s)
{
switch (s->offload_mode) {
case VMXNET3_OM_NONE:
- net_tx_pkt_build_vheader(s->tx_pkt, false, false, 0);
+ vmxnet_tx_pkt_build_vheader(s->tx_pkt, false, false, 0);
break;
case VMXNET3_OM_CSUM:
- net_tx_pkt_build_vheader(s->tx_pkt, false, true, 0);
+ vmxnet_tx_pkt_build_vheader(s->tx_pkt, false, true, 0);
VMW_PKPRN("L4 CSO requested\n");
break;
case VMXNET3_OM_TSO:
- net_tx_pkt_build_vheader(s->tx_pkt, true, true,
+ vmxnet_tx_pkt_build_vheader(s->tx_pkt, true, true,
s->cso_or_gso_size);
- net_tx_pkt_update_ip_checksums(s->tx_pkt);
+ vmxnet_tx_pkt_update_ip_checksums(s->tx_pkt);
VMW_PKPRN("GSO offload requested.");
break;
@@ -592,12 +590,12 @@ static void
vmxnet3_on_tx_done_update_stats(VMXNET3State *s, int qidx,
Vmxnet3PktStatus status)
{
- size_t tot_len = net_tx_pkt_get_total_len(s->tx_pkt);
+ size_t tot_len = vmxnet_tx_pkt_get_total_len(s->tx_pkt);
struct UPT1_TxStats *stats = &s->txq_descr[qidx].txq_stats;
switch (status) {
case VMXNET3_PKT_STATUS_OK:
- switch (net_tx_pkt_get_packet_type(s->tx_pkt)) {
+ switch (vmxnet_tx_pkt_get_packet_type(s->tx_pkt)) {
case ETH_PKT_BCAST:
stats->bcastPktsTxOK++;
stats->bcastBytesTxOK += tot_len;
@@ -645,7 +643,7 @@ vmxnet3_on_rx_done_update_stats(VMXNET3State *s,
Vmxnet3PktStatus status)
{
struct UPT1_RxStats *stats = &s->rxq_descr[qidx].rxq_stats;
- size_t tot_len = net_rx_pkt_get_total_len(s->rx_pkt);
+ size_t tot_len = vmxnet_rx_pkt_get_total_len(s->rx_pkt);
switch (status) {
case VMXNET3_PKT_STATUS_OUT_OF_BUF:
@@ -656,7 +654,7 @@ vmxnet3_on_rx_done_update_stats(VMXNET3State *s,
stats->pktsRxError++;
break;
case VMXNET3_PKT_STATUS_OK:
- switch (net_rx_pkt_get_packet_type(s->rx_pkt)) {
+ switch (vmxnet_rx_pkt_get_packet_type(s->rx_pkt)) {
case ETH_PKT_BCAST:
stats->bcastPktsRxOK++;
stats->bcastBytesRxOK += tot_len;
@@ -690,14 +688,13 @@ vmxnet3_pop_next_tx_descr(VMXNET3State *s,
uint32_t *descr_idx)
{
Vmxnet3Ring *ring = &s->txq_descr[qidx].tx_ring;
- PCIDevice *d = PCI_DEVICE(s);
- vmxnet3_ring_read_curr_cell(d, ring, txd);
+ vmxnet3_ring_read_curr_cell(ring, txd);
if (txd->gen == vmxnet3_ring_curr_gen(ring)) {
/* Only read after generation field verification */
smp_rmb();
/* Re-read to be sure we got the latest version */
- vmxnet3_ring_read_curr_cell(d, ring, txd);
+ vmxnet3_ring_read_curr_cell(ring, txd);
VMXNET3_RING_DUMP(VMW_RIPRN, "TX", qidx, ring);
*descr_idx = vmxnet3_ring_curr_cell_idx(ring);
vmxnet3_inc_tx_consumption_counter(s, qidx);
@@ -718,10 +715,10 @@ vmxnet3_send_packet(VMXNET3State *s, uint32_t qidx)
}
/* debug prints */
- vmxnet3_dump_virt_hdr(net_tx_pkt_get_vhdr(s->tx_pkt));
- net_tx_pkt_dump(s->tx_pkt);
+ vmxnet3_dump_virt_hdr(vmxnet_tx_pkt_get_vhdr(s->tx_pkt));
+ vmxnet_tx_pkt_dump(s->tx_pkt);
- if (!net_tx_pkt_send(s->tx_pkt, qemu_get_queue(s->nic))) {
+ if (!vmxnet_tx_pkt_send(s->tx_pkt, qemu_get_queue(s->nic))) {
status = VMXNET3_PKT_STATUS_DISCARD;
goto func_exit;
}
@@ -749,7 +746,7 @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)
data_len = (txd.len > 0) ? txd.len : VMXNET3_MAX_TX_BUF_SIZE;
data_pa = le64_to_cpu(txd.addr);
- if (!net_tx_pkt_add_raw_fragment(s->tx_pkt,
+ if (!vmxnet_tx_pkt_add_raw_fragment(s->tx_pkt,
data_pa,
data_len)) {
s->skip_current_tx_pkt = true;
@@ -762,9 +759,9 @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)
}
if (txd.eop) {
- if (!s->skip_current_tx_pkt && net_tx_pkt_parse(s->tx_pkt)) {
+ if (!s->skip_current_tx_pkt && vmxnet_tx_pkt_parse(s->tx_pkt)) {
if (s->needs_vlan) {
- net_tx_pkt_setup_vlan_header(s->tx_pkt, s->tci);
+ vmxnet_tx_pkt_setup_vlan_header(s->tx_pkt, s->tci);
}
vmxnet3_send_packet(s, qidx);
@@ -776,7 +773,7 @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)
vmxnet3_complete_packet(s, qidx, txd_idx);
s->tx_sop = true;
s->skip_current_tx_pkt = false;
- net_tx_pkt_reset(s->tx_pkt);
+ vmxnet_tx_pkt_reset(s->tx_pkt);
}
}
}
@@ -785,11 +782,9 @@ static inline void
vmxnet3_read_next_rx_descr(VMXNET3State *s, int qidx, int ridx,
struct Vmxnet3_RxDesc *dbuf, uint32_t *didx)
{
- PCIDevice *d = PCI_DEVICE(s);
-
Vmxnet3Ring *ring = &s->rxq_descr[qidx].rx_ring[ridx];
*didx = vmxnet3_ring_curr_cell_idx(ring);
- vmxnet3_ring_read_curr_cell(d, ring, dbuf);
+ vmxnet3_ring_read_curr_cell(ring, dbuf);
}
static inline uint8_t
@@ -807,8 +802,7 @@ vmxnet3_pop_rxc_descr(VMXNET3State *s, int qidx, uint32_t *descr_gen)
hwaddr daddr =
vmxnet3_ring_curr_cell_pa(&s->rxq_descr[qidx].comp_ring);
- pci_dma_read(PCI_DEVICE(s),
- daddr, &rxcd, sizeof(struct Vmxnet3_RxCompDesc));
+ cpu_physical_memory_read(daddr, &rxcd, sizeof(struct Vmxnet3_RxCompDesc));
ring_gen = vmxnet3_ring_curr_gen(&s->rxq_descr[qidx].comp_ring);
if (rxcd.gen != ring_gen) {
@@ -934,7 +928,7 @@ vmxnet3_get_next_rx_descr(VMXNET3State *s, bool is_head,
* in the case the host OS performs forwarding, it will forward an
* incorrectly checksummed packet.
*/
-static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
+static void vmxnet3_rx_need_csum_calculate(struct VmxnetRxPkt *pkt,
const void *pkt_data,
size_t pkt_len)
{
@@ -943,16 +937,16 @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
uint8_t *data;
int len;
- if (!net_rx_pkt_has_virt_hdr(pkt)) {
+ if (!vmxnet_rx_pkt_has_virt_hdr(pkt)) {
return;
}
- vhdr = net_rx_pkt_get_vhdr(pkt);
+ vhdr = vmxnet_rx_pkt_get_vhdr(pkt);
if (!VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM)) {
return;
}
- net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
+ vmxnet_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
if (!(isip4 || isip6) || !(istcp || isudp)) {
return;
}
@@ -976,7 +970,7 @@ static void vmxnet3_rx_need_csum_calculate(struct NetRxPkt *pkt,
vhdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
}
-static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
+static void vmxnet3_rx_update_descr(struct VmxnetRxPkt *pkt,
struct Vmxnet3_RxCompDesc *rxcd)
{
int csum_ok, is_gso;
@@ -984,16 +978,16 @@ static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
struct virtio_net_hdr *vhdr;
uint8_t offload_type;
- if (net_rx_pkt_is_vlan_stripped(pkt)) {
+ if (vmxnet_rx_pkt_is_vlan_stripped(pkt)) {
rxcd->ts = 1;
- rxcd->tci = net_rx_pkt_get_vlan_tag(pkt);
+ rxcd->tci = vmxnet_rx_pkt_get_vlan_tag(pkt);
}
- if (!net_rx_pkt_has_virt_hdr(pkt)) {
+ if (!vmxnet_rx_pkt_has_virt_hdr(pkt)) {
goto nocsum;
}
- vhdr = net_rx_pkt_get_vhdr(pkt);
+ vhdr = vmxnet_rx_pkt_get_vhdr(pkt);
/*
* Checksum is valid when lower level tell so or when lower level
* requires checksum offload telling that packet produced/bridged
@@ -1010,7 +1004,7 @@ static void vmxnet3_rx_update_descr(struct NetRxPkt *pkt,
goto nocsum;
}
- net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
+ vmxnet_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
if ((!istcp && !isudp) || (!isip4 && !isip6)) {
goto nocsum;
}
@@ -1029,11 +1023,10 @@ nocsum:
}
static void
-vmxnet3_pci_dma_writev(PCIDevice *pci_dev,
- const struct iovec *iov,
- size_t start_iov_off,
- hwaddr target_addr,
- size_t bytes_to_copy)
+vmxnet3_physical_memory_writev(const struct iovec *iov,
+ size_t start_iov_off,
+ hwaddr target_addr,
+ size_t bytes_to_copy)
{
size_t curr_off = 0;
size_t copied = 0;
@@ -1043,9 +1036,9 @@ vmxnet3_pci_dma_writev(PCIDevice *pci_dev,
size_t chunk_len =
MIN((curr_off + iov->iov_len) - start_iov_off, bytes_to_copy);
- pci_dma_write(pci_dev, target_addr + copied,
- iov->iov_base + start_iov_off - curr_off,
- chunk_len);
+ cpu_physical_memory_write(target_addr + copied,
+ iov->iov_base + start_iov_off - curr_off,
+ chunk_len);
copied += chunk_len;
start_iov_off += chunk_len;
@@ -1062,7 +1055,6 @@ static bool
vmxnet3_indicate_packet(VMXNET3State *s)
{
struct Vmxnet3_RxDesc rxd;
- PCIDevice *d = PCI_DEVICE(s);
bool is_head = true;
uint32_t rxd_idx;
uint32_t rx_ridx = 0;
@@ -1071,13 +1063,13 @@ vmxnet3_indicate_packet(VMXNET3State *s)
uint32_t new_rxcd_gen = VMXNET3_INIT_GEN;
hwaddr new_rxcd_pa = 0;
hwaddr ready_rxcd_pa = 0;
- struct iovec *data = net_rx_pkt_get_iovec(s->rx_pkt);
+ struct iovec *data = vmxnet_rx_pkt_get_iovec(s->rx_pkt);
size_t bytes_copied = 0;
- size_t bytes_left = net_rx_pkt_get_total_len(s->rx_pkt);
+ size_t bytes_left = vmxnet_rx_pkt_get_total_len(s->rx_pkt);
uint16_t num_frags = 0;
size_t chunk_size;
- net_rx_pkt_dump(s->rx_pkt);
+ vmxnet_rx_pkt_dump(s->rx_pkt);
while (bytes_left > 0) {
@@ -1096,15 +1088,15 @@ vmxnet3_indicate_packet(VMXNET3State *s)
}
chunk_size = MIN(bytes_left, rxd.len);
- vmxnet3_pci_dma_writev(d, data, bytes_copied,
- le64_to_cpu(rxd.addr), chunk_size);
+ vmxnet3_physical_memory_writev(data, bytes_copied,
+ le64_to_cpu(rxd.addr), chunk_size);
bytes_copied += chunk_size;
bytes_left -= chunk_size;
vmxnet3_dump_rx_descr(&rxd);
if (ready_rxcd_pa != 0) {
- pci_dma_write(d, ready_rxcd_pa, &rxcd, sizeof(rxcd));
+ cpu_physical_memory_write(ready_rxcd_pa, &rxcd, sizeof(rxcd));
}
memset(&rxcd, 0, sizeof(struct Vmxnet3_RxCompDesc));
@@ -1135,8 +1127,7 @@ vmxnet3_indicate_packet(VMXNET3State *s)
if (ready_rxcd_pa != 0) {
rxcd.eop = 1;
rxcd.err = (bytes_left != 0);
-
- pci_dma_write(d, ready_rxcd_pa, &rxcd, sizeof(rxcd));
+ cpu_physical_memory_write(ready_rxcd_pa, &rxcd, sizeof(rxcd));
/* Flush RX descriptor changes */
smp_wmb();
@@ -1167,10 +1158,6 @@ vmxnet3_io_bar0_write(void *opaque, hwaddr addr,
{
VMXNET3State *s = opaque;
- if (!s->device_active) {
- return;
- }
-
if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_TXPROD,
VMXNET3_DEVICE_MAX_TX_QUEUES, VMXNET3_REG_ALIGN)) {
int tx_queue_idx =
@@ -1232,16 +1219,16 @@ static void vmxnet3_reset_interrupt_states(VMXNET3State *s)
static void vmxnet3_reset_mac(VMXNET3State *s)
{
memcpy(&s->conf.macaddr.a, &s->perm_mac.a, sizeof(s->perm_mac.a));
- VMW_CFPRN("MAC address set to: " MAC_FMT, MAC_ARG(s->conf.macaddr.a));
+ VMW_CFPRN("MAC address set to: " VMXNET_MF, VMXNET_MA(s->conf.macaddr.a));
}
static void vmxnet3_deactivate_device(VMXNET3State *s)
{
if (s->device_active) {
VMW_CBPRN("Deactivating vmxnet3...");
- net_tx_pkt_reset(s->tx_pkt);
- net_tx_pkt_uninit(s->tx_pkt);
- net_rx_pkt_uninit(s->rx_pkt);
+ vmxnet_tx_pkt_reset(s->tx_pkt);
+ vmxnet_tx_pkt_uninit(s->tx_pkt);
+ vmxnet_rx_pkt_uninit(s->rx_pkt);
s->device_active = false;
}
}
@@ -1259,9 +1246,7 @@ static void vmxnet3_reset(VMXNET3State *s)
static void vmxnet3_update_rx_mode(VMXNET3State *s)
{
- PCIDevice *d = PCI_DEVICE(s);
-
- s->rx_mode = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem,
+ s->rx_mode = VMXNET3_READ_DRV_SHARED32(s->drv_shmem,
devRead.rxFilterConf.rxMode);
VMW_CFPRN("RX mode: 0x%08X", s->rx_mode);
}
@@ -1269,10 +1254,9 @@ static void vmxnet3_update_rx_mode(VMXNET3State *s)
static void vmxnet3_update_vlan_filters(VMXNET3State *s)
{
int i;
- PCIDevice *d = PCI_DEVICE(s);
/* Copy configuration from shared memory */
- VMXNET3_READ_DRV_SHARED(d, s->drv_shmem,
+ VMXNET3_READ_DRV_SHARED(s->drv_shmem,
devRead.rxFilterConf.vfTable,
s->vlan_table,
sizeof(s->vlan_table));
@@ -1293,10 +1277,8 @@ static void vmxnet3_update_vlan_filters(VMXNET3State *s)
static void vmxnet3_update_mcast_filters(VMXNET3State *s)
{
- PCIDevice *d = PCI_DEVICE(s);
-
uint16_t list_bytes =
- VMXNET3_READ_DRV_SHARED16(d, s->drv_shmem,
+ VMXNET3_READ_DRV_SHARED16(s->drv_shmem,
devRead.rxFilterConf.mfTableLen);
s->mcast_list_len = list_bytes / sizeof(s->mcast_list[0]);
@@ -1313,14 +1295,13 @@ static void vmxnet3_update_mcast_filters(VMXNET3State *s)
} else {
int i;
hwaddr mcast_list_pa =
- VMXNET3_READ_DRV_SHARED64(d, s->drv_shmem,
+ VMXNET3_READ_DRV_SHARED64(s->drv_shmem,
devRead.rxFilterConf.mfTablePA);
- pci_dma_read(d, mcast_list_pa, s->mcast_list, list_bytes);
-
+ cpu_physical_memory_read(mcast_list_pa, s->mcast_list, list_bytes);
VMW_CFPRN("Current multicast list len is %d:", s->mcast_list_len);
for (i = 0; i < s->mcast_list_len; i++) {
- VMW_CFPRN("\t" MAC_FMT, MAC_ARG(s->mcast_list[i].a));
+ VMW_CFPRN("\t" VMXNET_MF, VMXNET_MA(s->mcast_list[i].a));
}
}
}
@@ -1342,32 +1323,28 @@ static uint32_t vmxnet3_get_interrupt_config(VMXNET3State *s)
static void vmxnet3_fill_stats(VMXNET3State *s)
{
int i;
- PCIDevice *d = PCI_DEVICE(s);
if (!s->device_active)
return;
for (i = 0; i < s->txq_num; i++) {
- pci_dma_write(d,
- s->txq_descr[i].tx_stats_pa,
- &s->txq_descr[i].txq_stats,
- sizeof(s->txq_descr[i].txq_stats));
+ cpu_physical_memory_write(s->txq_descr[i].tx_stats_pa,
+ &s->txq_descr[i].txq_stats,
+ sizeof(s->txq_descr[i].txq_stats));
}
for (i = 0; i < s->rxq_num; i++) {
- pci_dma_write(d,
- s->rxq_descr[i].rx_stats_pa,
- &s->rxq_descr[i].rxq_stats,
- sizeof(s->rxq_descr[i].rxq_stats));
+ cpu_physical_memory_write(s->rxq_descr[i].rx_stats_pa,
+ &s->rxq_descr[i].rxq_stats,
+ sizeof(s->rxq_descr[i].rxq_stats));
}
}
static void vmxnet3_adjust_by_guest_type(VMXNET3State *s)
{
struct Vmxnet3_GOSInfo gos;
- PCIDevice *d = PCI_DEVICE(s);
- VMXNET3_READ_DRV_SHARED(d, s->drv_shmem, devRead.misc.driverInfo.gos,
+ VMXNET3_READ_DRV_SHARED(s->drv_shmem, devRead.misc.driverInfo.gos,
&gos, sizeof(gos));
s->rx_packets_compound =
(gos.gosType == VMXNET3_GOS_TYPE_WIN) ? false : true;
@@ -1387,14 +1364,13 @@ vmxnet3_dump_conf_descr(const char *name,
static void vmxnet3_update_pm_state(VMXNET3State *s)
{
struct Vmxnet3_VariableLenConfDesc pm_descr;
- PCIDevice *d = PCI_DEVICE(s);
pm_descr.confLen =
- VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.pmConfDesc.confLen);
+ VMXNET3_READ_DRV_SHARED32(s->drv_shmem, devRead.pmConfDesc.confLen);
pm_descr.confVer =
- VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.pmConfDesc.confVer);
+ VMXNET3_READ_DRV_SHARED32(s->drv_shmem, devRead.pmConfDesc.confVer);
pm_descr.confPA =
- VMXNET3_READ_DRV_SHARED64(d, s->drv_shmem, devRead.pmConfDesc.confPA);
+ VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.pmConfDesc.confPA);
vmxnet3_dump_conf_descr("PM State", &pm_descr);
}
@@ -1403,9 +1379,8 @@ static void vmxnet3_update_features(VMXNET3State *s)
{
uint32_t guest_features;
int rxcso_supported;
- PCIDevice *d = PCI_DEVICE(s);
- guest_features = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem,
+ guest_features = VMXNET3_READ_DRV_SHARED32(s->drv_shmem,
devRead.misc.uptFeatures);
rxcso_supported = VMXNET_FLAG_IS_SET(guest_features, UPT1_F_RXCSUM);
@@ -1427,8 +1402,8 @@ static void vmxnet3_update_features(VMXNET3State *s)
static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
{
- return s->msix_used || msi_enabled(PCI_DEVICE(s))
- || intx == pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1;
+ return s->msix_used || s->msi_used || (intx ==
+ (pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
}
static void vmxnet3_validate_interrupt_idx(bool is_msix, int idx)
@@ -1480,13 +1455,12 @@ static void vmxnet3_activate_device(VMXNET3State *s)
{
int i;
static const uint32_t VMXNET3_DEF_TX_THRESHOLD = 1;
- PCIDevice *d = PCI_DEVICE(s);
hwaddr qdescr_table_pa;
uint64_t pa;
uint32_t size;
/* Verify configuration consistency */
- if (!vmxnet3_verify_driver_magic(d, s->drv_shmem)) {
+ if (!vmxnet3_verify_driver_magic(s->drv_shmem)) {
VMW_ERPRN("Device configuration received from driver is invalid");
return;
}
@@ -1502,11 +1476,11 @@ static void vmxnet3_activate_device(VMXNET3State *s)
vmxnet3_update_pm_state(s);
vmxnet3_setup_rx_filtering(s);
/* Cache fields from shared memory */
- s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu);
+ s->mtu = VMXNET3_READ_DRV_SHARED32(s->drv_shmem, devRead.misc.mtu);
VMW_CFPRN("MTU is %u", s->mtu);
s->max_rx_frags =
- VMXNET3_READ_DRV_SHARED16(d, s->drv_shmem, devRead.misc.maxNumRxSG);
+ VMXNET3_READ_DRV_SHARED16(s->drv_shmem, devRead.misc.maxNumRxSG);
if (s->max_rx_frags == 0) {
s->max_rx_frags = 1;
@@ -1515,24 +1489,24 @@ static void vmxnet3_activate_device(VMXNET3State *s)
VMW_CFPRN("Max RX fragments is %u", s->max_rx_frags);
s->event_int_idx =
- VMXNET3_READ_DRV_SHARED8(d, s->drv_shmem, devRead.intrConf.eventIntrIdx);
+ VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.intrConf.eventIntrIdx);
assert(vmxnet3_verify_intx(s, s->event_int_idx));
VMW_CFPRN("Events interrupt line is %u", s->event_int_idx);
s->auto_int_masking =
- VMXNET3_READ_DRV_SHARED8(d, s->drv_shmem, devRead.intrConf.autoMask);
+ VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.intrConf.autoMask);
VMW_CFPRN("Automatic interrupt masking is %d", (int)s->auto_int_masking);
s->txq_num =
- VMXNET3_READ_DRV_SHARED8(d, s->drv_shmem, devRead.misc.numTxQueues);
+ VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numTxQueues);
s->rxq_num =
- VMXNET3_READ_DRV_SHARED8(d, s->drv_shmem, devRead.misc.numRxQueues);
+ VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
vmxnet3_validate_queues(s);
qdescr_table_pa =
- VMXNET3_READ_DRV_SHARED64(d, s->drv_shmem, devRead.misc.queueDescPA);
+ VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
VMW_CFPRN("TX queues descriptors table is at 0x%" PRIx64, qdescr_table_pa);
/*
@@ -1548,25 +1522,25 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* Read interrupt number for this TX queue */
s->txq_descr[i].intr_idx =
- VMXNET3_READ_TX_QUEUE_DESCR8(d, qdescr_pa, conf.intrIdx);
+ VMXNET3_READ_TX_QUEUE_DESCR8(qdescr_pa, conf.intrIdx);
assert(vmxnet3_verify_intx(s, s->txq_descr[i].intr_idx));
VMW_CFPRN("TX Queue %d interrupt: %d", i, s->txq_descr[i].intr_idx);
/* Read rings memory locations for TX queues */
- pa = VMXNET3_READ_TX_QUEUE_DESCR64(d, qdescr_pa, conf.txRingBasePA);
- size = VMXNET3_READ_TX_QUEUE_DESCR32(d, qdescr_pa, conf.txRingSize);
+ pa = VMXNET3_READ_TX_QUEUE_DESCR64(qdescr_pa, conf.txRingBasePA);
+ size = VMXNET3_READ_TX_QUEUE_DESCR32(qdescr_pa, conf.txRingSize);
- vmxnet3_ring_init(d, &s->txq_descr[i].tx_ring, pa, size,
+ vmxnet3_ring_init(&s->txq_descr[i].tx_ring, pa, size,
sizeof(struct Vmxnet3_TxDesc), false);
VMXNET3_RING_DUMP(VMW_CFPRN, "TX", i, &s->txq_descr[i].tx_ring);
s->max_tx_frags += size;
/* TXC ring */
- pa = VMXNET3_READ_TX_QUEUE_DESCR64(d, qdescr_pa, conf.compRingBasePA);
- size = VMXNET3_READ_TX_QUEUE_DESCR32(d, qdescr_pa, conf.compRingSize);
- vmxnet3_ring_init(d, &s->txq_descr[i].comp_ring, pa, size,
+ pa = VMXNET3_READ_TX_QUEUE_DESCR64(qdescr_pa, conf.compRingBasePA);
+ size = VMXNET3_READ_TX_QUEUE_DESCR32(qdescr_pa, conf.compRingSize);
+ vmxnet3_ring_init(&s->txq_descr[i].comp_ring, pa, size,
sizeof(struct Vmxnet3_TxCompDesc), true);
VMXNET3_RING_DUMP(VMW_CFPRN, "TXC", i, &s->txq_descr[i].comp_ring);
@@ -1577,16 +1551,15 @@ static void vmxnet3_activate_device(VMXNET3State *s)
sizeof(s->txq_descr[i].txq_stats));
/* Fill device-managed parameters for queues */
- VMXNET3_WRITE_TX_QUEUE_DESCR32(d, qdescr_pa,
+ VMXNET3_WRITE_TX_QUEUE_DESCR32(qdescr_pa,
ctrl.txThreshold,
VMXNET3_DEF_TX_THRESHOLD);
}
/* Preallocate TX packet wrapper */
VMW_CFPRN("Max TX fragments is %u", s->max_tx_frags);
- net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s),
- s->max_tx_frags, s->peer_has_vhdr);
- net_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
+ vmxnet_tx_pkt_init(&s->tx_pkt, s->max_tx_frags, s->peer_has_vhdr);
+ vmxnet_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
/* Read rings memory locations for RX queues */
for (i = 0; i < s->rxq_num; i++) {
@@ -1597,7 +1570,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* Read interrupt number for this RX queue */
s->rxq_descr[i].intr_idx =
- VMXNET3_READ_TX_QUEUE_DESCR8(d, qd_pa, conf.intrIdx);
+ VMXNET3_READ_TX_QUEUE_DESCR8(qd_pa, conf.intrIdx);
assert(vmxnet3_verify_intx(s, s->rxq_descr[i].intr_idx));
VMW_CFPRN("RX Queue %d interrupt: %d", i, s->rxq_descr[i].intr_idx);
@@ -1605,18 +1578,18 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* Read rings memory locations */
for (j = 0; j < VMXNET3_RX_RINGS_PER_QUEUE; j++) {
/* RX rings */
- pa = VMXNET3_READ_RX_QUEUE_DESCR64(d, qd_pa, conf.rxRingBasePA[j]);
- size = VMXNET3_READ_RX_QUEUE_DESCR32(d, qd_pa, conf.rxRingSize[j]);
- vmxnet3_ring_init(d, &s->rxq_descr[i].rx_ring[j], pa, size,
+ pa = VMXNET3_READ_RX_QUEUE_DESCR64(qd_pa, conf.rxRingBasePA[j]);
+ size = VMXNET3_READ_RX_QUEUE_DESCR32(qd_pa, conf.rxRingSize[j]);
+ vmxnet3_ring_init(&s->rxq_descr[i].rx_ring[j], pa, size,
sizeof(struct Vmxnet3_RxDesc), false);
VMW_CFPRN("RX queue %d:%d: Base: %" PRIx64 ", Size: %d",
i, j, pa, size);
}
/* RXC ring */
- pa = VMXNET3_READ_RX_QUEUE_DESCR64(d, qd_pa, conf.compRingBasePA);
- size = VMXNET3_READ_RX_QUEUE_DESCR32(d, qd_pa, conf.compRingSize);
- vmxnet3_ring_init(d, &s->rxq_descr[i].comp_ring, pa, size,
+ pa = VMXNET3_READ_RX_QUEUE_DESCR64(qd_pa, conf.compRingBasePA);
+ size = VMXNET3_READ_RX_QUEUE_DESCR32(qd_pa, conf.compRingSize);
+ vmxnet3_ring_init(&s->rxq_descr[i].comp_ring, pa, size,
sizeof(struct Vmxnet3_RxCompDesc), true);
VMW_CFPRN("RXC queue %d: Base: %" PRIx64 ", Size: %d", i, pa, size);
@@ -1783,21 +1756,19 @@ static uint64_t vmxnet3_get_command_status(VMXNET3State *s)
static void vmxnet3_set_events(VMXNET3State *s, uint32_t val)
{
uint32_t events;
- PCIDevice *d = PCI_DEVICE(s);
VMW_CBPRN("Setting events: 0x%x", val);
- events = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, ecr) | val;
- VMXNET3_WRITE_DRV_SHARED32(d, s->drv_shmem, ecr, events);
+ events = VMXNET3_READ_DRV_SHARED32(s->drv_shmem, ecr) | val;
+ VMXNET3_WRITE_DRV_SHARED32(s->drv_shmem, ecr, events);
}
static void vmxnet3_ack_events(VMXNET3State *s, uint32_t val)
{
- PCIDevice *d = PCI_DEVICE(s);
uint32_t events;
VMW_CBPRN("Clearing events: 0x%x", val);
- events = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, ecr) & ~val;
- VMXNET3_WRITE_DRV_SHARED32(d, s->drv_shmem, ecr, events);
+ events = VMXNET3_READ_DRV_SHARED32(s->drv_shmem, ecr) & ~val;
+ VMXNET3_WRITE_DRV_SHARED32(s->drv_shmem, ecr, events);
}
static void
@@ -1994,7 +1965,7 @@ vmxnet3_rx_filter_may_indicate(VMXNET3State *s, const void *data,
return false;
}
- switch (net_rx_pkt_get_packet_type(s->rx_pkt)) {
+ switch (vmxnet_rx_pkt_get_packet_type(s->rx_pkt)) {
case ETH_PKT_UCAST:
if (!VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_UCAST)) {
return false;
@@ -2042,7 +2013,7 @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
}
if (s->peer_has_vhdr) {
- net_rx_pkt_set_vhdr(s->rx_pkt, (struct virtio_net_hdr *)buf);
+ vmxnet_rx_pkt_set_vhdr(s->rx_pkt, (struct virtio_net_hdr *)buf);
buf += sizeof(struct virtio_net_hdr);
size -= sizeof(struct virtio_net_hdr);
}
@@ -2055,13 +2026,13 @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
size = sizeof(min_buf);
}
- net_rx_pkt_set_packet_type(s->rx_pkt,
+ vmxnet_rx_pkt_set_packet_type(s->rx_pkt,
get_eth_packet_type(PKT_GET_ETH_HDR(buf)));
if (vmxnet3_rx_filter_may_indicate(s, buf, size)) {
- net_rx_pkt_set_protocols(s->rx_pkt, buf, size);
+ vmxnet_rx_pkt_set_protocols(s->rx_pkt, buf, size);
vmxnet3_rx_need_csum_calculate(s->rx_pkt, buf, size);
- net_rx_pkt_attach_data(s->rx_pkt, buf, size, s->rx_vlan_stripping);
+ vmxnet_rx_pkt_attach_data(s->rx_pkt, buf, size, s->rx_vlan_stripping);
bytes_indicated = vmxnet3_indicate_packet(s) ? size : -1;
if (bytes_indicated < size) {
VMW_PKPRN("RX: %zu of %zu bytes indicated", bytes_indicated, size);
@@ -2091,7 +2062,7 @@ static void vmxnet3_set_link_status(NetClientState *nc)
}
static NetClientInfo net_vmxnet3_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = vmxnet3_receive,
.link_status_changed = vmxnet3_set_link_status,
@@ -2131,7 +2102,7 @@ static void vmxnet3_net_init(VMXNET3State *s)
s->link_status_and_speed = VMXNET3_LINK_SPEED | VMXNET3_LINK_STATUS_UP;
- VMW_CFPRN("Permanent MAC: " MAC_FMT, MAC_ARG(s->perm_mac.a));
+ VMW_CFPRN("Permanent MAC: " VMXNET_MF, VMXNET_MA(s->perm_mac.a));
s->nic = qemu_new_nic(&net_vmxnet3_info, &s->conf,
object_get_typename(OBJECT(s)),
@@ -2218,12 +2189,35 @@ vmxnet3_cleanup_msix(VMXNET3State *s)
}
}
+#define VMXNET3_USE_64BIT (true)
+#define VMXNET3_PER_VECTOR_MASK (false)
+
+static bool
+vmxnet3_init_msi(VMXNET3State *s)
+{
+ PCIDevice *d = PCI_DEVICE(s);
+ int res;
+
+ res = msi_init(d, VMXNET3_MSI_OFFSET(s), VMXNET3_MAX_NMSIX_INTRS,
+ VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
+ if (0 > res) {
+ VMW_WRPRN("Failed to initialize MSI, error %d", res);
+ s->msi_used = false;
+ } else {
+ s->msi_used = true;
+ }
+
+ return s->msi_used;
+}
+
static void
vmxnet3_cleanup_msi(VMXNET3State *s)
{
PCIDevice *d = PCI_DEVICE(s);
- msi_uninit(d);
+ if (s->msi_used) {
+ msi_uninit(d);
+ }
}
static void
@@ -2261,9 +2255,9 @@ static const MemoryRegionOps b1_ops = {
},
};
-static uint64_t vmxnet3_device_serial_num(VMXNET3State *s)
+static uint8_t *vmxnet3_device_serial_num(VMXNET3State *s)
{
- uint64_t dsn_payload;
+ static uint64_t dsn_payload;
uint8_t *dsnp = (uint8_t *)&dsn_payload;
dsnp[0] = 0xfe;
@@ -2274,18 +2268,13 @@ static uint64_t vmxnet3_device_serial_num(VMXNET3State *s)
dsnp[5] = s->conf.macaddr.a[1];
dsnp[6] = s->conf.macaddr.a[2];
dsnp[7] = 0xff;
- return dsn_payload;
+ return dsnp;
}
-
-#define VMXNET3_USE_64BIT (true)
-#define VMXNET3_PER_VECTOR_MASK (false)
-
static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
{
DeviceState *dev = DEVICE(pci_dev);
VMXNET3State *s = VMXNET3(pci_dev);
- int ret;
VMW_CBPRN("Starting init...");
@@ -2309,16 +2298,14 @@ static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
/* Interrupt pin A */
pci_dev->config[PCI_INTERRUPT_PIN] = 0x01;
- ret = msi_init(pci_dev, VMXNET3_MSI_OFFSET(s), VMXNET3_MAX_NMSIX_INTRS,
- VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK, NULL);
- /* Any error other than -ENOTSUP(board's MSI support is broken)
- * is a programming error. Fall back to INTx silently on -ENOTSUP */
- assert(!ret || ret == -ENOTSUP);
-
if (!vmxnet3_init_msix(s)) {
VMW_WRPRN("Failed to initialize MSI-X, configuration is inconsistent.");
}
+ if (!vmxnet3_init_msi(s)) {
+ VMW_WRPRN("Failed to initialize MSI, configuration is inconsistent.");
+ }
+
vmxnet3_net_init(s);
if (pci_is_express(pci_dev)) {
@@ -2326,8 +2313,10 @@ static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
pcie_endpoint_cap_init(pci_dev, VMXNET3_EXP_EP_OFFSET);
}
- pcie_dev_ser_num_init(pci_dev, VMXNET3_DSN_OFFSET,
- vmxnet3_device_serial_num(s));
+ pcie_add_capability(pci_dev, PCI_EXT_CAP_ID_DSN, 0x1,
+ VMXNET3_DSN_OFFSET, PCI_EXT_CAP_DSN_SIZEOF);
+ memcpy(pci_dev->config + VMXNET3_DSN_OFFSET + 4,
+ vmxnet3_device_serial_num(s), sizeof(uint64_t));
}
register_savevm(dev, "vmxnet3-msix", -1, 1,
@@ -2549,9 +2538,8 @@ static int vmxnet3_post_load(void *opaque, int version_id)
VMXNET3State *s = opaque;
PCIDevice *d = PCI_DEVICE(s);
- net_tx_pkt_init(&s->tx_pkt, PCI_DEVICE(s),
- s->max_tx_frags, s->peer_has_vhdr);
- net_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
+ vmxnet_tx_pkt_init(&s->tx_pkt, s->max_tx_frags, s->peer_has_vhdr);
+ vmxnet_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
if (s->msix_used) {
if (!vmxnet3_use_msix_vectors(s, VMXNET3_MAX_INTRS)) {
@@ -2705,7 +2693,6 @@ static void vmxnet3_class_init(ObjectClass *class, void *data)
c->vendor_id = PCI_VENDOR_ID_VMWARE;
c->device_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
c->revision = PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION;
- c->romfile = "efi-vmxnet3.rom";
c->class_id = PCI_CLASS_NETWORK_ETHERNET;
c->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
c->subsystem_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
diff --git a/hw/net/vmxnet3.h b/hw/net/vmxnet3.h
index f9352c4a2..f7006afe9 100644
--- a/hw/net/vmxnet3.h
+++ b/hw/net/vmxnet3.h
@@ -15,8 +15,8 @@
*
*/
-#ifndef QEMU_VMXNET3_H
-#define QEMU_VMXNET3_H
+#ifndef _QEMU_VMXNET3_H
+#define _QEMU_VMXNET3_H
#define VMXNET3_DEVICE_MAX_TX_QUEUES 8
#define VMXNET3_DEVICE_MAX_RX_QUEUES 8 /* Keep this value as a power of 2 */
diff --git a/hw/net/vmxnet_debug.h b/hw/net/vmxnet_debug.h
index cb50aa95d..96495dbb1 100644
--- a/hw/net/vmxnet_debug.h
+++ b/hw/net/vmxnet_debug.h
@@ -15,8 +15,8 @@
*
*/
-#ifndef QEMU_VMXNET_DEBUG_H
-#define QEMU_VMXNET_DEBUG_H
+#ifndef _QEMU_VMXNET_DEBUG_H
+#define _QEMU_VMXNET_DEBUG_H
#define VMXNET_DEVICE_NAME "vmxnet3"
@@ -142,4 +142,7 @@
} \
} while (0)
-#endif /* QEMU_VMXNET_DEBUG_H */
+#define VMXNET_MF "%02X:%02X:%02X:%02X:%02X:%02X"
+#define VMXNET_MA(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+
+#endif /* _QEMU_VMXNET3_DEBUG_H */
diff --git a/hw/net/vmxnet_rx_pkt.c b/hw/net/vmxnet_rx_pkt.c
new file mode 100644
index 000000000..21bb46e68
--- /dev/null
+++ b/hw/net/vmxnet_rx_pkt.c
@@ -0,0 +1,187 @@
+/*
+ * QEMU VMWARE VMXNET* paravirtual NICs - RX packets abstractions
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry@daynix.com>
+ * Tamir Shomer <tamirs@daynix.com>
+ * Yan Vugenfirer <yan@daynix.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.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "vmxnet_rx_pkt.h"
+#include "net/eth.h"
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "net/checksum.h"
+#include "net/tap.h"
+
+/*
+ * RX packet may contain up to 2 fragments - rebuilt eth header
+ * in case of VLAN tag stripping
+ * and payload received from QEMU - in any case
+ */
+#define VMXNET_MAX_RX_PACKET_FRAGMENTS (2)
+
+struct VmxnetRxPkt {
+ struct virtio_net_hdr virt_hdr;
+ uint8_t ehdr_buf[ETH_MAX_L2_HDR_LEN];
+ struct iovec vec[VMXNET_MAX_RX_PACKET_FRAGMENTS];
+ uint16_t vec_len;
+ uint32_t tot_len;
+ uint16_t tci;
+ bool vlan_stripped;
+ bool has_virt_hdr;
+ eth_pkt_types_e packet_type;
+
+ /* Analysis results */
+ bool isip4;
+ bool isip6;
+ bool isudp;
+ bool istcp;
+};
+
+void vmxnet_rx_pkt_init(struct VmxnetRxPkt **pkt, bool has_virt_hdr)
+{
+ struct VmxnetRxPkt *p = g_malloc0(sizeof *p);
+ p->has_virt_hdr = has_virt_hdr;
+ *pkt = p;
+}
+
+void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt)
+{
+ g_free(pkt);
+}
+
+struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt)
+{
+ assert(pkt);
+ return &pkt->virt_hdr;
+}
+
+void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data,
+ size_t len, bool strip_vlan)
+{
+ uint16_t tci = 0;
+ uint16_t ploff;
+ assert(pkt);
+ pkt->vlan_stripped = false;
+
+ if (strip_vlan) {
+ pkt->vlan_stripped = eth_strip_vlan(data, pkt->ehdr_buf, &ploff, &tci);
+ }
+
+ if (pkt->vlan_stripped) {
+ pkt->vec[0].iov_base = pkt->ehdr_buf;
+ pkt->vec[0].iov_len = ploff - sizeof(struct vlan_header);
+ pkt->vec[1].iov_base = (uint8_t *) data + ploff;
+ pkt->vec[1].iov_len = len - ploff;
+ pkt->vec_len = 2;
+ pkt->tot_len = len - ploff + sizeof(struct eth_header);
+ } else {
+ pkt->vec[0].iov_base = (void *)data;
+ pkt->vec[0].iov_len = len;
+ pkt->vec_len = 1;
+ pkt->tot_len = len;
+ }
+
+ pkt->tci = tci;
+}
+
+void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt)
+{
+#ifdef VMXNET_RX_PKT_DEBUG
+ VmxnetRxPkt *pkt = (VmxnetRxPkt *)pkt;
+ assert(pkt);
+
+ printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
+ pkt->tot_len, pkt->vlan_stripped, pkt->tci);
+#endif
+}
+
+void vmxnet_rx_pkt_set_packet_type(struct VmxnetRxPkt *pkt,
+ eth_pkt_types_e packet_type)
+{
+ assert(pkt);
+
+ pkt->packet_type = packet_type;
+
+}
+
+eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt)
+{
+ assert(pkt);
+
+ return pkt->packet_type;
+}
+
+size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt)
+{
+ assert(pkt);
+
+ return pkt->tot_len;
+}
+
+void vmxnet_rx_pkt_set_protocols(struct VmxnetRxPkt *pkt, const void *data,
+ size_t len)
+{
+ assert(pkt);
+
+ eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6,
+ &pkt->isudp, &pkt->istcp);
+}
+
+void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
+ bool *isip4, bool *isip6,
+ bool *isudp, bool *istcp)
+{
+ assert(pkt);
+
+ *isip4 = pkt->isip4;
+ *isip6 = pkt->isip6;
+ *isudp = pkt->isudp;
+ *istcp = pkt->istcp;
+}
+
+struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt)
+{
+ assert(pkt);
+
+ return pkt->vec;
+}
+
+void vmxnet_rx_pkt_set_vhdr(struct VmxnetRxPkt *pkt,
+ struct virtio_net_hdr *vhdr)
+{
+ assert(pkt);
+
+ memcpy(&pkt->virt_hdr, vhdr, sizeof pkt->virt_hdr);
+}
+
+bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt)
+{
+ assert(pkt);
+
+ return pkt->vlan_stripped;
+}
+
+bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt)
+{
+ assert(pkt);
+
+ return pkt->has_virt_hdr;
+}
+
+uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt)
+{
+ assert(pkt);
+
+ return pkt->tci;
+}
diff --git a/hw/net/vmxnet_rx_pkt.h b/hw/net/vmxnet_rx_pkt.h
new file mode 100644
index 000000000..0a45c1ba0
--- /dev/null
+++ b/hw/net/vmxnet_rx_pkt.h
@@ -0,0 +1,174 @@
+/*
+ * QEMU VMWARE VMXNET* paravirtual NICs - RX packets abstraction
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry@daynix.com>
+ * Tamir Shomer <tamirs@daynix.com>
+ * Yan Vugenfirer <yan@daynix.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 VMXNET_RX_PKT_H
+#define VMXNET_RX_PKT_H
+
+#include "net/eth.h"
+
+/* defines to enable packet dump functions */
+/*#define VMXNET_RX_PKT_DEBUG*/
+
+struct VmxnetRxPkt;
+
+/**
+ * Clean all rx packet resources
+ *
+ * @pkt: packet
+ *
+ */
+void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt);
+
+/**
+ * Init function for rx packet functionality
+ *
+ * @pkt: packet pointer
+ * @has_virt_hdr: device uses virtio header
+ *
+ */
+void vmxnet_rx_pkt_init(struct VmxnetRxPkt **pkt, bool has_virt_hdr);
+
+/**
+ * returns total length of data attached to rx context
+ *
+ * @pkt: packet
+ *
+ * Return: nothing
+ *
+ */
+size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt);
+
+/**
+ * parse and set packet analysis results
+ *
+ * @pkt: packet
+ * @data: pointer to the data buffer to be parsed
+ * @len: data length
+ *
+ */
+void vmxnet_rx_pkt_set_protocols(struct VmxnetRxPkt *pkt, const void *data,
+ size_t len);
+
+/**
+ * fetches packet analysis results
+ *
+ * @pkt: packet
+ * @isip4: whether the packet given is IPv4
+ * @isip6: whether the packet given is IPv6
+ * @isudp: whether the packet given is UDP
+ * @istcp: whether the packet given is TCP
+ *
+ */
+void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
+ bool *isip4, bool *isip6,
+ bool *isudp, bool *istcp);
+
+/**
+ * returns virtio header stored in rx context
+ *
+ * @pkt: packet
+ * @ret: virtio header
+ *
+ */
+struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt);
+
+/**
+ * returns packet type
+ *
+ * @pkt: packet
+ * @ret: packet type
+ *
+ */
+eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt);
+
+/**
+ * returns vlan tag
+ *
+ * @pkt: packet
+ * @ret: VLAN tag
+ *
+ */
+uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt);
+
+/**
+ * tells whether vlan was stripped from the packet
+ *
+ * @pkt: packet
+ * @ret: VLAN stripped sign
+ *
+ */
+bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt);
+
+/**
+ * notifies caller if the packet has virtio header
+ *
+ * @pkt: packet
+ * @ret: true if packet has virtio header, false otherwize
+ *
+ */
+bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt);
+
+/**
+ * attach data to rx packet
+ *
+ * @pkt: packet
+ * @data: pointer to the data buffer
+ * @len: data length
+ * @strip_vlan: should the module strip vlan from data
+ *
+ */
+void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data,
+ size_t len, bool strip_vlan);
+
+/**
+ * returns io vector that holds the attached data
+ *
+ * @pkt: packet
+ * @ret: pointer to IOVec
+ *
+ */
+struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt);
+
+/**
+ * prints rx packet data if debug is enabled
+ *
+ * @pkt: packet
+ *
+ */
+void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt);
+
+/**
+ * copy passed vhdr data to packet context
+ *
+ * @pkt: packet
+ * @vhdr: VHDR buffer
+ *
+ */
+void vmxnet_rx_pkt_set_vhdr(struct VmxnetRxPkt *pkt,
+ struct virtio_net_hdr *vhdr);
+
+/**
+ * save packet type in packet context
+ *
+ * @pkt: packet
+ * @packet_type: the packet type
+ *
+ */
+void vmxnet_rx_pkt_set_packet_type(struct VmxnetRxPkt *pkt,
+ eth_pkt_types_e packet_type);
+
+#endif
diff --git a/hw/net/net_tx_pkt.c b/hw/net/vmxnet_tx_pkt.c
index 20b25496e..91e1e08fd 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/vmxnet_tx_pkt.c
@@ -1,5 +1,5 @@
/*
- * QEMU TX packets abstractions
+ * QEMU VMWARE VMXNET* paravirtual NICs - TX packets abstractions
*
* Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
*
@@ -16,24 +16,24 @@
*/
#include "qemu/osdep.h"
-#include "net_tx_pkt.h"
+#include "hw/hw.h"
+#include "vmxnet_tx_pkt.h"
#include "net/eth.h"
+#include "qemu-common.h"
+#include "qemu/iov.h"
#include "net/checksum.h"
#include "net/tap.h"
#include "net/net.h"
-#include "hw/pci/pci.h"
enum {
- NET_TX_PKT_VHDR_FRAG = 0,
- NET_TX_PKT_L2HDR_FRAG,
- NET_TX_PKT_L3HDR_FRAG,
- NET_TX_PKT_PL_START_FRAG
+ VMXNET_TX_PKT_VHDR_FRAG = 0,
+ VMXNET_TX_PKT_L2HDR_FRAG,
+ VMXNET_TX_PKT_L3HDR_FRAG,
+ VMXNET_TX_PKT_PL_START_FRAG
};
/* TX packet private context */
-struct NetTxPkt {
- PCIDevice *pci_dev;
-
+struct VmxnetTxPkt {
struct virtio_net_hdr virt_hdr;
bool has_virt_hdr;
@@ -44,7 +44,6 @@ struct NetTxPkt {
struct iovec *vec;
uint8_t l2_hdr[ETH_MAX_L2_HDR_LEN];
- uint8_t l3_hdr[ETH_MAX_IP_DGRAM_LEN];
uint32_t payload_len;
@@ -54,34 +53,32 @@ struct NetTxPkt {
uint16_t hdr_len;
eth_pkt_types_e packet_type;
uint8_t l4proto;
-
- bool is_loopback;
};
-void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev,
- uint32_t max_frags, bool has_virt_hdr)
+void vmxnet_tx_pkt_init(struct VmxnetTxPkt **pkt, uint32_t max_frags,
+ bool has_virt_hdr)
{
- struct NetTxPkt *p = g_malloc0(sizeof *p);
-
- p->pci_dev = pci_dev;
+ struct VmxnetTxPkt *p = g_malloc0(sizeof *p);
- p->vec = g_new(struct iovec, max_frags + NET_TX_PKT_PL_START_FRAG);
+ p->vec = g_malloc((sizeof *p->vec) *
+ (max_frags + VMXNET_TX_PKT_PL_START_FRAG));
- p->raw = g_new(struct iovec, max_frags);
+ p->raw = g_malloc((sizeof *p->raw) * max_frags);
p->max_payload_frags = max_frags;
p->max_raw_frags = max_frags;
p->has_virt_hdr = has_virt_hdr;
- p->vec[NET_TX_PKT_VHDR_FRAG].iov_base = &p->virt_hdr;
- p->vec[NET_TX_PKT_VHDR_FRAG].iov_len =
+ p->vec[VMXNET_TX_PKT_VHDR_FRAG].iov_base = &p->virt_hdr;
+ p->vec[VMXNET_TX_PKT_VHDR_FRAG].iov_len =
p->has_virt_hdr ? sizeof p->virt_hdr : 0;
- p->vec[NET_TX_PKT_L2HDR_FRAG].iov_base = &p->l2_hdr;
- p->vec[NET_TX_PKT_L3HDR_FRAG].iov_base = &p->l3_hdr;
+ p->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_base = &p->l2_hdr;
+ p->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base = NULL;
+ p->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len = 0;
*pkt = p;
}
-void net_tx_pkt_uninit(struct NetTxPkt *pkt)
+void vmxnet_tx_pkt_uninit(struct VmxnetTxPkt *pkt)
{
if (pkt) {
g_free(pkt->vec);
@@ -90,63 +87,49 @@ void net_tx_pkt_uninit(struct NetTxPkt *pkt)
}
}
-void net_tx_pkt_update_ip_hdr_checksum(struct NetTxPkt *pkt)
+void vmxnet_tx_pkt_update_ip_checksums(struct VmxnetTxPkt *pkt)
{
uint16_t csum;
+ uint32_t ph_raw_csum;
assert(pkt);
+ uint8_t gso_type = pkt->virt_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN;
struct ip_header *ip_hdr;
- ip_hdr = pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base;
- ip_hdr->ip_len = cpu_to_be16(pkt->payload_len +
- pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len);
-
- ip_hdr->ip_sum = 0;
- csum = net_raw_checksum((uint8_t *)ip_hdr,
- pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len);
- ip_hdr->ip_sum = cpu_to_be16(csum);
-}
+ if (VIRTIO_NET_HDR_GSO_TCPV4 != gso_type &&
+ VIRTIO_NET_HDR_GSO_UDP != gso_type) {
+ return;
+ }
-void net_tx_pkt_update_ip_checksums(struct NetTxPkt *pkt)
-{
- uint16_t csum;
- uint32_t cntr, cso;
- assert(pkt);
- uint8_t gso_type = pkt->virt_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN;
- void *ip_hdr = pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base;
+ ip_hdr = pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base;
- if (pkt->payload_len + pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len >
+ if (pkt->payload_len + pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len >
ETH_MAX_IP_DGRAM_LEN) {
return;
}
- if (gso_type == VIRTIO_NET_HDR_GSO_TCPV4 ||
- gso_type == VIRTIO_NET_HDR_GSO_UDP) {
- /* Calculate IP header checksum */
- net_tx_pkt_update_ip_hdr_checksum(pkt);
-
- /* Calculate IP pseudo header checksum */
- cntr = eth_calc_ip4_pseudo_hdr_csum(ip_hdr, pkt->payload_len, &cso);
- csum = cpu_to_be16(~net_checksum_finish(cntr));
- } else if (gso_type == VIRTIO_NET_HDR_GSO_TCPV6) {
- /* Calculate IP pseudo header checksum */
- cntr = eth_calc_ip6_pseudo_hdr_csum(ip_hdr, pkt->payload_len,
- IP_PROTO_TCP, &cso);
- csum = cpu_to_be16(~net_checksum_finish(cntr));
- } else {
- return;
- }
+ ip_hdr->ip_len = cpu_to_be16(pkt->payload_len +
+ pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len);
- iov_from_buf(&pkt->vec[NET_TX_PKT_PL_START_FRAG], pkt->payload_frags,
+ /* Calculate IP header checksum */
+ ip_hdr->ip_sum = 0;
+ csum = net_raw_checksum((uint8_t *)ip_hdr,
+ pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len);
+ ip_hdr->ip_sum = cpu_to_be16(csum);
+
+ /* Calculate IP pseudo header checksum */
+ ph_raw_csum = eth_calc_pseudo_hdr_csum(ip_hdr, pkt->payload_len);
+ csum = cpu_to_be16(~net_checksum_finish(ph_raw_csum));
+ iov_from_buf(&pkt->vec[VMXNET_TX_PKT_PL_START_FRAG], pkt->payload_frags,
pkt->virt_hdr.csum_offset, &csum, sizeof(csum));
}
-static void net_tx_pkt_calculate_hdr_len(struct NetTxPkt *pkt)
+static void vmxnet_tx_pkt_calculate_hdr_len(struct VmxnetTxPkt *pkt)
{
- pkt->hdr_len = pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len +
- pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len;
+ pkt->hdr_len = pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len +
+ pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len;
}
-static bool net_tx_pkt_parse_headers(struct NetTxPkt *pkt)
+static bool vmxnet_tx_pkt_parse_headers(struct VmxnetTxPkt *pkt)
{
struct iovec *l2_hdr, *l3_hdr;
size_t bytes_read;
@@ -155,8 +138,8 @@ static bool net_tx_pkt_parse_headers(struct NetTxPkt *pkt)
assert(pkt);
- l2_hdr = &pkt->vec[NET_TX_PKT_L2HDR_FRAG];
- l3_hdr = &pkt->vec[NET_TX_PKT_L3HDR_FRAG];
+ l2_hdr = &pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG];
+ l3_hdr = &pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG];
bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags, 0, l2_hdr->iov_base,
ETH_MAX_L2_HDR_LEN);
@@ -177,19 +160,15 @@ static bool net_tx_pkt_parse_headers(struct NetTxPkt *pkt)
if (bytes_read < l2_hdr->iov_len) {
l2_hdr->iov_len = 0;
- l3_hdr->iov_len = 0;
- pkt->packet_type = ETH_PKT_UCAST;
return false;
- } else {
- l2_hdr->iov_len = ETH_MAX_L2_HDR_LEN;
- l2_hdr->iov_len = eth_get_l2_hdr_length(l2_hdr->iov_base);
- pkt->packet_type = get_eth_packet_type(l2_hdr->iov_base);
}
- l3_proto = eth_get_l3_proto(l2_hdr, 1, l2_hdr->iov_len);
+ l3_proto = eth_get_l3_proto(l2_hdr->iov_base, l2_hdr->iov_len);
switch (l3_proto) {
case ETH_P_IP:
+ l3_hdr->iov_base = g_malloc(ETH_MAX_IP4_HDR_LEN);
+
bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags, l2_hdr->iov_len,
l3_hdr->iov_base, sizeof(struct ip_header));
@@ -199,45 +178,27 @@ static bool net_tx_pkt_parse_headers(struct NetTxPkt *pkt)
}
l3_hdr->iov_len = IP_HDR_GET_LEN(l3_hdr->iov_base);
+ pkt->l4proto = ((struct ip_header *) l3_hdr->iov_base)->ip_p;
- if (l3_hdr->iov_len < sizeof(struct ip_header)) {
+ /* copy optional IPv4 header data */
+ bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags,
+ l2_hdr->iov_len + sizeof(struct ip_header),
+ l3_hdr->iov_base + sizeof(struct ip_header),
+ l3_hdr->iov_len - sizeof(struct ip_header));
+ if (bytes_read < l3_hdr->iov_len - sizeof(struct ip_header)) {
l3_hdr->iov_len = 0;
return false;
}
-
- pkt->l4proto = ((struct ip_header *) l3_hdr->iov_base)->ip_p;
-
- if (IP_HDR_GET_LEN(l3_hdr->iov_base) != sizeof(struct ip_header)) {
- /* copy optional IPv4 header data if any*/
- bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags,
- l2_hdr->iov_len + sizeof(struct ip_header),
- l3_hdr->iov_base + sizeof(struct ip_header),
- l3_hdr->iov_len - sizeof(struct ip_header));
- if (bytes_read < l3_hdr->iov_len - sizeof(struct ip_header)) {
- l3_hdr->iov_len = 0;
- return false;
- }
- }
-
break;
case ETH_P_IPV6:
- {
- eth_ip6_hdr_info hdrinfo;
-
if (!eth_parse_ipv6_hdr(pkt->raw, pkt->raw_frags, l2_hdr->iov_len,
- &hdrinfo)) {
+ &pkt->l4proto, &full_ip6hdr_len)) {
l3_hdr->iov_len = 0;
return false;
}
- pkt->l4proto = hdrinfo.l4proto;
- full_ip6hdr_len = hdrinfo.full_hdr_len;
-
- if (full_ip6hdr_len > ETH_MAX_IP_DGRAM_LEN) {
- l3_hdr->iov_len = 0;
- return false;
- }
+ l3_hdr->iov_base = g_malloc(full_ip6hdr_len);
bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags, l2_hdr->iov_len,
l3_hdr->iov_base, full_ip6hdr_len);
@@ -249,62 +210,67 @@ static bool net_tx_pkt_parse_headers(struct NetTxPkt *pkt)
l3_hdr->iov_len = full_ip6hdr_len;
}
break;
- }
+
default:
l3_hdr->iov_len = 0;
break;
}
- net_tx_pkt_calculate_hdr_len(pkt);
+ vmxnet_tx_pkt_calculate_hdr_len(pkt);
+ pkt->packet_type = get_eth_packet_type(l2_hdr->iov_base);
return true;
}
-static void net_tx_pkt_rebuild_payload(struct NetTxPkt *pkt)
+static bool vmxnet_tx_pkt_rebuild_payload(struct VmxnetTxPkt *pkt)
{
- pkt->payload_len = iov_size(pkt->raw, pkt->raw_frags) - pkt->hdr_len;
- pkt->payload_frags = iov_copy(&pkt->vec[NET_TX_PKT_PL_START_FRAG],
+ size_t payload_len = iov_size(pkt->raw, pkt->raw_frags) - pkt->hdr_len;
+
+ pkt->payload_frags = iov_copy(&pkt->vec[VMXNET_TX_PKT_PL_START_FRAG],
pkt->max_payload_frags,
pkt->raw, pkt->raw_frags,
- pkt->hdr_len, pkt->payload_len);
-}
+ pkt->hdr_len, payload_len);
-bool net_tx_pkt_parse(struct NetTxPkt *pkt)
-{
- if (net_tx_pkt_parse_headers(pkt)) {
- net_tx_pkt_rebuild_payload(pkt);
+ if (pkt->payload_frags != (uint32_t) -1) {
+ pkt->payload_len = payload_len;
return true;
} else {
return false;
}
}
-struct virtio_net_hdr *net_tx_pkt_get_vhdr(struct NetTxPkt *pkt)
+bool vmxnet_tx_pkt_parse(struct VmxnetTxPkt *pkt)
+{
+ return vmxnet_tx_pkt_parse_headers(pkt) &&
+ vmxnet_tx_pkt_rebuild_payload(pkt);
+}
+
+struct virtio_net_hdr *vmxnet_tx_pkt_get_vhdr(struct VmxnetTxPkt *pkt)
{
assert(pkt);
return &pkt->virt_hdr;
}
-static uint8_t net_tx_pkt_get_gso_type(struct NetTxPkt *pkt,
+static uint8_t vmxnet_tx_pkt_get_gso_type(struct VmxnetTxPkt *pkt,
bool tso_enable)
{
uint8_t rc = VIRTIO_NET_HDR_GSO_NONE;
uint16_t l3_proto;
- l3_proto = eth_get_l3_proto(&pkt->vec[NET_TX_PKT_L2HDR_FRAG], 1,
- pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len);
+ l3_proto = eth_get_l3_proto(pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_base,
+ pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len);
if (!tso_enable) {
goto func_exit;
}
- rc = eth_get_gso_type(l3_proto, pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base,
+ rc = eth_get_gso_type(l3_proto, pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base,
pkt->l4proto);
func_exit:
return rc;
}
-void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
+void vmxnet_tx_pkt_build_vheader(struct VmxnetTxPkt *pkt, bool tso_enable,
bool csum_enable, uint32_t gso_size)
{
struct tcp_hdr l4hdr;
@@ -313,7 +279,7 @@ void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
/* csum has to be enabled if tso is. */
assert(csum_enable || !tso_enable);
- pkt->virt_hdr.gso_type = net_tx_pkt_get_gso_type(pkt, tso_enable);
+ pkt->virt_hdr.gso_type = vmxnet_tx_pkt_get_gso_type(pkt, tso_enable);
switch (pkt->virt_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
case VIRTIO_NET_HDR_GSO_NONE:
@@ -322,16 +288,16 @@ void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
break;
case VIRTIO_NET_HDR_GSO_UDP:
- pkt->virt_hdr.gso_size = gso_size;
+ pkt->virt_hdr.gso_size = IP_FRAG_ALIGN_SIZE(gso_size);
pkt->virt_hdr.hdr_len = pkt->hdr_len + sizeof(struct udp_header);
break;
case VIRTIO_NET_HDR_GSO_TCPV4:
case VIRTIO_NET_HDR_GSO_TCPV6:
- iov_to_buf(&pkt->vec[NET_TX_PKT_PL_START_FRAG], pkt->payload_frags,
+ iov_to_buf(&pkt->vec[VMXNET_TX_PKT_PL_START_FRAG], pkt->payload_frags,
0, &l4hdr, sizeof(l4hdr));
pkt->virt_hdr.hdr_len = pkt->hdr_len + l4hdr.th_off * sizeof(uint32_t);
- pkt->virt_hdr.gso_size = gso_size;
+ pkt->virt_hdr.gso_size = IP_FRAG_ALIGN_SIZE(gso_size);
break;
default:
@@ -356,24 +322,23 @@ void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
}
}
-void net_tx_pkt_setup_vlan_header_ex(struct NetTxPkt *pkt,
- uint16_t vlan, uint16_t vlan_ethtype)
+void vmxnet_tx_pkt_setup_vlan_header(struct VmxnetTxPkt *pkt, uint16_t vlan)
{
bool is_new;
assert(pkt);
- eth_setup_vlan_headers_ex(pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_base,
- vlan, vlan_ethtype, &is_new);
+ eth_setup_vlan_headers(pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_base,
+ vlan, &is_new);
/* update l2hdrlen */
if (is_new) {
pkt->hdr_len += sizeof(struct vlan_header);
- pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len +=
+ pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len +=
sizeof(struct vlan_header);
}
}
-bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa,
+bool vmxnet_tx_pkt_add_raw_fragment(struct VmxnetTxPkt *pkt, hwaddr pa,
size_t len)
{
hwaddr mapped_len = 0;
@@ -388,50 +353,44 @@ bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa,
ventry = &pkt->raw[pkt->raw_frags];
mapped_len = len;
- ventry->iov_base = pci_dma_map(pkt->pci_dev, pa,
- &mapped_len, DMA_DIRECTION_TO_DEVICE);
+ ventry->iov_base = cpu_physical_memory_map(pa, &mapped_len, false);
+ ventry->iov_len = mapped_len;
+ pkt->raw_frags += !!ventry->iov_base;
- if ((ventry->iov_base != NULL) && (len == mapped_len)) {
- ventry->iov_len = mapped_len;
- pkt->raw_frags++;
- return true;
- } else {
+ if ((ventry->iov_base == NULL) || (len != mapped_len)) {
return false;
}
-}
-bool net_tx_pkt_has_fragments(struct NetTxPkt *pkt)
-{
- return pkt->raw_frags > 0;
+ return true;
}
-eth_pkt_types_e net_tx_pkt_get_packet_type(struct NetTxPkt *pkt)
+eth_pkt_types_e vmxnet_tx_pkt_get_packet_type(struct VmxnetTxPkt *pkt)
{
assert(pkt);
return pkt->packet_type;
}
-size_t net_tx_pkt_get_total_len(struct NetTxPkt *pkt)
+size_t vmxnet_tx_pkt_get_total_len(struct VmxnetTxPkt *pkt)
{
assert(pkt);
return pkt->hdr_len + pkt->payload_len;
}
-void net_tx_pkt_dump(struct NetTxPkt *pkt)
+void vmxnet_tx_pkt_dump(struct VmxnetTxPkt *pkt)
{
-#ifdef NET_TX_PKT_DEBUG
+#ifdef VMXNET_TX_PKT_DEBUG
assert(pkt);
printf("TX PKT: hdr_len: %d, pkt_type: 0x%X, l2hdr_len: %lu, "
"l3hdr_len: %lu, payload_len: %u\n", pkt->hdr_len, pkt->packet_type,
- pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len,
- pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len, pkt->payload_len);
+ pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len,
+ pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len, pkt->payload_len);
#endif
}
-void net_tx_pkt_reset(struct NetTxPkt *pkt)
+void vmxnet_tx_pkt_reset(struct VmxnetTxPkt *pkt)
{
int i;
@@ -442,31 +401,38 @@ void net_tx_pkt_reset(struct NetTxPkt *pkt)
memset(&pkt->virt_hdr, 0, sizeof(pkt->virt_hdr));
- assert(pkt->vec);
+ g_free(pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base);
+ pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base = NULL;
+ assert(pkt->vec);
+ for (i = VMXNET_TX_PKT_L2HDR_FRAG;
+ i < pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG; i++) {
+ pkt->vec[i].iov_len = 0;
+ }
pkt->payload_len = 0;
pkt->payload_frags = 0;
assert(pkt->raw);
for (i = 0; i < pkt->raw_frags; i++) {
assert(pkt->raw[i].iov_base);
- pci_dma_unmap(pkt->pci_dev, pkt->raw[i].iov_base, pkt->raw[i].iov_len,
- DMA_DIRECTION_TO_DEVICE, 0);
+ cpu_physical_memory_unmap(pkt->raw[i].iov_base, pkt->raw[i].iov_len,
+ false, pkt->raw[i].iov_len);
+ pkt->raw[i].iov_len = 0;
}
pkt->raw_frags = 0;
pkt->hdr_len = 0;
+ pkt->packet_type = 0;
pkt->l4proto = 0;
}
-static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
+static void vmxnet_tx_pkt_do_sw_csum(struct VmxnetTxPkt *pkt)
{
- struct iovec *iov = &pkt->vec[NET_TX_PKT_L2HDR_FRAG];
+ struct iovec *iov = &pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG];
uint32_t csum_cntr;
uint16_t csum = 0;
- uint32_t cso;
/* num of iovec without vhdr */
- uint32_t iov_len = pkt->payload_frags + NET_TX_PKT_PL_START_FRAG - 1;
+ uint32_t iov_len = pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG - 1;
uint16_t csl;
struct ip_header *iphdr;
size_t csum_offset = pkt->virt_hdr.csum_start + pkt->virt_hdr.csum_offset;
@@ -477,13 +443,12 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
/* Calculate L4 TCP/UDP checksum */
csl = pkt->payload_len;
- /* add pseudo header to csum */
- iphdr = pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base;
- csum_cntr = eth_calc_ip4_pseudo_hdr_csum(iphdr, csl, &cso);
-
/* data checksum */
- csum_cntr +=
- net_checksum_add_iov(iov, iov_len, pkt->virt_hdr.csum_start, csl, cso);
+ csum_cntr =
+ net_checksum_add_iov(iov, iov_len, pkt->virt_hdr.csum_start, csl);
+ /* add pseudo header to csum */
+ iphdr = pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base;
+ csum_cntr += eth_calc_pseudo_hdr_csum(iphdr, csl);
/* Put the checksum obtained into the packet */
csum = cpu_to_be16(net_checksum_finish(csum_cntr));
@@ -491,37 +456,37 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
}
enum {
- NET_TX_PKT_FRAGMENT_L2_HDR_POS = 0,
- NET_TX_PKT_FRAGMENT_L3_HDR_POS,
- NET_TX_PKT_FRAGMENT_HEADER_NUM
+ VMXNET_TX_PKT_FRAGMENT_L2_HDR_POS = 0,
+ VMXNET_TX_PKT_FRAGMENT_L3_HDR_POS,
+ VMXNET_TX_PKT_FRAGMENT_HEADER_NUM
};
-#define NET_MAX_FRAG_SG_LIST (64)
+#define VMXNET_MAX_FRAG_SG_LIST (64)
-static size_t net_tx_pkt_fetch_fragment(struct NetTxPkt *pkt,
+static size_t vmxnet_tx_pkt_fetch_fragment(struct VmxnetTxPkt *pkt,
int *src_idx, size_t *src_offset, struct iovec *dst, int *dst_idx)
{
size_t fetched = 0;
struct iovec *src = pkt->vec;
- *dst_idx = NET_TX_PKT_FRAGMENT_HEADER_NUM;
+ *dst_idx = VMXNET_TX_PKT_FRAGMENT_HEADER_NUM;
- while (fetched < IP_FRAG_ALIGN_SIZE(pkt->virt_hdr.gso_size)) {
+ while (fetched < pkt->virt_hdr.gso_size) {
/* no more place in fragment iov */
- if (*dst_idx == NET_MAX_FRAG_SG_LIST) {
+ if (*dst_idx == VMXNET_MAX_FRAG_SG_LIST) {
break;
}
/* no more data in iovec */
- if (*src_idx == (pkt->payload_frags + NET_TX_PKT_PL_START_FRAG)) {
+ if (*src_idx == (pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG)) {
break;
}
dst[*dst_idx].iov_base = src[*src_idx].iov_base + *src_offset;
dst[*dst_idx].iov_len = MIN(src[*src_idx].iov_len - *src_offset,
- IP_FRAG_ALIGN_SIZE(pkt->virt_hdr.gso_size) - fetched);
+ pkt->virt_hdr.gso_size - fetched);
*src_offset += dst[*dst_idx].iov_len;
fetched += dst[*dst_idx].iov_len;
@@ -537,45 +502,35 @@ static size_t net_tx_pkt_fetch_fragment(struct NetTxPkt *pkt,
return fetched;
}
-static inline void net_tx_pkt_sendv(struct NetTxPkt *pkt,
- NetClientState *nc, const struct iovec *iov, int iov_cnt)
-{
- if (pkt->is_loopback) {
- nc->info->receive_iov(nc, iov, iov_cnt);
- } else {
- qemu_sendv_packet(nc, iov, iov_cnt);
- }
-}
-
-static bool net_tx_pkt_do_sw_fragmentation(struct NetTxPkt *pkt,
+static bool vmxnet_tx_pkt_do_sw_fragmentation(struct VmxnetTxPkt *pkt,
NetClientState *nc)
{
- struct iovec fragment[NET_MAX_FRAG_SG_LIST];
+ struct iovec fragment[VMXNET_MAX_FRAG_SG_LIST];
size_t fragment_len = 0;
bool more_frags = false;
/* some pointers for shorter code */
void *l2_iov_base, *l3_iov_base;
size_t l2_iov_len, l3_iov_len;
- int src_idx = NET_TX_PKT_PL_START_FRAG, dst_idx;
+ int src_idx = VMXNET_TX_PKT_PL_START_FRAG, dst_idx;
size_t src_offset = 0;
size_t fragment_offset = 0;
- l2_iov_base = pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_base;
- l2_iov_len = pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len;
- l3_iov_base = pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base;
- l3_iov_len = pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len;
+ l2_iov_base = pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_base;
+ l2_iov_len = pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len;
+ l3_iov_base = pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base;
+ l3_iov_len = pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len;
/* Copy headers */
- fragment[NET_TX_PKT_FRAGMENT_L2_HDR_POS].iov_base = l2_iov_base;
- fragment[NET_TX_PKT_FRAGMENT_L2_HDR_POS].iov_len = l2_iov_len;
- fragment[NET_TX_PKT_FRAGMENT_L3_HDR_POS].iov_base = l3_iov_base;
- fragment[NET_TX_PKT_FRAGMENT_L3_HDR_POS].iov_len = l3_iov_len;
+ fragment[VMXNET_TX_PKT_FRAGMENT_L2_HDR_POS].iov_base = l2_iov_base;
+ fragment[VMXNET_TX_PKT_FRAGMENT_L2_HDR_POS].iov_len = l2_iov_len;
+ fragment[VMXNET_TX_PKT_FRAGMENT_L3_HDR_POS].iov_base = l3_iov_base;
+ fragment[VMXNET_TX_PKT_FRAGMENT_L3_HDR_POS].iov_len = l3_iov_len;
/* Put as much data as possible and send */
do {
- fragment_len = net_tx_pkt_fetch_fragment(pkt, &src_idx, &src_offset,
+ fragment_len = vmxnet_tx_pkt_fetch_fragment(pkt, &src_idx, &src_offset,
fragment, &dst_idx);
more_frags = (fragment_offset + fragment_len < pkt->payload_len);
@@ -585,22 +540,22 @@ static bool net_tx_pkt_do_sw_fragmentation(struct NetTxPkt *pkt,
eth_fix_ip4_checksum(l3_iov_base, l3_iov_len);
- net_tx_pkt_sendv(pkt, nc, fragment, dst_idx);
+ qemu_sendv_packet(nc, fragment, dst_idx);
fragment_offset += fragment_len;
- } while (fragment_len && more_frags);
+ } while (more_frags);
return true;
}
-bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState *nc)
+bool vmxnet_tx_pkt_send(struct VmxnetTxPkt *pkt, NetClientState *nc)
{
assert(pkt);
if (!pkt->has_virt_hdr &&
pkt->virt_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
- net_tx_pkt_do_sw_csum(pkt);
+ vmxnet_tx_pkt_do_sw_csum(pkt);
}
/*
@@ -610,28 +565,17 @@ bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState *nc)
if (VIRTIO_NET_HDR_GSO_NONE != pkt->virt_hdr.gso_type) {
if (pkt->payload_len >
ETH_MAX_IP_DGRAM_LEN -
- pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len) {
+ pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len) {
return false;
}
}
if (pkt->has_virt_hdr ||
pkt->virt_hdr.gso_type == VIRTIO_NET_HDR_GSO_NONE) {
- net_tx_pkt_sendv(pkt, nc, pkt->vec,
- pkt->payload_frags + NET_TX_PKT_PL_START_FRAG);
+ qemu_sendv_packet(nc, pkt->vec,
+ pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG);
return true;
}
- return net_tx_pkt_do_sw_fragmentation(pkt, nc);
-}
-
-bool net_tx_pkt_send_loopback(struct NetTxPkt *pkt, NetClientState *nc)
-{
- bool res;
-
- pkt->is_loopback = true;
- res = net_tx_pkt_send(pkt, nc);
- pkt->is_loopback = false;
-
- return res;
+ return vmxnet_tx_pkt_do_sw_fragmentation(pkt, nc);
}
diff --git a/hw/net/vmxnet_tx_pkt.h b/hw/net/vmxnet_tx_pkt.h
new file mode 100644
index 000000000..f51e98ad9
--- /dev/null
+++ b/hw/net/vmxnet_tx_pkt.h
@@ -0,0 +1,146 @@
+/*
+ * QEMU VMWARE VMXNET* paravirtual NICs - TX packets abstraction
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry@daynix.com>
+ * Tamir Shomer <tamirs@daynix.com>
+ * Yan Vugenfirer <yan@daynix.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 VMXNET_TX_PKT_H
+#define VMXNET_TX_PKT_H
+
+#include "net/eth.h"
+#include "exec/hwaddr.h"
+
+/* define to enable packet dump functions */
+/*#define VMXNET_TX_PKT_DEBUG*/
+
+struct VmxnetTxPkt;
+
+/**
+ * Init function for tx packet functionality
+ *
+ * @pkt: packet pointer
+ * @max_frags: max tx ip fragments
+ * @has_virt_hdr: device uses virtio header.
+ */
+void vmxnet_tx_pkt_init(struct VmxnetTxPkt **pkt, uint32_t max_frags,
+ bool has_virt_hdr);
+
+/**
+ * Clean all tx packet resources.
+ *
+ * @pkt: packet.
+ */
+void vmxnet_tx_pkt_uninit(struct VmxnetTxPkt *pkt);
+
+/**
+ * get virtio header
+ *
+ * @pkt: packet
+ * @ret: virtio header
+ */
+struct virtio_net_hdr *vmxnet_tx_pkt_get_vhdr(struct VmxnetTxPkt *pkt);
+
+/**
+ * build virtio header (will be stored in module context)
+ *
+ * @pkt: packet
+ * @tso_enable: TSO enabled
+ * @csum_enable: CSO enabled
+ * @gso_size: MSS size for TSO
+ *
+ */
+void vmxnet_tx_pkt_build_vheader(struct VmxnetTxPkt *pkt, bool tso_enable,
+ bool csum_enable, uint32_t gso_size);
+
+/**
+ * updates vlan tag, and adds vlan header in case it is missing
+ *
+ * @pkt: packet
+ * @vlan: VLAN tag
+ *
+ */
+void vmxnet_tx_pkt_setup_vlan_header(struct VmxnetTxPkt *pkt, uint16_t vlan);
+
+/**
+ * populate data fragment into pkt context.
+ *
+ * @pkt: packet
+ * @pa: physical address of fragment
+ * @len: length of fragment
+ *
+ */
+bool vmxnet_tx_pkt_add_raw_fragment(struct VmxnetTxPkt *pkt, hwaddr pa,
+ size_t len);
+
+/**
+ * fix ip header fields and calculate checksums needed.
+ *
+ * @pkt: packet
+ *
+ */
+void vmxnet_tx_pkt_update_ip_checksums(struct VmxnetTxPkt *pkt);
+
+/**
+ * get length of all populated data.
+ *
+ * @pkt: packet
+ * @ret: total data length
+ *
+ */
+size_t vmxnet_tx_pkt_get_total_len(struct VmxnetTxPkt *pkt);
+
+/**
+ * get packet type
+ *
+ * @pkt: packet
+ * @ret: packet type
+ *
+ */
+eth_pkt_types_e vmxnet_tx_pkt_get_packet_type(struct VmxnetTxPkt *pkt);
+
+/**
+ * prints packet data if debug is enabled
+ *
+ * @pkt: packet
+ *
+ */
+void vmxnet_tx_pkt_dump(struct VmxnetTxPkt *pkt);
+
+/**
+ * reset tx packet private context (needed to be called between packets)
+ *
+ * @pkt: packet
+ *
+ */
+void vmxnet_tx_pkt_reset(struct VmxnetTxPkt *pkt);
+
+/**
+ * Send packet to qemu. handles sw offloads if vhdr is not supported.
+ *
+ * @pkt: packet
+ * @nc: NetClientState
+ * @ret: operation result
+ *
+ */
+bool vmxnet_tx_pkt_send(struct VmxnetTxPkt *pkt, NetClientState *nc);
+
+/**
+ * parse raw packet data and analyze offload requirements.
+ *
+ * @pkt: packet
+ *
+ */
+bool vmxnet_tx_pkt_parse(struct VmxnetTxPkt *pkt);
+
+#endif
diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c
index 6856b5299..7281730d9 100644
--- a/hw/net/xen_nic.c
+++ b/hw/net/xen_nic.c
@@ -22,6 +22,7 @@
#include "qemu/osdep.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
+#include <sys/mman.h>
#include <sys/wait.h>
#include "hw/hw.h"
@@ -269,7 +270,7 @@ static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size
/* ------------------------------------------------------------- */
static NetClientInfo net_xen_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = net_rx_packet,
};
diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c
index 46b1aa17f..0c5f793bd 100644
--- a/hw/net/xgmac.c
+++ b/hw/net/xgmac.c
@@ -371,7 +371,7 @@ out:
}
static NetClientInfo net_xgmac_enet_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = eth_rx,
};
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index b6701844d..de23ab5dc 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -935,7 +935,7 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
}
static NetClientInfo net_xilinx_enet_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = eth_rx,
};
diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index 35de353b7..bc846e709 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -197,10 +197,6 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
}
D(qemu_log("%s %zd rxbase=%x\n", __func__, size, rxbase));
- if (size > (R_MAX - R_RX_BUF0 - rxbase) * 4) {
- D(qemu_log("ethlite packet is too big, size=%x\n", size));
- return -1;
- }
memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size);
s->regs[rxbase + R_RX_CTRL0] |= CTRL_S;
@@ -221,7 +217,7 @@ static void xilinx_ethlite_reset(DeviceState *dev)
}
static NetClientInfo net_xilinx_ethlite_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = eth_can_rx,
.receive = eth_rx,
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 6a68e594d..999f48028 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -25,7 +25,6 @@
#include "hw/hw.h"
#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
-#include "hw/boards.h"
#include "hw/isa/isa.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/sysbus.h"
@@ -552,7 +551,7 @@ static bool is_version_1(void *opaque, int version_id)
return version_id == 1;
}
-bool fw_cfg_dma_enabled(void *opaque)
+static bool fw_cfg_dma_enabled(void *opaque)
{
FWCfgState *s = opaque;
@@ -729,22 +728,17 @@ static int get_fw_cfg_order(FWCfgState *s, const char *name)
{
int i;
- if (s->fw_cfg_order_override > 0) {
- return s->fw_cfg_order_override;
- }
+ if (s->fw_cfg_order_override > 0)
+ return s->fw_cfg_order_override;
for (i = 0; i < ARRAY_SIZE(fw_cfg_order); i++) {
- if (fw_cfg_order[i].name == NULL) {
- continue;
- }
-
- if (strcmp(name, fw_cfg_order[i].name) == 0) {
- return fw_cfg_order[i].order;
- }
+ if (fw_cfg_order[i].name == NULL)
+ continue;
+ if (strcmp(name, fw_cfg_order[i].name) == 0)
+ return fw_cfg_order[i].order;
}
-
/* Stick unknown stuff at the end. */
- error_report("warning: Unknown firmware file in legacy mode: %s", name);
+ error_report("warning: Unknown firmware file in legacy mode: %s\n", name);
return FW_CFG_ORDER_OVERRIDE_LAST;
}
@@ -874,17 +868,16 @@ static void fw_cfg_machine_ready(struct Notifier *n, void *data)
static void fw_cfg_init1(DeviceState *dev)
{
FWCfgState *s = FW_CFG(dev);
- MachineState *machine = MACHINE(qdev_get_machine());
assert(!object_resolve_path(FW_CFG_PATH, NULL));
- object_property_add_child(OBJECT(machine), FW_CFG_NAME, OBJECT(s), NULL);
+ object_property_add_child(qdev_get_machine(), FW_CFG_NAME, OBJECT(s), NULL);
qdev_init_nofail(dev);
fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (char *)"QEMU", 4);
fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
- fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)!machine->enable_graphics);
+ fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC));
fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
fw_cfg_bootsplash(s);
@@ -990,7 +983,6 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data)
static const TypeInfo fw_cfg_info = {
.name = TYPE_FW_CFG,
.parent = TYPE_SYS_BUS_DEVICE,
- .abstract = true,
.instance_size = sizeof(FWCfgState),
.class_init = fw_cfg_class_init,
};
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
index 4de5f705d..802636ef3 100644
--- a/hw/nvram/spapr_nvram.c
+++ b/hw/nvram/spapr_nvram.c
@@ -39,7 +39,6 @@ typedef struct sPAPRNVRAM {
uint32_t size;
uint8_t *buf;
BlockBackend *blk;
- VMChangeStateEntry *vmstate;
} sPAPRNVRAM;
#define TYPE_VIO_SPAPR_NVRAM "spapr-nvram"
@@ -125,7 +124,7 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPRMachineState *spapr,
alen = len;
if (nvram->blk) {
- alen = blk_pwrite(nvram->blk, offset, membuf, len, 0);
+ alen = blk_pwrite(nvram->blk, offset, membuf, len);
}
assert(nvram->buf);
@@ -186,25 +185,19 @@ static int spapr_nvram_pre_load(void *opaque)
return 0;
}
-static void postload_update_cb(void *opaque, int running, RunState state)
-{
- sPAPRNVRAM *nvram = opaque;
-
- /* This is called after bdrv_invalidate_cache_all. */
-
- qemu_del_vm_change_state_handler(nvram->vmstate);
- nvram->vmstate = NULL;
-
- blk_pwrite(nvram->blk, 0, nvram->buf, nvram->size, 0);
-}
-
static int spapr_nvram_post_load(void *opaque, int version_id)
{
sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(opaque);
if (nvram->blk) {
- nvram->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
- nvram);
+ int alen = blk_pwrite(nvram->blk, 0, nvram->buf, nvram->size);
+
+ if (alen < 0) {
+ return alen;
+ }
+ if (alen != nvram->size) {
+ return -1;
+ }
}
return 0;
diff --git a/hw/nvram/trace-events b/hw/nvram/trace-events
deleted file mode 100644
index 1f1e05ab6..000000000
--- a/hw/nvram/trace-events
+++ /dev/null
@@ -1,10 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/nvram/ds1225y.c
-nvram_read(uint32_t addr, uint32_t ret) "read addr %d: 0x%02x"
-nvram_write(uint32_t addr, uint32_t old, uint32_t val) "write addr %d: 0x%02x -> 0x%02x"
-
-# hw/nvram/fw_cfg.c
-fw_cfg_select(void *s, uint16_t key, int ret) "%p key %d = %d"
-fw_cfg_read(void *s, uint64_t ret) "%p = %"PRIx64
-fw_cfg_add_file(void *s, int index, char *name, size_t len) "%p #%d: %s (%zd bytes)"
diff --git a/hw/pci-bridge/dec.h b/hw/pci-bridge/dec.h
index ae17ca736..17dc0c2b0 100644
--- a/hw/pci-bridge/dec.h
+++ b/hw/pci-bridge/dec.h
@@ -1,5 +1,5 @@
-#ifndef HW_PCI_BRIDGE_DEC_H
-#define HW_PCI_BRIDGE_DEC_H
+#ifndef DEC_PCI_H
+#define DEC_PCI_H
#include "qemu-common.h"
diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
index c8b5ac420..0937fa34b 100644
--- a/hw/pci-bridge/ioh3420.c
+++ b/hw/pci-bridge/ioh3420.c
@@ -25,7 +25,6 @@
#include "hw/pci/msi.h"
#include "hw/pci/pcie.h"
#include "ioh3420.h"
-#include "qapi/error.h"
#define PCI_DEVICE_ID_IOH_EPORT 0x3420 /* D0:F0 express mode */
#define PCI_DEVICE_ID_IOH_REV 0x2
@@ -98,9 +97,7 @@ static int ioh3420_initfn(PCIDevice *d)
PCIEPort *p = PCIE_PORT(d);
PCIESlot *s = PCIE_SLOT(d);
int rc;
- Error *err = NULL;
- pci_config_set_interrupt_pin(d->config, 1);
pci_bridge_initfn(d, TYPE_PCIE_BUS);
pcie_port_init_reg(d);
@@ -109,16 +106,12 @@ static int ioh3420_initfn(PCIDevice *d)
if (rc < 0) {
goto err_bridge;
}
-
rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR,
IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
- IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, &err);
+ IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
if (rc < 0) {
- assert(rc == -ENOTSUP);
- error_report_err(err);
goto err_bridge;
}
-
rc = pcie_cap_init(d, IOH_EP_EXP_OFFSET, PCI_EXP_TYPE_ROOT_PORT, p->port);
if (rc < 0) {
goto err_msi;
@@ -127,21 +120,18 @@ static int ioh3420_initfn(PCIDevice *d)
pcie_cap_arifwd_init(d);
pcie_cap_deverr_init(d);
pcie_cap_slot_init(d, s->slot);
- pcie_cap_root_init(d);
-
pcie_chassis_create(s->chassis);
rc = pcie_chassis_add_slot(s);
if (rc < 0) {
goto err_pcie_cap;
}
-
+ pcie_cap_root_init(d);
rc = pcie_aer_init(d, IOH_EP_AER_OFFSET, PCI_ERR_SIZEOF);
if (rc < 0) {
goto err;
}
pcie_aer_root_init(d);
ioh3420_aer_vector_update(d);
-
return 0;
err:
@@ -217,3 +207,12 @@ static void ioh3420_register_types(void)
}
type_init(ioh3420_register_types)
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
index 5dbd933cc..7b582e96a 100644
--- a/hw/pci-bridge/pci_bridge_dev.c
+++ b/hw/pci-bridge/pci_bridge_dev.c
@@ -42,10 +42,9 @@ struct PCIBridgeDev {
MemoryRegion bar;
uint8_t chassis_nr;
-#define PCI_BRIDGE_DEV_F_SHPC_REQ 0
+#define PCI_BRIDGE_DEV_F_MSI_REQ 0
+#define PCI_BRIDGE_DEV_F_SHPC_REQ 1
uint32_t flags;
-
- OnOffAuto msi;
};
typedef struct PCIBridgeDev PCIBridgeDev;
@@ -54,7 +53,6 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
PCIBridge *br = PCI_BRIDGE(dev);
PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);
int err;
- Error *local_err = NULL;
pci_bridge_initfn(dev, TYPE_PCI_BUS);
@@ -68,33 +66,19 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
}
} else {
/* MSI is not applicable without SHPC */
- bridge_dev->msi = ON_OFF_AUTO_OFF;
+ bridge_dev->flags &= ~(1 << PCI_BRIDGE_DEV_F_MSI_REQ);
}
-
err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0);
if (err) {
goto slotid_error;
}
-
- if (bridge_dev->msi != ON_OFF_AUTO_OFF) {
- /* it means SHPC exists, because MSI is needed by SHPC */
-
- err = msi_init(dev, 0, 1, true, true, &local_err);
- /* Any error other than -ENOTSUP(board's MSI support is broken)
- * is a programming error */
- assert(!err || err == -ENOTSUP);
- if (err && bridge_dev->msi == ON_OFF_AUTO_ON) {
- /* Can't satisfy user's explicit msi=on request, fail */
- error_append_hint(&local_err, "You have to use msi=auto (default) "
- "or msi=off with this machine type.\n");
- error_report_err(local_err);
+ if ((bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_MSI_REQ)) &&
+ msi_nonbroken) {
+ err = msi_init(dev, 0, 1, true, true);
+ if (err < 0) {
goto msi_error;
}
- assert(!local_err || bridge_dev->msi == ON_OFF_AUTO_AUTO);
- /* With msi=auto, we fall back to MSI off silently */
- error_free(local_err);
}
-
if (shpc_present(dev)) {
/* TODO: spec recommends using 64 bit prefetcheable BAR.
* Check whether that works well. */
@@ -102,7 +86,6 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
}
return 0;
-
msi_error:
slotid_cap_cleanup(dev);
slotid_error:
@@ -160,8 +143,8 @@ static Property pci_bridge_dev_properties[] = {
/* Note: 0 is not a legal chassis number. */
DEFINE_PROP_UINT8(PCI_BRIDGE_DEV_PROP_CHASSIS_NR, PCIBridgeDev, chassis_nr,
0),
- DEFINE_PROP_ON_OFF_AUTO(PCI_BRIDGE_DEV_PROP_MSI, PCIBridgeDev, msi,
- ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_BIT(PCI_BRIDGE_DEV_PROP_MSI, PCIBridgeDev, flags,
+ PCI_BRIDGE_DEV_F_MSI_REQ, true),
DEFINE_PROP_BIT(PCI_BRIDGE_DEV_PROP_SHPC, PCIBridgeDev, flags,
PCI_BRIDGE_DEV_F_SHPC_REQ, true),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c
index 1cc598f7e..ba320bd85 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_host.h"
@@ -150,8 +149,6 @@ static void pxb_host_class_init(ObjectClass *class, void *data)
PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(class);
dc->fw_name = "pci";
- /* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself */
- dc->cannot_instantiate_with_device_add_yet = true;
sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
hc->root_bus_path = pxb_host_root_bus_path;
}
@@ -163,25 +160,30 @@ static const TypeInfo pxb_host_info = {
};
/*
- * Registers the PXB bus as a child of pci host root bus.
+ * Registers the PXB bus as a child of the i440fx root bus.
+ *
+ * Returns 0 on successs, -1 if i440fx host was not
+ * found or the bus number is already in use.
*/
-static void pxb_register_bus(PCIDevice *dev, PCIBus *pxb_bus, Error **errp)
+static int pxb_register_bus(PCIDevice *dev, PCIBus *pxb_bus)
{
PCIBus *bus = dev->bus;
int pxb_bus_num = pci_bus_num(pxb_bus);
if (bus->parent_dev) {
- error_setg(errp, "PXB devices can be attached only to root bus");
- return;
+ error_report("PXB devices can be attached only to root bus.");
+ return -1;
}
QLIST_FOREACH(bus, &bus->child, sibling) {
if (pci_bus_num(bus) == pxb_bus_num) {
- error_setg(errp, "Bus %d is already in use", pxb_bus_num);
- return;
+ error_report("Bus %d is already in use.", pxb_bus_num);
+ return -1;
}
}
QLIST_INSERT_HEAD(&dev->bus->child, pxb_bus, sibling);
+
+ return 0;
}
static int pxb_map_irq_fn(PCIDevice *pci_dev, int pin)
@@ -211,18 +213,17 @@ static gint pxb_compare(gconstpointer a, gconstpointer b)
0;
}
-static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp)
+static int pxb_dev_init_common(PCIDevice *dev, bool pcie)
{
PXBDev *pxb = convert_to_pxb(dev);
DeviceState *ds, *bds = NULL;
PCIBus *bus;
const char *dev_name = NULL;
- Error *local_err = NULL;
if (pxb->numa_node != NUMA_NODE_UNASSIGNED &&
pxb->numa_node >= nb_numa_nodes) {
- error_setg(errp, "Illegal numa node %d", pxb->numa_node);
- return;
+ error_report("Illegal numa node %d.", pxb->numa_node);
+ return -EINVAL;
}
if (dev->qdev.id && *dev->qdev.id) {
@@ -247,9 +248,7 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp)
PCI_HOST_BRIDGE(ds)->bus = bus;
- pxb_register_bus(dev, bus, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
+ if (pxb_register_bus(dev, bus)) {
goto err_register_bus;
}
@@ -263,22 +262,23 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp)
pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_HOST);
pxb_dev_list = g_list_insert_sorted(pxb_dev_list, pxb, pxb_compare);
- return;
+ return 0;
err_register_bus:
object_unref(OBJECT(bds));
object_unparent(OBJECT(bus));
object_unref(OBJECT(ds));
+ return -EINVAL;
}
-static void pxb_dev_realize(PCIDevice *dev, Error **errp)
+static int pxb_dev_initfn(PCIDevice *dev)
{
if (pci_bus_is_express(dev->bus)) {
- error_setg(errp, "pxb devices cannot reside on a PCIe bus");
- return;
+ error_report("pxb devices cannot reside on a PCIe bus!");
+ return -EINVAL;
}
- pxb_dev_realize_common(dev, false, errp);
+ return pxb_dev_init_common(dev, false);
}
static void pxb_dev_exitfn(PCIDevice *pci_dev)
@@ -300,7 +300,7 @@ static void pxb_dev_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->realize = pxb_dev_realize;
+ k->init = pxb_dev_initfn;
k->exit = pxb_dev_exitfn;
k->vendor_id = PCI_VENDOR_ID_REDHAT;
k->device_id = PCI_DEVICE_ID_REDHAT_PXB;
@@ -308,7 +308,6 @@ static void pxb_dev_class_init(ObjectClass *klass, void *data)
dc->desc = "PCI Expander Bridge";
dc->props = pxb_dev_properties;
- dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
@@ -319,14 +318,14 @@ static const TypeInfo pxb_dev_info = {
.class_init = pxb_dev_class_init,
};
-static void pxb_pcie_dev_realize(PCIDevice *dev, Error **errp)
+static int pxb_pcie_dev_initfn(PCIDevice *dev)
{
if (!pci_bus_is_express(dev->bus)) {
- error_setg(errp, "pxb-pcie devices cannot reside on a PCI bus");
- return;
+ error_report("pxb-pcie devices cannot reside on a PCI bus!");
+ return -EINVAL;
}
- pxb_dev_realize_common(dev, true, errp);
+ return pxb_dev_init_common(dev, true);
}
static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data)
@@ -334,7 +333,7 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->realize = pxb_pcie_dev_realize;
+ k->init = pxb_pcie_dev_initfn;
k->exit = pxb_dev_exitfn;
k->vendor_id = PCI_VENDOR_ID_REDHAT;
k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE;
@@ -342,7 +341,6 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data)
dc->desc = "PCI Express Expander Bridge";
dc->props = pxb_dev_properties;
- dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index cef6e1325..cf1ee63ab 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -24,7 +24,6 @@
#include "hw/pci/msi.h"
#include "hw/pci/pcie.h"
#include "xio3130_downstream.h"
-#include "qapi/error.h"
#define PCI_DEVICE_ID_TI_XIO3130D 0x8233 /* downstream port */
#define XIO3130_REVISION 0x1
@@ -61,26 +60,21 @@ static int xio3130_downstream_initfn(PCIDevice *d)
PCIEPort *p = PCIE_PORT(d);
PCIESlot *s = PCIE_SLOT(d);
int rc;
- Error *err = NULL;
pci_bridge_initfn(d, TYPE_PCIE_BUS);
pcie_port_init_reg(d);
rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
- XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, &err);
+ XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
if (rc < 0) {
- assert(rc == -ENOTSUP);
- error_report_err(err);
goto err_bridge;
}
-
rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
if (rc < 0) {
goto err_bridge;
}
-
rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_DOWNSTREAM,
p->port);
if (rc < 0) {
@@ -89,14 +83,12 @@ static int xio3130_downstream_initfn(PCIDevice *d)
pcie_cap_flr_init(d);
pcie_cap_deverr_init(d);
pcie_cap_slot_init(d, s->slot);
- pcie_cap_arifwd_init(d);
-
pcie_chassis_create(s->chassis);
rc = pcie_chassis_add_slot(s);
if (rc < 0) {
goto err_pcie_cap;
}
-
+ pcie_cap_arifwd_init(d);
rc = pcie_aer_init(d, XIO3130_AER_OFFSET, PCI_ERR_SIZEOF);
if (rc < 0) {
goto err;
@@ -203,3 +195,12 @@ static void xio3130_downstream_register_types(void)
}
type_init(xio3130_downstream_register_types)
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
index 4ad0440aa..164ef58c4 100644
--- a/hw/pci-bridge/xio3130_upstream.c
+++ b/hw/pci-bridge/xio3130_upstream.c
@@ -24,7 +24,6 @@
#include "hw/pci/msi.h"
#include "hw/pci/pcie.h"
#include "xio3130_upstream.h"
-#include "qapi/error.h"
#define PCI_DEVICE_ID_TI_XIO3130U 0x8232 /* upstream port */
#define XIO3130_REVISION 0x2
@@ -57,26 +56,21 @@ static int xio3130_upstream_initfn(PCIDevice *d)
{
PCIEPort *p = PCIE_PORT(d);
int rc;
- Error *err = NULL;
pci_bridge_initfn(d, TYPE_PCIE_BUS);
pcie_port_init_reg(d);
rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
- XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, &err);
+ XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
if (rc < 0) {
- assert(rc == -ENOTSUP);
- error_report_err(err);
goto err_bridge;
}
-
rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
if (rc < 0) {
goto err_bridge;
}
-
rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_UPSTREAM,
p->port);
if (rc < 0) {
@@ -84,7 +78,6 @@ static int xio3130_upstream_initfn(PCIDevice *d)
}
pcie_cap_flr_init(d);
pcie_cap_deverr_init(d);
-
rc = pcie_aer_init(d, XIO3130_AER_OFFSET, PCI_ERR_SIZEOF);
if (rc < 0) {
goto err;
@@ -174,3 +167,13 @@ static void xio3130_upstream_register_types(void)
}
type_init(xio3130_upstream_register_types)
+
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci-bridge/xio3130_upstream.h b/hw/pci-bridge/xio3130_upstream.h
index d0ab7577e..08c1d5f75 100644
--- a/hw/pci-bridge/xio3130_upstream.h
+++ b/hw/pci-bridge/xio3130_upstream.h
@@ -7,4 +7,4 @@ PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
const char *bus_name, pci_map_irq_fn map_irq,
uint8_t port);
-#endif /* QEMU_XIO3130_UPSTREAM_H */
+#endif /* QEMU_XIO3130_H */
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 653e71112..aaef7bb3a 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -36,7 +36,6 @@
#include "hw/pci-host/apb.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"
-#include "qemu/log.h"
/* debug APB */
//#define DEBUG_APB
@@ -634,7 +633,7 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
}
}
-static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp)
+static int apb_pci_bridge_initfn(PCIDevice *dev)
{
pci_bridge_initfn(dev, TYPE_PCI_BUS);
@@ -652,6 +651,7 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp)
pci_set_word(dev->config + PCI_STATUS,
PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
PCI_STATUS_DEVSEL_MEDIUM);
+ return 0;
}
PCIBus *pci_apb_init(hwaddr special_base,
@@ -669,13 +669,6 @@ PCIBus *pci_apb_init(hwaddr special_base,
/* Ultrasparc PBM main bus */
dev = qdev_create(NULL, TYPE_APB);
- d = APB_DEVICE(dev);
- phb = PCI_HOST_BRIDGE(dev);
- phb->bus = pci_register_bus(DEVICE(phb), "pci",
- pci_apb_set_irq, pci_pbm_map_irq, d,
- &d->pci_mmio,
- get_system_io(),
- 0, 32, TYPE_PCI_BUS);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
/* apb_config */
@@ -684,10 +677,18 @@ PCIBus *pci_apb_init(hwaddr special_base,
sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
/* pci_ioport */
sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
+ d = APB_DEVICE(dev);
memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
+ phb = PCI_HOST_BRIDGE(dev);
+ phb->bus = pci_register_bus(DEVICE(phb), "pci",
+ pci_apb_set_irq, pci_pbm_map_irq, d,
+ &d->pci_mmio,
+ get_system_io(),
+ 0, 32, TYPE_PCI_BUS);
+
*pbm_irqs = d->pbm_irqs;
d->ivec_irqs = ivec_irqs;
@@ -842,7 +843,7 @@ static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->realize = apb_pci_bridge_realize;
+ k->init = apb_pci_bridge_initfn;
k->exit = pci_bridge_exitfn;
k->vendor_id = PCI_VENDOR_ID_SUN;
k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c
index 2c8acdaac..8f9121615 100644
--- a/hw/pci-host/grackle.c
+++ b/hw/pci-host/grackle.c
@@ -72,6 +72,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
GrackleState *d;
dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE);
+ qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
phb = PCI_HOST_BRIDGE(dev);
d = GRACKLE_PCI_HOST_BRIDGE(dev);
@@ -91,7 +92,6 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
0, 4, TYPE_PCI_BUS);
pci_create_simple(phb->bus, 0, "grackle");
- qdev_init_nofail(dev);
sysbus_mmio_map(s, 0, base);
sysbus_mmio_map(s, 1, base + 0x00200000);
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index f9218aa95..df2b0e26f 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -48,7 +48,7 @@
typedef struct I440FXState {
PCIHostState parent_obj;
- Range pci_hole;
+ PcPciInfo pci_info;
uint64_t pci_hole64_size;
uint32_t short_root_bus;
} I440FXState;
@@ -221,12 +221,8 @@ static void i440fx_pcihost_get_pci_hole_start(Object *obj, Visitor *v,
Error **errp)
{
I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
- uint64_t val64;
- uint32_t value;
+ uint32_t value = s->pci_info.w32.begin;
- val64 = range_is_empty(&s->pci_hole) ? 0 : range_lob(&s->pci_hole);
- value = val64;
- assert(value == val64);
visit_type_uint32(v, name, &value, errp);
}
@@ -235,12 +231,8 @@ static void i440fx_pcihost_get_pci_hole_end(Object *obj, Visitor *v,
Error **errp)
{
I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
- uint64_t val64;
- uint32_t value;
+ uint32_t value = s->pci_info.w32.end;
- val64 = range_is_empty(&s->pci_hole) ? 0 : range_upb(&s->pci_hole) + 1;
- value = val64;
- assert(value == val64);
visit_type_uint32(v, name, &value, errp);
}
@@ -250,11 +242,10 @@ static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
{
PCIHostState *h = PCI_HOST_BRIDGE(obj);
Range w64;
- uint64_t value;
pci_bus_get_w64_range(h->bus, &w64);
- value = range_is_empty(&w64) ? 0 : range_lob(&w64);
- visit_type_uint64(v, name, &value, errp);
+
+ visit_type_uint64(v, name, &w64.begin, errp);
}
static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
@@ -263,16 +254,16 @@ static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
{
PCIHostState *h = PCI_HOST_BRIDGE(obj);
Range w64;
- uint64_t value;
pci_bus_get_w64_range(h->bus, &w64);
- value = range_is_empty(&w64) ? 0 : range_upb(&w64) + 1;
- visit_type_uint64(v, name, &value, errp);
+
+ visit_type_uint64(v, name, &w64.end, errp);
}
static void i440fx_pcihost_initfn(Object *obj)
{
PCIHostState *s = PCI_HOST_BRIDGE(obj);
+ I440FXState *d = I440FX_PCI_HOST_BRIDGE(obj);
memory_region_init_io(&s->conf_mem, obj, &pci_host_conf_le_ops, s,
"pci-conf-idx", 4);
@@ -294,6 +285,8 @@ static void i440fx_pcihost_initfn(Object *obj)
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
i440fx_pcihost_get_pci_hole64_end,
NULL, NULL, NULL, NULL);
+
+ d->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
}
static void i440fx_pcihost_realize(DeviceState *dev, Error **errp)
@@ -354,8 +347,7 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
f->ram_memory = ram_memory;
i440fx = I440FX_PCI_HOST_BRIDGE(dev);
- range_set_bounds(&i440fx->pci_hole, below_4g_mem_size,
- IO_APIC_DEFAULT_ADDRESS - 1);
+ i440fx->pci_info.w32.begin = below_4g_mem_size;
/* setup pci memory mapping */
pc_pci_as_mapping_init(OBJECT(f), f->system_memory,
@@ -873,8 +865,6 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
dc->realize = i440fx_pcihost_realize;
dc->fw_name = "pci";
dc->props = i440fx_props;
- /* Reason: needs to be wired up by pc_init1 */
- dc->cannot_instantiate_with_device_add_yet = true;
}
static const TypeInfo i440fx_pcihost_info = {
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 5580293f9..487e32ecb 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -247,7 +247,6 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->pci_intack);
/* TODO Remove once realize propagates to child devices. */
- object_property_set_bool(OBJECT(&s->pci_bus), true, "realized", errp);
object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
}
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 344f77b10..70f897e3a 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -52,7 +52,6 @@ static void q35_host_realize(DeviceState *dev, Error **errp)
pci->bus = pci_bus_new(DEVICE(s), "pcie.0",
s->mch.pci_address_space, s->mch.address_space_io,
0, TYPE_PCIE_BUS);
- PC_MACHINE(qdev_get_machine())->bus = pci->bus;
qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus));
qdev_init_nofail(DEVICE(&s->mch));
}
@@ -74,13 +73,8 @@ static void q35_host_get_pci_hole_start(Object *obj, Visitor *v,
Error **errp)
{
Q35PCIHost *s = Q35_HOST_DEVICE(obj);
- uint64_t val64;
- uint32_t value;
+ uint32_t value = s->mch.pci_info.w32.begin;
- val64 = range_is_empty(&s->mch.pci_hole)
- ? 0 : range_lob(&s->mch.pci_hole);
- value = val64;
- assert(value == val64);
visit_type_uint32(v, name, &value, errp);
}
@@ -89,13 +83,8 @@ static void q35_host_get_pci_hole_end(Object *obj, Visitor *v,
Error **errp)
{
Q35PCIHost *s = Q35_HOST_DEVICE(obj);
- uint64_t val64;
- uint32_t value;
+ uint32_t value = s->mch.pci_info.w32.end;
- val64 = range_is_empty(&s->mch.pci_hole)
- ? 0 : range_upb(&s->mch.pci_hole) + 1;
- value = val64;
- assert(value == val64);
visit_type_uint32(v, name, &value, errp);
}
@@ -105,11 +94,10 @@ static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v,
{
PCIHostState *h = PCI_HOST_BRIDGE(obj);
Range w64;
- uint64_t value;
pci_bus_get_w64_range(h->bus, &w64);
- value = range_is_empty(&w64) ? 0 : range_lob(&w64);
- visit_type_uint64(v, name, &value, errp);
+
+ visit_type_uint64(v, name, &w64.begin, errp);
}
static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
@@ -118,11 +106,10 @@ static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
{
PCIHostState *h = PCI_HOST_BRIDGE(obj);
Range w64;
- uint64_t value;
pci_bus_get_w64_range(h->bus, &w64);
- value = range_is_empty(&w64) ? 0 : range_upb(&w64) + 1;
- visit_type_uint64(v, name, &value, errp);
+
+ visit_type_uint64(v, name, &w64.end, errp);
}
static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name,
@@ -140,10 +127,6 @@ static Property mch_props[] = {
DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost,
mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
DEFINE_PROP_UINT32("short_root_bus", Q35PCIHost, mch.short_root_bus, 0),
- DEFINE_PROP_SIZE(PCI_HOST_BELOW_4G_MEM_SIZE, Q35PCIHost,
- mch.below_4g_mem_size, 0),
- DEFINE_PROP_SIZE(PCI_HOST_ABOVE_4G_MEM_SIZE, Q35PCIHost,
- mch.above_4g_mem_size, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -155,8 +138,6 @@ static void q35_host_class_init(ObjectClass *klass, void *data)
hc->root_bus_path = q35_host_root_bus_path;
dc->realize = q35_host_realize;
dc->props = mch_props;
- /* Reason: needs to be wired up by pc_q35_init */
- dc->cannot_instantiate_with_device_add_yet = true;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->fw_name = "pci";
}
@@ -196,30 +177,14 @@ static void q35_host_initfn(Object *obj)
q35_host_get_mmcfg_size,
NULL, NULL, NULL, NULL);
- object_property_add_link(obj, MCH_HOST_PROP_RAM_MEM, TYPE_MEMORY_REGION,
- (Object **) &s->mch.ram_memory,
- qdev_prop_allow_set_link_before_realize, 0, NULL);
-
- object_property_add_link(obj, MCH_HOST_PROP_PCI_MEM, TYPE_MEMORY_REGION,
- (Object **) &s->mch.pci_address_space,
- qdev_prop_allow_set_link_before_realize, 0, NULL);
-
- object_property_add_link(obj, MCH_HOST_PROP_SYSTEM_MEM, TYPE_MEMORY_REGION,
- (Object **) &s->mch.system_memory,
- qdev_prop_allow_set_link_before_realize, 0, NULL);
-
- object_property_add_link(obj, MCH_HOST_PROP_IO_MEM, TYPE_MEMORY_REGION,
- (Object **) &s->mch.address_space_io,
- qdev_prop_allow_set_link_before_realize, 0, NULL);
-
/* Leave enough space for the biggest MCFG BAR */
/* TODO: this matches current bios behaviour, but
* it's not a power of two, which means an MTRR
* can't cover it exactly.
*/
- range_set_bounds(&s->mch.pci_hole,
- MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT + MCH_HOST_BRIDGE_PCIEXBAR_MAX,
- IO_APIC_DEFAULT_ADDRESS - 1);
+ s->mch.pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT +
+ MCH_HOST_BRIDGE_PCIEXBAR_MAX;
+ s->mch.pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
}
static const TypeInfo q35_host_info = {
@@ -287,7 +252,10 @@ static void mch_update_pciexbar(MCHPCIState *mch)
break;
case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
default:
+ enable = 0;
+ length = 0;
abort();
+ break;
}
addr = pciexbar & addr_mask;
pcie_host_mmcfg_update(pehb, enable, addr, length);
@@ -297,13 +265,9 @@ static void mch_update_pciexbar(MCHPCIState *mch)
* which means an MTRR can't cover it exactly.
*/
if (enable) {
- range_set_bounds(&mch->pci_hole,
- addr + length,
- IO_APIC_DEFAULT_ADDRESS - 1);
+ mch->pci_info.w32.begin = addr + length;
} else {
- range_set_bounds(&mch->pci_hole,
- MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT,
- IO_APIC_DEFAULT_ADDRESS - 1);
+ mch->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
}
}
@@ -460,6 +424,30 @@ static void mch_reset(DeviceState *qdev)
mch_update(mch);
}
+static AddressSpace *q35_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
+{
+ IntelIOMMUState *s = opaque;
+ VTDAddressSpace *vtd_as;
+
+ assert(0 <= devfn && devfn <= VTD_PCI_DEVFN_MAX);
+
+ vtd_as = vtd_find_add_as(s, bus, devfn);
+ return &vtd_as->as;
+}
+
+static void mch_init_dmar(MCHPCIState *mch)
+{
+ PCIBus *pci_bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+
+ mch->iommu = INTEL_IOMMU_DEVICE(qdev_create(NULL, TYPE_INTEL_IOMMU_DEVICE));
+ object_property_add_child(OBJECT(mch), "intel-iommu",
+ OBJECT(mch->iommu), NULL);
+ qdev_init_nofail(DEVICE(mch->iommu));
+ sysbus_mmio_map(SYS_BUS_DEVICE(mch->iommu), 0, Q35_HOST_BRIDGE_IOMMU_ADDR);
+
+ pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu);
+}
+
static void mch_realize(PCIDevice *d, Error **errp)
{
int i;
@@ -518,6 +506,10 @@ static void mch_realize(PCIDevice *d, Error **errp)
mch->pci_address_space, &mch->pam_regions[i+1],
PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
}
+ /* Intel IOMMU (VT-d) */
+ if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+ mch_init_dmar(mch);
+ }
}
uint64_t mch_mcfg_base(void)
diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c
index 7aac4d67a..15b105423 100644
--- a/hw/pci-host/uninorth.c
+++ b/hw/pci-host/uninorth.c
@@ -62,9 +62,12 @@ typedef struct UNINState {
static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
{
+ int retval;
int devfn = pci_dev->devfn & 0x00FFFFFF;
- return (((devfn >> 11) & 0x1F) + irq_num) & 3;
+ retval = (((devfn >> 11) & 0x1F) + irq_num) & 3;
+
+ return retval;
}
static void pci_unin_set_irq(void *opaque, int irq_num, int level)
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index 467cbb9cb..339ec2c50 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -13,7 +13,6 @@
#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_host.h"
#include "exec/address-spaces.h"
-#include "qemu/log.h"
/* Old and buggy versions of QEMU used the wrong mapping from
* PCI IRQs to system interrupt lines. Unfortunately the Linux
@@ -455,7 +454,6 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp)
}
/* TODO Remove once realize propagates to child devices. */
- object_property_set_bool(OBJECT(&s->pci_bus), true, "realized", errp);
object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
}
diff --git a/hw/pci/msi.c b/hw/pci/msi.c
index a87b2278a..a87ef4d75 100644
--- a/hw/pci/msi.c
+++ b/hw/pci/msi.c
@@ -22,7 +22,6 @@
#include "hw/pci/msi.h"
#include "hw/xen/xen.h"
#include "qemu/range.h"
-#include "qapi/error.h"
/* PCI_MSI_ADDRESS_LO */
#define PCI_MSI_ADDRESS_LO_MASK (~0x3)
@@ -166,25 +165,8 @@ bool msi_enabled(const PCIDevice *dev)
PCI_MSI_FLAGS_ENABLE);
}
-/*
- * Make PCI device @dev MSI-capable.
- * Non-zero @offset puts capability MSI at that offset in PCI config
- * space.
- * @nr_vectors is the number of MSI vectors (1, 2, 4, 8, 16 or 32).
- * If @msi64bit, make the device capable of sending a 64-bit message
- * address.
- * If @msi_per_vector_mask, make the device support per-vector masking.
- * @errp is for returning errors.
- * Return 0 on success; set @errp and return -errno on error.
- *
- * -ENOTSUP means lacking msi support for a msi-capable platform.
- * -EINVAL means capability overlap, happens when @offset is non-zero,
- * also means a programming error, except device assignment, which can check
- * if a real HW is broken.
- */
int msi_init(struct PCIDevice *dev, uint8_t offset,
- unsigned int nr_vectors, bool msi64bit,
- bool msi_per_vector_mask, Error **errp)
+ unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask)
{
unsigned int vectors_order;
uint16_t flags;
@@ -192,7 +174,6 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
int config_offset;
if (!msi_nonbroken) {
- error_setg(errp, "MSI is not supported by interrupt controller");
return -ENOTSUP;
}
@@ -216,8 +197,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
}
cap_size = msi_cap_sizeof(flags);
- config_offset = pci_add_capability2(dev, PCI_CAP_ID_MSI, offset,
- cap_size, errp);
+ config_offset = pci_add_capability(dev, PCI_CAP_ID_MSI, offset, cap_size);
if (config_offset < 0) {
return config_offset;
}
@@ -240,8 +220,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
pci_set_long(dev->wmask + msi_mask_off(dev, msi64bit),
0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors));
}
-
- return 0;
+ return config_offset;
}
void msi_uninit(struct PCIDevice *dev)
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 0ec1cb14f..b75f0e9c4 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -72,7 +72,7 @@ void msix_set_pending(PCIDevice *dev, unsigned int vector)
*msix_pending_byte(dev, vector) |= msix_pending_mask(vector);
}
-void msix_clr_pending(PCIDevice *dev, int vector)
+static void msix_clr_pending(PCIDevice *dev, int vector)
{
*msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
}
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 24fae1689..616f04c1f 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -80,37 +80,10 @@ static const VMStateDescription vmstate_pcibus = {
}
};
-static void pci_init_bus_master(PCIDevice *pci_dev)
-{
- AddressSpace *dma_as = pci_device_iommu_address_space(pci_dev);
-
- memory_region_init_alias(&pci_dev->bus_master_enable_region,
- OBJECT(pci_dev), "bus master",
- dma_as->root, 0, memory_region_size(dma_as->root));
- memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
- address_space_init(&pci_dev->bus_master_as,
- &pci_dev->bus_master_enable_region, pci_dev->name);
-}
-
-static void pcibus_machine_done(Notifier *notifier, void *data)
-{
- PCIBus *bus = container_of(notifier, PCIBus, machine_done);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
- if (bus->devices[i]) {
- pci_init_bus_master(bus->devices[i]);
- }
- }
-}
-
static void pci_bus_realize(BusState *qbus, Error **errp)
{
PCIBus *bus = PCI_BUS(qbus);
- bus->machine_done.notify = pcibus_machine_done;
- qemu_add_machine_init_done_notifier(&bus->machine_done);
-
vmstate_register(NULL, -1, &vmstate_pcibus, bus);
}
@@ -118,8 +91,6 @@ static void pci_bus_unrealize(BusState *qbus, Error **errp)
{
PCIBus *bus = PCI_BUS(qbus);
- qemu_remove_machine_init_done_notifier(&bus->machine_done);
-
vmstate_unregister(NULL, &vmstate_pcibus, bus);
}
@@ -867,81 +838,6 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
address_space_destroy(&pci_dev->bus_master_as);
}
-/* Extract PCIReqIDCache into BDF format */
-static uint16_t pci_req_id_cache_extract(PCIReqIDCache *cache)
-{
- uint8_t bus_n;
- uint16_t result;
-
- switch (cache->type) {
- case PCI_REQ_ID_BDF:
- result = pci_get_bdf(cache->dev);
- break;
- case PCI_REQ_ID_SECONDARY_BUS:
- bus_n = pci_bus_num(cache->dev->bus);
- result = PCI_BUILD_BDF(bus_n, 0);
- break;
- default:
- error_printf("Invalid PCI requester ID cache type: %d\n",
- cache->type);
- exit(1);
- break;
- }
-
- return result;
-}
-
-/* Parse bridges up to the root complex and return requester ID
- * cache for specific device. For full PCIe topology, the cache
- * result would be exactly the same as getting BDF of the device.
- * However, several tricks are required when system mixed up with
- * legacy PCI devices and PCIe-to-PCI bridges.
- *
- * Here we cache the proxy device (and type) not requester ID since
- * bus number might change from time to time.
- */
-static PCIReqIDCache pci_req_id_cache_get(PCIDevice *dev)
-{
- PCIDevice *parent;
- PCIReqIDCache cache = {
- .dev = dev,
- .type = PCI_REQ_ID_BDF,
- };
-
- while (!pci_bus_is_root(dev->bus)) {
- /* We are under PCI/PCIe bridges */
- parent = dev->bus->parent_dev;
- if (pci_is_express(parent)) {
- if (pcie_cap_get_type(parent) == PCI_EXP_TYPE_PCI_BRIDGE) {
- /* When we pass through PCIe-to-PCI/PCIX bridges, we
- * override the requester ID using secondary bus
- * number of parent bridge with zeroed devfn
- * (pcie-to-pci bridge spec chap 2.3). */
- cache.type = PCI_REQ_ID_SECONDARY_BUS;
- cache.dev = dev;
- }
- } else {
- /* Legacy PCI, override requester ID with the bridge's
- * BDF upstream. When the root complex connects to
- * legacy PCI devices (including buses), it can only
- * obtain requester ID info from directly attached
- * devices. If devices are attached under bridges, only
- * the requester ID of the bridge that is directly
- * attached to the root complex can be recognized. */
- cache.type = PCI_REQ_ID_BDF;
- cache.dev = parent;
- }
- dev = parent;
- }
-
- return cache;
-}
-
-uint16_t pci_requester_id(PCIDevice *dev)
-{
- return pci_req_id_cache_extract(&dev->requester_id_cache);
-}
-
/* -1 for devfn means auto assign */
static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
const char *name, int devfn,
@@ -951,6 +847,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
PCIConfigReadFunc *config_read = pc->config_read;
PCIConfigWriteFunc *config_write = pc->config_write;
Error *local_err = NULL;
+ AddressSpace *dma_as;
DeviceState *dev = DEVICE(pci_dev);
pci_dev->bus = bus;
@@ -990,11 +887,15 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
}
pci_dev->devfn = devfn;
- pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev);
+ dma_as = pci_device_iommu_address_space(pci_dev);
+
+ memory_region_init_alias(&pci_dev->bus_master_enable_region,
+ OBJECT(pci_dev), "bus master",
+ dma_as->root, 0, memory_region_size(dma_as->root));
+ memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
+ address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,
+ name);
- if (qdev_hotplug) {
- pci_init_bus_master(pci_dev);
- }
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
pci_dev->irq_state = 0;
pci_config_alloc(pci_dev);
@@ -1076,7 +977,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
uint8_t type, MemoryRegion *memory)
{
PCIIORegion *r;
- uint32_t addr; /* offset in pci config space */
+ uint32_t addr;
uint64_t wmask;
pcibus_t size = memory_region_size(memory);
@@ -1092,20 +993,15 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
r->addr = PCI_BAR_UNMAPPED;
r->size = size;
r->type = type;
- r->memory = memory;
- r->address_space = type & PCI_BASE_ADDRESS_SPACE_IO
- ? pci_dev->bus->address_space_io
- : pci_dev->bus->address_space_mem;
+ r->memory = NULL;
wmask = ~(size - 1);
+ addr = pci_bar(pci_dev, region_num);
if (region_num == PCI_ROM_SLOT) {
/* ROM enable bit is writable */
wmask |= PCI_ROM_ADDRESS_ENABLE;
}
-
- addr = pci_bar(pci_dev, region_num);
pci_set_long(pci_dev->config + addr, type);
-
if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
pci_set_quad(pci_dev->wmask + addr, wmask);
@@ -1114,6 +1010,11 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
pci_set_long(pci_dev->cmask + addr, 0xffffffff);
}
+ pci_dev->io_regions[region_num].memory = memory;
+ pci_dev->io_regions[region_num].address_space
+ = type & PCI_BASE_ADDRESS_SPACE_IO
+ ? pci_dev->bus->address_space_io
+ : pci_dev->bus->address_space_mem;
}
static void pci_update_vga(PCIDevice *pci_dev)
@@ -2253,8 +2154,10 @@ int pci_add_capability2(PCIDevice *pdev, uint8_t cap_id,
if (!offset) {
offset = pci_find_space(pdev, size);
- /* out of PCI config space is programming error */
- assert(offset);
+ if (!offset) {
+ error_setg(errp, "out of PCI config space");
+ return -ENOSPC;
+ }
} else {
/* Verify that capabilities don't overlap. Note: device assignment
* depends on this check to verify that the device is not broken.
@@ -2535,13 +2438,13 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
if (limit >= base) {
Range pref_range;
- range_set_bounds(&pref_range, base, limit);
+ pref_range.begin = base;
+ pref_range.end = limit + 1;
range_extend(range, &pref_range);
}
}
for (i = 0; i < PCI_NUM_REGIONS; ++i) {
PCIIORegion *r = &dev->io_regions[i];
- pcibus_t lob, upb;
Range region_range;
if (!r->size ||
@@ -2549,17 +2452,16 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
continue;
}
+ region_range.begin = pci_bar_address(dev, i, r->type, r->size);
+ region_range.end = region_range.begin + r->size;
- lob = pci_bar_address(dev, i, r->type, r->size);
- upb = lob + r->size - 1;
- if (lob == PCI_BAR_UNMAPPED) {
+ if (region_range.begin == PCI_BAR_UNMAPPED) {
continue;
}
- lob = MAX(lob, 0x1ULL << 32);
+ region_range.begin = MAX(region_range.begin, 0x1ULL << 32);
- if (upb >= lob) {
- range_set_bounds(&region_range, lob, upb);
+ if (region_range.end - 1 >= region_range.begin) {
range_extend(range, &region_range);
}
}
@@ -2567,7 +2469,7 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
void pci_bus_get_w64_range(PCIBus *bus, Range *range)
{
- range_make_empty(range);
+ range->begin = range->end = 0;
pci_for_each_device_under_bus(bus, pci_dev_get_w64, range);
}
@@ -2598,21 +2500,6 @@ PCIDevice *pci_get_function_0(PCIDevice *pci_dev)
}
}
-MSIMessage pci_get_msi_message(PCIDevice *dev, int vector)
-{
- MSIMessage msg;
- if (msix_enabled(dev)) {
- msg = msix_get_message(dev, vector);
- } else if (msi_enabled(dev)) {
- msg = msi_get_message(dev, vector);
- } else {
- /* Should never happen */
- error_report("%s: unknown interrupt type", __func__);
- abort();
- }
- return msg;
-}
-
static const TypeInfo pci_device_type_info = {
.name = TYPE_PCI_DEVICE,
.parent = TYPE_DEVICE,
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 99cfb4561..c85b4f7ae 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -43,18 +43,28 @@
/***************************************************************************
* pci express capability helper functions
*/
-
-static void
-pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
+int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
{
- uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
- uint8_t *cmask = dev->cmask + dev->exp.exp_cap;
+ int pos;
+ uint8_t *exp_cap;
+ uint8_t *cmask;
+
+ assert(pci_is_express(dev));
+
+ pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
+ PCI_EXP_VER2_SIZEOF);
+ if (pos < 0) {
+ return pos;
+ }
+ dev->exp.exp_cap = pos;
+ exp_cap = dev->config + pos;
+ cmask = dev->cmask + pos;
/* capability register
- interrupt message number defaults to 0 */
+ interrupt message number defaults to 0 */
pci_set_word(exp_cap + PCI_EXP_FLAGS,
((type << PCI_EXP_FLAGS_TYPE_SHIFT) & PCI_EXP_FLAGS_TYPE) |
- version);
+ PCI_EXP_FLAGS_VER2);
/* device capability register
* table 7-12:
@@ -84,27 +94,7 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
* Let's not bother checking.
*/
pci_set_word(cmask + PCI_EXP_LNKSTA, 0);
-}
-int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
-{
- /* PCIe cap v2 init */
- int pos;
- uint8_t *exp_cap;
-
- assert(pci_is_express(dev));
-
- pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset, PCI_EXP_VER2_SIZEOF);
- if (pos < 0) {
- return pos;
- }
- dev->exp.exp_cap = pos;
- exp_cap = dev->config + pos;
-
- /* Filling values common with v1 */
- pcie_cap_v1_fill(dev, port, type, PCI_EXP_FLAGS_VER2);
-
- /* Filling v2 specific values */
pci_set_long(exp_cap + PCI_EXP_DEVCAP2,
PCI_EXP_DEVCAP2_EFF | PCI_EXP_DEVCAP2_EETLPP);
@@ -112,27 +102,7 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
return pos;
}
-int pcie_cap_v1_init(PCIDevice *dev, uint8_t offset, uint8_t type,
- uint8_t port)
-{
- /* PCIe cap v1 init */
- int pos;
-
- assert(pci_is_express(dev));
-
- pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset, PCI_EXP_VER1_SIZEOF);
- if (pos < 0) {
- return pos;
- }
- dev->exp.exp_cap = pos;
-
- pcie_cap_v1_fill(dev, port, type, PCI_EXP_FLAGS_VER1);
-
- return pos;
-}
-
-static int
-pcie_endpoint_cap_common_init(PCIDevice *dev, uint8_t offset, uint8_t cap_size)
+int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset)
{
uint8_t type = PCI_EXP_TYPE_ENDPOINT;
@@ -145,19 +115,7 @@ pcie_endpoint_cap_common_init(PCIDevice *dev, uint8_t offset, uint8_t cap_size)
type = PCI_EXP_TYPE_RC_END;
}
- return (cap_size == PCI_EXP_VER1_SIZEOF)
- ? pcie_cap_v1_init(dev, offset, type, 0)
- : pcie_cap_init(dev, offset, type, 0);
-}
-
-int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset)
-{
- return pcie_endpoint_cap_common_init(dev, offset, PCI_EXP_VER2_SIZEOF);
-}
-
-int pcie_endpoint_cap_v1_init(PCIDevice *dev, uint8_t offset)
-{
- return pcie_endpoint_cap_common_init(dev, offset, PCI_EXP_VER1_SIZEOF);
+ return pcie_cap_init(dev, offset, type, 0);
}
void pcie_cap_exit(PCIDevice *dev)
@@ -165,11 +123,6 @@ void pcie_cap_exit(PCIDevice *dev)
pci_del_capability(dev, PCI_CAP_ID_EXP, PCI_EXP_VER2_SIZEOF);
}
-void pcie_cap_v1_exit(PCIDevice *dev)
-{
- pci_del_capability(dev, PCI_CAP_ID_EXP, PCI_EXP_VER1_SIZEOF);
-}
-
uint8_t pcie_cap_get_type(const PCIDevice *dev)
{
uint32_t pos = dev->exp.exp_cap;
@@ -707,13 +660,3 @@ void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn)
offset, PCI_ARI_SIZEOF);
pci_set_long(dev->config + offset + PCI_ARI_CAP, (nextfn & 0xff) << 8);
}
-
-void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num)
-{
- static const int pci_dsn_ver = 1;
- static const int pci_dsn_cap = 4;
-
- pcie_add_capability(dev, PCI_EXT_CAP_ID_DSN, pci_dsn_ver, offset,
- PCI_EXT_CAP_DSN_SIZEOF);
- pci_set_quad(dev->config + offset + pci_dsn_cap, ser_num);
-}
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index 048ce6a42..e2d4e68ba 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -21,7 +21,6 @@
#include "qemu/osdep.h"
#include "sysemu/sysemu.h"
#include "qapi/qmp/types.h"
-#include "qapi/qmp/qjson.h"
#include "monitor/monitor.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pcie.h"
diff --git a/hw/pci/trace-events b/hw/pci/trace-events
deleted file mode 100644
index 2b9cf2440..000000000
--- a/hw/pci/trace-events
+++ /dev/null
@@ -1,9 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/pci/pci.c
-pci_update_mappings_del(void *d, uint32_t bus, uint32_t slot, uint32_t func, int bar, uint64_t addr, uint64_t size) "d=%p %02x:%02x.%x %d,%#"PRIx64"+%#"PRIx64
-pci_update_mappings_add(void *d, uint32_t bus, uint32_t slot, uint32_t func, int bar, uint64_t addr, uint64_t size) "d=%p %02x:%02x.%x %d,%#"PRIx64"+%#"PRIx64
-
-# hw/pci/pci_host.c
-pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x -> 0x%x"
-pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x <- 0x%x"
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 91a3420f4..c1ffc7771 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -4,11 +4,9 @@ obj-y += ppc.o ppc_booke.o
obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
-obj-$(CONFIG_PSERIES) += spapr_cpu_core.o
ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
obj-y += spapr_pci_vfio.o
endif
-obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
# PowerPC 4xx boards
obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
obj-y += ppc4xx_pci.o
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 0cd534df5..ee1c60b82 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -601,7 +601,7 @@ static int ppce500_prep_device_tree(MachineState *machine,
}
/* Create -kernel TLB entries for BookE. */
-hwaddr booke206_page_size_to_tlb(uint64_t size)
+static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
{
return 63 - clz64(size >> 10);
}
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index 70ba1d8f4..ef224ea5e 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -26,6 +26,4 @@ typedef struct PPCE500Params {
void ppce500_init(MachineState *machine, PPCE500Params *params);
-hwaddr booke206_page_size_to_tlb(uint64_t size);
-
#endif
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index 94b454551..b00565c3d 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -14,7 +14,6 @@
#include "e500.h"
#include "hw/boards.h"
#include "sysemu/device_tree.h"
-#include "sysemu/kvm.h"
#include "hw/pci/pci.h"
#include "hw/ppc/openpic.h"
#include "kvm_ppc.h"
diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 20cbddb4e..5764b86c2 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -22,9 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-
-#ifndef PPC_MAC_H
-#define PPC_MAC_H
+#if !defined(__PPC_MAC_H__)
+#define __PPC_MAC_H__
#include "exec/memory.h"
#include "hw/sysbus.h"
@@ -185,4 +184,4 @@ typedef struct MacIONVRAMState {
} MacIONVRAMState;
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
-#endif /* PPC_MAC_H */
+#endif /* !defined(__PPC_MAC_H__) */
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 7d2510658..32e88b378 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -380,7 +380,6 @@ static void ppc_core99_init(MachineState *machine)
pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io());
machine_arch = ARCH_MAC99;
}
- object_property_set_bool(OBJECT(pci_bus), true, "realized", &error_abort);
machine->usb |= defaults_enabled() && !machine->usb_disabled;
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 447948746..a9bb1c27d 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -309,7 +309,7 @@ static void ppc_heathrow_init(MachineState *machine)
dev = qdev_create(adb_bus, TYPE_ADB_MOUSE);
qdev_init_nofail(dev);
- if (machine_usb(machine)) {
+ if (usb_enabled()) {
pci_create_simple(pci_bus, -1, "pci-ohci");
}
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 894586900..38ff2e159 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -33,7 +33,6 @@
#include "hw/timer/m48t59.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
-#include "qapi/error.h"
#include "hw/loader.h"
#include "sysemu/kvm.h"
#include "kvm_ppc.h"
@@ -165,9 +164,9 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
}
}
-void ppc6xx_irq_init(PowerPCCPU *cpu)
+void ppc6xx_irq_init(CPUPPCState *env)
{
- CPUPPCState *env = &cpu->env;
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu,
PPC6xx_INPUT_NB);
@@ -252,9 +251,9 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
}
}
-void ppc970_irq_init(PowerPCCPU *cpu)
+void ppc970_irq_init(CPUPPCState *env)
{
- CPUPPCState *env = &cpu->env;
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu,
PPC970_INPUT_NB);
@@ -288,9 +287,9 @@ static void power7_set_irq(void *opaque, int pin, int level)
}
}
-void ppcPOWER7_irq_init(PowerPCCPU *cpu)
+void ppcPOWER7_irq_init(CPUPPCState *env)
{
- CPUPPCState *env = &cpu->env;
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
POWER7_INPUT_NB);
@@ -373,9 +372,9 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
}
}
-void ppc40x_irq_init(PowerPCCPU *cpu)
+void ppc40x_irq_init(CPUPPCState *env)
{
- CPUPPCState *env = &cpu->env;
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
cpu, PPC40x_INPUT_NB);
@@ -437,9 +436,9 @@ static void ppce500_set_irq(void *opaque, int pin, int level)
}
}
-void ppce500_irq_init(PowerPCCPU *cpu)
+void ppce500_irq_init(CPUPPCState *env)
{
- CPUPPCState *env = &cpu->env;
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
cpu, PPCE500_INPUT_NB);
@@ -700,18 +699,9 @@ static inline void cpu_ppc_decr_lower(PowerPCCPU *cpu)
static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
{
- CPUPPCState *env = &cpu->env;
-
/* Raise it */
- LOG_TB("raise hv decrementer exception\n");
-
- /* The architecture specifies that we don't deliver HDEC
- * interrupts in a PM state. Not only they don't cause a
- * wakeup but they also get effectively discarded.
- */
- if (!env->in_pm_state) {
- ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
- }
+ LOG_TB("raise decrementer exception\n");
+ ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
}
static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu)
@@ -890,7 +880,7 @@ static int timebase_post_load(void *opaque, int version_id)
host_ns = qemu_clock_get_ns(QEMU_CLOCK_HOST);
ns_diff = MAX(0, host_ns - tb_remote->time_of_the_day_ns);
migration_duration_ns = MIN(NANOSECONDS_PER_SECOND, ns_diff);
- migration_duration_tb = muldiv64(freq, migration_duration_ns,
+ migration_duration_tb = muldiv64(migration_duration_ns, freq,
NANOSECONDS_PER_SECOND);
guest_tb = tb_remote->guest_timebase + MIN(0, migration_duration_tb);
@@ -938,7 +928,9 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
}
/* Create new timer */
tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu);
- if (env->has_hv_mode) {
+ if (0) {
+ /* XXX: find a suitable condition to enable the hypervisor decrementer
+ */
tb_env->hdecr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_hdecr_cb,
cpu);
} else {
@@ -1351,28 +1343,3 @@ PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id)
return NULL;
}
-
-void ppc_cpu_parse_features(const char *cpu_model)
-{
- CPUClass *cc;
- ObjectClass *oc;
- const char *typename;
- gchar **model_pieces;
-
- model_pieces = g_strsplit(cpu_model, ",", 2);
- if (!model_pieces[0]) {
- error_report("Invalid/empty CPU model name");
- exit(1);
- }
-
- oc = cpu_class_by_name(TYPE_POWERPC_CPU, model_pieces[0]);
- if (oc == NULL) {
- error_report("Unable to find CPU definition: %s", model_pieces[0]);
- exit(1);
- }
-
- typename = object_class_get_name(oc);
- cc = CPU_CLASS(oc);
- cc->parse_features(typename, model_pieces[1], &error_fatal);
- g_strfreev(model_pieces);
-}
diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index c67febca2..1c5f04fae 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -22,8 +22,8 @@
* THE SOFTWARE.
*/
-#ifndef PPC405_H
-#define PPC405_H
+#if !defined(PPC_405_H)
+#define PPC_405_H
#include "hw/ppc/ppc4xx.h"
@@ -78,4 +78,4 @@ CPUPPCState *ppc_stb025_init (MemoryRegion ram_memories[2],
uint32_t sysclk, qemu_irq **picp,
ram_addr_t *offsetp);
-#endif /* PPC405_H */
+#endif /* !defined(PPC_405_H) */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index e7f413e49..7d59018fc 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -22,7 +22,6 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
-#include "cpu.h"
#include "hw/hw.h"
#include "hw/ppc/ppc.h"
#include "hw/ppc/ppc4xx.h"
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
index 22c584eb8..76bd78bfd 100644
--- a/hw/ppc/ppce500_spin.c
+++ b/hw/ppc/ppce500_spin.c
@@ -32,7 +32,6 @@
#include "sysemu/sysemu.h"
#include "hw/sysbus.h"
#include "sysemu/kvm.h"
-#include "e500.h"
#define MAX_CPUS 32
@@ -73,6 +72,12 @@ static void spin_reset(void *opaque)
}
}
+/* Create -kernel TLB entries for BookE, linearly spanning 256MB. */
+static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
+{
+ return ctz32(size >> 10) >> 1;
+}
+
static void mmubooke_create_initial_mapping(CPUPPCState *env,
target_ulong va,
hwaddr pa,
@@ -99,7 +104,7 @@ static void spin_kick(void *data)
hwaddr map_start;
cpu_synchronize_state(cpu);
- stl_p(&curspin->pir, env->spr[SPR_BOOKE_PIR]);
+ stl_p(&curspin->pir, env->spr[SPR_PIR]);
env->nip = ldq_p(&curspin->addr) & (map_size - 1);
env->gpr[3] = ldq_p(&curspin->r3);
env->gpr[4] = 0;
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 054af1e8b..3ffb85e60 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -22,7 +22,6 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
-#include "cpu.h"
#include "hw/hw.h"
#include "hw/timer/m48t59.h"
#include "hw/i386/pc.h"
@@ -649,7 +648,7 @@ static void ppc_prep_init(MachineState *machine)
memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr);
#endif
- if (machine_usb(machine)) {
+ if (usb_enabled()) {
pci_create_simple(pci_bus, -1, "pci-ohci");
}
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 30d6800ab..b69995e0d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -29,7 +29,6 @@
#include "sysemu/sysemu.h"
#include "sysemu/numa.h"
#include "hw/hw.h"
-#include "qemu/log.h"
#include "hw/fw-path-provider.h"
#include "elf.h"
#include "net/net.h"
@@ -66,8 +65,6 @@
#include "hw/compat.h"
#include "qemu/cutils.h"
-#include "hw/ppc/spapr_cpu_core.h"
-#include "qmp-commands.h"
#include <libfdt.h>
@@ -91,6 +88,8 @@
#define MIN_RMA_SLOF 128UL
+#define TIMEBASE_FREQ 512000000ULL
+
#define PHANDLE_XICP 0x00001111
#define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift))
@@ -116,16 +115,15 @@ static XICSState *try_create_xics(const char *type, int nr_servers,
static XICSState *xics_system_init(MachineState *machine,
int nr_servers, int nr_irqs, Error **errp)
{
- XICSState *xics = NULL;
+ XICSState *icp = NULL;
if (kvm_enabled()) {
Error *err = NULL;
if (machine_kernel_irqchip_allowed(machine)) {
- xics = try_create_xics(TYPE_XICS_SPAPR_KVM, nr_servers, nr_irqs,
- &err);
+ icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs, &err);
}
- if (machine_kernel_irqchip_required(machine) && !xics) {
+ if (machine_kernel_irqchip_required(machine) && !icp) {
error_reportf_err(err,
"kernel_irqchip requested but unavailable: ");
} else {
@@ -133,11 +131,11 @@ static XICSState *xics_system_init(MachineState *machine,
}
}
- if (!xics) {
- xics = try_create_xics(TYPE_XICS_SPAPR, nr_servers, nr_irqs, errp);
+ if (!icp) {
+ icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs, errp);
}
- return xics;
+ return icp;
}
static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
@@ -340,9 +338,6 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
add_str(hypertas, "hcall-splpar");
add_str(hypertas, "hcall-bulk");
add_str(hypertas, "hcall-set-mode");
- add_str(hypertas, "hcall-sprg0");
- add_str(hypertas, "hcall-copy");
- add_str(hypertas, "hcall-debug");
add_str(qemu_hypertas, "hcall-memop1");
fdt = g_malloc0(FDT_MAX_SIZE);
@@ -603,23 +598,12 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
int index = ppc_get_vcpu_dt_id(cpu);
uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
0xffffffff, 0xffffffff};
- uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq()
- : SPAPR_TIMEBASE_FREQ;
+ uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
uint32_t page_sizes_prop[64];
size_t page_sizes_prop_size;
uint32_t vcpus_per_socket = smp_threads * smp_cores;
uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
- sPAPRDRConnector *drc;
- sPAPRDRConnectorClass *drck;
- int drc_index;
-
- drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index);
- if (drc) {
- drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
- drc_index = drck->get_index(drc);
- _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)));
- }
/* Note: we keep CI large pages off for now because a 64K capable guest
* provisioned with large pages might otherwise try to map a qemu
@@ -777,17 +761,14 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
int ret, i, offset;
uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
- uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size;
- uint32_t nr_lmbs = (spapr->hotplug_memory.base +
- memory_region_size(&spapr->hotplug_memory.mr)) /
- lmb_size;
+ uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size;
uint32_t *int_buf, *cur_index, buf_len;
int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
/*
- * Don't create the node if there is no hotpluggable memory
+ * Don't create the node if there are no DR LMBs.
*/
- if (machine->ram_size == machine->maxram_size) {
+ if (!nr_lmbs) {
return 0;
}
@@ -821,40 +802,26 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
int_buf[0] = cpu_to_be32(nr_lmbs);
cur_index++;
for (i = 0; i < nr_lmbs; i++) {
- uint64_t addr = i * lmb_size;
+ sPAPRDRConnector *drc;
+ sPAPRDRConnectorClass *drck;
+ uint64_t addr = i * lmb_size + spapr->hotplug_memory.base;;
uint32_t *dynamic_memory = cur_index;
- if (i >= hotplug_lmb_start) {
- sPAPRDRConnector *drc;
- sPAPRDRConnectorClass *drck;
-
- drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i);
- g_assert(drc);
- drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
-
- dynamic_memory[0] = cpu_to_be32(addr >> 32);
- dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
- dynamic_memory[2] = cpu_to_be32(drck->get_index(drc));
- dynamic_memory[3] = cpu_to_be32(0); /* reserved */
- dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL));
- if (memory_region_present(get_system_memory(), addr)) {
- dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED);
- } else {
- dynamic_memory[5] = cpu_to_be32(0);
- }
+ drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
+ addr/lmb_size);
+ g_assert(drc);
+ drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+
+ dynamic_memory[0] = cpu_to_be32(addr >> 32);
+ dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
+ dynamic_memory[2] = cpu_to_be32(drck->get_index(drc));
+ dynamic_memory[3] = cpu_to_be32(0); /* reserved */
+ dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL));
+ if (addr < machine->ram_size ||
+ memory_region_present(get_system_memory(), addr)) {
+ dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED);
} else {
- /*
- * LMB information for RMA, boot time RAM and gap b/n RAM and
- * hotplug memory region -- all these are marked as reserved
- * and as having no valid DRC.
- */
- dynamic_memory[0] = cpu_to_be32(addr >> 32);
- dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
- dynamic_memory[2] = cpu_to_be32(0);
- dynamic_memory[3] = cpu_to_be32(0); /* reserved */
- dynamic_memory[4] = cpu_to_be32(-1);
- dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED |
- SPAPR_LMB_FLAGS_DRC_INVALID);
+ dynamic_memory[5] = cpu_to_be32(0);
}
cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE;
@@ -938,7 +905,6 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr,
hwaddr rtas_size)
{
MachineState *machine = MACHINE(qdev_get_machine());
- MachineClass *mc = MACHINE_GET_CLASS(machine);
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
const char *boot_device = machine->boot_order;
int ret, i;
@@ -1021,16 +987,6 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr,
_FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
}
- if (mc->query_hotpluggable_cpus) {
- int offset = fdt_path_offset(fdt, "/cpus");
- ret = spapr_drc_populate_dt(fdt, offset, NULL,
- SPAPR_DR_CONNECTOR_TYPE_CPU);
- if (ret < 0) {
- error_report("Couldn't set up CPU DR device tree properties");
- exit(1);
- }
- }
-
_FDT((fdt_pack(fdt)));
if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
@@ -1224,6 +1180,26 @@ static void ppc_spapr_reset(void)
}
+static void spapr_cpu_reset(void *opaque)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+ PowerPCCPU *cpu = opaque;
+ CPUState *cs = CPU(cpu);
+ CPUPPCState *env = &cpu->env;
+
+ cpu_reset(cs);
+
+ /* All CPUs start halted. CPU0 is unhalted from the machine level
+ * reset code and the rest are explicitly started up by the guest
+ * using an RTAS call */
+ cs->halted = 1;
+
+ env->spr[SPR_HIOR] = 0;
+
+ ppc_hash64_set_external_hpt(cpu, spapr->htab, spapr->htab_shift,
+ &error_fatal);
+}
+
static void spapr_create_nvram(sPAPRMachineState *spapr)
{
DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
@@ -1513,6 +1489,7 @@ static int htab_save_complete(QEMUFile *f, void *opaque)
if (rc < 0) {
return rc;
}
+ close_htab_fd(spapr);
} else {
if (spapr->htab_first_pass) {
htab_save_first_pass(f, spapr, -1);
@@ -1614,18 +1591,10 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
-static void htab_cleanup(void *opaque)
-{
- sPAPRMachineState *spapr = opaque;
-
- close_htab_fd(spapr);
-}
-
static SaveVMHandlers savevm_htab_handlers = {
.save_live_setup = htab_save_setup,
.save_live_iterate = htab_save_iterate,
.save_live_complete_precopy = htab_save_complete,
- .cleanup = htab_cleanup,
.load_state = htab_load,
};
@@ -1636,6 +1605,32 @@ static void spapr_boot_set(void *opaque, const char *boot_device,
machine->boot_order = g_strdup(boot_device);
}
+static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
+ Error **errp)
+{
+ CPUPPCState *env = &cpu->env;
+
+ /* Set time-base frequency to 512 MHz */
+ cpu_ppc_tb_init(env, TIMEBASE_FREQ);
+
+ /* Enable PAPR mode in TCG or KVM */
+ cpu_ppc_set_papr(cpu);
+
+ if (cpu->max_compat) {
+ Error *local_err = NULL;
+
+ ppc_set_compat(cpu, cpu->max_compat, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+
+ xics_cpu_setup(spapr->icp, cpu);
+
+ qemu_register_reset(spapr_cpu_reset, cpu);
+}
+
/*
* Reset routine for LMB DR devices.
*
@@ -1713,11 +1708,11 @@ static void spapr_validate_node_memory(MachineState *machine, Error **errp)
static void ppc_spapr_init(MachineState *machine)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
- MachineClass *mc = MACHINE_GET_CLASS(machine);
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
const char *kernel_filename = machine->kernel_filename;
const char *kernel_cmdline = machine->kernel_cmdline;
const char *initrd_filename = machine->initrd_filename;
+ PowerPCCPU *cpu;
PCIHostState *phb;
int i;
MemoryRegion *sysmem = get_system_memory();
@@ -1731,22 +1726,6 @@ static void ppc_spapr_init(MachineState *machine)
long load_limit, fw_size;
bool kernel_le = false;
char *filename;
- int smt = kvmppc_smt_threads();
- int spapr_cores = smp_cpus / smp_threads;
- int spapr_max_cores = max_cpus / smp_threads;
-
- if (mc->query_hotpluggable_cpus) {
- if (smp_cpus % smp_threads) {
- error_report("smp_cpus (%u) must be multiple of threads (%u)",
- smp_cpus, smp_threads);
- exit(1);
- }
- if (max_cpus % smp_threads) {
- error_report("max_cpus (%u) must be multiple of threads (%u)",
- max_cpus, smp_threads);
- exit(1);
- }
- }
msi_nonbroken = true;
@@ -1780,13 +1759,6 @@ static void ppc_spapr_init(MachineState *machine)
spapr->vrma_adjust = 1;
spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
}
-
- /* Actually we don't support unbounded RMA anymore since we
- * added proper emulation of HV mode. The max we can get is
- * 16G which also happens to be what we configure for PAPR
- * mode so make sure we don't do anything bigger than that
- */
- spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull);
}
if (spapr->rma_size > node0_size) {
@@ -1799,9 +1771,10 @@ static void ppc_spapr_init(MachineState *machine)
load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD;
/* Set up Interrupt Controller before we create the VCPUs */
- spapr->xics = xics_system_init(machine,
- DIV_ROUND_UP(max_cpus * smt, smp_threads),
- XICS_IRQS_SPAPR, &error_fatal);
+ spapr->icp = xics_system_init(machine,
+ DIV_ROUND_UP(max_cpus * kvmppc_smt_threads(),
+ smp_threads),
+ XICS_IRQS, &error_fatal);
if (smc->dr_lmb_enabled) {
spapr_validate_node_memory(machine, &error_fatal);
@@ -1811,46 +1784,13 @@ static void ppc_spapr_init(MachineState *machine)
if (machine->cpu_model == NULL) {
machine->cpu_model = kvm_enabled() ? "host" : "POWER7";
}
-
- ppc_cpu_parse_features(machine->cpu_model);
-
- if (mc->query_hotpluggable_cpus) {
- char *type = spapr_get_cpu_core_type(machine->cpu_model);
-
- if (type == NULL) {
- error_report("Unable to find sPAPR CPU Core definition");
+ for (i = 0; i < smp_cpus; i++) {
+ cpu = cpu_ppc_init(machine->cpu_model);
+ if (cpu == NULL) {
+ error_report("Unable to find PowerPC CPU definition");
exit(1);
}
-
- spapr->cores = g_new0(Object *, spapr_max_cores);
- for (i = 0; i < spapr_max_cores; i++) {
- int core_id = i * smp_threads;
- sPAPRDRConnector *drc =
- spapr_dr_connector_new(OBJECT(spapr),
- SPAPR_DR_CONNECTOR_TYPE_CPU,
- (core_id / smp_threads) * smt);
-
- qemu_register_reset(spapr_drc_reset, drc);
-
- if (i < spapr_cores) {
- Object *core = object_new(type);
- object_property_set_int(core, smp_threads, "nr-threads",
- &error_fatal);
- object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID,
- &error_fatal);
- object_property_set_bool(core, true, "realized", &error_fatal);
- }
- }
- g_free(type);
- } else {
- for (i = 0; i < smp_cpus; i++) {
- PowerPCCPU *cpu = cpu_ppc_init(machine->cpu_model);
- if (cpu == NULL) {
- error_report("Unable to find PowerPC CPU definition");
- exit(1);
- }
- spapr_cpu_init(spapr, cpu, &error_fatal);
- }
+ spapr_cpu_init(spapr, cpu, &error_fatal);
}
if (kvm_enabled()) {
@@ -1875,21 +1815,11 @@ static void ppc_spapr_init(MachineState *machine)
/* initialize hotplug memory address space */
if (machine->ram_size < machine->maxram_size) {
ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size;
- /*
- * Limit the number of hotpluggable memory slots to half the number
- * slots that KVM supports, leaving the other half for PCI and other
- * devices. However ensure that number of slots doesn't drop below 32.
- */
- int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 :
- SPAPR_MAX_RAM_SLOTS;
- if (max_memslots < SPAPR_MAX_RAM_SLOTS) {
- max_memslots = SPAPR_MAX_RAM_SLOTS;
- }
- if (machine->ram_slots > max_memslots) {
+ if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) {
error_report("Specified number of memory slots %"
PRIu64" exceeds max supported %d",
- machine->ram_slots, max_memslots);
+ machine->ram_slots, SPAPR_MAX_RAM_SLOTS);
exit(1);
}
@@ -1911,10 +1841,6 @@ static void ppc_spapr_init(MachineState *machine)
exit(1);
}
spapr->rtas_size = get_image_size(filename);
- if (spapr->rtas_size < 0) {
- error_report("Could not get size of LPAR rtas '%s'", filename);
- exit(1);
- }
spapr->rtas_blob = g_malloc(spapr->rtas_size);
if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) {
error_report("Could not load LPAR rtas '%s'", filename);
@@ -2205,6 +2131,15 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size,
int i, fdt_offset, fdt_size;
void *fdt;
+ /*
+ * Check for DRC connectors and send hotplug notification to the
+ * guest only in case of hotplugged memory. This allows cold plugged
+ * memory to be specified at boot time.
+ */
+ if (!dev->hotplugged) {
+ return;
+ }
+
for (i = 0; i < nr_lmbs; i++) {
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
addr/SPAPR_MEMORY_BLOCK_SIZE);
@@ -2218,12 +2153,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size,
drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp);
addr += SPAPR_MEMORY_BLOCK_SIZE;
}
- /* send hotplug notification to the
- * guest only in case of hotplugged memory
- */
- if (dev->hotplugged) {
- spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs);
- }
+ spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs);
}
static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
@@ -2261,27 +2191,6 @@ out:
error_propagate(errp, local_err);
}
-void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
- sPAPRMachineState *spapr)
-{
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- DeviceClass *dc = DEVICE_GET_CLASS(cs);
- int id = ppc_get_vcpu_dt_id(cpu);
- void *fdt;
- int offset, fdt_size;
- char *nodename;
-
- fdt = create_device_tree(&fdt_size);
- nodename = g_strdup_printf("%s@%x", dc->fw_name, id);
- offset = fdt_add_subnode(fdt, 0, nodename);
-
- spapr_populate_cpu_dt(cs, fdt, offset, spapr);
- g_free(nodename);
-
- *fdt_offset = offset;
- return fdt;
-}
-
static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
@@ -2326,40 +2235,21 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
}
spapr_memory_plug(hotplug_dev, dev, node, errp);
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
- spapr_core_plug(hotplug_dev, dev, errp);
}
}
static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
-
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
error_setg(errp, "Memory hot unplug not supported by sPAPR");
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
- if (!mc->query_hotpluggable_cpus) {
- error_setg(errp, "CPU hot unplug not supported on this machine");
- return;
- }
- spapr_core_unplug(hotplug_dev, dev, errp);
- }
-}
-
-static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
- spapr_core_pre_plug(hotplug_dev, dev, errp);
}
}
static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine,
DeviceState *dev)
{
- if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
- object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
return HOTPLUG_HANDLER(machine);
}
return NULL;
@@ -2372,37 +2262,6 @@ static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index)
return cpu_index / smp_threads / smp_cores;
}
-static HotpluggableCPUList *spapr_query_hotpluggable_cpus(MachineState *machine)
-{
- int i;
- HotpluggableCPUList *head = NULL;
- sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
- int spapr_max_cores = max_cpus / smp_threads;
-
- for (i = 0; i < spapr_max_cores; i++) {
- HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
- HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
- CpuInstanceProperties *cpu_props = g_new0(typeof(*cpu_props), 1);
-
- cpu_item->type = spapr_get_cpu_core_type(machine->cpu_model);
- cpu_item->vcpus_count = smp_threads;
- cpu_props->has_core_id = true;
- cpu_props->core_id = i * smp_threads;
- /* TODO: add 'has_node/node' here to describe
- to which node core belongs */
-
- cpu_item->props = cpu_props;
- if (spapr->cores[i]) {
- cpu_item->has_qom_path = true;
- cpu_item->qom_path = object_get_canonical_path(spapr->cores[i]);
- }
- list_item->value = cpu_item;
- list_item->next = head;
- head = list_item;
- }
- return head;
-}
-
static void spapr_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -2429,13 +2288,11 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
mc->has_dynamic_sysbus = true;
mc->pci_allow_0_address = true;
mc->get_hotplug_handler = spapr_get_hotpug_handler;
- hc->pre_plug = spapr_machine_device_pre_plug;
hc->plug = spapr_machine_device_plug;
hc->unplug = spapr_machine_device_unplug;
mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id;
smc->dr_lmb_enabled = true;
- mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus;
fwc->get_dev_path = spapr_get_fw_dev_path;
nc->nmi_monitor_handler = spapr_nmi;
}
@@ -2486,42 +2343,18 @@ static const TypeInfo spapr_machine_info = {
type_init(spapr_machine_register_##suffix)
/*
- * pseries-2.7
- */
-static void spapr_machine_2_7_instance_options(MachineState *machine)
-{
-}
-
-static void spapr_machine_2_7_class_options(MachineClass *mc)
-{
- /* Defaults for the latest behaviour inherited from the base class */
-}
-
-DEFINE_SPAPR_MACHINE(2_7, "2.7", true);
-
-/*
* pseries-2.6
*/
-#define SPAPR_COMPAT_2_6 \
- HW_COMPAT_2_6 \
- { \
- .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\
- .property = "ddw",\
- .value = stringify(off),\
- },
-
static void spapr_machine_2_6_instance_options(MachineState *machine)
{
}
static void spapr_machine_2_6_class_options(MachineClass *mc)
{
- spapr_machine_2_7_class_options(mc);
- mc->query_hotpluggable_cpus = NULL;
- SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6);
+ /* Defaults for the latest behaviour inherited from the base class */
}
-DEFINE_SPAPR_MACHINE(2_6, "2.6", false);
+DEFINE_SPAPR_MACHINE(2_6, "2.6", true);
/*
* pseries-2.5
@@ -2553,6 +2386,7 @@ DEFINE_SPAPR_MACHINE(2_5, "2.5", false);
* pseries-2.4
*/
#define SPAPR_COMPAT_2_4 \
+ SPAPR_COMPAT_2_5 \
HW_COMPAT_2_4
static void spapr_machine_2_4_instance_options(MachineState *machine)
@@ -2575,6 +2409,7 @@ DEFINE_SPAPR_MACHINE(2_4, "2.4", false);
* pseries-2.3
*/
#define SPAPR_COMPAT_2_3 \
+ SPAPR_COMPAT_2_4 \
HW_COMPAT_2_3 \
{\
.driver = "spapr-pci-host-bridge",\
@@ -2602,6 +2437,7 @@ DEFINE_SPAPR_MACHINE(2_3, "2.3", false);
*/
#define SPAPR_COMPAT_2_2 \
+ SPAPR_COMPAT_2_3 \
HW_COMPAT_2_2 \
{\
.driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\
@@ -2626,6 +2462,7 @@ DEFINE_SPAPR_MACHINE(2_2, "2.2", false);
* pseries-2.1
*/
#define SPAPR_COMPAT_2_1 \
+ SPAPR_COMPAT_2_2 \
HW_COMPAT_2_1
static void spapr_machine_2_1_instance_options(MachineState *machine)
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
deleted file mode 100644
index bcb483dbe..000000000
--- a/hw/ppc/spapr_cpu_core.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * sPAPR CPU core device, acts as container of CPU thread devices.
- *
- * 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.
- */
-#include "hw/cpu/core.h"
-#include "hw/ppc/spapr_cpu_core.h"
-#include "target-ppc/cpu.h"
-#include "hw/ppc/spapr.h"
-#include "hw/boards.h"
-#include "qapi/error.h"
-#include "sysemu/cpus.h"
-#include "target-ppc/kvm_ppc.h"
-#include "hw/ppc/ppc.h"
-#include "target-ppc/mmu-hash64.h"
-#include "sysemu/numa.h"
-
-static void spapr_cpu_reset(void *opaque)
-{
- sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
- PowerPCCPU *cpu = opaque;
- CPUState *cs = CPU(cpu);
- CPUPPCState *env = &cpu->env;
-
- cpu_reset(cs);
-
- /* All CPUs start halted. CPU0 is unhalted from the machine level
- * reset code and the rest are explicitly started up by the guest
- * using an RTAS call */
- cs->halted = 1;
-
- env->spr[SPR_HIOR] = 0;
-
- ppc_hash64_set_external_hpt(cpu, spapr->htab, spapr->htab_shift,
- &error_fatal);
-}
-
-static void spapr_cpu_destroy(PowerPCCPU *cpu)
-{
- sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
-
- xics_cpu_destroy(spapr->xics, cpu);
- qemu_unregister_reset(spapr_cpu_reset, cpu);
-}
-
-void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp)
-{
- CPUPPCState *env = &cpu->env;
- CPUState *cs = CPU(cpu);
- int i;
-
- /* Set time-base frequency to 512 MHz */
- cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
-
- /* Enable PAPR mode in TCG or KVM */
- cpu_ppc_set_papr(cpu);
-
- if (cpu->max_compat) {
- Error *local_err = NULL;
-
- ppc_set_compat(cpu, cpu->max_compat, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- }
-
- /* Set NUMA node for the added CPUs */
- for (i = 0; i < nb_numa_nodes; i++) {
- if (test_bit(cs->cpu_index, numa_info[i].node_cpu)) {
- cs->numa_node = i;
- break;
- }
- }
-
- xics_cpu_setup(spapr->xics, cpu);
-
- qemu_register_reset(spapr_cpu_reset, cpu);
- spapr_cpu_reset(cpu);
-}
-
-/*
- * Return the sPAPR CPU core type for @model which essentially is the CPU
- * model specified with -cpu cmdline option.
- */
-char *spapr_get_cpu_core_type(const char *model)
-{
- char *core_type;
- gchar **model_pieces = g_strsplit(model, ",", 2);
-
- core_type = g_strdup_printf("%s-%s", model_pieces[0], TYPE_SPAPR_CPU_CORE);
- g_strfreev(model_pieces);
-
- /* Check whether it exists or whether we have to look up an alias name */
- if (!object_class_by_name(core_type)) {
- const char *realmodel;
-
- g_free(core_type);
- realmodel = ppc_cpu_lookup_alias(model);
- if (realmodel) {
- return spapr_get_cpu_core_type(realmodel);
- }
- return NULL;
- }
-
- return core_type;
-}
-
-static void spapr_core_release(DeviceState *dev, void *opaque)
-{
- sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
- const char *typename = object_class_get_name(sc->cpu_class);
- size_t size = object_type_get_instance_size(typename);
- sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
- CPUCore *cc = CPU_CORE(dev);
- int i;
-
- for (i = 0; i < cc->nr_threads; i++) {
- void *obj = sc->threads + i * size;
- DeviceState *dev = DEVICE(obj);
- CPUState *cs = CPU(dev);
- PowerPCCPU *cpu = POWERPC_CPU(cs);
-
- spapr_cpu_destroy(cpu);
- cpu_remove_sync(cs);
- object_unparent(obj);
- }
-
- spapr->cores[cc->core_id / smp_threads] = NULL;
-
- g_free(sc->threads);
- object_unparent(OBJECT(dev));
-}
-
-void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
-{
- CPUCore *cc = CPU_CORE(dev);
- int smt = kvmppc_smt_threads();
- int index = cc->core_id / smp_threads;
- sPAPRDRConnector *drc =
- spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt);
- sPAPRDRConnectorClass *drck;
- Error *local_err = NULL;
-
- if (index == 0) {
- error_setg(errp, "Boot CPU core may not be unplugged");
- return;
- }
-
- g_assert(drc);
-
- drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
- drck->detach(drc, dev, spapr_core_release, NULL, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- spapr_hotplug_req_remove_by_index(drc);
-}
-
-void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
-{
- sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
- sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
- CPUCore *cc = CPU_CORE(dev);
- CPUState *cs = CPU(core->threads);
- sPAPRDRConnector *drc;
- sPAPRDRConnectorClass *drck;
- Error *local_err = NULL;
- void *fdt = NULL;
- int fdt_offset = 0;
- int index = cc->core_id / smp_threads;
- int smt = kvmppc_smt_threads();
-
- drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt);
- spapr->cores[index] = OBJECT(dev);
-
- g_assert(drc);
-
- /*
- * Setup CPU DT entries only for hotplugged CPUs. For boot time or
- * coldplugged CPUs DT entries are setup in spapr_finalize_fdt().
- */
- if (dev->hotplugged) {
- fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr);
- }
-
- drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
- drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, &local_err);
- if (local_err) {
- g_free(fdt);
- spapr->cores[index] = NULL;
- error_propagate(errp, local_err);
- return;
- }
-
- if (dev->hotplugged) {
- /*
- * Send hotplug notification interrupt to the guest only in case
- * of hotplugged CPUs.
- */
- spapr_hotplug_req_add_by_index(drc);
- } else {
- /*
- * Set the right DRC states for cold plugged CPU.
- */
- drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE);
- drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED);
- }
-}
-
-void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
-{
- MachineState *machine = MACHINE(OBJECT(hotplug_dev));
- MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
- sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
- int spapr_max_cores = max_cpus / smp_threads;
- int index;
- Error *local_err = NULL;
- CPUCore *cc = CPU_CORE(dev);
- char *base_core_type = spapr_get_cpu_core_type(machine->cpu_model);
- const char *type = object_get_typename(OBJECT(dev));
-
- if (!mc->query_hotpluggable_cpus) {
- error_setg(&local_err, "CPU hotplug not supported for this machine");
- goto out;
- }
-
- if (strcmp(base_core_type, type)) {
- error_setg(&local_err, "CPU core type should be %s", base_core_type);
- goto out;
- }
-
- if (cc->nr_threads != smp_threads) {
- error_setg(&local_err, "threads must be %d", smp_threads);
- goto out;
- }
-
- if (cc->core_id % smp_threads) {
- error_setg(&local_err, "invalid core id %d", cc->core_id);
- goto out;
- }
-
- index = cc->core_id / smp_threads;
- if (index < 0 || index >= spapr_max_cores) {
- error_setg(&local_err, "core id %d out of range", cc->core_id);
- goto out;
- }
-
- if (spapr->cores[index]) {
- error_setg(&local_err, "core %d already populated", cc->core_id);
- goto out;
- }
-
-out:
- g_free(base_core_type);
- error_propagate(errp, local_err);
-}
-
-static void spapr_cpu_core_realize_child(Object *child, Error **errp)
-{
- Error *local_err = NULL;
- sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
- CPUState *cs = CPU(child);
- PowerPCCPU *cpu = POWERPC_CPU(cs);
-
- object_property_set_bool(child, true, "realized", &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- spapr_cpu_init(spapr, cpu, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-}
-
-static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
-{
- sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
- CPUCore *cc = CPU_CORE(OBJECT(dev));
- const char *typename = object_class_get_name(sc->cpu_class);
- size_t size = object_type_get_instance_size(typename);
- Error *local_err = NULL;
- void *obj;
- int i, j;
-
- sc->threads = g_malloc0(size * cc->nr_threads);
- for (i = 0; i < cc->nr_threads; i++) {
- char id[32];
- CPUState *cs;
-
- obj = sc->threads + i * size;
-
- object_initialize(obj, size, typename);
- cs = CPU(obj);
- cs->cpu_index = cc->core_id + i;
- snprintf(id, sizeof(id), "thread[%d]", i);
- object_property_add_child(OBJECT(sc), id, obj, &local_err);
- if (local_err) {
- goto err;
- }
- object_unref(obj);
- }
-
- for (j = 0; j < cc->nr_threads; j++) {
- obj = sc->threads + j * size;
-
- spapr_cpu_core_realize_child(obj, &local_err);
- if (local_err) {
- goto err;
- }
- }
- return;
-
-err:
- while (--i >= 0) {
- obj = sc->threads + i * size;
- object_unparent(obj);
- }
- g_free(sc->threads);
- error_propagate(errp, local_err);
-}
-
-static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- dc->realize = spapr_cpu_core_realize;
-}
-
-/*
- * instance_init routines from different flavours of sPAPR CPU cores.
- */
-#define SPAPR_CPU_CORE_INITFN(_type, _fname) \
-static void glue(glue(spapr_cpu_core_, _fname), _initfn(Object *obj)) \
-{ \
- sPAPRCPUCore *core = SPAPR_CPU_CORE(obj); \
- char *name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, stringify(_type)); \
- ObjectClass *oc = object_class_by_name(name); \
- g_assert(oc); \
- g_free((void *)name); \
- core->cpu_class = oc; \
-}
-
-SPAPR_CPU_CORE_INITFN(970mp_v1.0, 970MP_v10);
-SPAPR_CPU_CORE_INITFN(970mp_v1.1, 970MP_v11);
-SPAPR_CPU_CORE_INITFN(970_v2.2, 970);
-SPAPR_CPU_CORE_INITFN(POWER5+_v2.1, POWER5plus);
-SPAPR_CPU_CORE_INITFN(POWER7_v2.3, POWER7);
-SPAPR_CPU_CORE_INITFN(POWER7+_v2.1, POWER7plus);
-SPAPR_CPU_CORE_INITFN(POWER8_v2.0, POWER8);
-SPAPR_CPU_CORE_INITFN(POWER8E_v2.1, POWER8E);
-SPAPR_CPU_CORE_INITFN(POWER8NVL_v1.0, POWER8NVL);
-
-typedef struct SPAPRCoreInfo {
- const char *name;
- void (*initfn)(Object *obj);
-} SPAPRCoreInfo;
-
-static const SPAPRCoreInfo spapr_cores[] = {
- /* 970 */
- { .name = "970_v2.2", .initfn = spapr_cpu_core_970_initfn },
-
- /* 970MP variants */
- { .name = "970MP_v1.0", .initfn = spapr_cpu_core_970MP_v10_initfn },
- { .name = "970mp_v1.0", .initfn = spapr_cpu_core_970MP_v10_initfn },
- { .name = "970MP_v1.1", .initfn = spapr_cpu_core_970MP_v11_initfn },
- { .name = "970mp_v1.1", .initfn = spapr_cpu_core_970MP_v11_initfn },
-
- /* POWER5+ */
- { .name = "POWER5+_v2.1", .initfn = spapr_cpu_core_POWER5plus_initfn },
-
- /* POWER7 */
- { .name = "POWER7_v2.3", .initfn = spapr_cpu_core_POWER7_initfn },
-
- /* POWER7+ */
- { .name = "POWER7+_v2.1", .initfn = spapr_cpu_core_POWER7plus_initfn },
-
- /* POWER8 */
- { .name = "POWER8_v2.0", .initfn = spapr_cpu_core_POWER8_initfn },
-
- /* POWER8E */
- { .name = "POWER8E_v2.1", .initfn = spapr_cpu_core_POWER8E_initfn },
-
- /* POWER8NVL */
- { .name = "POWER8NVL_v1.0", .initfn = spapr_cpu_core_POWER8NVL_initfn },
-
- { .name = NULL }
-};
-
-static void spapr_cpu_core_register(const SPAPRCoreInfo *info)
-{
- TypeInfo type_info = {
- .parent = TYPE_SPAPR_CPU_CORE,
- .instance_size = sizeof(sPAPRCPUCore),
- .instance_init = info->initfn,
- };
-
- type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE, info->name);
- type_register(&type_info);
- g_free((void *)type_info.name);
-}
-
-static const TypeInfo spapr_cpu_core_type_info = {
- .name = TYPE_SPAPR_CPU_CORE,
- .parent = TYPE_CPU_CORE,
- .abstract = true,
- .instance_size = sizeof(sPAPRCPUCore),
- .class_init = spapr_cpu_core_class_init,
-};
-
-static void spapr_cpu_core_register_types(void)
-{
- const SPAPRCoreInfo *info = spapr_cores;
-
- type_register_static(&spapr_cpu_core_type_info);
- while (info->name) {
- spapr_cpu_core_register(info);
- info++;
- }
-}
-
-type_init(spapr_cpu_core_register_types)
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 26a067951..1f5f1d790 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -140,8 +140,6 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc,
DPRINTFN("finalizing device removal");
drck->detach(drc, DEVICE(drc->dev), drc->detach_cb,
drc->detach_cb_opaque, NULL);
- } else if (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
- drc->awaiting_allocation = false;
}
}
return RTAS_OUT_SUCCESS;
@@ -271,7 +269,11 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
void *fdt;
if (!drc->fdt) {
- visit_type_null(v, NULL, errp);
+ visit_start_struct(v, name, NULL, 0, &err);
+ if (!err) {
+ visit_end_struct(v, &err);
+ }
+ error_propagate(errp, err);
return;
}
@@ -299,8 +301,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
case FDT_END_NODE:
/* shouldn't ever see an FDT_END_NODE before FDT_BEGIN_NODE */
g_assert(fdt_depth > 0);
- visit_check_struct(v, &err);
- visit_end_struct(v, NULL);
+ visit_end_struct(v, &err);
if (err) {
error_propagate(errp, err);
return;
@@ -311,7 +312,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
int i;
prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len);
name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
- visit_start_list(v, name, NULL, 0, &err);
+ visit_start_list(v, name, &err);
if (err) {
error_propagate(errp, err);
return;
@@ -323,7 +324,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
return;
}
}
- visit_end_list(v, NULL);
+ visit_end_list(v);
break;
}
default:
@@ -375,10 +376,6 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
drc->signalled = (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI)
? true : coldplug;
- if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) {
- drc->awaiting_allocation = true;
- }
-
object_property_add_link(OBJECT(drc), "device",
object_get_typename(OBJECT(drc->dev)),
(Object **)(&drc->dev),
@@ -427,12 +424,6 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d,
return;
}
- if (drc->awaiting_allocation) {
- drc->awaiting_release = true;
- DPRINTFN("awaiting allocation to complete before removal");
- return;
- }
-
drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE;
if (drc->detach_cb) {
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index b0668b34a..049fb1b32 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -386,7 +386,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
rtas_event_log_queue(RTAS_LOG_TYPE_EPOW, new_epow, true);
- qemu_irq_pulse(xics_get_qirq(spapr->xics, spapr->check_exception_irq));
+ qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
}
static void spapr_hotplug_set_signalled(uint32_t drc_index)
@@ -449,9 +449,6 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
case SPAPR_DR_CONNECTOR_TYPE_LMB:
hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_MEMORY;
break;
- case SPAPR_DR_CONNECTOR_TYPE_CPU:
- hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_CPU;
- break;
default:
/* we shouldn't be signaling hotplug events for resources
* that don't support them
@@ -468,7 +465,7 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
rtas_event_log_queue(RTAS_LOG_TYPE_HOTPLUG, new_hp, true);
- qemu_irq_pulse(xics_get_qirq(spapr->xics, spapr->check_exception_irq));
+ qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
}
void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc)
@@ -551,7 +548,7 @@ static void check_exception(PowerPCCPU *cpu, sPAPRMachineState *spapr,
* interrupts.
*/
if (rtas_event_log_contains(mask, true)) {
- qemu_irq_pulse(xics_get_qirq(spapr->xics, spapr->check_exception_irq));
+ qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
}
return;
@@ -603,7 +600,7 @@ out_no_events:
void spapr_events_init(sPAPRMachineState *spapr)
{
QTAILQ_INIT(&spapr->pending_events);
- spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, 0, false,
+ spapr->check_exception_irq = xics_alloc(spapr->icp, 0, 0, false,
&error_fatal);
spapr->epow_notifier.notify = spapr_powerdown_req;
qemu_register_powerdown_notifier(&spapr->epow_notifier);
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 73af112e1..8f40602a5 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1,15 +1,12 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "sysemu/sysemu.h"
-#include "qemu/log.h"
#include "cpu.h"
-#include "exec/exec-all.h"
#include "helper_regs.h"
#include "hw/ppc/spapr.h"
#include "mmu-hash64.h"
#include "cpu-models.h"
#include "trace.h"
-#include "sysemu/kvm.h"
#include "kvm_ppc.h"
struct SPRSyncState {
@@ -83,12 +80,12 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong pte_index = args[1];
target_ulong pteh = args[2];
target_ulong ptel = args[3];
- unsigned apshift;
+ unsigned apshift, spshift;
target_ulong raddr;
target_ulong index;
uint64_t token;
- apshift = ppc_hash64_hpte_page_shift_noslb(cpu, pteh, ptel);
+ apshift = ppc_hash64_hpte_page_shift_noslb(cpu, pteh, ptel, &spshift);
if (!apshift) {
/* Bad page size encoding */
return H_PARAMETER;
@@ -102,15 +99,11 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return H_PARAMETER;
}
} else {
- target_ulong wimg_flags;
/* Looks like an IO address */
/* FIXME: What WIMG combinations could be sensible for IO?
* For now we allow WIMG=010x, but are there others? */
/* FIXME: Should we check against registered IO addresses? */
- wimg_flags = (ptel & (HPTE64_R_W | HPTE64_R_I | HPTE64_R_M));
-
- if (wimg_flags != HPTE64_R_I &&
- wimg_flags != (HPTE64_R_I | HPTE64_R_M)) {
+ if ((ptel & (HPTE64_R_W | HPTE64_R_I | HPTE64_R_M)) != HPTE64_R_I) {
return H_PARAMETER;
}
}
@@ -190,7 +183,6 @@ static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex,
static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
{
- CPUPPCState *env = &cpu->env;
target_ulong flags = args[0];
target_ulong pte_index = args[1];
target_ulong avpn = args[2];
@@ -201,7 +193,6 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
switch (ret) {
case REMOVE_SUCCESS:
- check_tlb_flush(env);
return H_SUCCESS;
case REMOVE_NOT_FOUND:
@@ -238,9 +229,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
{
- CPUPPCState *env = &cpu->env;
int i;
- target_ulong rc = H_SUCCESS;
for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
target_ulong *tsh = &args[i*2];
@@ -273,18 +262,14 @@ static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
break;
case REMOVE_PARM:
- rc = H_PARAMETER;
- goto exit;
+ return H_PARAMETER;
case REMOVE_HW:
- rc = H_HARDWARE;
- goto exit;
+ return H_HARDWARE;
}
}
- exit:
- check_tlb_flush(env);
- return rc;
+ return H_SUCCESS;
}
static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
@@ -926,41 +911,6 @@ static void do_set_compat(void *arg)
((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \
((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0)
-static void cas_handle_compat_cpu(PowerPCCPUClass *pcc, uint32_t pvr,
- unsigned max_lvl, unsigned *compat_lvl,
- unsigned *cpu_version)
-{
- unsigned lvl = get_compat_level(pvr);
- bool is205, is206, is207;
-
- if (!lvl) {
- return;
- }
-
- /* If it is a logical PVR, try to determine the highest level */
- is205 = (pcc->pcr_supported & PCR_COMPAT_2_05) &&
- (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
- is206 = (pcc->pcr_supported & PCR_COMPAT_2_06) &&
- ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
- (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
- is207 = (pcc->pcr_supported & PCR_COMPAT_2_07) &&
- (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_07));
-
- if (is205 || is206 || is207) {
- if (!max_lvl) {
- /* User did not set the level, choose the highest */
- if (*compat_lvl <= lvl) {
- *compat_lvl = lvl;
- *cpu_version = pvr;
- }
- } else if (max_lvl >= lvl) {
- /* User chose the level, don't set higher than this */
- *compat_lvl = lvl;
- *cpu_version = pvr;
- }
- }
-}
-
#define OV5_DRCONF_MEMORY 0x20
static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
@@ -970,7 +920,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
{
target_ulong list = ppc64_phys_to_real(args[0]);
target_ulong ov_table, ov5;
- PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu_);
+ PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_);
CPUState *cs;
bool cpu_match = false, cpu_update = true, memory_update = false;
unsigned old_cpu_version = cpu_->cpu_version;
@@ -997,7 +947,29 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
cpu_match = true;
cpu_version = cpu_->cpu_version;
} else if (!cpu_match) {
- cas_handle_compat_cpu(pcc, pvr, max_lvl, &compat_lvl, &cpu_version);
+ /* If it is a logical PVR, try to determine the highest level */
+ unsigned lvl = get_compat_level(pvr);
+ if (lvl) {
+ bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) &&
+ (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
+ bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) &&
+ ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
+ (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
+
+ if (is205 || is206) {
+ if (!max_lvl) {
+ /* User did not set the level, choose the highest */
+ if (compat_lvl <= lvl) {
+ compat_lvl = lvl;
+ cpu_version = pvr;
+ }
+ } else if (max_lvl >= lvl) {
+ /* User chose the level, don't set higher than this */
+ compat_lvl = lvl;
+ cpu_version = pvr;
+ }
+ }
+ }
}
/* Terminator record */
if (~pvr_mask & pvr) {
@@ -1007,7 +979,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
/* Parsing finished */
trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match,
- cpu_version, pcc->pcr_mask);
+ cpu_version, pcc_->pcr_mask);
/* Update CPUs */
if (old_cpu_version != cpu_version) {
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 6bc4d4db3..7dd458846 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -17,9 +17,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
-#include "qemu/error-report.h"
#include "hw/hw.h"
-#include "qemu/log.h"
#include "sysemu/kvm.h"
#include "hw/qdev.h"
#include "kvm_ppc.h"
@@ -77,37 +75,6 @@ static IOMMUAccessFlags spapr_tce_iommu_access_flags(uint64_t tce)
}
}
-static uint64_t *spapr_tce_alloc_table(uint32_t liobn,
- uint32_t page_shift,
- uint32_t nb_table,
- int *fd,
- bool need_vfio)
-{
- uint64_t *table = NULL;
- uint64_t window_size = (uint64_t)nb_table << page_shift;
-
- if (kvm_enabled() && !(window_size >> 32)) {
- table = kvmppc_create_spapr_tce(liobn, window_size, fd, need_vfio);
- }
-
- if (!table) {
- *fd = -1;
- table = g_malloc0(nb_table * sizeof(uint64_t));
- }
-
- trace_spapr_iommu_new_table(liobn, table, *fd);
-
- return table;
-}
-
-static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
-{
- if (!kvm_enabled() ||
- (kvmppc_remove_spapr_tce(table, fd, nb_table) != 0)) {
- g_free(table);
- }
-}
-
/* Called from RCU critical section */
static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
bool is_write)
@@ -138,131 +105,61 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
return ret;
}
-static void spapr_tce_table_pre_save(void *opaque)
-{
- sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
-
- tcet->mig_table = tcet->table;
- tcet->mig_nb_table = tcet->nb_table;
-
- trace_spapr_iommu_pre_save(tcet->liobn, tcet->mig_nb_table,
- tcet->bus_offset, tcet->page_shift);
-}
-
-static uint64_t spapr_tce_get_min_page_size(MemoryRegion *iommu)
-{
- sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
-
- return 1ULL << tcet->page_shift;
-}
-
-static void spapr_tce_notify_started(MemoryRegion *iommu)
-{
- spapr_tce_set_need_vfio(container_of(iommu, sPAPRTCETable, iommu), true);
-}
-
-static void spapr_tce_notify_stopped(MemoryRegion *iommu)
-{
- spapr_tce_set_need_vfio(container_of(iommu, sPAPRTCETable, iommu), false);
-}
-
static int spapr_tce_table_post_load(void *opaque, int version_id)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
- uint32_t old_nb_table = tcet->nb_table;
- uint64_t old_bus_offset = tcet->bus_offset;
- uint32_t old_page_shift = tcet->page_shift;
if (tcet->vdev) {
spapr_vio_set_bypass(tcet->vdev, tcet->bypass);
}
- if (tcet->mig_nb_table != tcet->nb_table) {
- spapr_tce_table_disable(tcet);
- }
-
- if (tcet->mig_nb_table) {
- if (!tcet->nb_table) {
- spapr_tce_table_enable(tcet, old_page_shift, old_bus_offset,
- tcet->mig_nb_table);
- }
-
- memcpy(tcet->table, tcet->mig_table,
- tcet->nb_table * sizeof(tcet->table[0]));
-
- free(tcet->mig_table);
- tcet->mig_table = NULL;
- }
-
- trace_spapr_iommu_post_load(tcet->liobn, old_nb_table, tcet->nb_table,
- tcet->bus_offset, tcet->page_shift);
-
return 0;
}
-static bool spapr_tce_table_ex_needed(void *opaque)
-{
- sPAPRTCETable *tcet = opaque;
-
- return tcet->bus_offset || tcet->page_shift != 0xC;
-}
-
-static const VMStateDescription vmstate_spapr_tce_table_ex = {
- .name = "spapr_iommu_ex",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = spapr_tce_table_ex_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(bus_offset, sPAPRTCETable),
- VMSTATE_UINT32(page_shift, sPAPRTCETable),
- VMSTATE_END_OF_LIST()
- },
-};
-
static const VMStateDescription vmstate_spapr_tce_table = {
.name = "spapr_iommu",
.version_id = 2,
.minimum_version_id = 2,
- .pre_save = spapr_tce_table_pre_save,
.post_load = spapr_tce_table_post_load,
.fields = (VMStateField []) {
/* Sanity check */
VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable),
+ VMSTATE_UINT32_EQUAL(nb_table, sPAPRTCETable),
/* IOMMU state */
- VMSTATE_UINT32(mig_nb_table, sPAPRTCETable),
VMSTATE_BOOL(bypass, sPAPRTCETable),
- VMSTATE_VARRAY_UINT32_ALLOC(mig_table, sPAPRTCETable, mig_nb_table, 0,
- vmstate_info_uint64, uint64_t),
+ VMSTATE_VARRAY_UINT32(table, sPAPRTCETable, nb_table, 0, vmstate_info_uint64, uint64_t),
VMSTATE_END_OF_LIST()
},
- .subsections = (const VMStateDescription*[]) {
- &vmstate_spapr_tce_table_ex,
- NULL
- }
};
static MemoryRegionIOMMUOps spapr_iommu_ops = {
.translate = spapr_tce_translate_iommu,
- .get_min_page_size = spapr_tce_get_min_page_size,
- .notify_started = spapr_tce_notify_started,
- .notify_stopped = spapr_tce_notify_stopped,
};
static int spapr_tce_table_realize(DeviceState *dev)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
- Object *tcetobj = OBJECT(tcet);
- char tmp[32];
+ uint64_t window_size = (uint64_t)tcet->nb_table << tcet->page_shift;
- tcet->fd = -1;
- tcet->need_vfio = false;
- snprintf(tmp, sizeof(tmp), "tce-root-%x", tcet->liobn);
- memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX);
+ if (kvm_enabled() && !(window_size >> 32)) {
+ tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
+ window_size,
+ &tcet->fd,
+ tcet->need_vfio);
+ }
+
+ if (!tcet->table) {
+ size_t table_size = tcet->nb_table * sizeof(uint64_t);
+ tcet->table = g_malloc0(table_size);
+ }
- snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn);
- memory_region_init_iommu(&tcet->iommu, tcetobj, &spapr_iommu_ops, tmp, 0);
+ trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd);
+
+ memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops,
+ "iommu-spapr",
+ (uint64_t)tcet->nb_table << tcet->page_shift);
QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
@@ -304,10 +201,14 @@ void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio)
tcet->table = newtable;
}
-sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn)
+sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
+ uint64_t bus_offset,
+ uint32_t page_shift,
+ uint32_t nb_table,
+ bool need_vfio)
{
sPAPRTCETable *tcet;
- char tmp[32];
+ char tmp[64];
if (spapr_tce_find_by_liobn(liobn)) {
fprintf(stderr, "Attempted to create TCE table with duplicate"
@@ -315,8 +216,16 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn)
return NULL;
}
+ if (!nb_table) {
+ return NULL;
+ }
+
tcet = SPAPR_TCE_TABLE(object_new(TYPE_SPAPR_TCE_TABLE));
tcet->liobn = liobn;
+ tcet->bus_offset = bus_offset;
+ tcet->page_shift = page_shift;
+ tcet->nb_table = nb_table;
+ tcet->need_vfio = need_vfio;
snprintf(tmp, sizeof(tmp), "tce-table-%x", liobn);
object_property_add_child(OBJECT(owner), tmp, OBJECT(tcet), NULL);
@@ -326,58 +235,22 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn)
return tcet;
}
-void spapr_tce_table_enable(sPAPRTCETable *tcet,
- uint32_t page_shift, uint64_t bus_offset,
- uint32_t nb_table)
-{
- if (tcet->nb_table) {
- error_report("Warning: trying to enable already enabled TCE table");
- return;
- }
-
- tcet->bus_offset = bus_offset;
- tcet->page_shift = page_shift;
- tcet->nb_table = nb_table;
- tcet->table = spapr_tce_alloc_table(tcet->liobn,
- tcet->page_shift,
- tcet->nb_table,
- &tcet->fd,
- tcet->need_vfio);
-
- memory_region_set_size(&tcet->iommu,
- (uint64_t)tcet->nb_table << tcet->page_shift);
- memory_region_add_subregion(&tcet->root, tcet->bus_offset, &tcet->iommu);
-}
-
-void spapr_tce_table_disable(sPAPRTCETable *tcet)
-{
- if (!tcet->nb_table) {
- return;
- }
-
- memory_region_del_subregion(&tcet->root, &tcet->iommu);
- memory_region_set_size(&tcet->iommu, 0);
-
- spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
- tcet->fd = -1;
- tcet->table = NULL;
- tcet->bus_offset = 0;
- tcet->page_shift = 0;
- tcet->nb_table = 0;
-}
-
static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
QLIST_REMOVE(tcet, list);
- spapr_tce_table_disable(tcet);
+ if (!kvm_enabled() ||
+ (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
+ tcet->nb_table) != 0)) {
+ g_free(tcet->table);
+ }
}
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
{
- return &tcet->root;
+ return &tcet->iommu;
}
static void spapr_tce_reset(DeviceState *dev)
@@ -385,9 +258,7 @@ static void spapr_tce_reset(DeviceState *dev)
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
size_t table_size = tcet->nb_table * sizeof(uint64_t);
- if (tcet->nb_table) {
- memset(tcet->table, 0, table_size);
- }
+ memset(tcet->table, 0, table_size);
}
static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
@@ -406,7 +277,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
tcet->table[index] = tce;
entry.target_as = &address_space_memory,
- entry.iova = (ioba - tcet->bus_offset) & page_mask;
+ entry.iova = ioba & page_mask;
entry.translated_addr = tce & page_mask;
entry.addr_mask = ~page_mask;
entry.perm = spapr_tce_iommu_access_flags(tce);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 949c44fec..573e635bf 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -35,7 +35,6 @@
#include "hw/ppc/spapr.h"
#include "hw/pci-host/spapr.h"
#include "exec/address-spaces.h"
-#include "exec/ram_addr.h"
#include <libfdt.h>
#include "trace.h"
#include "qemu/error-report.h"
@@ -45,8 +44,6 @@
#include "hw/pci/pci_bus.h"
#include "hw/ppc/spapr_drc.h"
#include "sysemu/device_tree.h"
-#include "sysemu/kvm.h"
-#include "sysemu/hostmem.h"
#include "hw/vfio/vfio.h"
@@ -324,7 +321,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return;
}
- xics_spapr_free(spapr->xics, msi->first_irq, msi->num);
+ xics_free(spapr->icp, msi->first_irq, msi->num);
if (msi_present(pdev)) {
spapr_msi_setmsg(pdev, 0, false, 0, 0);
}
@@ -362,7 +359,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
}
/* Allocate MSIs */
- irq = xics_spapr_alloc_block(spapr->xics, 0, req_num, false,
+ irq = xics_alloc_block(spapr->icp, 0, req_num, false,
ret_intr_type == RTAS_TYPE_MSI, &err);
if (err) {
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
@@ -373,7 +370,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
/* Release previous MSIs */
if (msi) {
- xics_spapr_free(spapr->xics, msi->first_irq, msi->num);
+ xics_free(spapr->icp, msi->first_irq, msi->num);
g_hash_table_remove(phb->msi, &config_addr);
}
@@ -735,7 +732,7 @@ static void spapr_msi_write(void *opaque, hwaddr addr,
trace_spapr_pci_msi_write(addr, data, irq);
- qemu_irq_pulse(xics_get_qirq(spapr->xics, irq));
+ qemu_irq_pulse(xics_get_qirq(spapr->icp, irq));
}
static const MemoryRegionOps spapr_msi_ops = {
@@ -1089,11 +1086,19 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
void *fdt = NULL;
int fdt_start_offset = 0, fdt_size;
- fdt = create_device_tree(&fdt_size);
- fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0);
- if (!fdt_start_offset) {
- error_setg(errp, "Failed to create pci child device tree node");
- goto out;
+ if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
+ sPAPRTCETable *tcet = spapr_tce_find_by_liobn(phb->dma_liobn);
+
+ spapr_tce_set_need_vfio(tcet, true);
+ }
+
+ if (dev->hotplugged) {
+ fdt = create_device_tree(&fdt_size);
+ fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0);
+ if (!fdt_start_offset) {
+ error_setg(errp, "Failed to create pci child device tree node");
+ goto out;
+ }
}
drck->attach(drc, DEVICE(pdev),
@@ -1306,14 +1311,12 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
PCIBus *bus;
uint64_t msi_window_size = 4096;
sPAPRTCETable *tcet;
- const unsigned windows_supported =
- sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
+ uint32_t nb_table;
if (sphb->index != (uint32_t)-1) {
hwaddr windows_base;
- if ((sphb->buid != (uint64_t)-1) || (sphb->dma_liobn[0] != (uint32_t)-1)
- || (sphb->dma_liobn[1] != (uint32_t)-1 && windows_supported == 2)
+ if ((sphb->buid != (uint64_t)-1) || (sphb->dma_liobn != (uint32_t)-1)
|| (sphb->mem_win_addr != (hwaddr)-1)
|| (sphb->io_win_addr != (hwaddr)-1)) {
error_setg(errp, "Either \"index\" or other parameters must"
@@ -1328,9 +1331,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
}
sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index;
- for (i = 0; i < windows_supported; ++i) {
- sphb->dma_liobn[i] = SPAPR_PCI_LIOBN(sphb->index, i);
- }
+ sphb->dma_liobn = SPAPR_PCI_LIOBN(sphb->index, 0);
windows_base = SPAPR_PCI_WINDOW_BASE
+ sphb->index * SPAPR_PCI_WINDOW_SPACING;
@@ -1343,9 +1344,8 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
return;
}
- if ((sphb->dma_liobn[0] == (uint32_t)-1) ||
- ((sphb->dma_liobn[1] == (uint32_t)-1) && (windows_supported > 1))) {
- error_setg(errp, "LIOBN(s) not specified for PHB");
+ if (sphb->dma_liobn == (uint32_t)-1) {
+ error_setg(errp, "LIOBN not specified for PHB");
return;
}
@@ -1444,8 +1444,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
uint32_t irq;
Error *local_err = NULL;
- irq = xics_spapr_alloc_block(spapr->xics, 0, 1, true, false,
- &local_err);
+ irq = xics_alloc_block(spapr->icp, 0, 1, true, false, &local_err);
if (local_err) {
error_propagate(errp, local_err);
error_prepend(errp, "can't allocate LSIs: ");
@@ -1464,18 +1463,19 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
}
}
- /* DMA setup */
- for (i = 0; i < windows_supported; ++i) {
- tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn[i]);
- if (!tcet) {
- error_setg(errp, "Creating window#%d failed for %s",
- i, sphb->dtbusname);
- return;
- }
- memory_region_add_subregion_overlap(&sphb->iommu_root, 0,
- spapr_tce_get_iommu(tcet), 0);
+ nb_table = sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT;
+ tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
+ 0, SPAPR_TCE_PAGE_SHIFT, nb_table, false);
+ if (!tcet) {
+ error_setg(errp, "Unable to create TCE table for %s",
+ sphb->dtbusname);
+ return;
}
+ /* Register default 32bit DMA window */
+ memory_region_add_subregion(&sphb->iommu_root, sphb->dma_win_addr,
+ spapr_tce_get_iommu(tcet));
+
sphb->msi = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
}
@@ -1490,31 +1490,8 @@ static int spapr_phb_children_reset(Object *child, void *opaque)
return 0;
}
-void spapr_phb_dma_reset(sPAPRPHBState *sphb)
-{
- int i;
- sPAPRTCETable *tcet;
-
- for (i = 0; i < SPAPR_PCI_DMA_MAX_WINDOWS; ++i) {
- tcet = spapr_tce_find_by_liobn(sphb->dma_liobn[i]);
-
- if (tcet && tcet->nb_table) {
- spapr_tce_table_disable(tcet);
- }
- }
-
- /* Register default 32bit DMA window */
- tcet = spapr_tce_find_by_liobn(sphb->dma_liobn[0]);
- spapr_tce_table_enable(tcet, SPAPR_TCE_PAGE_SHIFT, sphb->dma_win_addr,
- sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT);
-}
-
static void spapr_phb_reset(DeviceState *qdev)
{
- sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev);
-
- spapr_phb_dma_reset(sphb);
-
/* Reset the IOMMU state */
object_child_foreach(OBJECT(qdev), spapr_phb_children_reset, NULL);
@@ -1526,8 +1503,7 @@ static void spapr_phb_reset(DeviceState *qdev)
static Property spapr_phb_properties[] = {
DEFINE_PROP_UINT32("index", sPAPRPHBState, index, -1),
DEFINE_PROP_UINT64("buid", sPAPRPHBState, buid, -1),
- DEFINE_PROP_UINT32("liobn", sPAPRPHBState, dma_liobn[0], -1),
- DEFINE_PROP_UINT32("liobn64", sPAPRPHBState, dma_liobn[1], -1),
+ DEFINE_PROP_UINT32("liobn", sPAPRPHBState, dma_liobn, -1),
DEFINE_PROP_UINT64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1),
DEFINE_PROP_UINT64("mem_win_size", sPAPRPHBState, mem_win_size,
SPAPR_PCI_MMIO_WIN_SIZE),
@@ -1539,11 +1515,6 @@ static Property spapr_phb_properties[] = {
/* Default DMA window is 0..1GB */
DEFINE_PROP_UINT64("dma_win_addr", sPAPRPHBState, dma_win_addr, 0),
DEFINE_PROP_UINT64("dma_win_size", sPAPRPHBState, dma_win_size, 0x40000000),
- DEFINE_PROP_UINT64("dma64_win_addr", sPAPRPHBState, dma64_win_addr,
- 0x800000000000000ULL),
- DEFINE_PROP_BOOL("ddw", sPAPRPHBState, ddw_enabled, true),
- DEFINE_PROP_UINT64("pgsz", sPAPRPHBState, page_size_mask,
- (1ULL << 12) | (1ULL << 16)),
DEFINE_PROP_END_OF_LIST(),
};
@@ -1620,7 +1591,7 @@ static const VMStateDescription vmstate_spapr_pci = {
.post_load = spapr_pci_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT64_EQUAL(buid, sPAPRPHBState),
- VMSTATE_UINT32_EQUAL(dma_liobn[0], sPAPRPHBState),
+ VMSTATE_UINT32_EQUAL(dma_liobn, sPAPRPHBState),
VMSTATE_UINT64_EQUAL(mem_win_addr, sPAPRPHBState),
VMSTATE_UINT64_EQUAL(mem_win_size, sPAPRPHBState),
VMSTATE_UINT64_EQUAL(io_win_addr, sPAPRPHBState),
@@ -1654,6 +1625,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
dc->reset = spapr_phb_reset;
dc->vmsd = &vmstate_spapr_pci;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+ dc->cannot_instantiate_with_device_add_yet = false;
hp->plug = spapr_phb_hot_plug_child;
hp->unplug = spapr_phb_hot_unplug_child;
}
@@ -1796,15 +1768,6 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
uint32_t interrupt_map_mask[] = {
cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)};
uint32_t interrupt_map[PCI_SLOT_MAX * PCI_NUM_PINS][7];
- uint32_t ddw_applicable[] = {
- cpu_to_be32(RTAS_IBM_QUERY_PE_DMA_WINDOW),
- cpu_to_be32(RTAS_IBM_CREATE_PE_DMA_WINDOW),
- cpu_to_be32(RTAS_IBM_REMOVE_PE_DMA_WINDOW)
- };
- uint32_t ddw_extensions[] = {
- cpu_to_be32(1),
- cpu_to_be32(RTAS_IBM_RESET_PE_DMA_WINDOW)
- };
sPAPRTCETable *tcet;
PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus;
sPAPRFDT s_fdt;
@@ -1827,15 +1790,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
_FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges));
_FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
- _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS_SPAPR));
-
- /* Dynamic DMA window */
- if (phb->ddw_enabled) {
- _FDT(fdt_setprop(fdt, bus_off, "ibm,ddw-applicable", &ddw_applicable,
- sizeof(ddw_applicable)));
- _FDT(fdt_setprop(fdt, bus_off, "ibm,ddw-extensions",
- &ddw_extensions, sizeof(ddw_extensions)));
- }
+ _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS));
/* Build the interrupt-map, this must matches what is done
* in pci_spapr_map_irq
@@ -1860,7 +1815,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
_FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
sizeof(interrupt_map)));
- tcet = spapr_tce_find_by_liobn(phb->dma_liobn[0]);
+ tcet = spapr_tce_find_by_liobn(SPAPR_PCI_LIOBN(phb->index, 0));
if (!tcet) {
return -1;
}
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index 8448e0b02..cbd3d23c9 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -18,16 +18,15 @@
*/
#include "qemu/osdep.h"
-#include <linux/vfio.h>
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "hw/ppc/spapr.h"
#include "hw/pci-host/spapr.h"
#include "hw/pci/msix.h"
+#include "linux/vfio.h"
#include "hw/vfio/vfio.h"
#include "qemu/error-report.h"
-#include "sysemu/qtest.h"
#define TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE "spapr-pci-vfio-host-bridge"
@@ -49,9 +48,7 @@ static Property spapr_phb_vfio_properties[] = {
static void spapr_phb_vfio_instance_init(Object *obj)
{
- if (!qtest_enabled()) {
- error_report("spapr-pci-vfio-host-bridge is deprecated");
- }
+ error_report("spapr-pci-vfio-host-bridge is deprecated");
}
bool spapr_phb_eeh_available(sPAPRPHBState *sphb)
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index dc058e512..f07325831 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -26,17 +26,14 @@
*/
#include "qemu/osdep.h"
#include "cpu.h"
-#include "qemu/log.h"
#include "sysemu/sysemu.h"
#include "sysemu/char.h"
#include "hw/qdev.h"
#include "sysemu/device_tree.h"
#include "sysemu/cpus.h"
-#include "sysemu/kvm.h"
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
-#include "hw/ppc/ppc.h"
#include "qapi-event.h"
#include "hw/boards.h"
@@ -165,27 +162,6 @@ static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
}
-/*
- * Set the timebase offset of the CPU to that of first CPU.
- * This helps hotplugged CPU to have the correct timebase offset.
- */
-static void spapr_cpu_update_tb_offset(PowerPCCPU *cpu)
-{
- PowerPCCPU *fcpu = POWERPC_CPU(first_cpu);
-
- cpu->env.tb_env->tb_offset = fcpu->env.tb_env->tb_offset;
-}
-
-static void spapr_cpu_set_endianness(PowerPCCPU *cpu)
-{
- PowerPCCPU *fcpu = POWERPC_CPU(first_cpu);
- PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(fcpu);
-
- if (!pcc->interrupts_big_endian(fcpu)) {
- cpu->env.spr[SPR_LPCR] |= LPCR_ILE;
- }
-}
-
static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
target_ulong args,
@@ -222,8 +198,6 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
env->nip = start;
env->gpr[3] = r3;
cs->halted = 0;
- spapr_cpu_set_endianness(cpu);
- spapr_cpu_update_tb_offset(cpu);
qemu_cpu_kick(cs);
diff --git a/hw/ppc/spapr_rtas_ddw.c b/hw/ppc/spapr_rtas_ddw.c
deleted file mode 100644
index 177dcffc9..000000000
--- a/hw/ppc/spapr_rtas_ddw.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * QEMU sPAPR Dynamic DMA windows support
- *
- * Copyright (c) 2015 Alexey Kardashevskiy, IBM Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "qemu/error-report.h"
-#include "hw/ppc/spapr.h"
-#include "hw/pci-host/spapr.h"
-#include "trace.h"
-
-static int spapr_phb_get_active_win_num_cb(Object *child, void *opaque)
-{
- sPAPRTCETable *tcet;
-
- tcet = (sPAPRTCETable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
- if (tcet && tcet->nb_table) {
- ++*(unsigned *)opaque;
- }
- return 0;
-}
-
-static unsigned spapr_phb_get_active_win_num(sPAPRPHBState *sphb)
-{
- unsigned ret = 0;
-
- object_child_foreach(OBJECT(sphb), spapr_phb_get_active_win_num_cb, &ret);
-
- return ret;
-}
-
-static int spapr_phb_get_free_liobn_cb(Object *child, void *opaque)
-{
- sPAPRTCETable *tcet;
-
- tcet = (sPAPRTCETable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
- if (tcet && !tcet->nb_table) {
- *(uint32_t *)opaque = tcet->liobn;
- return 1;
- }
- return 0;
-}
-
-static unsigned spapr_phb_get_free_liobn(sPAPRPHBState *sphb)
-{
- uint32_t liobn = 0;
-
- object_child_foreach(OBJECT(sphb), spapr_phb_get_free_liobn_cb, &liobn);
-
- return liobn;
-}
-
-static uint32_t spapr_page_mask_to_query_mask(uint64_t page_mask)
-{
- int i;
- uint32_t mask = 0;
- const struct { int shift; uint32_t mask; } masks[] = {
- { 12, RTAS_DDW_PGSIZE_4K },
- { 16, RTAS_DDW_PGSIZE_64K },
- { 24, RTAS_DDW_PGSIZE_16M },
- { 25, RTAS_DDW_PGSIZE_32M },
- { 26, RTAS_DDW_PGSIZE_64M },
- { 27, RTAS_DDW_PGSIZE_128M },
- { 28, RTAS_DDW_PGSIZE_256M },
- { 34, RTAS_DDW_PGSIZE_16G },
- };
-
- for (i = 0; i < ARRAY_SIZE(masks); ++i) {
- if (page_mask & (1ULL << masks[i].shift)) {
- mask |= masks[i].mask;
- }
- }
-
- return mask;
-}
-
-static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
- sPAPRMachineState *spapr,
- uint32_t token, uint32_t nargs,
- target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- sPAPRPHBState *sphb;
- uint64_t buid, max_window_size;
- uint32_t avail, addr, pgmask = 0;
- MachineState *machine = MACHINE(spapr);
-
- if ((nargs != 3) || (nret != 5)) {
- goto param_error_exit;
- }
-
- buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
- addr = rtas_ld(args, 0);
- sphb = spapr_pci_find_phb(spapr, buid);
- if (!sphb || !sphb->ddw_enabled) {
- goto param_error_exit;
- }
-
- /* Translate page mask to LoPAPR format */
- pgmask = spapr_page_mask_to_query_mask(sphb->page_size_mask);
-
- /*
- * This is "Largest contiguous block of TCEs allocated specifically
- * for (that is, are reserved for) this PE".
- * Return the maximum number as maximum supported RAM size was in 4K pages.
- */
- if (machine->ram_size == machine->maxram_size) {
- max_window_size = machine->ram_size;
- } else {
- MemoryHotplugState *hpms = &spapr->hotplug_memory;
-
- max_window_size = hpms->base + memory_region_size(&hpms->mr);
- }
-
- avail = SPAPR_PCI_DMA_MAX_WINDOWS - spapr_phb_get_active_win_num(sphb);
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
- rtas_st(rets, 1, avail);
- rtas_st(rets, 2, max_window_size >> SPAPR_TCE_PAGE_SHIFT);
- rtas_st(rets, 3, pgmask);
- rtas_st(rets, 4, 0); /* DMA migration mask, not supported */
-
- trace_spapr_iommu_ddw_query(buid, addr, avail, max_window_size, pgmask);
- return;
-
-param_error_exit:
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
-}
-
-static void rtas_ibm_create_pe_dma_window(PowerPCCPU *cpu,
- sPAPRMachineState *spapr,
- uint32_t token, uint32_t nargs,
- target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- sPAPRPHBState *sphb;
- sPAPRTCETable *tcet = NULL;
- uint32_t addr, page_shift, window_shift, liobn;
- uint64_t buid, win_addr;
- int windows;
-
- if ((nargs != 5) || (nret != 4)) {
- goto param_error_exit;
- }
-
- buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
- addr = rtas_ld(args, 0);
- sphb = spapr_pci_find_phb(spapr, buid);
- if (!sphb || !sphb->ddw_enabled) {
- goto param_error_exit;
- }
-
- page_shift = rtas_ld(args, 3);
- window_shift = rtas_ld(args, 4);
- liobn = spapr_phb_get_free_liobn(sphb);
- windows = spapr_phb_get_active_win_num(sphb);
-
- if (!(sphb->page_size_mask & (1ULL << page_shift)) ||
- (window_shift < page_shift)) {
- goto param_error_exit;
- }
-
- if (!liobn || !sphb->ddw_enabled || windows == SPAPR_PCI_DMA_MAX_WINDOWS) {
- goto hw_error_exit;
- }
-
- tcet = spapr_tce_find_by_liobn(liobn);
- if (!tcet) {
- goto hw_error_exit;
- }
-
- win_addr = (windows == 0) ? sphb->dma_win_addr : sphb->dma64_win_addr;
- spapr_tce_table_enable(tcet, page_shift, win_addr,
- 1ULL << (window_shift - page_shift));
- if (!tcet->nb_table) {
- goto hw_error_exit;
- }
-
- trace_spapr_iommu_ddw_create(buid, addr, 1ULL << page_shift,
- 1ULL << window_shift, tcet->bus_offset, liobn);
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
- rtas_st(rets, 1, liobn);
- rtas_st(rets, 2, tcet->bus_offset >> 32);
- rtas_st(rets, 3, tcet->bus_offset & ((uint32_t) -1));
-
- return;
-
-hw_error_exit:
- rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
- return;
-
-param_error_exit:
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
-}
-
-static void rtas_ibm_remove_pe_dma_window(PowerPCCPU *cpu,
- sPAPRMachineState *spapr,
- uint32_t token, uint32_t nargs,
- target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- sPAPRPHBState *sphb;
- sPAPRTCETable *tcet;
- uint32_t liobn;
-
- if ((nargs != 1) || (nret != 1)) {
- goto param_error_exit;
- }
-
- liobn = rtas_ld(args, 0);
- tcet = spapr_tce_find_by_liobn(liobn);
- if (!tcet) {
- goto param_error_exit;
- }
-
- sphb = SPAPR_PCI_HOST_BRIDGE(OBJECT(tcet)->parent);
- if (!sphb || !sphb->ddw_enabled || !tcet->nb_table) {
- goto param_error_exit;
- }
-
- spapr_tce_table_disable(tcet);
- trace_spapr_iommu_ddw_remove(liobn);
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
- return;
-
-param_error_exit:
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
-}
-
-static void rtas_ibm_reset_pe_dma_window(PowerPCCPU *cpu,
- sPAPRMachineState *spapr,
- uint32_t token, uint32_t nargs,
- target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- sPAPRPHBState *sphb;
- uint64_t buid;
- uint32_t addr;
-
- if ((nargs != 3) || (nret != 1)) {
- goto param_error_exit;
- }
-
- buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
- addr = rtas_ld(args, 0);
- sphb = spapr_pci_find_phb(spapr, buid);
- if (!sphb || !sphb->ddw_enabled) {
- goto param_error_exit;
- }
-
- spapr_phb_dma_reset(sphb);
- trace_spapr_iommu_ddw_reset(buid, addr);
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-
- return;
-
-param_error_exit:
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
-}
-
-static void spapr_rtas_ddw_init(void)
-{
- spapr_rtas_register(RTAS_IBM_QUERY_PE_DMA_WINDOW,
- "ibm,query-pe-dma-window",
- rtas_ibm_query_pe_dma_window);
- spapr_rtas_register(RTAS_IBM_CREATE_PE_DMA_WINDOW,
- "ibm,create-pe-dma-window",
- rtas_ibm_create_pe_dma_window);
- spapr_rtas_register(RTAS_IBM_REMOVE_PE_DMA_WINDOW,
- "ibm,remove-pe-dma-window",
- rtas_ibm_remove_pe_dma_window);
- spapr_rtas_register(RTAS_IBM_RESET_PE_DMA_WINDOW,
- "ibm,reset-pe-dma-window",
- rtas_ibm_reset_pe_dma_window);
-}
-
-type_init(spapr_rtas_ddw_init)
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index f93244d7c..8aa021fde 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -22,7 +22,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/hw.h"
-#include "qemu/log.h"
#include "sysemu/sysemu.h"
#include "hw/boards.h"
#include "hw/loader.h"
@@ -57,9 +56,12 @@ static char *spapr_vio_get_dev_name(DeviceState *qdev)
{
VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+ char *name;
/* Device tree style name device@reg */
- return g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
+ name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
+
+ return name;
}
static void spapr_vio_bus_class_init(ObjectClass *klass, void *data)
@@ -463,7 +465,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
dev->qdev.id = id;
}
- dev->irq = xics_spapr_alloc(spapr->xics, 0, dev->irq, false, &local_err);
+ dev->irq = xics_alloc(spapr->icp, 0, dev->irq, false, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -480,9 +482,11 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
memory_region_add_subregion_overlap(&dev->mrroot, 0, &dev->mrbypass, 1);
address_space_init(&dev->as, &dev->mrroot, qdev->id);
- dev->tcet = spapr_tce_new_table(qdev, liobn);
- spapr_tce_table_enable(dev->tcet, SPAPR_TCE_PAGE_SHIFT, 0,
- pc->rtce_window_size >> SPAPR_TCE_PAGE_SHIFT);
+ dev->tcet = spapr_tce_new_table(qdev, liobn,
+ 0,
+ SPAPR_TCE_PAGE_SHIFT,
+ pc->rtce_window_size >>
+ SPAPR_TCE_PAGE_SHIFT, false);
dev->tcet->vdev = dev;
memory_region_add_subregion_overlap(&dev->mrroot, 0,
spapr_tce_get_iommu(dev->tcet), 2);
@@ -580,7 +584,7 @@ const VMStateDescription vmstate_spapr_vio = {
VMSTATE_UINT32_EQUAL(irq, VIOsPAPRDevice),
/* General VIO device state */
- VMSTATE_UINT64(signal_state, VIOsPAPRDevice),
+ VMSTATE_UINTTL(signal_state, VIOsPAPRDevice),
VMSTATE_UINT64(crq.qladdr, VIOsPAPRDevice),
VMSTATE_UINT32(crq.qsize, VIOsPAPRDevice),
VMSTATE_UINT32(crq.qnext, VIOsPAPRDevice),
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
deleted file mode 100644
index dfeab9308..000000000
--- a/hw/ppc/trace-events
+++ /dev/null
@@ -1,43 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/ppc/spapr_pci.c
-spapr_pci_msi(const char *msg, uint32_t ca) "%s (cfg=%x)"
-spapr_pci_msi_setup(const char *name, unsigned vector, uint64_t addr) "dev\"%s\" vector %u, addr=%"PRIx64
-spapr_pci_rtas_ibm_change_msi(unsigned cfg, unsigned func, unsigned req, unsigned first) "cfgaddr %x func %u, requested %u, first irq %u"
-spapr_pci_rtas_ibm_query_interrupt_source_number(unsigned ioa, unsigned intr) "queries for #%u, IRQ%u"
-spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) "@%"PRIx64"<=%"PRIx64" IRQ %u"
-spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u"
-spapr_pci_msi_retry(unsigned config_addr, unsigned req_num, unsigned max_irqs) "Guest device at %x asked %u, have only %u"
-
-# hw/ppc/spapr.c
-spapr_cas_failed(unsigned long n) "DT diff buffer is too small: %ld bytes"
-spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes"
-
-# hw/ppc/spapr_hcall.c
-spapr_cas_pvr_try(uint32_t pvr) "%x"
-spapr_cas_pvr(uint32_t cur_pvr, bool cpu_match, uint32_t new_pvr, uint64_t pcr) "current=%x, cpu_match=%u, new=%x, compat flags=%"PRIx64
-
-# hw/ppc/spapr_iommu.c
-spapr_iommu_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64
-spapr_iommu_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "liobn=%"PRIx64" ioba=0x%"PRIx64" ret=%"PRId64" tce=0x%"PRIx64
-spapr_iommu_indirect(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t iobaN, uint64_t tceN, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcelist=0x%"PRIx64" iobaN=0x%"PRIx64" tceN=0x%"PRIx64" ret=%"PRId64
-spapr_iommu_stuff(uint64_t liobn, uint64_t ioba, uint64_t tce_value, uint64_t npages, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcevalue=0x%"PRIx64" npages=%"PRId64" ret=%"PRId64
-spapr_iommu_pci_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64
-spapr_iommu_pci_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "liobn=%"PRIx64" ioba=0x%"PRIx64" ret=%"PRId64" tce=0x%"PRIx64
-spapr_iommu_pci_indirect(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t iobaN, uint64_t tceN, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcelist=0x%"PRIx64" iobaN=0x%"PRIx64" tceN=0x%"PRIx64" ret=%"PRId64
-spapr_iommu_pci_stuff(uint64_t liobn, uint64_t ioba, uint64_t tce_value, uint64_t npages, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcevalue=0x%"PRIx64" npages=%"PRId64" ret=%"PRId64
-spapr_iommu_xlate(uint64_t liobn, uint64_t ioba, uint64_t tce, unsigned perm, unsigned pgsize) "liobn=%"PRIx64" 0x%"PRIx64" -> 0x%"PRIx64" perm=%u mask=%x"
-spapr_iommu_new_table(uint64_t liobn, void *table, int fd) "liobn=%"PRIx64" table=%p fd=%d"
-spapr_iommu_pre_save(uint64_t liobn, uint32_t nb, uint64_t offs, uint32_t ps) "liobn=%"PRIx64" %"PRIx32" bus_offset=%"PRIx64" ps=%"PRIu32
-spapr_iommu_post_load(uint64_t liobn, uint32_t pre_nb, uint32_t post_nb, uint64_t offs, uint32_t ps) "liobn=%"PRIx64" %"PRIx32" => %"PRIx32" bus_offset=%"PRIx64" ps=%"PRIu32
-spapr_iommu_ddw_query(uint64_t buid, uint32_t cfgaddr, unsigned wa, uint64_t win_size, uint32_t pgmask) "buid=%"PRIx64" addr=%"PRIx32", %u windows available, max window size=%"PRIx64", mask=%"PRIx32
-spapr_iommu_ddw_create(uint64_t buid, uint32_t cfgaddr, uint64_t pg_size, uint64_t req_size, uint64_t start, uint32_t liobn) "buid=%"PRIx64" addr=%"PRIx32", page size=0x%"PRIx64", requested=0x%"PRIx64", start addr=%"PRIx64", liobn=%"PRIx32
-spapr_iommu_ddw_remove(uint32_t liobn) "liobn=%"PRIx32
-spapr_iommu_ddw_reset(uint64_t buid, uint32_t cfgaddr) "buid=%"PRIx64" addr=%"PRIx32
-
-# hw/ppc/ppc.c
-ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)"
-
-# hw/ppc/prep.c
-prep_io_800_writeb(uint32_t addr, uint32_t val) "0x%08" PRIx32 " => 0x%02" PRIx32
-prep_io_800_readb(uint32_t addr, uint32_t retval) "0x%08" PRIx32 " <= 0x%02" PRIx32
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index b97d96685..b807a08c2 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -23,7 +23,6 @@
*/
#include "qemu/osdep.h"
-#include "cpu.h"
#include "hw/sysbus.h"
#include "hw/hw.h"
#include "hw/char/serial.h"
diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
index 41ac4ec32..220361782 100644
--- a/hw/s390x/Makefile.objs
+++ b/hw/s390x/Makefile.objs
@@ -8,8 +8,6 @@ obj-y += ipl.o
obj-y += css.o
obj-y += s390-virtio-ccw.o
obj-y += virtio-ccw.o
-obj-y += css-bridge.o
-obj-y += ccw-device.o
obj-y += s390-pci-bus.o s390-pci-inst.o
obj-y += s390-skeys.o
obj-$(CONFIG_KVM) += s390-skeys-kvm.o
diff --git a/hw/s390x/ccw-device.c b/hw/s390x/ccw-device.c
deleted file mode 100644
index 28ea20440..000000000
--- a/hw/s390x/ccw-device.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Common device infrastructure for devices in the virtual css
- *
- * Copyright 2016 IBM Corp.
- * Author(s): 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.
- */
-#include "qemu/osdep.h"
-#include "ccw-device.h"
-
-static const TypeInfo ccw_device_info = {
- .name = TYPE_CCW_DEVICE,
- .parent = TYPE_DEVICE,
- .instance_size = sizeof(CcwDevice),
- .class_size = sizeof(CCWDeviceClass),
- .abstract = true,
-};
-
-static void ccw_device_register(void)
-{
- type_register_static(&ccw_device_info);
-}
-
-type_init(ccw_device_register)
diff --git a/hw/s390x/ccw-device.h b/hw/s390x/ccw-device.h
deleted file mode 100644
index 59ba01b6c..000000000
--- a/hw/s390x/ccw-device.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Common device infrastructure for devices in the virtual css
- *
- * Copyright 2016 IBM Corp.
- * Author(s): 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_CCW_DEVICE_H
-#define HW_S390X_CCW_DEVICE_H
-#include "qom/object.h"
-#include "hw/qdev-core.h"
-#include "hw/s390x/css.h"
-
-typedef struct CcwDevice {
- DeviceState parent_obj;
- SubchDev *sch;
- /* <cssid>.<ssid>.<device number> */
- CssDevId bus_id;
-} CcwDevice;
-
-typedef struct CCWDeviceClass {
- DeviceClass parent_class;
- void (*unplug)(HotplugHandler *, DeviceState *, Error **);
-} CCWDeviceClass;
-
-static inline CcwDevice *to_ccw_dev_fast(DeviceState *d)
-{
- return container_of(d, CcwDevice, parent_obj);
-}
-
-#define TYPE_CCW_DEVICE "ccw-device"
-
-#define CCW_DEVICE(obj) OBJECT_CHECK(CcwDevice, (obj), TYPE_CCW_DEVICE)
-#define CCW_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(CCWDeviceClass, (obj), TYPE_CCW_DEVICE)
-#define CCW_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(CCWDeviceClass, (klass), TYPE_CCW_DEVICE)
-
-#endif
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
deleted file mode 100644
index 9a7f7ee60..000000000
--- a/hw/s390x/css-bridge.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * css bridge implementation
- *
- * 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.
- */
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "hw/hotplug.h"
-#include "hw/sysbus.h"
-#include "qemu/bitops.h"
-#include "hw/s390x/css.h"
-#include "ccw-device.h"
-#include "hw/s390x/css-bridge.h"
-
-/*
- * Invoke device-specific unplug handler, disable the subchannel
- * (including sending a channel report to the guest) and remove the
- * device from the virtual css bus.
- */
-static void ccw_device_unplug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- CcwDevice *ccw_dev = CCW_DEVICE(dev);
- CCWDeviceClass *k = CCW_DEVICE_GET_CLASS(ccw_dev);
- SubchDev *sch = ccw_dev->sch;
- Error *err = NULL;
-
- if (k->unplug) {
- k->unplug(hotplug_dev, dev, &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- }
-
- /*
- * We should arrive here only for device_del, since we don't support
- * direct hot(un)plug of channels.
- */
- assert(sch != NULL);
- /* Subchannel is now disabled and no longer valid. */
- sch->curr_status.pmcw.flags &= ~(PMCW_FLAGS_MASK_ENA |
- PMCW_FLAGS_MASK_DNV);
-
- css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
-
- object_unparent(OBJECT(dev));
-}
-
-static void virtual_css_bus_reset(BusState *qbus)
-{
- /* This should actually be modelled via the generic css */
- css_reset();
-}
-
-static char *virtual_css_bus_get_dev_path(DeviceState *dev)
-{
- CcwDevice *ccw_dev = CCW_DEVICE(dev);
- SubchDev *sch = ccw_dev->sch;
- VirtualCssBridge *bridge =
- VIRTUAL_CSS_BRIDGE(qdev_get_parent_bus(dev)->parent);
-
- /*
- * We can't provide a dev path for backward compatibility on
- * older machines, as it is visible in the migration stream.
- */
- return bridge->css_dev_path ?
- g_strdup_printf("/%02x.%1x.%04x", sch->cssid, sch->ssid, sch->devno) :
- NULL;
-}
-
-static void virtual_css_bus_class_init(ObjectClass *klass, void *data)
-{
- BusClass *k = BUS_CLASS(klass);
-
- k->reset = virtual_css_bus_reset;
- k->get_dev_path = virtual_css_bus_get_dev_path;
-}
-
-static const TypeInfo virtual_css_bus_info = {
- .name = TYPE_VIRTUAL_CSS_BUS,
- .parent = TYPE_BUS,
- .instance_size = sizeof(VirtualCssBus),
- .class_init = virtual_css_bus_class_init,
-};
-
-VirtualCssBus *virtual_css_bus_init(void)
-{
- VirtualCssBus *cbus;
- BusState *bus;
- DeviceState *dev;
-
- /* Create bridge device */
- dev = qdev_create(NULL, TYPE_VIRTUAL_CSS_BRIDGE);
- qdev_init_nofail(dev);
-
- /* Create bus on bridge device */
- bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
- cbus = VIRTUAL_CSS_BUS(bus);
-
- /* Enable hotplugging */
- qbus_set_hotplug_handler(bus, dev, &error_abort);
-
- return cbus;
- }
-
-/***************** Virtual-css Bus Bridge Device ********************/
-
-static Property virtual_css_bridge_properties[] = {
- DEFINE_PROP_BOOL("css_dev_path", VirtualCssBridge, css_dev_path,
- true),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtual_css_bridge_class_init(ObjectClass *klass, void *data)
-{
- HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- hc->unplug = ccw_device_unplug;
- set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
- dc->props = virtual_css_bridge_properties;
-}
-
-static const TypeInfo virtual_css_bridge_info = {
- .name = TYPE_VIRTUAL_CSS_BRIDGE,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(VirtualCssBridge),
- .class_init = virtual_css_bridge_class_init,
- .interfaces = (InterfaceInfo[]) {
- { TYPE_HOTPLUG_HANDLER },
- { }
- }
-};
-
-static void virtual_css_register(void)
-{
- type_register_static(&virtual_css_bridge_info);
- type_register_static(&virtual_css_bus_info);
-}
-
-type_init(virtual_css_register)
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index bb8e4be33..3a1d91958 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -10,14 +10,12 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qapi/visitor.h"
-#include "hw/qdev.h"
+#include <hw/qdev.h>
#include "qemu/bitops.h"
#include "exec/address-spaces.h"
#include "cpu.h"
-#include "hw/s390x/ioinst.h"
-#include "hw/s390x/css.h"
+#include "ioinst.h"
+#include "css.h"
#include "trace.h"
#include "hw/s390x/s390_flic.h"
@@ -194,46 +192,12 @@ out:
return ret;
}
-static void css_clear_io_interrupt(uint16_t subchannel_id,
- uint16_t subchannel_nr)
-{
- Error *err = NULL;
- static bool no_clear_irq;
- S390FLICState *fs = s390_get_flic();
- S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
- int r;
-
- if (unlikely(no_clear_irq)) {
- return;
- }
- r = fsc->clear_io_irq(fs, subchannel_id, subchannel_nr);
- switch (r) {
- case 0:
- break;
- case -ENOSYS:
- no_clear_irq = true;
- /*
- * Ignore unavailability, as the user can't do anything
- * about it anyway.
- */
- break;
- default:
- error_setg_errno(&err, -r, "unexpected error condition");
- error_propagate(&error_abort, err);
- }
-}
-
-static inline uint16_t css_do_build_subchannel_id(uint8_t cssid, uint8_t ssid)
+uint16_t css_build_subchannel_id(SubchDev *sch)
{
if (channel_subsys.max_cssid > 0) {
- return (cssid << 8) | (1 << 3) | (ssid << 1) | 1;
+ return (sch->cssid << 8) | (1 << 3) | (sch->ssid << 1) | 1;
}
- return (ssid << 1) | 1;
-}
-
-uint16_t css_build_subchannel_id(SubchDev *sch)
-{
- return css_do_build_subchannel_id(sch->cssid, sch->ssid);
+ return (sch->ssid << 1) | 1;
}
static void css_inject_io_interrupt(SubchDev *sch)
@@ -511,7 +475,6 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
path = 0x80;
if (!(s->ctrl & SCSW_ACTL_SUSP)) {
- /* Start Function triggered via ssch, i.e. we have an ORB */
s->cstat = 0;
s->dstat = 0;
/* Look at the orb and try to execute the channel program. */
@@ -525,12 +488,9 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
return;
}
sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT);
- s->flags |= (sch->ccw_fmt_1) ? SCSW_FLAGS_MASK_FMT : 0;
sch->ccw_no_data_cnt = 0;
suspend_allowed = !!(orb->ctrl0 & ORB_CTRL0_MASK_SPND);
} else {
- /* Start Function resumed via rsch, i.e. we don't have an
- * ORB */
s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND);
/* The channel program had been suspended before. */
suspend_allowed = true;
@@ -613,7 +573,6 @@ static void do_subchannel_work(SubchDev *sch, ORB *orb)
} else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {
sch_handle_halt_func(sch);
} else if (s->ctrl & SCSW_FCTL_START_FUNC) {
- /* Triggered by both ssch and rsch. */
sch_handle_start_func(sch, orb);
} else {
/* Cannot happen. */
@@ -1345,116 +1304,6 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, uint16_t schid)
return channel_subsys.css[real_cssid]->sch_set[ssid]->sch[schid];
}
-/**
- * Return free device number in subchannel set.
- *
- * Return index of the first free device number in the subchannel set
- * identified by @p cssid and @p ssid, beginning the search at @p
- * start and wrapping around at MAX_DEVNO. Return a value exceeding
- * MAX_SCHID if there are no free device numbers in the subchannel
- * set.
- */
-static uint32_t css_find_free_devno(uint8_t cssid, uint8_t ssid,
- uint16_t start)
-{
- uint32_t round;
-
- for (round = 0; round <= MAX_DEVNO; round++) {
- uint16_t devno = (start + round) % MAX_DEVNO;
-
- if (!css_devno_used(cssid, ssid, devno)) {
- return devno;
- }
- }
- return MAX_DEVNO + 1;
-}
-
-/**
- * Return first free subchannel (id) in subchannel set.
- *
- * Return index of the first free subchannel in the subchannel set
- * identified by @p cssid and @p ssid, if there is any. Return a value
- * exceeding MAX_SCHID if there are no free subchannels in the
- * subchannel set.
- */
-static uint32_t css_find_free_subch(uint8_t cssid, uint8_t ssid)
-{
- uint32_t schid;
-
- for (schid = 0; schid <= MAX_SCHID; schid++) {
- if (!css_find_subch(1, cssid, ssid, schid)) {
- return schid;
- }
- }
- return MAX_SCHID + 1;
-}
-
-/**
- * Return first free subchannel (id) in subchannel set for a device number
- *
- * Verify the device number @p devno is not used yet in the subchannel
- * set identified by @p cssid and @p ssid. Set @p schid to the index
- * of the first free subchannel in the subchannel set, if there is
- * any. Return true if everything succeeded and false otherwise.
- */
-static bool css_find_free_subch_for_devno(uint8_t cssid, uint8_t ssid,
- uint16_t devno, uint16_t *schid,
- Error **errp)
-{
- uint32_t free_schid;
-
- assert(schid);
- if (css_devno_used(cssid, ssid, devno)) {
- error_setg(errp, "Device %x.%x.%04x already exists",
- cssid, ssid, devno);
- return false;
- }
- free_schid = css_find_free_subch(cssid, ssid);
- if (free_schid > MAX_SCHID) {
- error_setg(errp, "No free subchannel found for %x.%x.%04x",
- cssid, ssid, devno);
- return false;
- }
- *schid = free_schid;
- return true;
-}
-
-/**
- * Return first free subchannel (id) and device number
- *
- * Locate the first free subchannel and first free device number in
- * any of the subchannel sets of the channel subsystem identified by
- * @p cssid. Return false if no free subchannel / device number could
- * be found. Otherwise set @p ssid, @p devno and @p schid to identify
- * the available subchannel and device number and return true.
- *
- * May modify @p ssid, @p devno and / or @p schid even if no free
- * subchannel / device number could be found.
- */
-static bool css_find_free_subch_and_devno(uint8_t cssid, uint8_t *ssid,
- uint16_t *devno, uint16_t *schid,
- Error **errp)
-{
- uint32_t free_schid, free_devno;
-
- assert(ssid && devno && schid);
- for (*ssid = 0; *ssid <= MAX_SSID; (*ssid)++) {
- free_schid = css_find_free_subch(cssid, *ssid);
- if (free_schid > MAX_SCHID) {
- continue;
- }
- free_devno = css_find_free_devno(cssid, *ssid, free_schid);
- if (free_devno > MAX_DEVNO) {
- continue;
- }
- *schid = free_schid;
- *devno = free_devno;
- return true;
- }
- error_setg(errp, "Virtual channel subsystem is full!");
- return false;
-}
-
bool css_subch_visible(SubchDev *sch)
{
if (sch->ssid > channel_subsys.max_ssid) {
@@ -1580,8 +1429,6 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0,
(guest_cssid << 8) | (ssid << 4));
}
- /* RW_ERC_IPI --> clear pending interrupts */
- css_clear_io_interrupt(css_do_build_subchannel_id(cssid, ssid), schid);
}
void css_generate_chp_crws(uint8_t cssid, uint8_t chpid)
@@ -1797,116 +1644,3 @@ void css_reset(void)
channel_subsys.max_cssid = 0;
channel_subsys.max_ssid = 0;
}
-
-static void get_css_devid(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- CssDevId *dev_id = qdev_get_prop_ptr(dev, prop);
- char buffer[] = "xx.x.xxxx";
- char *p = buffer;
- int r;
-
- if (dev_id->valid) {
-
- r = snprintf(buffer, sizeof(buffer), "%02x.%1x.%04x", dev_id->cssid,
- dev_id->ssid, dev_id->devid);
- assert(r == sizeof(buffer) - 1);
-
- /* drop leading zero */
- if (dev_id->cssid <= 0xf) {
- p++;
- }
- } else {
- snprintf(buffer, sizeof(buffer), "<unset>");
- }
-
- visit_type_str(v, name, &p, errp);
-}
-
-/*
- * parse <cssid>.<ssid>.<devid> and assert valid range for cssid/ssid
- */
-static void set_css_devid(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- CssDevId *dev_id = qdev_get_prop_ptr(dev, prop);
- Error *local_err = NULL;
- char *str;
- int num, n1, n2;
- unsigned int cssid, ssid, devid;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- visit_type_str(v, name, &str, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- num = sscanf(str, "%2x.%1x%n.%4x%n", &cssid, &ssid, &n1, &devid, &n2);
- if (num != 3 || (n2 - n1) != 5 || strlen(str) != n2) {
- error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
- goto out;
- }
- if ((cssid > MAX_CSSID) || (ssid > MAX_SSID)) {
- error_setg(errp, "Invalid cssid or ssid: cssid %x, ssid %x",
- cssid, ssid);
- goto out;
- }
-
- dev_id->cssid = cssid;
- dev_id->ssid = ssid;
- dev_id->devid = devid;
- dev_id->valid = true;
-
-out:
- g_free(str);
-}
-
-PropertyInfo css_devid_propinfo = {
- .name = "str",
- .description = "Identifier of an I/O device in the channel "
- "subsystem, example: fe.1.23ab",
- .get = get_css_devid,
- .set = set_css_devid,
-};
-
-SubchDev *css_create_virtual_sch(CssDevId bus_id, Error **errp)
-{
- uint16_t schid = 0;
- SubchDev *sch;
-
- if (bus_id.valid) {
- /* Enforce use of virtual cssid. */
- if (bus_id.cssid != VIRTUAL_CSSID) {
- error_setg(errp, "cssid %hhx not valid for virtual devices",
- bus_id.cssid);
- return NULL;
- }
- if (!css_find_free_subch_for_devno(bus_id.cssid, bus_id.ssid,
- bus_id.devid, &schid, errp)) {
- return NULL;
- }
- } else {
- bus_id.cssid = VIRTUAL_CSSID;
- if (!css_find_free_subch_and_devno(bus_id.cssid, &bus_id.ssid,
- &bus_id.devid, &schid, errp)) {
- return NULL;
- }
- }
-
- sch = g_malloc0(sizeof(*sch));
- sch->cssid = bus_id.cssid;
- sch->ssid = bus_id.ssid;
- sch->devno = bus_id.devid;
- sch->schid = schid;
- css_subch_assign(sch->cssid, sch->ssid, schid, sch->devno, sch);
- return sch;
-}
diff --git a/hw/s390x/css.h b/hw/s390x/css.h
new file mode 100644
index 000000000..a320eea59
--- /dev/null
+++ b/hw/s390x/css.h
@@ -0,0 +1,126 @@
+/*
+ * 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 "ioinst.h"
+
+/* Channel subsystem constants. */
+#define MAX_SCHID 65535
+#define MAX_SSID 3
+#define MAX_CSSID 254 /* 255 is reserved */
+#define MAX_CHPID 255
+
+#define MAX_CIWS 62
+
+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 */
+} QEMU_PACKED SenseId;
+
+/* 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;
+
+struct SubchDev {
+ /* channel-subsystem related things: */
+ uint8_t cssid;
+ uint8_t ssid;
+ uint16_t schid;
+ uint16_t devno;
+ SCHIB curr_status;
+ 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;
+ /* transport-provided data: */
+ int (*ccw_cb) (SubchDev *, CCW1);
+ void (*disable_cb)(SubchDev *);
+ SenseId id;
+ void *driver_data;
+};
+
+typedef struct IndAddr {
+ hwaddr addr;
+ uint64_t map;
+ unsigned long refcnt;
+ int len;
+ QTAILQ_ENTRY(IndAddr) sibling;
+} 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);
+void subch_device_save(SubchDev *s, QEMUFile *f);
+int subch_device_load(SubchDev *s, QEMUFile *f);
+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);
+uint16_t css_build_subchannel_id(SubchDev *sch);
+void css_reset(void);
+void css_reset_sch(SubchDev *sch);
+void css_queue_crw(uint8_t rsc, uint8_t erc, 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);
+void css_adapter_interrupt(uint8_t isc);
+
+#define CSS_IO_ADAPTER_VIRTIO 1
+int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap,
+ bool maskable, uint32_t *id);
+#endif
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 2e2664f22..3173dcfdf 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -30,24 +30,6 @@
#define ZIPL_IMAGE_START 0x009000UL
#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
-static bool iplb_extended_needed(void *opaque)
-{
- S390IPLState *ipl = S390_IPL(object_resolve_path(TYPE_S390_IPL, NULL));
-
- return ipl->iplbext_migration;
-}
-
-static const VMStateDescription vmstate_iplb_extended = {
- .name = "ipl/iplb_extended",
- .version_id = 0,
- .minimum_version_id = 0,
- .needed = iplb_extended_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8_ARRAY(reserved_ext, IplParameterBlock, 4096 - 200),
- VMSTATE_END_OF_LIST()
- }
-};
-
static const VMStateDescription vmstate_iplb = {
.name = "ipl/iplb",
.version_id = 0,
@@ -57,10 +39,6 @@ static const VMStateDescription vmstate_iplb = {
VMSTATE_UINT16(devno, IplParameterBlock),
VMSTATE_UINT8_ARRAY(reserved2, IplParameterBlock, 88),
VMSTATE_END_OF_LIST()
- },
- .subsections = (const VMStateDescription*[]) {
- &vmstate_iplb_extended,
- NULL
}
};
@@ -129,7 +107,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
/* Adjust ELF start address to final location */
ipl->bios_start_addr += fwbase;
} else {
- /* Try to load non-ELF file */
+ /* Try to load non-ELF file (e.g. s390-ccw.img) */
bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
4096);
ipl->bios_start_addr = ZIPL_IMAGE_START;
@@ -210,52 +188,46 @@ static Property s390_ipl_properties[] = {
DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline),
DEFINE_PROP_STRING("firmware", S390IPLState, firmware),
DEFINE_PROP_BOOL("enforce_bios", S390IPLState, enforce_bios, false),
- DEFINE_PROP_BOOL("iplbext_migration", S390IPLState, iplbext_migration,
- true),
DEFINE_PROP_END_OF_LIST(),
};
-static bool s390_gen_initial_iplb(S390IPLState *ipl)
+/*
+ * In addition to updating the iplstate, this function returns:
+ * - 0 if system was ipled with external kernel
+ * - -1 if no valid boot device was found
+ * - ccw id of the boot device otherwise
+ */
+static uint64_t s390_update_iplstate(S390IPLState *ipl)
{
DeviceState *dev_st;
+ if (ipl->iplb_valid) {
+ ipl->cssid = 0;
+ ipl->ssid = 0;
+ ipl->devno = ipl->iplb.devno;
+ goto out;
+ }
+
+ if (ipl->kernel) {
+ return 0;
+ }
+
dev_st = get_boot_device(0);
if (dev_st) {
- VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
- object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
+ VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
+ OBJECT(qdev_get_parent_bus(dev_st)->parent),
TYPE_VIRTIO_CCW_DEVICE);
- SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
- TYPE_SCSI_DEVICE);
- if (virtio_ccw_dev) {
- CcwDevice *ccw_dev = CCW_DEVICE(virtio_ccw_dev);
-
- ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
- ipl->iplb.blk0_len =
- cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
- ipl->iplb.pbt = S390_IPL_TYPE_CCW;
- ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
- ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
- return true;
- } else if (sd) {
- SCSIBus *bus = scsi_bus_from_device(sd);
- VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
- VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev);
- CcwDevice *ccw_dev = CCW_DEVICE(scsi_ccw);
-
- ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
- ipl->iplb.blk0_len =
- cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN);
- ipl->iplb.pbt = S390_IPL_TYPE_QEMU_SCSI;
- ipl->iplb.scsi.lun = cpu_to_be32(sd->lun);
- ipl->iplb.scsi.target = cpu_to_be16(sd->id);
- ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
- ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
- ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
- return true;
+ if (ccw_dev) {
+ ipl->cssid = ccw_dev->sch->cssid;
+ ipl->ssid = ccw_dev->sch->ssid;
+ ipl->devno = ccw_dev->sch->devno;
+ goto out;
}
}
- return false;
+ return -1;
+out:
+ return (uint32_t) (ipl->cssid << 24 | ipl->ssid << 16 | ipl->devno);
}
void s390_ipl_update_diag308(IplParameterBlock *iplb)
@@ -293,9 +265,7 @@ void s390_ipl_prepare_cpu(S390CPU *cpu)
if (!ipl->kernel || ipl->iplb_valid) {
cpu->env.psw.addr = ipl->bios_start_addr;
- if (!ipl->iplb_valid) {
- ipl->iplb_valid = s390_gen_initial_iplb(ipl);
- }
+ cpu->env.regs[7] = s390_update_iplstate(ipl);
}
}
@@ -305,7 +275,6 @@ static void s390_ipl_reset(DeviceState *dev)
if (!ipl->reipl_requested) {
ipl->iplb_valid = false;
- memset(&ipl->iplb, 0, sizeof(IplParameterBlock));
}
ipl->reipl_requested = false;
}
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index c89109585..0bfb72b71 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -15,71 +15,11 @@
#include "hw/qdev.h"
#include "cpu.h"
-struct IplBlockCcw {
- uint8_t reserved0[85];
- uint8_t ssid;
- uint16_t devno;
- uint8_t vm_flags;
- uint8_t reserved3[3];
- uint32_t vm_parm_len;
- uint8_t nss_name[8];
- uint8_t vm_parm[64];
- uint8_t reserved4[8];
-} QEMU_PACKED;
-typedef struct IplBlockCcw IplBlockCcw;
-
-struct IplBlockFcp {
- uint8_t reserved1[305 - 1];
- uint8_t opt;
- uint8_t reserved2[3];
- uint16_t reserved3;
- uint16_t devno;
- uint8_t reserved4[4];
- uint64_t wwpn;
- uint64_t lun;
- uint32_t bootprog;
- uint8_t reserved5[12];
- uint64_t br_lba;
- uint32_t scp_data_len;
- uint8_t reserved6[260];
- uint8_t scp_data[];
-} QEMU_PACKED;
-typedef struct IplBlockFcp IplBlockFcp;
-
-struct IplBlockQemuScsi {
- uint32_t lun;
- uint16_t target;
- uint16_t channel;
- uint8_t reserved0[77];
- uint8_t ssid;
- uint16_t devno;
-} QEMU_PACKED;
-typedef struct IplBlockQemuScsi IplBlockQemuScsi;
-
-union IplParameterBlock {
- struct {
- uint32_t len;
- uint8_t reserved0[3];
- uint8_t version;
- uint32_t blk0_len;
- uint8_t pbt;
- uint8_t flags;
- uint16_t reserved01;
- uint8_t loadparm[8];
- union {
- IplBlockCcw ccw;
- IplBlockFcp fcp;
- IplBlockQemuScsi scsi;
- };
- } QEMU_PACKED;
- struct {
- uint8_t reserved1[110];
- uint16_t devno;
- uint8_t reserved2[88];
- uint8_t reserved_ext[4096 - 200];
- } QEMU_PACKED;
-} QEMU_PACKED;
-typedef union IplParameterBlock IplParameterBlock;
+typedef struct IplParameterBlock {
+ uint8_t reserved1[110];
+ uint16_t devno;
+ uint8_t reserved2[88];
+} IplParameterBlock;
void s390_ipl_update_diag308(IplParameterBlock *iplb);
void s390_ipl_prepare_cpu(S390CPU *cpu);
@@ -109,34 +49,7 @@ struct S390IPLState {
uint8_t cssid;
uint8_t ssid;
uint16_t devno;
- bool iplbext_migration;
};
typedef struct S390IPLState S390IPLState;
-#define S390_IPL_TYPE_FCP 0x00
-#define S390_IPL_TYPE_CCW 0x02
-#define S390_IPL_TYPE_QEMU_SCSI 0xff
-
-#define S390_IPLB_HEADER_LEN 8
-#define S390_IPLB_MIN_CCW_LEN 200
-#define S390_IPLB_MIN_FCP_LEN 384
-#define S390_IPLB_MIN_QEMU_SCSI_LEN 200
-
-static inline bool iplb_valid_len(IplParameterBlock *iplb)
-{
- return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock);
-}
-
-static inline bool iplb_valid_ccw(IplParameterBlock *iplb)
-{
- return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_CCW_LEN &&
- iplb->pbt == S390_IPL_TYPE_CCW;
-}
-
-static inline bool iplb_valid_fcp(IplParameterBlock *iplb)
-{
- return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_FCP_LEN &&
- iplb->pbt == S390_IPL_TYPE_FCP;
-}
-
#endif
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 9c1c04e59..918b58543 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -12,15 +12,12 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qapi/visitor.h"
#include "qemu-common.h"
#include "cpu.h"
#include "s390-pci-bus.h"
-#include "s390-pci-inst.h"
-#include "hw/pci/pci_bus.h"
-#include "hw/pci/msi.h"
-#include "qemu/error-report.h"
+#include <hw/pci/pci_bus.h>
+#include <hw/pci/msi.h>
+#include <qemu/error-report.h>
/* #define DEBUG_S390PCI_BUS */
#ifdef DEBUG_S390PCI_BUS
@@ -31,19 +28,6 @@
do { } while (0)
#endif
-static S390pciState *s390_get_phb(void)
-{
- static S390pciState *phb;
-
- if (!phb) {
- phb = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
- assert(phb != NULL);
- }
-
- return phb;
-}
-
int chsc_sei_nt2_get_event(void *res)
{
ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res;
@@ -51,7 +35,12 @@ int chsc_sei_nt2_get_event(void *res)
PciCcdfErr *eccdf;
int rc = 1;
SeiContainer *sei_cont;
- S390pciState *s = s390_get_phb();
+ S390pciState *s = S390_PCI_HOST_BRIDGE(
+ object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+
+ if (!s) {
+ return rc;
+ }
sei_cont = QTAILQ_FIRST(&s->pending_sei);
if (sei_cont) {
@@ -86,40 +75,30 @@ int chsc_sei_nt2_get_event(void *res)
int chsc_sei_nt2_have_event(void)
{
- S390pciState *s = s390_get_phb();
-
- return !QTAILQ_EMPTY(&s->pending_sei);
-}
+ S390pciState *s = S390_PCI_HOST_BRIDGE(
+ object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
-S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev)
-{
- int idx = 0;
- S390PCIBusDevice *dev = NULL;
- S390pciState *s = s390_get_phb();
-
- if (pbdev) {
- idx = (pbdev->fh & FH_MASK_INDEX) + 1;
- }
-
- for (; idx < PCI_SLOT_MAX; idx++) {
- dev = s->pbdev[idx];
- if (dev && dev->state != ZPCI_FS_RESERVED) {
- return dev;
- }
+ if (!s) {
+ return 0;
}
- return NULL;
+ return !QTAILQ_EMPTY(&s->pending_sei);
}
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
{
S390PCIBusDevice *pbdev;
int i;
- S390pciState *s = s390_get_phb();
+ S390pciState *s = S390_PCI_HOST_BRIDGE(
+ object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+
+ if (!s) {
+ return NULL;
+ }
for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = s->pbdev[i];
- if (pbdev && pbdev->fid == fid) {
+ pbdev = &s->pbdev[i];
+ if ((pbdev->fh != 0) && (pbdev->fid == fid)) {
return pbdev;
}
}
@@ -127,139 +106,82 @@ S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
return NULL;
}
-void s390_pci_sclp_configure(SCCB *sccb)
+void s390_pci_sclp_configure(int configure, SCCB *sccb)
{
PciCfgSccb *psccb = (PciCfgSccb *)sccb;
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid));
uint16_t rc;
- if (be16_to_cpu(sccb->h.length) < 16) {
- rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
- goto out;
- }
-
- if (!pbdev) {
- DPRINTF("sclp config no dev found\n");
+ if (pbdev) {
+ if ((configure == 1 && pbdev->configured == true) ||
+ (configure == 0 && pbdev->configured == false)) {
+ rc = SCLP_RC_NO_ACTION_REQUIRED;
+ } else {
+ pbdev->configured = !pbdev->configured;
+ rc = SCLP_RC_NORMAL_COMPLETION;
+ }
+ } else {
+ DPRINTF("sclp config %d no dev found\n", configure);
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
- goto out;
}
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- rc = SCLP_RC_ADAPTER_IN_RESERVED_STATE;
- break;
- case ZPCI_FS_STANDBY:
- pbdev->state = ZPCI_FS_DISABLED;
- rc = SCLP_RC_NORMAL_COMPLETION;
- break;
- default:
- rc = SCLP_RC_NO_ACTION_REQUIRED;
- }
-out:
psccb->header.response_code = cpu_to_be16(rc);
}
-void s390_pci_sclp_deconfigure(SCCB *sccb)
+static uint32_t s390_pci_get_pfid(PCIDevice *pdev)
{
- PciCfgSccb *psccb = (PciCfgSccb *)sccb;
- S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid));
- uint16_t rc;
-
- if (be16_to_cpu(sccb->h.length) < 16) {
- rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
- goto out;
- }
-
- if (!pbdev) {
- DPRINTF("sclp deconfig no dev found\n");
- rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
- goto out;
- }
-
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- rc = SCLP_RC_ADAPTER_IN_RESERVED_STATE;
- break;
- case ZPCI_FS_STANDBY:
- rc = SCLP_RC_NO_ACTION_REQUIRED;
- break;
- default:
- if (pbdev->summary_ind) {
- pci_dereg_irqs(pbdev);
- }
- if (pbdev->iommu_enabled) {
- pci_dereg_ioat(pbdev);
- }
- pbdev->state = ZPCI_FS_STANDBY;
- rc = SCLP_RC_NORMAL_COMPLETION;
-
- if (pbdev->release_timer) {
- qdev_unplug(DEVICE(pbdev->pdev), NULL);
- }
- }
-out:
- psccb->header.response_code = cpu_to_be16(rc);
+ return PCI_SLOT(pdev->devfn);
}
-static S390PCIBusDevice *s390_pci_find_dev_by_uid(uint16_t uid)
+static uint32_t s390_pci_get_pfh(PCIDevice *pdev)
{
- int i;
- S390PCIBusDevice *pbdev;
- S390pciState *s = s390_get_phb();
-
- for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = s->pbdev[i];
- if (!pbdev) {
- continue;
- }
-
- if (pbdev->uid == uid) {
- return pbdev;
- }
- }
-
- return NULL;
+ return PCI_SLOT(pdev->devfn) | FH_VIRT;
}
-static S390PCIBusDevice *s390_pci_find_dev_by_target(const char *target)
+S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx)
{
- int i;
S390PCIBusDevice *pbdev;
- S390pciState *s = s390_get_phb();
+ int i;
+ int j = 0;
+ S390pciState *s = S390_PCI_HOST_BRIDGE(
+ object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
- if (!target) {
+ if (!s) {
return NULL;
}
for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = s->pbdev[i];
- if (!pbdev) {
+ pbdev = &s->pbdev[i];
+
+ if (pbdev->fh == 0) {
continue;
}
- if (!strcmp(pbdev->target, target)) {
+ if (j == idx) {
return pbdev;
}
+ j++;
}
return NULL;
}
-S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx)
-{
- S390pciState *s = s390_get_phb();
-
- return s->pbdev[idx & FH_MASK_INDEX];
-}
-
S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh)
{
- S390pciState *s = s390_get_phb();
S390PCIBusDevice *pbdev;
+ int i;
+ S390pciState *s = S390_PCI_HOST_BRIDGE(
+ object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
- pbdev = s->pbdev[fh & FH_MASK_INDEX];
- if (pbdev && pbdev->fh == fh) {
- return pbdev;
+ if (!s || !fh) {
+ return NULL;
+ }
+
+ for (i = 0; i < PCI_SLOT_MAX; i++) {
+ pbdev = &s->pbdev[i];
+ if (pbdev->fh == fh) {
+ return pbdev;
+ }
}
return NULL;
@@ -269,7 +191,12 @@ static void s390_pci_generate_event(uint8_t cc, uint16_t pec, uint32_t fh,
uint32_t fid, uint64_t faddr, uint32_t e)
{
SeiContainer *sei_cont;
- S390pciState *s = s390_get_phb();
+ S390pciState *s = S390_PCI_HOST_BRIDGE(
+ object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+
+ if (!s) {
+ return;
+ }
sei_cont = g_malloc0(sizeof(SeiContainer));
sei_cont->fh = fh;
@@ -289,8 +216,9 @@ static void s390_pci_generate_plug_event(uint16_t pec, uint32_t fh,
s390_pci_generate_event(2, pec, fh, fid, 0, 0);
}
-void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid,
- uint64_t faddr, uint32_t e)
+static void s390_pci_generate_error_event(uint16_t pec, uint32_t fh,
+ uint32_t fid, uint64_t faddr,
+ uint32_t e)
{
s390_pci_generate_event(1, pec, fh, fid, faddr, e);
}
@@ -392,14 +320,7 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
.perm = IOMMU_NONE,
};
- switch (pbdev->state) {
- case ZPCI_FS_ENABLED:
- case ZPCI_FS_BLOCKED:
- if (!pbdev->iommu_enabled) {
- return ret;
- }
- break;
- default:
+ if (!pbdev->configured || !pbdev->pdev || !(pbdev->fh & FH_ENABLED)) {
return ret;
}
@@ -418,13 +339,30 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
return ret;
}
+ if (!pbdev->g_iota) {
+ pbdev->error_state = true;
+ pbdev->lgstg_blocked = true;
+ s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,
+ addr, 0);
+ return ret;
+ }
+
if (addr < pbdev->pba || addr > pbdev->pal) {
+ pbdev->error_state = true;
+ pbdev->lgstg_blocked = true;
+ s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,
+ addr, 0);
return ret;
}
pte = s390_guest_io_table_walk(s390_pci_get_table_origin(pbdev->g_iota),
addr);
+
if (!pte) {
+ pbdev->error_state = true;
+ pbdev->lgstg_blocked = true;
+ s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,
+ addr, ERR_EVENT_Q_BIT);
return ret;
}
@@ -450,7 +388,7 @@ static AddressSpace *s390_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
{
S390pciState *s = opaque;
- return &s->iommu[PCI_SLOT(devfn)]->as;
+ return &s->pbdev[PCI_SLOT(devfn)].as;
}
static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set)
@@ -478,22 +416,22 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data,
{
S390PCIBusDevice *pbdev;
uint32_t io_int_word;
- uint32_t idx = data >> ZPCI_MSI_VEC_BITS;
+ uint32_t fid = data >> ZPCI_MSI_VEC_BITS;
uint32_t vec = data & ZPCI_MSI_VEC_MASK;
uint64_t ind_bit;
uint32_t sum_bit;
uint32_t e = 0;
- DPRINTF("write_msix data 0x%" PRIx64 " idx %d vec 0x%x\n", data, idx, vec);
+ DPRINTF("write_msix data 0x%" PRIx64 " fid %d vec 0x%x\n", data, fid, vec);
- pbdev = s390_pci_find_dev_by_idx(idx);
+ pbdev = s390_pci_find_dev_by_fid(fid);
if (!pbdev) {
e |= (vec << ERR_EVENT_MVN_OFFSET);
- s390_pci_generate_error_event(ERR_EVENT_NOMSI, idx, 0, addr, e);
+ s390_pci_generate_error_event(ERR_EVENT_NOMSI, 0, fid, addr, e);
return;
}
- if (pbdev->state != ZPCI_FS_ENABLED) {
+ if (!(pbdev->fh & FH_ENABLED)) {
return;
}
@@ -520,33 +458,32 @@ static const MemoryRegionOps s390_msi_ctrl_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-void s390_pci_iommu_enable(S390PCIBusDevice *pbdev)
+void s390_pcihost_iommu_configure(S390PCIBusDevice *pbdev, bool enable)
{
- memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->iommu->mr),
- &s390_iommu_ops, "iommu-s390", pbdev->pal + 1);
- memory_region_add_subregion(&pbdev->iommu->mr, 0, &pbdev->iommu_mr);
- pbdev->iommu_enabled = true;
-}
+ pbdev->configured = false;
-void s390_pci_iommu_disable(S390PCIBusDevice *pbdev)
-{
- memory_region_del_subregion(&pbdev->iommu->mr, &pbdev->iommu_mr);
- object_unparent(OBJECT(&pbdev->iommu_mr));
- pbdev->iommu_enabled = false;
+ if (enable) {
+ uint64_t size = pbdev->pal - pbdev->pba + 1;
+ memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr),
+ &s390_iommu_ops, "iommu-s390", size);
+ memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr);
+ } else {
+ memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr);
+ }
+
+ pbdev->configured = true;
}
static void s390_pcihost_init_as(S390pciState *s)
{
int i;
- S390PCIIOMMU *iommu;
+ S390PCIBusDevice *pbdev;
for (i = 0; i < PCI_SLOT_MAX; i++) {
- iommu = g_malloc0(sizeof(S390PCIIOMMU));
- memory_region_init(&iommu->mr, OBJECT(s),
+ pbdev = &s->pbdev[i];
+ memory_region_init(&pbdev->mr, OBJECT(s),
"iommu-root-s390", UINT64_MAX);
- address_space_init(&iommu->as, &iommu->mr, "iommu-pci");
-
- s->iommu[i] = iommu;
+ address_space_init(&pbdev->as, &pbdev->mr, "iommu-pci");
}
memory_region_init_io(&s->msix_notify_mr, OBJECT(s),
@@ -573,10 +510,6 @@ static int s390_pcihost_init(SysBusDevice *dev)
bus = BUS(b);
qbus_set_hotplug_handler(bus, DEVICE(dev), NULL);
phb->bus = b;
-
- s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, DEVICE(s), NULL));
- qbus_set_hotplug_handler(BUS(s->bus), DEVICE(s), NULL);
-
QTAILQ_INIT(&s->pending_sei);
return 0;
}
@@ -609,155 +542,51 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev)
return 0;
}
-static S390PCIBusDevice *s390_pci_device_new(const char *target)
-{
- DeviceState *dev = NULL;
- S390pciState *s = s390_get_phb();
-
- dev = qdev_try_create(BUS(s->bus), TYPE_S390_PCI_DEVICE);
- if (!dev) {
- return NULL;
- }
-
- qdev_prop_set_string(dev, "target", target);
- qdev_init_nofail(dev);
-
- return S390_PCI_DEVICE(dev);
-}
-
static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- PCIDevice *pdev = NULL;
- S390PCIBusDevice *pbdev = NULL;
- S390pciState *s = s390_get_phb();
-
- if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
- pdev = PCI_DEVICE(dev);
-
- if (!dev->id) {
- /* In the case the PCI device does not define an id */
- /* we generate one based on the PCI address */
- dev->id = g_strdup_printf("auto_%02x:%02x.%01x",
- pci_bus_num(pdev->bus),
- PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn));
- }
-
- pbdev = s390_pci_find_dev_by_target(dev->id);
- if (!pbdev) {
- pbdev = s390_pci_device_new(dev->id);
- if (!pbdev) {
- error_setg(errp, "create zpci device failed");
- }
- }
-
- if (object_dynamic_cast(OBJECT(dev), "vfio-pci")) {
- pbdev->fh |= FH_SHM_VFIO;
- } else {
- pbdev->fh |= FH_SHM_EMUL;
- }
+ PCIDevice *pci_dev = PCI_DEVICE(dev);
+ S390PCIBusDevice *pbdev;
+ S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev)
+ ->qbus.parent);
- pbdev->pdev = pdev;
- pbdev->iommu = s->iommu[PCI_SLOT(pdev->devfn)];
- pbdev->state = ZPCI_FS_STANDBY;
- s390_pcihost_setup_msix(pbdev);
+ pbdev = &s->pbdev[PCI_SLOT(pci_dev->devfn)];
- if (dev->hotplugged) {
- s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY,
- pbdev->fh, pbdev->fid);
- }
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) {
- int idx;
-
- pbdev = S390_PCI_DEVICE(dev);
- for (idx = 0; idx < PCI_SLOT_MAX; idx++) {
- if (!s->pbdev[idx]) {
- s->pbdev[idx] = pbdev;
- pbdev->fh = idx;
- return;
- }
- }
+ pbdev->fid = s390_pci_get_pfid(pci_dev);
+ pbdev->pdev = pci_dev;
+ pbdev->configured = true;
+ pbdev->fh = s390_pci_get_pfh(pci_dev);
- error_setg(errp, "no slot for plugging zpci device");
- }
-}
-
-static void s390_pcihost_timer_cb(void *opaque)
-{
- S390PCIBusDevice *pbdev = opaque;
+ s390_pcihost_setup_msix(pbdev);
- if (pbdev->summary_ind) {
- pci_dereg_irqs(pbdev);
- }
- if (pbdev->iommu_enabled) {
- pci_dereg_ioat(pbdev);
+ if (dev->hotplugged) {
+ s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY,
+ pbdev->fh, pbdev->fid);
+ s390_pci_generate_plug_event(HP_EVENT_TO_CONFIGURED,
+ pbdev->fh, pbdev->fid);
}
-
- pbdev->state = ZPCI_FS_STANDBY;
- s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES,
- pbdev->fh, pbdev->fid);
- qdev_unplug(DEVICE(pbdev), NULL);
}
static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- int i;
- PCIDevice *pci_dev = NULL;
- S390PCIBusDevice *pbdev = NULL;
- S390pciState *s = s390_get_phb();
-
- if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
- pci_dev = PCI_DEVICE(dev);
-
- for (i = 0 ; i < PCI_SLOT_MAX; i++) {
- if (s->pbdev[i] && s->pbdev[i]->pdev == pci_dev) {
- pbdev = s->pbdev[i];
- break;
- }
- }
+ PCIDevice *pci_dev = PCI_DEVICE(dev);
+ S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev)
+ ->qbus.parent);
+ S390PCIBusDevice *pbdev = &s->pbdev[PCI_SLOT(pci_dev->devfn)];
- if (!pbdev) {
- object_unparent(OBJECT(pci_dev));
- return;
- }
- } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) {
- pbdev = S390_PCI_DEVICE(dev);
- pci_dev = pbdev->pdev;
- }
-
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- goto out;
- case ZPCI_FS_STANDBY:
- break;
- default:
- s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST,
+ if (pbdev->configured) {
+ pbdev->configured = false;
+ s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES,
pbdev->fh, pbdev->fid);
- pbdev->release_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- s390_pcihost_timer_cb,
- pbdev);
- timer_mod(pbdev->release_timer,
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + HOT_UNPLUG_TIMEOUT);
- return;
- }
-
- if (pbdev->release_timer && timer_pending(pbdev->release_timer)) {
- timer_del(pbdev->release_timer);
- timer_free(pbdev->release_timer);
- pbdev->release_timer = NULL;
}
s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED,
pbdev->fh, pbdev->fid);
- object_unparent(OBJECT(pci_dev));
- pbdev->pdev = NULL;
- pbdev->state = ZPCI_FS_RESERVED;
-out:
+ pbdev->fh = 0;
pbdev->fid = 0;
- s->pbdev[pbdev->fh & FH_MASK_INDEX] = NULL;
- object_unparent(OBJECT(pbdev));
+ pbdev->pdev = NULL;
+ object_unparent(OBJECT(pci_dev));
}
static void s390_pcihost_class_init(ObjectClass *klass, void *data)
@@ -784,178 +613,9 @@ static const TypeInfo s390_pcihost_info = {
}
};
-static const TypeInfo s390_pcibus_info = {
- .name = TYPE_S390_PCI_BUS,
- .parent = TYPE_BUS,
- .instance_size = sizeof(S390PCIBus),
-};
-
-static uint16_t s390_pci_generate_uid(void)
-{
- uint16_t uid = 0;
-
- do {
- uid++;
- if (!s390_pci_find_dev_by_uid(uid)) {
- return uid;
- }
- } while (uid < ZPCI_MAX_UID);
-
- return UID_UNDEFINED;
-}
-
-static uint32_t s390_pci_generate_fid(Error **errp)
-{
- uint32_t fid = 0;
-
- while (fid <= ZPCI_MAX_FID) {
- if (!s390_pci_find_dev_by_fid(fid)) {
- return fid;
- }
-
- if (fid == ZPCI_MAX_FID) {
- break;
- }
-
- fid++;
- }
-
- error_setg(errp, "no free fid could be found");
- return 0;
-}
-
-static void s390_pci_device_realize(DeviceState *dev, Error **errp)
-{
- S390PCIBusDevice *zpci = S390_PCI_DEVICE(dev);
-
- if (!zpci->target) {
- error_setg(errp, "target must be defined");
- return;
- }
-
- if (s390_pci_find_dev_by_target(zpci->target)) {
- error_setg(errp, "target %s already has an associated zpci device",
- zpci->target);
- return;
- }
-
- if (zpci->uid == UID_UNDEFINED) {
- zpci->uid = s390_pci_generate_uid();
- if (!zpci->uid) {
- error_setg(errp, "no free uid could be found");
- return;
- }
- } else if (s390_pci_find_dev_by_uid(zpci->uid)) {
- error_setg(errp, "uid %u already in use", zpci->uid);
- return;
- }
-
- if (!zpci->fid_defined) {
- Error *local_error = NULL;
-
- zpci->fid = s390_pci_generate_fid(&local_error);
- if (local_error) {
- error_propagate(errp, local_error);
- return;
- }
- } else if (s390_pci_find_dev_by_fid(zpci->fid)) {
- error_setg(errp, "fid %u already in use", zpci->fid);
- return;
- }
-
- zpci->state = ZPCI_FS_RESERVED;
-}
-
-static void s390_pci_device_reset(DeviceState *dev)
-{
- S390PCIBusDevice *pbdev = S390_PCI_DEVICE(dev);
-
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- return;
- case ZPCI_FS_STANDBY:
- break;
- default:
- pbdev->fh &= ~FH_MASK_ENABLE;
- pbdev->state = ZPCI_FS_DISABLED;
- break;
- }
-
- if (pbdev->summary_ind) {
- pci_dereg_irqs(pbdev);
- }
- if (pbdev->iommu_enabled) {
- pci_dereg_ioat(pbdev);
- }
-
- pbdev->fmb_addr = 0;
-}
-
-static void s390_pci_get_fid(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- Property *prop = opaque;
- uint32_t *ptr = qdev_get_prop_ptr(DEVICE(obj), prop);
-
- visit_type_uint32(v, name, ptr, errp);
-}
-
-static void s390_pci_set_fid(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- S390PCIBusDevice *zpci = S390_PCI_DEVICE(obj);
- Property *prop = opaque;
- uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- visit_type_uint32(v, name, ptr, errp);
- zpci->fid_defined = true;
-}
-
-static PropertyInfo s390_pci_fid_propinfo = {
- .name = "zpci_fid",
- .get = s390_pci_get_fid,
- .set = s390_pci_set_fid,
-};
-
-#define DEFINE_PROP_S390_PCI_FID(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, s390_pci_fid_propinfo, uint32_t)
-
-static Property s390_pci_device_properties[] = {
- DEFINE_PROP_UINT16("uid", S390PCIBusDevice, uid, UID_UNDEFINED),
- DEFINE_PROP_S390_PCI_FID("fid", S390PCIBusDevice, fid),
- DEFINE_PROP_STRING("target", S390PCIBusDevice, target),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void s390_pci_device_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->desc = "zpci device";
- dc->reset = s390_pci_device_reset;
- dc->bus_type = TYPE_S390_PCI_BUS;
- dc->realize = s390_pci_device_realize;
- dc->props = s390_pci_device_properties;
-}
-
-static const TypeInfo s390_pci_device_info = {
- .name = TYPE_S390_PCI_DEVICE,
- .parent = TYPE_DEVICE,
- .instance_size = sizeof(S390PCIBusDevice),
- .class_init = s390_pci_device_class_init,
-};
-
static void s390_pci_register_types(void)
{
type_register_static(&s390_pcihost_info);
- type_register_static(&s390_pcibus_info);
- type_register_static(&s390_pci_device_info);
}
type_init(s390_pci_register_types)
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index 4f564e02f..59fd5c958 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -14,38 +14,23 @@
#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/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"
#define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost"
-#define TYPE_S390_PCI_BUS "s390-pcibus"
-#define TYPE_S390_PCI_DEVICE "zpci"
-#define FH_MASK_ENABLE 0x80000000
-#define FH_MASK_INSTANCE 0x7f000000
-#define FH_MASK_SHM 0x00ff0000
-#define FH_MASK_INDEX 0x0000001f
-#define FH_SHM_VFIO 0x00010000
-#define FH_SHM_EMUL 0x00020000
+#define FH_VIRT 0x00ff0000
+#define ENABLE_BIT_OFFSET 31
+#define FH_ENABLED (1 << ENABLE_BIT_OFFSET)
#define S390_PCIPT_ADAPTER 2
-#define ZPCI_MAX_FID 0xffffffff
-#define ZPCI_MAX_UID 0xffff
-#define UID_UNDEFINED 0
-#define UID_CHECKING_ENABLED 0x01
-#define HOT_UNPLUG_TIMEOUT (NANOSECONDS_PER_SECOND * 60 * 5)
#define S390_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(S390pciState, (obj), TYPE_S390_PCI_HOST_BRIDGE)
-#define S390_PCI_BUS(obj) \
- OBJECT_CHECK(S390PCIBus, (obj), TYPE_S390_PCI_BUS)
-#define S390_PCI_DEVICE(obj) \
- OBJECT_CHECK(S390PCIBusDevice, (obj), TYPE_S390_PCI_DEVICE)
#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
@@ -165,34 +150,6 @@ enum ZpciIoatDtype {
#define ZPCI_TABLE_VALID_MASK 0x20
#define ZPCI_TABLE_PROT_MASK 0x200
-/* 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 occured; transition back to enabled via mpcifc
- * permanent error: an unrecoverable error occured; 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;
@@ -241,11 +198,11 @@ typedef struct ChscSeiNt2Res {
} QEMU_PACKED ChscSeiNt2Res;
typedef struct PciCfgSccb {
- SCCBHeader header;
- uint8_t atype;
- uint8_t reserved1;
- uint16_t reserved2;
- uint32_t aid;
+ SCCBHeader header;
+ uint8_t atype;
+ uint8_t reserved1;
+ uint16_t reserved2;
+ uint32_t aid;
} QEMU_PACKED PciCfgSccb;
typedef struct S390MsixInfo {
@@ -257,21 +214,13 @@ typedef struct S390MsixInfo {
uint32_t pba_offset;
} S390MsixInfo;
-typedef struct S390PCIIOMMU {
- AddressSpace as;
- MemoryRegion mr;
-} S390PCIIOMMU;
-
typedef struct S390PCIBusDevice {
- DeviceState qdev;
PCIDevice *pdev;
- ZpciState state;
- bool iommu_enabled;
- char *target;
- uint16_t uid;
+ bool configured;
+ bool error_state;
+ bool lgstg_blocked;
uint32_t fh;
uint32_t fid;
- bool fid_defined;
uint64_t g_iota;
uint64_t pba;
uint64_t pal;
@@ -281,22 +230,16 @@ typedef struct S390PCIBusDevice {
uint8_t sum;
S390MsixInfo msix;
AdapterRoutes routes;
- S390PCIIOMMU *iommu;
+ AddressSpace as;
+ MemoryRegion mr;
MemoryRegion iommu_mr;
IndAddr *summary_ind;
IndAddr *indicator;
- QEMUTimer *release_timer;
} S390PCIBusDevice;
-typedef struct S390PCIBus {
- BusState qbus;
-} S390PCIBus;
-
typedef struct S390pciState {
PCIHostState parent_obj;
- S390PCIBus *bus;
- S390PCIBusDevice *pbdev[PCI_SLOT_MAX];
- S390PCIIOMMU *iommu[PCI_SLOT_MAX];
+ S390PCIBusDevice pbdev[PCI_SLOT_MAX];
AddressSpace msix_notify_as;
MemoryRegion msix_notify_mr;
QTAILQ_HEAD(, SeiContainer) pending_sei;
@@ -304,15 +247,10 @@ typedef struct S390pciState {
int chsc_sei_nt2_get_event(void *res);
int 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(S390PCIBusDevice *pbdev);
-void s390_pci_iommu_disable(S390PCIBusDevice *pbdev);
-void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid,
- uint64_t faddr, uint32_t e);
+void s390_pci_sclp_configure(int configure, SCCB *sccb);
+void s390_pcihost_iommu_configure(S390PCIBusDevice *pbdev, bool enable);
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx);
S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh);
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid);
-S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev);
#endif
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index f069b110b..b28e7d14f 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -16,8 +16,8 @@
#include "cpu.h"
#include "s390-pci-inst.h"
#include "s390-pci-bus.h"
-#include "exec/memory-internal.h"
-#include "qemu/error-report.h"
+#include <exec/memory-internal.h>
+#include <qemu/error-report.h>
/* #define DEBUG_S390PCI_INST */
#ifdef DEBUG_S390PCI_INST
@@ -37,9 +37,9 @@ static void s390_set_status_code(CPUS390XState *env,
static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
{
- S390PCIBusDevice *pbdev = NULL;
- uint32_t res_code, initial_l2, g_l2;
- int rc, i;
+ S390PCIBusDevice *pbdev;
+ uint32_t res_code, initial_l2, g_l2, finish;
+ int rc, idx;
uint64_t resume_token;
rc = 0;
@@ -56,7 +56,8 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
}
if ((ldl_p(&rrb->request.fmt) & ~CLP_MASK_FMT) != 0 ||
- ldq_p(&rrb->request.reserved1) != 0) {
+ ldq_p(&rrb->request.reserved1) != 0 ||
+ ldq_p(&rrb->request.reserved2) != 0) {
res_code = CLP_RC_RESNOT0;
rc = -EINVAL;
goto out;
@@ -71,8 +72,6 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
rc = -EINVAL;
goto out;
}
- } else {
- pbdev = s390_pci_find_next_avail_dev(NULL);
}
if (lduw_p(&rrb->response.hdr.len) < 48) {
@@ -92,40 +91,43 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
stl_p(&rrb->response.fmt, 0);
stq_p(&rrb->response.reserved1, 0);
- stl_p(&rrb->response.mdd, FH_MASK_SHM);
+ stq_p(&rrb->response.reserved2, 0);
+ stl_p(&rrb->response.mdd, FH_VIRT);
stw_p(&rrb->response.max_fn, PCI_MAX_FUNCTIONS);
- rrb->response.flags = UID_CHECKING_ENABLED;
rrb->response.entry_size = sizeof(ClpFhListEntry);
-
- i = 0;
+ finish = 0;
+ idx = resume_token;
g_l2 = LIST_PCI_HDR_LEN;
- while (g_l2 < initial_l2 && pbdev) {
- stw_p(&rrb->response.fh_list[i].device_id,
+ do {
+ pbdev = s390_pci_find_dev_by_idx(idx);
+ if (!pbdev) {
+ finish = 1;
+ break;
+ }
+ stw_p(&rrb->response.fh_list[idx - resume_token].device_id,
pci_get_word(pbdev->pdev->config + PCI_DEVICE_ID));
- stw_p(&rrb->response.fh_list[i].vendor_id,
+ stw_p(&rrb->response.fh_list[idx - resume_token].vendor_id,
pci_get_word(pbdev->pdev->config + PCI_VENDOR_ID));
- /* Ignore RESERVED devices. */
- stl_p(&rrb->response.fh_list[i].config,
- pbdev->state == ZPCI_FS_STANDBY ? 0 : 1 << 31);
- stl_p(&rrb->response.fh_list[i].fid, pbdev->fid);
- stl_p(&rrb->response.fh_list[i].fh, pbdev->fh);
+ stl_p(&rrb->response.fh_list[idx - resume_token].config,
+ pbdev->configured << 31);
+ stl_p(&rrb->response.fh_list[idx - resume_token].fid, pbdev->fid);
+ stl_p(&rrb->response.fh_list[idx - resume_token].fh, pbdev->fh);
g_l2 += sizeof(ClpFhListEntry);
/* Add endian check for DPRINTF? */
DPRINTF("g_l2 %d vendor id 0x%x device id 0x%x fid 0x%x fh 0x%x\n",
- g_l2,
- lduw_p(&rrb->response.fh_list[i].vendor_id),
- lduw_p(&rrb->response.fh_list[i].device_id),
- ldl_p(&rrb->response.fh_list[i].fid),
- ldl_p(&rrb->response.fh_list[i].fh));
- pbdev = s390_pci_find_next_avail_dev(pbdev);
- i++;
- }
-
- if (!pbdev) {
+ g_l2,
+ lduw_p(&rrb->response.fh_list[idx - resume_token].vendor_id),
+ lduw_p(&rrb->response.fh_list[idx - resume_token].device_id),
+ ldl_p(&rrb->response.fh_list[idx - resume_token].fid),
+ ldl_p(&rrb->response.fh_list[idx - resume_token].fh));
+ idx++;
+ } while (g_l2 < initial_l2);
+
+ if (finish == 1) {
resume_token = 0;
} else {
- resume_token = pbdev->fh & FH_MASK_INDEX;
+ resume_token = idx;
}
stq_p(&rrb->response.resume_token, resume_token);
stw_p(&rrb->response.hdr.len, g_l2);
@@ -210,35 +212,14 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
switch (reqsetpci->oc) {
case CLP_SET_ENABLE_PCI_FN:
- switch (reqsetpci->ndas) {
- case 0:
- stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_DMAAS);
- goto out;
- case 1:
- break;
- default:
- stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_RES);
- goto out;
- }
-
- if (pbdev->fh & FH_MASK_ENABLE) {
- stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
- goto out;
- }
-
- pbdev->fh |= FH_MASK_ENABLE;
- pbdev->state = ZPCI_FS_ENABLED;
+ pbdev->fh = pbdev->fh | FH_ENABLED;
stl_p(&ressetpci->fh, pbdev->fh);
stw_p(&ressetpci->hdr.rsp, CLP_RC_OK);
break;
case CLP_SET_DISABLE_PCI_FN:
- if (!(pbdev->fh & FH_MASK_ENABLE)) {
- stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
- goto out;
- }
- device_reset(DEVICE(pbdev));
- pbdev->fh &= ~FH_MASK_ENABLE;
- pbdev->state = ZPCI_FS_DISABLED;
+ pbdev->fh = pbdev->fh & ~FH_ENABLED;
+ pbdev->error_state = false;
+ pbdev->lgstg_blocked = false;
stl_p(&ressetpci->fh, pbdev->fh);
stw_p(&ressetpci->hdr.rsp, CLP_RC_OK);
break;
@@ -275,10 +256,9 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
stq_p(&resquery->sdma, ZPCI_SDMA_ADDR);
stq_p(&resquery->edma, ZPCI_EDMA_ADDR);
- stl_p(&resquery->fid, pbdev->fid);
stw_p(&resquery->pchid, 0);
stw_p(&resquery->ug, 1);
- stl_p(&resquery->uid, pbdev->uid);
+ stl_p(&resquery->uid, pbdev->fid);
stw_p(&resquery->hdr.rsp, CLP_RC_OK);
break;
}
@@ -337,25 +317,16 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
offset = env->regs[r2 + 1];
pbdev = s390_pci_find_dev_by_fh(fh);
- if (!pbdev) {
+ if (!pbdev || !(pbdev->fh & FH_ENABLED)) {
DPRINTF("pcilg no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
return 0;
}
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- case ZPCI_FS_STANDBY:
- case ZPCI_FS_DISABLED:
- case ZPCI_FS_PERMANENT_ERROR:
- setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
- return 0;
- case ZPCI_FS_ERROR:
+ if (pbdev->lgstg_blocked) {
setcc(cpu, ZPCI_PCI_LS_ERR);
s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED);
return 0;
- default:
- break;
}
if (pcias < 6) {
@@ -419,8 +390,7 @@ static void update_msix_table_msg_data(S390PCIBusDevice *pbdev, uint64_t offset,
msg_data = (uint8_t *)data - offset % PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_VECTOR_CTRL;
- val = pci_get_long(msg_data) |
- ((pbdev->fh & FH_MASK_INDEX) << ZPCI_MSI_VEC_BITS);
+ val = pci_get_long(msg_data) | (pbdev->fid << ZPCI_MSI_VEC_BITS);
pci_set_long(msg_data, val);
DPRINTF("update msix msg_data to 0x%" PRIx64 "\n", *data);
}
@@ -464,25 +434,16 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
offset = env->regs[r2 + 1];
pbdev = s390_pci_find_dev_by_fh(fh);
- if (!pbdev) {
+ if (!pbdev || !(pbdev->fh & FH_ENABLED)) {
DPRINTF("pcistg no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
return 0;
}
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- case ZPCI_FS_STANDBY:
- case ZPCI_FS_DISABLED:
- case ZPCI_FS_PERMANENT_ERROR:
- setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
- return 0;
- case ZPCI_FS_ERROR:
+ if (pbdev->lgstg_blocked) {
setcc(cpu, ZPCI_PCI_LS_ERR);
s390_set_status_code(env, r2, ZPCI_PCI_ST_BLOCKED);
return 0;
- default:
- break;
}
data = env->regs[r1];
@@ -564,55 +525,18 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
end = start + env->regs[r2 + 1];
pbdev = s390_pci_find_dev_by_fh(fh);
- if (!pbdev) {
+ if (!pbdev || !(pbdev->fh & FH_ENABLED)) {
DPRINTF("rpcit no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
goto out;
}
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- case ZPCI_FS_STANDBY:
- case ZPCI_FS_DISABLED:
- case ZPCI_FS_PERMANENT_ERROR:
- setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
- return 0;
- case ZPCI_FS_ERROR:
- setcc(cpu, ZPCI_PCI_LS_ERR);
- s390_set_status_code(env, r1, ZPCI_MOD_ST_ERROR_RECOVER);
- return 0;
- default:
- break;
- }
-
- if (!pbdev->g_iota) {
- pbdev->state = ZPCI_FS_ERROR;
- setcc(cpu, ZPCI_PCI_LS_ERR);
- s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
- s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,
- start, 0);
- goto out;
- }
-
- if (end < pbdev->pba || start > pbdev->pal) {
- pbdev->state = ZPCI_FS_ERROR;
- setcc(cpu, ZPCI_PCI_LS_ERR);
- s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
- s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,
- start, 0);
- goto out;
- }
-
mr = &pbdev->iommu_mr;
while (start < end) {
entry = mr->iommu_ops->translate(mr, start, 0);
if (!entry.translated_addr) {
- pbdev->state = ZPCI_FS_ERROR;
setcc(cpu, ZPCI_PCI_LS_ERR);
- s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
- s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,
- start, ERR_EVENT_Q_BIT);
goto out;
}
@@ -665,25 +589,16 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
}
pbdev = s390_pci_find_dev_by_fh(fh);
- if (!pbdev) {
+ if (!pbdev || !(pbdev->fh & FH_ENABLED)) {
DPRINTF("pcistb no pci dev fh 0x%x\n", fh);
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
return 0;
}
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- case ZPCI_FS_STANDBY:
- case ZPCI_FS_DISABLED:
- case ZPCI_FS_PERMANENT_ERROR:
- setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
- return 0;
- case ZPCI_FS_ERROR:
+ if (pbdev->lgstg_blocked) {
setcc(cpu, ZPCI_PCI_LS_ERR);
s390_set_status_code(env, r1, ZPCI_PCI_ST_BLOCKED);
return 0;
- default:
- break;
}
mr = pbdev->pdev->io_regions[pcias].memory;
@@ -719,15 +634,8 @@ static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long);
pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len);
- ret = map_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
- if (ret) {
- goto out;
- }
-
- ret = map_indicator(&pbdev->routes.adapter, pbdev->indicator);
- if (ret) {
- goto out;
- }
+ map_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
+ map_indicator(&pbdev->routes.adapter, pbdev->indicator);
pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb);
pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data));
@@ -739,15 +647,9 @@ static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
DPRINTF("reg_irqs adapter id %d\n", pbdev->routes.adapter.adapter_id);
return 0;
-out:
- release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
- release_indicator(&pbdev->routes.adapter, pbdev->indicator);
- pbdev->summary_ind = NULL;
- pbdev->indicator = NULL;
- return ret;
}
-int pci_dereg_irqs(S390PCIBusDevice *pbdev)
+static int dereg_irqs(S390PCIBusDevice *pbdev)
{
release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
release_indicator(&pbdev->routes.adapter, pbdev->indicator);
@@ -790,23 +692,24 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
pbdev->pal = pal;
pbdev->g_iota = g_iota;
- s390_pci_iommu_enable(pbdev);
+ s390_pcihost_iommu_configure(pbdev, true);
return 0;
}
-void pci_dereg_ioat(S390PCIBusDevice *pbdev)
+static void dereg_ioat(S390PCIBusDevice *pbdev)
{
- s390_pci_iommu_disable(pbdev);
pbdev->pba = 0;
pbdev->pal = 0;
pbdev->g_iota = 0;
+
+ s390_pcihost_iommu_configure(pbdev, false);
}
int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
{
CPUS390XState *env = &cpu->env;
- uint8_t oc, dmaas;
+ uint8_t oc;
uint32_t fh;
ZpciFib fib;
S390PCIBusDevice *pbdev;
@@ -818,7 +721,6 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
}
oc = env->regs[r1] & 0xff;
- dmaas = (env->regs[r1] >> 16) & 0xff;
fh = env->regs[r1] >> 32;
if (fiba & 0x7) {
@@ -827,108 +729,45 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
}
pbdev = s390_pci_find_dev_by_fh(fh);
- if (!pbdev) {
+ if (!pbdev || !(pbdev->fh & FH_ENABLED)) {
DPRINTF("mpcifc no pci dev fh 0x%x\n", fh);
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
return 0;
}
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- case ZPCI_FS_STANDBY:
- case ZPCI_FS_DISABLED:
- case ZPCI_FS_PERMANENT_ERROR:
- setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
- return 0;
- default:
- break;
- }
-
if (s390_cpu_virt_mem_read(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
return 0;
}
- if (fib.fmt != 0) {
- program_interrupt(env, PGM_OPERAND, 6);
- return 0;
- }
-
switch (oc) {
case ZPCI_MOD_FC_REG_INT:
- if (pbdev->summary_ind) {
+ if (reg_irqs(env, pbdev, fib)) {
cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
- } else if (reg_irqs(env, pbdev, fib)) {
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_RES_NOT_AVAIL);
}
break;
case ZPCI_MOD_FC_DEREG_INT:
- if (!pbdev->summary_ind) {
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
- } else {
- pci_dereg_irqs(pbdev);
- }
+ dereg_irqs(pbdev);
break;
case ZPCI_MOD_FC_REG_IOAT:
- if (dmaas != 0) {
+ if (reg_ioat(env, pbdev, fib)) {
cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
- } else if (pbdev->iommu_enabled) {
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
- } else if (reg_ioat(env, pbdev, fib)) {
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
}
break;
case ZPCI_MOD_FC_DEREG_IOAT:
- if (dmaas != 0) {
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
- } else if (!pbdev->iommu_enabled) {
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
- } else {
- pci_dereg_ioat(pbdev);
- }
+ dereg_ioat(pbdev);
break;
case ZPCI_MOD_FC_REREG_IOAT:
- if (dmaas != 0) {
+ dereg_ioat(pbdev);
+ if (reg_ioat(env, pbdev, fib)) {
cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
- } else if (!pbdev->iommu_enabled) {
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
- } else {
- pci_dereg_ioat(pbdev);
- if (reg_ioat(env, pbdev, fib)) {
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
- }
}
break;
case ZPCI_MOD_FC_RESET_ERROR:
- switch (pbdev->state) {
- case ZPCI_FS_BLOCKED:
- case ZPCI_FS_ERROR:
- pbdev->state = ZPCI_FS_ENABLED;
- break;
- default:
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
- }
+ pbdev->error_state = false;
+ pbdev->lgstg_blocked = false;
break;
case ZPCI_MOD_FC_RESET_BLOCK:
- switch (pbdev->state) {
- case ZPCI_FS_ERROR:
- pbdev->state = ZPCI_FS_BLOCKED;
- break;
- default:
- cc = ZPCI_PCI_LS_ERR;
- s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
- }
+ pbdev->lgstg_blocked = false;
break;
case ZPCI_MOD_FC_SET_MEASURE:
pbdev->fmb_addr = ldq_p(&fib.fmb_addr);
@@ -945,7 +784,6 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
{
CPUS390XState *env = &cpu->env;
- uint8_t dmaas;
uint32_t fh;
ZpciFib fib;
S390PCIBusDevice *pbdev;
@@ -958,59 +796,19 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
}
fh = env->regs[r1] >> 32;
- dmaas = (env->regs[r1] >> 16) & 0xff;
-
- if (dmaas) {
- setcc(cpu, ZPCI_PCI_LS_ERR);
- s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_INVAL_DMAAS);
- return 0;
- }
if (fiba & 0x7) {
program_interrupt(env, PGM_SPECIFICATION, 6);
return 0;
}
- pbdev = s390_pci_find_dev_by_idx(fh & FH_MASK_INDEX);
+ pbdev = s390_pci_find_dev_by_fh(fh);
if (!pbdev) {
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
return 0;
}
memset(&fib, 0, sizeof(fib));
-
- switch (pbdev->state) {
- case ZPCI_FS_RESERVED:
- case ZPCI_FS_STANDBY:
- setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
- return 0;
- case ZPCI_FS_DISABLED:
- if (fh & FH_MASK_ENABLE) {
- setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
- return 0;
- }
- goto out;
- /* BLOCKED bit is set to one coincident with the setting of ERROR bit.
- * FH Enabled bit is set to one in states of ENABLED, BLOCKED or ERROR. */
- case ZPCI_FS_ERROR:
- fib.fc |= 0x20;
- case ZPCI_FS_BLOCKED:
- fib.fc |= 0x40;
- case ZPCI_FS_ENABLED:
- fib.fc |= 0x80;
- if (pbdev->iommu_enabled) {
- fib.fc |= 0x10;
- }
- if (!(fh & FH_MASK_ENABLE)) {
- env->regs[r1] |= 1ULL << 63;
- }
- break;
- case ZPCI_FS_PERMANENT_ERROR:
- setcc(cpu, ZPCI_PCI_LS_ERR);
- s390_set_status_code(env, r1, ZPCI_STPCIFC_ST_PERM_ERROR);
- return 0;
- }
-
stq_p(&fib.pba, pbdev->pba);
stq_p(&fib.pal, pbdev->pal);
stq_p(&fib.iota, pbdev->g_iota);
@@ -1023,7 +821,22 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset;
stl_p(&fib.data, data);
-out:
+ if (pbdev->fh & FH_ENABLED) {
+ fib.fc |= 0x80;
+ }
+
+ if (pbdev->error_state) {
+ fib.fc |= 0x40;
+ }
+
+ if (pbdev->lgstg_blocked) {
+ fib.fc |= 0x20;
+ }
+
+ if (pbdev->g_iota) {
+ fib.fc |= 0x10;
+ }
+
if (s390_cpu_virt_mem_write(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
return 0;
}
diff --git a/hw/s390x/s390-pci-inst.h b/hw/s390x/s390-pci-inst.h
index 23f4bfa0e..70fa71395 100644
--- a/hw/s390x/s390-pci-inst.h
+++ b/hw/s390x/s390-pci-inst.h
@@ -14,8 +14,7 @@
#ifndef HW_S390_PCI_INST_H
#define HW_S390_PCI_INST_H
-#include "s390-pci-bus.h"
-#include "sysemu/dma.h"
+#include <sysemu/dma.h>
/* CLP common request & response block size */
#define CLP_BLK_SIZE 4096
@@ -104,7 +103,7 @@ typedef struct ClpRspListPci {
uint64_t resume_token;
uint32_t mdd;
uint16_t max_fn;
- uint8_t flags;
+ uint8_t reserved2;
uint8_t entry_size;
ClpFhListEntry fh_list[CLP_FH_LIST_NR_ENTRIES];
} QEMU_PACKED ClpRspListPci;
@@ -231,14 +230,6 @@ typedef struct ClpReqRspQueryPciGrp {
#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
@@ -249,11 +240,6 @@ typedef struct ClpReqRspQueryPciGrp {
#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
-
/* FIB function controls */
#define ZPCI_FIB_FC_ENABLED 0x80
#define ZPCI_FIB_FC_ERROR 0x40
@@ -291,8 +277,6 @@ typedef struct ZpciFib {
uint32_t gd;
} QEMU_PACKED ZpciFib;
-int pci_dereg_irqs(S390PCIBusDevice *pbdev);
-void pci_dereg_ioat(S390PCIBusDevice *pbdev);
int clp_service_call(S390CPU *cpu, uint8_t r2);
int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index e2d4e1af7..6528ffed1 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -15,7 +15,6 @@
#include "migration/qemu-file.h"
#include "hw/s390x/storage-keys.h"
#include "qemu/error-report.h"
-#include "sysemu/kvm.h"
#define S390_SKEYS_BUFFER_SIZE 131072 /* Room for 128k storage keys */
#define S390_SKEYS_SAVE_FLAG_EOS 0x01
@@ -47,11 +46,15 @@ void s390_skeys_init(void)
qdev_init_nofail(DEVICE(obj));
}
-static void write_keys(FILE *f, uint8_t *keys, uint64_t startgfn,
+static void write_keys(QEMUFile *f, uint8_t *keys, uint64_t startgfn,
uint64_t count, Error **errp)
{
uint64_t curpage = startgfn;
uint64_t maxpage = curpage + count - 1;
+ const char *fmt = "page=%03" PRIx64 ": key(%d) => ACC=%X, FP=%d, REF=%d,"
+ " ch=%d, reserved=%d\n";
+ char buf[128];
+ int len;
for (; curpage <= maxpage; curpage++) {
uint8_t acc = (*keys & 0xF0) >> 4;
@@ -60,9 +63,10 @@ static void write_keys(FILE *f, uint8_t *keys, uint64_t startgfn,
int ch = (*keys & 0x02);
int res = (*keys & 0x01);
- fprintf(f, "page=%03" PRIx64 ": key(%d) => ACC=%X, FP=%d, REF=%d,"
- " ch=%d, reserved=%d\n",
- curpage, *keys, acc, fp, ref, ch, res);
+ len = snprintf(buf, sizeof(buf), fmt, curpage,
+ *keys, acc, fp, ref, ch, res);
+ assert(len < sizeof(buf));
+ qemu_put_buffer(f, (uint8_t *)buf, len);
keys++;
}
}
@@ -111,8 +115,7 @@ void qmp_dump_skeys(const char *filename, Error **errp)
vaddr cur_gfn = 0;
uint8_t *buf;
int ret;
- int fd;
- FILE *f;
+ QEMUFile *f;
/* Quick check to see if guest is using storage keys*/
if (!skeyclass->skeys_enabled(ss)) {
@@ -121,14 +124,8 @@ void qmp_dump_skeys(const char *filename, Error **errp)
return;
}
- fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (fd < 0) {
- error_setg_file_open(errp, errno, filename);
- return;
- }
- f = fdopen(fd, "wb");
+ f = qemu_fopen(filename, "wb");
if (!f) {
- close(fd);
error_setg_file_open(errp, errno, filename);
return;
}
@@ -164,7 +161,7 @@ out_free:
error_propagate(errp, lerr);
g_free(buf);
out:
- fclose(f);
+ qemu_fclose(f);
}
static void qemu_s390_skeys_init(Object *obj)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 91d9cefbb..e3df9c78b 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -18,19 +18,17 @@
#include "s390-virtio.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
-#include "hw/s390x/ioinst.h"
-#include "hw/s390x/css.h"
+#include "ioinst.h"
+#include "css.h"
#include "virtio-ccw.h"
#include "qemu/config-file.h"
#include "s390-pci-bus.h"
#include "hw/s390x/storage-keys.h"
#include "hw/compat.h"
-#include "ipl.h"
#include "hw/s390x/s390-virtio-ccw.h"
-#include "hw/s390x/css-bridge.h"
static const char *const reset_dev_types[] = {
- TYPE_VIRTUAL_CSS_BRIDGE,
+ "virtual-css-bridge",
"s390-sclp-event-facility",
"s390-flic",
"diag288",
@@ -181,8 +179,10 @@ static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
static void s390_hot_add_cpu(const int64_t id, Error **errp)
{
MachineState *machine = MACHINE(qdev_get_machine());
+ Error *err = NULL;
- s390x_new_cpu(machine->cpu_model, id, errp);
+ s390x_new_cpu(machine->cpu_model, id, &err);
+ error_propagate(errp, err);
}
static void ccw_machine_class_init(ObjectClass *oc, void *data)
@@ -190,9 +190,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
MachineClass *mc = MACHINE_CLASS(oc);
NMIClass *nc = NMI_CLASS(oc);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
- S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
- s390mc->ri_allowed = true;
mc->init = ccw_init;
mc->reset = s390_machine_reset;
mc->hot_add_cpu = s390_hot_add_cpu;
@@ -203,7 +201,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
mc->no_parallel = 1;
mc->no_sdcard = 1;
mc->use_sclp = 1;
- mc->max_cpus = 248;
+ mc->max_cpus = 255;
mc->get_hotplug_handler = s390_get_hotplug_handler;
hc->plug = s390_machine_device_plug;
nc->nmi_monitor_handler = s390_nmi;
@@ -239,20 +237,6 @@ static inline void machine_set_dea_key_wrap(Object *obj, bool value,
ms->dea_key_wrap = value;
}
-bool ri_allowed(void)
-{
- if (kvm_enabled()) {
- MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
- if (object_class_dynamic_cast(OBJECT_CLASS(mc),
- TYPE_S390_CCW_MACHINE)) {
- S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
-
- return s390mc->ri_allowed;
- }
- }
- return 0;
-}
-
static inline void s390_machine_initfn(Object *obj)
{
object_property_add_bool(obj, "aes-key-wrap",
@@ -278,7 +262,6 @@ static const TypeInfo ccw_machine_info = {
.abstract = true,
.instance_size = sizeof(S390CcwMachineState),
.instance_init = s390_machine_initfn,
- .class_size = sizeof(S390CcwMachineClass),
.class_init = ccw_machine_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_NMI },
@@ -316,23 +299,11 @@ static const TypeInfo ccw_machine_info = {
} \
type_init(ccw_machine_register_##suffix)
-#define CCW_COMPAT_2_6 \
- HW_COMPAT_2_6 \
- {\
- .driver = TYPE_S390_IPL,\
- .property = "iplbext_migration",\
- .value = "off",\
- }, {\
- .driver = TYPE_VIRTUAL_CSS_BRIDGE,\
- .property = "css_dev_path",\
- .value = "off",\
- },
-
#define CCW_COMPAT_2_5 \
- CCW_COMPAT_2_6 \
HW_COMPAT_2_5
#define CCW_COMPAT_2_4 \
+ CCW_COMPAT_2_5 \
HW_COMPAT_2_4 \
{\
.driver = TYPE_S390_SKEYS,\
@@ -372,38 +343,21 @@ static const TypeInfo ccw_machine_info = {
.value = "0",\
},
-static void ccw_machine_2_7_instance_options(MachineState *machine)
-{
-}
-
-static void ccw_machine_2_7_class_options(MachineClass *mc)
-{
-}
-DEFINE_CCW_MACHINE(2_7, "2.7", true);
-
static void ccw_machine_2_6_instance_options(MachineState *machine)
{
- ccw_machine_2_7_instance_options(machine);
}
static void ccw_machine_2_6_class_options(MachineClass *mc)
{
- S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
-
- s390mc->ri_allowed = false;
- ccw_machine_2_7_class_options(mc);
- SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_6);
}
-DEFINE_CCW_MACHINE(2_6, "2.6", false);
+DEFINE_CCW_MACHINE(2_6, "2.6", true);
static void ccw_machine_2_5_instance_options(MachineState *machine)
{
- ccw_machine_2_6_instance_options(machine);
}
static void ccw_machine_2_5_class_options(MachineClass *mc)
{
- ccw_machine_2_6_class_options(mc);
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_5);
}
DEFINE_CCW_MACHINE(2_5, "2.5", false);
@@ -415,7 +369,6 @@ static void ccw_machine_2_4_instance_options(MachineState *machine)
static void ccw_machine_2_4_class_options(MachineClass *mc)
{
- ccw_machine_2_5_class_options(mc);
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_4);
}
DEFINE_CCW_MACHINE(2_4, "2.4", false);
diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h
index f588b80a6..ffd014cb5 100644
--- a/hw/s390x/s390-virtio.h
+++ b/hw/s390x/s390-virtio.h
@@ -10,7 +10,7 @@
*/
#ifndef HW_S390_VIRTIO_H
-#define HW_S390_VIRTIO_H
+#define HW_S390_VIRTIO_H 1
#include "hw/nmi.h"
#include "standard-headers/asm-s390/kvm_virtio.h"
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index fca37f511..85dbe1b60 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -357,10 +357,10 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
sclp_c->unassign_storage(sclp, sccb);
break;
case SCLP_CMDW_CONFIGURE_PCI:
- s390_pci_sclp_configure(sccb);
+ s390_pci_sclp_configure(1, sccb);
break;
case SCLP_CMDW_DECONFIGURE_PCI:
- s390_pci_sclp_deconfigure(sccb);
+ s390_pci_sclp_configure(0, sccb);
break;
default:
efc->command_handler(ef, sccb, code);
diff --git a/hw/s390x/sclpquiesce.c b/hw/s390x/sclpquiesce.c
index 762cb184a..c0ecab9c3 100644
--- a/hw/s390x/sclpquiesce.c
+++ b/hw/s390x/sclpquiesce.c
@@ -12,7 +12,7 @@
*
*/
#include "qemu/osdep.h"
-#include "hw/qdev.h"
+#include <hw/qdev.h>
#include "sysemu/sysemu.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/event-facility.h"
diff --git a/hw/s390x/trace-events b/hw/s390x/trace-events
deleted file mode 100644
index 84ea96487..000000000
--- a/hw/s390x/trace-events
+++ /dev/null
@@ -1,15 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/s390x/css.c
-css_enable_facility(const char *facility) "CSS: enable %s"
-css_crw(uint8_t rsc, uint8_t erc, uint16_t rsid, const char *chained) "CSS: queueing crw: rsc=%x, erc=%x, rsid=%x %s"
-css_chpid_add(uint8_t cssid, uint8_t chpid, uint8_t type) "CSS: add chpid %x.%02x (type %02x)"
-css_new_image(uint8_t cssid, const char *default_cssid) "CSS: add css image %02x %s"
-css_assign_subch(const char *do_assign, uint8_t cssid, uint8_t ssid, uint16_t schid, uint16_t devno) "CSS: %s %x.%x.%04x (devno %04x)"
-css_io_interrupt(int cssid, int ssid, int schid, uint32_t intparm, uint8_t isc, const char *conditional) "CSS: I/O interrupt on sch %x.%x.%04x (intparm %08x, isc %x) %s"
-css_adapter_interrupt(uint8_t isc) "CSS: adapter I/O interrupt (isc %x)"
-
-# hw/s390x/virtio-ccw.c
-virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) "VIRTIO-CCW: %x.%x.%04x: interpret command %x"
-virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char *devno_mode) "VIRTIO-CCW: add subchannel %x.%x.%04x, devno %04x (%s)"
-virtio_ccw_set_ind(uint64_t ind_loc, uint8_t ind_old, uint8_t ind_new) "VIRTIO-CCW: indicator at %" PRIu64 ": %x->%x"
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index a554a24d0..d51642db0 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -16,7 +16,6 @@
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
#include "sysemu/sysemu.h"
-#include "sysemu/kvm.h"
#include "net/net.h"
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-serial.h"
@@ -29,15 +28,35 @@
#include "hw/s390x/adapter.h"
#include "hw/s390x/s390_flic.h"
-#include "hw/s390x/ioinst.h"
-#include "hw/s390x/css.h"
+#include "ioinst.h"
+#include "css.h"
#include "virtio-ccw.h"
#include "trace.h"
-#include "hw/s390x/css-bridge.h"
static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
VirtioCcwDevice *dev);
+static void virtual_css_bus_reset(BusState *qbus)
+{
+ /* This should actually be modelled via the generic css */
+ css_reset();
+}
+
+
+static void virtual_css_bus_class_init(ObjectClass *klass, void *data)
+{
+ BusClass *k = BUS_CLASS(klass);
+
+ k->reset = virtual_css_bus_reset;
+}
+
+static const TypeInfo virtual_css_bus_info = {
+ .name = TYPE_VIRTUAL_CSS_BUS,
+ .parent = TYPE_BUS,
+ .instance_size = sizeof(VirtualCssBus),
+ .class_init = virtual_css_bus_class_init,
+};
+
VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
{
VirtIODevice *vdev = NULL;
@@ -49,59 +68,112 @@ VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
return vdev;
}
-static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
+static int virtio_ccw_set_guest2host_notifier(VirtioCcwDevice *dev, int n,
+ bool assign, bool set_handler)
{
- virtio_bus_start_ioeventfd(&dev->bus);
-}
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
+ EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
+ int r = 0;
+ SubchDev *sch = dev->sch;
+ uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
-static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
-{
- virtio_bus_stop_ioeventfd(&dev->bus);
+ if (assign) {
+ r = event_notifier_init(notifier, 1);
+ if (r < 0) {
+ error_report("%s: unable to init event notifier: %d", __func__, r);
+ return r;
+ }
+ virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
+ r = s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
+ if (r < 0) {
+ error_report("%s: unable to assign ioeventfd: %d", __func__, r);
+ virtio_queue_set_host_notifier_fd_handler(vq, false, false);
+ event_notifier_cleanup(notifier);
+ return r;
+ }
+ } else {
+ virtio_queue_set_host_notifier_fd_handler(vq, false, false);
+ s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
+ event_notifier_cleanup(notifier);
+ }
+ return r;
}
-static bool virtio_ccw_ioeventfd_started(DeviceState *d)
+static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
{
- VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
-
- return dev->ioeventfd_started;
-}
+ VirtIODevice *vdev;
+ int n, r;
-static void virtio_ccw_ioeventfd_set_started(DeviceState *d, bool started,
- bool err)
-{
- VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ if (!(dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD) ||
+ dev->ioeventfd_disabled ||
+ dev->ioeventfd_started) {
+ return;
+ }
+ vdev = virtio_bus_get_device(&dev->bus);
+ for (n = 0; n < VIRTIO_CCW_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+ r = virtio_ccw_set_guest2host_notifier(dev, n, true, true);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+ dev->ioeventfd_started = true;
+ return;
- dev->ioeventfd_started = started;
- if (err) {
- /* Disable ioeventfd for this device. */
- dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD;
+ assign_error:
+ while (--n >= 0) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+ r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
+ assert(r >= 0);
}
+ dev->ioeventfd_started = false;
+ /* Disable ioeventfd for this device. */
+ dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD;
+ error_report("%s: failed. Fallback to userspace (slower).", __func__);
}
-static bool virtio_ccw_ioeventfd_disabled(DeviceState *d)
+static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
{
- VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ VirtIODevice *vdev;
+ int n, r;
- return dev->ioeventfd_disabled ||
- !(dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD);
+ if (!dev->ioeventfd_started) {
+ return;
+ }
+ vdev = virtio_bus_get_device(&dev->bus);
+ for (n = 0; n < VIRTIO_CCW_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+ r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
+ assert(r >= 0);
+ }
+ dev->ioeventfd_started = false;
}
-static void virtio_ccw_ioeventfd_set_disabled(DeviceState *d, bool disabled)
+VirtualCssBus *virtual_css_bus_init(void)
{
- VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ VirtualCssBus *cbus;
+ BusState *bus;
+ DeviceState *dev;
- dev->ioeventfd_disabled = disabled;
-}
+ /* Create bridge device */
+ dev = qdev_create(NULL, "virtual-css-bridge");
+ qdev_init_nofail(dev);
-static int virtio_ccw_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
- int n, bool assign)
-{
- VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
- CcwDevice *ccw_dev = CCW_DEVICE(dev);
- SubchDev *sch = ccw_dev->sch;
- uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
+ /* Create bus on bridge device */
+ bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
+ cbus = VIRTUAL_CSS_BUS(bus);
+
+ /* Enable hotplugging */
+ qbus_set_hotplug_handler(bus, dev, &error_abort);
- return s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
+ return cbus;
}
/* Communication blocks used by several channel commands. */
@@ -195,8 +267,6 @@ static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
{
- CcwDevice *ccw_dev = CCW_DEVICE(dev);
-
virtio_ccw_stop_ioeventfd(dev);
virtio_reset(vdev);
if (dev->indicators) {
@@ -211,7 +281,7 @@ static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
release_indicator(&dev->routes.adapter, dev->summary_indicator);
dev->summary_indicator = NULL;
}
- ccw_dev->sch->thinint_active = false;
+ dev->sch->thinint_active = false;
}
static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
@@ -666,44 +736,151 @@ static void virtio_sch_disable_cb(SubchDev *sch)
static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
{
- VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
- CcwDevice *ccw_dev = CCW_DEVICE(dev);
- SubchDev *sch = css_create_virtual_sch(ccw_dev->bus_id, errp);
+ unsigned int cssid = 0;
+ unsigned int ssid = 0;
+ unsigned int schid;
+ unsigned int devno;
+ bool have_devno = false;
+ bool found = false;
+ SubchDev *sch;
+ int num;
Error *err = NULL;
+ VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
- if (!sch) {
- return;
- }
+ sch = g_malloc0(sizeof(SubchDev));
sch->driver_data = dev;
+ dev->sch = sch;
+
+ dev->indicators = NULL;
+
+ /* Initialize subchannel structure. */
+ sch->channel_prog = 0x0;
+ sch->last_cmd_valid = false;
+ sch->thinint_active = false;
+ /*
+ * Use a device number if provided. Otherwise, fall back to subchannel
+ * number.
+ */
+ if (dev->bus_id) {
+ num = sscanf(dev->bus_id, "%x.%x.%04x", &cssid, &ssid, &devno);
+ if (num == 3) {
+ if ((cssid > MAX_CSSID) || (ssid > MAX_SSID)) {
+ error_setg(errp, "Invalid cssid or ssid: cssid %x, ssid %x",
+ cssid, ssid);
+ goto out_err;
+ }
+ /* Enforce use of virtual cssid. */
+ if (cssid != VIRTUAL_CSSID) {
+ error_setg(errp, "cssid %x not valid for virtio devices",
+ cssid);
+ goto out_err;
+ }
+ if (css_devno_used(cssid, ssid, devno)) {
+ error_setg(errp, "Device %x.%x.%04x already exists",
+ cssid, ssid, devno);
+ goto out_err;
+ }
+ sch->cssid = cssid;
+ sch->ssid = ssid;
+ sch->devno = devno;
+ have_devno = true;
+ } else {
+ error_setg(errp, "Malformed devno parameter '%s'", dev->bus_id);
+ goto out_err;
+ }
+ }
+
+ /* Find the next free id. */
+ if (have_devno) {
+ for (schid = 0; schid <= MAX_SCHID; schid++) {
+ if (!css_find_subch(1, cssid, ssid, schid)) {
+ sch->schid = schid;
+ css_subch_assign(cssid, ssid, schid, devno, sch);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ error_setg(errp, "No free subchannel found for %x.%x.%04x",
+ cssid, ssid, devno);
+ goto out_err;
+ }
+ trace_virtio_ccw_new_device(cssid, ssid, schid, devno,
+ "user-configured");
+ } else {
+ cssid = VIRTUAL_CSSID;
+ for (ssid = 0; ssid <= MAX_SSID; ssid++) {
+ for (schid = 0; schid <= MAX_SCHID; schid++) {
+ if (!css_find_subch(1, cssid, ssid, schid)) {
+ sch->cssid = cssid;
+ sch->ssid = ssid;
+ sch->schid = schid;
+ devno = schid;
+ /*
+ * If the devno is already taken, look further in this
+ * subchannel set.
+ */
+ while (css_devno_used(cssid, ssid, devno)) {
+ if (devno == MAX_SCHID) {
+ devno = 0;
+ } else if (devno == schid - 1) {
+ error_setg(errp, "No free devno found");
+ goto out_err;
+ } else {
+ devno++;
+ }
+ }
+ sch->devno = devno;
+ css_subch_assign(cssid, ssid, schid, devno, sch);
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+ }
+ if (!found) {
+ error_setg(errp, "Virtual channel subsystem is full!");
+ goto out_err;
+ }
+ trace_virtio_ccw_new_device(cssid, ssid, schid, devno,
+ "auto-configured");
+ }
+
+ /* Build initial schib. */
+ css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE);
+
sch->ccw_cb = virtio_ccw_cb;
sch->disable_cb = virtio_sch_disable_cb;
+
+ /* Build senseid data. */
+ memset(&sch->id, 0, sizeof(SenseId));
sch->id.reserved = 0xff;
sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
- ccw_dev->sch = sch;
- dev->indicators = NULL;
- dev->revision = -1;
- css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE);
- trace_virtio_ccw_new_device(
- sch->cssid, sch->ssid, sch->schid, sch->devno,
- ccw_dev->bus_id.valid ? "user-configured" : "auto-configured");
+ dev->revision = -1;
if (k->realize) {
k->realize(dev, &err);
}
if (err) {
error_propagate(errp, err);
- css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
- ccw_dev->sch = NULL;
- g_free(sch);
+ css_subch_assign(cssid, ssid, schid, devno, NULL);
+ goto out_err;
}
+
+ return;
+
+out_err:
+ dev->sch = NULL;
+ g_free(sch);
}
static int virtio_ccw_exit(VirtioCcwDevice *dev)
{
- CcwDevice *ccw_dev = CCW_DEVICE(dev);
- SubchDev *sch = ccw_dev->sch;
+ SubchDev *sch = dev->sch;
if (sch) {
css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
@@ -721,11 +898,15 @@ static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp)
DeviceState *qdev = DEVICE(ccw_dev);
VirtIONetCcw *dev = VIRTIO_NET_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
+ Error *err = NULL;
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
object_get_typename(OBJECT(qdev)));
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
- object_property_set_bool(OBJECT(vdev), true, "realized", errp);
+ object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ }
}
static void virtio_ccw_net_instance_init(Object *obj)
@@ -742,9 +923,13 @@ static void virtio_ccw_blk_realize(VirtioCcwDevice *ccw_dev, Error **errp)
{
VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
+ Error *err = NULL;
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
- object_property_set_bool(OBJECT(vdev), true, "realized", errp);
+ object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ }
}
static void virtio_ccw_blk_instance_init(Object *obj)
@@ -764,6 +949,7 @@ static void virtio_ccw_serial_realize(VirtioCcwDevice *ccw_dev, Error **errp)
VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
DeviceState *proxy = DEVICE(ccw_dev);
+ Error *err = NULL;
char *bus_name;
/*
@@ -777,7 +963,10 @@ static void virtio_ccw_serial_realize(VirtioCcwDevice *ccw_dev, Error **errp)
}
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
- object_property_set_bool(OBJECT(vdev), true, "realized", errp);
+ object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ }
}
@@ -793,9 +982,13 @@ static void virtio_ccw_balloon_realize(VirtioCcwDevice *ccw_dev, Error **errp)
{
VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
+ Error *err = NULL;
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
- object_property_set_bool(OBJECT(vdev), true, "realized", errp);
+ object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ }
}
static void virtio_ccw_balloon_instance_init(Object *obj)
@@ -816,6 +1009,7 @@ static void virtio_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp)
VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
DeviceState *qdev = DEVICE(ccw_dev);
+ Error *err = NULL;
char *bus_name;
/*
@@ -829,7 +1023,10 @@ static void virtio_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp)
}
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
- object_property_set_bool(OBJECT(vdev), true, "realized", errp);
+ object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ }
}
static void virtio_ccw_scsi_instance_init(Object *obj)
@@ -847,9 +1044,13 @@ static void vhost_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp)
{
VHostSCSICcw *dev = VHOST_SCSI_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
+ Error *err = NULL;
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
- object_property_set_bool(OBJECT(vdev), true, "realized", errp);
+ object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ }
}
static void vhost_ccw_scsi_instance_init(Object *obj)
@@ -884,9 +1085,7 @@ static void virtio_ccw_rng_realize(VirtioCcwDevice *ccw_dev, Error **errp)
*/
static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d)
{
- CcwDevice *ccw_dev = to_ccw_dev_fast(d);
-
- return container_of(ccw_dev, VirtioCcwDevice, parent_obj);
+ return container_of(d, VirtioCcwDevice, parent_obj);
}
static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
@@ -906,7 +1105,6 @@ static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
ind_old = *ind_addr;
ind_new = ind_old | to_be_set;
} while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old);
- trace_virtio_ccw_set_ind(ind_loc, ind_old, ind_new);
cpu_physical_memory_unmap(ind_addr, len, 1, len);
return ind_old;
@@ -915,8 +1113,7 @@ static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
{
VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d);
- CcwDevice *ccw_dev = to_ccw_dev_fast(d);
- SubchDev *sch = ccw_dev->sch;
+ SubchDev *sch = dev->sch;
uint64_t indicators;
/* queue indicators + secondary indicators */
@@ -974,10 +1171,9 @@ static void virtio_ccw_reset(DeviceState *d)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
- CcwDevice *ccw_dev = CCW_DEVICE(d);
virtio_ccw_reset_virtio(dev, vdev);
- css_reset_sch(ccw_dev->sch);
+ css_reset_sch(dev->sch);
}
static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
@@ -993,17 +1189,29 @@ static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
{
- CcwDevice *dev = CCW_DEVICE(d);
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
}
+static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+
+ /* Stop using the generic ioeventfd, we are doing eventfd handling
+ * ourselves below */
+ dev->ioeventfd_disabled = assign;
+ if (assign) {
+ virtio_ccw_stop_ioeventfd(dev);
+ }
+ return virtio_ccw_set_guest2host_notifier(dev, n, assign, false);
+}
+
static int virtio_ccw_get_mappings(VirtioCcwDevice *dev)
{
int r;
- CcwDevice *ccw_dev = CCW_DEVICE(dev);
- if (!ccw_dev->sch->thinint_active) {
+ if (!dev->sch->thinint_active) {
return -EINVAL;
}
@@ -1125,8 +1333,7 @@ static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
- CcwDevice *ccw_dev = CCW_DEVICE(d);
- bool with_irqfd = ccw_dev->sch->thinint_active && kvm_irqfds_enabled();
+ bool with_irqfd = dev->sch->thinint_active && kvm_irqfds_enabled();
int r, n;
if (with_irqfd && assigned) {
@@ -1185,8 +1392,7 @@ static int virtio_ccw_load_queue(DeviceState *d, int n, QEMUFile *f)
static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
- CcwDevice *ccw_dev = CCW_DEVICE(d);
- SubchDev *s = ccw_dev->sch;
+ SubchDev *s = dev->sch;
VirtIODevice *vdev = virtio_ccw_get_vdev(s);
subch_device_save(s, f);
@@ -1220,8 +1426,7 @@ static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
- CcwDevice *ccw_dev = CCW_DEVICE(d);
- SubchDev *s = ccw_dev->sch;
+ SubchDev *s = dev->sch;
VirtIODevice *vdev = virtio_ccw_get_vdev(s);
int len;
@@ -1266,12 +1471,11 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
- CcwDevice *ccw_dev = CCW_DEVICE(d);
- SubchDev *sch = ccw_dev->sch;
+ SubchDev *sch = dev->sch;
int n = virtio_get_num_queues(vdev);
if (virtio_get_num_queues(vdev) > VIRTIO_CCW_QUEUE_MAX) {
- error_setg(errp, "The number of virtqueues %d "
+ error_setg(errp, "The nubmer of virtqueues %d "
"exceeds ccw limit %d", n,
VIRTIO_CCW_QUEUE_MAX);
return;
@@ -1311,7 +1515,7 @@ static void virtio_ccw_device_unplugged(DeviceState *d)
/**************** Virtio-ccw Bus Device Descriptions *******************/
static Property virtio_ccw_net_properties[] = {
- DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
+ DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1340,7 +1544,7 @@ static const TypeInfo virtio_ccw_net = {
};
static Property virtio_ccw_blk_properties[] = {
- DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
+ DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1369,7 +1573,7 @@ static const TypeInfo virtio_ccw_blk = {
};
static Property virtio_ccw_serial_properties[] = {
- DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
+ DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1398,7 +1602,7 @@ static const TypeInfo virtio_ccw_serial = {
};
static Property virtio_ccw_balloon_properties[] = {
- DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
+ DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1427,7 +1631,7 @@ static const TypeInfo virtio_ccw_balloon = {
};
static Property virtio_ccw_scsi_properties[] = {
- DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
+ DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1457,7 +1661,7 @@ static const TypeInfo virtio_ccw_scsi = {
#ifdef CONFIG_VHOST_SCSI
static Property vhost_ccw_scsi_properties[] = {
- DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
+ DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
VIRTIO_CCW_MAX_REV),
DEFINE_PROP_END_OF_LIST(),
@@ -1495,7 +1699,7 @@ static void virtio_ccw_rng_instance_init(Object *obj)
}
static Property virtio_ccw_rng_properties[] = {
- DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
+ DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1542,17 +1746,29 @@ static int virtio_ccw_busdev_exit(DeviceState *dev)
static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- VirtioCcwDevice *_dev = to_virtio_ccw_dev_fast(dev);
+ VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
+ SubchDev *sch = _dev->sch;
virtio_ccw_stop_ioeventfd(_dev);
+
+ /*
+ * We should arrive here only for device_del, since we don't support
+ * direct hot(un)plug of channels, but only through virtio.
+ */
+ assert(sch != NULL);
+ /* Subchannel is now disabled and no longer valid. */
+ sch->curr_status.pmcw.flags &= ~(PMCW_FLAGS_MASK_ENA |
+ PMCW_FLAGS_MASK_DNV);
+
+ css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
+
+ object_unparent(OBJECT(dev));
}
static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- CCWDeviceClass *k = CCW_DEVICE_CLASS(dc);
- k->unplug = virtio_ccw_busdev_unplug;
dc->realize = virtio_ccw_busdev_realize;
dc->exit = virtio_ccw_busdev_exit;
dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
@@ -1560,13 +1776,44 @@ static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
static const TypeInfo virtio_ccw_device_info = {
.name = TYPE_VIRTIO_CCW_DEVICE,
- .parent = TYPE_CCW_DEVICE,
+ .parent = TYPE_DEVICE,
.instance_size = sizeof(VirtioCcwDevice),
.class_init = virtio_ccw_device_class_init,
.class_size = sizeof(VirtIOCCWDeviceClass),
.abstract = true,
};
+/***************** Virtual-css Bus Bridge Device ********************/
+/* Only required to have the virtio bus as child in the system bus */
+
+static int virtual_css_bridge_init(SysBusDevice *dev)
+{
+ /* nothing */
+ return 0;
+}
+
+static void virtual_css_bridge_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = virtual_css_bridge_init;
+ hc->unplug = virtio_ccw_busdev_unplug;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+}
+
+static const TypeInfo virtual_css_bridge_info = {
+ .name = "virtual-css-bridge",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SysBusDevice),
+ .class_init = virtual_css_bridge_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ }
+};
+
/* virtio-ccw-bus */
static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
@@ -1588,6 +1835,7 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
k->notify = virtio_ccw_notify;
k->vmstate_change = virtio_ccw_vmstate_change;
k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
+ k->set_host_notifier = virtio_ccw_set_host_notifier;
k->set_guest_notifiers = virtio_ccw_set_guest_notifiers;
k->save_queue = virtio_ccw_save_queue;
k->load_queue = virtio_ccw_load_queue;
@@ -1596,11 +1844,6 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
k->device_plugged = virtio_ccw_device_plugged;
k->post_plugged = virtio_ccw_post_plugged;
k->device_unplugged = virtio_ccw_device_unplugged;
- k->ioeventfd_started = virtio_ccw_ioeventfd_started;
- k->ioeventfd_set_started = virtio_ccw_ioeventfd_set_started;
- k->ioeventfd_disabled = virtio_ccw_ioeventfd_disabled;
- k->ioeventfd_set_disabled = virtio_ccw_ioeventfd_set_disabled;
- k->ioeventfd_assign = virtio_ccw_ioeventfd_assign;
}
static const TypeInfo virtio_ccw_bus_info = {
@@ -1612,7 +1855,7 @@ static const TypeInfo virtio_ccw_bus_info = {
#ifdef CONFIG_VIRTFS
static Property virtio_ccw_9p_properties[] = {
- DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
+ DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
@@ -1624,9 +1867,13 @@ static void virtio_ccw_9p_realize(VirtioCcwDevice *ccw_dev, Error **errp)
{
V9fsCCWState *dev = VIRTIO_9P_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
+ Error *err = NULL;
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
- object_property_set_bool(OBJECT(vdev), true, "realized", errp);
+ object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ }
}
static void virtio_ccw_9p_class_init(ObjectClass *klass, void *data)
@@ -1661,6 +1908,7 @@ static const TypeInfo virtio_ccw_9p_info = {
static void virtio_ccw_register(void)
{
type_register_static(&virtio_ccw_bus_info);
+ type_register_static(&virtual_css_bus_info);
type_register_static(&virtio_ccw_device_info);
type_register_static(&virtio_ccw_serial);
type_register_static(&virtio_ccw_blk);
@@ -1671,6 +1919,7 @@ static void virtio_ccw_register(void)
type_register_static(&vhost_ccw_scsi);
#endif
type_register_static(&virtio_ccw_rng);
+ type_register_static(&virtual_css_bridge_info);
#ifdef CONFIG_VIRTFS
type_register_static(&virtio_ccw_9p_info);
#endif
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 1c6bc8631..66c831ba8 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -13,21 +13,20 @@
#ifndef HW_S390X_VIRTIO_CCW_H
#define HW_S390X_VIRTIO_CCW_H
-#include "hw/virtio/virtio-blk.h"
-#include "hw/virtio/virtio-net.h"
-#include "hw/virtio/virtio-serial.h"
-#include "hw/virtio/virtio-scsi.h"
+#include <hw/virtio/virtio-blk.h>
+#include <hw/virtio/virtio-net.h>
+#include <hw/virtio/virtio-serial.h>
+#include <hw/virtio/virtio-scsi.h>
#ifdef CONFIG_VHOST_SCSI
-#include "hw/virtio/vhost-scsi.h"
+#include <hw/virtio/vhost-scsi.h>
#endif
-#include "hw/virtio/virtio-balloon.h"
-#include "hw/virtio/virtio-rng.h"
-#include "hw/virtio/virtio-bus.h"
+#include <hw/virtio/virtio-balloon.h>
+#include <hw/virtio/virtio-rng.h>
+#include <hw/virtio/virtio-bus.h>
-#include "hw/s390x/s390_flic.h"
-#include "hw/s390x/css.h"
-#include "ccw-device.h"
-#include "hw/s390x/css-bridge.h"
+#include "css.h"
+
+#define VIRTUAL_CSSID 0xfe
#define VIRTIO_CCW_CU_TYPE 0x3832
#define VIRTIO_CCW_CHPID_TYPE 0x32
@@ -67,7 +66,7 @@ typedef struct VirtioBusClass VirtioCcwBusClass;
typedef struct VirtioCcwDevice VirtioCcwDevice;
typedef struct VirtIOCCWDeviceClass {
- CCWDeviceClass parent_class;
+ DeviceClass parent_class;
void (*realize)(VirtioCcwDevice *dev, Error **errp);
int (*exit)(VirtioCcwDevice *dev);
} VirtIOCCWDeviceClass;
@@ -78,7 +77,9 @@ typedef struct VirtIOCCWDeviceClass {
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT)
struct VirtioCcwDevice {
- CcwDevice parent_obj;
+ DeviceState parent_obj;
+ SubchDev *sch;
+ char *bus_id;
int revision;
uint32_t max_rev;
VirtioBusState bus;
@@ -101,6 +102,15 @@ static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev)
return dev->max_rev;
}
+/* virtual css bus type */
+typedef struct VirtualCssBus {
+ BusState parent_obj;
+} VirtualCssBus;
+
+#define TYPE_VIRTUAL_CSS_BUS "virtual-css-bus"
+#define VIRTUAL_CSS_BUS(obj) \
+ OBJECT_CHECK(VirtualCssBus, (obj), TYPE_VIRTUAL_CSS_BUS)
+
/* virtio-scsi-ccw */
#define TYPE_VIRTIO_SCSI_CCW "virtio-scsi-ccw"
@@ -180,6 +190,7 @@ typedef struct VirtIORNGCcw {
VirtIORNG vdev;
} VirtIORNGCcw;
+VirtualCssBus *virtual_css_bus_init(void);
void virtio_ccw_device_update_status(SubchDev *sch);
VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch);
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 1f2f2d33d..baa0a2cfd 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -574,7 +574,7 @@ static bool esp_mem_accepts(void *opaque, hwaddr addr,
const VMStateDescription vmstate_esp = {
.name ="esp",
- .version_id = 4,
+ .version_id = 3,
.minimum_version_id = 3,
.fields = (VMStateField[]) {
VMSTATE_BUFFER(rregs, ESPState),
@@ -585,8 +585,7 @@ const VMStateDescription vmstate_esp = {
VMSTATE_BUFFER(ti_buf, ESPState),
VMSTATE_UINT32(status, ESPState),
VMSTATE_UINT32(dma, ESPState),
- VMSTATE_PARTIAL_BUFFER(cmdbuf, ESPState, 16),
- VMSTATE_BUFFER_START_MIDDLE_V(cmdbuf, ESPState, 16, 4),
+ VMSTATE_BUFFER(cmdbuf, ESPState),
VMSTATE_UINT32(cmdlen, ESPState),
VMSTATE_UINT32(do_cmd, ESPState),
VMSTATE_UINT32(dma_left, ESPState),
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index e968302fd..a9ffc3268 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -29,7 +29,7 @@
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "trace.h"
-#include "qapi/error.h"
+
#include "mfi.h"
#define MEGASAS_VERSION_GEN1 "1.70"
@@ -48,7 +48,11 @@
#define MEGASAS_FLAG_USE_JBOD 0
#define MEGASAS_MASK_USE_JBOD (1 << MEGASAS_FLAG_USE_JBOD)
-#define MEGASAS_FLAG_USE_QUEUE64 1
+#define MEGASAS_FLAG_USE_MSI 1
+#define MEGASAS_MASK_USE_MSI (1 << MEGASAS_FLAG_USE_MSI)
+#define MEGASAS_FLAG_USE_MSIX 2
+#define MEGASAS_MASK_USE_MSIX (1 << MEGASAS_FLAG_USE_MSIX)
+#define MEGASAS_FLAG_USE_QUEUE64 3
#define MEGASAS_MASK_USE_QUEUE64 (1 << MEGASAS_FLAG_USE_QUEUE64)
static const char *mfi_frame_desc[] = {
@@ -92,8 +96,6 @@ typedef struct MegasasState {
int busy;
int diag;
int adp_reset;
- OnOffAuto msi;
- OnOffAuto msix;
MegasasCmd *event_cmd;
int event_locale;
@@ -155,9 +157,14 @@ static bool megasas_use_queue64(MegasasState *s)
return s->flags & MEGASAS_MASK_USE_QUEUE64;
}
+static bool megasas_use_msi(MegasasState *s)
+{
+ return s->flags & MEGASAS_MASK_USE_MSI;
+}
+
static bool megasas_use_msix(MegasasState *s)
{
- return s->msix != ON_OFF_AUTO_OFF;
+ return s->flags & MEGASAS_MASK_USE_MSIX;
}
static bool megasas_is_jbod(MegasasState *s)
@@ -403,14 +410,17 @@ static void megasas_encode_lba(uint8_t *cdb, uint64_t lba,
static uint64_t megasas_fw_time(void)
{
struct tm curtime;
+ uint64_t bcd_time;
qemu_get_timedate(&curtime, 0);
- return ((uint64_t)curtime.tm_sec & 0xff) << 48 |
+ bcd_time = ((uint64_t)curtime.tm_sec & 0xff) << 48 |
((uint64_t)curtime.tm_min & 0xff) << 40 |
((uint64_t)curtime.tm_hour & 0xff) << 32 |
((uint64_t)curtime.tm_mday & 0xff) << 24 |
((uint64_t)curtime.tm_mon & 0xff) << 16 |
((uint64_t)(curtime.tm_year + 1900) & 0xffff);
+
+ return bcd_time;
}
/*
@@ -1981,7 +1991,11 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr,
break;
}
if (frame_status != MFI_STAT_INVALID_STATUS) {
- cmd->frame->header.cmd_status = frame_status;
+ if (cmd->frame) {
+ cmd->frame->header.cmd_status = frame_status;
+ } else {
+ megasas_frame_set_cmd_status(s, frame_addr, frame_status);
+ }
megasas_unmap_frame(s, cmd);
megasas_complete_frame(s, cmd->context);
}
@@ -2298,7 +2312,9 @@ static void megasas_scsi_uninit(PCIDevice *d)
if (megasas_use_msix(s)) {
msix_uninit(d, &s->mmio_io, &s->mmio_io);
}
- msi_uninit(d);
+ if (megasas_use_msi(s)) {
+ msi_uninit(d);
+ }
}
static const struct SCSIBusInfo megasas_scsi_info = {
@@ -2319,8 +2335,6 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
MegasasBaseClass *b = MEGASAS_DEVICE_GET_CLASS(s);
uint8_t *pci_conf;
int i, bar_type;
- Error *err = NULL;
- int ret;
pci_conf = dev->config;
@@ -2329,24 +2343,6 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
/* Interrupt pin 1 */
pci_conf[PCI_INTERRUPT_PIN] = 0x01;
- if (s->msi != ON_OFF_AUTO_OFF) {
- ret = msi_init(dev, 0x50, 1, true, false, &err);
- /* Any error other than -ENOTSUP(board's MSI support is broken)
- * is a programming error */
- assert(!ret || ret == -ENOTSUP);
- if (ret && s->msi == ON_OFF_AUTO_ON) {
- /* Can't satisfy user's explicit msi=on request, fail */
- error_append_hint(&err, "You have to use msi=auto (default) or "
- "msi=off with this machine type.\n");
- error_propagate(errp, err);
- return;
- } else if (ret) {
- /* With msi=auto, we fall back to MSI off silently */
- s->msi = ON_OFF_AUTO_OFF;
- error_free(err);
- }
- }
-
memory_region_init_io(&s->mmio_io, OBJECT(s), &megasas_mmio_ops, s,
"megasas-mmio", 0x4000);
memory_region_init_io(&s->port_io, OBJECT(s), &megasas_port_ops, s,
@@ -2354,10 +2350,14 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s,
"megasas-queue", 0x40000);
+ if (megasas_use_msi(s) &&
+ msi_init(dev, 0x50, 1, true, false)) {
+ s->flags &= ~MEGASAS_MASK_USE_MSI;
+ }
if (megasas_use_msix(s) &&
msix_init(dev, 15, &s->mmio_io, b->mmio_bar, 0x2000,
&s->mmio_io, b->mmio_bar, 0x3800, 0x68)) {
- s->msix = ON_OFF_AUTO_OFF;
+ s->flags &= ~MEGASAS_MASK_USE_MSIX;
}
if (pci_is_express(dev)) {
pcie_endpoint_cap_init(dev, 0xa0);
@@ -2425,8 +2425,10 @@ static Property megasas_properties_gen1[] = {
MEGASAS_DEFAULT_FRAMES),
DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial),
DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0),
- DEFINE_PROP_ON_OFF_AUTO("msi", MegasasState, msi, ON_OFF_AUTO_AUTO),
- DEFINE_PROP_ON_OFF_AUTO("msix", MegasasState, msix, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_BIT("use_msi", MegasasState, flags,
+ MEGASAS_FLAG_USE_MSI, false),
+ DEFINE_PROP_BIT("use_msix", MegasasState, flags,
+ MEGASAS_FLAG_USE_MSIX, false),
DEFINE_PROP_BIT("use_jbod", MegasasState, flags,
MEGASAS_FLAG_USE_JBOD, false),
DEFINE_PROP_END_OF_LIST(),
@@ -2439,8 +2441,10 @@ static Property megasas_properties_gen2[] = {
MEGASAS_GEN2_DEFAULT_FRAMES),
DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial),
DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0),
- DEFINE_PROP_ON_OFF_AUTO("msi", MegasasState, msi, ON_OFF_AUTO_AUTO),
- DEFINE_PROP_ON_OFF_AUTO("msix", MegasasState, msix, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_BIT("use_msi", MegasasState, flags,
+ MEGASAS_FLAG_USE_MSI, true),
+ DEFINE_PROP_BIT("use_msix", MegasasState, flags,
+ MEGASAS_FLAG_USE_MSIX, true),
DEFINE_PROP_BIT("use_jbod", MegasasState, flags,
MEGASAS_FLAG_USE_JBOD, false),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h
index e67a5c0b4..29d41775d 100644
--- a/hw/scsi/mfi.h
+++ b/hw/scsi/mfi.h
@@ -30,8 +30,8 @@
* SUCH DAMAGE.
*/
-#ifndef SCSI_MFI_H
-#define SCSI_MFI_H
+#ifndef MFI_REG_H
+#define MFI_REG_H
/*
* MegaRAID SAS MFI firmware definitions
@@ -1269,4 +1269,4 @@ struct mfi_config_data {
#define MFI_SCSI_MAX_CMDS 8
#define MFI_SCSI_MAX_CDB_LEN 16
-#endif /* SCSI_MFI_H */
+#endif /* MFI_REG_H */
diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
index 0e0a22f69..be88e161a 100644
--- a/hw/scsi/mptsas.c
+++ b/hw/scsi/mptsas.c
@@ -32,7 +32,7 @@
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "trace.h"
-#include "qapi/error.h"
+
#include "mptsas.h"
#include "mpi.h"
@@ -63,7 +63,7 @@ static void mptsas_update_interrupt(MPTSASState *s)
PCIDevice *pci = (PCIDevice *) s;
uint32_t state = s->intr_status & ~(s->intr_mask | MPI_HIS_IOP_DOORBELL_STATUS);
- if (msi_enabled(pci)) {
+ if (s->msi_in_use && msi_enabled(pci)) {
if (state) {
trace_mptsas_irq_msi(s);
msi_notify(pci, 0);
@@ -1273,32 +1273,10 @@ static void mptsas_scsi_init(PCIDevice *dev, Error **errp)
{
DeviceState *d = DEVICE(dev);
MPTSASState *s = MPT_SAS(dev);
- Error *err = NULL;
- int ret;
dev->config[PCI_LATENCY_TIMER] = 0;
dev->config[PCI_INTERRUPT_PIN] = 0x01;
- if (s->msi != ON_OFF_AUTO_OFF) {
- ret = msi_init(dev, 0, 1, true, false, &err);
- /* Any error other than -ENOTSUP(board's MSI support is broken)
- * is a programming error */
- assert(!ret || ret == -ENOTSUP);
- if (ret && s->msi == ON_OFF_AUTO_ON) {
- /* Can't satisfy user's explicit msi=on request, fail */
- error_append_hint(&err, "You have to use msi=auto (default) or "
- "msi=off with this machine type.\n");
- error_propagate(errp, err);
- return;
- }
- assert(!err || s->msi == ON_OFF_AUTO_AUTO);
- /* With msi=auto, we fall back to MSI off silently */
- error_free(err);
-
- /* Only used for migration. */
- s->msi_in_use = (ret == 0);
- }
-
memory_region_init_io(&s->mmio_io, OBJECT(s), &mptsas_mmio_ops, s,
"mptsas-mmio", 0x4000);
memory_region_init_io(&s->port_io, OBJECT(s), &mptsas_port_ops, s,
@@ -1306,6 +1284,11 @@ static void mptsas_scsi_init(PCIDevice *dev, Error **errp)
memory_region_init_io(&s->diag_io, OBJECT(s), &mptsas_diag_ops, s,
"mptsas-diag", 0x10000);
+ if (s->msi_available &&
+ msi_init(dev, 0, 1, true, false) >= 0) {
+ s->msi_in_use = true;
+ }
+
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_TYPE_32, &s->mmio_io);
@@ -1336,7 +1319,9 @@ static void mptsas_scsi_uninit(PCIDevice *dev)
MPTSASState *s = MPT_SAS(dev);
qemu_bh_delete(s->request_bh);
- msi_uninit(dev);
+ if (s->msi_in_use) {
+ msi_uninit(dev);
+ }
}
static void mptsas_reset(DeviceState *dev)
@@ -1373,6 +1358,7 @@ static const VMStateDescription vmstate_mptsas = {
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(dev, MPTSASState),
VMSTATE_BOOL(msi_in_use, MPTSASState),
+
VMSTATE_UINT32(state, MPTSASState),
VMSTATE_UINT8(who_init, MPTSASState),
VMSTATE_UINT8(doorbell_state, MPTSASState),
@@ -1417,7 +1403,7 @@ static const VMStateDescription vmstate_mptsas = {
static Property mptsas_properties[] = {
DEFINE_PROP_UINT64("sas_address", MPTSASState, sas_addr, 0),
/* TODO: test MSI support under Windows */
- DEFINE_PROP_ON_OFF_AUTO("msi", MPTSASState, msi, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_BIT("msi", MPTSASState, msi_available, 0, true),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/scsi/mptsas.h b/hw/scsi/mptsas.h
index 0436a3391..595f81fb5 100644
--- a/hw/scsi/mptsas.h
+++ b/hw/scsi/mptsas.h
@@ -27,8 +27,7 @@ struct MPTSASState {
MemoryRegion diag_io;
QEMUBH *request_bh;
- /* properties */
- OnOffAuto msi;
+ uint32_t msi_available;
uint64_t sas_addr;
bool msi_in_use;
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 297216dfc..ad6f398c3 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -461,14 +461,6 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
return true;
}
-static size_t scsi_sense_len(SCSIRequest *req)
-{
- if (req->dev->type == TYPE_SCANNER)
- return SCSI_SENSE_LEN_SCANNER;
- else
- return SCSI_SENSE_LEN;
-}
-
static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
{
SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
@@ -485,7 +477,7 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
}
break;
case REQUEST_SENSE:
- scsi_target_alloc_buf(&r->req, scsi_sense_len(req));
+ scsi_target_alloc_buf(&r->req, SCSI_SENSE_LEN);
r->len = scsi_device_get_sense(r->req.dev, r->buf,
MIN(req->cmd.xfer, r->buf_len),
(req->cmd.buf[1] & 1) == 0);
@@ -1140,29 +1132,6 @@ static int scsi_req_medium_changer_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8
return 0;
}
-static int scsi_req_scanner_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
-{
- switch (buf[0]) {
- /* Scanner commands */
- case OBJECT_POSITION:
- cmd->xfer = 0;
- break;
- case SCAN:
- cmd->xfer = buf[4];
- break;
- case READ_10:
- case SEND:
- case GET_WINDOW:
- case SET_WINDOW:
- cmd->xfer = buf[8] | (buf[7] << 8) | (buf[6] << 16);
- break;
- default:
- /* GET_DATA_BUFFER_STATUS xfer handled by scsi_req_xfer */
- return scsi_req_xfer(cmd, dev, buf);
- }
-
- return 0;
-}
static void scsi_cmd_xfer_mode(SCSICommand *cmd)
{
@@ -1209,11 +1178,6 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
case SEND_DVD_STRUCTURE:
case PERSISTENT_RESERVE_OUT:
case MAINTENANCE_OUT:
- case SET_WINDOW:
- case SCAN:
- /* SCAN conflicts with START_STOP. START_STOP has cmd->xfer set to 0 for
- * non-scanner devices, so we only get here for SCAN and not for START_STOP.
- */
cmd->mode = SCSI_XFER_TO_DEV;
break;
case ATA_PASSTHROUGH_12:
@@ -1294,9 +1258,6 @@ int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
case TYPE_MEDIUM_CHANGER:
rc = scsi_req_medium_changer_xfer(cmd, dev, buf);
break;
- case TYPE_SCANNER:
- rc = scsi_req_scanner_length(cmd, dev, buf);
- break;
default:
rc = scsi_req_xfer(cmd, dev, buf);
break;
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 836a1553e..c3ce54a20 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -53,21 +53,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#define DEFAULT_MAX_UNMAP_SIZE (1 << 30) /* 1 GB */
#define DEFAULT_MAX_IO_SIZE INT_MAX /* 2 GB - 1 block */
-#define TYPE_SCSI_DISK_BASE "scsi-disk-base"
-
-#define SCSI_DISK_BASE(obj) \
- OBJECT_CHECK(SCSIDiskState, (obj), TYPE_SCSI_DISK_BASE)
-#define SCSI_DISK_BASE_CLASS(klass) \
- OBJECT_CLASS_CHECK(SCSIDiskClass, (klass), TYPE_SCSI_DISK_BASE)
-#define SCSI_DISK_BASE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SCSIDiskClass, (obj), TYPE_SCSI_DISK_BASE)
-
-typedef struct SCSIDiskClass {
- SCSIDeviceClass parent_class;
- DMAIOFunc *dma_readv;
- DMAIOFunc *dma_writev;
- bool (*need_fua_emulation)(SCSICommand *cmd);
-} SCSIDiskClass;
+typedef struct SCSIDiskState SCSIDiskState;
typedef struct SCSIDiskReq {
SCSIRequest req;
@@ -76,18 +62,16 @@ typedef struct SCSIDiskReq {
uint32_t sector_count;
uint32_t buflen;
bool started;
- bool need_fua_emulation;
struct iovec iov;
QEMUIOVector qiov;
BlockAcctCookie acct;
- unsigned char *status;
} SCSIDiskReq;
#define SCSI_DISK_F_REMOVABLE 0
#define SCSI_DISK_F_DPOFUA 1
#define SCSI_DISK_F_NO_REMOVABLE_DEVOPS 2
-typedef struct SCSIDiskState
+struct SCSIDiskState
{
SCSIDevice qdev;
uint32_t features;
@@ -104,7 +88,7 @@ typedef struct SCSIDiskState
char *product;
bool tray_open;
bool tray_locked;
-} SCSIDiskState;
+};
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed);
@@ -124,7 +108,7 @@ static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
scsi_req_complete(&r->req, CHECK_CONDITION);
}
-static void scsi_init_iovec(SCSIDiskReq *r, size_t size)
+static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
@@ -134,6 +118,7 @@ static void scsi_init_iovec(SCSIDiskReq *r, size_t size)
}
r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
+ return r->qiov.size / 512;
}
static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
@@ -177,29 +162,6 @@ static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
}
-static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed)
-{
- if (r->req.io_canceled) {
- scsi_req_cancel_complete(&r->req);
- return true;
- }
-
- if (ret < 0) {
- return scsi_handle_rw_error(r, -ret, acct_failed);
- }
-
- if (r->status && *r->status) {
- if (acct_failed) {
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
- }
- scsi_req_complete(&r->req, *r->status);
- return true;
- }
-
- return false;
-}
-
static void scsi_aio_complete(void *opaque, int ret)
{
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
@@ -207,10 +169,17 @@ static void scsi_aio_complete(void *opaque, int ret)
assert(r->req.aiocb != NULL);
r->req.aiocb = NULL;
- if (scsi_disk_req_check_error(r, ret, true)) {
+ if (r->req.io_canceled) {
+ scsi_req_cancel_complete(&r->req);
goto done;
}
+ if (ret < 0) {
+ if (scsi_handle_rw_error(r, -ret, true)) {
+ goto done;
+ }
+ }
+
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
scsi_req_complete(&r->req, GOOD);
@@ -249,9 +218,13 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
assert(r->req.aiocb == NULL);
- assert(!r->req.io_canceled);
- if (r->need_fua_emulation) {
+ if (r->req.io_canceled) {
+ scsi_req_cancel_complete(&r->req);
+ goto done;
+ }
+
+ if (scsi_is_cmd_fua(&r->req.cmd)) {
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0,
BLOCK_ACCT_FLUSH);
r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r);
@@ -259,16 +232,26 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
}
scsi_req_complete(&r->req, GOOD);
+
+done:
scsi_req_unref(&r->req);
}
static void scsi_dma_complete_noio(SCSIDiskReq *r, int ret)
{
assert(r->req.aiocb == NULL);
- if (scsi_disk_req_check_error(r, ret, false)) {
+
+ if (r->req.io_canceled) {
+ scsi_req_cancel_complete(&r->req);
goto done;
}
+ if (ret < 0) {
+ if (scsi_handle_rw_error(r, -ret, false)) {
+ goto done;
+ }
+ }
+
r->sector += r->sector_count;
r->sector_count = 0;
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
@@ -306,10 +289,17 @@ static void scsi_read_complete(void * opaque, int ret)
assert(r->req.aiocb != NULL);
r->req.aiocb = NULL;
- if (scsi_disk_req_check_error(r, ret, true)) {
+ if (r->req.io_canceled) {
+ scsi_req_cancel_complete(&r->req);
goto done;
}
+ if (ret < 0) {
+ if (scsi_handle_rw_error(r, -ret, true)) {
+ goto done;
+ }
+ }
+
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
@@ -326,29 +316,35 @@ done:
static void scsi_do_read(SCSIDiskReq *r, int ret)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
+ uint32_t n;
assert (r->req.aiocb == NULL);
- if (scsi_disk_req_check_error(r, ret, false)) {
+
+ if (r->req.io_canceled) {
+ scsi_req_cancel_complete(&r->req);
goto done;
}
+ if (ret < 0) {
+ if (scsi_handle_rw_error(r, -ret, false)) {
+ goto done;
+ }
+ }
+
/* The request is used as the AIO opaque value, so add a ref. */
scsi_req_ref(&r->req);
if (r->req.sg) {
dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_READ);
r->req.resid -= r->req.sg->size;
- r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk),
- r->req.sg, r->sector << BDRV_SECTOR_BITS,
- sdc->dma_readv, r, scsi_dma_complete, r,
- DMA_DIRECTION_FROM_DEVICE);
+ r->req.aiocb = dma_blk_read(s->qdev.conf.blk, r->req.sg, r->sector,
+ scsi_dma_complete, r);
} else {
- scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
+ n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
- r->qiov.size, BLOCK_ACCT_READ);
- r->req.aiocb = sdc->dma_readv(r->sector << BDRV_SECTOR_BITS, &r->qiov,
- scsi_read_complete, r, r);
+ n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
+ r->req.aiocb = blk_aio_readv(s->qdev.conf.blk, r->sector, &r->qiov, n,
+ scsi_read_complete, r);
}
done:
@@ -403,7 +399,7 @@ static void scsi_read_data(SCSIRequest *req)
first = !r->started;
r->started = true;
- if (first && r->need_fua_emulation) {
+ if (first && scsi_is_cmd_fua(&r->req.cmd)) {
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0,
BLOCK_ACCT_FLUSH);
r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_do_read_cb, r);
@@ -460,10 +456,18 @@ static void scsi_write_complete_noio(SCSIDiskReq *r, int ret)
uint32_t n;
assert (r->req.aiocb == NULL);
- if (scsi_disk_req_check_error(r, ret, false)) {
+
+ if (r->req.io_canceled) {
+ scsi_req_cancel_complete(&r->req);
goto done;
}
+ if (ret < 0) {
+ if (scsi_handle_rw_error(r, -ret, false)) {
+ goto done;
+ }
+ }
+
n = r->qiov.size / 512;
r->sector += n;
r->sector_count -= n;
@@ -500,7 +504,7 @@ static void scsi_write_data(SCSIRequest *req)
{
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
+ uint32_t n;
/* No data transfer may already be in progress */
assert(r->req.aiocb == NULL);
@@ -537,15 +541,14 @@ static void scsi_write_data(SCSIRequest *req)
if (r->req.sg) {
dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_WRITE);
r->req.resid -= r->req.sg->size;
- r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk),
- r->req.sg, r->sector << BDRV_SECTOR_BITS,
- sdc->dma_writev, r, scsi_dma_complete, r,
- DMA_DIRECTION_TO_DEVICE);
+ r->req.aiocb = dma_blk_write(s->qdev.conf.blk, r->req.sg, r->sector,
+ scsi_dma_complete, r);
} else {
+ n = r->qiov.size / 512;
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
- r->qiov.size, BLOCK_ACCT_WRITE);
- r->req.aiocb = sdc->dma_writev(r->sector << BDRV_SECTOR_BITS, &r->qiov,
- scsi_write_complete, r, r);
+ n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE);
+ r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, r->sector, &r->qiov, n,
+ scsi_write_complete, r);
}
}
@@ -1597,10 +1600,18 @@ static void scsi_unmap_complete_noio(UnmapCBData *data, int ret)
uint32_t nb_sectors;
assert(r->req.aiocb == NULL);
- if (scsi_disk_req_check_error(r, ret, false)) {
+
+ if (r->req.io_canceled) {
+ scsi_req_cancel_complete(&r->req);
goto done;
}
+ if (ret < 0) {
+ if (scsi_handle_rw_error(r, -ret, false)) {
+ goto done;
+ }
+ }
+
if (data->count > 0) {
sector_num = ldq_be_p(&data->inbuf[0]);
nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
@@ -1609,10 +1620,10 @@ static void scsi_unmap_complete_noio(UnmapCBData *data, int ret)
goto done;
}
- r->req.aiocb = blk_aio_pdiscard(s->qdev.conf.blk,
- sector_num * s->qdev.blocksize,
- nb_sectors * s->qdev.blocksize,
- scsi_unmap_complete, data);
+ r->req.aiocb = blk_aio_discard(s->qdev.conf.blk,
+ sector_num * (s->qdev.blocksize / 512),
+ nb_sectors * (s->qdev.blocksize / 512),
+ scsi_unmap_complete, data);
data->count--;
data->inbuf += 16;
return;
@@ -1700,10 +1711,17 @@ static void scsi_write_same_complete(void *opaque, int ret)
assert(r->req.aiocb != NULL);
r->req.aiocb = NULL;
- if (scsi_disk_req_check_error(r, ret, true)) {
+ if (r->req.io_canceled) {
+ scsi_req_cancel_complete(&r->req);
goto done;
}
+ if (ret < 0) {
+ if (scsi_handle_rw_error(r, -ret, true)) {
+ goto done;
+ }
+ }
+
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
data->nb_sectors -= data->iov.iov_len / 512;
@@ -1712,13 +1730,13 @@ static void scsi_write_same_complete(void *opaque, int ret)
if (data->iov.iov_len) {
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
data->iov.iov_len, BLOCK_ACCT_WRITE);
- /* Reinitialize qiov, to handle unaligned WRITE SAME request
- * where final qiov may need smaller size */
+ /* blk_aio_write doesn't like the qiov size being different from
+ * nb_sectors, make sure they match.
+ */
qemu_iovec_init_external(&data->qiov, &data->iov, 1);
- r->req.aiocb = blk_aio_pwritev(s->qdev.conf.blk,
- data->sector << BDRV_SECTOR_BITS,
- &data->qiov, 0,
- scsi_write_same_complete, data);
+ r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector,
+ &data->qiov, data->iov.iov_len / 512,
+ scsi_write_same_complete, data);
return;
}
@@ -1762,9 +1780,9 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
nb_sectors * s->qdev.blocksize,
BLOCK_ACCT_WRITE);
- r->req.aiocb = blk_aio_pwrite_zeroes(s->qdev.conf.blk,
- r->req.cmd.lba * s->qdev.blocksize,
- nb_sectors * s->qdev.blocksize,
+ r->req.aiocb = blk_aio_write_zeroes(s->qdev.conf.blk,
+ r->req.cmd.lba * (s->qdev.blocksize / 512),
+ nb_sectors * (s->qdev.blocksize / 512),
flags, scsi_aio_complete, r);
return;
}
@@ -1785,10 +1803,9 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
scsi_req_ref(&r->req);
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
data->iov.iov_len, BLOCK_ACCT_WRITE);
- r->req.aiocb = blk_aio_pwritev(s->qdev.conf.blk,
- data->sector << BDRV_SECTOR_BITS,
- &data->qiov, 0,
- scsi_write_same_complete, data);
+ r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector,
+ &data->qiov, data->iov.iov_len / 512,
+ scsi_write_same_complete, data);
}
static void scsi_disk_emulate_write_data(SCSIRequest *req)
@@ -2060,13 +2077,13 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
}
break;
case MODE_SELECT:
- DPRINTF("Mode Select(6) (len %lu)\n", (unsigned long)r->req.cmd.xfer);
+ DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
break;
case MODE_SELECT_10:
- DPRINTF("Mode Select(10) (len %lu)\n", (unsigned long)r->req.cmd.xfer);
+ DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
break;
case UNMAP:
- DPRINTF("Unmap (len %lu)\n", (unsigned long)r->req.cmd.xfer);
+ DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer);
break;
case VERIFY_10:
case VERIFY_12:
@@ -2080,7 +2097,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
case WRITE_SAME_16:
DPRINTF("WRITE SAME %d (len %lu)\n",
req->cmd.buf[0] == WRITE_SAME_10 ? 10 : 16,
- (unsigned long)r->req.cmd.xfer);
+ (long)r->req.cmd.xfer);
break;
default:
DPRINTF("Unknown SCSI command (%2.2x=%s)\n", buf[0],
@@ -2120,7 +2137,6 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
{
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
- SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
uint32_t len;
uint8_t command;
@@ -2179,7 +2195,6 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
return 0;
}
- r->need_fua_emulation = sdc->need_fua_emulation(&r->req.cmd);
if (r->sector_count == 0) {
scsi_req_complete(&r->req, GOOD);
}
@@ -2309,7 +2324,6 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
return;
}
}
- blkconf_apply_backend_options(&dev->conf);
if (s->qdev.conf.discard_granularity == -1) {
s->qdev.conf.discard_granularity =
@@ -2563,145 +2577,16 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp)
scsi_generic_read_device_identification(&s->qdev);
}
-typedef struct SCSIBlockReq {
- SCSIDiskReq req;
- sg_io_hdr_t io_header;
-
- /* Selected bytes of the original CDB, copied into our own CDB. */
- uint8_t cmd, cdb1, group_number;
-
- /* CDB passed to SG_IO. */
- uint8_t cdb[16];
-} SCSIBlockReq;
-
-static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req,
- int64_t offset, QEMUIOVector *iov,
- int direction,
- BlockCompletionFunc *cb, void *opaque)
-{
- sg_io_hdr_t *io_header = &req->io_header;
- SCSIDiskReq *r = &req->req;
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- int nb_logical_blocks;
- uint64_t lba;
- BlockAIOCB *aiocb;
-
- /* This is not supported yet. It can only happen if the guest does
- * reads and writes that are not aligned to one logical sectors
- * _and_ cover multiple MemoryRegions.
- */
- assert(offset % s->qdev.blocksize == 0);
- assert(iov->size % s->qdev.blocksize == 0);
-
- io_header->interface_id = 'S';
-
- /* The data transfer comes from the QEMUIOVector. */
- io_header->dxfer_direction = direction;
- io_header->dxfer_len = iov->size;
- io_header->dxferp = (void *)iov->iov;
- io_header->iovec_count = iov->niov;
- assert(io_header->iovec_count == iov->niov); /* no overflow! */
-
- /* Build a new CDB with the LBA and length patched in, in case
- * DMA helpers split the transfer in multiple segments. Do not
- * build a CDB smaller than what the guest wanted, and only build
- * a larger one if strictly necessary.
- */
- io_header->cmdp = req->cdb;
- lba = offset / s->qdev.blocksize;
- nb_logical_blocks = io_header->dxfer_len / s->qdev.blocksize;
-
- if ((req->cmd >> 5) == 0 && lba <= 0x1ffff) {
- /* 6-byte CDB */
- stl_be_p(&req->cdb[0], lba | (req->cmd << 24));
- req->cdb[4] = nb_logical_blocks;
- req->cdb[5] = 0;
- io_header->cmd_len = 6;
- } else if ((req->cmd >> 5) <= 1 && lba <= 0xffffffffULL) {
- /* 10-byte CDB */
- req->cdb[0] = (req->cmd & 0x1f) | 0x20;
- req->cdb[1] = req->cdb1;
- stl_be_p(&req->cdb[2], lba);
- req->cdb[6] = req->group_number;
- stw_be_p(&req->cdb[7], nb_logical_blocks);
- req->cdb[9] = 0;
- io_header->cmd_len = 10;
- } else if ((req->cmd >> 5) != 4 && lba <= 0xffffffffULL) {
- /* 12-byte CDB */
- req->cdb[0] = (req->cmd & 0x1f) | 0xA0;
- req->cdb[1] = req->cdb1;
- stl_be_p(&req->cdb[2], lba);
- stl_be_p(&req->cdb[6], nb_logical_blocks);
- req->cdb[10] = req->group_number;
- req->cdb[11] = 0;
- io_header->cmd_len = 12;
- } else {
- /* 16-byte CDB */
- req->cdb[0] = (req->cmd & 0x1f) | 0x80;
- req->cdb[1] = req->cdb1;
- stq_be_p(&req->cdb[2], lba);
- stl_be_p(&req->cdb[10], nb_logical_blocks);
- req->cdb[14] = req->group_number;
- req->cdb[15] = 0;
- io_header->cmd_len = 16;
- }
-
- /* The rest is as in scsi-generic.c. */
- io_header->mx_sb_len = sizeof(r->req.sense);
- io_header->sbp = r->req.sense;
- io_header->timeout = UINT_MAX;
- io_header->usr_ptr = r;
- io_header->flags |= SG_FLAG_DIRECT_IO;
-
- aiocb = blk_aio_ioctl(s->qdev.conf.blk, SG_IO, io_header, cb, opaque);
- assert(aiocb != NULL);
- return aiocb;
-}
-
-static bool scsi_block_no_fua(SCSICommand *cmd)
-{
- return false;
-}
-
-static BlockAIOCB *scsi_block_dma_readv(int64_t offset,
- QEMUIOVector *iov,
- BlockCompletionFunc *cb, void *cb_opaque,
- void *opaque)
-{
- SCSIBlockReq *r = opaque;
- return scsi_block_do_sgio(r, offset, iov,
- SG_DXFER_FROM_DEV, cb, cb_opaque);
-}
-
-static BlockAIOCB *scsi_block_dma_writev(int64_t offset,
- QEMUIOVector *iov,
- BlockCompletionFunc *cb, void *cb_opaque,
- void *opaque)
-{
- SCSIBlockReq *r = opaque;
- return scsi_block_do_sgio(r, offset, iov,
- SG_DXFER_TO_DEV, cb, cb_opaque);
-}
-
static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf)
{
switch (buf[0]) {
- case VERIFY_10:
- case VERIFY_12:
- case VERIFY_16:
- /* Check if BYTCHK == 0x01 (data-out buffer contains data
- * for the number of logical blocks specified in the length
- * field). For other modes, do not use scatter/gather operation.
- */
- if ((buf[1] & 6) != 2) {
- return false;
- }
- break;
-
case READ_6:
case READ_10:
case READ_12:
case READ_16:
+ case VERIFY_10:
+ case VERIFY_12:
+ case VERIFY_16:
case WRITE_6:
case WRITE_10:
case WRITE_12:
@@ -2709,8 +2594,21 @@ static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf)
case WRITE_VERIFY_10:
case WRITE_VERIFY_12:
case WRITE_VERIFY_16:
- /* MMC writing cannot be done via DMA helpers, because it sometimes
+ /* If we are not using O_DIRECT, we might read stale data from the
+ * host cache if writes were made using other commands than these
+ * ones (such as WRITE SAME or EXTENDED COPY, etc.). So, without
+ * O_DIRECT everything must go through SG_IO.
+ */
+ if (!(blk_get_flags(s->qdev.conf.blk) & BDRV_O_NOCACHE)) {
+ break;
+ }
+
+ /* MMC writing cannot be done via pread/pwrite, because it sometimes
* involves writing beyond the maximum LBA or to negative LBA (lead-in).
+ * And once you do these writes, reading from the block device is
+ * unreliable, too. It is even possible that reads deliver random data
+ * from the host page cache (this is probably a Linux bug).
+ *
* We might use scsi_disk_dma_reqops as long as no writing commands are
* seen, but performance usually isn't paramount on optical media. So,
* just make scsi-block operate the same as scsi-generic for them.
@@ -2728,55 +2626,6 @@ static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf)
}
-static int32_t scsi_block_dma_command(SCSIRequest *req, uint8_t *buf)
-{
- SCSIBlockReq *r = (SCSIBlockReq *)req;
- r->cmd = req->cmd.buf[0];
- switch (r->cmd >> 5) {
- case 0:
- /* 6-byte CDB. */
- r->cdb1 = r->group_number = 0;
- break;
- case 1:
- /* 10-byte CDB. */
- r->cdb1 = req->cmd.buf[1];
- r->group_number = req->cmd.buf[6];
- break;
- case 4:
- /* 12-byte CDB. */
- r->cdb1 = req->cmd.buf[1];
- r->group_number = req->cmd.buf[10];
- break;
- case 5:
- /* 16-byte CDB. */
- r->cdb1 = req->cmd.buf[1];
- r->group_number = req->cmd.buf[14];
- break;
- default:
- abort();
- }
-
- if (r->cdb1 & 0xe0) {
- /* Protection information is not supported. */
- scsi_check_condition(&r->req, SENSE_CODE(INVALID_FIELD));
- return 0;
- }
-
- r->req.status = &r->io_header.status;
- return scsi_disk_dma_command(req, buf);
-}
-
-static const SCSIReqOps scsi_block_dma_reqops = {
- .size = sizeof(SCSIBlockReq),
- .free_req = scsi_free_request,
- .send_command = scsi_block_dma_command,
- .read_data = scsi_read_data,
- .write_data = scsi_write_data,
- .get_buf = scsi_get_buf,
- .load_request = scsi_disk_load_request,
- .save_request = scsi_disk_save_request,
-};
-
static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
uint32_t lun, uint8_t *buf,
void *hba_private)
@@ -2787,7 +2636,7 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
hba_private);
} else {
- return scsi_req_alloc(&scsi_block_dma_reqops, &s->qdev, tag, lun,
+ return scsi_req_alloc(&scsi_disk_dma_reqops, &s->qdev, tag, lun,
hba_private);
}
}
@@ -2806,50 +2655,8 @@ static int scsi_block_parse_cdb(SCSIDevice *d, SCSICommand *cmd,
#endif
-static
-BlockAIOCB *scsi_dma_readv(int64_t offset, QEMUIOVector *iov,
- BlockCompletionFunc *cb, void *cb_opaque,
- void *opaque)
-{
- SCSIDiskReq *r = opaque;
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- return blk_aio_preadv(s->qdev.conf.blk, offset, iov, 0, cb, cb_opaque);
-}
-
-static
-BlockAIOCB *scsi_dma_writev(int64_t offset, QEMUIOVector *iov,
- BlockCompletionFunc *cb, void *cb_opaque,
- void *opaque)
-{
- SCSIDiskReq *r = opaque;
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- return blk_aio_pwritev(s->qdev.conf.blk, offset, iov, 0, cb, cb_opaque);
-}
-
-static void scsi_disk_base_class_initfn(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SCSIDiskClass *sdc = SCSI_DISK_BASE_CLASS(klass);
-
- dc->fw_name = "disk";
- dc->reset = scsi_disk_reset;
- sdc->dma_readv = scsi_dma_readv;
- sdc->dma_writev = scsi_dma_writev;
- sdc->need_fua_emulation = scsi_is_cmd_fua;
-}
-
-static const TypeInfo scsi_disk_base_info = {
- .name = TYPE_SCSI_DISK_BASE,
- .parent = TYPE_SCSI_DEVICE,
- .class_init = scsi_disk_base_class_initfn,
- .instance_size = sizeof(SCSIDiskState),
- .class_size = sizeof(SCSIDiskClass),
- .abstract = true,
-};
-
#define DEFINE_SCSI_DISK_PROPERTIES() \
DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), \
- DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \
DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \
DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \
@@ -2895,14 +2702,17 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
sc->realize = scsi_hd_realize;
sc->alloc_req = scsi_new_request;
sc->unit_attention_reported = scsi_disk_unit_attention_reported;
+ dc->fw_name = "disk";
dc->desc = "virtual SCSI disk";
+ dc->reset = scsi_disk_reset;
dc->props = scsi_hd_properties;
dc->vmsd = &vmstate_scsi_disk_state;
}
static const TypeInfo scsi_hd_info = {
.name = "scsi-hd",
- .parent = TYPE_SCSI_DISK_BASE,
+ .parent = TYPE_SCSI_DEVICE,
+ .instance_size = sizeof(SCSIDiskState),
.class_init = scsi_hd_class_initfn,
};
@@ -2924,14 +2734,17 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
sc->realize = scsi_cd_realize;
sc->alloc_req = scsi_new_request;
sc->unit_attention_reported = scsi_disk_unit_attention_reported;
+ dc->fw_name = "disk";
dc->desc = "virtual SCSI CD-ROM";
+ dc->reset = scsi_disk_reset;
dc->props = scsi_cd_properties;
dc->vmsd = &vmstate_scsi_disk_state;
}
static const TypeInfo scsi_cd_info = {
.name = "scsi-cd",
- .parent = TYPE_SCSI_DISK_BASE,
+ .parent = TYPE_SCSI_DEVICE,
+ .instance_size = sizeof(SCSIDiskState),
.class_init = scsi_cd_class_initfn,
};
@@ -2945,22 +2758,21 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
- SCSIDiskClass *sdc = SCSI_DISK_BASE_CLASS(klass);
sc->realize = scsi_block_realize;
sc->alloc_req = scsi_block_new_request;
sc->parse_cdb = scsi_block_parse_cdb;
- sdc->dma_readv = scsi_block_dma_readv;
- sdc->dma_writev = scsi_block_dma_writev;
- sdc->need_fua_emulation = scsi_block_no_fua;
+ dc->fw_name = "disk";
dc->desc = "SCSI block device passthrough";
+ dc->reset = scsi_disk_reset;
dc->props = scsi_block_properties;
dc->vmsd = &vmstate_scsi_disk_state;
}
static const TypeInfo scsi_block_info = {
.name = "scsi-block",
- .parent = TYPE_SCSI_DISK_BASE,
+ .parent = TYPE_SCSI_DEVICE,
+ .instance_size = sizeof(SCSIDiskState),
.class_init = scsi_block_class_initfn,
};
#endif
@@ -2998,13 +2810,13 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
static const TypeInfo scsi_disk_info = {
.name = "scsi-disk",
- .parent = TYPE_SCSI_DISK_BASE,
+ .parent = TYPE_SCSI_DEVICE,
+ .instance_size = sizeof(SCSIDiskState),
.class_init = scsi_disk_class_initfn,
};
static void scsi_disk_register_types(void)
{
- type_register_static(&scsi_disk_base_info);
type_register_static(&scsi_hd_info);
type_register_static(&scsi_cd_info);
#ifdef __linux__
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index 7a588a7ad..c4ba9a485 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -225,14 +225,14 @@ static void scsi_read_complete(void * opaque, int ret)
if (s->type == TYPE_DISK &&
r->req.cmd.buf[0] == INQUIRY &&
r->req.cmd.buf[2] == 0xb0) {
- uint32_t max_transfer =
- blk_get_max_transfer(s->conf.blk) / s->blocksize;
-
- assert(max_transfer);
- stl_be_p(&r->buf[8], max_transfer);
- /* Also take care of the opt xfer len. */
- if (ldl_be_p(&r->buf[12]) > max_transfer) {
- stl_be_p(&r->buf[12], max_transfer);
+ uint32_t max_xfer_len = blk_get_max_transfer_length(s->conf.blk) /
+ (s->blocksize / BDRV_SECTOR_SIZE);
+ if (max_xfer_len) {
+ stl_be_p(&r->buf[8], max_xfer_len);
+ /* Also take care of the opt xfer len. */
+ if (ldl_be_p(&r->buf[12]) > max_xfer_len) {
+ stl_be_p(&r->buf[12], max_xfer_len);
+ }
}
}
scsi_req_data(&r->req, len);
@@ -580,7 +580,10 @@ const SCSIReqOps scsi_generic_req_ops = {
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
uint8_t *buf, void *hba_private)
{
- return scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
+ SCSIRequest *req;
+
+ req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
+ return req;
}
static Property scsi_generic_properties[] = {
diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events
deleted file mode 100644
index ed64858fe..000000000
--- a/hw/scsi/trace-events
+++ /dev/null
@@ -1,204 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/scsi/scsi-bus.c
-scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d"
-scsi_req_cancel(int target, int lun, int tag) "target %d lun %d tag %d"
-scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d"
-scsi_req_data_canceled(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d"
-scsi_req_dequeue(int target, int lun, int tag) "target %d lun %d tag %d"
-scsi_req_continue(int target, int lun, int tag) "target %d lun %d tag %d"
-scsi_req_continue_canceled(int target, int lun, int tag) "target %d lun %d tag %d"
-scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer) "target %d lun %d tag %d command %d dir %d length %d"
-scsi_req_parsed_lba(int target, int lun, int tag, int cmd, uint64_t lba) "target %d lun %d tag %d command %d lba %"PRIu64
-scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d tag %d command %d"
-scsi_req_build_sense(int target, int lun, int tag, int key, int asc, int ascq) "target %d lun %d tag %d key %#02x asc %#02x ascq %#02x"
-scsi_device_set_ua(int target, int lun, int key, int asc, int ascq) "target %d lun %d key %#02x asc %#02x ascq %#02x"
-scsi_report_luns(int target, int lun, int tag) "target %d lun %d tag %d"
-scsi_inquiry(int target, int lun, int tag, int cdb1, int cdb2) "target %d lun %d tag %d page %#02x/%#02x"
-scsi_test_unit_ready(int target, int lun, int tag) "target %d lun %d tag %d"
-scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d"
-
-# hw/scsi/mptsas.c
-mptsas_command_complete(void *dev, uint32_t ctx, uint32_t status, uint32_t resid) "dev %p context 0x%08x status %x resid %d"
-mptsas_diag_read(void *dev, uint32_t addr, uint32_t val) "dev %p addr 0x%08x value 0x%08x"
-mptsas_diag_write(void *dev, uint32_t addr, uint32_t val) "dev %p addr 0x%08x value 0x%08x"
-mptsas_irq_intx(void *dev, int level) "dev %p level %d"
-mptsas_irq_msi(void *dev) "dev %p "
-mptsas_mmio_read(void *dev, uint32_t addr, uint32_t val) "dev %p addr 0x%08x value 0x%x"
-mptsas_mmio_unhandled_read(void *dev, uint32_t addr) "dev %p addr 0x%08x"
-mptsas_mmio_unhandled_write(void *dev, uint32_t addr, uint32_t val) "dev %p addr 0x%08x value 0x%x"
-mptsas_mmio_write(void *dev, uint32_t addr, uint32_t val) "dev %p addr 0x%08x value 0x%x"
-mptsas_process_message(void *dev, int msg, uint32_t ctx) "dev %p cmd %d context 0x%08x\n"
-mptsas_process_scsi_io_request(void *dev, int bus, int target, int lun, uint64_t len) "dev %p dev %d:%d:%d length %"PRIu64""
-mptsas_reset(void *dev) "dev %p "
-mptsas_scsi_overflow(void *dev, uint32_t ctx, uint64_t req, uint64_t found) "dev %p context 0x%08x: %"PRIu64"/%"PRIu64""
-mptsas_sgl_overflow(void *dev, uint32_t ctx, uint64_t req, uint64_t found) "dev %p context 0x%08x: %"PRIu64"/%"PRIu64""
-mptsas_unhandled_cmd(void *dev, uint32_t ctx, uint8_t msg_cmd) "dev %p context 0x%08x: Unhandled cmd %x"
-mptsas_unhandled_doorbell_cmd(void *dev, int cmd) "dev %p value 0x%08x"
-
-# hw/scsi/mptconfig.c
-mptsas_config_sas_device(void *dev, int address, int port, int phy_handle, int dev_handle, int page) "dev %p address %d (port %d, handles: phy %d dev %d) page %d"
-mptsas_config_sas_phy(void *dev, int address, int port, int phy_handle, int dev_handle, int page) "dev %p address %d (port %d, handles: phy %d dev %d) page %d"
-
-# hw/scsi/megasas.c
-megasas_init_firmware(uint64_t pa) "pa %" PRIx64 " "
-megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) "queue at %" PRIx64 " len %d head %" PRIx64 " tail %" PRIx64 " flags %x"
-megasas_initq_map_failed(int frame) "scmd %d: failed to map queue"
-megasas_initq_mapped(uint64_t pa) "queue already mapped at %" PRIx64
-megasas_initq_mismatch(int queue_len, int fw_cmds) "queue size %d max fw cmds %d"
-megasas_qf_mapped(unsigned int index) "skip mapped frame %x"
-megasas_qf_new(unsigned int index, uint64_t frame) "frame %x addr %" PRIx64
-megasas_qf_busy(unsigned long pa) "all frames busy for frame %lx"
-megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int head, unsigned int tail, int busy) "frame %x count %d context %" PRIx64 " head %x tail %x busy %d"
-megasas_qf_update(unsigned int head, unsigned int tail, unsigned int busy) "head %x tail %x busy %d"
-megasas_qf_map_failed(int cmd, unsigned long frame) "scmd %d: frame %lu"
-megasas_qf_complete_noirq(uint64_t context) "context %" PRIx64 " "
-megasas_qf_complete(uint64_t context, unsigned int head, unsigned int tail, int busy) "context %" PRIx64 " head %x tail %x busy %d"
-megasas_frame_busy(uint64_t addr) "frame %" PRIx64 " busy"
-megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) "scmd %d: MFI cmd %x"
-megasas_handle_scsi(const char *frame, int bus, int dev, int lun, void *sdev, unsigned long size) "%s dev %x/%x/%x sdev %p xfer %lu"
-megasas_scsi_target_not_present(const char *frame, int bus, int dev, int lun) "%s dev %x/%x/%x"
-megasas_scsi_invalid_cdb_len(const char *frame, int bus, int dev, int lun, int len) "%s dev %x/%x/%x invalid cdb len %d"
-megasas_iov_read_overflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
-megasas_iov_write_overflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
-megasas_iov_read_underflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
-megasas_iov_write_underflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
-megasas_scsi_req_alloc_failed(const char *frame, int dev, int lun) "%s dev %x/%x"
-megasas_scsi_read_start(int cmd, int len) "scmd %d: transfer %d bytes of data"
-megasas_scsi_write_start(int cmd, int len) "scmd %d: transfer %d bytes of data"
-megasas_scsi_nodata(int cmd) "scmd %d: no data to be transferred"
-megasas_scsi_complete(int cmd, uint32_t status, int len, int xfer) "scmd %d: status %x, len %u/%u"
-megasas_command_complete(int cmd, uint32_t status, uint32_t resid) "scmd %d: status %x, residual %d"
-megasas_handle_io(int cmd, const char *frame, int dev, int lun, unsigned long lba, unsigned long count) "scmd %d: %s dev %x/%x lba %lx count %lu"
-megasas_io_target_not_present(int cmd, const char *frame, int dev, int lun) "scmd %d: %s dev 1/%x/%x LUN not present"
-megasas_io_read_start(int cmd, unsigned long lba, unsigned long count, unsigned long len) "scmd %d: start LBA %lx %lu blocks (%lu bytes)"
-megasas_io_write_start(int cmd, unsigned long lba, unsigned long count, unsigned long len) "scmd %d: start LBA %lx %lu blocks (%lu bytes)"
-megasas_io_complete(int cmd, uint32_t len) "scmd %d: %d bytes"
-megasas_iovec_sgl_overflow(int cmd, int index, int limit) "scmd %d: iovec count %d limit %d"
-megasas_iovec_sgl_underflow(int cmd, int index) "scmd %d: iovec count %d"
-megasas_iovec_sgl_invalid(int cmd, int index, uint64_t pa, uint32_t len) "scmd %d: element %d pa %" PRIx64 " len %u"
-megasas_iovec_overflow(int cmd, int len, int limit) "scmd %d: len %d limit %d"
-megasas_iovec_underflow(int cmd, int len, int limit) "scmd %d: len %d limit %d"
-megasas_handle_dcmd(int cmd, int opcode) "scmd %d: MFI DCMD opcode %x"
-megasas_finish_dcmd(int cmd, int size) "scmd %d: MFI DCMD wrote %d bytes"
-megasas_dcmd_req_alloc_failed(int cmd, const char *desc) "scmd %d: %s"
-megasas_dcmd_internal_submit(int cmd, const char *desc, int dev) "scmd %d: %s to dev %d"
-megasas_dcmd_internal_finish(int cmd, int opcode, int lun) "scmd %d: cmd %x lun %d"
-megasas_dcmd_internal_invalid(int cmd, int opcode) "scmd %d: DCMD %x"
-megasas_dcmd_unhandled(int cmd, int opcode, int len) "scmd %d: opcode %x, len %d"
-megasas_dcmd_zero_sge(int cmd) "scmd %d: zero DCMD sge count"
-megasas_dcmd_invalid_sge(int cmd, int count) "scmd %d: DCMD sge count %d"
-megasas_dcmd_invalid_xfer_len(int cmd, unsigned long size, unsigned long max) "scmd %d: xfer len %ld, max %ld"
-megasas_dcmd_enter(int cmd, const char *dcmd, int len) "scmd %d: DCMD %s len %d"
-megasas_dcmd_dummy(int cmd, unsigned long size) "scmd %d: xfer len %ld"
-megasas_dcmd_set_fw_time(int cmd, unsigned long time) "scmd %d: Set FW time %lx"
-megasas_dcmd_pd_get_list(int cmd, int num, int max, int offset) "scmd %d: DCMD PD get list: %d / %d PDs, size %d"
-megasas_dcmd_ld_get_list(int cmd, int num, int max) "scmd %d: DCMD LD get list: found %d / %d LDs"
-megasas_dcmd_ld_get_info(int cmd, int ld_id) "scmd %d: dev %d"
-megasas_dcmd_ld_list_query(int cmd, int flags) "scmd %d: query flags %x"
-megasas_dcmd_pd_get_info(int cmd, int pd_id) "scmd %d: dev %d"
-megasas_dcmd_pd_list_query(int cmd, int flags) "scmd %d: query flags %x"
-megasas_dcmd_reset_ld(int cmd, int target_id) "scmd %d: dev %d"
-megasas_dcmd_unsupported(int cmd, unsigned long size) "scmd %d: set properties len %ld"
-megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: frame %x"
-megasas_abort_no_cmd(int cmd, uint64_t context) "scmd %d: no active command for frame context %" PRIx64
-megasas_abort_invalid_context(int cmd, uint64_t context, int abort_cmd) "scmd %d: invalid frame context %" PRIx64 " for abort frame %x"
-megasas_reset(int fw_state) "firmware state %x"
-megasas_init(int sges, int cmds, const char *mode) "Using %d sges, %d cmds, %s mode"
-megasas_msix_raise(int vector) "vector %d"
-megasas_msi_raise(int vector) "vector %d"
-megasas_irq_lower(void) "INTx"
-megasas_irq_raise(void) "INTx"
-megasas_intr_enabled(void) "Interrupts enabled"
-megasas_intr_disabled(void) "Interrupts disabled"
-megasas_msix_enabled(int vector) "vector %d"
-megasas_msi_enabled(int vector) "vector %d"
-megasas_mmio_readl(const char *reg, uint32_t val) "reg %s: 0x%x"
-megasas_mmio_invalid_readl(unsigned long addr) "addr 0x%lx"
-megasas_mmio_writel(const char *reg, uint32_t val) "reg %s: 0x%x"
-megasas_mmio_invalid_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x"
-
-# hw/scsi/vmw_pvscsi.c
-pvscsi_ring_init_data(uint32_t txr_len_log2, uint32_t rxr_len_log2) "TX/RX rings logarithms set to %d/%d"
-pvscsi_ring_init_msg(uint32_t len_log2) "MSG ring logarithm set to %d"
-pvscsi_ring_flush_cmp(uint64_t filled_cmp_ptr) "new production counter of completion ring is 0x%"PRIx64
-pvscsi_ring_flush_msg(uint64_t filled_cmp_ptr) "new production counter of message ring is 0x%"PRIx64
-pvscsi_update_irq_level(bool raise, uint64_t mask, uint64_t status) "interrupt level set to %d (MASK: 0x%"PRIx64", STATUS: 0x%"PRIx64")"
-pvscsi_update_irq_msi(void) "sending MSI notification"
-pvscsi_cmp_ring_put(unsigned long addr) "got completion descriptor 0x%lx"
-pvscsi_msg_ring_put(unsigned long addr) "got message descriptor 0x%lx"
-pvscsi_complete_request(uint64_t context, uint64_t len, uint8_t sense_key) "completion: ctx: 0x%"PRIx64", len: 0x%"PRIx64", sense key: %u"
-pvscsi_get_sg_list(int nsg, size_t size) "get SG list: depth: %u, size: %zu"
-pvscsi_get_next_sg_elem(uint32_t flags) "unknown flags in SG element (val: 0x%x)"
-pvscsi_command_complete_not_found(uint32_t tag) "can't find request for tag 0x%x"
-pvscsi_command_complete_data_run(void) "not all data required for command transferred"
-pvscsi_command_complete_sense_len(int len) "sense information length is %d bytes"
-pvscsi_convert_sglist(uint64_t context, unsigned long addr, uint32_t resid) "element: ctx: 0x%"PRIx64" addr: 0x%lx, len: %ul"
-pvscsi_process_req_descr(uint8_t cmd, uint64_t ctx) "SCSI cmd 0x%x, ctx: 0x%"PRIx64
-pvscsi_process_req_descr_unknown_device(void) "command directed to unknown device rejected"
-pvscsi_process_req_descr_invalid_dir(void) "command with invalid transfer direction rejected"
-pvscsi_process_io(unsigned long addr) "got descriptor 0x%lx"
-pvscsi_on_cmd_noimpl(const char* cmd) "unimplemented command %s ignored"
-pvscsi_on_cmd_reset_dev(uint32_t tgt, int lun, void* dev) "PVSCSI_CMD_RESET_DEVICE[target %u lun %d (dev 0x%p)]"
-pvscsi_on_cmd_arrived(const char* cmd) "command %s arrived"
-pvscsi_on_cmd_abort(uint64_t ctx, uint32_t tgt) "command PVSCSI_CMD_ABORT_CMD for ctx 0x%"PRIx64", target %u"
-pvscsi_on_cmd_unknown(uint64_t cmd_id) "unknown command %"PRIx64
-pvscsi_on_cmd_unknown_data(uint32_t data) "data for unknown command 0x:%x"
-pvscsi_io_write(const char* cmd, uint64_t val) "%s write: %"PRIx64
-pvscsi_io_write_unknown(unsigned long addr, unsigned sz, uint64_t val) "unknown write address: 0x%lx size: %u bytes value: 0x%"PRIx64
-pvscsi_io_read(const char* cmd, uint64_t status) "%s read: 0x%"PRIx64
-pvscsi_io_read_unknown(unsigned long addr, unsigned sz) "unknown read address: 0x%lx size: %u bytes"
-pvscsi_init_msi_fail(int res) "failed to initialize MSI, error %d"
-pvscsi_state(const char* state) "starting %s ..."
-pvscsi_tx_rings_ppn(const char* label, uint64_t ppn) "%s page: %"PRIx64
-pvscsi_tx_rings_num_pages(const char* label, uint32_t num) "Number of %s pages: %u"
-
-# hw/scsi/esp.c
-esp_error_fifo_overrun(void) "FIFO overrun"
-esp_error_unhandled_command(uint32_t val) "unhandled command (%2.2x)"
-esp_error_invalid_write(uint32_t val, uint32_t addr) "invalid write of 0x%02x at [0x%x]"
-esp_raise_irq(void) "Raise IRQ"
-esp_lower_irq(void) "Lower IRQ"
-esp_dma_enable(void) "Raise enable"
-esp_dma_disable(void) "Lower enable"
-esp_get_cmd(uint32_t dmalen, int target) "len %d target %d"
-esp_do_busid_cmd(uint8_t busid) "busid 0x%x"
-esp_handle_satn_stop(uint32_t cmdlen) "cmdlen %d"
-esp_write_response(uint32_t status) "Transfer status (status=%d)"
-esp_do_dma(uint32_t cmdlen, uint32_t len) "command len %d + %d"
-esp_command_complete(void) "SCSI Command complete"
-esp_command_complete_unexpected(void) "SCSI command completed unexpectedly"
-esp_command_complete_fail(void) "Command failed"
-esp_transfer_data(uint32_t dma_left, int32_t ti_size) "transfer %d/%d"
-esp_handle_ti(uint32_t minlen) "Transfer Information len %d"
-esp_handle_ti_cmd(uint32_t cmdlen) "command len %d"
-esp_mem_readb(uint32_t saddr, uint8_t reg) "reg[%d]: 0x%2.2x"
-esp_mem_writeb(uint32_t saddr, uint8_t reg, uint32_t val) "reg[%d]: 0x%2.2x -> 0x%2.2x"
-esp_mem_writeb_cmd_nop(uint32_t val) "NOP (%2.2x)"
-esp_mem_writeb_cmd_flush(uint32_t val) "Flush FIFO (%2.2x)"
-esp_mem_writeb_cmd_reset(uint32_t val) "Chip reset (%2.2x)"
-esp_mem_writeb_cmd_bus_reset(uint32_t val) "Bus reset (%2.2x)"
-esp_mem_writeb_cmd_iccs(uint32_t val) "Initiator Command Complete Sequence (%2.2x)"
-esp_mem_writeb_cmd_msgacc(uint32_t val) "Message Accepted (%2.2x)"
-esp_mem_writeb_cmd_pad(uint32_t val) "Transfer padding (%2.2x)"
-esp_mem_writeb_cmd_satn(uint32_t val) "Set ATN (%2.2x)"
-esp_mem_writeb_cmd_rstatn(uint32_t val) "Reset ATN (%2.2x)"
-esp_mem_writeb_cmd_sel(uint32_t val) "Select without ATN (%2.2x)"
-esp_mem_writeb_cmd_selatn(uint32_t val) "Select with ATN (%2.2x)"
-esp_mem_writeb_cmd_selatns(uint32_t val) "Select with ATN & stop (%2.2x)"
-esp_mem_writeb_cmd_ensel(uint32_t val) "Enable selection (%2.2x)"
-esp_mem_writeb_cmd_dissel(uint32_t val) "Disable selection (%2.2x)"
-
-# hw/scsi/esp-pci.c
-esp_pci_error_invalid_dma_direction(void) "invalid DMA transfer direction"
-esp_pci_error_invalid_read(uint32_t reg) "read access outside bounds (reg 0x%x)"
-esp_pci_error_invalid_write(uint32_t reg) "write access outside bounds (reg 0x%x)"
-esp_pci_error_invalid_write_dma(uint32_t val, uint32_t addr) "invalid write of 0x%02x at [0x%x]"
-esp_pci_dma_read(uint32_t saddr, uint32_t reg) "reg[%d]: 0x%8.8x"
-esp_pci_dma_write(uint32_t saddr, uint32_t reg, uint32_t val) "reg[%d]: 0x%8.8x -> 0x%8.8x"
-esp_pci_dma_idle(uint32_t val) "IDLE (%.8x)"
-esp_pci_dma_blast(uint32_t val) "BLAST (%.8x)"
-esp_pci_dma_abort(uint32_t val) "ABORT (%.8x)"
-esp_pci_dma_start(uint32_t val) "START (%.8x)"
-esp_pci_sbac_read(uint32_t reg) "sbac: 0x%8.8x"
-esp_pci_sbac_write(uint32_t reg, uint32_t val) "sbac: 0x%8.8x -> 0x%8.8x"
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 5b2694615..9261d51da 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -15,9 +15,8 @@
*/
#include "qemu/osdep.h"
-#include <linux/vhost.h>
-#include <sys/ioctl.h>
#include "qapi/error.h"
+#include <sys/ioctl.h>
#include "qemu/error-report.h"
#include "qemu/queue.h"
#include "monitor/monitor.h"
@@ -28,6 +27,7 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
#include "hw/fw-path-provider.h"
+#include "linux/vhost.h"
#include "qemu/cutils.h"
/* Features supported by host kernel. */
@@ -248,7 +248,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
s->dev.backend_features = 0;
ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd,
- VHOST_BACKEND_TYPE_KERNEL, 0);
+ VHOST_BACKEND_TYPE_KERNEL);
if (ret < 0) {
error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
strerror(-ret));
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index b173b9494..1a49f1e4b 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -15,9 +15,9 @@
#include "hw/virtio/virtio-scsi.h"
#include "qemu/error-report.h"
#include "sysemu/block-backend.h"
-#include "hw/scsi/scsi.h"
-#include "block/scsi.h"
-#include "hw/virtio/virtio-bus.h"
+#include <hw/scsi/scsi.h>
+#include <block/scsi.h>
+#include <hw/virtio/virtio-bus.h>
#include "hw/virtio/virtio-access.h"
/* Context: QEMU global mutex held */
@@ -31,7 +31,7 @@ void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread *iothread)
s->ctx = iothread_get_aio_context(vs->conf.iothread);
/* Don't try if transport does not support notifiers. */
- if (!k->set_guest_notifiers || !k->ioeventfd_started) {
+ if (!k->set_guest_notifiers || !k->set_host_notifier) {
fprintf(stderr, "virtio-scsi: Failed to set iothread "
"(transport does not support notifiers)");
exit(1);
@@ -69,10 +69,11 @@ static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n,
void (*fn)(VirtIODevice *vdev, VirtQueue *vq))
{
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
int rc;
/* Set up virtqueue notify */
- rc = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), n, true);
+ rc = k->set_host_notifier(qbus->parent, n, true);
if (rc != 0) {
fprintf(stderr, "virtio-scsi: Failed to set host notifier (%d)\n",
rc);
@@ -158,7 +159,7 @@ fail_vrings:
virtio_scsi_clear_aio(s);
aio_context_release(s->ctx);
for (i = 0; i < vs->conf.num_queues + 2; i++) {
- virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ k->set_host_notifier(qbus->parent, i, false);
}
k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false);
fail_guest_notifiers:
@@ -197,7 +198,7 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s)
aio_context_release(s->ctx);
for (i = 0; i < vs->conf.num_queues + 2; i++) {
- virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ k->set_host_notifier(qbus->parent, i, false);
}
/* Clean up guest notifier (irq) */
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index ce57ef624..30415c6a9 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -20,9 +20,9 @@
#include "qemu/error-report.h"
#include "qemu/iov.h"
#include "sysemu/block-backend.h"
-#include "hw/scsi/scsi.h"
-#include "block/scsi.h"
-#include "hw/virtio/virtio-bus.h"
+#include <hw/scsi/scsi.h>
+#include <block/scsi.h>
+#include <hw/virtio/virtio-bus.h>
#include "hw/virtio/virtio-access.h"
static inline int virtio_scsi_get_lun(uint8_t *lun)
@@ -185,7 +185,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
{
VirtIOSCSIReq *req = sreq->hba_private;
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev);
- uint32_t n = virtio_get_queue_index(req->vq) - 2;
+ uint32_t n = virtio_queue_get_id(req->vq) - 2;
assert(n < vs->conf.num_queues);
qemu_put_be32s(f, &n);
@@ -663,17 +663,27 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
/* The device does not have anything to save beyond the virtio data.
* Request data is saved with callbacks from SCSI devices.
*/
-static void virtio_scsi_save(QEMUFile *f, void *opaque, size_t size)
+static void virtio_scsi_save(QEMUFile *f, void *opaque)
{
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
+ VirtIOSCSI *s = VIRTIO_SCSI(vdev);
+
+ if (s->dataplane_started) {
+ virtio_scsi_dataplane_stop(s);
+ }
virtio_save(vdev, f);
}
-static int virtio_scsi_load(QEMUFile *f, void *opaque, size_t size)
+static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
+ int ret;
- return virtio_load(vdev, f, 1);
+ ret = virtio_load(vdev, f, version_id);
+ if (ret) {
+ return ret;
+ }
+ return 0;
}
void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
@@ -763,6 +773,22 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
}
}
+static void virtio_scsi_blk_insert_notifier(Notifier *n, void *data)
+{
+ VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier,
+ n, n);
+ assert(cn->sd->conf.blk == data);
+ blk_op_block_all(cn->sd->conf.blk, cn->s->blocker);
+}
+
+static void virtio_scsi_blk_remove_notifier(Notifier *n, void *data)
+{
+ VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier,
+ n, n);
+ assert(cn->sd->conf.blk == data);
+ blk_op_unblock_all(cn->sd->conf.blk, cn->s->blocker);
+}
+
static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
@@ -771,13 +797,29 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
SCSIDevice *sd = SCSI_DEVICE(dev);
if (s->ctx && !s->dataplane_fenced) {
+ VirtIOSCSIBlkChangeNotifier *insert_notifier, *remove_notifier;
+
if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
return;
}
+ blk_op_block_all(sd->conf.blk, s->blocker);
aio_context_acquire(s->ctx);
blk_set_aio_context(sd->conf.blk, s->ctx);
aio_context_release(s->ctx);
+ insert_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1);
+ insert_notifier->n.notify = virtio_scsi_blk_insert_notifier;
+ insert_notifier->s = s;
+ insert_notifier->sd = sd;
+ blk_add_insert_bs_notifier(sd->conf.blk, &insert_notifier->n);
+ QTAILQ_INSERT_TAIL(&s->insert_notifiers, insert_notifier, next);
+
+ remove_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1);
+ remove_notifier->n.notify = virtio_scsi_blk_remove_notifier;
+ remove_notifier->s = s;
+ remove_notifier->sd = sd;
+ blk_add_remove_bs_notifier(sd->conf.blk, &remove_notifier->n);
+ QTAILQ_INSERT_TAIL(&s->remove_notifiers, remove_notifier, next);
}
if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
@@ -793,6 +835,7 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
SCSIDevice *sd = SCSI_DEVICE(dev);
+ VirtIOSCSIBlkChangeNotifier *insert_notifier, *remove_notifier;
if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
virtio_scsi_push_event(s, sd,
@@ -800,6 +843,28 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
VIRTIO_SCSI_EVT_RESET_REMOVED);
}
+ if (s->ctx) {
+ blk_op_unblock_all(sd->conf.blk, s->blocker);
+ }
+
+ QTAILQ_FOREACH(insert_notifier, &s->insert_notifiers, next) {
+ if (insert_notifier->sd == sd) {
+ notifier_remove(&insert_notifier->n);
+ QTAILQ_REMOVE(&s->insert_notifiers, insert_notifier, next);
+ g_free(insert_notifier);
+ break;
+ }
+ }
+
+ QTAILQ_FOREACH(remove_notifier, &s->remove_notifiers, next) {
+ if (remove_notifier->sd == sd) {
+ notifier_remove(&remove_notifier->n);
+ QTAILQ_REMOVE(&s->remove_notifiers, remove_notifier, next);
+ g_free(remove_notifier);
+ break;
+ }
+ }
+
qdev_simple_device_unplug_cb(hotplug_dev, dev, errp);
}
@@ -819,9 +884,8 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
};
void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
- VirtIOHandleOutput ctrl,
- VirtIOHandleOutput evt,
- VirtIOHandleOutput cmd)
+ HandleOutput ctrl, HandleOutput evt,
+ HandleOutput cmd)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);
@@ -842,10 +906,13 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
s->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
s->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
- s->ctrl_vq = virtio_add_queue_aio(vdev, VIRTIO_SCSI_VQ_SIZE, ctrl);
- s->event_vq = virtio_add_queue_aio(vdev, VIRTIO_SCSI_VQ_SIZE, evt);
+ s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
+ ctrl);
+ s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
+ evt);
for (i = 0; i < s->conf.num_queues; i++) {
- s->cmd_vqs[i] = virtio_add_queue_aio(vdev, VIRTIO_SCSI_VQ_SIZE, cmd);
+ s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
+ cmd);
}
if (s->conf.iothread) {
@@ -857,6 +924,7 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOSCSI *s = VIRTIO_SCSI(dev);
+ static int virtio_scsi_id;
Error *err = NULL;
virtio_scsi_common_realize(dev, &err, virtio_scsi_handle_ctrl,
@@ -879,6 +947,14 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
return;
}
}
+
+ register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
+ virtio_scsi_save, virtio_scsi_load, s);
+
+ error_setg(&s->blocker, "block device is in use by data plane");
+
+ QTAILQ_INIT(&s->insert_notifiers);
+ QTAILQ_INIT(&s->remove_notifiers);
}
static void virtio_scsi_instance_init(Object *obj)
@@ -902,6 +978,11 @@ void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
{
+ VirtIOSCSI *s = VIRTIO_SCSI(dev);
+
+ error_free(s->blocker);
+
+ unregister_savevm(dev, "virtio-scsi", s);
virtio_scsi_common_unrealize(dev, errp);
}
@@ -918,8 +999,6 @@ static Property virtio_scsi_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-VMSTATE_VIRTIO_DEVICE(scsi, 1, virtio_scsi_load, virtio_scsi_save);
-
static void virtio_scsi_common_class_init(ObjectClass *klass, void *data)
{
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
@@ -936,7 +1015,6 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data)
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
dc->props = virtio_scsi_properties;
- dc->vmsd = &vmstate_virtio_scsi;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->realize = virtio_scsi_device_realize;
vdc->unrealize = virtio_scsi_device_unrealize;
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 5116f4ad6..2d7528d1d 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -28,7 +28,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/scsi/scsi.h"
-#include "block/scsi.h"
+#include <block/scsi.h>
#include "hw/pci/msi.h"
#include "vmw_pvscsi.h"
#include "trace.h"
@@ -121,7 +121,8 @@ typedef struct {
uint8_t msg_ring_info_valid; /* Whether message ring initialized */
uint8_t use_msg; /* Whether to use message ring */
- uint8_t msi_used; /* For migration compatibility */
+ uint8_t msi_used; /* Whether MSI support was installed successfully */
+
PVSCSIRingInfo rings; /* Data transfer rings manager */
uint32_t resetting; /* Reset in progress */
@@ -361,7 +362,7 @@ pvscsi_update_irq_status(PVSCSIState *s)
trace_pvscsi_update_irq_level(should_raise, s->reg_interrupt_enabled,
s->reg_interrupt_status);
- if (msi_enabled(d)) {
+ if (s->msi_used && msi_enabled(d)) {
if (should_raise) {
trace_pvscsi_update_irq_msi();
msi_notify(d, PVSCSI_VECTOR_COMPLETION);
@@ -1055,20 +1056,22 @@ pvscsi_io_read(void *opaque, hwaddr addr, unsigned size)
}
-static void
+static bool
pvscsi_init_msi(PVSCSIState *s)
{
int res;
PCIDevice *d = PCI_DEVICE(s);
res = msi_init(d, PVSCSI_MSI_OFFSET(s), PVSCSI_MSIX_NUM_VECTORS,
- PVSCSI_USE_64BIT, PVSCSI_PER_VECTOR_MASK, NULL);
+ PVSCSI_USE_64BIT, PVSCSI_PER_VECTOR_MASK);
if (res < 0) {
trace_pvscsi_init_msi_fail(res);
s->msi_used = false;
} else {
s->msi_used = true;
}
+
+ return s->msi_used;
}
static void
@@ -1076,7 +1079,9 @@ pvscsi_cleanup_msi(PVSCSIState *s)
{
PCIDevice *d = PCI_DEVICE(s);
- msi_uninit(d);
+ if (s->msi_used) {
+ msi_uninit(d);
+ }
}
static const MemoryRegionOps pvscsi_ops = {
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 1f2f0ed44..c04ff02fa 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -18,7 +18,7 @@
*
*
* Specification available at:
- * http://milkymist.walle.cc/socdoc/memcard.pdf
+ * http://www.milkymist.org/socdoc/memcard.pdf
*/
#include "qemu/osdep.h"
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 82c63a4fb..e87abb205 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -12,8 +12,6 @@
#include "sysemu/blockdev.h"
#include "hw/sysbus.h"
#include "hw/sd/sd.h"
-#include "qemu/log.h"
-#include "qapi/error.h"
//#define DEBUG_PL181 1
@@ -482,48 +480,43 @@ static void pl181_reset(DeviceState *d)
sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
}
-static void pl181_init(Object *obj)
+static int pl181_init(SysBusDevice *sbd)
{
- DeviceState *dev = DEVICE(obj);
- PL181State *s = PL181(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ DeviceState *dev = DEVICE(sbd);
+ PL181State *s = PL181(dev);
+ DriveInfo *dinfo;
- memory_region_init_io(&s->iomem, obj, &pl181_ops, s, "pl181", 0x1000);
+ memory_region_init_io(&s->iomem, OBJECT(s), &pl181_ops, s, "pl181", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq[0]);
sysbus_init_irq(sbd, &s->irq[1]);
qdev_init_gpio_out(dev, s->cardstatus, 2);
-}
-
-static void pl181_realize(DeviceState *dev, Error **errp)
-{
- PL181State *s = PL181(dev);
- DriveInfo *dinfo;
-
/* FIXME use a qdev drive property instead of drive_get_next() */
dinfo = drive_get_next(IF_SD);
s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
if (s->card == NULL) {
- error_setg(errp, "sd_init failed");
+ return -1;
}
+
+ return 0;
}
static void pl181_class_init(ObjectClass *klass, void *data)
{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *k = DEVICE_CLASS(klass);
+ sdc->init = pl181_init;
k->vmsd = &vmstate_pl181;
k->reset = pl181_reset;
/* Reason: init() method uses drive_get_next() */
k->cannot_instantiate_with_device_add_yet = true;
- k->realize = pl181_realize;
}
static const TypeInfo pl181_info = {
.name = TYPE_PL181,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PL181State),
- .instance_init = pl181_init,
.class_init = pl181_class_init,
};
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 87c6dc108..b66e5d2db 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -39,7 +39,6 @@
#include "hw/qdev-properties.h"
#include "qemu/error-report.h"
#include "qemu/timer.h"
-#include "qemu/log.h"
//#define DEBUG_SD 1
@@ -124,6 +123,7 @@ struct SDState {
qemu_irq readonly_cb;
qemu_irq inserted_cb;
BlockBackend *blk;
+ uint8_t *buf;
bool enable;
};
@@ -551,7 +551,7 @@ static const VMStateDescription sd_vmstate = {
VMSTATE_UINT64(data_start, SDState),
VMSTATE_UINT32(data_offset, SDState),
VMSTATE_UINT8_ARRAY(data, SDState, 512),
- VMSTATE_UNUSED_V(1, 512),
+ VMSTATE_BUFFER_POINTER_UNSAFE(buf, SDState, 1, 512),
VMSTATE_BOOL(enable, SDState),
VMSTATE_END_OF_LIST()
},
@@ -1577,17 +1577,57 @@ send_response:
static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
{
+ uint64_t end = addr + len;
+
DPRINTF("sd_blk_read: addr = 0x%08llx, len = %d\n",
(unsigned long long) addr, len);
- if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) {
+ if (!sd->blk || blk_read(sd->blk, addr >> 9, sd->buf, 1) < 0) {
fprintf(stderr, "sd_blk_read: read error on host side\n");
+ return;
}
+
+ if (end > (addr & ~511) + 512) {
+ memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511));
+
+ if (blk_read(sd->blk, end >> 9, sd->buf, 1) < 0) {
+ fprintf(stderr, "sd_blk_read: read error on host side\n");
+ return;
+ }
+ memcpy(sd->data + 512 - (addr & 511), sd->buf, end & 511);
+ } else
+ memcpy(sd->data, sd->buf + (addr & 511), len);
}
static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
{
- if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) {
- fprintf(stderr, "sd_blk_write: write error on host side\n");
+ uint64_t end = addr + len;
+
+ if ((addr & 511) || len < 512)
+ if (!sd->blk || blk_read(sd->blk, addr >> 9, sd->buf, 1) < 0) {
+ fprintf(stderr, "sd_blk_write: read error on host side\n");
+ return;
+ }
+
+ if (end > (addr & ~511) + 512) {
+ memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511));
+ if (blk_write(sd->blk, addr >> 9, sd->buf, 1) < 0) {
+ fprintf(stderr, "sd_blk_write: write error on host side\n");
+ return;
+ }
+
+ if (blk_read(sd->blk, end >> 9, sd->buf, 1) < 0) {
+ fprintf(stderr, "sd_blk_write: read error on host side\n");
+ return;
+ }
+ memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511);
+ if (blk_write(sd->blk, end >> 9, sd->buf, 1) < 0) {
+ fprintf(stderr, "sd_blk_write: write error on host side\n");
+ }
+ } else {
+ memcpy(sd->buf + (addr & 511), sd->data, len);
+ if (!sd->blk || blk_write(sd->blk, addr >> 9, sd->buf, 1) < 0) {
+ fprintf(stderr, "sd_blk_write: write error on host side\n");
+ }
}
}
@@ -1885,6 +1925,8 @@ static void sd_realize(DeviceState *dev, Error **errp)
return;
}
+ sd->buf = blk_blockalign(sd->blk, 512);
+
if (sd->blk) {
blk_set_dev_ops(sd->blk, &sd_block_ops, sd);
}
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 01fbf228b..d28b5871f 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -30,7 +30,6 @@
#include "qemu/timer.h"
#include "qemu/bitops.h"
#include "sdhci-internal.h"
-#include "qemu/log.h"
/* host controller debug messages */
#ifndef SDHC_DEBUG
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 3ff0886dd..075e4ed5d 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -15,7 +15,6 @@
#include "sysemu/blockdev.h"
#include "hw/ssi/ssi.h"
#include "hw/sd/sd.h"
-#include "qapi/error.h"
//#define DEBUG_SSI_SD 1
@@ -250,7 +249,7 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
-static void ssi_sd_realize(SSISlave *d, Error **errp)
+static int ssi_sd_init(SSISlave *d)
{
DeviceState *dev = DEVICE(d);
ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
@@ -261,17 +260,17 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
dinfo = drive_get_next(IF_SD);
s->sd = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, true);
if (s->sd == NULL) {
- error_setg(errp, "Device initialization failed.");
- return;
+ return -1;
}
register_savevm(dev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
+ return 0;
}
static void ssi_sd_class_init(ObjectClass *klass, void *data)
{
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
- k->realize = ssi_sd_realize;
+ k->init = ssi_sd_init;
k->transfer = ssi_sd_transfer;
k->cs_polarity = SSI_CS_LOW;
}
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
deleted file mode 100644
index b17e7ba44..000000000
--- a/hw/sd/trace-events
+++ /dev/null
@@ -1,5 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/sd/milkymist-memcard.c
-milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c
index 3132d559d..a1ea760f6 100644
--- a/hw/sh4/sh7750.c
+++ b/hw/sh4/sh7750.c
@@ -30,7 +30,6 @@
#include "sh7750_regnames.h"
#include "hw/sh4/sh_intc.h"
#include "cpu.h"
-#include "exec/exec-all.h"
#include "exec/address-spaces.h"
#define NB_DEVICES 4
diff --git a/hw/sh4/sh7750_regnames.h b/hw/sh4/sh7750_regnames.h
index e3ba88636..7463709b4 100644
--- a/hw/sh4/sh7750_regnames.h
+++ b/hw/sh4/sh7750_regnames.h
@@ -1,6 +1,6 @@
-#ifndef SH7750_REGNAMES_H
-#define SH7750_REGNAMES_H
+#ifndef _SH7750_REGNAMES_H
+#define _SH7750_REGNAMES_H
const char *regname(uint32_t addr);
-#endif /* SH7750_REGNAMES_H */
+#endif /* _SH7750_REGNAMES_H */
diff --git a/hw/sh4/sh7750_regs.h b/hw/sh4/sh7750_regs.h
index 3e4554af3..534aa4840 100644
--- a/hw/sh4/sh7750_regs.h
+++ b/hw/sh4/sh7750_regs.h
@@ -16,8 +16,8 @@
* @(#) sh7750_regs.h,v 1.2.4.1 2003/09/04 18:46:00 joel Exp
*/
-#ifndef SH7750_REGS_H
-#define SH7750_REGS_H
+#ifndef __SH7750_REGS_H__
+#define __SH7750_REGS_H__
/*
* All register has 2 addresses: in 0xff000000 - 0xffffffff (P4 address) and
diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
index 1747628f3..e820a3230 100644
--- a/hw/sh4/sh_pci.c
+++ b/hw/sh4/sh_pci.c
@@ -55,7 +55,7 @@ static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
switch(addr) {
case 0 ... 0xfc:
- stl_le_p(pcic->dev->config + addr, val);
+ cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
break;
case 0x1c0:
pcic->par = val;
@@ -85,7 +85,7 @@ static uint64_t sh_pci_reg_read (void *p, hwaddr addr,
switch(addr) {
case 0 ... 0xfc:
- return ldl_le_p(pcic->dev->config + addr);
+ return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
case 0x1c0:
return pcic->par;
case 0x1c4:
diff --git a/hw/smbios/Makefile.objs b/hw/smbios/Makefile.objs
index c3d375360..f69a92f96 100644
--- a/hw/smbios/Makefile.objs
+++ b/hw/smbios/Makefile.objs
@@ -1,2 +1 @@
common-obj-$(CONFIG_SMBIOS) += smbios.o
-common-obj-$(call land,$(CONFIG_SMBIOS),$(CONFIG_IPMI)) += smbios_type_38.o
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 74c710292..cb8a11110 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -24,8 +24,6 @@
#include "hw/smbios/smbios.h"
#include "hw/loader.h"
#include "exec/cpu-common.h"
-#include "smbios_build.h"
-#include "hw/smbios/ipmi.h"
/* legacy structures and constants for <= 2.0 machines */
struct smbios_header {
@@ -55,10 +53,10 @@ static bool smbios_uuid_encoded = true;
/* end: legacy structures & constants for <= 2.0 machines */
-uint8_t *smbios_tables;
-size_t smbios_tables_len;
-unsigned smbios_table_max;
-unsigned smbios_table_cnt;
+static uint8_t *smbios_tables;
+static size_t smbios_tables_len;
+static unsigned smbios_table_max;
+static unsigned smbios_table_cnt;
static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_21;
static SmbiosEntryPoint ep;
@@ -431,7 +429,7 @@ uint8_t *smbios_get_table_legacy(size_t *length)
/* end: legacy setup functions for <= 2.0 machines */
-bool smbios_skip_table(uint8_t type, bool required_table)
+static bool smbios_skip_table(uint8_t type, bool required_table)
{
if (test_bit(type, have_binfile_bitmap)) {
return true; /* user provided their own binary blob(s) */
@@ -445,6 +443,65 @@ bool smbios_skip_table(uint8_t type, bool required_table)
return true;
}
+#define SMBIOS_BUILD_TABLE_PRE(tbl_type, tbl_handle, tbl_required) \
+ struct smbios_type_##tbl_type *t; \
+ size_t t_off; /* table offset into smbios_tables */ \
+ int str_index = 0; \
+ do { \
+ /* should we skip building this table ? */ \
+ if (smbios_skip_table(tbl_type, tbl_required)) { \
+ return; \
+ } \
+ \
+ /* use offset of table t within smbios_tables */ \
+ /* (pointer must be updated after each realloc) */ \
+ t_off = smbios_tables_len; \
+ smbios_tables_len += sizeof(*t); \
+ smbios_tables = g_realloc(smbios_tables, smbios_tables_len); \
+ t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
+ \
+ t->header.type = tbl_type; \
+ t->header.length = sizeof(*t); \
+ t->header.handle = cpu_to_le16(tbl_handle); \
+ } while (0)
+
+#define SMBIOS_TABLE_SET_STR(tbl_type, field, value) \
+ do { \
+ int len = (value != NULL) ? strlen(value) + 1 : 0; \
+ if (len > 1) { \
+ smbios_tables = g_realloc(smbios_tables, \
+ smbios_tables_len + len); \
+ memcpy(smbios_tables + smbios_tables_len, value, len); \
+ smbios_tables_len += len; \
+ /* update pointer post-realloc */ \
+ t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
+ t->field = ++str_index; \
+ } else { \
+ t->field = 0; \
+ } \
+ } while (0)
+
+#define SMBIOS_BUILD_TABLE_POST \
+ do { \
+ size_t term_cnt, t_size; \
+ \
+ /* add '\0' terminator (add two if no strings defined) */ \
+ term_cnt = (str_index == 0) ? 2 : 1; \
+ smbios_tables = g_realloc(smbios_tables, \
+ smbios_tables_len + term_cnt); \
+ memset(smbios_tables + smbios_tables_len, 0, term_cnt); \
+ smbios_tables_len += term_cnt; \
+ \
+ /* update smbios max. element size */ \
+ t_size = smbios_tables_len - t_off; \
+ if (t_size > smbios_table_max) { \
+ smbios_table_max = t_size; \
+ } \
+ \
+ /* update smbios element count */ \
+ smbios_table_cnt++; \
+ } while (0)
+
static void smbios_build_type_0_table(void)
{
SMBIOS_BUILD_TABLE_PRE(0, 0x000, false); /* optional, leave up to BIOS */
@@ -849,7 +906,6 @@ void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
}
smbios_build_type_32_table();
- smbios_build_type_38_table();
smbios_build_type_127_table();
smbios_validate_table();
diff --git a/hw/smbios/smbios_build.h b/hw/smbios/smbios_build.h
deleted file mode 100644
index 68b8b72e0..000000000
--- a/hw/smbios/smbios_build.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * SMBIOS Support
- *
- * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
- * Copyright (C) 2013 Red Hat, Inc.
- *
- * Authors:
- * Alex Williamson <alex.williamson@hp.com>
- * Markus Armbruster <armbru@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#ifndef QEMU_SMBIOS_BUILD_H
-#define QEMU_SMBIOS_BUILD_H
-
-bool smbios_skip_table(uint8_t type, bool required_table);
-
-extern uint8_t *smbios_tables;
-extern size_t smbios_tables_len;
-extern unsigned smbios_table_max;
-extern unsigned smbios_table_cnt;
-
-#define SMBIOS_BUILD_TABLE_PRE(tbl_type, tbl_handle, tbl_required) \
- struct smbios_type_##tbl_type *t; \
- size_t t_off; /* table offset into smbios_tables */ \
- int str_index = 0; \
- do { \
- /* should we skip building this table ? */ \
- if (smbios_skip_table(tbl_type, tbl_required)) { \
- return; \
- } \
- \
- /* use offset of table t within smbios_tables */ \
- /* (pointer must be updated after each realloc) */ \
- t_off = smbios_tables_len; \
- smbios_tables_len += sizeof(*t); \
- smbios_tables = g_realloc(smbios_tables, smbios_tables_len); \
- t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
- \
- t->header.type = tbl_type; \
- t->header.length = sizeof(*t); \
- t->header.handle = cpu_to_le16(tbl_handle); \
- } while (0)
-
-#define SMBIOS_TABLE_SET_STR(tbl_type, field, value) \
- do { \
- int len = (value != NULL) ? strlen(value) + 1 : 0; \
- if (len > 1) { \
- smbios_tables = g_realloc(smbios_tables, \
- smbios_tables_len + len); \
- memcpy(smbios_tables + smbios_tables_len, value, len); \
- smbios_tables_len += len; \
- /* update pointer post-realloc */ \
- t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
- t->field = ++str_index; \
- } else { \
- t->field = 0; \
- } \
- } while (0)
-
-#define SMBIOS_BUILD_TABLE_POST \
- do { \
- size_t term_cnt, t_size; \
- \
- /* add '\0' terminator (add two if no strings defined) */ \
- term_cnt = (str_index == 0) ? 2 : 1; \
- smbios_tables = g_realloc(smbios_tables, \
- smbios_tables_len + term_cnt); \
- memset(smbios_tables + smbios_tables_len, 0, term_cnt); \
- smbios_tables_len += term_cnt; \
- \
- /* update smbios max. element size */ \
- t_size = smbios_tables_len - t_off; \
- if (t_size > smbios_table_max) { \
- smbios_table_max = t_size; \
- } \
- \
- /* update smbios element count */ \
- smbios_table_cnt++; \
- } while (0)
-
-#endif /* QEMU_SMBIOS_BUILD_H */
diff --git a/hw/smbios/smbios_type_38.c b/hw/smbios/smbios_type_38.c
deleted file mode 100644
index 56e8609c0..000000000
--- a/hw/smbios/smbios_type_38.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * IPMI SMBIOS firmware handling
- *
- * Copyright (c) 2015,2016 Corey Minyard, MontaVista Software, 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.
- */
-
-#include "qemu/osdep.h"
-#include "hw/ipmi/ipmi.h"
-#include "hw/smbios/ipmi.h"
-#include "hw/smbios/smbios.h"
-#include "qemu/error-report.h"
-#include "smbios_build.h"
-
-/* SMBIOS type 38 - IPMI */
-struct smbios_type_38 {
- struct smbios_structure_header header;
- uint8_t interface_type;
- uint8_t ipmi_spec_revision;
- uint8_t i2c_slave_address;
- uint8_t nv_storage_device_address;
- uint64_t base_address;
- uint8_t base_address_modifier;
- uint8_t interrupt_number;
-} QEMU_PACKED;
-
-static void smbios_build_one_type_38(IPMIFwInfo *info)
-{
- uint64_t baseaddr = info->base_address;
- SMBIOS_BUILD_TABLE_PRE(38, 0x3000, true);
-
- t->interface_type = info->interface_type;
- t->ipmi_spec_revision = ((info->ipmi_spec_major_revision << 4)
- | info->ipmi_spec_minor_revision);
- t->i2c_slave_address = info->i2c_slave_address;
- t->nv_storage_device_address = 0;
-
- assert(info->ipmi_spec_minor_revision <= 15);
- assert(info->ipmi_spec_major_revision <= 15);
-
- /* or 1 to set it to I/O space */
- switch (info->memspace) {
- case IPMI_MEMSPACE_IO:
- baseaddr |= 1;
- break;
- case IPMI_MEMSPACE_MEM32:
- case IPMI_MEMSPACE_MEM64:
- break;
- case IPMI_MEMSPACE_SMBUS:
- baseaddr <<= 1;
- break;
- }
-
- t->base_address = cpu_to_le64(baseaddr);
-
- t->base_address_modifier = 0;
- if (info->irq_type == IPMI_LEVEL_IRQ) {
- t->base_address_modifier |= 1;
- }
- switch (info->register_spacing) {
- case 1:
- break;
- case 4:
- t->base_address_modifier |= 1 << 6;
- break;
- case 16:
- t->base_address_modifier |= 2 << 6;
- break;
- default:
- error_report("IPMI register spacing %d is not compatible with"
- " SMBIOS, ignoring this entry.", info->register_spacing);
- return;
- }
- t->interrupt_number = info->interrupt_number;
-
- SMBIOS_BUILD_TABLE_POST;
-}
-
-static void smbios_add_ipmi_devices(BusState *bus)
-{
- BusChild *kid;
-
- QTAILQ_FOREACH(kid, &bus->children, sibling) {
- DeviceState *dev = kid->child;
- Object *obj = object_dynamic_cast(OBJECT(dev), TYPE_IPMI_INTERFACE);
- BusState *childbus;
-
- if (obj) {
- IPMIInterface *ii;
- IPMIInterfaceClass *iic;
- IPMIFwInfo info;
-
- ii = IPMI_INTERFACE(obj);
- iic = IPMI_INTERFACE_GET_CLASS(obj);
- memset(&info, 0, sizeof(info));
- iic->get_fwinfo(ii, &info);
- smbios_build_one_type_38(&info);
- continue;
- }
-
- QLIST_FOREACH(childbus, &dev->child_bus, sibling) {
- smbios_add_ipmi_devices(childbus);
- }
- }
-}
-
-void smbios_build_type_38_table(void)
-{
- BusState *bus;
-
- bus = sysbus_get_default();
- if (bus) {
- smbios_add_ipmi_devices(bus);
- }
-}
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 6e1647841..dbae41f3a 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -171,11 +171,7 @@ static void leon3_generic_hw_init(MachineState *machine)
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
- if (filename) {
- bios_size = get_image_size(filename);
- } else {
- bios_size = -1;
- }
+ bios_size = get_image_size(filename);
if (bios_size > prom_size) {
fprintf(stderr, "qemu: could not load prom '%s': file too big\n",
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 478fda820..7bfc00abc 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -1000,7 +1000,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus);
slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
- !machine->enable_graphics, ESCC_CLOCK, 1);
+ display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
/* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
diff --git a/hw/sparc/trace-events b/hw/sparc/trace-events
deleted file mode 100644
index 30fb0373e..000000000
--- a/hw/sparc/trace-events
+++ /dev/null
@@ -1,11 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/sparc/sun4m.c
-sun4m_cpu_interrupt(unsigned int level) "Set CPU IRQ %d"
-sun4m_cpu_reset_interrupt(unsigned int level) "Reset CPU IRQ %d"
-sun4m_cpu_set_irq_raise(int level) "Raise CPU IRQ %d"
-sun4m_cpu_set_irq_lower(int level) "Lower CPU IRQ %d"
-
-# hw/sparc/leon3.c
-leon3_set_irq(int intno) "Set CPU IRQ %d"
-leon3_reset_irq(int intno) "Reset CPU IRQ %d"
diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
index c79a8dcd8..9555825ac 100644
--- a/hw/ssi/Makefile.objs
+++ b/hw/ssi/Makefile.objs
@@ -2,7 +2,5 @@ common-obj-$(CONFIG_PL022) += pl022.o
common-obj-$(CONFIG_SSI) += ssi.o
common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
-common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o
obj-$(CONFIG_OMAP) += omap_spi.o
-obj-$(CONFIG_IMX) += imx_spi.o
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
deleted file mode 100644
index d319e04a2..000000000
--- a/hw/ssi/aspeed_smc.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * 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.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "sysemu/sysemu.h"
-#include "qemu/log.h"
-#include "include/qemu/error-report.h"
-#include "exec/address-spaces.h"
-
-#include "hw/ssi/aspeed_smc.h"
-
-/* CE Type Setting Register */
-#define R_CONF (0x00 / 4)
-#define CONF_LEGACY_DISABLE (1 << 31)
-#define CONF_ENABLE_W4 20
-#define CONF_ENABLE_W3 19
-#define CONF_ENABLE_W2 18
-#define CONF_ENABLE_W1 17
-#define CONF_ENABLE_W0 16
-#define CONF_FLASH_TYPE4 9
-#define CONF_FLASH_TYPE3 7
-#define CONF_FLASH_TYPE2 5
-#define CONF_FLASH_TYPE1 3
-#define CONF_FLASH_TYPE0 1
-
-/* CE Control Register */
-#define R_CE_CTRL (0x04 / 4)
-#define CTRL_EXTENDED4 4 /* 32 bit addressing for SPI */
-#define CTRL_EXTENDED3 3 /* 32 bit addressing for SPI */
-#define CTRL_EXTENDED2 2 /* 32 bit addressing for SPI */
-#define CTRL_EXTENDED1 1 /* 32 bit addressing for SPI */
-#define CTRL_EXTENDED0 0 /* 32 bit addressing for SPI */
-
-/* Interrupt Control and Status Register */
-#define R_INTR_CTRL (0x08 / 4)
-#define INTR_CTRL_DMA_STATUS (1 << 11)
-#define INTR_CTRL_CMD_ABORT_STATUS (1 << 10)
-#define INTR_CTRL_WRITE_PROTECT_STATUS (1 << 9)
-#define INTR_CTRL_DMA_EN (1 << 3)
-#define INTR_CTRL_CMD_ABORT_EN (1 << 2)
-#define INTR_CTRL_WRITE_PROTECT_EN (1 << 1)
-
-/* CEx Control Register */
-#define R_CTRL0 (0x10 / 4)
-#define CTRL_CMD_SHIFT 16
-#define CTRL_CMD_MASK 0xff
-#define CTRL_CE_STOP_ACTIVE (1 << 2)
-#define CTRL_CMD_MODE_MASK 0x3
-#define CTRL_READMODE 0x0
-#define CTRL_FREADMODE 0x1
-#define CTRL_WRITEMODE 0x2
-#define CTRL_USERMODE 0x3
-#define R_CTRL1 (0x14 / 4)
-#define R_CTRL2 (0x18 / 4)
-#define R_CTRL3 (0x1C / 4)
-#define R_CTRL4 (0x20 / 4)
-
-/* CEx Segment Address Register */
-#define R_SEG_ADDR0 (0x30 / 4)
-#define SEG_SIZE_SHIFT 24 /* 8MB units */
-#define SEG_SIZE_MASK 0x7f
-#define SEG_START_SHIFT 16 /* address bit [A29-A23] */
-#define SEG_START_MASK 0x7f
-#define R_SEG_ADDR1 (0x34 / 4)
-#define R_SEG_ADDR2 (0x38 / 4)
-#define R_SEG_ADDR3 (0x3C / 4)
-#define R_SEG_ADDR4 (0x40 / 4)
-
-/* Misc Control Register #1 */
-#define R_MISC_CTRL1 (0x50 / 4)
-
-/* Misc Control Register #2 */
-#define R_MISC_CTRL2 (0x54 / 4)
-
-/* DMA Control/Status Register */
-#define R_DMA_CTRL (0x80 / 4)
-#define DMA_CTRL_DELAY_MASK 0xf
-#define DMA_CTRL_DELAY_SHIFT 8
-#define DMA_CTRL_FREQ_MASK 0xf
-#define DMA_CTRL_FREQ_SHIFT 4
-#define DMA_CTRL_MODE (1 << 3)
-#define DMA_CTRL_CKSUM (1 << 2)
-#define DMA_CTRL_DIR (1 << 1)
-#define DMA_CTRL_EN (1 << 0)
-
-/* DMA Flash Side Address */
-#define R_DMA_FLASH_ADDR (0x84 / 4)
-
-/* DMA DRAM Side Address */
-#define R_DMA_DRAM_ADDR (0x88 / 4)
-
-/* DMA Length Register */
-#define R_DMA_LEN (0x8C / 4)
-
-/* Checksum Calculation Result */
-#define R_DMA_CHECKSUM (0x90 / 4)
-
-/* Misc Control Register #2 */
-#define R_TIMINGS (0x94 / 4)
-
-/* SPI controller registers and bits */
-#define R_SPI_CONF (0x00 / 4)
-#define SPI_CONF_ENABLE_W0 0
-#define R_SPI_CTRL0 (0x4 / 4)
-#define R_SPI_MISC_CTRL (0x10 / 4)
-#define R_SPI_TIMINGS (0x14 / 4)
-
-/*
- * Default segments mapping addresses and size for each slave per
- * controller. These can be changed when board is initialized with the
- * Segment Address Registers but they don't seem do be used on the
- * field.
- */
-static const AspeedSegments aspeed_segments_legacy[] = {
- { 0x10000000, 32 * 1024 * 1024 },
-};
-
-static const AspeedSegments aspeed_segments_fmc[] = {
- { 0x20000000, 64 * 1024 * 1024 },
- { 0x24000000, 32 * 1024 * 1024 },
- { 0x26000000, 32 * 1024 * 1024 },
- { 0x28000000, 32 * 1024 * 1024 },
- { 0x2A000000, 32 * 1024 * 1024 }
-};
-
-static const AspeedSegments aspeed_segments_spi[] = {
- { 0x30000000, 64 * 1024 * 1024 },
-};
-
-static const AspeedSMCController controllers[] = {
- { "aspeed.smc.smc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
- CONF_ENABLE_W0, 5, aspeed_segments_legacy, 0x6000000 },
- { "aspeed.smc.fmc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
- CONF_ENABLE_W0, 5, aspeed_segments_fmc, 0x10000000 },
- { "aspeed.smc.spi", R_SPI_CONF, 0xff, R_SPI_CTRL0, R_SPI_TIMINGS,
- SPI_CONF_ENABLE_W0, 1, aspeed_segments_spi, 0x10000000 },
-};
-
-static uint64_t aspeed_smc_flash_default_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- qemu_log_mask(LOG_GUEST_ERROR, "%s: To 0x%" HWADDR_PRIx " of size %u"
- PRIx64 "\n", __func__, addr, size);
- return 0;
-}
-
-static void aspeed_smc_flash_default_write(void *opaque, hwaddr addr,
- uint64_t data, unsigned size)
-{
- qemu_log_mask(LOG_GUEST_ERROR, "%s: To 0x%" HWADDR_PRIx " of size %u: 0x%"
- PRIx64 "\n", __func__, addr, size, data);
-}
-
-static const MemoryRegionOps aspeed_smc_flash_default_ops = {
- .read = aspeed_smc_flash_default_read,
- .write = aspeed_smc_flash_default_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 4,
- },
-};
-
-static inline int aspeed_smc_flash_mode(const AspeedSMCState *s, int cs)
-{
- return s->regs[s->r_ctrl0 + cs] & CTRL_CMD_MODE_MASK;
-}
-
-static inline bool aspeed_smc_is_usermode(const AspeedSMCState *s, int cs)
-{
- return aspeed_smc_flash_mode(s, cs) == CTRL_USERMODE;
-}
-
-static inline bool aspeed_smc_is_writable(const AspeedSMCState *s, int cs)
-{
- return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + cs));
-}
-
-static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
-{
- AspeedSMCFlash *fl = opaque;
- const AspeedSMCState *s = fl->controller;
- uint64_t ret = 0;
- int i;
-
- if (aspeed_smc_is_usermode(s, fl->id)) {
- for (i = 0; i < size; i++) {
- ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
- }
- } else {
- qemu_log_mask(LOG_UNIMP, "%s: usermode not implemented\n",
- __func__);
- ret = -1;
- }
-
- return ret;
-}
-
-static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
- unsigned size)
-{
- AspeedSMCFlash *fl = opaque;
- const AspeedSMCState *s = fl->controller;
- int i;
-
- if (!aspeed_smc_is_writable(s, fl->id)) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: flash is not writable at 0x%"
- HWADDR_PRIx "\n", __func__, addr);
- return;
- }
-
- if (!aspeed_smc_is_usermode(s, fl->id)) {
- qemu_log_mask(LOG_UNIMP, "%s: usermode not implemented\n",
- __func__);
- return;
- }
-
- for (i = 0; i < size; i++) {
- ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
- }
-}
-
-static const MemoryRegionOps aspeed_smc_flash_ops = {
- .read = aspeed_smc_flash_read,
- .write = aspeed_smc_flash_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 4,
- },
-};
-
-static bool aspeed_smc_is_ce_stop_active(const AspeedSMCState *s, int cs)
-{
- return s->regs[s->r_ctrl0 + cs] & CTRL_CE_STOP_ACTIVE;
-}
-
-static void aspeed_smc_update_cs(const AspeedSMCState *s)
-{
- int i;
-
- for (i = 0; i < s->num_cs; ++i) {
- qemu_set_irq(s->cs_lines[i], aspeed_smc_is_ce_stop_active(s, i));
- }
-}
-
-static void aspeed_smc_reset(DeviceState *d)
-{
- AspeedSMCState *s = ASPEED_SMC(d);
- int i;
-
- memset(s->regs, 0, sizeof s->regs);
-
- /* Pretend DMA is done (u-boot initialization) */
- s->regs[R_INTR_CTRL] = INTR_CTRL_DMA_STATUS;
-
- /* Unselect all slaves */
- for (i = 0; i < s->num_cs; ++i) {
- s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE;
- }
-
- aspeed_smc_update_cs(s);
-}
-
-static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
-{
- AspeedSMCState *s = ASPEED_SMC(opaque);
-
- addr >>= 2;
-
- if (addr >= ARRAY_SIZE(s->regs)) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Out-of-bounds read at 0x%" HWADDR_PRIx "\n",
- __func__, addr);
- return 0;
- }
-
- if (addr == s->r_conf ||
- addr == s->r_timings ||
- addr == s->r_ce_ctrl ||
- addr == R_INTR_CTRL ||
- (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs)) {
- return s->regs[addr];
- } else {
- qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
- __func__, addr);
- return 0;
- }
-}
-
-static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
- unsigned int size)
-{
- AspeedSMCState *s = ASPEED_SMC(opaque);
- uint32_t value = data;
-
- addr >>= 2;
-
- if (addr >= ARRAY_SIZE(s->regs)) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Out-of-bounds write at 0x%" HWADDR_PRIx "\n",
- __func__, addr);
- return;
- }
-
- if (addr == s->r_conf ||
- addr == s->r_timings ||
- addr == s->r_ce_ctrl) {
- s->regs[addr] = value;
- } else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
- s->regs[addr] = value;
- aspeed_smc_update_cs(s);
- } else {
- qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
- __func__, addr);
- return;
- }
-}
-
-static const MemoryRegionOps aspeed_smc_ops = {
- .read = aspeed_smc_read,
- .write = aspeed_smc_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid.unaligned = true,
-};
-
-static void aspeed_smc_realize(DeviceState *dev, Error **errp)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- AspeedSMCState *s = ASPEED_SMC(dev);
- AspeedSMCClass *mc = ASPEED_SMC_GET_CLASS(s);
- int i;
- char name[32];
- hwaddr offset = 0;
-
- s->ctrl = mc->ctrl;
-
- /* keep a copy under AspeedSMCState to speed up accesses */
- s->r_conf = s->ctrl->r_conf;
- s->r_ce_ctrl = s->ctrl->r_ce_ctrl;
- s->r_ctrl0 = s->ctrl->r_ctrl0;
- s->r_timings = s->ctrl->r_timings;
- s->conf_enable_w0 = s->ctrl->conf_enable_w0;
-
- /* Enforce some real HW limits */
- if (s->num_cs > s->ctrl->max_slaves) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: num_cs cannot exceed: %d\n",
- __func__, s->ctrl->max_slaves);
- s->num_cs = s->ctrl->max_slaves;
- }
-
- s->spi = ssi_create_bus(dev, "spi");
-
- /* Setup cs_lines for slaves */
- sysbus_init_irq(sbd, &s->irq);
- s->cs_lines = g_new0(qemu_irq, s->num_cs);
- ssi_auto_connect_slaves(dev, s->cs_lines, s->spi);
-
- for (i = 0; i < s->num_cs; ++i) {
- sysbus_init_irq(sbd, &s->cs_lines[i]);
- }
-
- aspeed_smc_reset(dev);
-
- memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s,
- s->ctrl->name, ASPEED_SMC_R_MAX * 4);
- sysbus_init_mmio(sbd, &s->mmio);
-
- /*
- * Memory region where flash modules are remapped
- */
- snprintf(name, sizeof(name), "%s.flash", s->ctrl->name);
-
- memory_region_init_io(&s->mmio_flash, OBJECT(s),
- &aspeed_smc_flash_default_ops, s, name,
- s->ctrl->mapping_window_size);
- sysbus_init_mmio(sbd, &s->mmio_flash);
-
- s->flashes = g_new0(AspeedSMCFlash, s->num_cs);
-
- for (i = 0; i < s->num_cs; ++i) {
- AspeedSMCFlash *fl = &s->flashes[i];
-
- snprintf(name, sizeof(name), "%s.%d", s->ctrl->name, i);
-
- fl->id = i;
- fl->controller = s;
- fl->size = s->ctrl->segments[i].size;
- memory_region_init_io(&fl->mmio, OBJECT(s), &aspeed_smc_flash_ops,
- fl, name, fl->size);
- memory_region_add_subregion(&s->mmio_flash, offset, &fl->mmio);
- offset += fl->size;
- }
-}
-
-static const VMStateDescription vmstate_aspeed_smc = {
- .name = "aspeed.smc",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(regs, AspeedSMCState, ASPEED_SMC_R_MAX),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static Property aspeed_smc_properties[] = {
- DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void aspeed_smc_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- AspeedSMCClass *mc = ASPEED_SMC_CLASS(klass);
-
- dc->realize = aspeed_smc_realize;
- dc->reset = aspeed_smc_reset;
- dc->props = aspeed_smc_properties;
- dc->vmsd = &vmstate_aspeed_smc;
- mc->ctrl = data;
-}
-
-static const TypeInfo aspeed_smc_info = {
- .name = TYPE_ASPEED_SMC,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(AspeedSMCState),
- .class_size = sizeof(AspeedSMCClass),
- .abstract = true,
-};
-
-static void aspeed_smc_register_types(void)
-{
- int i;
-
- type_register_static(&aspeed_smc_info);
- for (i = 0; i < ARRAY_SIZE(controllers); ++i) {
- TypeInfo ti = {
- .name = controllers[i].name,
- .parent = TYPE_ASPEED_SMC,
- .class_init = aspeed_smc_class_init,
- .class_data = (void *)&controllers[i],
- };
- type_register(&ti);
- }
-}
-
-type_init(aspeed_smc_register_types)
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
deleted file mode 100644
index 422619981..000000000
--- a/hw/ssi/imx_spi.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * IMX SPI Controller
- *
- * Copyright (c) 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.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/ssi/imx_spi.h"
-#include "sysemu/sysemu.h"
-#include "qemu/log.h"
-
-#ifndef DEBUG_IMX_SPI
-#define DEBUG_IMX_SPI 0
-#endif
-
-#define DPRINTF(fmt, args...) \
- do { \
- if (DEBUG_IMX_SPI) { \
- fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_SPI, \
- __func__, ##args); \
- } \
- } while (0)
-
-static char const *imx_spi_reg_name(uint32_t reg)
-{
- static char unknown[20];
-
- switch (reg) {
- case ECSPI_RXDATA:
- return "ECSPI_RXDATA";
- case ECSPI_TXDATA:
- return "ECSPI_TXDATA";
- case ECSPI_CONREG:
- return "ECSPI_CONREG";
- case ECSPI_CONFIGREG:
- return "ECSPI_CONFIGREG";
- case ECSPI_INTREG:
- return "ECSPI_INTREG";
- case ECSPI_DMAREG:
- return "ECSPI_DMAREG";
- case ECSPI_STATREG:
- return "ECSPI_STATREG";
- case ECSPI_PERIODREG:
- return "ECSPI_PERIODREG";
- case ECSPI_TESTREG:
- return "ECSPI_TESTREG";
- case ECSPI_MSGDATA:
- return "ECSPI_MSGDATA";
- default:
- sprintf(unknown, "%d ?", reg);
- return unknown;
- }
-}
-
-static const VMStateDescription vmstate_imx_spi = {
- .name = TYPE_IMX_SPI,
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_FIFO32(tx_fifo, IMXSPIState),
- VMSTATE_FIFO32(rx_fifo, IMXSPIState),
- VMSTATE_INT16(burst_length, IMXSPIState),
- VMSTATE_UINT32_ARRAY(regs, IMXSPIState, ECSPI_MAX),
- VMSTATE_END_OF_LIST()
- },
-};
-
-static void imx_spi_txfifo_reset(IMXSPIState *s)
-{
- fifo32_reset(&s->tx_fifo);
- s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
- s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
-}
-
-static void imx_spi_rxfifo_reset(IMXSPIState *s)
-{
- fifo32_reset(&s->rx_fifo);
- s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
- s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
- s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RO;
-}
-
-static void imx_spi_update_irq(IMXSPIState *s)
-{
- int level;
-
- if (fifo32_is_empty(&s->rx_fifo)) {
- s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
- } else {
- s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RR;
- }
-
- if (fifo32_is_full(&s->rx_fifo)) {
- s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RF;
- } else {
- s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
- }
-
- if (fifo32_is_empty(&s->tx_fifo)) {
- s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
- } else {
- s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TE;
- }
-
- if (fifo32_is_full(&s->tx_fifo)) {
- s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TF;
- } else {
- s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
- }
-
- level = s->regs[ECSPI_STATREG] & s->regs[ECSPI_INTREG] ? 1 : 0;
-
- qemu_set_irq(s->irq, level);
-
- DPRINTF("IRQ level is %d\n", level);
-}
-
-static uint8_t imx_spi_selected_channel(IMXSPIState *s)
-{
- return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_CHANNEL_SELECT);
-}
-
-static uint32_t imx_spi_burst_length(IMXSPIState *s)
-{
- return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_BURST_LENGTH) + 1;
-}
-
-static bool imx_spi_is_enabled(IMXSPIState *s)
-{
- return s->regs[ECSPI_CONREG] & ECSPI_CONREG_EN;
-}
-
-static bool imx_spi_channel_is_master(IMXSPIState *s)
-{
- uint8_t mode = EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_CHANNEL_MODE);
-
- return (mode & (1 << imx_spi_selected_channel(s))) ? true : false;
-}
-
-static bool imx_spi_is_multiple_master_burst(IMXSPIState *s)
-{
- uint8_t wave = EXTRACT(s->regs[ECSPI_CONFIGREG], ECSPI_CONFIGREG_SS_CTL);
-
- return imx_spi_channel_is_master(s) &&
- !(s->regs[ECSPI_CONREG] & ECSPI_CONREG_SMC) &&
- ((wave & (1 << imx_spi_selected_channel(s))) ? true : false);
-}
-
-static void imx_spi_flush_txfifo(IMXSPIState *s)
-{
- uint32_t tx;
- uint32_t rx;
-
- DPRINTF("Begin: TX Fifo Size = %d, RX Fifo Size = %d\n",
- fifo32_num_used(&s->tx_fifo), fifo32_num_used(&s->rx_fifo));
-
- while (!fifo32_is_empty(&s->tx_fifo)) {
- int tx_burst = 0;
- int index = 0;
-
- if (s->burst_length <= 0) {
- s->burst_length = imx_spi_burst_length(s);
-
- DPRINTF("Burst length = %d\n", s->burst_length);
-
- if (imx_spi_is_multiple_master_burst(s)) {
- s->regs[ECSPI_CONREG] |= ECSPI_CONREG_XCH;
- }
- }
-
- tx = fifo32_pop(&s->tx_fifo);
-
- DPRINTF("data tx:0x%08x\n", tx);
-
- tx_burst = MIN(s->burst_length, 32);
-
- rx = 0;
-
- while (tx_burst) {
- uint8_t byte = tx & 0xff;
-
- DPRINTF("writing 0x%02x\n", (uint32_t)byte);
-
- /* We need to write one byte at a time */
- byte = ssi_transfer(s->bus, byte);
-
- DPRINTF("0x%02x read\n", (uint32_t)byte);
-
- tx = tx >> 8;
- rx |= (byte << (index * 8));
-
- /* Remove 8 bits from the actual burst */
- tx_burst -= 8;
- s->burst_length -= 8;
- index++;
- }
-
- DPRINTF("data rx:0x%08x\n", rx);
-
- if (fifo32_is_full(&s->rx_fifo)) {
- s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RO;
- } else {
- fifo32_push(&s->rx_fifo, (uint8_t)rx);
- }
-
- if (s->burst_length <= 0) {
- s->regs[ECSPI_CONREG] &= ~ECSPI_CONREG_XCH;
-
- if (!imx_spi_is_multiple_master_burst(s)) {
- s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TC;
- break;
- }
- }
- }
-
- if (fifo32_is_empty(&s->tx_fifo)) {
- s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TC;
- }
-
- /* TODO: We should also use TDR and RDR bits */
-
- DPRINTF("End: TX Fifo Size = %d, RX Fifo Size = %d\n",
- fifo32_num_used(&s->tx_fifo), fifo32_num_used(&s->rx_fifo));
-}
-
-static void imx_spi_reset(DeviceState *dev)
-{
- IMXSPIState *s = IMX_SPI(dev);
-
- DPRINTF("\n");
-
- memset(s->regs, 0, sizeof(s->regs));
-
- s->regs[ECSPI_STATREG] = 0x00000003;
-
- imx_spi_rxfifo_reset(s);
- imx_spi_txfifo_reset(s);
-
- imx_spi_update_irq(s);
-
- s->burst_length = 0;
-}
-
-static uint64_t imx_spi_read(void *opaque, hwaddr offset, unsigned size)
-{
- uint32_t value = 0;
- IMXSPIState *s = opaque;
- uint32_t index = offset >> 2;
-
- if (index >= ECSPI_MAX) {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- HWADDR_PRIx "\n", TYPE_IMX_SPI, __func__, offset);
- return 0;
- }
-
- switch (index) {
- case ECSPI_RXDATA:
- if (!imx_spi_is_enabled(s)) {
- value = 0;
- } else if (fifo32_is_empty(&s->rx_fifo)) {
- /* value is undefined */
- value = 0xdeadbeef;
- } else {
- /* read from the RX FIFO */
- value = fifo32_pop(&s->rx_fifo);
- }
-
- break;
- case ECSPI_TXDATA:
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read from TX FIFO\n",
- TYPE_IMX_SPI, __func__);
-
- /* Reading from TXDATA gives 0 */
-
- break;
- case ECSPI_MSGDATA:
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read from MSG FIFO\n",
- TYPE_IMX_SPI, __func__);
-
- /* Reading from MSGDATA gives 0 */
-
- break;
- default:
- value = s->regs[index];
- break;
- }
-
- DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx_spi_reg_name(index), value);
-
- imx_spi_update_irq(s);
-
- return (uint64_t)value;
-}
-
-static void imx_spi_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- IMXSPIState *s = opaque;
- uint32_t index = offset >> 2;
- uint32_t change_mask;
-
- if (index >= ECSPI_MAX) {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- HWADDR_PRIx "\n", TYPE_IMX_SPI, __func__, offset);
- return;
- }
-
- DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_spi_reg_name(index),
- (uint32_t)value);
-
- change_mask = s->regs[index] ^ value;
-
- switch (index) {
- case ECSPI_RXDATA:
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to write to RX FIFO\n",
- TYPE_IMX_SPI, __func__);
- break;
- case ECSPI_TXDATA:
- case ECSPI_MSGDATA:
- /* Is there any difference between TXDATA and MSGDATA ? */
- /* I'll have to look in the linux driver */
- if (!imx_spi_is_enabled(s)) {
- /* Ignore writes if device is disabled */
- break;
- } else if (fifo32_is_full(&s->tx_fifo)) {
- /* Ignore writes if queue is full */
- break;
- }
-
- fifo32_push(&s->tx_fifo, (uint32_t)value);
-
- if (imx_spi_channel_is_master(s) &&
- (s->regs[ECSPI_CONREG] & ECSPI_CONREG_SMC)) {
- /*
- * Start emitting if current channel is master and SMC bit is
- * set.
- */
- imx_spi_flush_txfifo(s);
- }
-
- break;
- case ECSPI_STATREG:
- /* the RO and TC bits are write-one-to-clear */
- value &= ECSPI_STATREG_RO | ECSPI_STATREG_TC;
- s->regs[ECSPI_STATREG] &= ~value;
-
- break;
- case ECSPI_CONREG:
- s->regs[ECSPI_CONREG] = value;
-
- if (!imx_spi_is_enabled(s)) {
- /* device is disabled, so this is a reset */
- imx_spi_reset(DEVICE(s));
- return;
- }
-
- if (imx_spi_channel_is_master(s)) {
- int i;
-
- /* We are in master mode */
-
- for (i = 0; i < 4; i++) {
- qemu_set_irq(s->cs_lines[i],
- i == imx_spi_selected_channel(s) ? 0 : 1);
- }
-
- if ((value & change_mask & ECSPI_CONREG_SMC) &&
- !fifo32_is_empty(&s->tx_fifo)) {
- /* SMC bit is set and TX FIFO has some slots filled in */
- imx_spi_flush_txfifo(s);
- } else if ((value & change_mask & ECSPI_CONREG_XCH) &&
- !(value & ECSPI_CONREG_SMC)) {
- /* This is a request to start emitting */
- imx_spi_flush_txfifo(s);
- }
- }
-
- break;
- default:
- s->regs[index] = value;
-
- break;
- }
-
- imx_spi_update_irq(s);
-}
-
-static const struct MemoryRegionOps imx_spi_ops = {
- .read = imx_spi_read,
- .write = imx_spi_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- /*
- * Our device would not work correctly if the guest was doing
- * unaligned access. This might not be a limitation on the real
- * device but in practice there is no reason for a guest to access
- * this device unaligned.
- */
- .min_access_size = 4,
- .max_access_size = 4,
- .unaligned = false,
- },
-};
-
-static void imx_spi_realize(DeviceState *dev, Error **errp)
-{
- IMXSPIState *s = IMX_SPI(dev);
- int i;
-
- s->bus = ssi_create_bus(dev, "spi");
-
- memory_region_init_io(&s->iomem, OBJECT(dev), &imx_spi_ops, s,
- TYPE_IMX_SPI, 0x1000);
- sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
- sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
-
- ssi_auto_connect_slaves(dev, s->cs_lines, s->bus);
-
- for (i = 0; i < 4; ++i) {
- sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->cs_lines[i]);
- }
-
- s->burst_length = 0;
-
- fifo32_create(&s->tx_fifo, ECSPI_FIFO_SIZE);
- fifo32_create(&s->rx_fifo, ECSPI_FIFO_SIZE);
-}
-
-static void imx_spi_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = imx_spi_realize;
- dc->vmsd = &vmstate_imx_spi;
- dc->reset = imx_spi_reset;
- dc->desc = "i.MX SPI Controller";
-}
-
-static const TypeInfo imx_spi_info = {
- .name = TYPE_IMX_SPI,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(IMXSPIState),
- .class_init = imx_spi_class_init,
-};
-
-static void imx_spi_register_types(void)
-{
- type_register_static(&imx_spi_info);
-}
-
-type_init(imx_spi_register_types)
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
index c1368018e..564a0d36e 100644
--- a/hw/ssi/pl022.c
+++ b/hw/ssi/pl022.c
@@ -10,7 +10,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "hw/ssi/ssi.h"
-#include "qemu/log.h"
//#define DEBUG_PL022 1
diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c
index 7eaaf565f..9791c0d94 100644
--- a/hw/ssi/ssi.c
+++ b/hw/ssi/ssi.c
@@ -54,7 +54,7 @@ static uint32_t ssi_transfer_raw_default(SSISlave *dev, uint32_t val)
return 0;
}
-static void ssi_slave_realize(DeviceState *dev, Error **errp)
+static int ssi_slave_init(DeviceState *dev)
{
SSISlave *s = SSI_SLAVE(dev);
SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s);
@@ -64,7 +64,7 @@ static void ssi_slave_realize(DeviceState *dev, Error **errp)
qdev_init_gpio_in_named(dev, ssi_cs_default, SSI_GPIO_CS, 1);
}
- ssc->realize(s, errp);
+ return ssc->init(s);
}
static void ssi_slave_class_init(ObjectClass *klass, void *data)
@@ -72,7 +72,7 @@ static void ssi_slave_class_init(ObjectClass *klass, void *data)
SSISlaveClass *ssc = SSI_SLAVE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = ssi_slave_realize;
+ dc->init = ssi_slave_init;
dc->bus_type = TYPE_SSI_BUS;
if (!ssc->transfer_raw) {
ssc->transfer_raw = ssi_transfer_raw_default;
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index 7ba8c23c7..003c14fa2 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -26,7 +26,6 @@ obj-$(CONFIG_OMAP) += omap_synctimer.o
obj-$(CONFIG_PXA2XX) += pxa2xx_timer.o
obj-$(CONFIG_SH4) += sh_timer.o
obj-$(CONFIG_DIGIC) += digic-timer.o
-obj-$(CONFIG_MIPS_CPS) += mips_gictimer.o
obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
index 3385e5dc3..51cdc98f3 100644
--- a/hw/timer/allwinner-a10-pit.c
+++ b/hw/timer/allwinner-a10-pit.c
@@ -19,7 +19,6 @@
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
#include "hw/timer/allwinner-a10-pit.h"
-#include "qemu/log.h"
static void a10_pit_update_irq(AwA10PITState *s)
{
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 111a16db3..f1ede5f53 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -14,7 +14,6 @@
#include "hw/qdev.h"
#include "hw/ptimer.h"
#include "qemu/main-loop.h"
-#include "qemu/log.h"
/* Common timer implementation. */
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
index 9b70ee09b..ebec35935 100644
--- a/hw/timer/aspeed_timer.c
+++ b/hw/timer/aspeed_timer.c
@@ -10,12 +10,13 @@
*/
#include "qemu/osdep.h"
+#include "hw/ptimer.h"
#include "hw/sysbus.h"
#include "hw/timer/aspeed_timer.h"
#include "qemu-common.h"
#include "qemu/bitops.h"
+#include "qemu/main-loop.h"
#include "qemu/timer.h"
-#include "qemu/log.h"
#include "trace.h"
#define TIMER_NR_REGS 4
@@ -75,96 +76,21 @@ static inline bool timer_can_pulse(AspeedTimer *t)
return t->id >= TIMER_FIRST_CAP_PULSE;
}
-static inline bool timer_external_clock(AspeedTimer *t)
-{
- return timer_ctrl_status(t, op_external_clock);
-}
-
-static uint32_t clock_rates[] = { TIMER_CLOCK_APB_HZ, TIMER_CLOCK_EXT_HZ };
-
-static inline uint32_t calculate_rate(struct AspeedTimer *t)
-{
- return clock_rates[timer_external_clock(t)];
-}
-
-static inline uint32_t calculate_ticks(struct AspeedTimer *t, uint64_t now_ns)
-{
- uint64_t delta_ns = now_ns - MIN(now_ns, t->start);
- uint32_t rate = calculate_rate(t);
- uint64_t ticks = muldiv64(delta_ns, rate, NANOSECONDS_PER_SECOND);
-
- return t->reload - MIN(t->reload, ticks);
-}
-
-static inline uint64_t calculate_time(struct AspeedTimer *t, uint32_t ticks)
-{
- uint64_t delta_ns;
- uint64_t delta_ticks;
-
- delta_ticks = t->reload - MIN(t->reload, ticks);
- delta_ns = muldiv64(delta_ticks, NANOSECONDS_PER_SECOND, calculate_rate(t));
-
- return t->start + delta_ns;
-}
-
-static uint64_t calculate_next(struct AspeedTimer *t)
-{
- uint64_t next = 0;
- uint32_t rate = calculate_rate(t);
-
- while (!next) {
- /* We don't know the relationship between the values in the match
- * registers, so sort using MAX/MIN/zero. We sort in that order as the
- * timer counts down to zero. */
- uint64_t seq[] = {
- calculate_time(t, MAX(t->match[0], t->match[1])),
- calculate_time(t, MIN(t->match[0], t->match[1])),
- calculate_time(t, 0),
- };
- uint64_t reload_ns;
- uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
- if (now < seq[0]) {
- next = seq[0];
- } else if (now < seq[1]) {
- next = seq[1];
- } else if (now < seq[2]) {
- next = seq[2];
- } else {
- reload_ns = muldiv64(t->reload, NANOSECONDS_PER_SECOND, rate);
- t->start = now - ((now - t->start) % reload_ns);
- }
- }
-
- return next;
-}
-
static void aspeed_timer_expire(void *opaque)
{
AspeedTimer *t = opaque;
- bool interrupt = false;
- uint32_t ticks;
-
- if (!timer_enabled(t)) {
- return;
- }
-
- ticks = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
- if (!ticks) {
- interrupt = timer_overflow_interrupt(t) || !t->match[0] || !t->match[1];
- } else if (ticks <= MIN(t->match[0], t->match[1])) {
- interrupt = true;
- } else if (ticks <= MAX(t->match[0], t->match[1])) {
- interrupt = true;
- }
-
- if (interrupt) {
+ /* Only support interrupts on match values of zero for the moment - this is
+ * sufficient to boot an aspeed_defconfig Linux kernel.
+ *
+ * TODO: matching on arbitrary values (see e.g. hw/timer/a9gtimer.c)
+ */
+ bool match = !(t->match[0] && t->match[1]);
+ bool interrupt = timer_overflow_interrupt(t) || match;
+ if (timer_enabled(t) && interrupt) {
t->level = !t->level;
qemu_set_irq(t->irq, t->level);
}
-
- timer_mod(&t->timer, calculate_next(t));
}
static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
@@ -173,7 +99,7 @@ static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
switch (reg) {
case TIMER_REG_STATUS:
- value = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+ value = ptimer_get_count(t->timer);
break;
case TIMER_REG_RELOAD:
value = t->reload;
@@ -233,22 +159,24 @@ static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
switch (reg) {
case TIMER_REG_STATUS:
if (timer_enabled(t)) {
- uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- int64_t delta = (int64_t) value - (int64_t) calculate_ticks(t, now);
- uint32_t rate = calculate_rate(t);
-
- t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
- timer_mod(&t->timer, calculate_next(t));
+ ptimer_set_count(t->timer, value);
}
break;
case TIMER_REG_RELOAD:
t->reload = value;
+ ptimer_set_limit(t->timer, value, 1);
break;
case TIMER_REG_MATCH_FIRST:
case TIMER_REG_MATCH_SECOND:
- t->match[reg - 2] = value;
- if (timer_enabled(t)) {
- timer_mod(&t->timer, calculate_next(t));
+ if (value) {
+ /* Non-zero match values are unsupported. As such an interrupt will
+ * always be triggered when the timer reaches zero even if the
+ * overflow interrupt control bit is clear.
+ */
+ qemu_log_mask(LOG_UNIMP, "%s: Match value unsupported by device: "
+ "0x%" PRIx32 "\n", __func__, value);
+ } else {
+ t->match[reg - 2] = value;
}
break;
default:
@@ -267,16 +195,21 @@ static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool enable)
{
trace_aspeed_timer_ctrl_enable(t->id, enable);
if (enable) {
- t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- timer_mod(&t->timer, calculate_next(t));
+ ptimer_run(t->timer, 0);
} else {
- timer_del(&t->timer);
+ ptimer_stop(t->timer);
+ ptimer_set_limit(t->timer, t->reload, 1);
}
}
static void aspeed_timer_ctrl_external_clock(AspeedTimer *t, bool enable)
{
trace_aspeed_timer_ctrl_external_clock(t->id, enable);
+ if (enable) {
+ ptimer_set_freq(t->timer, TIMER_CLOCK_EXT_HZ);
+ } else {
+ ptimer_set_freq(t->timer, TIMER_CLOCK_APB_HZ);
+ }
}
static void aspeed_timer_ctrl_overflow_interrupt(AspeedTimer *t, bool enable)
@@ -417,10 +350,12 @@ static const MemoryRegionOps aspeed_timer_ops = {
static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
{
+ QEMUBH *bh;
AspeedTimer *t = &s->timers[id];
t->id = id;
- timer_init_ns(&t->timer, QEMU_CLOCK_VIRTUAL, aspeed_timer_expire, t);
+ bh = qemu_bh_new(aspeed_timer_expire, t);
+ t->timer = ptimer_init(bh);
}
static void aspeed_timer_realize(DeviceState *dev, Error **errp)
@@ -463,12 +398,12 @@ static void aspeed_timer_reset(DeviceState *dev)
static const VMStateDescription vmstate_aspeed_timer = {
.name = "aspeed.timer",
- .version_id = 2,
- .minimum_version_id = 2,
+ .version_id = 1,
+ .minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT8(id, AspeedTimer),
VMSTATE_INT32(level, AspeedTimer),
- VMSTATE_TIMER(timer, AspeedTimer),
+ VMSTATE_PTIMER(timer, AspeedTimer),
VMSTATE_UINT32(reload, AspeedTimer),
VMSTATE_UINT32_ARRAY(match, AspeedTimer, 2),
VMSTATE_END_OF_LIST()
@@ -483,7 +418,7 @@ static const VMStateDescription vmstate_aspeed_timer_state = {
VMSTATE_UINT32(ctrl, AspeedTimerCtrlState),
VMSTATE_UINT32(ctrl2, AspeedTimerCtrlState),
VMSTATE_STRUCT_ARRAY(timers, AspeedTimerCtrlState,
- ASPEED_TIMER_NR_TIMERS, 2, vmstate_aspeed_timer,
+ ASPEED_TIMER_NR_TIMERS, 1, vmstate_aspeed_timer,
AspeedTimer),
VMSTATE_END_OF_LIST()
}
diff --git a/hw/timer/digic-timer.c b/hw/timer/digic-timer.c
index 0f21faf87..5b97e1e1a 100644
--- a/hw/timer/digic-timer.c
+++ b/hw/timer/digic-timer.c
@@ -30,7 +30,6 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
#include "qemu/main-loop.h"
-#include "qemu/log.h"
#include "hw/timer/digic-timer.h"
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index eddf3481e..f5836e21f 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -16,7 +16,6 @@
#include "hw/timer/imx_epit.h"
#include "hw/misc/imx_ccm.h"
#include "qemu/main-loop.h"
-#include "qemu/log.h"
#ifndef DEBUG_IMX_EPIT
#define DEBUG_IMX_EPIT 0
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 82bc73cb8..ab2e213a1 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -14,8 +14,8 @@
#include "qemu/osdep.h"
#include "hw/timer/imx_gpt.h"
+#include "hw/misc/imx_ccm.h"
#include "qemu/main-loop.h"
-#include "qemu/log.h"
#ifndef DEBUG_IMX_GPT
#define DEBUG_IMX_GPT 0
@@ -80,18 +80,7 @@ static const VMStateDescription vmstate_imx_timer_gpt = {
}
};
-static const IMXClk imx25_gpt_clocks[] = {
- CLK_NONE, /* 000 No clock source */
- CLK_IPG, /* 001 ipg_clk, 532MHz*/
- CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
- CLK_NONE, /* 011 not defined */
- CLK_32k, /* 100 ipg_clk_32k */
- CLK_32k, /* 101 ipg_clk_32k */
- CLK_32k, /* 110 ipg_clk_32k */
- CLK_32k, /* 111 ipg_clk_32k */
-};
-
-static const IMXClk imx31_gpt_clocks[] = {
+static const IMXClk imx_gpt_clocks[] = {
CLK_NONE, /* 000 No clock source */
CLK_IPG, /* 001 ipg_clk, 532MHz*/
CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
@@ -102,23 +91,12 @@ static const IMXClk imx31_gpt_clocks[] = {
CLK_NONE, /* 111 not defined */
};
-static const IMXClk imx6_gpt_clocks[] = {
- CLK_NONE, /* 000 No clock source */
- CLK_IPG, /* 001 ipg_clk, 532MHz*/
- CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
- CLK_EXT, /* 011 External clock */
- CLK_32k, /* 100 ipg_clk_32k */
- CLK_HIGH_DIV, /* 101 reference clock / 8 */
- CLK_NONE, /* 110 not defined */
- CLK_HIGH, /* 111 reference clock */
-};
-
static void imx_gpt_set_freq(IMXGPTState *s)
{
uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
s->freq = imx_ccm_get_clock_frequency(s->ccm,
- s->clocks[clksrc]) / (1 + s->pr);
+ imx_gpt_clocks[clksrc]) / (1 + s->pr);
DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, s->freq);
@@ -474,52 +452,16 @@ static void imx_gpt_class_init(ObjectClass *klass, void *data)
dc->desc = "i.MX general timer";
}
-static void imx25_gpt_init(Object *obj)
-{
- IMXGPTState *s = IMX_GPT(obj);
-
- s->clocks = imx25_gpt_clocks;
-}
-
-static void imx31_gpt_init(Object *obj)
-{
- IMXGPTState *s = IMX_GPT(obj);
-
- s->clocks = imx31_gpt_clocks;
-}
-
-static void imx6_gpt_init(Object *obj)
-{
- IMXGPTState *s = IMX_GPT(obj);
-
- s->clocks = imx6_gpt_clocks;
-}
-
-static const TypeInfo imx25_gpt_info = {
- .name = TYPE_IMX25_GPT,
+static const TypeInfo imx_gpt_info = {
+ .name = TYPE_IMX_GPT,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMXGPTState),
- .instance_init = imx25_gpt_init,
.class_init = imx_gpt_class_init,
};
-static const TypeInfo imx31_gpt_info = {
- .name = TYPE_IMX31_GPT,
- .parent = TYPE_IMX25_GPT,
- .instance_init = imx31_gpt_init,
-};
-
-static const TypeInfo imx6_gpt_info = {
- .name = TYPE_IMX6_GPT,
- .parent = TYPE_IMX25_GPT,
- .instance_init = imx6_gpt_init,
-};
-
static void imx_gpt_register_types(void)
{
- type_register_static(&imx25_gpt_info);
- type_register_static(&imx31_gpt_info);
- type_register_static(&imx6_gpt_info);
+ type_register_static(&imx_gpt_info);
}
type_init(imx_gpt_register_types)
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
index e45a65bb9..3198355aa 100644
--- a/hw/timer/lm32_timer.c
+++ b/hw/timer/lm32_timer.c
@@ -176,26 +176,21 @@ static void timer_reset(DeviceState *d)
ptimer_stop(s->ptimer);
}
-static void lm32_timer_init(Object *obj)
+static int lm32_timer_init(SysBusDevice *dev)
{
- LM32TimerState *s = LM32_TIMER(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ LM32TimerState *s = LM32_TIMER(dev);
sysbus_init_irq(dev, &s->irq);
s->bh = qemu_bh_new(timer_hit, s);
s->ptimer = ptimer_init(s->bh);
+ ptimer_set_freq(s->ptimer, s->freq_hz);
- memory_region_init_io(&s->iomem, obj, &timer_ops, s,
+ memory_region_init_io(&s->iomem, OBJECT(s), &timer_ops, s,
"timer", R_MAX * 4);
sysbus_init_mmio(dev, &s->iomem);
-}
-static void lm32_timer_realize(DeviceState *dev, Error **errp)
-{
- LM32TimerState *s = LM32_TIMER(dev);
-
- ptimer_set_freq(s->ptimer, s->freq_hz);
+ return 0;
}
static const VMStateDescription vmstate_lm32_timer = {
@@ -218,8 +213,9 @@ static Property lm32_timer_properties[] = {
static void lm32_timer_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- dc->realize = lm32_timer_realize;
+ k->init = lm32_timer_init;
dc->reset = timer_reset;
dc->vmsd = &vmstate_lm32_timer;
dc->props = lm32_timer_properties;
@@ -229,7 +225,6 @@ static const TypeInfo lm32_timer_info = {
.name = TYPE_LM32_TIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LM32TimerState),
- .instance_init = lm32_timer_init,
.class_init = lm32_timer_class_init,
};
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index ea625f25c..2ac0fd3e4 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
+#include "config-target.h"
#include "qemu/cutils.h"
#include "qemu/bcd.h"
#include "hw/hw.h"
@@ -105,10 +106,12 @@ static inline bool rtc_running(RTCState *s)
static uint64_t get_guest_rtc_ns(RTCState *s)
{
+ uint64_t guest_rtc;
uint64_t guest_clock = qemu_clock_get_ns(rtc_clock);
- return s->base_rtc * NANOSECONDS_PER_SECOND +
+ guest_rtc = s->base_rtc * NANOSECONDS_PER_SECOND +
guest_clock - s->last_update + s->offset;
+ return guest_rtc;
}
#ifdef TARGET_I386
@@ -906,8 +909,6 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
object_property_add_alias(qdev_get_machine(), "rtc-time",
OBJECT(s), "date", NULL);
-
- qdev_init_gpio_out(dev, &s->irq, 1);
}
ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
@@ -922,9 +923,9 @@ ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
qdev_prop_set_int32(dev, "base_year", base_year);
qdev_init_nofail(dev);
if (intercept_irq) {
- qdev_connect_gpio_out(dev, 0, intercept_irq);
+ s->irq = intercept_irq;
} else {
- isa_connect_gpio_out(isadev, 0, RTC_ISA_IRQ);
+ isa_init_irq(isadev, &s->irq, RTC_ISA_IRQ);
}
QLIST_INSERT_HEAD(&rtc_devices, s, link);
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index 21948328c..5f2948037 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -18,7 +18,7 @@
*
*
* Specification available at:
- * http://milkymist.walle.cc/socdoc/sysctl.pdf
+ * http://www.milkymist.org/socdoc/sysctl.pdf
*/
#include "qemu/osdep.h"
@@ -270,10 +270,9 @@ static void milkymist_sysctl_reset(DeviceState *d)
s->regs[R_GPIO_IN] = s->strappings;
}
-static void milkymist_sysctl_init(Object *obj)
+static int milkymist_sysctl_init(SysBusDevice *dev)
{
- MilkymistSysctlState *s = MILKYMIST_SYSCTL(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+ MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev);
sysbus_init_irq(dev, &s->gpio_irq);
sysbus_init_irq(dev, &s->timer0_irq);
@@ -283,18 +282,14 @@ static void milkymist_sysctl_init(Object *obj)
s->bh1 = qemu_bh_new(timer1_hit, s);
s->ptimer0 = ptimer_init(s->bh0);
s->ptimer1 = ptimer_init(s->bh1);
+ ptimer_set_freq(s->ptimer0, s->freq_hz);
+ ptimer_set_freq(s->ptimer1, s->freq_hz);
- memory_region_init_io(&s->regs_region, obj, &sysctl_mmio_ops, s,
+ memory_region_init_io(&s->regs_region, OBJECT(s), &sysctl_mmio_ops, s,
"milkymist-sysctl", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
-}
-static void milkymist_sysctl_realize(DeviceState *dev, Error **errp)
-{
- MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev);
-
- ptimer_set_freq(s->ptimer0, s->freq_hz);
- ptimer_set_freq(s->ptimer1, s->freq_hz);
+ return 0;
}
static const VMStateDescription vmstate_milkymist_sysctl = {
@@ -324,8 +319,9 @@ static Property milkymist_sysctl_properties[] = {
static void milkymist_sysctl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- dc->realize = milkymist_sysctl_realize;
+ k->init = milkymist_sysctl_init;
dc->reset = milkymist_sysctl_reset;
dc->vmsd = &vmstate_milkymist_sysctl;
dc->props = milkymist_sysctl_properties;
@@ -335,7 +331,6 @@ static const TypeInfo milkymist_sysctl_info = {
.name = TYPE_MILKYMIST_SYSCTL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistSysctlState),
- .instance_init = milkymist_sysctl_init,
.class_init = milkymist_sysctl_class_init,
};
diff --git a/hw/timer/mips_gictimer.c b/hw/timer/mips_gictimer.c
deleted file mode 100644
index 369888947..000000000
--- a/hw/timer/mips_gictimer.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "qemu/timer.h"
-#include "hw/timer/mips_gictimer.h"
-
-#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */
-
-static void gic_vptimer_update(MIPSGICTimerState *gictimer,
- uint32_t vp_index, uint64_t now)
-{
- uint64_t next;
- uint32_t wait;
-
- wait = gictimer->vptimers[vp_index].comparelo - gictimer->sh_counterlo -
- (uint32_t)(now / TIMER_PERIOD);
- next = now + (uint64_t)wait * TIMER_PERIOD;
-
- timer_mod(gictimer->vptimers[vp_index].qtimer, next);
-}
-
-static void gic_vptimer_expire(MIPSGICTimerState *gictimer, uint32_t vp_index,
- uint64_t now)
-{
- if (gictimer->countstop) {
- /* timer stopped */
- return;
- }
- gictimer->cb(gictimer->opaque, vp_index);
- gic_vptimer_update(gictimer, vp_index, now);
-}
-
-static void gic_vptimer_cb(void *opaque)
-{
- MIPSGICTimerVPState *vptimer = opaque;
- MIPSGICTimerState *gictimer = vptimer->gictimer;
- gic_vptimer_expire(gictimer, vptimer->vp_index,
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
-}
-
-uint32_t mips_gictimer_get_sh_count(MIPSGICTimerState *gictimer)
-{
- int i;
- if (gictimer->countstop) {
- return gictimer->sh_counterlo;
- } else {
- uint64_t now;
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- for (i = 0; i < gictimer->num_vps; i++) {
- if (timer_pending(gictimer->vptimers[i].qtimer)
- && timer_expired(gictimer->vptimers[i].qtimer, now)) {
- /* The timer has already expired. */
- gic_vptimer_expire(gictimer, i, now);
- }
- }
- return gictimer->sh_counterlo + (uint32_t)(now / TIMER_PERIOD);
- }
-}
-
-void mips_gictimer_store_sh_count(MIPSGICTimerState *gictimer, uint64_t count)
-{
- int i;
- uint64_t now;
-
- if (gictimer->countstop || !gictimer->vptimers[0].qtimer) {
- gictimer->sh_counterlo = count;
- } else {
- /* Store new count register */
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- gictimer->sh_counterlo = count - (uint32_t)(now / TIMER_PERIOD);
- /* Update timer timer */
- for (i = 0; i < gictimer->num_vps; i++) {
- gic_vptimer_update(gictimer, i, now);
- }
- }
-}
-
-uint32_t mips_gictimer_get_vp_compare(MIPSGICTimerState *gictimer,
- uint32_t vp_index)
-{
- return gictimer->vptimers[vp_index].comparelo;
-}
-
-void mips_gictimer_store_vp_compare(MIPSGICTimerState *gictimer,
- uint32_t vp_index, uint64_t compare)
-{
- gictimer->vptimers[vp_index].comparelo = (uint32_t) compare;
- gic_vptimer_update(gictimer, vp_index,
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
-}
-
-uint8_t mips_gictimer_get_countstop(MIPSGICTimerState *gictimer)
-{
- return gictimer->countstop;
-}
-
-void mips_gictimer_start_count(MIPSGICTimerState *gictimer)
-{
- gictimer->countstop = 0;
- mips_gictimer_store_sh_count(gictimer, gictimer->sh_counterlo);
-}
-
-void mips_gictimer_stop_count(MIPSGICTimerState *gictimer)
-{
- int i;
-
- gictimer->countstop = 1;
- /* Store the current value */
- gictimer->sh_counterlo +=
- (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD);
- for (i = 0; i < gictimer->num_vps; i++) {
- timer_del(gictimer->vptimers[i].qtimer);
- }
-}
-
-MIPSGICTimerState *mips_gictimer_init(void *opaque, uint32_t nvps,
- MIPSGICTimerCB *cb)
-{
- int i;
- MIPSGICTimerState *gictimer = g_new(MIPSGICTimerState, 1);
- gictimer->vptimers = g_new(MIPSGICTimerVPState, nvps);
- gictimer->countstop = 1;
- gictimer->num_vps = nvps;
- gictimer->opaque = opaque;
- gictimer->cb = cb;
- for (i = 0; i < nvps; i++) {
- gictimer->vptimers[i].gictimer = gictimer;
- gictimer->vptimers[i].vp_index = i;
- gictimer->vptimers[i].qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- &gic_vptimer_cb,
- &gictimer->vptimers[i]);
- }
- return gictimer;
-}
diff --git a/hw/timer/omap_gptimer.c b/hw/timer/omap_gptimer.c
index 5e3e8a6d7..3a4386304 100644
--- a/hw/timer/omap_gptimer.c
+++ b/hw/timer/omap_gptimer.c
@@ -133,8 +133,8 @@ static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer)
timer_mod(timer->timer, timer->time + expires);
if (timer->ce && timer->match_val >= timer->val) {
- matches = muldiv64(timer->ticks_per_sec,
- timer->match_val - timer->val, timer->rate);
+ matches = muldiv64(timer->match_val - timer->val,
+ timer->ticks_per_sec, timer->rate);
timer_mod(timer->match, timer->time + matches);
} else
timer_del(timer->match);
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
index dbbeb9b16..38e0cb5ad 100644
--- a/hw/timer/pl031.c
+++ b/hw/timer/pl031.c
@@ -16,7 +16,6 @@
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
#include "qemu/cutils.h"
-#include "qemu/log.h"
//#define DEBUG_PL031
diff --git a/hw/timer/stm32f2xx_timer.c b/hw/timer/stm32f2xx_timer.c
index bf0fb288c..55dacbbe3 100644
--- a/hw/timer/stm32f2xx_timer.c
+++ b/hw/timer/stm32f2xx_timer.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
#include "hw/timer/stm32f2xx_timer.h"
-#include "qemu/log.h"
#ifndef STM_TIMER_ERR_DEBUG
#define STM_TIMER_ERR_DEBUG 0
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
deleted file mode 100644
index 3495c41c1..000000000
--- a/hw/timer/trace-events
+++ /dev/null
@@ -1,51 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/timer/slavio_timer.c
-slavio_timer_get_out(uint64_t limit, uint32_t counthigh, uint32_t count) "limit %"PRIx64" count %x%08x"
-slavio_timer_irq(uint32_t counthigh, uint32_t count) "callback: count %x%08x"
-slavio_timer_mem_readl_invalid(uint64_t addr) "invalid read address %"PRIx64
-slavio_timer_mem_readl(uint64_t addr, uint32_t ret) "read %"PRIx64" = %08x"
-slavio_timer_mem_writel(uint64_t addr, uint32_t val) "write %"PRIx64" = %08x"
-slavio_timer_mem_writel_limit(unsigned int timer_index, uint64_t count) "processor %d user timer set to %016"PRIx64
-slavio_timer_mem_writel_counter_invalid(void) "not user timer"
-slavio_timer_mem_writel_status_start(unsigned int timer_index) "processor %d user timer started"
-slavio_timer_mem_writel_status_stop(unsigned int timer_index) "processor %d user timer stopped"
-slavio_timer_mem_writel_mode_user(unsigned int timer_index) "processor %d changed from counter to user timer"
-slavio_timer_mem_writel_mode_counter(unsigned int timer_index) "processor %d changed from user timer to counter"
-slavio_timer_mem_writel_mode_invalid(void) "not system timer"
-slavio_timer_mem_writel_invalid(uint64_t addr) "invalid write address %"PRIx64
-
-# hw/timer/grlib_gptimer.c
-grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run"
-grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x"
-grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x"
-grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x"
-grlib_gptimer_hit(int id) "timer:%d HIT"
-grlib_gptimer_readl(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x"
-grlib_gptimer_writel(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x"
-
-# hw/timer/lm32_timer.c
-lm32_timer_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
-lm32_timer_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
-lm32_timer_hit(void) "timer hit"
-lm32_timer_irq_state(int level) "irq state %d"
-
-# hw/timer/milkymist-sysctl.c
-milkymist_sysctl_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_sysctl_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_sysctl_icap_write(uint32_t value) "value %08x"
-milkymist_sysctl_start_timer0(void) "Start timer0"
-milkymist_sysctl_stop_timer0(void) "Stop timer0"
-milkymist_sysctl_start_timer1(void) "Start timer1"
-milkymist_sysctl_stop_timer1(void) "Stop timer1"
-milkymist_sysctl_pulse_irq_timer0(void) "Pulse IRQ Timer0"
-milkymist_sysctl_pulse_irq_timer1(void) "Pulse IRQ Timer1"
-
-# hw/timer/aspeed_timer.c
-aspeed_timer_ctrl_enable(uint8_t i, bool enable) "Timer %" PRIu8 ": %d"
-aspeed_timer_ctrl_external_clock(uint8_t i, bool enable) "Timer %" PRIu8 ": %d"
-aspeed_timer_ctrl_overflow_interrupt(uint8_t i, bool enable) "Timer %" PRIu8 ": %d"
-aspeed_timer_ctrl_pulse_enable(uint8_t i, bool enable) "Timer %" PRIu8 ": %d"
-aspeed_timer_set_ctrl2(uint32_t value) "Value: 0x%" PRIx32
-aspeed_timer_set_value(int timer, int reg, uint32_t value) "Timer %d register %d: 0x%" PRIx32
-aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) "From 0x%" PRIx64 ": of size %u: 0x%" PRIx64
diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h
index df76245e6..e7f354a52 100644
--- a/hw/tpm/tpm_util.h
+++ b/hw/tpm/tpm_util.h
@@ -18,12 +18,11 @@
* 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 TPM_TPM_UTIL_H
-#define TPM_TPM_UTIL_H
+#ifndef TPM_TPM_UTILS_H
+#define TPM_TPM_UTILS_H
#include "sysemu/tpm_backend.h"
int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version);
-#endif /* TPM_TPM_UTIL_H */
+#endif /* TPM_TPM_UTILS_H */
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
index 98b5c9d27..2717027d3 100644
--- a/hw/usb/Makefile.objs
+++ b/hw/usb/Makefile.objs
@@ -38,7 +38,3 @@ common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o
# usb pass-through
common-obj-y += $(patsubst %,host-%.o,$(HOST_USB))
-
-ifeq ($(CONFIG_USB_LIBUSB),y)
-common-obj-$(CONFIG_XEN_BACKEND) += xen-usb.o
-endif
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 25913ad48..16c3461d9 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -55,9 +55,9 @@ static int usb_device_post_load(void *opaque, int version_id)
USBDevice *dev = opaque;
if (dev->state == USB_STATE_NOTATTACHED) {
- dev->attached = false;
+ dev->attached = 0;
} else {
- dev->attached = true;
+ dev->attached = 1;
}
if (dev->setup_index < 0 ||
dev->setup_len < 0 ||
@@ -279,13 +279,6 @@ static void usb_qdev_realize(DeviceState *qdev, Error **errp)
static void usb_qdev_unrealize(DeviceState *qdev, Error **errp)
{
USBDevice *dev = USB_DEVICE(qdev);
- USBDescString *s, *next;
-
- QLIST_FOREACH_SAFE(s, &dev->strings, next, next) {
- QLIST_REMOVE(s, next);
- g_free(s->str);
- g_free(s);
- }
if (dev->attached) {
usb_device_detach(dev);
@@ -540,7 +533,7 @@ void usb_device_attach(USBDevice *dev, Error **errp)
return;
}
- dev->attached = true;
+ dev->attached++;
usb_attach(port);
}
@@ -554,7 +547,7 @@ int usb_device_detach(USBDevice *dev)
trace_usb_port_detach(bus->busnr, port->path);
usb_detach(port);
- dev->attached = false;
+ dev->attached--;
return 0;
}
@@ -743,48 +736,6 @@ USBDevice *usbdevice_create(const char *cmdline)
return dev;
}
-static bool usb_get_attached(Object *obj, Error **errp)
-{
- USBDevice *dev = USB_DEVICE(obj);
-
- return dev->attached;
-}
-
-static void usb_set_attached(Object *obj, bool value, Error **errp)
-{
- USBDevice *dev = USB_DEVICE(obj);
- Error *err = NULL;
-
- if (dev->attached == value) {
- return;
- }
-
- if (value) {
- usb_device_attach(dev, &err);
- if (err) {
- error_propagate(errp, err);
- }
- } else {
- usb_device_detach(dev);
- }
-}
-
-static void usb_device_instance_init(Object *obj)
-{
- USBDevice *dev = USB_DEVICE(obj);
- USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-
- if (klass->attached_settable) {
- object_property_add_bool(obj, "attached",
- usb_get_attached, usb_set_attached,
- NULL);
- } else {
- object_property_add_bool(obj, "attached",
- usb_get_attached, NULL,
- NULL);
- }
-}
-
static void usb_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
@@ -798,7 +749,6 @@ static const TypeInfo usb_device_type_info = {
.name = TYPE_USB_DEVICE,
.parent = TYPE_DEVICE,
.instance_size = sizeof(USBDevice),
- .instance_init = usb_device_instance_init,
.abstract = true,
.class_size = sizeof(USBDeviceClass),
.class_init = usb_device_class_init,
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 5e0e1d157..adb026e43 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -574,7 +574,6 @@ void usb_desc_create_serial(USBDevice *dev)
}
dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path);
usb_desc_set_string(dev, index, serial);
- g_free(path);
}
const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 1be85ae75..bda84a64b 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -788,8 +788,8 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c)
trace_usb_mtp_op_get_device_info(s->dev.addr);
usb_mtp_add_u16(d, 100);
- usb_mtp_add_u32(d, 0x00000006);
- usb_mtp_add_u16(d, 0x0064);
+ usb_mtp_add_u32(d, 0xffffffff);
+ usb_mtp_add_u16(d, 0x0101);
usb_mtp_add_wstr(d, L"");
usb_mtp_add_u16(d, 0x0000);
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index c0f1193ba..74306b58e 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -670,49 +670,48 @@ static int ndis_query(USBNetState *s, uint32_t oid,
/* general oids (table 4-1) */
/* mandatory */
case OID_GEN_SUPPORTED_LIST:
- for (i = 0; i < ARRAY_SIZE(oid_supported_list); i++) {
- stl_le_p(outbuf + (i * sizeof(le32)), oid_supported_list[i]);
- }
+ for (i = 0; i < ARRAY_SIZE(oid_supported_list); i++)
+ ((le32 *) outbuf)[i] = cpu_to_le32(oid_supported_list[i]);
return sizeof(oid_supported_list);
/* mandatory */
case OID_GEN_HARDWARE_STATUS:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
/* mandatory */
case OID_GEN_MEDIA_SUPPORTED:
- stl_le_p(outbuf, s->medium);
+ *((le32 *) outbuf) = cpu_to_le32(s->medium);
return sizeof(le32);
/* mandatory */
case OID_GEN_MEDIA_IN_USE:
- stl_le_p(outbuf, s->medium);
+ *((le32 *) outbuf) = cpu_to_le32(s->medium);
return sizeof(le32);
/* mandatory */
case OID_GEN_MAXIMUM_FRAME_SIZE:
- stl_le_p(outbuf, ETH_FRAME_LEN);
+ *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
return sizeof(le32);
/* mandatory */
case OID_GEN_LINK_SPEED:
- stl_le_p(outbuf, s->speed);
+ *((le32 *) outbuf) = cpu_to_le32(s->speed);
return sizeof(le32);
/* mandatory */
case OID_GEN_TRANSMIT_BLOCK_SIZE:
- stl_le_p(outbuf, ETH_FRAME_LEN);
+ *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
return sizeof(le32);
/* mandatory */
case OID_GEN_RECEIVE_BLOCK_SIZE:
- stl_le_p(outbuf, ETH_FRAME_LEN);
+ *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
return sizeof(le32);
/* mandatory */
case OID_GEN_VENDOR_ID:
- stl_le_p(outbuf, s->vendorid);
+ *((le32 *) outbuf) = cpu_to_le32(s->vendorid);
return sizeof(le32);
/* mandatory */
@@ -721,57 +720,58 @@ static int ndis_query(USBNetState *s, uint32_t oid,
return strlen((char *)outbuf) + 1;
case OID_GEN_VENDOR_DRIVER_VERSION:
- stl_le_p(outbuf, 1);
+ *((le32 *) outbuf) = cpu_to_le32(1);
return sizeof(le32);
/* mandatory */
case OID_GEN_CURRENT_PACKET_FILTER:
- stl_le_p(outbuf, s->filter);
+ *((le32 *) outbuf) = cpu_to_le32(s->filter);
return sizeof(le32);
/* mandatory */
case OID_GEN_MAXIMUM_TOTAL_SIZE:
- stl_le_p(outbuf, RNDIS_MAX_TOTAL_SIZE);
+ *((le32 *) outbuf) = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
return sizeof(le32);
/* mandatory */
case OID_GEN_MEDIA_CONNECT_STATUS:
- stl_le_p(outbuf, s->media_state);
+ *((le32 *) outbuf) = cpu_to_le32(s->media_state);
return sizeof(le32);
case OID_GEN_PHYSICAL_MEDIUM:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
case OID_GEN_MAC_OPTIONS:
- stl_le_p(outbuf, NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
- NDIS_MAC_OPTION_FULL_DUPLEX);
+ *((le32 *) outbuf) = cpu_to_le32(
+ NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+ NDIS_MAC_OPTION_FULL_DUPLEX);
return sizeof(le32);
/* statistics OIDs (table 4-2) */
/* mandatory */
case OID_GEN_XMIT_OK:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
/* mandatory */
case OID_GEN_RCV_OK:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
/* mandatory */
case OID_GEN_XMIT_ERROR:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
/* mandatory */
case OID_GEN_RCV_ERROR:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
/* mandatory */
case OID_GEN_RCV_NO_BUFFER:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
/* ieee802.3 OIDs (table 4-3) */
@@ -787,12 +787,12 @@ static int ndis_query(USBNetState *s, uint32_t oid,
/* mandatory */
case OID_802_3_MULTICAST_LIST:
- stl_le_p(outbuf, 0xe0000000);
+ *((le32 *) outbuf) = cpu_to_le32(0xe0000000);
return sizeof(le32);
/* mandatory */
case OID_802_3_MAXIMUM_LIST_SIZE:
- stl_le_p(outbuf, 1);
+ *((le32 *) outbuf) = cpu_to_le32(1);
return sizeof(le32);
case OID_802_3_MAC_OPTIONS:
@@ -801,17 +801,17 @@ static int ndis_query(USBNetState *s, uint32_t oid,
/* ieee802.3 statistics OIDs (table 4-4) */
/* mandatory */
case OID_802_3_RCV_ERROR_ALIGNMENT:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
/* mandatory */
case OID_802_3_XMIT_ONE_COLLISION:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
/* mandatory */
case OID_802_3_XMIT_MORE_COLLISIONS:
- stl_le_p(outbuf, 0);
+ *((le32 *) outbuf) = cpu_to_le32(0);
return sizeof(le32);
default:
@@ -826,7 +826,7 @@ static int ndis_set(USBNetState *s, uint32_t oid,
{
switch (oid) {
case OID_GEN_CURRENT_PACKET_FILTER:
- s->filter = ldl_le_p(inbuf);
+ s->filter = le32_to_cpup((le32 *) inbuf);
if (s->filter) {
s->rndis_state = RNDIS_DATA_INITIALIZED;
} else {
@@ -1026,7 +1026,10 @@ static void usb_net_reset_in_buf(USBNetState *s)
static int rndis_parse(USBNetState *s, uint8_t *data, int length)
{
- uint32_t msg_type = ldl_le_p(data);
+ uint32_t msg_type;
+ le32 *tmp = (le32 *) data;
+
+ msg_type = le32_to_cpup(tmp);
switch (msg_type) {
case RNDIS_INITIALIZE_MSG:
@@ -1334,7 +1337,7 @@ static void usb_net_handle_destroy(USBDevice *dev)
}
static NetClientInfo net_usbnet_info = {
- .type = NET_CLIENT_DRIVER_NIC,
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.receive = usbnet_receive,
.cleanup = usbnet_cleanup,
@@ -1396,7 +1399,7 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
qemu_opt_set(opts, "type", "nic", &error_abort);
qemu_opt_set(opts, "model", "usb", &error_abort);
- idx = net_client_init(opts, false, &local_err);
+ idx = net_client_init(opts, 0, &local_err);
if (local_err) {
error_report_err(local_err);
return NULL;
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index c607f7606..248a58045 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -556,6 +556,21 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
}
}
+static void usb_msd_password_cb(void *opaque, int err)
+{
+ MSDState *s = opaque;
+ Error *local_err = NULL;
+
+ if (!err) {
+ usb_device_attach(&s->dev, &local_err);
+ }
+
+ if (local_err) {
+ error_report_err(local_err);
+ qdev_unplug(&s->dev.qdev, NULL);
+ }
+}
+
static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
{
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
@@ -601,21 +616,37 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
return;
}
+ if (blk_bs(blk)) {
+ bdrv_add_key(blk_bs(blk), NULL, &err);
+ if (err) {
+ if (monitor_cur_is_qmp()) {
+ error_propagate(errp, err);
+ return;
+ }
+ error_free(err);
+ err = NULL;
+ if (cur_mon) {
+ monitor_read_bdrv_key_start(cur_mon, blk_bs(blk),
+ usb_msd_password_cb, s);
+ s->dev.auto_attach = 0;
+ } else {
+ autostart = 0;
+ }
+ }
+ }
+
blkconf_serial(&s->conf, &dev->serial);
blkconf_blocksizes(&s->conf);
- blkconf_apply_backend_options(&s->conf);
/*
* Hack alert: this pretends to be a block device, but it's really
* a SCSI bus that can serve only a single device, which it
* creates automatically. But first it needs to detach from its
* blockdev, or else scsi_bus_legacy_add_drive() dies when it
- * attaches again. We also need to take another reference so that
- * blk_detach_dev() doesn't free blk while we still need it.
+ * attaches again.
*
* The hack is probably a bad idea.
*/
- blk_ref(blk);
blk_detach_dev(blk, &s->dev.qdev);
s->conf.blk = NULL;
@@ -626,7 +657,6 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
s->conf.bootindex, dev->serial,
&err);
- blk_unref(blk);
if (!scsi_dev) {
error_propagate(errp, err);
return;
@@ -638,14 +668,9 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
static void usb_msd_realize_bot(USBDevice *dev, Error **errp)
{
MSDState *s = USB_STORAGE_DEV(dev);
- DeviceState *d = DEVICE(dev);
usb_desc_create_serial(dev);
usb_desc_init(dev);
- if (d->hotplugged) {
- s->dev.auto_attach = 0;
- }
-
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
&usb_msd_scsi_info_bot, NULL);
usb_msd_handle_reset(dev);
@@ -793,7 +818,9 @@ static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name,
}
out:
- error_propagate(errp, local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ }
}
static const TypeInfo usb_storage_dev_type_info = {
@@ -815,9 +842,10 @@ static void usb_msd_instance_init(Object *obj)
static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data)
{
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
uc->realize = usb_msd_realize_bot;
- uc->attached_settable = true;
+ dc->hotpluggable = false;
}
static const TypeInfo msd_info = {
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 3a8ff18b1..0678b1b05 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -900,13 +900,9 @@ static void usb_uas_handle_destroy(USBDevice *dev)
static void usb_uas_realize(USBDevice *dev, Error **errp)
{
UASDevice *uas = USB_UAS(dev);
- DeviceState *d = DEVICE(dev);
usb_desc_create_serial(dev);
usb_desc_init(dev);
- if (d->hotplugged) {
- uas->dev.auto_attach = 0;
- }
QTAILQ_INIT(&uas->results);
QTAILQ_INIT(&uas->requests);
@@ -944,7 +940,6 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data)
uc->handle_control = usb_uas_handle_control;
uc->handle_data = usb_uas_handle_data;
uc->handle_destroy = usb_uas_handle_destroy;
- uc->attached_settable = true;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->fw_name = "storage";
dc->vmsd = &vmstate_usb_uas;
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index b093db729..43a8f7abc 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2206,28 +2206,29 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
static void ehci_update_frindex(EHCIState *ehci, int uframes)
{
+ int i;
+
if (!ehci_enabled(ehci) && ehci->pstate == EST_INACTIVE) {
return;
}
- /* Generate FLR interrupt if frame index rolls over 0x2000 */
- if ((ehci->frindex % 0x2000) + uframes >= 0x2000) {
- ehci_raise_irq(ehci, USBSTS_FLR);
- }
+ for (i = 0; i < uframes; i++) {
+ ehci->frindex++;
- /* How many times will frindex roll over 0x4000 with this frame count?
- * usbsts_frindex is decremented by 0x4000 on rollover until it reaches 0
- */
- int rollovers = (ehci->frindex + uframes) / 0x4000;
- if (rollovers > 0) {
- if (ehci->usbsts_frindex >= (rollovers * 0x4000)) {
- ehci->usbsts_frindex -= 0x4000 * rollovers;
- } else {
- ehci->usbsts_frindex = 0;
+ if (ehci->frindex == 0x00002000) {
+ ehci_raise_irq(ehci, USBSTS_FLR);
}
- }
- ehci->frindex = (ehci->frindex + uframes) % 0x4000;
+ if (ehci->frindex == 0x00004000) {
+ ehci_raise_irq(ehci, USBSTS_FLR);
+ ehci->frindex = 0;
+ if (ehci->usbsts_frindex >= 0x00004000) {
+ ehci->usbsts_frindex -= 0x00004000;
+ } else {
+ ehci->usbsts_frindex = 0;
+ }
+ }
+ }
}
static void ehci_frame_timer(void *opaque)
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index 3fd703865..30218423c 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -14,9 +14,8 @@
* 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_USB_HCD_EHCI_H
-#define HW_USB_HCD_EHCI_H
+#ifndef HW_USB_EHCI_H
+#define HW_USB_EHCI_H 1
#include "hw/hw.h"
#include "qemu/timer.h"
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index fa5703832..16d9ff7b4 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1474,7 +1474,7 @@ static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
if (tks >= usb_frame_time)
return (ohci->frt << 31);
- tks = tks / usb_bit_time;
+ tks = muldiv64(1, tks, usb_bit_time);
fr = (uint16_t)(ohci->fi - tks);
return (ohci->frt << 31) | fr;
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 188f95416..43ba61599 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -26,7 +26,6 @@
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
#include "trace.h"
-#include "qapi/error.h"
//#define DEBUG_XHCI
//#define DEBUG_DATA
@@ -462,8 +461,6 @@ struct XHCIState {
uint32_t numslots;
uint32_t flags;
uint32_t max_pstreams_mask;
- OnOffAuto msi;
- OnOffAuto msix;
/* Operational Registers */
uint32_t usbcmd;
@@ -501,7 +498,9 @@ typedef struct XHCIEvRingSeg {
} XHCIEvRingSeg;
enum xhci_flags {
- XHCI_FLAG_SS_FIRST = 1,
+ XHCI_FLAG_USE_MSI = 1,
+ XHCI_FLAG_USE_MSI_X,
+ XHCI_FLAG_SS_FIRST,
XHCI_FLAG_FORCE_PCIE_ENDCAP,
XHCI_FLAG_ENABLE_STREAMS,
};
@@ -2201,9 +2200,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
xfer->trb_count = length;
for (i = 0; i < length; i++) {
- TRBType type;
- type = xhci_ring_fetch(xhci, ring, &xfer->trbs[i], NULL);
- assert(type);
+ assert(xhci_ring_fetch(xhci, ring, &xfer->trbs[i], NULL));
}
xfer->streamid = streamid;
@@ -2366,8 +2363,6 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
slot->uport = uport;
slot->ctx = octx;
- /* Make sure device is in USB_STATE_DEFAULT state */
- usb_device_reset(dev);
if (bsr) {
slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT;
} else {
@@ -2375,6 +2370,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
uint8_t buf[1];
slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slotid;
+ usb_device_reset(dev);
memset(&p, 0, sizeof(p));
usb_packet_addbuf(&p, buf, sizeof(buf));
usb_packet_setup(&p, USB_TOKEN_OUT,
@@ -3585,7 +3581,6 @@ static void usb_xhci_init(XHCIState *xhci)
static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
{
int i, ret;
- Error *err = NULL;
XHCIState *xhci = XHCI(dev);
@@ -3596,23 +3591,6 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
usb_xhci_init(xhci);
- if (xhci->msi != ON_OFF_AUTO_OFF) {
- ret = msi_init(dev, 0x70, xhci->numintrs, true, false, &err);
- /* Any error other than -ENOTSUP(board's MSI support is broken)
- * is a programming error */
- assert(!ret || ret == -ENOTSUP);
- if (ret && xhci->msi == ON_OFF_AUTO_ON) {
- /* Can't satisfy user's explicit msi=on request, fail */
- error_append_hint(&err, "You have to use msi=auto (default) or "
- "msi=off with this machine type.\n");
- error_propagate(errp, err);
- return;
- }
- assert(!err || xhci->msi == ON_OFF_AUTO_AUTO);
- /* With msi=auto, we fall back to MSI off silently */
- error_free(err);
- }
-
if (xhci->numintrs > MAXINTRS) {
xhci->numintrs = MAXINTRS;
}
@@ -3670,8 +3648,10 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
assert(ret >= 0);
}
- if (xhci->msix != ON_OFF_AUTO_OFF) {
- /* TODO check for errors */
+ if (xhci_get_flag(xhci, XHCI_FLAG_USE_MSI)) {
+ msi_init(dev, 0x70, xhci->numintrs, true, false);
+ }
+ if (xhci_get_flag(xhci, XHCI_FLAG_USE_MSI_X)) {
msix_init(dev, xhci->numintrs,
&xhci->mem, 0, OFF_MSIX_TABLE,
&xhci->mem, 0, OFF_MSIX_PBA,
@@ -3892,8 +3872,8 @@ static const VMStateDescription vmstate_xhci = {
};
static Property xhci_properties[] = {
- DEFINE_PROP_ON_OFF_AUTO("msi", XHCIState, msi, ON_OFF_AUTO_AUTO),
- DEFINE_PROP_ON_OFF_AUTO("msix", XHCIState, msix, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_BIT("msi", XHCIState, flags, XHCI_FLAG_USE_MSI, true),
+ DEFINE_PROP_BIT("msix", XHCIState, flags, XHCI_FLAG_USE_MSI_X, true),
DEFINE_PROP_BIT("superspeed-ports-first",
XHCIState, flags, XHCI_FLAG_SS_FIRST, true),
DEFINE_PROP_BIT("force-pcie-endcap", XHCIState, flags,
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index e94672c15..6458a9448 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -34,9 +34,7 @@
*/
#include "qemu/osdep.h"
-#ifndef CONFIG_WIN32
#include <poll.h>
-#endif
#include <libusb.h>
#include "qapi/error.h"
@@ -81,7 +79,6 @@ struct USBHostDevice {
uint32_t iso_urb_frames;
uint32_t options;
uint32_t loglevel;
- bool needs_autoscan;
/* state */
QTAILQ_ENTRY(USBHostDevice) next;
@@ -207,8 +204,6 @@ static const char *err_names[] = {
static libusb_context *ctx;
static uint32_t loglevel;
-#ifndef CONFIG_WIN32
-
static void usb_host_handle_fd(void *opaque)
{
struct timeval tv = { 0, 0 };
@@ -228,14 +223,10 @@ static void usb_host_del_fd(int fd, void *user_data)
qemu_set_fd_handler(fd, NULL, NULL, NULL);
}
-#endif /* !CONFIG_WIN32 */
-
static int usb_host_init(void)
{
-#ifndef CONFIG_WIN32
const struct libusb_pollfd **poll;
-#endif
- int rc;
+ int i, rc;
if (ctx) {
return 0;
@@ -245,21 +236,17 @@ static int usb_host_init(void)
return -1;
}
libusb_set_debug(ctx, loglevel);
-#ifdef CONFIG_WIN32
- /* FIXME: add support for Windows. */
-#else
+
libusb_set_pollfd_notifiers(ctx, usb_host_add_fd,
usb_host_del_fd,
ctx);
poll = libusb_get_pollfds(ctx);
if (poll) {
- int i;
for (i = 0; poll[i] != NULL; i++) {
usb_host_add_fd(poll[i]->fd, poll[i]->events, ctx);
}
}
free(poll);
-#endif
return 0;
}
@@ -359,7 +346,7 @@ static USBHostRequest *usb_host_req_find(USBHostDevice *s, USBPacket *p)
return NULL;
}
-static void LIBUSB_CALL usb_host_req_complete_ctrl(struct libusb_transfer *xfer)
+static void usb_host_req_complete_ctrl(struct libusb_transfer *xfer)
{
USBHostRequest *r = xfer->user_data;
USBHostDevice *s = r->host;
@@ -392,7 +379,7 @@ out:
}
}
-static void LIBUSB_CALL usb_host_req_complete_data(struct libusb_transfer *xfer)
+static void usb_host_req_complete_data(struct libusb_transfer *xfer)
{
USBHostRequest *r = xfer->user_data;
USBHostDevice *s = r->host;
@@ -448,8 +435,7 @@ static void usb_host_req_abort(USBHostRequest *r)
/* ------------------------------------------------------------------------ */
-static void LIBUSB_CALL
-usb_host_req_complete_iso(struct libusb_transfer *transfer)
+static void usb_host_req_complete_iso(struct libusb_transfer *transfer)
{
USBHostIsoXfer *xfer = transfer->user_data;
@@ -977,32 +963,9 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data)
}
}
-static libusb_device *usb_host_find_ref(int bus, int addr)
-{
- libusb_device **devs = NULL;
- libusb_device *ret = NULL;
- int i, n;
-
- if (usb_host_init() != 0) {
- return NULL;
- }
- n = libusb_get_device_list(ctx, &devs);
- for (i = 0; i < n; i++) {
- if (libusb_get_bus_number(devs[i]) == bus &&
- libusb_get_device_address(devs[i]) == addr) {
- ret = libusb_ref_device(devs[i]);
- break;
- }
- }
- libusb_free_device_list(devs, 1);
- return ret;
-}
-
static void usb_host_realize(USBDevice *udev, Error **errp)
{
USBHostDevice *s = USB_HOST_DEVICE(udev);
- libusb_device *ldev;
- int rc;
if (s->match.vendor_id > 0xffff) {
error_setg(errp, "vendorid out of range");
@@ -1023,33 +986,11 @@ static void usb_host_realize(USBDevice *udev, Error **errp)
QTAILQ_INIT(&s->requests);
QTAILQ_INIT(&s->isorings);
- if (s->match.addr && s->match.bus_num &&
- !s->match.vendor_id &&
- !s->match.product_id &&
- !s->match.port) {
- s->needs_autoscan = false;
- ldev = usb_host_find_ref(s->match.bus_num,
- s->match.addr);
- if (!ldev) {
- error_setg(errp, "failed to find host usb device %d:%d",
- s->match.bus_num, s->match.addr);
- return;
- }
- rc = usb_host_open(s, ldev);
- libusb_unref_device(ldev);
- if (rc < 0) {
- error_setg(errp, "failed to open host usb device %d:%d",
- s->match.bus_num, s->match.addr);
- return;
- }
- } else {
- s->needs_autoscan = true;
- QTAILQ_INSERT_TAIL(&hostdevs, s, next);
- usb_host_auto_check(NULL);
- }
-
s->exit.notify = usb_host_exit_notifier;
qemu_add_exit_notifier(&s->exit);
+
+ QTAILQ_INSERT_TAIL(&hostdevs, s, next);
+ usb_host_auto_check(NULL);
}
static void usb_host_instance_init(Object *obj)
@@ -1067,9 +1008,7 @@ static void usb_host_handle_destroy(USBDevice *udev)
USBHostDevice *s = USB_HOST_DEVICE(udev);
qemu_remove_exit_notifier(&s->exit);
- if (s->needs_autoscan) {
- QTAILQ_REMOVE(&hostdevs, s, next);
- }
+ QTAILQ_REMOVE(&hostdevs, s, next);
usb_host_close(s);
}
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 444672a00..8d8054037 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -109,7 +109,6 @@ struct USBRedirDevice {
uint8_t debug;
char *filter_str;
int32_t bootindex;
- bool enable_streams;
/* Data passed from chardev the fd_read cb to the usbredirparser read cb */
const uint8_t *read_buf;
int read_buf_size;
@@ -543,9 +542,9 @@ static void usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
start_iso.pkts_per_urb = 32;
}
- start_iso.no_urbs = DIV_ROUND_UP(
- dev->endpoint[EP2I(ep)].bufpq_target_size,
- start_iso.pkts_per_urb);
+ start_iso.no_urbs = (dev->endpoint[EP2I(ep)].bufpq_target_size +
+ start_iso.pkts_per_urb - 1) /
+ start_iso.pkts_per_urb;
/* Output endpoints pre-fill only 1/2 of the packets, keeping the rest
as overflow buffer. Also see the usbredir protocol documentation */
if (!(ep & USB_DIR_IN)) {
@@ -1230,9 +1229,7 @@ static void usbredir_create_parser(USBRedirDevice *dev)
usbredirparser_caps_set_cap(caps, usb_redir_cap_32bits_bulk_length);
usbredirparser_caps_set_cap(caps, usb_redir_cap_bulk_receiving);
#if USBREDIR_VERSION >= 0x000700
- if (dev->enable_streams) {
- usbredirparser_caps_set_cap(caps, usb_redir_cap_bulk_streams);
- }
+ usbredirparser_caps_set_cap(caps, usb_redir_cap_bulk_streams);
#endif
if (runstate_check(RUN_STATE_INMIGRATE)) {
@@ -2479,7 +2476,6 @@ static Property usbredir_properties[] = {
DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, usbredirparser_warning),
DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
- DEFINE_PROP_BOOL("streams", USBRedirDevice, enable_streams, true),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/usb/trace-events b/hw/usb/trace-events
deleted file mode 100644
index 2d42fd45d..000000000
--- a/hw/usb/trace-events
+++ /dev/null
@@ -1,268 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/usb/core.c
-usb_packet_state_change(int bus, const char *port, int ep, void *p, const char *o, const char *n) "bus %d, port %s, ep %d, packet %p, state %s -> %s"
-usb_packet_state_fault(int bus, const char *port, int ep, void *p, const char *o, const char *n) "bus %d, port %s, ep %d, packet %p, state %s, expected %s"
-
-# hw/usb/bus.c
-usb_port_claim(int bus, const char *port) "bus %d, port %s"
-usb_port_attach(int bus, const char *port, const char *devspeed, const char *portspeed) "bus %d, port %s, devspeed %s, portspeed %s"
-usb_port_detach(int bus, const char *port) "bus %d, port %s"
-usb_port_release(int bus, const char *port) "bus %d, port %s"
-
-# hw/usb/hcd-ohci.c
-usb_ohci_iso_td_read_failed(uint32_t addr) "ISO_TD read error at %x"
-usb_ohci_iso_td_head(uint32_t head, uint32_t tail, uint32_t flags, uint32_t bp, uint32_t next, uint32_t be, uint32_t framenum, uint32_t startframe, uint32_t framecount, int rel_frame_num) "ISO_TD ED head 0x%.8x tailp 0x%.8x\n0x%.8x 0x%.8x 0x%.8x 0x%.8x\nframe_number 0x%.8x starting_frame 0x%.8x\nframe_count 0x%.8x relative %d"
-usb_ohci_iso_td_head_offset(uint32_t o0, uint32_t o1, uint32_t o2, uint32_t o3, uint32_t o4, uint32_t o5, uint32_t o6, uint32_t o7) "0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x"
-usb_ohci_iso_td_relative_frame_number_neg(int rel) "ISO_TD R=%d < 0"
-usb_ohci_iso_td_relative_frame_number_big(int rel, int count) "ISO_TD R=%d > FC=%d"
-usb_ohci_iso_td_bad_direction(int dir) "Bad direction %d"
-usb_ohci_iso_td_bad_bp_be(uint32_t bp, uint32_t be) "ISO_TD bp 0x%.8x be 0x%.8x"
-usb_ohci_iso_td_bad_cc_not_accessed(uint32_t start, uint32_t next) "ISO_TD cc != not accessed 0x%.8x 0x%.8x"
-usb_ohci_iso_td_bad_cc_overrun(uint32_t start, uint32_t next) "ISO_TD start_offset=0x%.8x > next_offset=0x%.8x"
-usb_ohci_iso_td_so(uint32_t so, uint32_t eo, uint32_t s, uint32_t e, const char *str, ssize_t len, int ret) "0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d"
-usb_ohci_iso_td_data_overrun(int ret, ssize_t len) "DataOverrun %d > %zu"
-usb_ohci_iso_td_data_underrun(int ret) "DataUnderrun %d"
-usb_ohci_iso_td_nak(int ret) "got NAK/STALL %d"
-usb_ohci_iso_td_bad_response(int ret) "Bad device response %d"
-usb_ohci_port_attach(int index) "port #%d"
-usb_ohci_port_detach(int index) "port #%d"
-usb_ohci_port_wakeup(int index) "port #%d"
-usb_ohci_port_suspend(int index) "port #%d"
-usb_ohci_port_reset(int index) "port #%d"
-usb_ohci_remote_wakeup(const char *s) "%s: SUSPEND->RESUME"
-usb_ohci_reset(const char *s) "%s"
-usb_ohci_start(const char *s) "%s: USB Operational"
-usb_ohci_resume(const char *s) "%s: USB Resume"
-usb_ohci_stop(const char *s) "%s: USB Suspended"
-usb_ohci_exit(const char *s) "%s"
-usb_ohci_set_ctl(const char *s, uint32_t new_state) "%s: new state 0x%x"
-usb_ohci_td_underrun(void) ""
-usb_ohci_td_dev_error(void) ""
-usb_ohci_td_nak(void) ""
-usb_ohci_td_stall(void) ""
-usb_ohci_td_babble(void) ""
-usb_ohci_td_bad_device_response(int rc) "%d"
-usb_ohci_td_read_error(uint32_t addr) "TD read error at %x"
-usb_ohci_td_bad_direction(int dir) "Bad direction %d"
-usb_ohci_td_skip_async(void) ""
-usb_ohci_td_pkt_hdr(uint32_t addr, int64_t pktlen, int64_t len, const char *s, int flag_r, uint32_t cbp, uint32_t be) " TD @ 0x%.8x %" PRId64 " of %" PRId64 " bytes %s r=%d cbp=0x%.8x be=0x%.8x"
-usb_ohci_td_pkt_short(const char *dir, const char *buf) "%s data: %s"
-usb_ohci_td_pkt_full(const char *dir, const char *buf) "%s data: %s"
-usb_ohci_td_too_many_pending(void) ""
-usb_ohci_td_packet_status(int status) "status=%d"
-usb_ohci_ed_read_error(uint32_t addr) "ED read error at %x"
-usb_ohci_ed_pkt(uint32_t cur, int h, int c, uint32_t head, uint32_t tail, uint32_t next) "ED @ 0x%.8x h=%u c=%u\n head=0x%.8x tailp=0x%.8x next=0x%.8x"
-usb_ohci_ed_pkt_flags(uint32_t fa, uint32_t en, uint32_t d, int s, int k, int f, uint32_t mps) "fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u"
-usb_ohci_hcca_read_error(uint32_t addr) "HCCA read error at %x"
-usb_ohci_mem_read_unaligned(uint32_t addr) "at %x"
-usb_ohci_mem_read_bad_offset(uint32_t addr) "%x"
-usb_ohci_mem_write_unaligned(uint32_t addr) "at %x"
-usb_ohci_mem_write_bad_offset(uint32_t addr) "%x"
-usb_ohci_process_lists(uint32_t head, uint32_t cur) "head %x, cur %x"
-usb_ohci_bus_eof_timer_failed(const char *name) "%s: timer_new_ns failed"
-usb_ohci_set_frame_interval(const char *name, uint16_t fi_x, uint16_t fi_u) "%s: FrameInterval = 0x%x (%u)"
-usb_ohci_hub_power_up(void) "powered up all ports"
-usb_ohci_hub_power_down(void) "powered down all ports"
-usb_ohci_init_time(int64_t frametime, int64_t bittime) "usb_bit_time=%" PRId64 " usb_frame_time=%" PRId64
-usb_ohci_die(void) ""
-usb_ohci_async_complete(void) ""
-
-# hw/usb/hcd-ehci.c
-usb_ehci_reset(void) "=== RESET ==="
-usb_ehci_unrealize(void) "=== UNREALIZE ==="
-usb_ehci_opreg_read(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x"
-usb_ehci_opreg_write(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x"
-usb_ehci_opreg_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)"
-usb_ehci_portsc_read(uint32_t addr, uint32_t port, uint32_t val) "rd mmio %04x [port %d] = %x"
-usb_ehci_portsc_write(uint32_t addr, uint32_t port, uint32_t val) "wr mmio %04x [port %d] = %x"
-usb_ehci_portsc_change(uint32_t addr, uint32_t port, uint32_t new, uint32_t old) "ch mmio %04x [port %d] = %x (old: %x)"
-usb_ehci_usbsts(const char *sts, int state) "usbsts %s %d"
-usb_ehci_state(const char *schedule, const char *state) "%s schedule %s"
-usb_ehci_qh_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) "q %p - QH @ %08x: next %08x qtds %08x,%08x,%08x"
-usb_ehci_qh_fields(uint32_t addr, int rl, int mplen, int eps, int ep, int devaddr) "QH @ %08x - rl %d, mplen %d, eps %d, ep %d, dev %d"
-usb_ehci_qh_bits(uint32_t addr, int c, int h, int dtc, int i) "QH @ %08x - c %d, h %d, dtc %d, i %d"
-usb_ehci_qtd_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t altnext) "q %p - QTD @ %08x: next %08x altnext %08x"
-usb_ehci_qtd_fields(uint32_t addr, int tbytes, int cpage, int cerr, int pid) "QTD @ %08x - tbytes %d, cpage %d, cerr %d, pid %d"
-usb_ehci_qtd_bits(uint32_t addr, int ioc, int active, int halt, int babble, int xacterr) "QTD @ %08x - ioc %d, active %d, halt %d, babble %d, xacterr %d"
-usb_ehci_itd(uint32_t addr, uint32_t nxt, uint32_t mplen, uint32_t mult, uint32_t ep, uint32_t devaddr) "ITD @ %08x: next %08x - mplen %d, mult %d, ep %d, dev %d"
-usb_ehci_sitd(uint32_t addr, uint32_t nxt, uint32_t active) "ITD @ %08x: next %08x - active %d"
-usb_ehci_port_attach(uint32_t port, const char *owner, const char *device) "attach port #%d, owner %s, device %s"
-usb_ehci_port_detach(uint32_t port, const char *owner) "detach port #%d, owner %s"
-usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d"
-usb_ehci_port_suspend(uint32_t port) "port #%d"
-usb_ehci_port_wakeup(uint32_t port) "port #%d"
-usb_ehci_port_resume(uint32_t port) "port #%d"
-usb_ehci_queue_action(void *q, const char *action) "q %p: %s"
-usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s"
-usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "level %d, frindex 0x%04x, sts 0x%x, mask 0x%x"
-usb_ehci_guest_bug(const char *reason) "%s"
-usb_ehci_doorbell_ring(void) ""
-usb_ehci_doorbell_ack(void) ""
-usb_ehci_dma_error(void) ""
-
-# hw/usb/hcd-uhci.c
-usb_uhci_reset(void) "=== RESET ==="
-usb_uhci_exit(void) "=== EXIT ==="
-usb_uhci_schedule_start(void) ""
-usb_uhci_schedule_stop(void) ""
-usb_uhci_frame_start(uint32_t num) "nr %d"
-usb_uhci_frame_stop_bandwidth(void) ""
-usb_uhci_frame_loop_stop_idle(void) ""
-usb_uhci_frame_loop_continue(void) ""
-usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%04x"
-usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%04x"
-usb_uhci_queue_add(uint32_t token) "token 0x%x"
-usb_uhci_queue_del(uint32_t token, const char *reason) "token 0x%x: %s"
-usb_uhci_packet_add(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-usb_uhci_packet_link_async(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-usb_uhci_packet_unlink_async(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-usb_uhci_packet_cancel(uint32_t token, uint32_t addr, int done) "token 0x%x, td 0x%x, done %d"
-usb_uhci_packet_complete_success(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-usb_uhci_packet_complete_shortxfer(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-usb_uhci_packet_complete_stall(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-usb_uhci_packet_complete_babble(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-usb_uhci_packet_complete_error(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-usb_uhci_packet_del(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-usb_uhci_qh_load(uint32_t qh) "qh 0x%x"
-usb_uhci_td_load(uint32_t qh, uint32_t td, uint32_t ctrl, uint32_t token) "qh 0x%x, td 0x%x, ctrl 0x%x, token 0x%x"
-usb_uhci_td_queue(uint32_t td, uint32_t ctrl, uint32_t token) "td 0x%x, ctrl 0x%x, token 0x%x"
-usb_uhci_td_nextqh(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
-usb_uhci_td_async(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
-usb_uhci_td_complete(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
-
-# hw/usb/hcd-xhci.c
-usb_xhci_reset(void) "=== RESET ==="
-usb_xhci_exit(void) "=== EXIT ==="
-usb_xhci_run(void) ""
-usb_xhci_stop(void) ""
-usb_xhci_cap_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
-usb_xhci_oper_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
-usb_xhci_port_read(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, ret 0x%08x"
-usb_xhci_runtime_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
-usb_xhci_doorbell_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
-usb_xhci_oper_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
-usb_xhci_port_write(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, val 0x%08x"
-usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
-usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
-usb_xhci_irq_intx(uint32_t level) "level %d"
-usb_xhci_irq_msi(uint32_t nr) "nr %d"
-usb_xhci_irq_msix(uint32_t nr) "nr %d"
-usb_xhci_irq_msix_use(uint32_t nr) "nr %d"
-usb_xhci_irq_msix_unuse(uint32_t nr) "nr %d"
-usb_xhci_queue_event(uint32_t vector, uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "v %d, idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
-usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
-usb_xhci_port_reset(uint32_t port, bool warm) "port %d, warm %d"
-usb_xhci_port_link(uint32_t port, uint32_t pls) "port %d, pls %d"
-usb_xhci_port_notify(uint32_t port, uint32_t pls) "port %d, bits %x"
-usb_xhci_slot_enable(uint32_t slotid) "slotid %d"
-usb_xhci_slot_disable(uint32_t slotid) "slotid %d"
-usb_xhci_slot_address(uint32_t slotid, const char *port) "slotid %d, port %s"
-usb_xhci_slot_configure(uint32_t slotid) "slotid %d"
-usb_xhci_slot_evaluate(uint32_t slotid) "slotid %d"
-usb_xhci_slot_reset(uint32_t slotid) "slotid %d"
-usb_xhci_ep_enable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
-usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
-usb_xhci_ep_set_dequeue(uint32_t slotid, uint32_t epid, uint32_t streamid, uint64_t param) "slotid %d, epid %d, streamid %d, ptr %016" PRIx64
-usb_xhci_ep_kick(uint32_t slotid, uint32_t epid, uint32_t streamid) "slotid %d, epid %d, streamid %d"
-usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
-usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
-usb_xhci_ep_state(uint32_t slotid, uint32_t epid, const char *os, const char *ns) "slotid %d, epid %d, %s -> %s"
-usb_xhci_xfer_start(void *xfer, uint32_t slotid, uint32_t epid, uint32_t streamid) "%p: slotid %d, epid %d, streamid %d"
-usb_xhci_xfer_async(void *xfer) "%p"
-usb_xhci_xfer_nak(void *xfer) "%p"
-usb_xhci_xfer_retry(void *xfer) "%p"
-usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d"
-usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d"
-usb_xhci_unimplemented(const char *item, int nr) "%s (0x%x)"
-
-# hw/usb/desc.c
-usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
-usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
-usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
-usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
-usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
-usb_desc_bos(int addr, int len, int ret) "dev %d bos, len %d, ret %d"
-usb_desc_msos(int addr, int index, int len, int ret) "dev %d msos, index 0x%x, len %d, ret %d"
-usb_set_addr(int addr) "dev %d"
-usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
-usb_set_interface(int addr, int iface, int alt, int ret) "dev %d, interface %d, altsetting %d, ret %d"
-usb_clear_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
-usb_set_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
-
-# hw/usb/dev-hub.c
-usb_hub_reset(int addr) "dev %d"
-usb_hub_control(int addr, int request, int value, int index, int length) "dev %d, req 0x%x, value %d, index %d, langth %d"
-usb_hub_get_port_status(int addr, int nr, int status, int changed) "dev %d, port %d, status 0x%x, changed 0x%x"
-usb_hub_set_port_feature(int addr, int nr, const char *f) "dev %d, port %d, feature %s"
-usb_hub_clear_port_feature(int addr, int nr, const char *f) "dev %d, port %d, feature %s"
-usb_hub_attach(int addr, int nr) "dev %d, port %d"
-usb_hub_detach(int addr, int nr) "dev %d, port %d"
-usb_hub_status_report(int addr, int status) "dev %d, status 0x%x"
-
-# hw/usb/dev-uas.c
-usb_uas_reset(int addr) "dev %d"
-usb_uas_command(int addr, uint16_t tag, int lun, uint32_t lun64_1, uint32_t lun64_2) "dev %d, tag 0x%x, lun %d, lun64 %08x-%08x"
-usb_uas_response(int addr, uint16_t tag, uint8_t code) "dev %d, tag 0x%x, code 0x%x"
-usb_uas_sense(int addr, uint16_t tag, uint8_t status) "dev %d, tag 0x%x, status 0x%x"
-usb_uas_read_ready(int addr, uint16_t tag) "dev %d, tag 0x%x"
-usb_uas_write_ready(int addr, uint16_t tag) "dev %d, tag 0x%x"
-usb_uas_xfer_data(int addr, uint16_t tag, uint32_t copy, uint32_t uoff, uint32_t usize, uint32_t soff, uint32_t ssize) "dev %d, tag 0x%x, copy %d, usb-pkt %d/%d, scsi-buf %d/%d"
-usb_uas_scsi_data(int addr, uint16_t tag, uint32_t bytes) "dev %d, tag 0x%x, bytes %d"
-usb_uas_scsi_complete(int addr, uint16_t tag, uint32_t status, uint32_t resid) "dev %d, tag 0x%x, status 0x%x, residue %d"
-usb_uas_tmf_abort_task(int addr, uint16_t tag, uint16_t task_tag) "dev %d, tag 0x%x, task-tag 0x%x"
-usb_uas_tmf_logical_unit_reset(int addr, uint16_t tag, int lun) "dev %d, tag 0x%x, lun %d"
-usb_uas_tmf_unsupported(int addr, uint16_t tag, uint32_t function) "dev %d, tag 0x%x, function 0x%x"
-
-# hw/usb/dev-mtp.c
-usb_mtp_reset(int addr) "dev %d"
-usb_mtp_command(int dev, uint16_t code, uint32_t trans, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4) "dev %d, code 0x%x, trans 0x%x, args 0x%x, 0x%x, 0x%x, 0x%x, 0x%x"
-usb_mtp_success(int dev, uint32_t trans, uint32_t arg0, uint32_t arg1) "dev %d, trans 0x%x, args 0x%x, 0x%x"
-usb_mtp_error(int dev, uint16_t code, uint32_t trans, uint32_t arg0, uint32_t arg1) "dev %d, code 0x%x, trans 0x%x, args 0x%x, 0x%x"
-usb_mtp_data_in(int dev, uint32_t trans, uint32_t len) "dev %d, trans 0x%x, len %d"
-usb_mtp_xfer(int dev, uint32_t ep, uint32_t dlen, uint32_t plen) "dev %d, ep %d, %d/%d"
-usb_mtp_nak(int dev, uint32_t ep) "dev %d, ep %d"
-usb_mtp_stall(int dev, const char *reason) "dev %d, reason: %s"
-usb_mtp_op_get_device_info(int dev) "dev %d"
-usb_mtp_op_open_session(int dev) "dev %d"
-usb_mtp_op_close_session(int dev) "dev %d"
-usb_mtp_op_get_storage_ids(int dev) "dev %d"
-usb_mtp_op_get_storage_info(int dev) "dev %d"
-usb_mtp_op_get_num_objects(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
-usb_mtp_op_get_object_handles(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
-usb_mtp_op_get_object_info(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
-usb_mtp_op_get_object(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
-usb_mtp_op_get_partial_object(int dev, uint32_t handle, const char *path, uint32_t offset, uint32_t length) "dev %d, handle 0x%x, path %s, off %d, len %d"
-usb_mtp_op_unknown(int dev, uint32_t code) "dev %d, command code 0x%x"
-usb_mtp_object_alloc(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
-usb_mtp_object_free(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
-usb_mtp_add_child(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
-usb_mtp_inotify_event(int dev, const char *path, uint32_t mask, const char *s) "dev %d, path %s mask 0x%x event %s"
-
-# hw/usb/host-libusb.c
-usb_host_open_started(int bus, int addr) "dev %d:%d"
-usb_host_open_success(int bus, int addr) "dev %d:%d"
-usb_host_open_failure(int bus, int addr) "dev %d:%d"
-usb_host_close(int bus, int addr) "dev %d:%d"
-usb_host_attach_kernel(int bus, int addr, int interface) "dev %d:%d, if %d"
-usb_host_detach_kernel(int bus, int addr, int interface) "dev %d:%d, if %d"
-usb_host_set_address(int bus, int addr, int config) "dev %d:%d, address %d"
-usb_host_set_config(int bus, int addr, int config) "dev %d:%d, config %d"
-usb_host_set_interface(int bus, int addr, int interface, int alt) "dev %d:%d, interface %d, alt %d"
-usb_host_claim_interface(int bus, int addr, int config, int interface) "dev %d:%d, config %d, if %d"
-usb_host_release_interface(int bus, int addr, int interface) "dev %d:%d, if %d"
-usb_host_req_control(int bus, int addr, void *p, int req, int value, int index) "dev %d:%d, packet %p, req 0x%x, value %d, index %d"
-usb_host_req_data(int bus, int addr, void *p, int in, int ep, int size) "dev %d:%d, packet %p, in %d, ep %d, size %d"
-usb_host_req_complete(int bus, int addr, void *p, int status, int length) "dev %d:%d, packet %p, status %d, length %d"
-usb_host_req_emulated(int bus, int addr, void *p, int status) "dev %d:%d, packet %p, status %d"
-usb_host_req_canceled(int bus, int addr, void *p) "dev %d:%d, packet %p"
-usb_host_iso_start(int bus, int addr, int ep) "dev %d:%d, ep %d"
-usb_host_iso_stop(int bus, int addr, int ep) "dev %d:%d, ep %d"
-usb_host_iso_out_of_bufs(int bus, int addr, int ep) "dev %d:%d, ep %d"
-usb_host_reset(int bus, int addr) "dev %d:%d"
-usb_host_auto_scan_enabled(void)
-usb_host_auto_scan_disabled(void)
-usb_host_parse_config(int bus, int addr, int value, int active) "dev %d:%d, value %d, active %d"
-usb_host_parse_interface(int bus, int addr, int num, int alt, int active) "dev %d:%d, num %d, alt %d, active %d"
-usb_host_parse_endpoint(int bus, int addr, int ep, const char *dir, const char *type, int active) "dev %d:%d, ep %d, %s, %s, active %d"
-usb_host_parse_error(int bus, int addr, const char *errmsg) "dev %d:%d, msg %s"
diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
deleted file mode 100644
index 174d715e3..000000000
--- a/hw/usb/xen-usb.c
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*
- * xen paravirt usb device backend
- *
- * (c) Juergen Gross <jgross@suse.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; under version 2 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/>.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include <libusb.h>
-#include <sys/user.h>
-
-#include "qemu-common.h"
-#include "qemu/config-file.h"
-#include "hw/sysbus.h"
-#include "hw/usb.h"
-#include "hw/xen/xen_backend.h"
-#include "monitor/qdev.h"
-#include "qapi/qmp/qbool.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qstring.h"
-
-#include <xen/io/ring.h>
-#include <xen/io/usbif.h>
-
-/*
- * Check for required support of usbif.h: USBIF_SHORT_NOT_OK was the last
- * macro added we rely on.
- */
-#ifdef USBIF_SHORT_NOT_OK
-
-#define TR(xendev, lvl, fmt, args...) \
- { \
- struct timeval tv; \
- \
- gettimeofday(&tv, NULL); \
- xen_be_printf(xendev, lvl, "%8ld.%06ld xen-usb(%s):" fmt, \
- tv.tv_sec, tv.tv_usec, __func__, ##args); \
- }
-#define TR_BUS(xendev, fmt, args...) TR(xendev, 2, fmt, ##args)
-#define TR_REQ(xendev, fmt, args...) TR(xendev, 3, fmt, ##args)
-
-#define USBBACK_MAXPORTS USBIF_PIPE_PORT_MASK
-#define USB_DEV_ADDR_SIZE (USBIF_PIPE_DEV_MASK + 1)
-
-/* USB wire protocol: structure describing control request parameter. */
-struct usbif_ctrlrequest {
- uint8_t bRequestType;
- uint8_t bRequest;
- uint16_t wValue;
- uint16_t wIndex;
- uint16_t wLength;
-};
-
-struct usbback_info;
-struct usbback_req;
-
-struct usbback_stub {
- USBDevice *dev;
- USBPort port;
- unsigned int speed;
- bool attached;
- QTAILQ_HEAD(submit_q_head, usbback_req) submit_q;
-};
-
-struct usbback_req {
- struct usbback_info *usbif;
- struct usbback_stub *stub;
- struct usbif_urb_request req;
- USBPacket packet;
-
- unsigned int nr_buffer_segs; /* # of transfer_buffer segments */
- unsigned int nr_extra_segs; /* # of iso_frame_desc segments */
-
- QTAILQ_ENTRY(usbback_req) q;
-
- void *buffer;
- void *isoc_buffer;
- struct libusb_transfer *xfer;
-
- bool cancelled;
-};
-
-struct usbback_hotplug {
- QSIMPLEQ_ENTRY(usbback_hotplug) q;
- unsigned port;
-};
-
-struct usbback_info {
- struct XenDevice xendev; /* must be first */
- USBBus bus;
- void *urb_sring;
- void *conn_sring;
- struct usbif_urb_back_ring urb_ring;
- struct usbif_conn_back_ring conn_ring;
- int num_ports;
- int usb_ver;
- bool ring_error;
- QTAILQ_HEAD(req_free_q_head, usbback_req) req_free_q;
- QSIMPLEQ_HEAD(hotplug_q_head, usbback_hotplug) hotplug_q;
- struct usbback_stub ports[USBBACK_MAXPORTS];
- struct usbback_stub *addr_table[USB_DEV_ADDR_SIZE];
- QEMUBH *bh;
-};
-
-static struct usbback_req *usbback_get_req(struct usbback_info *usbif)
-{
- struct usbback_req *usbback_req;
-
- if (QTAILQ_EMPTY(&usbif->req_free_q)) {
- usbback_req = g_new0(struct usbback_req, 1);
- } else {
- usbback_req = QTAILQ_FIRST(&usbif->req_free_q);
- QTAILQ_REMOVE(&usbif->req_free_q, usbback_req, q);
- }
- return usbback_req;
-}
-
-static void usbback_put_req(struct usbback_req *usbback_req)
-{
- struct usbback_info *usbif;
-
- usbif = usbback_req->usbif;
- memset(usbback_req, 0, sizeof(*usbback_req));
- QTAILQ_INSERT_HEAD(&usbif->req_free_q, usbback_req, q);
-}
-
-static int usbback_gnttab_map(struct usbback_req *usbback_req)
-{
- unsigned int nr_segs, i, prot;
- uint32_t ref[USBIF_MAX_SEGMENTS_PER_REQUEST];
- struct usbback_info *usbif = usbback_req->usbif;
- struct XenDevice *xendev = &usbif->xendev;
- struct usbif_request_segment *seg;
- void *addr;
-
- nr_segs = usbback_req->nr_buffer_segs + usbback_req->nr_extra_segs;
- if (!nr_segs) {
- return 0;
- }
-
- if (nr_segs > USBIF_MAX_SEGMENTS_PER_REQUEST) {
- xen_be_printf(xendev, 0, "bad number of segments in request (%d)\n",
- nr_segs);
- return -EINVAL;
- }
-
- for (i = 0; i < nr_segs; i++) {
- if ((unsigned)usbback_req->req.seg[i].offset +
- (unsigned)usbback_req->req.seg[i].length > PAGE_SIZE) {
- xen_be_printf(xendev, 0, "segment crosses page boundary\n");
- return -EINVAL;
- }
- }
-
- if (usbback_req->nr_buffer_segs) {
- prot = PROT_READ;
- if (usbif_pipein(usbback_req->req.pipe)) {
- prot |= PROT_WRITE;
- }
- for (i = 0; i < usbback_req->nr_buffer_segs; i++) {
- ref[i] = usbback_req->req.seg[i].gref;
- }
- usbback_req->buffer = xengnttab_map_domain_grant_refs(xendev->gnttabdev,
- usbback_req->nr_buffer_segs, xendev->dom, ref, prot);
-
- if (!usbback_req->buffer) {
- return -ENOMEM;
- }
-
- for (i = 0; i < usbback_req->nr_buffer_segs; i++) {
- seg = usbback_req->req.seg + i;
- addr = usbback_req->buffer + i * PAGE_SIZE + seg->offset;
- qemu_iovec_add(&usbback_req->packet.iov, addr, seg->length);
- }
- }
-
- if (!usbif_pipeisoc(usbback_req->req.pipe)) {
- return 0;
- }
-
- /*
- * Right now isoc requests are not supported.
- * Prepare supporting those by doing the work needed on the guest
- * interface side.
- */
-
- if (!usbback_req->nr_extra_segs) {
- xen_be_printf(xendev, 0, "iso request without descriptor segments\n");
- return -EINVAL;
- }
-
- prot = PROT_READ | PROT_WRITE;
- for (i = 0; i < usbback_req->nr_extra_segs; i++) {
- ref[i] = usbback_req->req.seg[i + usbback_req->req.nr_buffer_segs].gref;
- }
- usbback_req->isoc_buffer = xengnttab_map_domain_grant_refs(
- xendev->gnttabdev, usbback_req->nr_extra_segs, xendev->dom, ref, prot);
-
- if (!usbback_req->isoc_buffer) {
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int usbback_init_packet(struct usbback_req *usbback_req)
-{
- struct XenDevice *xendev = &usbback_req->usbif->xendev;
- USBPacket *packet = &usbback_req->packet;
- USBDevice *dev = usbback_req->stub->dev;
- USBEndpoint *ep;
- unsigned int pid, ep_nr;
- bool sok;
- int ret = 0;
-
- qemu_iovec_init(&packet->iov, USBIF_MAX_SEGMENTS_PER_REQUEST);
- pid = usbif_pipein(usbback_req->req.pipe) ? USB_TOKEN_IN : USB_TOKEN_OUT;
- ep_nr = usbif_pipeendpoint(usbback_req->req.pipe);
- sok = !!(usbback_req->req.transfer_flags & USBIF_SHORT_NOT_OK);
- if (usbif_pipectrl(usbback_req->req.pipe)) {
- ep_nr = 0;
- sok = false;
- }
- ep = usb_ep_get(dev, pid, ep_nr);
- usb_packet_setup(packet, pid, ep, 0, 1, sok, true);
-
- switch (usbif_pipetype(usbback_req->req.pipe)) {
- case USBIF_PIPE_TYPE_ISOC:
- TR_REQ(xendev, "iso transfer %s: buflen: %x, %d frames\n",
- (pid == USB_TOKEN_IN) ? "in" : "out",
- usbback_req->req.buffer_length,
- usbback_req->req.u.isoc.nr_frame_desc_segs);
- ret = -EINVAL; /* isoc not implemented yet */
- break;
-
- case USBIF_PIPE_TYPE_INT:
- TR_REQ(xendev, "int transfer %s: buflen: %x\n",
- (pid == USB_TOKEN_IN) ? "in" : "out",
- usbback_req->req.buffer_length);
- break;
-
- case USBIF_PIPE_TYPE_CTRL:
- packet->parameter = *(uint64_t *)usbback_req->req.u.ctrl;
- TR_REQ(xendev, "ctrl parameter: %"PRIx64", buflen: %x\n",
- packet->parameter,
- usbback_req->req.buffer_length);
- break;
-
- case USBIF_PIPE_TYPE_BULK:
- TR_REQ(xendev, "bulk transfer %s: buflen: %x\n",
- (pid == USB_TOKEN_IN) ? "in" : "out",
- usbback_req->req.buffer_length);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static void usbback_do_response(struct usbback_req *usbback_req, int32_t status,
- int32_t actual_length, int32_t error_count)
-{
- struct usbback_info *usbif;
- struct usbif_urb_response *res;
- struct XenDevice *xendev;
- unsigned int notify;
-
- usbif = usbback_req->usbif;
- xendev = &usbif->xendev;
-
- TR_REQ(xendev, "id %d, status %d, length %d, errcnt %d\n",
- usbback_req->req.id, status, actual_length, error_count);
-
- if (usbback_req->packet.iov.iov) {
- qemu_iovec_destroy(&usbback_req->packet.iov);
- }
-
- if (usbback_req->buffer) {
- xengnttab_unmap(xendev->gnttabdev, usbback_req->buffer,
- usbback_req->nr_buffer_segs);
- usbback_req->buffer = NULL;
- }
-
- if (usbback_req->isoc_buffer) {
- xengnttab_unmap(xendev->gnttabdev, usbback_req->isoc_buffer,
- usbback_req->nr_extra_segs);
- usbback_req->isoc_buffer = NULL;
- }
-
- if (usbif->urb_sring) {
- res = RING_GET_RESPONSE(&usbif->urb_ring, usbif->urb_ring.rsp_prod_pvt);
- res->id = usbback_req->req.id;
- res->status = status;
- res->actual_length = actual_length;
- res->error_count = error_count;
- res->start_frame = 0;
- usbif->urb_ring.rsp_prod_pvt++;
- RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&usbif->urb_ring, notify);
-
- if (notify) {
- xen_be_send_notify(xendev);
- }
- }
-
- if (!usbback_req->cancelled)
- usbback_put_req(usbback_req);
-}
-
-static void usbback_do_response_ret(struct usbback_req *usbback_req,
- int32_t status)
-{
- usbback_do_response(usbback_req, status, 0, 0);
-}
-
-static int32_t usbback_xlat_status(int status)
-{
- switch (status) {
- case USB_RET_SUCCESS:
- return 0;
- case USB_RET_NODEV:
- return -ENODEV;
- case USB_RET_STALL:
- return -EPIPE;
- case USB_RET_BABBLE:
- return -EOVERFLOW;
- case USB_RET_IOERROR:
- return -EPROTO;
- }
-
- return -ESHUTDOWN;
-}
-
-static void usbback_packet_complete(USBPacket *packet)
-{
- struct usbback_req *usbback_req;
- int32_t status;
-
- usbback_req = container_of(packet, struct usbback_req, packet);
-
- QTAILQ_REMOVE(&usbback_req->stub->submit_q, usbback_req, q);
-
- status = usbback_xlat_status(packet->status);
- usbback_do_response(usbback_req, status, packet->actual_length, 0);
-}
-
-static void usbback_set_address(struct usbback_info *usbif,
- struct usbback_stub *stub,
- unsigned int cur_addr, unsigned int new_addr)
-{
- if (cur_addr) {
- usbif->addr_table[cur_addr] = NULL;
- }
- if (new_addr) {
- usbif->addr_table[new_addr] = stub;
- }
-}
-
-static void usbback_cancel_req(struct usbback_req *usbback_req)
-{
- if (usb_packet_is_inflight(&usbback_req->packet)) {
- usb_cancel_packet(&usbback_req->packet);
- QTAILQ_REMOVE(&usbback_req->stub->submit_q, usbback_req, q);
- usbback_req->cancelled = true;
- usbback_do_response_ret(usbback_req, -EPROTO);
- }
-}
-
-static void usbback_process_unlink_req(struct usbback_req *usbback_req)
-{
- struct usbback_info *usbif;
- struct usbback_req *unlink_req;
- unsigned int id, devnum;
- int ret;
-
- usbif = usbback_req->usbif;
- ret = 0;
- id = usbback_req->req.u.unlink.unlink_id;
- TR_REQ(&usbif->xendev, "unlink id %d\n", id);
- devnum = usbif_pipedevice(usbback_req->req.pipe);
- if (unlikely(devnum == 0)) {
- usbback_req->stub = usbif->ports +
- usbif_pipeportnum(usbback_req->req.pipe) - 1;
- if (unlikely(!usbback_req->stub)) {
- ret = -ENODEV;
- goto fail_response;
- }
- } else {
- if (unlikely(!usbif->addr_table[devnum])) {
- ret = -ENODEV;
- goto fail_response;
- }
- usbback_req->stub = usbif->addr_table[devnum];
- }
-
- QTAILQ_FOREACH(unlink_req, &usbback_req->stub->submit_q, q) {
- if (unlink_req->req.id == id) {
- usbback_cancel_req(unlink_req);
- break;
- }
- }
-
-fail_response:
- usbback_do_response_ret(usbback_req, ret);
-}
-
-/*
- * Checks whether a request can be handled at once or should be forwarded
- * to the usb framework.
- * Return value is:
- * 0 in case of usb framework is needed
- * 1 in case of local handling (no error)
- * The request response has been queued already if return value not 0.
- */
-static int usbback_check_and_submit(struct usbback_req *usbback_req)
-{
- struct usbback_info *usbif;
- unsigned int devnum;
- struct usbback_stub *stub;
- struct usbif_ctrlrequest *ctrl;
- int ret;
- uint16_t wValue;
-
- usbif = usbback_req->usbif;
- stub = NULL;
- devnum = usbif_pipedevice(usbback_req->req.pipe);
- ctrl = (struct usbif_ctrlrequest *)usbback_req->req.u.ctrl;
- wValue = le16_to_cpu(ctrl->wValue);
-
- /*
- * When the device is first connected or resetted, USB device has no
- * address. In this initial state, following requests are sent to device
- * address (#0),
- *
- * 1. GET_DESCRIPTOR (with Descriptor Type is "DEVICE") is sent,
- * and OS knows what device is connected to.
- *
- * 2. SET_ADDRESS is sent, and then device has its address.
- *
- * In the next step, SET_CONFIGURATION is sent to addressed device, and
- * then the device is finally ready to use.
- */
- if (unlikely(devnum == 0)) {
- stub = usbif->ports + usbif_pipeportnum(usbback_req->req.pipe) - 1;
- if (!stub->dev || !stub->attached) {
- ret = -ENODEV;
- goto do_response;
- }
-
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- /*
- * GET_DESCRIPTOR request to device #0.
- * through normal transfer.
- */
- TR_REQ(&usbif->xendev, "devnum 0 GET_DESCRIPTOR\n");
- usbback_req->stub = stub;
- return 0;
- case USB_REQ_SET_ADDRESS:
- /*
- * SET_ADDRESS request to device #0.
- * add attached device to addr_table.
- */
- TR_REQ(&usbif->xendev, "devnum 0 SET_ADDRESS\n");
- usbback_set_address(usbif, stub, 0, wValue);
- ret = 0;
- break;
- default:
- ret = -EINVAL;
- break;
- }
- goto do_response;
- }
-
- if (unlikely(!usbif->addr_table[devnum])) {
- ret = -ENODEV;
- goto do_response;
- }
- usbback_req->stub = usbif->addr_table[devnum];
-
- /*
- * Check special request
- */
- if (ctrl->bRequest != USB_REQ_SET_ADDRESS) {
- return 0;
- }
-
- /*
- * SET_ADDRESS request to addressed device.
- * change addr or remove from addr_table.
- */
- usbback_set_address(usbif, usbback_req->stub, devnum, wValue);
- ret = 0;
-
-do_response:
- usbback_do_response_ret(usbback_req, ret);
- return 1;
-}
-
-static void usbback_dispatch(struct usbback_req *usbback_req)
-{
- int ret;
- unsigned int devnum;
- struct usbback_info *usbif;
-
- usbif = usbback_req->usbif;
-
- TR_REQ(&usbif->xendev, "start req_id %d pipe %08x\n", usbback_req->req.id,
- usbback_req->req.pipe);
-
- /* unlink request */
- if (unlikely(usbif_pipeunlink(usbback_req->req.pipe))) {
- usbback_process_unlink_req(usbback_req);
- return;
- }
-
- if (usbif_pipectrl(usbback_req->req.pipe)) {
- if (usbback_check_and_submit(usbback_req)) {
- return;
- }
- } else {
- devnum = usbif_pipedevice(usbback_req->req.pipe);
- usbback_req->stub = usbif->addr_table[devnum];
-
- if (!usbback_req->stub || !usbback_req->stub->attached) {
- ret = -ENODEV;
- goto fail_response;
- }
- }
-
- QTAILQ_INSERT_TAIL(&usbback_req->stub->submit_q, usbback_req, q);
-
- usbback_req->nr_buffer_segs = usbback_req->req.nr_buffer_segs;
- usbback_req->nr_extra_segs = usbif_pipeisoc(usbback_req->req.pipe) ?
- usbback_req->req.u.isoc.nr_frame_desc_segs : 0;
-
- ret = usbback_init_packet(usbback_req);
- if (ret) {
- xen_be_printf(&usbif->xendev, 0, "invalid request\n");
- ret = -ESHUTDOWN;
- goto fail_free_urb;
- }
-
- ret = usbback_gnttab_map(usbback_req);
- if (ret) {
- xen_be_printf(&usbif->xendev, 0, "invalid buffer, ret=%d\n", ret);
- ret = -ESHUTDOWN;
- goto fail_free_urb;
- }
-
- usb_handle_packet(usbback_req->stub->dev, &usbback_req->packet);
- if (usbback_req->packet.status != USB_RET_ASYNC) {
- usbback_packet_complete(&usbback_req->packet);
- }
- return;
-
-fail_free_urb:
- QTAILQ_REMOVE(&usbback_req->stub->submit_q, usbback_req, q);
-
-fail_response:
- usbback_do_response_ret(usbback_req, ret);
-}
-
-static void usbback_hotplug_notify(struct usbback_info *usbif)
-{
- struct usbif_conn_back_ring *ring = &usbif->conn_ring;
- struct usbif_conn_request req;
- struct usbif_conn_response *res;
- struct usbback_hotplug *usb_hp;
- unsigned int notify;
-
- if (!usbif->conn_sring) {
- return;
- }
-
- /* Check for full ring. */
- if ((RING_SIZE(ring) - ring->rsp_prod_pvt - ring->req_cons) == 0) {
- xen_be_send_notify(&usbif->xendev);
- return;
- }
-
- usb_hp = QSIMPLEQ_FIRST(&usbif->hotplug_q);
- QSIMPLEQ_REMOVE_HEAD(&usbif->hotplug_q, q);
-
- RING_COPY_REQUEST(ring, ring->req_cons, &req);
- ring->req_cons++;
- ring->sring->req_event = ring->req_cons + 1;
-
- res = RING_GET_RESPONSE(ring, ring->rsp_prod_pvt);
- res->id = req.id;
- res->portnum = usb_hp->port;
- res->speed = usbif->ports[usb_hp->port - 1].speed;
- ring->rsp_prod_pvt++;
- RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(ring, notify);
-
- if (notify) {
- xen_be_send_notify(&usbif->xendev);
- }
-
- TR_BUS(&usbif->xendev, "hotplug port %d speed %d\n", usb_hp->port,
- res->speed);
-
- g_free(usb_hp);
-
- if (!QSIMPLEQ_EMPTY(&usbif->hotplug_q)) {
- qemu_bh_schedule(usbif->bh);
- }
-}
-
-static void usbback_bh(void *opaque)
-{
- struct usbback_info *usbif;
- struct usbif_urb_back_ring *urb_ring;
- struct usbback_req *usbback_req;
- RING_IDX rc, rp;
- unsigned int more_to_do;
-
- usbif = opaque;
- if (usbif->ring_error) {
- return;
- }
-
- if (!QSIMPLEQ_EMPTY(&usbif->hotplug_q)) {
- usbback_hotplug_notify(usbif);
- }
-
- urb_ring = &usbif->urb_ring;
- rc = urb_ring->req_cons;
- rp = urb_ring->sring->req_prod;
- xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
-
- if (RING_REQUEST_PROD_OVERFLOW(urb_ring, rp)) {
- rc = urb_ring->rsp_prod_pvt;
- xen_be_printf(&usbif->xendev, 0, "domU provided bogus ring requests "
- "(%#x - %#x = %u). Halting ring processing.\n",
- rp, rc, rp - rc);
- usbif->ring_error = true;
- return;
- }
-
- while (rc != rp) {
- if (RING_REQUEST_CONS_OVERFLOW(urb_ring, rc)) {
- break;
- }
- usbback_req = usbback_get_req(usbif);
-
- RING_COPY_REQUEST(urb_ring, rc, &usbback_req->req);
- usbback_req->usbif = usbif;
-
- usbback_dispatch(usbback_req);
-
- urb_ring->req_cons = ++rc;
- }
-
- RING_FINAL_CHECK_FOR_REQUESTS(urb_ring, more_to_do);
- if (more_to_do) {
- qemu_bh_schedule(usbif->bh);
- }
-}
-
-static void usbback_hotplug_enq(struct usbback_info *usbif, unsigned port)
-{
- struct usbback_hotplug *usb_hp;
-
- usb_hp = g_new0(struct usbback_hotplug, 1);
- usb_hp->port = port;
- QSIMPLEQ_INSERT_TAIL(&usbif->hotplug_q, usb_hp, q);
- usbback_hotplug_notify(usbif);
-}
-
-static void usbback_portid_drain(struct usbback_info *usbif, unsigned port)
-{
- struct usbback_req *req, *tmp;
- bool sched = false;
-
- QTAILQ_FOREACH_SAFE(req, &usbif->ports[port - 1].submit_q, q, tmp) {
- usbback_cancel_req(req);
- sched = true;
- }
-
- if (sched) {
- qemu_bh_schedule(usbif->bh);
- }
-}
-
-static void usbback_portid_detach(struct usbback_info *usbif, unsigned port)
-{
- if (!usbif->ports[port - 1].attached) {
- return;
- }
-
- usbif->ports[port - 1].speed = USBIF_SPEED_NONE;
- usbif->ports[port - 1].attached = false;
- usbback_portid_drain(usbif, port);
- usbback_hotplug_enq(usbif, port);
-}
-
-static void usbback_portid_remove(struct usbback_info *usbif, unsigned port)
-{
- USBPort *p;
-
- if (!usbif->ports[port - 1].dev) {
- return;
- }
-
- p = &(usbif->ports[port - 1].port);
- snprintf(p->path, sizeof(p->path), "%d", 99);
-
- object_unparent(OBJECT(usbif->ports[port - 1].dev));
- usbif->ports[port - 1].dev = NULL;
- usbback_portid_detach(usbif, port);
-
- TR_BUS(&usbif->xendev, "port %d removed\n", port);
-}
-
-static void usbback_portid_add(struct usbback_info *usbif, unsigned port,
- char *busid)
-{
- unsigned speed;
- char *portname;
- USBPort *p;
- Error *local_err = NULL;
- QDict *qdict;
- QemuOpts *opts;
-
- if (usbif->ports[port - 1].dev) {
- return;
- }
-
- portname = strchr(busid, '-');
- if (!portname) {
- xen_be_printf(&usbif->xendev, 0, "device %s illegal specification\n",
- busid);
- return;
- }
- portname++;
- p = &(usbif->ports[port - 1].port);
- snprintf(p->path, sizeof(p->path), "%s", portname);
-
- qdict = qdict_new();
- qdict_put(qdict, "driver", qstring_from_str("usb-host"));
- qdict_put(qdict, "hostbus", qint_from_int(atoi(busid)));
- qdict_put(qdict, "hostport", qstring_from_str(portname));
- opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
- if (local_err) {
- goto err;
- }
- usbif->ports[port - 1].dev = USB_DEVICE(qdev_device_add(opts, &local_err));
- if (!usbif->ports[port - 1].dev) {
- goto err;
- }
- QDECREF(qdict);
- snprintf(p->path, sizeof(p->path), "%d", port);
- speed = usbif->ports[port - 1].dev->speed;
- switch (speed) {
- case USB_SPEED_LOW:
- speed = USBIF_SPEED_LOW;
- break;
- case USB_SPEED_FULL:
- speed = USBIF_SPEED_FULL;
- break;
- case USB_SPEED_HIGH:
- speed = (usbif->usb_ver < USB_VER_USB20) ?
- USBIF_SPEED_NONE : USBIF_SPEED_HIGH;
- break;
- default:
- speed = USBIF_SPEED_NONE;
- break;
- }
- if (speed == USBIF_SPEED_NONE) {
- xen_be_printf(&usbif->xendev, 0, "device %s wrong speed\n", busid);
- object_unparent(OBJECT(usbif->ports[port - 1].dev));
- usbif->ports[port - 1].dev = NULL;
- return;
- }
- usb_device_reset(usbif->ports[port - 1].dev);
- usbif->ports[port - 1].speed = speed;
- usbif->ports[port - 1].attached = true;
- QTAILQ_INIT(&usbif->ports[port - 1].submit_q);
- usbback_hotplug_enq(usbif, port);
-
- TR_BUS(&usbif->xendev, "port %d attached\n", port);
- return;
-
-err:
- QDECREF(qdict);
- snprintf(p->path, sizeof(p->path), "%d", 99);
- xen_be_printf(&usbif->xendev, 0, "device %s could not be opened\n", busid);
-}
-
-static void usbback_process_port(struct usbback_info *usbif, unsigned port)
-{
- char node[8];
- char *busid;
-
- snprintf(node, sizeof(node), "port/%d", port);
- busid = xenstore_read_be_str(&usbif->xendev, node);
- if (busid == NULL) {
- xen_be_printf(&usbif->xendev, 0, "xenstore_read %s failed\n", node);
- return;
- }
-
- /* Remove portid, if the port is not connected. */
- if (strlen(busid) == 0) {
- usbback_portid_remove(usbif, port);
- } else {
- usbback_portid_add(usbif, port, busid);
- }
-
- g_free(busid);
-}
-
-static void usbback_disconnect(struct XenDevice *xendev)
-{
- struct usbback_info *usbif;
- unsigned int i;
-
- TR_BUS(xendev, "start\n");
-
- usbif = container_of(xendev, struct usbback_info, xendev);
-
- xen_be_unbind_evtchn(xendev);
-
- if (usbif->urb_sring) {
- xengnttab_unmap(xendev->gnttabdev, usbif->urb_sring, 1);
- usbif->urb_sring = NULL;
- }
- if (usbif->conn_sring) {
- xengnttab_unmap(xendev->gnttabdev, usbif->conn_sring, 1);
- usbif->conn_sring = NULL;
- }
-
- for (i = 0; i < usbif->num_ports; i++) {
- if (usbif->ports[i].dev) {
- usbback_portid_drain(usbif, i + 1);
- }
- }
-
- TR_BUS(xendev, "finished\n");
-}
-
-static int usbback_connect(struct XenDevice *xendev)
-{
- struct usbback_info *usbif;
- struct usbif_urb_sring *urb_sring;
- struct usbif_conn_sring *conn_sring;
- int urb_ring_ref;
- int conn_ring_ref;
- unsigned int i;
-
- TR_BUS(xendev, "start\n");
-
- usbif = container_of(xendev, struct usbback_info, xendev);
-
- if (xenstore_read_fe_int(xendev, "urb-ring-ref", &urb_ring_ref)) {
- xen_be_printf(xendev, 0, "error reading urb-ring-ref\n");
- return -1;
- }
- if (xenstore_read_fe_int(xendev, "conn-ring-ref", &conn_ring_ref)) {
- xen_be_printf(xendev, 0, "error reading conn-ring-ref\n");
- return -1;
- }
- if (xenstore_read_fe_int(xendev, "event-channel", &xendev->remote_port)) {
- xen_be_printf(xendev, 0, "error reading event-channel\n");
- return -1;
- }
-
- usbif->urb_sring = xengnttab_map_grant_ref(xendev->gnttabdev, xendev->dom,
- urb_ring_ref,
- PROT_READ | PROT_WRITE);
- usbif->conn_sring = xengnttab_map_grant_ref(xendev->gnttabdev, xendev->dom,
- conn_ring_ref,
- PROT_READ | PROT_WRITE);
- if (!usbif->urb_sring || !usbif->conn_sring) {
- xen_be_printf(xendev, 0, "error mapping rings\n");
- usbback_disconnect(xendev);
- return -1;
- }
-
- urb_sring = usbif->urb_sring;
- conn_sring = usbif->conn_sring;
- BACK_RING_INIT(&usbif->urb_ring, urb_sring, XC_PAGE_SIZE);
- BACK_RING_INIT(&usbif->conn_ring, conn_sring, XC_PAGE_SIZE);
-
- xen_be_bind_evtchn(xendev);
-
- xen_be_printf(xendev, 1, "urb-ring-ref %d, conn-ring-ref %d, "
- "remote port %d, local port %d\n", urb_ring_ref,
- conn_ring_ref, xendev->remote_port, xendev->local_port);
-
- for (i = 1; i <= usbif->num_ports; i++) {
- if (usbif->ports[i - 1].dev) {
- usbback_hotplug_enq(usbif, i);
- }
- }
-
- return 0;
-}
-
-static void usbback_backend_changed(struct XenDevice *xendev, const char *node)
-{
- struct usbback_info *usbif;
- unsigned int i;
-
- TR_BUS(xendev, "path %s\n", node);
-
- usbif = container_of(xendev, struct usbback_info, xendev);
- for (i = 1; i <= usbif->num_ports; i++) {
- usbback_process_port(usbif, i);
- }
-}
-
-static int usbback_init(struct XenDevice *xendev)
-{
- struct usbback_info *usbif;
-
- TR_BUS(xendev, "start\n");
-
- usbif = container_of(xendev, struct usbback_info, xendev);
-
- if (xenstore_read_be_int(xendev, "num-ports", &usbif->num_ports) ||
- usbif->num_ports < 1 || usbif->num_ports > USBBACK_MAXPORTS) {
- xen_be_printf(xendev, 0, "num-ports not readable or out of bounds\n");
- return -1;
- }
- if (xenstore_read_be_int(xendev, "usb-ver", &usbif->usb_ver) ||
- (usbif->usb_ver != USB_VER_USB11 && usbif->usb_ver != USB_VER_USB20)) {
- xen_be_printf(xendev, 0, "usb-ver not readable or out of bounds\n");
- return -1;
- }
-
- usbback_backend_changed(xendev, "port");
-
- TR_BUS(xendev, "finished\n");
-
- return 0;
-}
-
-static void xen_bus_attach(USBPort *port)
-{
- struct usbback_info *usbif;
-
- usbif = port->opaque;
- TR_BUS(&usbif->xendev, "\n");
- usbif->ports[port->index].attached = true;
- usbback_hotplug_enq(usbif, port->index + 1);
-}
-
-static void xen_bus_detach(USBPort *port)
-{
- struct usbback_info *usbif;
-
- usbif = port->opaque;
- TR_BUS(&usbif->xendev, "\n");
- usbback_portid_detach(usbif, port->index + 1);
-}
-
-static void xen_bus_child_detach(USBPort *port, USBDevice *child)
-{
- struct usbback_info *usbif;
-
- usbif = port->opaque;
- TR_BUS(&usbif->xendev, "\n");
-}
-
-static void xen_bus_complete(USBPort *port, USBPacket *packet)
-{
- struct usbback_req *usbback_req;
- struct usbback_info *usbif;
-
- usbback_req = container_of(packet, struct usbback_req, packet);
- if (usbback_req->cancelled) {
- g_free(usbback_req);
- return;
- }
-
- usbif = usbback_req->usbif;
- TR_REQ(&usbif->xendev, "\n");
- usbback_packet_complete(packet);
-}
-
-static USBPortOps xen_usb_port_ops = {
- .attach = xen_bus_attach,
- .detach = xen_bus_detach,
- .child_detach = xen_bus_child_detach,
- .complete = xen_bus_complete,
-};
-
-static USBBusOps xen_usb_bus_ops = {
-};
-
-static void usbback_alloc(struct XenDevice *xendev)
-{
- struct usbback_info *usbif;
- USBPort *p;
- unsigned int i, max_grants;
-
- usbif = container_of(xendev, struct usbback_info, xendev);
-
- usb_bus_new(&usbif->bus, sizeof(usbif->bus), &xen_usb_bus_ops, xen_sysdev);
- for (i = 0; i < USBBACK_MAXPORTS; i++) {
- p = &(usbif->ports[i].port);
- usb_register_port(&usbif->bus, p, usbif, i, &xen_usb_port_ops,
- USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL |
- USB_SPEED_MASK_HIGH);
- snprintf(p->path, sizeof(p->path), "%d", 99);
- }
-
- QTAILQ_INIT(&usbif->req_free_q);
- QSIMPLEQ_INIT(&usbif->hotplug_q);
- usbif->bh = qemu_bh_new(usbback_bh, usbif);
-
- /* max_grants: for each request and for the rings (request and connect). */
- max_grants = USBIF_MAX_SEGMENTS_PER_REQUEST * USB_URB_RING_SIZE + 2;
- if (xengnttab_set_max_grants(xendev->gnttabdev, max_grants) < 0) {
- xen_be_printf(xendev, 0, "xengnttab_set_max_grants failed: %s\n",
- strerror(errno));
- }
-}
-
-static int usbback_free(struct XenDevice *xendev)
-{
- struct usbback_info *usbif;
- struct usbback_req *usbback_req;
- struct usbback_hotplug *usb_hp;
- unsigned int i;
-
- TR_BUS(xendev, "start\n");
-
- usbback_disconnect(xendev);
- usbif = container_of(xendev, struct usbback_info, xendev);
- for (i = 1; i <= usbif->num_ports; i++) {
- usbback_portid_remove(usbif, i);
- }
-
- while (!QTAILQ_EMPTY(&usbif->req_free_q)) {
- usbback_req = QTAILQ_FIRST(&usbif->req_free_q);
- QTAILQ_REMOVE(&usbif->req_free_q, usbback_req, q);
- g_free(usbback_req);
- }
- while (!QSIMPLEQ_EMPTY(&usbif->hotplug_q)) {
- usb_hp = QSIMPLEQ_FIRST(&usbif->hotplug_q);
- QSIMPLEQ_REMOVE_HEAD(&usbif->hotplug_q, q);
- g_free(usb_hp);
- }
-
- qemu_bh_delete(usbif->bh);
-
- for (i = 0; i < USBBACK_MAXPORTS; i++) {
- usb_unregister_port(&usbif->bus, &(usbif->ports[i].port));
- }
-
- usb_bus_release(&usbif->bus);
- object_unparent(OBJECT(&usbif->bus));
-
- TR_BUS(xendev, "finished\n");
-
- return 0;
-}
-
-static void usbback_event(struct XenDevice *xendev)
-{
- struct usbback_info *usbif;
-
- usbif = container_of(xendev, struct usbback_info, xendev);
- qemu_bh_schedule(usbif->bh);
-}
-
-struct XenDevOps xen_usb_ops = {
- .size = sizeof(struct usbback_info),
- .flags = DEVOPS_FLAG_NEED_GNTDEV,
- .init = usbback_init,
- .alloc = usbback_alloc,
- .free = usbback_free,
- .backend_changed = usbback_backend_changed,
- .initialise = usbback_connect,
- .disconnect = usbback_disconnect,
- .event = usbback_event,
-};
-
-#else /* USBIF_SHORT_NOT_OK */
-
-static int usbback_not_supported(void)
-{
- return -EINVAL;
-}
-
-struct XenDevOps xen_usb_ops = {
- .backend_register = usbback_not_supported,
-};
-
-#endif
diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
index c25e32b02..ceddbb8f9 100644
--- a/hw/vfio/Makefile.objs
+++ b/hw/vfio/Makefile.objs
@@ -4,5 +4,4 @@ obj-$(CONFIG_PCI) += pci.o pci-quirks.o
obj-$(CONFIG_SOFTMMU) += platform.o
obj-$(CONFIG_SOFTMMU) += calxeda-xgmac.o
obj-$(CONFIG_SOFTMMU) += amd-xgbe.o
-obj-$(CONFIG_SOFTMMU) += spapr.o
endif
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b313e7c2c..e1927a5b9 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -20,9 +20,7 @@
#include "qemu/osdep.h"
#include <sys/ioctl.h>
-#ifdef CONFIG_KVM
-#include <linux/kvm.h>
-#endif
+#include <sys/mman.h>
#include <linux/vfio.h>
#include "hw/vfio/vfio-common.h"
@@ -31,7 +29,6 @@
#include "exec/memory.h"
#include "hw/hw.h"
#include "qemu/error-report.h"
-#include "qemu/range.h"
#include "sysemu/kvm.h"
#include "trace.h"
@@ -242,44 +239,6 @@ static int vfio_dma_map(VFIOContainer *container, hwaddr iova,
return -errno;
}
-static void vfio_host_win_add(VFIOContainer *container,
- hwaddr min_iova, hwaddr max_iova,
- uint64_t iova_pgsizes)
-{
- VFIOHostDMAWindow *hostwin;
-
- QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {
- if (ranges_overlap(hostwin->min_iova,
- hostwin->max_iova - hostwin->min_iova + 1,
- min_iova,
- max_iova - min_iova + 1)) {
- hw_error("%s: Overlapped IOMMU are not enabled", __func__);
- }
- }
-
- hostwin = g_malloc0(sizeof(*hostwin));
-
- hostwin->min_iova = min_iova;
- hostwin->max_iova = max_iova;
- hostwin->iova_pgsizes = iova_pgsizes;
- QLIST_INSERT_HEAD(&container->hostwin_list, hostwin, hostwin_next);
-}
-
-static int vfio_host_win_del(VFIOContainer *container, hwaddr min_iova,
- hwaddr max_iova)
-{
- VFIOHostDMAWindow *hostwin;
-
- QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {
- if (hostwin->min_iova == min_iova && hostwin->max_iova == max_iova) {
- QLIST_REMOVE(hostwin, hostwin_next);
- return 0;
- }
- }
-
- return -1;
-}
-
static bool vfio_listener_skipped_section(MemoryRegionSection *section)
{
return (!memory_region_is_ram(section->mr) &&
@@ -298,20 +257,14 @@ static void vfio_iommu_map_notify(Notifier *n, void *data)
VFIOGuestIOMMU *giommu = container_of(n, VFIOGuestIOMMU, n);
VFIOContainer *container = giommu->container;
IOMMUTLBEntry *iotlb = data;
- hwaddr iova = iotlb->iova + giommu->iommu_offset;
MemoryRegion *mr;
hwaddr xlat;
hwaddr len = iotlb->addr_mask + 1;
void *vaddr;
int ret;
- trace_vfio_iommu_map_notify(iova, iova + iotlb->addr_mask);
-
- if (iotlb->target_as != &address_space_memory) {
- error_report("Wrong target AS \"%s\", only system memory is allowed",
- iotlb->target_as->name ? iotlb->target_as->name : "none");
- return;
- }
+ trace_vfio_iommu_map_notify(iotlb->iova,
+ iotlb->iova + iotlb->addr_mask);
/*
* The IOMMU TLB entry we have just covers translation through
@@ -338,21 +291,21 @@ static void vfio_iommu_map_notify(Notifier *n, void *data)
if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) {
vaddr = memory_region_get_ram_ptr(mr) + xlat;
- ret = vfio_dma_map(container, iova,
+ ret = vfio_dma_map(container, iotlb->iova,
iotlb->addr_mask + 1, vaddr,
!(iotlb->perm & IOMMU_WO) || mr->readonly);
if (ret) {
error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
"0x%"HWADDR_PRIx", %p) = %d (%m)",
- container, iova,
+ container, iotlb->iova,
iotlb->addr_mask + 1, vaddr, ret);
}
} else {
- ret = vfio_dma_unmap(container, iova, iotlb->addr_mask + 1);
+ ret = vfio_dma_unmap(container, iotlb->iova, iotlb->addr_mask + 1);
if (ret) {
error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", "
"0x%"HWADDR_PRIx") = %d (%m)",
- container, iova,
+ container, iotlb->iova,
iotlb->addr_mask + 1, ret);
}
}
@@ -360,6 +313,11 @@ out:
rcu_read_unlock();
}
+static hwaddr vfio_container_granularity(VFIOContainer *container)
+{
+ return (hwaddr)1 << ctz64(container->iova_pgsizes);
+}
+
static void vfio_listener_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
@@ -368,8 +326,6 @@ static void vfio_listener_region_add(MemoryListener *listener,
Int128 llend, llsize;
void *vaddr;
int ret;
- VFIOHostDMAWindow *hostwin;
- bool hostwin_found;
if (vfio_listener_skipped_section(section)) {
trace_vfio_listener_region_add_skip(
@@ -395,40 +351,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
}
end = int128_get64(int128_sub(llend, int128_one()));
- if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {
- VFIOHostDMAWindow *hostwin;
- hwaddr pgsize = 0;
-
- /* For now intersections are not allowed, we may relax this later */
- QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {
- if (ranges_overlap(hostwin->min_iova,
- hostwin->max_iova - hostwin->min_iova + 1,
- section->offset_within_address_space,
- int128_get64(section->size))) {
- ret = -1;
- goto fail;
- }
- }
-
- ret = vfio_spapr_create_window(container, section, &pgsize);
- if (ret) {
- goto fail;
- }
-
- vfio_host_win_add(container, section->offset_within_address_space,
- section->offset_within_address_space +
- int128_get64(section->size) - 1, pgsize);
- }
-
- hostwin_found = false;
- QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {
- if (hostwin->min_iova <= iova && end <= hostwin->max_iova) {
- hostwin_found = true;
- break;
- }
- }
-
- if (!hostwin_found) {
+ if ((iova < container->min_iova) || (end > container->max_iova)) {
error_report("vfio: IOMMU container %p can't map guest IOVA region"
" 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,
container, iova, end);
@@ -443,6 +366,10 @@ static void vfio_listener_region_add(MemoryListener *listener,
trace_vfio_listener_region_add_iommu(iova, end);
/*
+ * FIXME: We should do some checking to see if the
+ * capabilities of the host VFIO IOMMU are adequate to model
+ * the guest IOMMU
+ *
* FIXME: For VFIO iommu types which have KVM acceleration to
* avoid bouncing all map/unmaps through qemu this way, this
* would be the right place to wire that up (tell the KVM
@@ -450,14 +377,14 @@ static void vfio_listener_region_add(MemoryListener *listener,
*/
giommu = g_malloc0(sizeof(*giommu));
giommu->iommu = section->mr;
- giommu->iommu_offset = section->offset_within_address_space -
- section->offset_within_region;
giommu->container = container;
giommu->n.notify = vfio_iommu_map_notify;
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);
- memory_region_iommu_replay(giommu->iommu, &giommu->n, false);
+ memory_region_iommu_replay(giommu->iommu, &giommu->n,
+ vfio_container_granularity(container),
+ false);
return;
}
@@ -503,7 +430,6 @@ static void vfio_listener_region_del(MemoryListener *listener,
{
VFIOContainer *container = container_of(listener, VFIOContainer, listener);
hwaddr iova, end;
- Int128 llend, llsize;
int ret;
if (vfio_listener_skipped_section(section)) {
@@ -525,8 +451,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
if (giommu->iommu == section->mr) {
- memory_region_unregister_iommu_notifier(giommu->iommu,
- &giommu->n);
+ memory_region_unregister_iommu_notifier(&giommu->n);
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
break;
@@ -543,37 +468,21 @@ static void vfio_listener_region_del(MemoryListener *listener,
}
iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);
- llend = int128_make64(section->offset_within_address_space);
- llend = int128_add(llend, section->size);
- llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));
+ end = (section->offset_within_address_space + int128_get64(section->size)) &
+ TARGET_PAGE_MASK;
- if (int128_ge(int128_make64(iova), llend)) {
+ if (iova >= end) {
return;
}
- end = int128_get64(int128_sub(llend, int128_one()));
-
- llsize = int128_sub(llend, int128_make64(iova));
- trace_vfio_listener_region_del(iova, end);
+ trace_vfio_listener_region_del(iova, end - 1);
- ret = vfio_dma_unmap(container, iova, int128_get64(llsize));
+ ret = vfio_dma_unmap(container, iova, end - iova);
memory_region_unref(section->mr);
if (ret) {
error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", "
"0x%"HWADDR_PRIx") = %d (%m)",
- container, iova, int128_get64(llsize), ret);
- }
-
- if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {
- vfio_spapr_remove_window(container,
- section->offset_within_address_space);
- if (vfio_host_win_del(container,
- section->offset_within_address_space,
- section->offset_within_address_space +
- int128_get64(section->size) - 1) < 0) {
- hw_error("%s: Cannot delete missing window at %"HWADDR_PRIx,
- __func__, section->offset_within_address_space);
- }
+ container, iova, end - iova, ret);
}
}
@@ -585,57 +494,6 @@ static const MemoryListener vfio_memory_listener = {
static void vfio_listener_release(VFIOContainer *container)
{
memory_listener_unregister(&container->listener);
- if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {
- memory_listener_unregister(&container->prereg_listener);
- }
-}
-
-static struct vfio_info_cap_header *
-vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id)
-{
- struct vfio_info_cap_header *hdr;
- void *ptr = info;
-
- if (!(info->flags & VFIO_REGION_INFO_FLAG_CAPS)) {
- return NULL;
- }
-
- for (hdr = ptr + info->cap_offset; hdr != ptr; hdr = ptr + hdr->next) {
- if (hdr->id == id) {
- return hdr;
- }
- }
-
- return NULL;
-}
-
-static void vfio_setup_region_sparse_mmaps(VFIORegion *region,
- struct vfio_region_info *info)
-{
- struct vfio_info_cap_header *hdr;
- struct vfio_region_info_cap_sparse_mmap *sparse;
- int i;
-
- hdr = vfio_get_region_info_cap(info, VFIO_REGION_INFO_CAP_SPARSE_MMAP);
- if (!hdr) {
- return;
- }
-
- sparse = container_of(hdr, struct vfio_region_info_cap_sparse_mmap, header);
-
- trace_vfio_region_sparse_mmap_header(region->vbasedev->name,
- region->nr, sparse->nr_areas);
-
- region->nr_mmaps = sparse->nr_areas;
- region->mmaps = g_new0(VFIOMmap, region->nr_mmaps);
-
- for (i = 0; i < region->nr_mmaps; i++) {
- region->mmaps[i].offset = sparse->areas[i].offset;
- region->mmaps[i].size = sparse->areas[i].size;
- trace_vfio_region_sparse_mmap_entry(i, region->mmaps[i].offset,
- region->mmaps[i].offset +
- region->mmaps[i].size);
- }
}
int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region,
@@ -664,14 +522,11 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region,
region->flags & VFIO_REGION_INFO_FLAG_MMAP &&
!(region->size & ~qemu_real_host_page_mask)) {
- vfio_setup_region_sparse_mmaps(region, info);
+ region->nr_mmaps = 1;
+ region->mmaps = g_new0(VFIOMmap, region->nr_mmaps);
- if (!region->nr_mmaps) {
- region->nr_mmaps = 1;
- region->mmaps = g_new0(VFIOMmap, region->nr_mmaps);
- region->mmaps[0].offset = 0;
- region->mmaps[0].size = region->size;
- }
+ region->mmaps[0].offset = 0;
+ region->mmaps[0].size = region->size;
}
}
@@ -946,8 +801,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
goto free_container_exit;
}
- container->iommu_type = v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU;
- ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type);
+ ret = ioctl(fd, VFIO_SET_IOMMU,
+ v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU);
if (ret) {
error_report("vfio: failed to set iommu for container: %m");
ret = -errno;
@@ -961,18 +816,19 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
* existing Type1 IOMMUs generally support any IOVA we're
* going to actually try in practice.
*/
+ container->min_iova = 0;
+ container->max_iova = (hwaddr)-1;
+
+ /* Assume just 4K IOVA page size */
+ container->iova_pgsizes = 0x1000;
info.argsz = sizeof(info);
ret = ioctl(fd, VFIO_IOMMU_GET_INFO, &info);
/* Ignore errors */
- if (ret || !(info.flags & VFIO_IOMMU_INFO_PGSIZES)) {
- /* Assume 4k IOVA page size */
- info.iova_pgsizes = 4096;
+ if ((ret == 0) && (info.flags & VFIO_IOMMU_INFO_PGSIZES)) {
+ container->iova_pgsizes = info.iova_pgsizes;
}
- vfio_host_win_add(container, 0, (hwaddr)-1, info.iova_pgsizes);
- } else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU) ||
- ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_v2_IOMMU)) {
+ } else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU)) {
struct vfio_iommu_spapr_tce_info info;
- bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_v2_IOMMU);
ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
if (ret) {
@@ -980,9 +836,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
ret = -errno;
goto free_container_exit;
}
- container->iommu_type =
- v2 ? VFIO_SPAPR_TCE_v2_IOMMU : VFIO_SPAPR_TCE_IOMMU;
- ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type);
+ ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_SPAPR_TCE_IOMMU);
if (ret) {
error_report("vfio: failed to set iommu for container: %m");
ret = -errno;
@@ -994,54 +848,30 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
* when container fd is closed so we do not call it explicitly
* in this file.
*/
- if (!v2) {
- ret = ioctl(fd, VFIO_IOMMU_ENABLE);
- if (ret) {
- error_report("vfio: failed to enable container: %m");
- ret = -errno;
- goto free_container_exit;
- }
- } else {
- container->prereg_listener = vfio_prereg_listener;
-
- memory_listener_register(&container->prereg_listener,
- &address_space_memory);
- if (container->error) {
- memory_listener_unregister(&container->prereg_listener);
- error_report("vfio: RAM memory listener initialization failed for container");
- goto free_container_exit;
- }
+ ret = ioctl(fd, VFIO_IOMMU_ENABLE);
+ if (ret) {
+ error_report("vfio: failed to enable container: %m");
+ ret = -errno;
+ goto free_container_exit;
}
+ /*
+ * This only considers the host IOMMU's 32-bit window. At
+ * some point we need to add support for the optional 64-bit
+ * window and dynamic windows
+ */
info.argsz = sizeof(info);
ret = ioctl(fd, VFIO_IOMMU_SPAPR_TCE_GET_INFO, &info);
if (ret) {
error_report("vfio: VFIO_IOMMU_SPAPR_TCE_GET_INFO failed: %m");
ret = -errno;
- if (v2) {
- memory_listener_unregister(&container->prereg_listener);
- }
goto free_container_exit;
}
+ container->min_iova = info.dma32_window_start;
+ container->max_iova = container->min_iova + info.dma32_window_size - 1;
- if (v2) {
- /*
- * There is a default window in just created container.
- * To make region_add/del simpler, we better remove this
- * window now and let those iommu_listener callbacks
- * create/remove them when needed.
- */
- ret = vfio_spapr_remove_window(container, info.dma32_window_start);
- if (ret) {
- goto free_container_exit;
- }
- } else {
- /* The default table uses 4K pages */
- vfio_host_win_add(container, info.dma32_window_start,
- info.dma32_window_start +
- info.dma32_window_size - 1,
- 0x1000);
- }
+ /* Assume just 4K IOVA pages for now */
+ container->iova_pgsizes = 0x1000;
} else {
error_report("vfio: No available IOMMU models");
ret = -EINVAL;
@@ -1102,7 +932,7 @@ static void vfio_disconnect_container(VFIOGroup *group)
QLIST_REMOVE(container, next);
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
- memory_region_unregister_iommu_notifier(giommu->iommu, &giommu->n);
+ memory_region_unregister_iommu_notifier(&giommu->n);
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
}
@@ -1256,60 +1086,16 @@ int vfio_get_region_info(VFIODevice *vbasedev, int index,
*info = g_malloc0(argsz);
(*info)->index = index;
-retry:
(*info)->argsz = argsz;
if (ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, *info)) {
g_free(*info);
- *info = NULL;
return -errno;
}
- if ((*info)->argsz > argsz) {
- argsz = (*info)->argsz;
- *info = g_realloc(*info, argsz);
-
- goto retry;
- }
-
return 0;
}
-int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type,
- uint32_t subtype, struct vfio_region_info **info)
-{
- int i;
-
- for (i = 0; i < vbasedev->num_regions; i++) {
- struct vfio_info_cap_header *hdr;
- struct vfio_region_info_cap_type *cap_type;
-
- if (vfio_get_region_info(vbasedev, i, info)) {
- continue;
- }
-
- hdr = vfio_get_region_info_cap(*info, VFIO_REGION_INFO_CAP_TYPE);
- if (!hdr) {
- g_free(*info);
- continue;
- }
-
- cap_type = container_of(hdr, struct vfio_region_info_cap_type, header);
-
- trace_vfio_get_dev_region(vbasedev->name, i,
- cap_type->type, cap_type->subtype);
-
- if (cap_type->type == type && cap_type->subtype == subtype) {
- return 0;
- }
-
- g_free(*info);
- }
-
- *info = NULL;
- return -ENODEV;
-}
-
/*
* Interfaces for IBM EEH (Enhanced Error Handling)
*/
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index bec694c8d..6624905e1 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -11,12 +11,9 @@
*/
#include "qemu/osdep.h"
-#include "qemu/error-report.h"
-#include "qemu/range.h"
-#include "qapi/error.h"
-#include "hw/nvram/fw_cfg.h"
#include "pci.h"
#include "trace.h"
+#include "qemu/range.h"
/* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */
static bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device)
@@ -965,643 +962,6 @@ static void vfio_probe_rtl8168_bar2_quirk(VFIOPCIDevice *vdev, int nr)
}
/*
- * Intel IGD support
- *
- * Obviously IGD is not a discrete device, this is evidenced not only by it
- * being integrated into the CPU, but by the various chipset and BIOS
- * dependencies that it brings along with it. Intel is trying to move away
- * from this and Broadwell and newer devices can run in what Intel calls
- * "Universal Pass-Through" mode, or UPT. Theoretically in UPT mode, nothing
- * more is required beyond assigning the IGD device to a VM. There are
- * however support limitations to this mode. It only supports IGD as a
- * secondary graphics device in the VM and it doesn't officially support any
- * physical outputs.
- *
- * The code here attempts to enable what we'll call legacy mode assignment,
- * IGD retains most of the capabilities we expect for it to have on bare
- * metal. To enable this mode, the IGD device must be assigned to the VM
- * at PCI address 00:02.0, it must have a ROM, it very likely needs VGA
- * support, we must have VM BIOS support for reserving and populating some
- * of the required tables, and we need to tweak the chipset with revisions
- * and IDs and an LPC/ISA bridge device. The intention is to make all of
- * this happen automatically by installing the device at the correct VM PCI
- * bus address. If any of the conditions are not met, we cross our fingers
- * and hope the user knows better.
- *
- * NB - It is possible to enable physical outputs in UPT mode by supplying
- * an OpRegion table. We don't do this by default because the guest driver
- * behaves differently if an OpRegion is provided and no monitor is attached
- * vs no OpRegion and a monitor being attached or not. Effectively, if a
- * headless setup is desired, the OpRegion gets in the way of that.
- */
-
-/*
- * This presumes the device is already known to be an Intel VGA device, so we
- * take liberties in which device ID bits match which generation. This should
- * not be taken as an indication that all the devices are supported, or even
- * supportable, some of them don't even support VT-d.
- * See linux:include/drm/i915_pciids.h for IDs.
- */
-static int igd_gen(VFIOPCIDevice *vdev)
-{
- if ((vdev->device_id & 0xfff) == 0xa84) {
- return 8; /* Broxton */
- }
-
- switch (vdev->device_id & 0xff00) {
- /* Old, untested, unavailable, unknown */
- case 0x0000:
- case 0x2500:
- case 0x2700:
- case 0x2900:
- case 0x2a00:
- case 0x2e00:
- case 0x3500:
- case 0xa000:
- return -1;
- /* SandyBridge, IvyBridge, ValleyView, Haswell */
- case 0x0100:
- case 0x0400:
- case 0x0a00:
- case 0x0c00:
- case 0x0d00:
- case 0x0f00:
- return 6;
- /* BroadWell, CherryView, SkyLake, KabyLake */
- case 0x1600:
- case 0x1900:
- case 0x2200:
- case 0x5900:
- return 8;
- }
-
- return 8; /* Assume newer is compatible */
-}
-
-typedef struct VFIOIGDQuirk {
- struct VFIOPCIDevice *vdev;
- uint32_t index;
-} VFIOIGDQuirk;
-
-#define IGD_GMCH 0x50 /* Graphics Control Register */
-#define IGD_BDSM 0x5c /* Base Data of Stolen Memory */
-#define IGD_ASLS 0xfc /* ASL Storage Register */
-
-/*
- * The OpRegion includes the Video BIOS Table, which seems important for
- * telling the driver what sort of outputs it has. Without this, the device
- * may work in the guest, but we may not get output. This also requires BIOS
- * support to reserve and populate a section of guest memory sufficient for
- * the table and to write the base address of that memory to the ASLS register
- * of the IGD device.
- */
-int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
- struct vfio_region_info *info)
-{
- int ret;
-
- vdev->igd_opregion = g_malloc0(info->size);
- ret = pread(vdev->vbasedev.fd, vdev->igd_opregion,
- info->size, info->offset);
- if (ret != info->size) {
- error_report("vfio: Error reading IGD OpRegion");
- g_free(vdev->igd_opregion);
- vdev->igd_opregion = NULL;
- return -EINVAL;
- }
-
- /*
- * Provide fw_cfg with a copy of the OpRegion which the VM firmware is to
- * allocate 32bit reserved memory for, copy these contents into, and write
- * the reserved memory base address to the device ASLS register at 0xFC.
- * Alignment of this reserved region seems flexible, but using a 4k page
- * alignment seems to work well. This interface assumes a single IGD
- * device, which may be at VM address 00:02.0 in legacy mode or another
- * address in UPT mode.
- *
- * NB, there may be future use cases discovered where the VM should have
- * direct interaction with the host OpRegion, in which case the write to
- * the ASLS register would trigger MemoryRegion setup to enable that.
- */
- fw_cfg_add_file(fw_cfg_find(), "etc/igd-opregion",
- vdev->igd_opregion, info->size);
-
- trace_vfio_pci_igd_opregion_enabled(vdev->vbasedev.name);
-
- pci_set_long(vdev->pdev.config + IGD_ASLS, 0);
- pci_set_long(vdev->pdev.wmask + IGD_ASLS, ~0);
- pci_set_long(vdev->emulated_config_bits + IGD_ASLS, ~0);
-
- return 0;
-}
-
-/*
- * The rather short list of registers that we copy from the host devices.
- * The LPC/ISA bridge values are definitely needed to support the vBIOS, the
- * host bridge values may or may not be needed depending on the guest OS.
- * Since we're only munging revision and subsystem values on the host bridge,
- * we don't require our own device. The LPC/ISA bridge needs to be our very
- * own though.
- */
-typedef struct {
- uint8_t offset;
- uint8_t len;
-} IGDHostInfo;
-
-static const IGDHostInfo igd_host_bridge_infos[] = {
- {PCI_REVISION_ID, 2},
- {PCI_SUBSYSTEM_VENDOR_ID, 2},
- {PCI_SUBSYSTEM_ID, 2},
-};
-
-static const IGDHostInfo igd_lpc_bridge_infos[] = {
- {PCI_VENDOR_ID, 2},
- {PCI_DEVICE_ID, 2},
- {PCI_REVISION_ID, 2},
- {PCI_SUBSYSTEM_VENDOR_ID, 2},
- {PCI_SUBSYSTEM_ID, 2},
-};
-
-static int vfio_pci_igd_copy(VFIOPCIDevice *vdev, PCIDevice *pdev,
- struct vfio_region_info *info,
- const IGDHostInfo *list, int len)
-{
- int i, ret;
-
- for (i = 0; i < len; i++) {
- ret = pread(vdev->vbasedev.fd, pdev->config + list[i].offset,
- list[i].len, info->offset + list[i].offset);
- if (ret != list[i].len) {
- error_report("IGD copy failed: %m");
- return -errno;
- }
- }
-
- return 0;
-}
-
-/*
- * Stuff a few values into the host bridge.
- */
-static int vfio_pci_igd_host_init(VFIOPCIDevice *vdev,
- struct vfio_region_info *info)
-{
- PCIBus *bus;
- PCIDevice *host_bridge;
- int ret;
-
- bus = pci_device_root_bus(&vdev->pdev);
- host_bridge = pci_find_device(bus, 0, PCI_DEVFN(0, 0));
-
- if (!host_bridge) {
- error_report("Can't find host bridge");
- return -ENODEV;
- }
-
- ret = vfio_pci_igd_copy(vdev, host_bridge, info, igd_host_bridge_infos,
- ARRAY_SIZE(igd_host_bridge_infos));
- if (!ret) {
- trace_vfio_pci_igd_host_bridge_enabled(vdev->vbasedev.name);
- }
-
- return ret;
-}
-
-/*
- * IGD LPC/ISA bridge support code. The vBIOS needs this, but we can't write
- * arbitrary values into just any bridge, so we must create our own. We try
- * to handle if the user has created it for us, which they might want to do
- * to enable multifuction so we don't occupy the whole PCI slot.
- */
-static void vfio_pci_igd_lpc_bridge_realize(PCIDevice *pdev, Error **errp)
-{
- if (pdev->devfn != PCI_DEVFN(0x1f, 0)) {
- error_setg(errp, "VFIO dummy ISA/LPC bridge must have address 1f.0");
- }
-}
-
-static void vfio_pci_igd_lpc_bridge_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
- dc->desc = "VFIO dummy ISA/LPC bridge for IGD assignment";
- dc->hotpluggable = false;
- k->realize = vfio_pci_igd_lpc_bridge_realize;
- k->class_id = PCI_CLASS_BRIDGE_ISA;
-}
-
-static TypeInfo vfio_pci_igd_lpc_bridge_info = {
- .name = "vfio-pci-igd-lpc-bridge",
- .parent = TYPE_PCI_DEVICE,
- .class_init = vfio_pci_igd_lpc_bridge_class_init,
-};
-
-static void vfio_pci_igd_register_types(void)
-{
- type_register_static(&vfio_pci_igd_lpc_bridge_info);
-}
-
-type_init(vfio_pci_igd_register_types)
-
-static int vfio_pci_igd_lpc_init(VFIOPCIDevice *vdev,
- struct vfio_region_info *info)
-{
- PCIDevice *lpc_bridge;
- int ret;
-
- lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),
- 0, PCI_DEVFN(0x1f, 0));
- if (!lpc_bridge) {
- lpc_bridge = pci_create_simple(pci_device_root_bus(&vdev->pdev),
- PCI_DEVFN(0x1f, 0), "vfio-pci-igd-lpc-bridge");
- }
-
- ret = vfio_pci_igd_copy(vdev, lpc_bridge, info, igd_lpc_bridge_infos,
- ARRAY_SIZE(igd_lpc_bridge_infos));
- if (!ret) {
- trace_vfio_pci_igd_lpc_bridge_enabled(vdev->vbasedev.name);
- }
-
- return ret;
-}
-
-/*
- * IGD Gen8 and newer support up to 8MB for the GTT and use a 64bit PTE
- * entry, older IGDs use 2MB and 32bit. Each PTE maps a 4k page. Therefore
- * we either have 2M/4k * 4 = 2k or 8M/4k * 8 = 16k as the maximum iobar index
- * for programming the GTT.
- *
- * See linux:include/drm/i915_drm.h for shift and mask values.
- */
-static int vfio_igd_gtt_max(VFIOPCIDevice *vdev)
-{
- uint32_t gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, sizeof(gmch));
- int ggms, gen = igd_gen(vdev);
-
- gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, sizeof(gmch));
- ggms = (gmch >> (gen < 8 ? 8 : 6)) & 0x3;
- if (gen > 6) {
- ggms = 1 << ggms;
- }
-
- ggms *= 1024 * 1024;
-
- return (ggms / (4 * 1024)) * (gen < 8 ? 4 : 8);
-}
-
-/*
- * The IGD ROM will make use of stolen memory (GGMS) for support of VESA modes.
- * Somehow the host stolen memory range is used for this, but how the ROM gets
- * it is a mystery, perhaps it's hardcoded into the ROM. Thankfully though, it
- * reprograms the GTT through the IOBAR where we can trap it and transpose the
- * programming to the VM allocated buffer. That buffer gets reserved by the VM
- * firmware via the fw_cfg entry added below. Here we're just monitoring the
- * IOBAR address and data registers to detect a write sequence targeting the
- * GTTADR. This code is developed by observed behavior and doesn't have a
- * direct spec reference, unfortunately.
- */
-static uint64_t vfio_igd_quirk_data_read(void *opaque,
- hwaddr addr, unsigned size)
-{
- VFIOIGDQuirk *igd = opaque;
- VFIOPCIDevice *vdev = igd->vdev;
-
- igd->index = ~0;
-
- return vfio_region_read(&vdev->bars[4].region, addr + 4, size);
-}
-
-static void vfio_igd_quirk_data_write(void *opaque, hwaddr addr,
- uint64_t data, unsigned size)
-{
- VFIOIGDQuirk *igd = opaque;
- VFIOPCIDevice *vdev = igd->vdev;
- uint64_t val = data;
- int gen = igd_gen(vdev);
-
- /*
- * Programming the GGMS starts at index 0x1 and uses every 4th index (ie.
- * 0x1, 0x5, 0x9, 0xd,...). For pre-Gen8 each 4-byte write is a whole PTE
- * entry, with 0th bit enable set. For Gen8 and up, PTEs are 64bit, so
- * entries 0x5 & 0xd are the high dword, in our case zero. Each PTE points
- * to a 4k page, which we translate to a page from the VM allocated region,
- * pointed to by the BDSM register. If this is not set, we fail.
- *
- * We trap writes to the full configured GTT size, but we typically only
- * see the vBIOS writing up to (nearly) the 1MB barrier. In fact it often
- * seems to miss the last entry for an even 1MB GTT. Doing a gratuitous
- * write of that last entry does work, but is hopefully unnecessary since
- * we clear the previous GTT on initialization.
- */
- if ((igd->index % 4 == 1) && igd->index < vfio_igd_gtt_max(vdev)) {
- if (gen < 8 || (igd->index % 8 == 1)) {
- uint32_t base;
-
- base = pci_get_long(vdev->pdev.config + IGD_BDSM);
- if (!base) {
- hw_error("vfio-igd: Guest attempted to program IGD GTT before "
- "BIOS reserved stolen memory. Unsupported BIOS?");
- }
-
- val = base | (data & ((1 << 20) - 1));
- } else {
- val = 0; /* upper 32bits of pte, we only enable below 4G PTEs */
- }
-
- trace_vfio_pci_igd_bar4_write(vdev->vbasedev.name,
- igd->index, data, val);
- }
-
- vfio_region_write(&vdev->bars[4].region, addr + 4, val, size);
-
- igd->index = ~0;
-}
-
-static const MemoryRegionOps vfio_igd_data_quirk = {
- .read = vfio_igd_quirk_data_read,
- .write = vfio_igd_quirk_data_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static uint64_t vfio_igd_quirk_index_read(void *opaque,
- hwaddr addr, unsigned size)
-{
- VFIOIGDQuirk *igd = opaque;
- VFIOPCIDevice *vdev = igd->vdev;
-
- igd->index = ~0;
-
- return vfio_region_read(&vdev->bars[4].region, addr, size);
-}
-
-static void vfio_igd_quirk_index_write(void *opaque, hwaddr addr,
- uint64_t data, unsigned size)
-{
- VFIOIGDQuirk *igd = opaque;
- VFIOPCIDevice *vdev = igd->vdev;
-
- igd->index = data;
-
- vfio_region_write(&vdev->bars[4].region, addr, data, size);
-}
-
-static const MemoryRegionOps vfio_igd_index_quirk = {
- .read = vfio_igd_quirk_index_read,
- .write = vfio_igd_quirk_index_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
-{
- struct vfio_region_info *rom = NULL, *opregion = NULL,
- *host = NULL, *lpc = NULL;
- VFIOQuirk *quirk;
- VFIOIGDQuirk *igd;
- PCIDevice *lpc_bridge;
- int i, ret, ggms_mb, gms_mb = 0, gen;
- uint64_t *bdsm_size;
- uint32_t gmch;
- uint16_t cmd_orig, cmd;
-
- /*
- * This must be an Intel VGA device at address 00:02.0 for us to even
- * consider enabling legacy mode. The vBIOS has dependencies on the
- * PCI bus address.
- */
- if (!vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||
- !vfio_is_vga(vdev) || nr != 4 ||
- &vdev->pdev != pci_find_device(pci_device_root_bus(&vdev->pdev),
- 0, PCI_DEVFN(0x2, 0))) {
- return;
- }
-
- /*
- * We need to create an LPC/ISA bridge at PCI bus address 00:1f.0 that we
- * can stuff host values into, so if there's already one there and it's not
- * one we can hack on, legacy mode is no-go. Sorry Q35.
- */
- lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),
- 0, PCI_DEVFN(0x1f, 0));
- if (lpc_bridge && !object_dynamic_cast(OBJECT(lpc_bridge),
- "vfio-pci-igd-lpc-bridge")) {
- error_report("IGD device %s cannot support legacy mode due to existing "
- "devices at address 1f.0", vdev->vbasedev.name);
- return;
- }
-
- /*
- * IGD is not a standard, they like to change their specs often. We
- * only attempt to support back to SandBridge and we hope that newer
- * devices maintain compatibility with generation 8.
- */
- gen = igd_gen(vdev);
- if (gen != 6 && gen != 8) {
- error_report("IGD device %s is unsupported in legacy mode, "
- "try SandyBridge or newer", vdev->vbasedev.name);
- return;
- }
-
- /*
- * Most of what we're doing here is to enable the ROM to run, so if
- * there's no ROM, there's no point in setting up this quirk.
- * NB. We only seem to get BIOS ROMs, so a UEFI VM would need CSM support.
- */
- ret = vfio_get_region_info(&vdev->vbasedev,
- VFIO_PCI_ROM_REGION_INDEX, &rom);
- if ((ret || !rom->size) && !vdev->pdev.romfile) {
- error_report("IGD device %s has no ROM, legacy mode disabled",
- vdev->vbasedev.name);
- goto out;
- }
-
- /*
- * Ignore the hotplug corner case, mark the ROM failed, we can't
- * create the devices we need for legacy mode in the hotplug scenario.
- */
- if (vdev->pdev.qdev.hotplugged) {
- error_report("IGD device %s hotplugged, ROM disabled, "
- "legacy mode disabled", vdev->vbasedev.name);
- vdev->rom_read_failed = true;
- goto out;
- }
-
- /*
- * Check whether we have all the vfio device specific regions to
- * support legacy mode (added in Linux v4.6). If not, bail.
- */
- ret = vfio_get_dev_region_info(&vdev->vbasedev,
- VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
- VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);
- if (ret) {
- error_report("IGD device %s does not support OpRegion access,"
- "legacy mode disabled", vdev->vbasedev.name);
- goto out;
- }
-
- ret = vfio_get_dev_region_info(&vdev->vbasedev,
- VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
- VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG, &host);
- if (ret) {
- error_report("IGD device %s does not support host bridge access,"
- "legacy mode disabled", vdev->vbasedev.name);
- goto out;
- }
-
- ret = vfio_get_dev_region_info(&vdev->vbasedev,
- VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
- VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG, &lpc);
- if (ret) {
- error_report("IGD device %s does not support LPC bridge access,"
- "legacy mode disabled", vdev->vbasedev.name);
- goto out;
- }
-
- gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, 4);
-
- /*
- * If IGD VGA Disable is clear (expected) and VGA is not already enabled,
- * try to enable it. Probably shouldn't be using legacy mode without VGA,
- * but also no point in us enabling VGA if disabled in hardware.
- */
- if (!(gmch & 0x2) && !vdev->vga && vfio_populate_vga(vdev)) {
- error_report("IGD device %s failed to enable VGA access, "
- "legacy mode disabled", vdev->vbasedev.name);
- goto out;
- }
-
- /* Create our LPC/ISA bridge */
- ret = vfio_pci_igd_lpc_init(vdev, lpc);
- if (ret) {
- error_report("IGD device %s failed to create LPC bridge, "
- "legacy mode disabled", vdev->vbasedev.name);
- goto out;
- }
-
- /* Stuff some host values into the VM PCI host bridge */
- ret = vfio_pci_igd_host_init(vdev, host);
- if (ret) {
- error_report("IGD device %s failed to modify host bridge, "
- "legacy mode disabled", vdev->vbasedev.name);
- goto out;
- }
-
- /* Setup OpRegion access */
- ret = vfio_pci_igd_opregion_init(vdev, opregion);
- if (ret) {
- error_report("IGD device %s failed to setup OpRegion, "
- "legacy mode disabled", vdev->vbasedev.name);
- goto out;
- }
-
- /* Setup our quirk to munge GTT addresses to the VM allocated buffer */
- quirk = g_malloc0(sizeof(*quirk));
- quirk->mem = g_new0(MemoryRegion, 2);
- quirk->nr_mem = 2;
- igd = quirk->data = g_malloc0(sizeof(*igd));
- igd->vdev = vdev;
- igd->index = ~0;
-
- memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_igd_index_quirk,
- igd, "vfio-igd-index-quirk", 4);
- memory_region_add_subregion_overlap(vdev->bars[nr].region.mem,
- 0, &quirk->mem[0], 1);
-
- memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_igd_data_quirk,
- igd, "vfio-igd-data-quirk", 4);
- memory_region_add_subregion_overlap(vdev->bars[nr].region.mem,
- 4, &quirk->mem[1], 1);
-
- QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
-
- /* Determine the size of stolen memory needed for GTT */
- ggms_mb = (gmch >> (gen < 8 ? 8 : 6)) & 0x3;
- if (gen > 6) {
- ggms_mb = 1 << ggms_mb;
- }
-
- /*
- * Assume we have no GMS memory, but allow it to be overrided by device
- * option (experimental). The spec doesn't actually allow zero GMS when
- * when IVD (IGD VGA Disable) is clear, but the claim is that it's unused,
- * so let's not waste VM memory for it.
- */
- gmch &= ~((gen < 8 ? 0x1f : 0xff) << (gen < 8 ? 3 : 8));
-
- if (vdev->igd_gms) {
- if (vdev->igd_gms <= 0x10) {
- gms_mb = vdev->igd_gms * 32;
- gmch |= vdev->igd_gms << (gen < 8 ? 3 : 8);
- } else {
- error_report("Unsupported IGD GMS value 0x%x", vdev->igd_gms);
- vdev->igd_gms = 0;
- }
- }
-
- /*
- * Request reserved memory for stolen memory via fw_cfg. VM firmware
- * must allocate a 1MB aligned reserved memory region below 4GB with
- * the requested size (in bytes) for use by the Intel PCI class VGA
- * device at VM address 00:02.0. The base address of this reserved
- * memory region must be written to the device BDSM regsiter at PCI
- * config offset 0x5C.
- */
- bdsm_size = g_malloc(sizeof(*bdsm_size));
- *bdsm_size = cpu_to_le64((ggms_mb + gms_mb) * 1024 * 1024);
- fw_cfg_add_file(fw_cfg_find(), "etc/igd-bdsm-size",
- bdsm_size, sizeof(*bdsm_size));
-
- /* GMCH is read-only, emulated */
- pci_set_long(vdev->pdev.config + IGD_GMCH, gmch);
- pci_set_long(vdev->pdev.wmask + IGD_GMCH, 0);
- pci_set_long(vdev->emulated_config_bits + IGD_GMCH, ~0);
-
- /* BDSM is read-write, emulated. The BIOS needs to be able to write it */
- pci_set_long(vdev->pdev.config + IGD_BDSM, 0);
- pci_set_long(vdev->pdev.wmask + IGD_BDSM, ~0);
- pci_set_long(vdev->emulated_config_bits + IGD_BDSM, ~0);
-
- /*
- * This IOBAR gives us access to GTTADR, which allows us to write to
- * the GTT itself. So let's go ahead and write zero to all the GTT
- * entries to avoid spurious DMA faults. Be sure I/O access is enabled
- * before talking to the device.
- */
- if (pread(vdev->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),
- vdev->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {
- error_report("IGD device %s - failed to read PCI command register",
- vdev->vbasedev.name);
- }
-
- cmd = cmd_orig | PCI_COMMAND_IO;
-
- if (pwrite(vdev->vbasedev.fd, &cmd, sizeof(cmd),
- vdev->config_offset + PCI_COMMAND) != sizeof(cmd)) {
- error_report("IGD device %s - failed to write PCI command register",
- vdev->vbasedev.name);
- }
-
- for (i = 1; i < vfio_igd_gtt_max(vdev); i += 4) {
- vfio_region_write(&vdev->bars[4].region, 0, i, 4);
- vfio_region_write(&vdev->bars[4].region, 4, 0, 4);
- }
-
- if (pwrite(vdev->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),
- vdev->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {
- error_report("IGD device %s - failed to restore PCI command register",
- vdev->vbasedev.name);
- }
-
- trace_vfio_pci_igd_bdsm_enabled(vdev->vbasedev.name, ggms_mb + gms_mb);
-
-out:
- g_free(rom);
- g_free(opregion);
- g_free(host);
- g_free(lpc);
-}
-
-/*
* Common quirk probe entry points.
*/
void vfio_vga_quirk_setup(VFIOPCIDevice *vdev)
@@ -1650,7 +1010,6 @@ void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr)
vfio_probe_nvidia_bar5_quirk(vdev, nr);
vfio_probe_nvidia_bar0_quirk(vdev, nr);
vfio_probe_rtl8168_bar2_quirk(vdev, nr);
- vfio_probe_igd_bar4_quirk(vdev, nr);
}
void vfio_bar_quirk_exit(VFIOPCIDevice *vdev, int nr)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 7bfa17ce3..d091d8cf0 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include <linux/vfio.h>
#include <sys/ioctl.h>
+#include <sys/mman.h>
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
@@ -31,7 +32,6 @@
#include "sysemu/sysemu.h"
#include "pci.h"
#include "trace.h"
-#include "qapi/error.h"
#define MSIX_CAP_LENGTH 12
@@ -417,11 +417,11 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
}
static void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
- int vector_n, bool msix)
+ MSIMessage *msg, bool msix)
{
int virq;
- if ((msix && vdev->no_kvm_msix) || (!msix && vdev->no_kvm_msi)) {
+ if ((msix && vdev->no_kvm_msix) || (!msix && vdev->no_kvm_msi) || !msg) {
return;
}
@@ -429,7 +429,7 @@ static void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
return;
}
- virq = kvm_irqchip_add_msi_route(kvm_state, vector_n, &vdev->pdev);
+ virq = kvm_irqchip_add_msi_route(kvm_state, *msg, &vdev->pdev);
if (virq < 0) {
event_notifier_cleanup(&vector->kvm_interrupt);
return;
@@ -458,7 +458,6 @@ static void vfio_update_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage msg,
PCIDevice *pdev)
{
kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg, pdev);
- kvm_irqchip_commit_routes(kvm_state);
}
static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
@@ -496,7 +495,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
vfio_update_kvm_msi_virq(vector, *msg, pdev);
}
} else {
- vfio_add_kvm_msi_virq(vdev, vector, nr, true);
+ vfio_add_kvm_msi_virq(vdev, vector, msg, true);
}
/*
@@ -640,6 +639,7 @@ retry:
for (i = 0; i < vdev->nr_vectors; i++) {
VFIOMSIVector *vector = &vdev->msi_vectors[i];
+ MSIMessage msg = msi_get_message(&vdev->pdev, i);
vector->vdev = vdev;
vector->virq = -1;
@@ -656,7 +656,7 @@ retry:
* Attempt to enable route through KVM irqchip,
* default to userspace handling if unavailable.
*/
- vfio_add_kvm_msi_virq(vdev, vector, i, false);
+ vfio_add_kvm_msi_virq(vdev, vector, &msg, false);
}
/* Set interrupt type prior to possible interrupts */
@@ -1171,7 +1171,6 @@ static int vfio_msi_setup(VFIOPCIDevice *vdev, int pos)
uint16_t ctrl;
bool msi_64bit, msi_maskbit;
int ret, entries;
- Error *err = NULL;
if (pread(vdev->vbasedev.fd, &ctrl, sizeof(ctrl),
vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) {
@@ -1185,13 +1184,12 @@ static int vfio_msi_setup(VFIOPCIDevice *vdev, int pos)
trace_vfio_msi_setup(vdev->vbasedev.name, pos);
- ret = msi_init(&vdev->pdev, pos, entries, msi_64bit, msi_maskbit, &err);
+ ret = msi_init(&vdev->pdev, pos, entries, msi_64bit, msi_maskbit);
if (ret < 0) {
if (ret == -ENOTSUP) {
return 0;
}
- error_prepend(&err, "vfio: msi_init failed: ");
- error_report_err(err);
+ error_report("vfio: msi_init failed");
return ret;
}
vdev->msi_cap_size = 0xa + (msi_maskbit ? 0xa : 0) + (msi_64bit ? 0x4 : 0);
@@ -1442,6 +1440,8 @@ static void vfio_bar_setup(VFIOPCIDevice *vdev, int nr)
vdev->vbasedev.name, nr);
}
+ vfio_bar_quirk_setup(vdev, nr);
+
pci_register_bar(&vdev->pdev, nr, type, bar->region.mem);
}
@@ -1452,6 +1452,29 @@ static void vfio_bars_setup(VFIOPCIDevice *vdev)
for (i = 0; i < PCI_ROM_SLOT; i++) {
vfio_bar_setup(vdev, i);
}
+
+ if (vdev->vga) {
+ memory_region_init_io(&vdev->vga->region[QEMU_PCI_VGA_MEM].mem,
+ OBJECT(vdev), &vfio_vga_ops,
+ &vdev->vga->region[QEMU_PCI_VGA_MEM],
+ "vfio-vga-mmio@0xa0000",
+ QEMU_PCI_VGA_MEM_SIZE);
+ memory_region_init_io(&vdev->vga->region[QEMU_PCI_VGA_IO_LO].mem,
+ OBJECT(vdev), &vfio_vga_ops,
+ &vdev->vga->region[QEMU_PCI_VGA_IO_LO],
+ "vfio-vga-io@0x3b0",
+ QEMU_PCI_VGA_IO_LO_SIZE);
+ memory_region_init_io(&vdev->vga->region[QEMU_PCI_VGA_IO_HI].mem,
+ OBJECT(vdev), &vfio_vga_ops,
+ &vdev->vga->region[QEMU_PCI_VGA_IO_HI],
+ "vfio-vga-io@0x3c0",
+ QEMU_PCI_VGA_IO_HI_SIZE);
+
+ pci_register_vga(&vdev->pdev, &vdev->vga->region[QEMU_PCI_VGA_MEM].mem,
+ &vdev->vga->region[QEMU_PCI_VGA_IO_LO].mem,
+ &vdev->vga->region[QEMU_PCI_VGA_IO_HI].mem);
+ vfio_vga_quirk_setup(vdev);
+ }
}
static void vfio_bars_exit(VFIOPCIDevice *vdev)
@@ -1505,21 +1528,6 @@ static uint8_t vfio_std_cap_max_size(PCIDevice *pdev, uint8_t pos)
return next - pos;
}
-
-static uint16_t vfio_ext_cap_max_size(const uint8_t *config, uint16_t pos)
-{
- uint16_t tmp, next = PCIE_CONFIG_SPACE_SIZE;
-
- for (tmp = PCI_CONFIG_SPACE_SIZE; tmp;
- tmp = PCI_EXT_CAP_NEXT(pci_get_long(config + tmp))) {
- if (tmp > pos && tmp < next) {
- next = tmp;
- }
- }
-
- return next - pos;
-}
-
static void vfio_set_word_bits(uint8_t *buf, uint16_t val, uint16_t mask)
{
pci_set_word(buf, (pci_get_word(buf) & ~mask) | val);
@@ -1767,101 +1775,16 @@ static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos)
return 0;
}
-static int vfio_add_ext_cap(VFIOPCIDevice *vdev)
-{
- PCIDevice *pdev = &vdev->pdev;
- uint32_t header;
- uint16_t cap_id, next, size;
- uint8_t cap_ver;
- uint8_t *config;
-
- /* Only add extended caps if we have them and the guest can see them */
- if (!pci_is_express(pdev) || !pci_bus_is_express(pdev->bus) ||
- !pci_get_long(pdev->config + PCI_CONFIG_SPACE_SIZE)) {
- return 0;
- }
-
- /*
- * pcie_add_capability always inserts the new capability at the tail
- * of the chain. Therefore to end up with a chain that matches the
- * physical device, we cache the config space to avoid overwriting
- * the original config space when we parse the extended capabilities.
- */
- config = g_memdup(pdev->config, vdev->config_size);
-
- /*
- * Extended capabilities are chained with each pointing to the next, so we
- * can drop anything other than the head of the chain simply by modifying
- * the previous next pointer. For the head of the chain, we can modify the
- * capability ID to something that cannot match a valid capability. ID
- * 0 is reserved for this since absence of capabilities is indicated by
- * 0 for the ID, version, AND next pointer. However, pcie_add_capability()
- * uses ID 0 as reserved for list management and will incorrectly match and
- * assert if we attempt to pre-load the head of the chain with with this
- * ID. Use ID 0xFFFF temporarily since it is also seems to be reserved in
- * part for identifying absence of capabilities in a root complex register
- * block. If the ID still exists after adding capabilities, switch back to
- * zero. We'll mark this entire first dword as emulated for this purpose.
- */
- pci_set_long(pdev->config + PCI_CONFIG_SPACE_SIZE,
- PCI_EXT_CAP(0xFFFF, 0, 0));
- pci_set_long(pdev->wmask + PCI_CONFIG_SPACE_SIZE, 0);
- pci_set_long(vdev->emulated_config_bits + PCI_CONFIG_SPACE_SIZE, ~0);
-
- for (next = PCI_CONFIG_SPACE_SIZE; next;
- next = PCI_EXT_CAP_NEXT(pci_get_long(config + next))) {
- header = pci_get_long(config + next);
- cap_id = PCI_EXT_CAP_ID(header);
- cap_ver = PCI_EXT_CAP_VER(header);
-
- /*
- * If it becomes important to configure extended capabilities to their
- * actual size, use this as the default when it's something we don't
- * recognize. Since QEMU doesn't actually handle many of the config
- * accesses, exact size doesn't seem worthwhile.
- */
- size = vfio_ext_cap_max_size(config, next);
-
- /* Use emulated next pointer to allow dropping extended caps */
- pci_long_test_and_set_mask(vdev->emulated_config_bits + next,
- PCI_EXT_CAP_NEXT_MASK);
-
- switch (cap_id) {
- case PCI_EXT_CAP_ID_SRIOV: /* Read-only VF BARs confuse OVMF */
- case PCI_EXT_CAP_ID_ARI: /* XXX Needs next function virtualization */
- trace_vfio_add_ext_cap_dropped(vdev->vbasedev.name, cap_id, next);
- break;
- default:
- pcie_add_capability(pdev, cap_id, cap_ver, next, size);
- }
-
- }
-
- /* Cleanup chain head ID if necessary */
- if (pci_get_word(pdev->config + PCI_CONFIG_SPACE_SIZE) == 0xFFFF) {
- pci_set_word(pdev->config + PCI_CONFIG_SPACE_SIZE, 0);
- }
-
- g_free(config);
- return 0;
-}
-
static int vfio_add_capabilities(VFIOPCIDevice *vdev)
{
PCIDevice *pdev = &vdev->pdev;
- int ret;
if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST) ||
!pdev->config[PCI_CAPABILITY_LIST]) {
return 0; /* Nothing to add */
}
- ret = vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]);
- if (ret) {
- return ret;
- }
-
- return vfio_add_ext_cap(vdev);
+ return vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]);
}
static void vfio_pci_pre_reset(VFIOPCIDevice *vdev)
@@ -2138,61 +2061,42 @@ int vfio_populate_vga(VFIOPCIDevice *vdev)
struct vfio_region_info *reg_info;
int ret;
- ret = vfio_get_region_info(vbasedev, VFIO_PCI_VGA_REGION_INDEX, &reg_info);
- if (ret) {
- return ret;
- }
-
- if (!(reg_info->flags & VFIO_REGION_INFO_FLAG_READ) ||
- !(reg_info->flags & VFIO_REGION_INFO_FLAG_WRITE) ||
- reg_info->size < 0xbffff + 1) {
- error_report("vfio: Unexpected VGA info, flags 0x%lx, size 0x%lx",
- (unsigned long)reg_info->flags,
- (unsigned long)reg_info->size);
- g_free(reg_info);
- return -EINVAL;
- }
-
- vdev->vga = g_new0(VFIOVGA, 1);
-
- vdev->vga->fd_offset = reg_info->offset;
- vdev->vga->fd = vdev->vbasedev.fd;
-
- g_free(reg_info);
+ if (vbasedev->num_regions > VFIO_PCI_VGA_REGION_INDEX) {
+ ret = vfio_get_region_info(vbasedev,
+ VFIO_PCI_VGA_REGION_INDEX, &reg_info);
+ if (ret) {
+ return ret;
+ }
- vdev->vga->region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
- vdev->vga->region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
- QLIST_INIT(&vdev->vga->region[QEMU_PCI_VGA_MEM].quirks);
+ if (!(reg_info->flags & VFIO_REGION_INFO_FLAG_READ) ||
+ !(reg_info->flags & VFIO_REGION_INFO_FLAG_WRITE) ||
+ reg_info->size < 0xbffff + 1) {
+ error_report("vfio: Unexpected VGA info, flags 0x%lx, size 0x%lx",
+ (unsigned long)reg_info->flags,
+ (unsigned long)reg_info->size);
+ g_free(reg_info);
+ return -EINVAL;
+ }
- memory_region_init_io(&vdev->vga->region[QEMU_PCI_VGA_MEM].mem,
- OBJECT(vdev), &vfio_vga_ops,
- &vdev->vga->region[QEMU_PCI_VGA_MEM],
- "vfio-vga-mmio@0xa0000",
- QEMU_PCI_VGA_MEM_SIZE);
+ vdev->vga = g_new0(VFIOVGA, 1);
- vdev->vga->region[QEMU_PCI_VGA_IO_LO].offset = QEMU_PCI_VGA_IO_LO_BASE;
- vdev->vga->region[QEMU_PCI_VGA_IO_LO].nr = QEMU_PCI_VGA_IO_LO;
- QLIST_INIT(&vdev->vga->region[QEMU_PCI_VGA_IO_LO].quirks);
+ vdev->vga->fd_offset = reg_info->offset;
+ vdev->vga->fd = vdev->vbasedev.fd;
- memory_region_init_io(&vdev->vga->region[QEMU_PCI_VGA_IO_LO].mem,
- OBJECT(vdev), &vfio_vga_ops,
- &vdev->vga->region[QEMU_PCI_VGA_IO_LO],
- "vfio-vga-io@0x3b0",
- QEMU_PCI_VGA_IO_LO_SIZE);
+ g_free(reg_info);
- vdev->vga->region[QEMU_PCI_VGA_IO_HI].offset = QEMU_PCI_VGA_IO_HI_BASE;
- vdev->vga->region[QEMU_PCI_VGA_IO_HI].nr = QEMU_PCI_VGA_IO_HI;
- QLIST_INIT(&vdev->vga->region[QEMU_PCI_VGA_IO_HI].quirks);
+ vdev->vga->region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
+ vdev->vga->region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
+ QLIST_INIT(&vdev->vga->region[QEMU_PCI_VGA_MEM].quirks);
- memory_region_init_io(&vdev->vga->region[QEMU_PCI_VGA_IO_HI].mem,
- OBJECT(vdev), &vfio_vga_ops,
- &vdev->vga->region[QEMU_PCI_VGA_IO_HI],
- "vfio-vga-io@0x3c0",
- QEMU_PCI_VGA_IO_HI_SIZE);
+ vdev->vga->region[QEMU_PCI_VGA_IO_LO].offset = QEMU_PCI_VGA_IO_LO_BASE;
+ vdev->vga->region[QEMU_PCI_VGA_IO_LO].nr = QEMU_PCI_VGA_IO_LO;
+ QLIST_INIT(&vdev->vga->region[QEMU_PCI_VGA_IO_LO].quirks);
- pci_register_vga(&vdev->pdev, &vdev->vga->region[QEMU_PCI_VGA_MEM].mem,
- &vdev->vga->region[QEMU_PCI_VGA_IO_LO].mem,
- &vdev->vga->region[QEMU_PCI_VGA_IO_HI].mem);
+ vdev->vga->region[QEMU_PCI_VGA_IO_HI].offset = QEMU_PCI_VGA_IO_HI_BASE;
+ vdev->vga->region[QEMU_PCI_VGA_IO_HI].nr = QEMU_PCI_VGA_IO_HI;
+ QLIST_INIT(&vdev->vga->region[QEMU_PCI_VGA_IO_HI].quirks);
+ }
return 0;
}
@@ -2494,7 +2398,7 @@ static int vfio_initfn(PCIDevice *pdev)
ssize_t len;
struct stat st;
int groupid;
- int i, ret;
+ int ret;
if (!vdev->vbasedev.sysfsdev) {
vdev->vbasedev.sysfsdev =
@@ -2656,43 +2560,6 @@ static int vfio_initfn(PCIDevice *pdev)
goto out_teardown;
}
- if (vdev->vga) {
- vfio_vga_quirk_setup(vdev);
- }
-
- for (i = 0; i < PCI_ROM_SLOT; i++) {
- vfio_bar_quirk_setup(vdev, i);
- }
-
- if (!vdev->igd_opregion &&
- vdev->features & VFIO_FEATURE_ENABLE_IGD_OPREGION) {
- struct vfio_region_info *opregion;
-
- if (vdev->pdev.qdev.hotplugged) {
- error_report("Cannot support IGD OpRegion feature on hotplugged "
- "device %s", vdev->vbasedev.name);
- ret = -EINVAL;
- goto out_teardown;
- }
-
- ret = vfio_get_dev_region_info(&vdev->vbasedev,
- VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
- VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);
- if (ret) {
- error_report("Device %s does not support requested IGD OpRegion "
- "feature", vdev->vbasedev.name);
- goto out_teardown;
- }
-
- ret = vfio_pci_igd_opregion_init(vdev, opregion);
- g_free(opregion);
- if (ret) {
- error_report("Device %s IGD OpRegion initialization failed",
- vdev->vbasedev.name);
- goto out_teardown;
- }
- }
-
/* QEMU emulates all of MSI & MSIX */
if (pdev->cap_present & QEMU_PCI_CAP_MSIX) {
memset(vdev->emulated_config_bits + pdev->msix_cap, 0xff,
@@ -2736,13 +2603,6 @@ static void vfio_instance_finalize(Object *obj)
vfio_bars_finalize(vdev);
g_free(vdev->emulated_config_bits);
g_free(vdev->rom);
- /*
- * XXX Leaking igd_opregion is not an oversight, we can't remove the
- * fw_cfg entry therefore leaking this allocation seems like the safest
- * option.
- *
- * g_free(vdev->igd_opregion);
- */
vfio_put_device(vdev);
vfio_put_group(group);
}
@@ -2817,8 +2677,6 @@ static Property vfio_pci_dev_properties[] = {
VFIO_FEATURE_ENABLE_VGA_BIT, false),
DEFINE_PROP_BIT("x-req", VFIOPCIDevice, features,
VFIO_FEATURE_ENABLE_REQ_BIT, true),
- DEFINE_PROP_BIT("x-igd-opregion", VFIOPCIDevice, features,
- VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT, false),
DEFINE_PROP_BOOL("x-no-mmap", VFIOPCIDevice, vbasedev.no_mmap, false),
DEFINE_PROP_BOOL("x-no-kvm-intx", VFIOPCIDevice, no_kvm_intx, false),
DEFINE_PROP_BOOL("x-no-kvm-msi", VFIOPCIDevice, no_kvm_msi, false),
@@ -2829,7 +2687,6 @@ static Property vfio_pci_dev_properties[] = {
sub_vendor_id, PCI_ANY_ID),
DEFINE_PROP_UINT32("x-pci-sub-device-id", VFIOPCIDevice,
sub_device_id, PCI_ANY_ID),
- DEFINE_PROP_UINT32("x-igd-gms", VFIOPCIDevice, igd_gms, 0),
/*
* TODO - support passed fds... is this necessary?
* DEFINE_PROP_STRING("vfiofd", VFIOPCIDevice, vfiofd_name),
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index 7d482d9d2..72174b3dd 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -115,7 +115,6 @@ typedef struct VFIOPCIDevice {
int interrupt; /* Current interrupt type */
VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */
VFIOVGA *vga; /* 0xa0000, 0x3b0, 0x3c0 */
- void *igd_opregion;
PCIHostDeviceAddress host;
EventNotifier err_notifier;
EventNotifier req_notifier;
@@ -129,11 +128,7 @@ typedef struct VFIOPCIDevice {
#define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
#define VFIO_FEATURE_ENABLE_REQ_BIT 1
#define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT)
-#define VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT 2
-#define VFIO_FEATURE_ENABLE_IGD_OPREGION \
- (1 << VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT)
int32_t bootindex;
- uint32_t igd_gms;
uint8_t pm_cap;
bool pci_aer;
bool req_enabled;
@@ -163,7 +158,4 @@ void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev);
int vfio_populate_vga(VFIOPCIDevice *vdev);
-int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
- struct vfio_region_info *info);
-
#endif /* HW_VFIO_VFIO_PCI_H */
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index a559e7b65..1798a00a3 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -496,7 +496,7 @@ static int vfio_populate_device(VFIODevice *vbasedev)
irq.index = i;
ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);
if (ret) {
- error_report("vfio: error getting device %s irq info",
+ error_printf("vfio: error getting device %s irq info",
vbasedev->name);
goto irq_err;
} else {
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
deleted file mode 100644
index 7443d348d..000000000
--- a/hw/vfio/spapr.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * DMA memory preregistration
- *
- * Authors:
- * Alexey Kardashevskiy <aik@ozlabs.ru>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include <sys/ioctl.h>
-#include <linux/vfio.h>
-
-#include "hw/vfio/vfio-common.h"
-#include "hw/hw.h"
-#include "qemu/error-report.h"
-#include "trace.h"
-
-static bool vfio_prereg_listener_skipped_section(MemoryRegionSection *section)
-{
- if (memory_region_is_iommu(section->mr)) {
- hw_error("Cannot possibly preregister IOMMU memory");
- }
-
- return !memory_region_is_ram(section->mr) ||
- memory_region_is_skip_dump(section->mr);
-}
-
-static void *vfio_prereg_gpa_to_vaddr(MemoryRegionSection *section, hwaddr gpa)
-{
- return memory_region_get_ram_ptr(section->mr) +
- section->offset_within_region +
- (gpa - section->offset_within_address_space);
-}
-
-static void vfio_prereg_listener_region_add(MemoryListener *listener,
- MemoryRegionSection *section)
-{
- VFIOContainer *container = container_of(listener, VFIOContainer,
- prereg_listener);
- const hwaddr gpa = section->offset_within_address_space;
- hwaddr end;
- int ret;
- hwaddr page_mask = qemu_real_host_page_mask;
- struct vfio_iommu_spapr_register_memory reg = {
- .argsz = sizeof(reg),
- .flags = 0,
- };
-
- if (vfio_prereg_listener_skipped_section(section)) {
- trace_vfio_prereg_listener_region_add_skip(
- section->offset_within_address_space,
- section->offset_within_address_space +
- int128_get64(int128_sub(section->size, int128_one())));
- return;
- }
-
- if (unlikely((section->offset_within_address_space & ~page_mask) ||
- (section->offset_within_region & ~page_mask) ||
- (int128_get64(section->size) & ~page_mask))) {
- error_report("%s received unaligned region", __func__);
- return;
- }
-
- end = section->offset_within_address_space + int128_get64(section->size);
- if (gpa >= end) {
- return;
- }
-
- memory_region_ref(section->mr);
-
- reg.vaddr = (uintptr_t) vfio_prereg_gpa_to_vaddr(section, gpa);
- reg.size = end - gpa;
-
- ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_REGISTER_MEMORY, &reg);
- trace_vfio_prereg_register(reg.vaddr, reg.size, ret ? -errno : 0);
- if (ret) {
- /*
- * On the initfn path, store the first error in the container so we
- * can gracefully fail. Runtime, there's not much we can do other
- * than throw a hardware error.
- */
- if (!container->initialized) {
- if (!container->error) {
- container->error = ret;
- }
- } else {
- hw_error("vfio: Memory registering failed, unable to continue");
- }
- }
-}
-
-static void vfio_prereg_listener_region_del(MemoryListener *listener,
- MemoryRegionSection *section)
-{
- VFIOContainer *container = container_of(listener, VFIOContainer,
- prereg_listener);
- const hwaddr gpa = section->offset_within_address_space;
- hwaddr end;
- int ret;
- hwaddr page_mask = qemu_real_host_page_mask;
- struct vfio_iommu_spapr_register_memory reg = {
- .argsz = sizeof(reg),
- .flags = 0,
- };
-
- if (vfio_prereg_listener_skipped_section(section)) {
- trace_vfio_prereg_listener_region_del_skip(
- section->offset_within_address_space,
- section->offset_within_address_space +
- int128_get64(int128_sub(section->size, int128_one())));
- return;
- }
-
- if (unlikely((section->offset_within_address_space & ~page_mask) ||
- (section->offset_within_region & ~page_mask) ||
- (int128_get64(section->size) & ~page_mask))) {
- error_report("%s received unaligned region", __func__);
- return;
- }
-
- end = section->offset_within_address_space + int128_get64(section->size);
- if (gpa >= end) {
- return;
- }
-
- reg.vaddr = (uintptr_t) vfio_prereg_gpa_to_vaddr(section, gpa);
- reg.size = end - gpa;
-
- ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_UNREGISTER_MEMORY, &reg);
- trace_vfio_prereg_unregister(reg.vaddr, reg.size, ret ? -errno : 0);
-}
-
-const MemoryListener vfio_prereg_listener = {
- .region_add = vfio_prereg_listener_region_add,
- .region_del = vfio_prereg_listener_region_del,
-};
-
-int vfio_spapr_create_window(VFIOContainer *container,
- MemoryRegionSection *section,
- hwaddr *pgsize)
-{
- int ret;
- unsigned pagesize = memory_region_iommu_get_min_page_size(section->mr);
- unsigned entries, pages;
- struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
-
- /*
- * FIXME: For VFIO iommu types which have KVM acceleration to
- * avoid bouncing all map/unmaps through qemu this way, this
- * would be the right place to wire that up (tell the KVM
- * device emulation the VFIO iommu handles to use).
- */
- create.window_size = int128_get64(section->size);
- create.page_shift = ctz64(pagesize);
- /*
- * SPAPR host supports multilevel TCE tables, there is some
- * heuristic to decide how many levels we want for our table:
- * 0..64 = 1; 65..4096 = 2; 4097..262144 = 3; 262145.. = 4
- */
- entries = create.window_size >> create.page_shift;
- pages = MAX((entries * sizeof(uint64_t)) / getpagesize(), 1);
- pages = MAX(pow2ceil(pages) - 1, 1); /* Round up */
- create.levels = ctz64(pages) / 6 + 1;
-
- ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_CREATE, &create);
- if (ret) {
- error_report("Failed to create a window, ret = %d (%m)", ret);
- return -errno;
- }
-
- if (create.start_addr != section->offset_within_address_space) {
- vfio_spapr_remove_window(container, create.start_addr);
-
- error_report("Host doesn't support DMA window at %"HWADDR_PRIx", must be %"PRIx64,
- section->offset_within_address_space,
- (uint64_t)create.start_addr);
- return -EINVAL;
- }
- trace_vfio_spapr_create_window(create.page_shift,
- create.window_size,
- create.start_addr);
- *pgsize = pagesize;
-
- return 0;
-}
-
-int vfio_spapr_remove_window(VFIOContainer *container,
- hwaddr offset_within_address_space)
-{
- struct vfio_iommu_spapr_tce_remove remove = {
- .argsz = sizeof(remove),
- .start_addr = offset_within_address_space,
- };
- int ret;
-
- ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove);
- if (ret) {
- error_report("Failed to remove window at %"PRIx64,
- (uint64_t)remove.start_addr);
- return -errno;
- }
-
- trace_vfio_spapr_remove_window(offset_within_address_space);
-
- return 0;
-}
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
deleted file mode 100644
index da133221d..000000000
--- a/hw/vfio/trace-events
+++ /dev/null
@@ -1,125 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/vfio/pci.c
-vfio_intx_interrupt(const char *name, char line) " (%s) Pin %c"
-vfio_intx_eoi(const char *name) " (%s) EOI"
-vfio_intx_enable_kvm(const char *name) " (%s) KVM INTx accel enabled"
-vfio_intx_disable_kvm(const char *name) " (%s) KVM INTx accel disabled"
-vfio_intx_update(const char *name, int new_irq, int target_irq) " (%s) IRQ moved %d -> %d"
-vfio_intx_enable(const char *name) " (%s)"
-vfio_intx_disable(const char *name) " (%s)"
-vfio_msi_interrupt(const char *name, int index, uint64_t addr, int data) " (%s) vector %d 0x%"PRIx64"/0x%x"
-vfio_msix_vector_do_use(const char *name, int index) " (%s) vector %d used"
-vfio_msix_vector_release(const char *name, int index) " (%s) vector %d released"
-vfio_msix_enable(const char *name) " (%s)"
-vfio_msix_pba_disable(const char *name) " (%s)"
-vfio_msix_pba_enable(const char *name) " (%s)"
-vfio_msix_disable(const char *name) " (%s)"
-vfio_msix_fixup(const char *name, int bar, uint64_t start, uint64_t end) " (%s) MSI-X region %d mmap fixup [0x%"PRIx64" - 0x%"PRIx64"]"
-vfio_msi_enable(const char *name, int nr_vectors) " (%s) Enabled %d MSI vectors"
-vfio_msi_disable(const char *name) " (%s)"
-vfio_pci_load_rom(const char *name, unsigned long size, unsigned long offset, unsigned long flags) "Device %s ROM:\n size: 0x%lx, offset: 0x%lx, flags: 0x%lx"
-vfio_rom_read(const char *name, uint64_t addr, int size, uint64_t data) " (%s, 0x%"PRIx64", 0x%x) = 0x%"PRIx64
-vfio_pci_size_rom(const char *name, int size) "%s ROM size 0x%x"
-vfio_vga_write(uint64_t addr, uint64_t data, int size) " (0x%"PRIx64", 0x%"PRIx64", %d)"
-vfio_vga_read(uint64_t addr, int size, uint64_t data) " (0x%"PRIx64", %d) = 0x%"PRIx64
-vfio_pci_read_config(const char *name, int addr, int len, int val) " (%s, @0x%x, len=0x%x) %x"
-vfio_pci_write_config(const char *name, int addr, int val, int len) " (%s, @0x%x, 0x%x, len=0x%x)"
-vfio_msi_setup(const char *name, int pos) "%s PCI MSI CAP @0x%x"
-vfio_msix_early_setup(const char *name, int pos, int table_bar, int offset, int entries) "%s PCI MSI-X CAP @0x%x, BAR %d, offset 0x%x, entries %d"
-vfio_check_pcie_flr(const char *name) "%s Supports FLR via PCIe cap"
-vfio_check_pm_reset(const char *name) "%s Supports PM reset"
-vfio_check_af_flr(const char *name) "%s Supports FLR via AF cap"
-vfio_pci_hot_reset(const char *name, const char *type) " (%s) %s"
-vfio_pci_hot_reset_has_dep_devices(const char *name) "%s: hot reset dependent devices:"
-vfio_pci_hot_reset_dep_devices(int domain, int bus, int slot, int function, int group_id) "\t%04x:%02x:%02x.%x group %d"
-vfio_pci_hot_reset_result(const char *name, const char *result) "%s hot reset: %s"
-vfio_populate_device_config(const char *name, unsigned long size, unsigned long offset, unsigned long flags) "Device %s config:\n size: 0x%lx, offset: 0x%lx, flags: 0x%lx"
-vfio_populate_device_get_irq_info_failure(void) "VFIO_DEVICE_GET_IRQ_INFO failure: %m"
-vfio_initfn(const char *name, int group_id) " (%s) group %d"
-vfio_add_ext_cap_dropped(const char *name, uint16_t cap, uint16_t offset) "%s %x@%x"
-vfio_pci_reset(const char *name) " (%s)"
-vfio_pci_reset_flr(const char *name) "%s FLR/VFIO_DEVICE_RESET"
-vfio_pci_reset_pm(const char *name) "%s PCI PM Reset"
-vfio_pci_emulated_vendor_id(const char *name, uint16_t val) "%s %04x"
-vfio_pci_emulated_device_id(const char *name, uint16_t val) "%s %04x"
-vfio_pci_emulated_sub_vendor_id(const char *name, uint16_t val) "%s %04x"
-vfio_pci_emulated_sub_device_id(const char *name, uint16_t val) "%s %04x"
-
-# hw/vfio/pci-quirks.
-vfio_quirk_rom_blacklisted(const char *name, uint16_t vid, uint16_t did) "%s %04x:%04x"
-vfio_quirk_generic_window_address_write(const char *name, const char * region_name, uint64_t data) "%s %s 0x%"PRIx64
-vfio_quirk_generic_window_data_read(const char *name, const char * region_name, uint64_t data) "%s %s 0x%"PRIx64
-vfio_quirk_generic_window_data_write(const char *name, const char * region_name, uint64_t data) "%s %s 0x%"PRIx64
-vfio_quirk_generic_mirror_read(const char *name, const char * region_name, uint64_t addr, uint64_t data) "%s %s 0x%"PRIx64": 0x%"PRIx64
-vfio_quirk_generic_mirror_write(const char *name, const char * region_name, uint64_t addr, uint64_t data) "%s %s 0x%"PRIx64": 0x%"PRIx64
-vfio_quirk_ati_3c3_read(const char *name, uint64_t data) "%s 0x%"PRIx64
-vfio_quirk_ati_3c3_probe(const char *name) "%s"
-vfio_quirk_ati_bar4_probe(const char *name) "%s"
-vfio_quirk_ati_bar2_probe(const char *name) "%s"
-vfio_quirk_nvidia_3d0_state(const char *name, const char *state) "%s %s"
-vfio_quirk_nvidia_3d0_read(const char *name, uint8_t offset, unsigned size, uint64_t val) " (%s, @0x%x, len=0x%x) %"PRIx64
-vfio_quirk_nvidia_3d0_write(const char *name, uint8_t offset, uint64_t data, unsigned size) "(%s, @0x%x, 0x%"PRIx64", len=0x%x)"
-vfio_quirk_nvidia_3d0_probe(const char *name) "%s"
-vfio_quirk_nvidia_bar5_state(const char *name, const char *state) "%s %s"
-vfio_quirk_nvidia_bar5_probe(const char *name) "%s"
-vfio_quirk_nvidia_bar0_msi_ack(const char *name) "%s"
-vfio_quirk_nvidia_bar0_probe(const char *name) "%s"
-vfio_quirk_rtl8168_fake_latch(const char *name, uint64_t val) "%s 0x%"PRIx64
-vfio_quirk_rtl8168_msix_write(const char *name, uint16_t offset, uint64_t val) "%s MSI-X table write[0x%x]: 0x%"PRIx64
-vfio_quirk_rtl8168_msix_read(const char *name, uint16_t offset, uint64_t val) "%s MSI-X table read[0x%x]: 0x%"PRIx64
-vfio_quirk_rtl8168_probe(const char *name) "%s"
-
-vfio_quirk_ati_bonaire_reset_skipped(const char *name) "%s"
-vfio_quirk_ati_bonaire_reset_no_smc(const char *name) "%s"
-vfio_quirk_ati_bonaire_reset_timeout(const char *name) "%s"
-vfio_quirk_ati_bonaire_reset_done(const char *name) "%s"
-vfio_quirk_ati_bonaire_reset(const char *name) "%s"
-vfio_pci_igd_bar4_write(const char *name, uint32_t index, uint32_t data, uint32_t base) "%s [%03x] %08x -> %08x"
-vfio_pci_igd_bdsm_enabled(const char *name, int size) "%s %dMB"
-vfio_pci_igd_opregion_enabled(const char *name) "%s"
-vfio_pci_igd_host_bridge_enabled(const char *name) "%s"
-vfio_pci_igd_lpc_bridge_enabled(const char *name) "%s"
-
-# hw/vfio/common.c
-vfio_region_write(const char *name, int index, uint64_t addr, uint64_t data, unsigned size) " (%s:region%d+0x%"PRIx64", 0x%"PRIx64 ", %d)"
-vfio_region_read(char *name, int index, uint64_t addr, unsigned size, uint64_t data) " (%s:region%d+0x%"PRIx64", %d) = 0x%"PRIx64
-vfio_iommu_map_notify(uint64_t iova_start, uint64_t iova_end) "iommu map @ %"PRIx64" - %"PRIx64
-vfio_listener_region_add_skip(uint64_t start, uint64_t end) "SKIPPING region_add %"PRIx64" - %"PRIx64
-vfio_listener_region_add_iommu(uint64_t start, uint64_t end) "region_add [iommu] %"PRIx64" - %"PRIx64
-vfio_listener_region_add_ram(uint64_t iova_start, uint64_t iova_end, void *vaddr) "region_add [ram] %"PRIx64" - %"PRIx64" [%p]"
-vfio_listener_region_del_skip(uint64_t start, uint64_t end) "SKIPPING region_del %"PRIx64" - %"PRIx64
-vfio_listener_region_del(uint64_t start, uint64_t end) "region_del %"PRIx64" - %"PRIx64
-vfio_disconnect_container(int fd) "close container->fd=%d"
-vfio_put_group(int fd) "close group->fd=%d"
-vfio_get_device(const char * name, unsigned int flags, unsigned int num_regions, unsigned int num_irqs) "Device %s flags: %u, regions: %u, irqs: %u"
-vfio_put_base_device(int fd) "close vdev->fd=%d"
-vfio_region_setup(const char *dev, int index, const char *name, unsigned long flags, unsigned long offset, unsigned long size) "Device %s, region %d \"%s\", flags: %lx, offset: %lx, size: %lx"
-vfio_region_mmap_fault(const char *name, int index, unsigned long offset, unsigned long size, int fault) "Region %s mmaps[%d], [%lx - %lx], fault: %d"
-vfio_region_mmap(const char *name, unsigned long offset, unsigned long end) "Region %s [%lx - %lx]"
-vfio_region_exit(const char *name, int index) "Device %s, region %d"
-vfio_region_finalize(const char *name, int index) "Device %s, region %d"
-vfio_region_mmaps_set_enabled(const char *name, bool enabled) "Region %s mmaps enabled: %d"
-vfio_region_sparse_mmap_header(const char *name, int index, int nr_areas) "Device %s region %d: %d sparse mmap entries"
-vfio_region_sparse_mmap_entry(int i, unsigned long start, unsigned long end) "sparse entry %d [0x%lx - 0x%lx]"
-vfio_get_dev_region(const char *name, int index, uint32_t type, uint32_t subtype) "%s index %d, %08x/%0x8"
-
-# hw/vfio/platform.c
-vfio_platform_base_device_init(char *name, int groupid) "%s belongs to group #%d"
-vfio_platform_realize(char *name, char *compat) "vfio device %s, compat = %s"
-vfio_platform_eoi(int pin, int fd) "EOI IRQ pin %d (fd=%d)"
-vfio_platform_intp_mmap_enable(int pin) "IRQ #%d still active, stay in slow path"
-vfio_platform_intp_interrupt(int pin, int fd) "Inject IRQ #%d (fd = %d)"
-vfio_platform_intp_inject_pending_lockheld(int pin, int fd) "Inject pending IRQ #%d (fd = %d)"
-vfio_platform_populate_interrupts(int pin, int count, int flags) "- IRQ index %d: count %d, flags=0x%x"
-vfio_intp_interrupt_set_pending(int index) "irq %d is set PENDING"
-vfio_platform_start_level_irqfd_injection(int index, int fd, int resamplefd) "IRQ index=%d, fd = %d, resamplefd = %d"
-vfio_platform_start_edge_irqfd_injection(int index, int fd) "IRQ index=%d, fd = %d"
-
-# hw/vfio/spapr.c
-vfio_prereg_listener_region_add_skip(uint64_t start, uint64_t end) "%"PRIx64" - %"PRIx64
-vfio_prereg_listener_region_del_skip(uint64_t start, uint64_t end) "%"PRIx64" - %"PRIx64
-vfio_prereg_register(uint64_t va, uint64_t size, int ret) "va=%"PRIx64" size=%"PRIx64" ret=%d"
-vfio_prereg_unregister(uint64_t va, uint64_t size, int ret) "va=%"PRIx64" size=%"PRIx64" ret=%d"
-vfio_spapr_create_window(int ps, uint64_t ws, uint64_t off) "pageshift=0x%x winsize=0x%"PRIx64" offset=0x%"PRIx64
-vfio_spapr_remove_window(uint64_t off) "offset=%"PRIx64
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
deleted file mode 100644
index 55184d33b..000000000
--- a/hw/virtio/trace-events
+++ /dev/null
@@ -1,16 +0,0 @@
-# See docs/tracing.txt for syntax documentation.
-
-# hw/virtio/virtio.c
-virtqueue_fill(void *vq, const void *elem, unsigned int len, unsigned int idx) "vq %p elem %p len %u idx %u"
-virtqueue_flush(void *vq, unsigned int count) "vq %p count %u"
-virtqueue_pop(void *vq, void *elem, unsigned int in_num, unsigned int out_num) "vq %p elem %p in_num %u out_num %u"
-virtio_queue_notify(void *vdev, int n, void *vq) "vdev %p n %d vq %p"
-virtio_irq(void *vq) "vq %p"
-virtio_notify(void *vdev, void *vq) "vdev %p vq %p"
-virtio_set_status(void *vdev, uint8_t val) "vdev %p val %u"
-
-# hw/virtio/virtio-rng.c
-virtio_rng_guest_not_ready(void *rng) "rng %p: guest not ready"
-virtio_rng_pushed(void *rng, size_t len) "rng %p: %zd bytes pushed"
-virtio_rng_request(void *rng, size_t size, unsigned quota) "rng %p: %zd bytes requested, %u bytes quota left"
-
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 7681f152f..b35890289 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -9,11 +9,12 @@
*/
#include "qemu/osdep.h"
-#include <linux/vhost.h>
-#include <sys/ioctl.h>
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-backend.h"
#include "qemu/error-report.h"
+#include "linux/vhost.h"
+
+#include <sys/ioctl.h>
static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
void *arg)
@@ -137,12 +138,6 @@ static int vhost_kernel_set_vring_call(struct vhost_dev *dev,
return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file);
}
-static int vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *dev,
- struct vhost_vring_state *s)
-{
- return vhost_kernel_call(dev, VHOST_SET_VRING_BUSYLOOP_TIMEOUT, s);
-}
-
static int vhost_kernel_set_features(struct vhost_dev *dev,
uint64_t features)
{
@@ -190,8 +185,6 @@ static const VhostOps kernel_ops = {
.vhost_get_vring_base = vhost_kernel_get_vring_base,
.vhost_set_vring_kick = vhost_kernel_set_vring_kick,
.vhost_set_vring_call = vhost_kernel_set_vring_call,
- .vhost_set_vring_busyloop_timeout =
- vhost_kernel_set_vring_busyloop_timeout,
.vhost_set_features = vhost_kernel_set_features,
.vhost_get_features = vhost_kernel_get_features,
.vhost_set_owner = vhost_kernel_set_owner,
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index b57454a4b..5914e8510 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -17,6 +17,7 @@
#include "sysemu/kvm.h"
#include "qemu/error-report.h"
#include "qemu/sockets.h"
+#include "exec/ram_addr.h"
#include "migration/migration.h"
#include <sys/ioctl.h>
@@ -31,7 +32,6 @@ enum VhostUserProtocolFeature {
VHOST_USER_PROTOCOL_F_MQ = 0,
VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
VHOST_USER_PROTOCOL_F_RARP = 2,
- VHOST_USER_PROTOCOL_F_REPLY_ACK = 3,
VHOST_USER_PROTOCOL_F_MAX
};
@@ -85,7 +85,6 @@ typedef struct VhostUserMsg {
#define VHOST_USER_VERSION_MASK (0x3)
#define VHOST_USER_REPLY_MASK (0x1<<2)
-#define VHOST_USER_NEED_REPLY_MASK (0x1 << 3)
uint32_t flags;
uint32_t size; /* the following payload size */
union {
@@ -160,25 +159,6 @@ fail:
return -1;
}
-static int process_message_reply(struct vhost_dev *dev,
- VhostUserRequest request)
-{
- VhostUserMsg msg;
-
- if (vhost_user_read(dev, &msg) < 0) {
- return -1;
- }
-
- if (msg.request != request) {
- error_report("Received unexpected msg type."
- "Expected %d received %d",
- request, msg.request);
- return -1;
- }
-
- return msg.payload.u64 ? -1 : 0;
-}
-
static bool vhost_user_one_time_request(VhostUserRequest request)
{
switch (request) {
@@ -197,7 +177,7 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
int *fds, int fd_num)
{
CharDriverState *chr = dev->opaque;
- int ret, size = VHOST_USER_HDR_SIZE + msg->size;
+ int size = VHOST_USER_HDR_SIZE + msg->size;
/*
* For non-vring specific requests, like VHOST_USER_SET_MEM_TABLE,
@@ -208,19 +188,12 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
return 0;
}
- if (qemu_chr_fe_set_msgfds(chr, fds, fd_num) < 0) {
- error_report("Failed to set msg fds.");
- return -1;
- }
-
- ret = qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size);
- if (ret != size) {
- error_report("Failed to write msg."
- " Wrote %d instead of %d.", ret, size);
- return -1;
+ if (fd_num) {
+ qemu_chr_fe_set_msgfds(chr, fds, fd_num);
}
- return 0;
+ return qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size) == size ?
+ 0 : -1;
}
static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
@@ -242,14 +215,12 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
fds[fd_num++] = log->fd;
}
- if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
- return -1;
- }
+ vhost_user_write(dev, &msg, fds, fd_num);
if (shmfd) {
msg.size = 0;
if (vhost_user_read(dev, &msg) < 0) {
- return -1;
+ return 0;
}
if (msg.request != VHOST_USER_SET_LOG_BASE) {
@@ -269,32 +240,25 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev,
int fds[VHOST_MEMORY_MAX_NREGIONS];
int i, fd;
size_t fd_num = 0;
- bool reply_supported = virtio_has_feature(dev->protocol_features,
- VHOST_USER_PROTOCOL_F_REPLY_ACK);
-
VhostUserMsg msg = {
.request = VHOST_USER_SET_MEM_TABLE,
.flags = VHOST_USER_VERSION,
};
- if (reply_supported) {
- msg.flags |= VHOST_USER_NEED_REPLY_MASK;
- }
-
for (i = 0; i < dev->mem->nregions; ++i) {
struct vhost_memory_region *reg = dev->mem->regions + i;
- ram_addr_t offset;
- MemoryRegion *mr;
+ ram_addr_t ram_addr;
assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
- mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr,
- &offset);
- fd = memory_region_get_fd(mr);
+ qemu_ram_addr_from_host((void *)(uintptr_t)reg->userspace_addr,
+ &ram_addr);
+ fd = qemu_get_ram_fd(ram_addr);
if (fd > 0) {
msg.payload.memory.regions[fd_num].userspace_addr = reg->userspace_addr;
msg.payload.memory.regions[fd_num].memory_size = reg->memory_size;
msg.payload.memory.regions[fd_num].guest_phys_addr = reg->guest_phys_addr;
- msg.payload.memory.regions[fd_num].mmap_offset = offset;
+ msg.payload.memory.regions[fd_num].mmap_offset = reg->userspace_addr -
+ (uintptr_t) qemu_get_ram_block_host_ptr(ram_addr);
assert(fd_num < VHOST_MEMORY_MAX_NREGIONS);
fds[fd_num++] = fd;
}
@@ -312,13 +276,7 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev,
msg.size += sizeof(msg.payload.memory.padding);
msg.size += fd_num * sizeof(VhostUserMemoryRegion);
- if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
- return -1;
- }
-
- if (reply_supported) {
- return process_message_reply(dev, msg.request);
- }
+ vhost_user_write(dev, &msg, fds, fd_num);
return 0;
}
@@ -333,9 +291,7 @@ static int vhost_user_set_vring_addr(struct vhost_dev *dev,
.size = sizeof(msg.payload.addr),
};
- if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
- return -1;
- }
+ vhost_user_write(dev, &msg, NULL, 0);
return 0;
}
@@ -358,9 +314,7 @@ static int vhost_set_vring(struct vhost_dev *dev,
.size = sizeof(msg.payload.state),
};
- if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
- return -1;
- }
+ vhost_user_write(dev, &msg, NULL, 0);
return 0;
}
@@ -407,12 +361,10 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev,
.size = sizeof(msg.payload.state),
};
- if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
- return -1;
- }
+ vhost_user_write(dev, &msg, NULL, 0);
if (vhost_user_read(dev, &msg) < 0) {
- return -1;
+ return 0;
}
if (msg.request != VHOST_USER_GET_VRING_BASE) {
@@ -450,9 +402,7 @@ static int vhost_set_vring_file(struct vhost_dev *dev,
msg.payload.u64 |= VHOST_USER_VRING_NOFD_MASK;
}
- if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
- return -1;
- }
+ vhost_user_write(dev, &msg, fds, fd_num);
return 0;
}
@@ -478,9 +428,7 @@ static int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64)
.size = sizeof(msg.payload.u64),
};
- if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
- return -1;
- }
+ vhost_user_write(dev, &msg, NULL, 0);
return 0;
}
@@ -508,12 +456,10 @@ static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64)
return 0;
}
- if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
- return -1;
- }
+ vhost_user_write(dev, &msg, NULL, 0);
if (vhost_user_read(dev, &msg) < 0) {
- return -1;
+ return 0;
}
if (msg.request != request) {
@@ -544,9 +490,7 @@ static int vhost_user_set_owner(struct vhost_dev *dev)
.flags = VHOST_USER_VERSION,
};
- if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
- return -1;
- }
+ vhost_user_write(dev, &msg, NULL, 0);
return 0;
}
@@ -558,9 +502,7 @@ static int vhost_user_reset_device(struct vhost_dev *dev)
.flags = VHOST_USER_VERSION,
};
- if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
- return -1;
- }
+ vhost_user_write(dev, &msg, NULL, 0);
return 0;
}
@@ -647,6 +589,7 @@ static bool vhost_user_requires_shm_log(struct vhost_dev *dev)
static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
{
VhostUserMsg msg = { 0 };
+ int err;
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
@@ -663,7 +606,8 @@ static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
memcpy((char *)&msg.payload.u64, mac_addr, 6);
msg.size = sizeof(msg.payload.u64);
- return vhost_user_write(dev, &msg, NULL, 0);
+ err = vhost_user_write(dev, &msg, NULL, 0);
+ return err;
}
return -1;
}
@@ -672,15 +616,17 @@ static bool vhost_user_can_merge(struct vhost_dev *dev,
uint64_t start1, uint64_t size1,
uint64_t start2, uint64_t size2)
{
- ram_addr_t offset;
+ ram_addr_t ram_addr;
int mfd, rfd;
MemoryRegion *mr;
- mr = memory_region_from_host((void *)(uintptr_t)start1, &offset);
- mfd = memory_region_get_fd(mr);
+ mr = qemu_ram_addr_from_host((void *)(uintptr_t)start1, &ram_addr);
+ assert(mr);
+ mfd = qemu_get_ram_fd(ram_addr);
- mr = memory_region_from_host((void *)(uintptr_t)start2, &offset);
- rfd = memory_region_get_fd(mr);
+ mr = qemu_ram_addr_from_host((void *)(uintptr_t)start2, &ram_addr);
+ assert(mr);
+ rfd = qemu_get_ram_fd(ram_addr);
return mfd == rfd;
}
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 3d0c807d0..440071815 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -27,18 +27,6 @@
#include "hw/virtio/virtio-access.h"
#include "migration/migration.h"
-/* enabled until disconnected backend stabilizes */
-#define _VHOST_DEBUG 1
-
-#ifdef _VHOST_DEBUG
-#define VHOST_OPS_DEBUG(fmt, ...) \
- do { error_report(fmt ": %s (%d)", ## __VA_ARGS__, \
- strerror(errno), errno); } while (0)
-#else
-#define VHOST_OPS_DEBUG(fmt, ...) \
- do { } while (0)
-#endif
-
static struct vhost_log *vhost_log;
static struct vhost_log *vhost_log_shm;
@@ -374,8 +362,6 @@ static void vhost_log_put(struct vhost_dev *dev, bool sync)
if (!log) {
return;
}
- dev->log = NULL;
- dev->log_size = 0;
--log->refcnt;
if (log->refcnt == 0) {
@@ -412,10 +398,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size)
/* inform backend of log switching, this must be done before
releasing the current log, to ensure no logging is lost */
r = dev->vhost_ops->vhost_set_log_base(dev, log_base, log);
- if (r < 0) {
- VHOST_OPS_DEBUG("vhost_set_log_base failed");
- }
-
+ assert(r >= 0);
vhost_log_put(dev, true);
dev->log = log;
dev->log_size = size;
@@ -439,11 +422,11 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
l = vq->ring_size;
p = cpu_physical_memory_map(vq->ring_phys, &l, 1);
if (!p || l != vq->ring_size) {
- error_report("Unable to map ring buffer for ring %d", i);
+ fprintf(stderr, "Unable to map ring buffer for ring %d\n", i);
r = -ENOMEM;
}
if (p != vq->ring) {
- error_report("Ring buffer relocated for ring %d", i);
+ fprintf(stderr, "Ring buffer relocated for ring %d\n", i);
r = -EBUSY;
}
cpu_physical_memory_unmap(p, l, 0, 0);
@@ -582,9 +565,7 @@ static void vhost_commit(MemoryListener *listener)
if (!dev->log_enabled) {
r = dev->vhost_ops->vhost_set_mem_table(dev, dev->mem);
- if (r < 0) {
- VHOST_OPS_DEBUG("vhost_set_mem_table failed");
- }
+ assert(r >= 0);
dev->memory_changed = false;
return;
}
@@ -597,9 +578,7 @@ static void vhost_commit(MemoryListener *listener)
vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER);
}
r = dev->vhost_ops->vhost_set_mem_table(dev, dev->mem);
- if (r < 0) {
- VHOST_OPS_DEBUG("vhost_set_mem_table failed");
- }
+ assert(r >= 0);
/* To log less, can only decrease log size after table update. */
if (dev->log_size > log_size + VHOST_LOG_BUFFER) {
vhost_dev_log_resize(dev, log_size);
@@ -668,7 +647,6 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
};
int r = dev->vhost_ops->vhost_set_vring_addr(dev, &addr);
if (r < 0) {
- VHOST_OPS_DEBUG("vhost_set_vring_addr failed");
return -errno;
}
return 0;
@@ -682,15 +660,12 @@ static int vhost_dev_set_features(struct vhost_dev *dev, bool enable_log)
features |= 0x1ULL << VHOST_F_LOG_ALL;
}
r = dev->vhost_ops->vhost_set_features(dev, features);
- if (r < 0) {
- VHOST_OPS_DEBUG("vhost_set_features failed");
- }
return r < 0 ? -errno : 0;
}
static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
{
- int r, i, idx;
+ int r, t, i, idx;
r = vhost_dev_set_features(dev, enable_log);
if (r < 0) {
goto err_features;
@@ -707,10 +682,12 @@ static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
err_vq:
for (; i >= 0; --i) {
idx = dev->vhost_ops->vhost_get_vq_index(dev, dev->vq_index + i);
- vhost_virtqueue_set_addr(dev, dev->vqs + i, idx,
- dev->log_enabled);
+ t = vhost_virtqueue_set_addr(dev, dev->vqs + i, idx,
+ dev->log_enabled);
+ assert(t >= 0);
}
- vhost_dev_set_features(dev, dev->log_enabled);
+ t = vhost_dev_set_features(dev, dev->log_enabled);
+ assert(t >= 0);
err_features:
return r;
}
@@ -733,6 +710,8 @@ static int vhost_migration_log(MemoryListener *listener, int enable)
return r;
}
vhost_log_put(dev, false);
+ dev->log = NULL;
+ dev->log_size = 0;
} else {
vhost_dev_log_resize(dev, vhost_get_log_size(dev));
r = vhost_dev_set_log(dev, true);
@@ -788,11 +767,15 @@ static inline bool vhost_needs_vring_endian(VirtIODevice *vdev)
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
return false;
}
+#ifdef TARGET_IS_BIENDIAN
#ifdef HOST_WORDS_BIGENDIAN
return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_LITTLE;
#else
return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG;
#endif
+#else
+ return false;
+#endif
}
static int vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev,
@@ -808,7 +791,6 @@ static int vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev,
return 0;
}
- VHOST_OPS_DEBUG("vhost_set_vring_endian failed");
if (errno == ENOTTY) {
error_report("vhost does not support cross-endian");
return -ENOSYS;
@@ -837,14 +819,12 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
vq->num = state.num = virtio_queue_get_num(vdev, idx);
r = dev->vhost_ops->vhost_set_vring_num(dev, &state);
if (r) {
- VHOST_OPS_DEBUG("vhost_set_vring_num failed");
return -errno;
}
state.num = virtio_queue_get_last_avail_idx(vdev, idx);
r = dev->vhost_ops->vhost_set_vring_base(dev, &state);
if (r) {
- VHOST_OPS_DEBUG("vhost_set_vring_base failed");
return -errno;
}
@@ -896,7 +876,6 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq));
r = dev->vhost_ops->vhost_set_vring_kick(dev, &file);
if (r) {
- VHOST_OPS_DEBUG("vhost_set_vring_kick failed");
r = -errno;
goto fail_kick;
}
@@ -944,21 +923,25 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
r = dev->vhost_ops->vhost_get_vring_base(dev, &state);
if (r < 0) {
- VHOST_OPS_DEBUG("vhost VQ %d ring restore failed: %d", idx, r);
- } else {
- virtio_queue_set_last_avail_idx(vdev, idx, state.num);
+ fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r);
+ fflush(stderr);
}
+ virtio_queue_set_last_avail_idx(vdev, idx, state.num);
virtio_queue_invalidate_signalled_used(vdev, idx);
/* In the cross-endian case, we need to reset the vring endianness to
* native as legacy devices expect so by default.
*/
if (vhost_needs_vring_endian(vdev)) {
- vhost_virtqueue_set_vring_endian_legacy(dev,
- !virtio_is_big_endian(vdev),
- vhost_vq_index);
+ r = vhost_virtqueue_set_vring_endian_legacy(dev,
+ !virtio_is_big_endian(vdev),
+ vhost_vq_index);
+ if (r < 0) {
+ error_report("failed to reset vring endianness");
+ }
}
+ assert (r >= 0);
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
0, virtio_queue_get_ring_size(vdev, idx));
cpu_physical_memory_unmap(vq->used, virtio_queue_get_used_size(vdev, idx),
@@ -981,29 +964,6 @@ static void vhost_eventfd_del(MemoryListener *listener,
{
}
-static int vhost_virtqueue_set_busyloop_timeout(struct vhost_dev *dev,
- int n, uint32_t timeout)
-{
- int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, n);
- struct vhost_vring_state state = {
- .index = vhost_vq_index,
- .num = timeout,
- };
- int r;
-
- if (!dev->vhost_ops->vhost_set_vring_busyloop_timeout) {
- return -EINVAL;
- }
-
- r = dev->vhost_ops->vhost_set_vring_busyloop_timeout(dev, &state);
- if (r) {
- VHOST_OPS_DEBUG("vhost_set_vring_busyloop_timeout failed");
- return r;
- }
-
- return 0;
-}
-
static int vhost_virtqueue_init(struct vhost_dev *dev,
struct vhost_virtqueue *vq, int n)
{
@@ -1019,7 +979,6 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
file.fd = event_notifier_get_fd(&vq->masked_notifier);
r = dev->vhost_ops->vhost_set_vring_call(dev, &file);
if (r) {
- VHOST_OPS_DEBUG("vhost_set_vring_call failed");
r = -errno;
goto fail_call;
}
@@ -1035,57 +994,47 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
}
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
- VhostBackendType backend_type, uint32_t busyloop_timeout)
+ VhostBackendType backend_type)
{
uint64_t features;
- int i, r, n_initialized_vqs = 0;
+ int i, r;
hdev->migration_blocker = NULL;
- r = vhost_set_backend_type(hdev, backend_type);
- assert(r >= 0);
+ if (vhost_set_backend_type(hdev, backend_type) < 0) {
+ close((uintptr_t)opaque);
+ return -1;
+ }
- r = hdev->vhost_ops->vhost_backend_init(hdev, opaque);
- if (r < 0) {
- goto fail;
+ if (hdev->vhost_ops->vhost_backend_init(hdev, opaque) < 0) {
+ close((uintptr_t)opaque);
+ return -errno;
}
if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) {
- error_report("vhost backend memory slots limit is less"
- " than current number of present memory slots");
- r = -1;
- goto fail;
+ fprintf(stderr, "vhost backend memory slots limit is less"
+ " than current number of present memory slots\n");
+ close((uintptr_t)opaque);
+ return -1;
}
+ QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
r = hdev->vhost_ops->vhost_set_owner(hdev);
if (r < 0) {
- VHOST_OPS_DEBUG("vhost_set_owner failed");
goto fail;
}
r = hdev->vhost_ops->vhost_get_features(hdev, &features);
if (r < 0) {
- VHOST_OPS_DEBUG("vhost_get_features failed");
goto fail;
}
- for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
+ for (i = 0; i < hdev->nvqs; ++i) {
r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
if (r < 0) {
- goto fail;
- }
- }
-
- if (busyloop_timeout) {
- for (i = 0; i < hdev->nvqs; ++i) {
- r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i,
- busyloop_timeout);
- if (r < 0) {
- goto fail_busyloop;
- }
+ goto fail_vq;
}
}
-
hdev->features = features;
hdev->memory_listener = (MemoryListener) {
@@ -1127,43 +1076,33 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
hdev->started = false;
hdev->memory_changed = false;
memory_listener_register(&hdev->memory_listener, &address_space_memory);
- QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
return 0;
-
-fail_busyloop:
+fail_vq:
while (--i >= 0) {
- vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i, 0);
+ vhost_virtqueue_cleanup(hdev->vqs + i);
}
fail:
- hdev->nvqs = n_initialized_vqs;
- vhost_dev_cleanup(hdev);
+ r = -errno;
+ hdev->vhost_ops->vhost_backend_cleanup(hdev);
+ QLIST_REMOVE(hdev, entry);
return r;
}
void vhost_dev_cleanup(struct vhost_dev *hdev)
{
int i;
-
for (i = 0; i < hdev->nvqs; ++i) {
vhost_virtqueue_cleanup(hdev->vqs + i);
}
- if (hdev->mem) {
- /* those are only safe after successful init */
- memory_listener_unregister(&hdev->memory_listener);
- QLIST_REMOVE(hdev, entry);
- }
+ memory_listener_unregister(&hdev->memory_listener);
if (hdev->migration_blocker) {
migrate_del_blocker(hdev->migration_blocker);
error_free(hdev->migration_blocker);
}
g_free(hdev->mem);
g_free(hdev->mem_sections);
- if (hdev->vhost_ops) {
- hdev->vhost_ops->vhost_backend_cleanup(hdev);
- }
- assert(!hdev->log);
-
- memset(hdev, 0, sizeof(struct vhost_dev));
+ hdev->vhost_ops->vhost_backend_cleanup(hdev);
+ QLIST_REMOVE(hdev, entry);
}
/* Stop processing guest IO notifications in qemu.
@@ -1175,18 +1114,16 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
VirtioBusState *vbus = VIRTIO_BUS(qbus);
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
int i, r, e;
-
- if (!k->ioeventfd_started) {
- error_report("binding does not support host notifiers");
+ if (!k->set_host_notifier) {
+ fprintf(stderr, "binding does not support host notifiers\n");
r = -ENOSYS;
goto fail;
}
for (i = 0; i < hdev->nvqs; ++i) {
- r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index + i,
- true);
+ r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, true);
if (r < 0) {
- error_report("vhost VQ %d notifier binding failed: %d", i, -r);
+ fprintf(stderr, "vhost VQ %d notifier binding failed: %d\n", i, -r);
goto fail_vq;
}
}
@@ -1194,10 +1131,10 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
return 0;
fail_vq:
while (--i >= 0) {
- e = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index + i,
- false);
+ e = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
if (e < 0) {
- error_report("vhost VQ %d notifier cleanup error: %d", i, -r);
+ fprintf(stderr, "vhost VQ %d notifier cleanup error: %d\n", i, -r);
+ fflush(stderr);
}
assert (e >= 0);
}
@@ -1213,13 +1150,15 @@ fail:
void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
{
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+ VirtioBusState *vbus = VIRTIO_BUS(qbus);
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
int i, r;
for (i = 0; i < hdev->nvqs; ++i) {
- r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index + i,
- false);
+ r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
if (r < 0) {
- error_report("vhost VQ %d notifier cleanup failed: %d", i, -r);
+ fprintf(stderr, "vhost VQ %d notifier cleanup failed: %d\n", i, -r);
+ fflush(stderr);
}
assert (r >= 0);
}
@@ -1243,9 +1182,6 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
int r, index = n - hdev->vq_index;
struct vhost_vring_file file;
- /* should only be called after backend is connected */
- assert(hdev->vhost_ops);
-
if (mask) {
assert(vdev->use_guest_notifier_mask);
file.fd = event_notifier_get_fd(&hdev->vqs[index].masked_notifier);
@@ -1255,9 +1191,7 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
file.index = hdev->vhost_ops->vhost_get_vq_index(hdev, n);
r = hdev->vhost_ops->vhost_set_vring_call(hdev, &file);
- if (r < 0) {
- VHOST_OPS_DEBUG("vhost_set_vring_call failed");
- }
+ assert(r >= 0);
}
uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
@@ -1292,9 +1226,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
{
int i, r;
- /* should only be called after backend is connected */
- assert(hdev->vhost_ops);
-
hdev->started = true;
r = vhost_dev_set_features(hdev, hdev->log_enabled);
@@ -1303,7 +1234,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
}
r = hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem);
if (r < 0) {
- VHOST_OPS_DEBUG("vhost_set_mem_table failed");
r = -errno;
goto fail_mem;
}
@@ -1328,7 +1258,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
hdev->log_size ? log_base : 0,
hdev->log);
if (r < 0) {
- VHOST_OPS_DEBUG("vhost_set_log_base failed");
r = -errno;
goto fail_log;
}
@@ -1357,9 +1286,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
{
int i;
- /* should only be called after backend is connected */
- assert(hdev->vhost_ops);
-
for (i = 0; i < hdev->nvqs; ++i) {
vhost_virtqueue_stop(hdev,
vdev,
@@ -1369,14 +1295,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
vhost_log_put(hdev, true);
hdev->started = false;
+ hdev->log = NULL;
+ hdev->log_size = 0;
}
-int vhost_net_set_backend(struct vhost_dev *hdev,
- struct vhost_vring_file *file)
-{
- if (hdev->vhost_ops->vhost_net_set_backend) {
- return hdev->vhost_ops->vhost_net_set_backend(hdev, file);
- }
-
- return -1;
-}
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 5af429a58..9dbe68179 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -27,6 +27,10 @@
#include "qapi-event.h"
#include "trace.h"
+#if defined(__linux__)
+#include <sys/mman.h>
+#endif
+
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
@@ -134,18 +138,17 @@ static void balloon_stats_get_all(Object *obj, Visitor *v, const char *name,
for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
visit_type_uint64(v, balloon_stat_names[i], &s->stats[i], &err);
if (err) {
- goto out_nested;
+ break;
}
}
- visit_check_struct(v, &err);
-out_nested:
- visit_end_struct(v, NULL);
+ error_propagate(errp, err);
+ err = NULL;
+ visit_end_struct(v, &err);
- if (!err) {
- visit_check_struct(v, &err);
- }
out_end:
- visit_end_struct(v, NULL);
+ error_propagate(errp, err);
+ err = NULL;
+ visit_end_struct(v, &err);
out:
error_propagate(errp, err);
}
@@ -396,6 +399,11 @@ static void virtio_balloon_to_target(void *opaque, ram_addr_t target)
trace_virtio_balloon_to_target(target, dev->num_pages);
}
+static void virtio_balloon_save(QEMUFile *f, void *opaque)
+{
+ virtio_save(VIRTIO_DEVICE(opaque), f);
+}
+
static void virtio_balloon_save_device(VirtIODevice *vdev, QEMUFile *f)
{
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
@@ -404,9 +412,12 @@ static void virtio_balloon_save_device(VirtIODevice *vdev, QEMUFile *f)
qemu_put_be32(f, s->actual);
}
-static int virtio_balloon_load(QEMUFile *f, void *opaque, size_t size)
+static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
{
- return virtio_load(VIRTIO_DEVICE(opaque), f, 1);
+ if (version_id != 1)
+ return -EINVAL;
+
+ return virtio_load(VIRTIO_DEVICE(opaque), f, version_id);
}
static int virtio_balloon_load_device(VirtIODevice *vdev, QEMUFile *f,
@@ -446,6 +457,9 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
reset_stats(s);
+
+ register_savevm(dev, "virtio-balloon", -1, 1,
+ virtio_balloon_save, virtio_balloon_load, s);
}
static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp)
@@ -455,6 +469,7 @@ static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp)
balloon_stats_destroy_timer(s);
qemu_remove_balloon_handler(s);
+ unregister_savevm(dev, "virtio-balloon", s);
virtio_cleanup(vdev);
}
@@ -481,8 +496,6 @@ static void virtio_balloon_instance_init(Object *obj)
NULL, s, NULL);
}
-VMSTATE_VIRTIO_DEVICE(balloon, 1, virtio_balloon_load, virtio_vmstate_save);
-
static Property virtio_balloon_properties[] = {
DEFINE_PROP_BIT("deflate-on-oom", VirtIOBalloon, host_features,
VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false),
@@ -495,7 +508,6 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->props = virtio_balloon_properties;
- dc->vmsd = &vmstate_virtio_balloon;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
vdc->realize = virtio_balloon_device_realize;
vdc->unrealize = virtio_balloon_device_unrealize;
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index a85b7c8ab..574f0e23f 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -146,132 +146,6 @@ void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
}
}
-/*
- * This function handles both assigning the ioeventfd handler and
- * registering it with the kernel.
- * assign: register/deregister ioeventfd with the kernel
- * set_handler: use the generic ioeventfd handler
- */
-static int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
- int n, bool assign, bool set_handler)
-{
- VirtIODevice *vdev = virtio_bus_get_device(bus);
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
- VirtQueue *vq = virtio_get_queue(vdev, n);
- EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
- int r = 0;
-
- if (assign) {
- r = event_notifier_init(notifier, 1);
- if (r < 0) {
- error_report("%s: unable to init event notifier: %d", __func__, r);
- return r;
- }
- virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
- r = k->ioeventfd_assign(proxy, notifier, n, assign);
- if (r < 0) {
- error_report("%s: unable to assign ioeventfd: %d", __func__, r);
- virtio_queue_set_host_notifier_fd_handler(vq, false, false);
- event_notifier_cleanup(notifier);
- return r;
- }
- } else {
- k->ioeventfd_assign(proxy, notifier, n, assign);
- virtio_queue_set_host_notifier_fd_handler(vq, false, false);
- event_notifier_cleanup(notifier);
- }
- return r;
-}
-
-void virtio_bus_start_ioeventfd(VirtioBusState *bus)
-{
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
- DeviceState *proxy = DEVICE(BUS(bus)->parent);
- VirtIODevice *vdev;
- int n, r;
-
- if (!k->ioeventfd_started || k->ioeventfd_started(proxy)) {
- return;
- }
- if (k->ioeventfd_disabled(proxy)) {
- return;
- }
- vdev = virtio_bus_get_device(bus);
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
- r = set_host_notifier_internal(proxy, bus, n, true, true);
- if (r < 0) {
- goto assign_error;
- }
- }
- k->ioeventfd_set_started(proxy, true, false);
- return;
-
-assign_error:
- while (--n >= 0) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
-
- r = set_host_notifier_internal(proxy, bus, n, false, false);
- assert(r >= 0);
- }
- k->ioeventfd_set_started(proxy, false, true);
- error_report("%s: failed. Fallback to userspace (slower).", __func__);
-}
-
-void virtio_bus_stop_ioeventfd(VirtioBusState *bus)
-{
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
- DeviceState *proxy = DEVICE(BUS(bus)->parent);
- VirtIODevice *vdev;
- int n, r;
-
- if (!k->ioeventfd_started || !k->ioeventfd_started(proxy)) {
- return;
- }
- vdev = virtio_bus_get_device(bus);
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
- r = set_host_notifier_internal(proxy, bus, n, false, false);
- assert(r >= 0);
- }
- k->ioeventfd_set_started(proxy, false, false);
-}
-
-/*
- * This function switches from/to the generic ioeventfd handler.
- * assign==false means 'use generic ioeventfd handler'.
- */
-int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign)
-{
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
- DeviceState *proxy = DEVICE(BUS(bus)->parent);
-
- if (!k->ioeventfd_started) {
- return -ENOSYS;
- }
- k->ioeventfd_set_disabled(proxy, assign);
- if (assign) {
- /*
- * Stop using the generic ioeventfd, we are doing eventfd handling
- * ourselves below
- *
- * FIXME: We should just switch the handler and not deassign the
- * ioeventfd.
- * Otherwise, there's a window where we don't have an
- * ioeventfd and we may end up with a notification where
- * we don't expect one.
- */
- virtio_bus_stop_ioeventfd(bus);
- }
- return set_host_notifier_internal(proxy, bus, n, assign, false);
-}
-
static char *virtio_bus_get_dev_path(DeviceState *dev)
{
BusState *bus = qdev_get_parent_bus(dev);
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 13798b3cb..d4cd91f8c 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -91,62 +91,92 @@ typedef struct {
VirtioBusState bus;
bool ioeventfd_disabled;
bool ioeventfd_started;
- bool format_transport_address;
} VirtIOMMIOProxy;
-static bool virtio_mmio_ioeventfd_started(DeviceState *d)
+static int virtio_mmio_set_host_notifier_internal(VirtIOMMIOProxy *proxy,
+ int n, bool assign,
+ bool set_handler)
{
- VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
-
- return proxy->ioeventfd_started;
-}
-
-static void virtio_mmio_ioeventfd_set_started(DeviceState *d, bool started,
- bool err)
-{
- VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
-
- proxy->ioeventfd_started = started;
-}
-
-static bool virtio_mmio_ioeventfd_disabled(DeviceState *d)
-{
- VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
-
- return !kvm_eventfds_enabled() || proxy->ioeventfd_disabled;
-}
-
-static void virtio_mmio_ioeventfd_set_disabled(DeviceState *d, bool disabled)
-{
- VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
-
- proxy->ioeventfd_disabled = disabled;
-}
-
-static int virtio_mmio_ioeventfd_assign(DeviceState *d,
- EventNotifier *notifier,
- int n, bool assign)
-{
- VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
+ EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
+ int r = 0;
if (assign) {
+ r = event_notifier_init(notifier, 1);
+ if (r < 0) {
+ error_report("%s: unable to init event notifier: %d",
+ __func__, r);
+ return r;
+ }
+ virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
memory_region_add_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUENOTIFY, 4,
true, n, notifier);
} else {
memory_region_del_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUENOTIFY, 4,
true, n, notifier);
+ virtio_queue_set_host_notifier_fd_handler(vq, false, false);
+ event_notifier_cleanup(notifier);
}
- return 0;
+ return r;
}
static void virtio_mmio_start_ioeventfd(VirtIOMMIOProxy *proxy)
{
- virtio_bus_start_ioeventfd(&proxy->bus);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ int n, r;
+
+ if (!kvm_eventfds_enabled() ||
+ proxy->ioeventfd_disabled ||
+ proxy->ioeventfd_started) {
+ return;
+ }
+
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+
+ r = virtio_mmio_set_host_notifier_internal(proxy, n, true, true);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+ proxy->ioeventfd_started = true;
+ return;
+
+assign_error:
+ while (--n >= 0) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+
+ r = virtio_mmio_set_host_notifier_internal(proxy, n, false, false);
+ assert(r >= 0);
+ }
+ proxy->ioeventfd_started = false;
+ error_report("%s: failed. Fallback to a userspace (slower).", __func__);
}
static void virtio_mmio_stop_ioeventfd(VirtIOMMIOProxy *proxy)
{
- virtio_bus_stop_ioeventfd(&proxy->bus);
+ int r;
+ int n;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
+ if (!proxy->ioeventfd_started) {
+ return;
+ }
+
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+
+ r = virtio_mmio_set_host_notifier_internal(proxy, n, false, false);
+ assert(r >= 0);
+ }
+ proxy->ioeventfd_started = false;
}
static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
@@ -468,13 +498,26 @@ assign_error:
return r;
}
-/* virtio-mmio device */
+static int virtio_mmio_set_host_notifier(DeviceState *opaque, int n,
+ bool assign)
+{
+ VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
-static Property virtio_mmio_properties[] = {
- DEFINE_PROP_BOOL("format_transport_address", VirtIOMMIOProxy,
- format_transport_address, true),
- DEFINE_PROP_END_OF_LIST(),
-};
+ /* Stop using ioeventfd for virtqueue kick if the device starts using host
+ * notifiers. This makes it easy to avoid stepping on each others' toes.
+ */
+ proxy->ioeventfd_disabled = assign;
+ if (assign) {
+ virtio_mmio_stop_ioeventfd(proxy);
+ }
+ /* We don't need to start here: it's not needed because backend
+ * currently only stops on status change away from ok,
+ * reset, vmstop and such. If we do add code to start here,
+ * need to check vmstate, device state etc. */
+ return virtio_mmio_set_host_notifier_internal(proxy, n, assign, false);
+}
+
+/* virtio-mmio device */
static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
{
@@ -496,7 +539,6 @@ static void virtio_mmio_class_init(ObjectClass *klass, void *data)
dc->realize = virtio_mmio_realizefn;
dc->reset = virtio_mmio_reset;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
- dc->props = virtio_mmio_properties;
}
static const TypeInfo virtio_mmio_info = {
@@ -508,46 +550,6 @@ static const TypeInfo virtio_mmio_info = {
/* virtio-mmio-bus. */
-static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
-{
- BusState *virtio_mmio_bus;
- VirtIOMMIOProxy *virtio_mmio_proxy;
- char *proxy_path;
- SysBusDevice *proxy_sbd;
- char *path;
-
- virtio_mmio_bus = qdev_get_parent_bus(dev);
- virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
- proxy_path = qdev_get_dev_path(DEVICE(virtio_mmio_proxy));
-
- /*
- * If @format_transport_address is false, then we just perform the same as
- * virtio_bus_get_dev_path(): we delegate the address formatting for the
- * device on the virtio-mmio bus to the bus that the virtio-mmio proxy
- * (i.e., the device that implements the virtio-mmio bus) resides on. In
- * this case the base address of the virtio-mmio transport will be
- * invisible.
- */
- if (!virtio_mmio_proxy->format_transport_address) {
- return proxy_path;
- }
-
- /* Otherwise, we append the base address of the transport. */
- proxy_sbd = SYS_BUS_DEVICE(virtio_mmio_proxy);
- assert(proxy_sbd->num_mmio == 1);
- assert(proxy_sbd->mmio[0].memory == &virtio_mmio_proxy->iomem);
-
- if (proxy_path) {
- path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path,
- proxy_sbd->mmio[0].addr);
- } else {
- path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx,
- proxy_sbd->mmio[0].addr);
- }
- g_free(proxy_path);
- return path;
-}
-
static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *bus_class = BUS_CLASS(klass);
@@ -556,15 +558,10 @@ static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
k->notify = virtio_mmio_update_irq;
k->save_config = virtio_mmio_save_config;
k->load_config = virtio_mmio_load_config;
+ k->set_host_notifier = virtio_mmio_set_host_notifier;
k->set_guest_notifiers = virtio_mmio_set_guest_notifiers;
- k->ioeventfd_started = virtio_mmio_ioeventfd_started;
- k->ioeventfd_set_started = virtio_mmio_ioeventfd_set_started;
- k->ioeventfd_disabled = virtio_mmio_ioeventfd_disabled;
- k->ioeventfd_set_disabled = virtio_mmio_ioeventfd_set_disabled;
- k->ioeventfd_assign = virtio_mmio_ioeventfd_assign;
k->has_variable_vring_alignment = true;
bus_class->max_dev = 1;
- bus_class->get_dev_path = virtio_mmio_bus_get_dev_path;
}
static const TypeInfo virtio_mmio_bus_info = {
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 755f9218b..bfedbbf17 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -161,7 +161,7 @@ static bool virtio_pci_modern_state_needed(void *opaque)
{
VirtIOPCIProxy *proxy = opaque;
- return virtio_pci_modern(proxy);
+ return !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN);
}
static const VMStateDescription vmstate_virtio_pci_modern_state = {
@@ -262,46 +262,16 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
return 0;
}
-static bool virtio_pci_ioeventfd_started(DeviceState *d)
-{
- VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
-
- return proxy->ioeventfd_started;
-}
-
-static void virtio_pci_ioeventfd_set_started(DeviceState *d, bool started,
- bool err)
-{
- VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
-
- proxy->ioeventfd_started = started;
-}
-
-static bool virtio_pci_ioeventfd_disabled(DeviceState *d)
-{
- VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
-
- return proxy->ioeventfd_disabled ||
- !(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD);
-}
-
-static void virtio_pci_ioeventfd_set_disabled(DeviceState *d, bool disabled)
-{
- VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
-
- proxy->ioeventfd_disabled = disabled;
-}
-
#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x1000
-static int virtio_pci_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
- int n, bool assign)
+static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
+ int n, bool assign, bool set_handler)
{
- VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtQueue *vq = virtio_get_queue(vdev, n);
- bool legacy = virtio_pci_legacy(proxy);
- bool modern = virtio_pci_modern(proxy);
+ EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
+ bool legacy = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_LEGACY);
+ bool modern = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN);
bool fast_mmio = kvm_ioeventfd_any_length_enabled();
bool modern_pio = proxy->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY;
MemoryRegion *modern_mr = &proxy->notify.mr;
@@ -310,8 +280,16 @@ static int virtio_pci_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
hwaddr modern_addr = QEMU_VIRTIO_PCI_QUEUE_MEM_MULT *
virtio_get_queue_index(vq);
hwaddr legacy_addr = VIRTIO_PCI_QUEUE_NOTIFY;
+ int r = 0;
if (assign) {
+ r = event_notifier_init(notifier, 1);
+ if (r < 0) {
+ error_report("%s: unable to init event notifier: %d",
+ __func__, r);
+ return r;
+ }
+ virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
if (modern) {
if (fast_mmio) {
memory_region_add_eventfd(modern_mr, modern_addr, 0,
@@ -347,18 +325,68 @@ static int virtio_pci_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
memory_region_del_eventfd(legacy_mr, legacy_addr, 2,
true, n, notifier);
}
+ virtio_queue_set_host_notifier_fd_handler(vq, false, false);
+ event_notifier_cleanup(notifier);
}
- return 0;
+ return r;
}
static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
{
- virtio_bus_start_ioeventfd(&proxy->bus);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ int n, r;
+
+ if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
+ proxy->ioeventfd_disabled ||
+ proxy->ioeventfd_started) {
+ return;
+ }
+
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+
+ r = virtio_pci_set_host_notifier_internal(proxy, n, true, true);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+ proxy->ioeventfd_started = true;
+ return;
+
+assign_error:
+ while (--n >= 0) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+
+ r = virtio_pci_set_host_notifier_internal(proxy, n, false, false);
+ assert(r >= 0);
+ }
+ proxy->ioeventfd_started = false;
+ error_report("%s: failed. Fallback to a userspace (slower).", __func__);
}
static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
{
- virtio_bus_stop_ioeventfd(&proxy->bus);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ int r;
+ int n;
+
+ if (!proxy->ioeventfd_started) {
+ return;
+ }
+
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+
+ r = virtio_pci_set_host_notifier_internal(proxy, n, false, false);
+ assert(r >= 0);
+ }
+ proxy->ioeventfd_started = false;
}
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
@@ -699,13 +727,14 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev,
static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
unsigned int queue_no,
- unsigned int vector)
+ unsigned int vector,
+ MSIMessage msg)
{
VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
int ret;
if (irqfd->users == 0) {
- ret = kvm_irqchip_add_msi_route(kvm_state, vector, &proxy->pci_dev);
+ ret = kvm_irqchip_add_msi_route(kvm_state, msg, &proxy->pci_dev);
if (ret < 0) {
return ret;
}
@@ -732,7 +761,9 @@ static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtQueue *vq = virtio_get_queue(vdev, queue_no);
EventNotifier *n = virtio_queue_get_guest_notifier(vq);
- return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq);
+ int ret;
+ ret = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq);
+ return ret;
}
static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
@@ -756,6 +787,7 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
unsigned int vector;
int ret, queue_no;
+ MSIMessage msg;
for (queue_no = 0; queue_no < nvqs; queue_no++) {
if (!virtio_queue_get_num(vdev, queue_no)) {
@@ -765,7 +797,8 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
if (vector >= msix_nr_vectors_allocated(dev)) {
continue;
}
- ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector);
+ msg = msix_get_message(dev, vector);
+ ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector, msg);
if (ret < 0) {
goto undo;
}
@@ -842,7 +875,6 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
if (ret < 0) {
return ret;
}
- kvm_irqchip_commit_routes(kvm_state);
}
}
@@ -1080,6 +1112,24 @@ assign_error:
return r;
}
+static int virtio_pci_set_host_notifier(DeviceState *d, int n, bool assign)
+{
+ VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+
+ /* Stop using ioeventfd for virtqueue kick if the device starts using host
+ * notifiers. This makes it easy to avoid stepping on each others' toes.
+ */
+ proxy->ioeventfd_disabled = assign;
+ if (assign) {
+ virtio_pci_stop_ioeventfd(proxy);
+ }
+ /* We don't need to start here: it's not needed because backend
+ * currently only stops on status change away from ok,
+ * reset, vmstop and such. If we do add code to start here,
+ * need to check vmstate, device state etc. */
+ return virtio_pci_set_host_notifier_internal(proxy, n, assign, false);
+}
+
static void virtio_pci_vmstate_change(DeviceState *d, bool running)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
@@ -1574,8 +1624,8 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
VirtioBusState *bus = &proxy->bus;
- bool legacy = virtio_pci_legacy(proxy);
- bool modern = virtio_pci_modern(proxy);
+ bool legacy = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_LEGACY);
+ bool modern = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN);
bool modern_pio = proxy->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY;
uint8_t *config;
uint32_t size;
@@ -1694,7 +1744,7 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
static void virtio_pci_device_unplugged(DeviceState *d)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
- bool modern = virtio_pci_modern(proxy);
+ bool modern = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN);
bool modern_pio = proxy->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY;
virtio_pci_stop_ioeventfd(proxy);
@@ -1714,8 +1764,6 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev);
- bool pcie_port = pci_bus_is_express(pci_dev->bus) &&
- !pci_bus_is_root(pci_dev->bus);
/*
* virtio pci bar layout used by default.
@@ -1766,11 +1814,8 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
address_space_init(&proxy->modern_as, &proxy->modern_cfg, "virtio-pci-cfg-as");
- if (proxy->disable_legacy == ON_OFF_AUTO_AUTO) {
- proxy->disable_legacy = pcie_port ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
- }
-
- if (pcie_port && pci_is_express(pci_dev)) {
+ if (pci_is_express(pci_dev) && pci_bus_is_express(pci_dev->bus) &&
+ !pci_bus_is_root(pci_dev->bus)) {
int pos;
pos = pcie_endpoint_cap_init(pci_dev, 0);
@@ -1824,9 +1869,10 @@ static void virtio_pci_reset(DeviceState *qdev)
static Property virtio_pci_properties[] = {
DEFINE_PROP_BIT("virtio-pci-bus-master-bug-migration", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT, false),
- DEFINE_PROP_ON_OFF_AUTO("disable-legacy", VirtIOPCIProxy, disable_legacy,
- ON_OFF_AUTO_AUTO),
- DEFINE_PROP_BOOL("disable-modern", VirtIOPCIProxy, disable_modern, false),
+ DEFINE_PROP_BIT("disable-legacy", VirtIOPCIProxy, flags,
+ VIRTIO_PCI_FLAG_DISABLE_LEGACY_BIT, false),
+ DEFINE_PROP_BIT("disable-modern", VirtIOPCIProxy, flags,
+ VIRTIO_PCI_FLAG_DISABLE_MODERN_BIT, true),
DEFINE_PROP_BIT("migrate-extra", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT, true),
DEFINE_PROP_BIT("modern-pio-notify", VirtIOPCIProxy, flags,
@@ -1843,7 +1889,7 @@ static void virtio_pci_dc_realize(DeviceState *qdev, Error **errp)
PCIDevice *pci_dev = &proxy->pci_dev;
if (!(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_PCIE) &&
- virtio_pci_modern(proxy)) {
+ !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN)) {
pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
}
@@ -2305,7 +2351,9 @@ static void virtio_input_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
DeviceState *vdev = DEVICE(&vinput->vdev);
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
- virtio_pci_force_virtio_1(vpci_dev);
+ /* force virtio-1.0 */
+ vpci_dev->flags &= ~VIRTIO_PCI_FLAG_DISABLE_MODERN;
+ vpci_dev->flags |= VIRTIO_PCI_FLAG_DISABLE_LEGACY;
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
@@ -2442,16 +2490,12 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
k->load_extra_state = virtio_pci_load_extra_state;
k->has_extra_state = virtio_pci_has_extra_state;
k->query_guest_notifiers = virtio_pci_query_guest_notifiers;
+ k->set_host_notifier = virtio_pci_set_host_notifier;
k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
k->vmstate_change = virtio_pci_vmstate_change;
k->device_plugged = virtio_pci_device_plugged;
k->device_unplugged = virtio_pci_device_unplugged;
k->query_nvectors = virtio_pci_query_nvectors;
- k->ioeventfd_started = virtio_pci_ioeventfd_started;
- k->ioeventfd_set_started = virtio_pci_ioeventfd_set_started;
- k->ioeventfd_disabled = virtio_pci_ioeventfd_disabled;
- k->ioeventfd_set_disabled = virtio_pci_ioeventfd_set_disabled;
- k->ioeventfd_assign = virtio_pci_ioeventfd_assign;
}
static const TypeInfo virtio_pci_bus_info = {
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 25fbf8a37..e4548c2f9 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -61,6 +61,8 @@ typedef struct VirtioBusClass VirtioPCIBusClass;
enum {
VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT,
+ VIRTIO_PCI_FLAG_DISABLE_LEGACY_BIT,
+ VIRTIO_PCI_FLAG_DISABLE_MODERN_BIT,
VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT,
VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT,
VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT,
@@ -75,6 +77,8 @@ enum {
#define VIRTIO_PCI_FLAG_USE_IOEVENTFD (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT)
/* virtio version flags */
+#define VIRTIO_PCI_FLAG_DISABLE_LEGACY (1 << VIRTIO_PCI_FLAG_DISABLE_LEGACY_BIT)
+#define VIRTIO_PCI_FLAG_DISABLE_MODERN (1 << VIRTIO_PCI_FLAG_DISABLE_MODERN_BIT)
#define VIRTIO_PCI_FLAG_DISABLE_PCIE (1 << VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT)
/* migrate extra state */
@@ -140,8 +144,6 @@ struct VirtIOPCIProxy {
uint32_t modern_mem_bar;
int config_cap;
uint32_t flags;
- bool disable_modern;
- OnOffAuto disable_legacy;
uint32_t class_code;
uint32_t nvectors;
uint32_t dfselect;
@@ -156,21 +158,6 @@ struct VirtIOPCIProxy {
VirtioBusState bus;
};
-static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
-{
- return !proxy->disable_modern;
-}
-
-static inline bool virtio_pci_legacy(VirtIOPCIProxy *proxy)
-{
- return proxy->disable_legacy == ON_OFF_AUTO_OFF;
-}
-
-static inline void virtio_pci_force_virtio_1(VirtIOPCIProxy *proxy)
-{
- proxy->disable_modern = false;
- proxy->disable_legacy = ON_OFF_AUTO_ON;
-}
/*
* virtio-scsi-pci: This extends VirtioPCIProxy.
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index cd8ca1017..6b991a764 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -120,12 +120,22 @@ static uint64_t get_features(VirtIODevice *vdev, uint64_t f, Error **errp)
return f;
}
-static int virtio_rng_load(QEMUFile *f, void *opaque, size_t size)
+static void virtio_rng_save(QEMUFile *f, void *opaque)
+{
+ VirtIODevice *vdev = opaque;
+
+ virtio_save(vdev, f);
+}
+
+static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIORNG *vrng = opaque;
int ret;
- ret = virtio_load(VIRTIO_DEVICE(vrng), f, 1);
+ if (version_id != 1) {
+ return -EINVAL;
+ }
+ ret = virtio_load(VIRTIO_DEVICE(vrng), f, version_id);
if (ret != 0) {
return ret;
}
@@ -204,6 +214,8 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
vrng->rate_limit_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
check_rate_limit, vrng);
vrng->activate_timer = true;
+ register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save,
+ virtio_rng_load, vrng);
}
static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
@@ -213,11 +225,10 @@ static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
timer_del(vrng->rate_limit_timer);
timer_free(vrng->rate_limit_timer);
+ unregister_savevm(dev, "virtio-rng", vrng);
virtio_cleanup(vdev);
}
-VMSTATE_VIRTIO_DEVICE(rng, 1, virtio_rng_load, virtio_vmstate_save);
-
static Property virtio_rng_properties[] = {
/* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s. If
* you have an entropy source capable of generating more entropy than this
@@ -235,7 +246,6 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->props = virtio_rng_properties;
- dc->vmsd = &vmstate_virtio_rng;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
vdc->realize = virtio_rng_device_realize;
vdc->unrealize = virtio_rng_device_unrealize;
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 74c085c74..8ed260a61 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -95,9 +95,8 @@ struct VirtQueue
int inuse;
uint16_t vector;
- VirtIOHandleOutput handle_output;
- VirtIOHandleOutput handle_aio_output;
- bool use_aio;
+ void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
+ void (*handle_aio_output)(VirtIODevice *vdev, VirtQueue *vq);
VirtIODevice *vdev;
EventNotifier guest_notifier;
EventNotifier host_notifier;
@@ -268,7 +267,6 @@ void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
unsigned int len)
{
vq->last_avail_idx--;
- vq->inuse--;
virtqueue_unmap_sg(vq, elem, len);
}
@@ -459,11 +457,6 @@ static void virtqueue_map_desc(unsigned int *p_num_sg, hwaddr *addr, struct iove
unsigned num_sg = *p_num_sg;
assert(num_sg <= max_num_sg);
- if (!sz) {
- error_report("virtio: zero sized buffers are not allowed");
- exit(1);
- }
-
while (sz) {
hwaddr len = sz;
@@ -1074,6 +1067,13 @@ int virtio_get_num_queues(VirtIODevice *vdev)
return i;
}
+int virtio_queue_get_id(VirtQueue *vq)
+{
+ VirtIODevice *vdev = vq->vdev;
+ assert(vq >= &vdev->vq[0] && vq < &vdev->vq[VIRTIO_QUEUE_MAX]);
+ return vq - &vdev->vq[0];
+}
+
void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
{
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
@@ -1142,9 +1142,8 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector)
}
}
-static VirtQueue *virtio_add_queue_internal(VirtIODevice *vdev, int queue_size,
- VirtIOHandleOutput handle_output,
- bool use_aio)
+VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
+ void (*handle_output)(VirtIODevice *, VirtQueue *))
{
int i;
@@ -1161,28 +1160,10 @@ static VirtQueue *virtio_add_queue_internal(VirtIODevice *vdev, int queue_size,
vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
vdev->vq[i].handle_output = handle_output;
vdev->vq[i].handle_aio_output = NULL;
- vdev->vq[i].use_aio = use_aio;
return &vdev->vq[i];
}
-/* Add a virt queue and mark AIO.
- * An AIO queue will use the AioContext based event interface instead of the
- * default IOHandler and EventNotifier interface.
- */
-VirtQueue *virtio_add_queue_aio(VirtIODevice *vdev, int queue_size,
- VirtIOHandleOutput handle_output)
-{
- return virtio_add_queue_internal(vdev, queue_size, handle_output, true);
-}
-
-/* Add a normal virt queue (on the contrary to the AIO version above. */
-VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
- VirtIOHandleOutput handle_output)
-{
- return virtio_add_queue_internal(vdev, queue_size, handle_output, false);
-}
-
void virtio_del_queue(VirtIODevice *vdev, int n)
{
if (n < 0 || n >= VIRTIO_QUEUE_MAX) {
@@ -1475,12 +1456,6 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
vmstate_save_state(f, &vmstate_virtio, vdev, NULL);
}
-/* A wrapper for use as a VMState .put function */
-void virtio_vmstate_save(QEMUFile *f, void *opaque, size_t size)
-{
- virtio_save(VIRTIO_DEVICE(opaque), f);
-}
-
static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val)
{
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
@@ -1649,21 +1624,6 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
}
vdev->vq[i].used_idx = vring_used_idx(&vdev->vq[i]);
vdev->vq[i].shadow_avail_idx = vring_avail_idx(&vdev->vq[i]);
-
- /*
- * Some devices migrate VirtQueueElements that have been popped
- * from the avail ring but not yet returned to the used ring.
- */
- vdev->vq[i].inuse = vdev->vq[i].last_avail_idx -
- vdev->vq[i].used_idx;
- if (vdev->vq[i].inuse > vdev->vq[i].vring.num) {
- error_report("VQ %d size 0x%x < last_avail_idx 0x%x - "
- "used_idx 0x%x",
- i, vdev->vq[i].vring.num,
- vdev->vq[i].last_avail_idx,
- vdev->vq[i].used_idx);
- return -1;
- }
}
}
@@ -1856,7 +1816,8 @@ static void virtio_queue_host_notifier_aio_read(EventNotifier *n)
}
void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx,
- VirtIOHandleOutput handle_output)
+ void (*handle_output)(VirtIODevice *,
+ VirtQueue *))
{
if (handle_output) {
vq->handle_aio_output = handle_output;
@@ -1882,21 +1843,11 @@ static void virtio_queue_host_notifier_read(EventNotifier *n)
void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign,
bool set_handler)
{
- AioContext *ctx = qemu_get_aio_context();
if (assign && set_handler) {
- if (vq->use_aio) {
- aio_set_event_notifier(ctx, &vq->host_notifier, true,
+ event_notifier_set_handler(&vq->host_notifier, true,
virtio_queue_host_notifier_read);
- } else {
- event_notifier_set_handler(&vq->host_notifier, true,
- virtio_queue_host_notifier_read);
- }
} else {
- if (vq->use_aio) {
- aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL);
- } else {
- event_notifier_set_handler(&vq->host_notifier, true, NULL);
- }
+ event_notifier_set_handler(&vq->host_notifier, true, NULL);
}
if (!assign) {
/* Test and clear notifier before after disabling event,
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 2aeaf1fbc..bbf3646ba 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -143,7 +143,7 @@ void watchdog_perform_action(void)
case WDT_NMI:
qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_INJECT_NMI,
&error_abort);
- nmi_monitor_handle(0, NULL);
+ inject_nmi();
break;
}
}
diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
index a7b64e2c4..f54a35a0e 100644
--- a/hw/watchdog/wdt_diag288.c
+++ b/hw/watchdog/wdt_diag288.c
@@ -16,7 +16,6 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "hw/watchdog/wdt_diag288.h"
-#include "qemu/log.h"
static WatchdogTimerModel model = {
.wdt_name = TYPE_WDT_DIAG288,
diff --git a/hw/xen/xen-host-pci-device.h b/hw/xen/xen-host-pci-device.h
index 4d8d34ecb..6acf36e13 100644
--- a/hw/xen/xen-host-pci-device.h
+++ b/hw/xen/xen-host-pci-device.h
@@ -55,4 +55,4 @@ int xen_host_pci_set_block(XenHostPCIDevice *d, int pos, uint8_t *buf,
int xen_host_pci_find_ext_cap_offset(XenHostPCIDevice *s, uint32_t cap);
-#endif /* XEN_HOST_PCI_DEVICE_H */
+#endif /* !XEN_HOST_PCI_DEVICE_H_ */
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index 69a238817..60575ad38 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -23,20 +23,16 @@
*/
#include "qemu/osdep.h"
+#include <sys/mman.h>
#include <sys/signal.h>
#include "hw/hw.h"
-#include "hw/sysbus.h"
#include "sysemu/char.h"
#include "qemu/log.h"
#include "hw/xen/xen_backend.h"
#include <xen/grant_table.h>
-#define TYPE_XENSYSDEV "xensysdev"
-
-DeviceState *xen_sysdev;
-
/* ------------------------------------------------------------- */
/* public */
@@ -46,36 +42,11 @@ struct xs_handle *xenstore = NULL;
const char *xen_protocol;
/* private */
-struct xs_dirs {
- char *xs_dir;
- QTAILQ_ENTRY(xs_dirs) list;
-};
-static QTAILQ_HEAD(xs_dirs_head, xs_dirs) xs_cleanup =
- QTAILQ_HEAD_INITIALIZER(xs_cleanup);
-
static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = QTAILQ_HEAD_INITIALIZER(xendevs);
static int debug = 0;
/* ------------------------------------------------------------- */
-static void xenstore_cleanup_dir(char *dir)
-{
- struct xs_dirs *d;
-
- d = g_malloc(sizeof(*d));
- d->xs_dir = dir;
- QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
-}
-
-void xen_config_cleanup(void)
-{
- struct xs_dirs *d;
-
- QTAILQ_FOREACH(d, &xs_cleanup, list) {
- xs_rm(xenstore, 0, d->xs_dir);
- }
-}
-
int xenstore_write_str(const char *base, const char *node, const char *val)
{
char abspath[XEN_BUFSIZE];
@@ -104,30 +75,6 @@ char *xenstore_read_str(const char *base, const char *node)
return ret;
}
-int xenstore_mkdir(char *path, int p)
-{
- struct xs_permissions perms[2] = {
- {
- .id = 0, /* set owner: dom0 */
- }, {
- .id = xen_domid,
- .perms = p,
- }
- };
-
- if (!xs_mkdir(xenstore, 0, path)) {
- xen_be_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
- return -1;
- }
- xenstore_cleanup_dir(g_strdup(path));
-
- if (!xs_set_permissions(xenstore, 0, path, perms, 2)) {
- xen_be_printf(NULL, 0, "xs_set_permissions %s: failed\n", path);
- return -1;
- }
- return 0;
-}
-
int xenstore_write_int(const char *base, const char *node, int ival)
{
char val[12];
@@ -321,28 +268,48 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
/*
* release xen backend device.
*/
-static void xen_be_del_xendev(struct XenDevice *xendev)
+static struct XenDevice *xen_be_del_xendev(int dom, int dev)
{
- if (xendev->ops->free) {
- xendev->ops->free(xendev);
- }
+ struct XenDevice *xendev, *xnext;
- if (xendev->fe) {
- char token[XEN_BUFSIZE];
- snprintf(token, sizeof(token), "fe:%p", xendev);
- xs_unwatch(xenstore, xendev->fe, token);
- g_free(xendev->fe);
- }
+ /*
+ * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next) but
+ * we save the next pointer in xnext because we might free xendev.
+ */
+ xnext = xendevs.tqh_first;
+ while (xnext) {
+ xendev = xnext;
+ xnext = xendev->next.tqe_next;
- if (xendev->evtchndev != NULL) {
- xenevtchn_close(xendev->evtchndev);
- }
- if (xendev->gnttabdev != NULL) {
- xengnttab_close(xendev->gnttabdev);
- }
+ if (xendev->dom != dom) {
+ continue;
+ }
+ if (xendev->dev != dev && dev != -1) {
+ continue;
+ }
+
+ if (xendev->ops->free) {
+ xendev->ops->free(xendev);
+ }
- QTAILQ_REMOVE(&xendevs, xendev, next);
- g_free(xendev);
+ if (xendev->fe) {
+ char token[XEN_BUFSIZE];
+ snprintf(token, sizeof(token), "fe:%p", xendev);
+ xs_unwatch(xenstore, xendev->fe, token);
+ g_free(xendev->fe);
+ }
+
+ if (xendev->evtchndev != NULL) {
+ xenevtchn_close(xendev->evtchndev);
+ }
+ if (xendev->gnttabdev != NULL) {
+ xengnttab_close(xendev->gnttabdev);
+ }
+
+ QTAILQ_REMOVE(&xendevs, xendev, next);
+ g_free(xendev);
+ }
+ return NULL;
}
/*
@@ -662,7 +629,7 @@ static void xenstore_update_be(char *watch, char *type, int dom,
if (xendev != NULL) {
bepath = xs_read(xenstore, 0, xendev->be, &len);
if (bepath == NULL) {
- xen_be_del_xendev(xendev);
+ xen_be_del_xendev(dom, dev);
} else {
free(bepath);
xen_be_backend_changed(xendev, path);
@@ -747,10 +714,6 @@ int xen_be_init(void)
/* Check if xen_init() have been called */
goto err;
}
-
- xen_sysdev = qdev_create(NULL, TYPE_XENSYSDEV);
- qdev_init_nofail(xen_sysdev);
-
return 0;
err:
@@ -763,33 +726,9 @@ err:
int xen_be_register(const char *type, struct XenDevOps *ops)
{
- char path[50];
- int rc;
-
- if (ops->backend_register) {
- rc = ops->backend_register();
- if (rc) {
- return rc;
- }
- }
-
- snprintf(path, sizeof(path), "device-model/%u/backends/%s", xen_domid,
- type);
- xenstore_mkdir(path, XS_PERM_NONE);
-
return xenstore_scan(type, xen_domid, ops);
}
-void xen_be_register_common(void)
-{
- xen_be_register("console", &xen_console_ops);
- xen_be_register("vkbd", &xen_kbdmouse_ops);
- xen_be_register("qdisk", &xen_blkdev_ops);
-#ifdef CONFIG_USB_LIBUSB
- xen_be_register("qusb", &xen_usb_ops);
-#endif
-}
-
int xen_be_bind_evtchn(struct XenDevice *xendev)
{
if (xendev->local_port != -1) {
@@ -861,35 +800,3 @@ void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...
}
qemu_log_flush();
}
-
-static int xen_sysdev_init(SysBusDevice *dev)
-{
- return 0;
-}
-
-static Property xen_sysdev_properties[] = {
- {/* end of property list */},
-};
-
-static void xen_sysdev_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = xen_sysdev_init;
- dc->props = xen_sysdev_properties;
-}
-
-static const TypeInfo xensysdev_info = {
- .name = TYPE_XENSYSDEV,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(SysBusDevice),
- .class_init = xen_sysdev_class_init,
-};
-
-static void xenbe_register_types(void)
-{
- type_register_static(&xensysdev_info);
-}
-
-type_init(xenbe_register_types);
diff --git a/hw/xen/xen_devconfig.c b/hw/xen/xen_devconfig.c
index b7d290df6..1f30fe4f5 100644
--- a/hw/xen/xen_devconfig.c
+++ b/hw/xen/xen_devconfig.c
@@ -5,6 +5,54 @@
/* ------------------------------------------------------------- */
+struct xs_dirs {
+ char *xs_dir;
+ QTAILQ_ENTRY(xs_dirs) list;
+};
+static QTAILQ_HEAD(xs_dirs_head, xs_dirs) xs_cleanup = QTAILQ_HEAD_INITIALIZER(xs_cleanup);
+
+static void xen_config_cleanup_dir(char *dir)
+{
+ struct xs_dirs *d;
+
+ d = g_malloc(sizeof(*d));
+ d->xs_dir = dir;
+ QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
+}
+
+void xen_config_cleanup(void)
+{
+ struct xs_dirs *d;
+
+ QTAILQ_FOREACH(d, &xs_cleanup, list) {
+ xs_rm(xenstore, 0, d->xs_dir);
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+static int xen_config_dev_mkdir(char *dev, int p)
+{
+ struct xs_permissions perms[2] = {{
+ .id = 0, /* set owner: dom0 */
+ },{
+ .id = xen_domid,
+ .perms = p,
+ }};
+
+ if (!xs_mkdir(xenstore, 0, dev)) {
+ xen_be_printf(NULL, 0, "xs_mkdir %s: failed\n", dev);
+ return -1;
+ }
+ xen_config_cleanup_dir(g_strdup(dev));
+
+ if (!xs_set_permissions(xenstore, 0, dev, perms, 2)) {
+ xen_be_printf(NULL, 0, "xs_set_permissions %s: failed\n", dev);
+ return -1;
+ }
+ return 0;
+}
+
static int xen_config_dev_dirs(const char *ftype, const char *btype, int vdev,
char *fe, char *be, int len)
{
@@ -18,8 +66,8 @@ static int xen_config_dev_dirs(const char *ftype, const char *btype, int vdev,
snprintf(be, len, "%s/backend/%s/%d/%d", dom, btype, xen_domid, vdev);
free(dom);
- xenstore_mkdir(fe, XS_PERM_READ | XS_PERM_WRITE);
- xenstore_mkdir(be, XS_PERM_READ);
+ xen_config_dev_mkdir(fe, XS_PERM_READ | XS_PERM_WRITE);
+ xen_config_dev_mkdir(be, XS_PERM_READ);
return 0;
}
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
index 191d9caea..c2f8e1fc2 100644
--- a/hw/xen/xen_pt.h
+++ b/hw/xen/xen_pt.h
@@ -332,4 +332,4 @@ int xen_pt_register_vga_regions(XenHostPCIDevice *dev);
int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev);
void xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev,
Error **errp);
-#endif /* XEN_PT_H */
+#endif /* !XEN_PT_H */
diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
index 6f18366f6..9869ffda0 100644
--- a/hw/xen/xen_pt_config_init.c
+++ b/hw/xen/xen_pt_config_init.c
@@ -2049,8 +2049,9 @@ void xen_pt_config_init(XenPCIPassthroughState *s, Error **errp)
for (j = 0; regs->size != 0; j++, regs++) {
xen_pt_config_reg_init(s, reg_grp_entry, regs, &err);
if (err) {
- error_append_hint(&err, "Failed to init register %d"
- " offsets 0x%x in grp_type = 0x%x (%d/%zu)", j,
+ error_append_hint(&err, "Failed to initialize %d/%zu"
+ " reg 0x%x in grp_type = 0x%x (%d/%zu)",
+ j, ARRAY_SIZE(xen_pt_emu_reg_grps[i].emu_regs),
regs->offset, xen_pt_emu_reg_grps[i].grp_type,
i, ARRAY_SIZE(xen_pt_emu_reg_grps));
error_propagate(errp, err);
diff --git a/hw/xen/xen_pt_msi.c b/hw/xen/xen_pt_msi.c
index 62add0639..9a16f2bff 100644
--- a/hw/xen/xen_pt_msi.c
+++ b/hw/xen/xen_pt_msi.c
@@ -10,6 +10,7 @@
*/
#include "qemu/osdep.h"
+#include <sys/mman.h>
#include "hw/xen/xen_backend.h"
#include "xen_pt.h"
diff --git a/hw/xenpv/xen_domainbuild.h b/hw/xenpv/xen_domainbuild.h
index 652d9b410..29a91ea7b 100644
--- a/hw/xenpv/xen_domainbuild.h
+++ b/hw/xenpv/xen_domainbuild.h
@@ -1,5 +1,5 @@
#ifndef QEMU_HW_XEN_DOMAINBUILD_H
-#define QEMU_HW_XEN_DOMAINBUILD_H
+#define QEMU_HW_XEN_DOMAINBUILD_H 1
#include "hw/xen/xen_common.h"
diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c
index 79aef4ecc..fc1353599 100644
--- a/hw/xenpv/xen_machine_pv.c
+++ b/hw/xenpv/xen_machine_pv.c
@@ -67,8 +67,10 @@ static void xen_init_pv(MachineState *machine)
break;
}
- xen_be_register_common();
+ xen_be_register("console", &xen_console_ops);
+ xen_be_register("vkbd", &xen_kbdmouse_ops);
xen_be_register("vfb", &xen_framebuffer_ops);
+ xen_be_register("qdisk", &xen_blkdev_ops);
xen_be_register("qnic", &xen_netdev_ops);
/* configure framebuffer */
diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h
index ade7891ec..955f4e86e 100644
--- a/hw/xtensa/bootparam.h
+++ b/hw/xtensa/bootparam.h
@@ -1,5 +1,5 @@
-#ifndef HW_XTENSA_BOOTPARAM_H
-#define HW_XTENSA_BOOTPARAM_H
+#ifndef HW_XTENSA_BOOTPARAM
+#define HW_XTENSA_BOOTPARAM
#define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/
#define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */
diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c
index 2bed64f15..c835bd009 100644
--- a/hw/xtensa/pic_cpu.c
+++ b/hw/xtensa/pic_cpu.c
@@ -26,7 +26,6 @@
*/
#include "qemu/osdep.h"
-#include "cpu.h"
#include "hw/hw.h"
#include "qemu/log.h"
#include "qemu/timer.h"
@@ -122,8 +121,8 @@ void xtensa_rearm_ccompare_timer(CPUXtensaState *env)
}
env->wake_ccount = wake_ccount;
timer_mod(env->ccompare_timer, env->halt_clock +
- (uint64_t)(wake_ccount - env->sregs[CCOUNT]) *
- 1000000 / env->config->clock_freq_khz);
+ muldiv64(wake_ccount - env->sregs[CCOUNT],
+ 1000000, env->config->clock_freq_khz));
}
static void xtensa_ccompare_cb(void *opaque)
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index ac7594948..2d117369a 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -165,7 +165,7 @@ static pflash_t *xtfpga_flash_init(MemoryRegion *address_space,
qdev_prop_set_uint32(dev, "num-blocks",
board->flash_size / board->flash_sector_size);
qdev_prop_set_uint64(dev, "sector-length", board->flash_sector_size);
- qdev_prop_set_uint8(dev, "width", 2);
+ qdev_prop_set_uint8(dev, "width", 4);
qdev_prop_set_bit(dev, "big-endian", be);
qdev_prop_set_string(dev, "name", "lx60.io.flash");
qdev_init_nofail(dev);