aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-02-02 18:56:32 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-02-02 18:56:32 +0000
commit4f2fdb10b5f78ba95300648fce74c42d3e4511c7 (patch)
treee944136735b09304a5b02c79097b8bb0b763d6d2 /hw
parent29b008927ef6e3fbb70e6607b25d3fcae26a5190 (diff)
parentf09c2b7ba9908714a3e2f1decd989462536cf731 (diff)
downloadqemu-4f2fdb10b5f78ba95300648fce74c42d3e4511c7.zip
qemu-4f2fdb10b5f78ba95300648fce74c42d3e4511c7.tar.gz
qemu-4f2fdb10b5f78ba95300648fce74c42d3e4511c7.tar.bz2
Merge tag 'pull-target-arm-20240202' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target/arm: fix exception syndrome for AArch32 bkpt insn pci, vmbus, adb, s390x/css-bridge: Switch buses to 3-phase reset system/vl.c: Fix handling of '-serial none -serial something' target/arm: Add ID_AA64ZFR0_EL1.B16B16 to the exposed-to-userspace set tests/qtest/xlnx-versal-trng-test.c: Drop use of variable length array target/arm: Reinstate "vfp" property on AArch32 CPUs doc/sphinx/hxtool.py: add optional label argument to SRST directive hw/arm: Check for CPU types in machine_run_board_init() for various boards pci-host: designware: Limit value range of iATU viewport register hw/arm: Convert some DPRINTF macros to trace events and guest errors hw/arm: NPCM7XX SoC: Add GMAC ethernet controller devices hw/arm: Implement BCM2835 SPI Controller # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmW9C84ZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3qS6D/wM0/JGEYfaadpuMEOAx4PG # AnfScbPqVhx9J31P2Ks3VrB5F108aq/SaL2BmCb3BLF/ECChlhBXIjd7ukdHstts # F1TvqtvLGDZQz6wSVUeB0YOvAjGa3vIskn+Xvk9e6Ne6PcXgVnxAof/cPsXUiYNy # 6DJjNiLJ/a9Xgq9rjFO6vzW3AL95U6/FmD2F0pOotWXERhNhoyYVV6RtyeqKlDQP # yFVk5h601YURk9PeNZn9zpOpZqjAM7PxyF3X50N3Sv+G0uoKSr6b+c3/fDJbJo3+ # 0LXomEa8hdheQxm1dLY5OD0JX3bvYxwH41bDg9B0iEdjxUdXt6LfXI9Nvw9BAwix # 8AcGJJUaL4XU4uPfHBpRJApM15+MRb0hqfv4ZcGk8e67IIqVeDbKL2clTQGoHSg1 # KaB0POhtFx//M/uBOyk/FR2gb2eBNU8GuoCgxdDwh0K5ylcaK1YPiX4Tcglu4iS0 # Frvazphb2pO1BK6JiJwN2/9ezzDkDJqTKoSqdc4g3ETVOGnxr+tXwcds3t2iK3g2 # y+pgijDOAT3bJO5kYeGvhoEJPKqXwJ3UQ8zTJsU2XSYwBjIyv5V3oOn6elwYJaWq # yUDTC3QEK61KfnQnfTyLfdGWX1aVzHnYLWmQdO+3cczuQU0s0MP246Z1GAgDtgvD # jGjDBz6mryWvP2H0xSmERQ== # =azdP # -----END PGP SIGNATURE----- # gpg: Signature made Fri 02 Feb 2024 15:35:42 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20240202' of https://git.linaro.org/people/pmaydell/qemu-arm: (36 commits) hw/arm: Connect SPI Controller to BCM2835 hw/ssi: Implement BCM2835 SPI Controller tests/qtest: Adding PCS Module test to GMAC Qtest hw/net: GMAC Tx Implementation hw/net: GMAC Rx Implementation tests/qtest: Creating qtest for GMAC Module hw/arm: Add GMAC devices to NPCM7XX SoC hw/net: Add NPCMXXX GMAC device hw/xen: convert stderr prints to error/warn reports hw/xen/xen-hvm-common.c: convert DPRINTF to tracepoints hw/xen/xen-mapcache.c: convert DPRINTF to tracepoints hw/arm/xen_arm.c: convert DPRINTF to trace events and error/warn reports hw/arm/z2: convert DPRINTF to trace events and guest errors hw/arm/strongarm.c: convert DPRINTF to trace events and guest errors pci-host: designware: Limit value range of iATU viewport register hw/arm/zynq: Check for CPU types in machine_run_board_init() hw/arm/vexpress: Check for CPU types in machine_run_board_init() hw/arm/npcm7xx_boards: Simplify setting MachineClass::valid_cpu_types[] hw/arm/musca: Simplify setting MachineClass::valid_cpu_types[] hw/arm/msf2: Simplify setting MachineClass::valid_cpu_types[] ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/Kconfig1
-rw-r--r--hw/arm/bcm2835_peripherals.c17
-rw-r--r--hw/arm/exynos4210.c1
-rw-r--r--hw/arm/exynos4_boards.c8
-rw-r--r--hw/arm/highbank.c11
-rw-r--r--hw/arm/msf2-soc.c3
-rw-r--r--hw/arm/msf2-som.c4
-rw-r--r--hw/arm/musca.c1
-rw-r--r--hw/arm/npcm7xx.c37
-rw-r--r--hw/arm/npcm7xx_boards.c1
-rw-r--r--hw/arm/strongarm.c82
-rw-r--r--hw/arm/trace-events15
-rw-r--r--hw/arm/vexpress.c12
-rw-r--r--hw/arm/xen_arm.c23
-rw-r--r--hw/arm/xilinx_zynq.c6
-rw-r--r--hw/arm/z2.c27
-rw-r--r--hw/core/bus.c67
-rw-r--r--hw/hyperv/vmbus.c7
-rw-r--r--hw/input/adb.c7
-rw-r--r--hw/net/meson.build2
-rw-r--r--hw/net/npcm_gmac.c942
-rw-r--r--hw/net/trace-events19
-rw-r--r--hw/pci-host/designware.c2
-rw-r--r--hw/pci/pci.c10
-rw-r--r--hw/s390x/css-bridge.c5
-rw-r--r--hw/ssi/Kconfig4
-rw-r--r--hw/ssi/bcm2835_spi.c288
-rw-r--r--hw/ssi/meson.build1
-rw-r--r--hw/xen/trace-events21
-rw-r--r--hw/xen/xen-hvm-common.c47
-rw-r--r--hw/xen/xen-mapcache.c59
31 files changed, 1518 insertions, 212 deletions
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index db08a00..980b14d 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -429,6 +429,7 @@ config RASPI
select PL011 # UART
select SDHCI
select USB_DWC2
+ select BCM2835_SPI
config STM32F100_SOC
bool
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 0233038..d5573fd 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -144,6 +144,10 @@ static void bcm2835_peripherals_init(Object *obj)
/* Power Management */
object_initialize_child(obj, "powermgt", &s->powermgt,
TYPE_BCM2835_POWERMGT);
+
+ /* SPI */
+ object_initialize_child(obj, "bcm2835-spi0", &s->spi[0],
+ TYPE_BCM2835_SPI);
}
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
@@ -402,11 +406,22 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(&s->peri_mr, PM_OFFSET,
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->powermgt), 0));
+ /* SPI */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[0]), errp)) {
+ return;
+ }
+
+ memory_region_add_subregion(&s->peri_mr, SPI0_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->spi[0]), 0));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[0]), 0,
+ qdev_get_gpio_in_named(DEVICE(&s->ic),
+ BCM2835_IC_GPU_IRQ,
+ INTERRUPT_SPI));
+
create_unimp(s, &s->txp, "bcm2835-txp", TXP_OFFSET, 0x1000);
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
create_unimp(s, &s->smi, "bcm2835-smi", SMI_OFFSET, 0x100);
- create_unimp(s, &s->spi[0], "bcm2835-spi0", SPI0_OFFSET, 0x20);
create_unimp(s, &s->bscsl, "bcm2835-spis", BSC_SL_OFFSET, 0x100);
create_unimp(s, &s->i2c[0], "bcm2835-i2c0", BSC0_OFFSET, 0x20);
create_unimp(s, &s->i2c[1], "bcm2835-i2c1", BSC1_OFFSET, 0x20);
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index 6c428d8..57c77b1 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -556,6 +556,7 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
Object *cpuobj = object_new(ARM_CPU_TYPE_NAME("cortex-a9"));
+ object_property_add_child(OBJECT(s), "cpu[*]", cpuobj);
/* By default A9 CPUs have EL3 enabled. This board does not currently
* support EL3 so the CPU EL3 property is disabled before realization.
*/
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
index 0039921..2410e2a 100644
--- a/hw/arm/exynos4_boards.c
+++ b/hw/arm/exynos4_boards.c
@@ -34,6 +34,7 @@
#include "hw/qdev-properties.h"
#include "hw/boards.h"
#include "hw/irq.h"
+#include "target/arm/cpu-qom.h"
#define SMDK_LAN9118_BASE_ADDR 0x05000000
@@ -148,12 +149,18 @@ static void smdkc210_init(MachineState *machine)
arm_load_kernel(s->soc.cpu[0], machine, &exynos4_board_binfo);
}
+static const char * const valid_cpu_types[] = {
+ ARM_CPU_TYPE_NAME("cortex-a9"),
+ NULL
+};
+
static void nuri_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "Samsung NURI board (Exynos4210)";
mc->init = nuri_init;
+ mc->valid_cpu_types = valid_cpu_types;
mc->max_cpus = EXYNOS4210_NCPUS;
mc->min_cpus = EXYNOS4210_NCPUS;
mc->default_cpus = EXYNOS4210_NCPUS;
@@ -172,6 +179,7 @@ static void smdkc210_class_init(ObjectClass *oc, void *data)
mc->desc = "Samsung SMDKC210 board (Exynos4210)";
mc->init = smdkc210_init;
+ mc->valid_cpu_types = valid_cpu_types;
mc->max_cpus = EXYNOS4210_NCPUS;
mc->min_cpus = EXYNOS4210_NCPUS;
mc->default_cpus = EXYNOS4210_NCPUS;
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index e123747..9fdac1c 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -209,6 +209,7 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
cpuobj = object_new(machine->cpu_type);
cpu = ARM_CPU(cpuobj);
+ object_property_add_child(OBJECT(machine), "cpu[*]", cpuobj);
object_property_set_int(cpuobj, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
&error_abort);
@@ -342,10 +343,15 @@ static void midway_init(MachineState *machine)
static void highbank_class_init(ObjectClass *oc, void *data)
{
+ static const char * const valid_cpu_types[] = {
+ ARM_CPU_TYPE_NAME("cortex-a9"),
+ NULL
+ };
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "Calxeda Highbank (ECX-1000)";
mc->init = highbank_init;
+ mc->valid_cpu_types = valid_cpu_types;
mc->block_default_type = IF_IDE;
mc->units_per_default_bus = 1;
mc->max_cpus = 4;
@@ -361,10 +367,15 @@ static const TypeInfo highbank_type = {
static void midway_class_init(ObjectClass *oc, void *data)
{
+ static const char * const valid_cpu_types[] = {
+ ARM_CPU_TYPE_NAME("cortex-a15"),
+ NULL
+ };
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "Calxeda Midway (ECX-2000)";
mc->init = midway_init;
+ mc->valid_cpu_types = valid_cpu_types;
mc->block_default_type = IF_IDE;
mc->units_per_default_bus = 1;
mc->max_cpus = 4;
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
index 35bf1d6..a94a10a 100644
--- a/hw/arm/msf2-soc.c
+++ b/hw/arm/msf2-soc.c
@@ -134,7 +134,7 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
armv7m = DEVICE(&s->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 81);
- qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
+ qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
qdev_prop_set_bit(armv7m, "enable-bitband", true);
qdev_connect_clock_in(armv7m, "cpuclk", s->m3clk);
qdev_connect_clock_in(armv7m, "refclk", s->refclk);
@@ -227,7 +227,6 @@ static Property m2sxxx_soc_properties[] = {
* part name specifies the type of SmartFusion2 device variant(this
* property is for information purpose only.
*/
- DEFINE_PROP_STRING("cpu-type", MSF2State, cpu_type),
DEFINE_PROP_STRING("part-name", MSF2State, part_name),
DEFINE_PROP_UINT64("eNVM-size", MSF2State, envm_size, MSF2_ENVM_MAX_SIZE),
DEFINE_PROP_UINT64("eSRAM-size", MSF2State, esram_size,
diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c
index a269cf0..5c415ab 100644
--- a/hw/arm/msf2-som.c
+++ b/hw/arm/msf2-som.c
@@ -47,7 +47,6 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
DeviceState *dev;
DeviceState *spi_flash;
MSF2State *soc;
- MachineClass *mc = MACHINE_GET_CLASS(machine);
DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
qemu_irq cs_line;
BusState *spi_bus;
@@ -62,8 +61,6 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
dev = qdev_new(TYPE_MSF2_SOC);
object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
qdev_prop_set_string(dev, "part-name", "M2S010");
- qdev_prop_set_string(dev, "cpu-type", mc->default_cpu_type);
-
qdev_prop_set_uint64(dev, "eNVM-size", M2S010_ENVM_SIZE);
qdev_prop_set_uint64(dev, "eSRAM-size", M2S010_ESRAM_SIZE);
@@ -108,7 +105,6 @@ static void emcraft_sf2_machine_init(MachineClass *mc)
mc->desc = "SmartFusion2 SOM kit from Emcraft (M2S010)";
mc->init = emcraft_sf2_s2s010_init;
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
mc->valid_cpu_types = valid_cpu_types;
}
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
index 770ec1a..e2c9d49 100644
--- a/hw/arm/musca.c
+++ b/hw/arm/musca.c
@@ -605,7 +605,6 @@ static void musca_class_init(ObjectClass *oc, void *data)
mc->default_cpus = 2;
mc->min_cpus = mc->default_cpus;
mc->max_cpus = mc->default_cpus;
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
mc->valid_cpu_types = valid_cpu_types;
mc->init = musca_init;
}
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index bdc609b..ff3ecde 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -84,8 +84,10 @@ enum NPCM7xxInterrupt {
NPCM7XX_UART1_IRQ,
NPCM7XX_UART2_IRQ,
NPCM7XX_UART3_IRQ,
+ NPCM7XX_GMAC1_IRQ = 14,
NPCM7XX_EMC1RX_IRQ = 15,
NPCM7XX_EMC1TX_IRQ,
+ NPCM7XX_GMAC2_IRQ,
NPCM7XX_MMC_IRQ = 26,
NPCM7XX_PSPI2_IRQ = 28,
NPCM7XX_PSPI1_IRQ = 31,
@@ -229,6 +231,12 @@ static const hwaddr npcm7xx_pspi_addr[] = {
0xf0201000,
};
+/* Register base address for each GMAC Module */
+static const hwaddr npcm7xx_gmac_addr[] = {
+ 0xf0802000,
+ 0xf0804000,
+};
+
static const struct {
hwaddr regs_addr;
uint32_t unconnected_pins;
@@ -457,6 +465,10 @@ static void npcm7xx_init(Object *obj)
object_initialize_child(obj, "pspi[*]", &s->pspi[i], TYPE_NPCM_PSPI);
}
+ for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
+ object_initialize_child(obj, "gmac[*]", &s->gmac[i], TYPE_NPCM_GMAC);
+ }
+
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
}
@@ -691,6 +703,29 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
}
/*
+ * GMAC Modules. Cannot fail.
+ */
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gmac_addr) != ARRAY_SIZE(s->gmac));
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->gmac) != 2);
+ for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->gmac[i]);
+
+ /*
+ * The device exists regardless of whether it's connected to a QEMU
+ * netdev backend. So always instantiate it even if there is no
+ * backend.
+ */
+ sysbus_realize(sbd, &error_abort);
+ sysbus_mmio_map(sbd, 0, npcm7xx_gmac_addr[i]);
+ int irq = i == 0 ? NPCM7XX_GMAC1_IRQ : NPCM7XX_GMAC2_IRQ;
+ /*
+ * N.B. The values for the second argument sysbus_connect_irq are
+ * chosen to match the registration order in npcm7xx_emc_realize.
+ */
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
+ }
+
+ /*
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
* specified, but this is a programming error.
*/
@@ -752,8 +787,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
- create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
- create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 2999b8b..e229efb 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -465,7 +465,6 @@ static void npcm7xx_machine_class_init(ObjectClass *oc, void *data)
mc->no_cdrom = 1;
mc->no_parallel = 1;
mc->default_ram_id = "ram";
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
mc->valid_cpu_types = valid_cpu_types;
}
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index 7fd99a0..823b493 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -46,8 +46,7 @@
#include "qemu/log.h"
#include "qom/object.h"
#include "target/arm/cpu-qom.h"
-
-//#define DEBUG
+#include "trace.h"
/*
TODO
@@ -66,12 +65,6 @@
- Enhance UART with modem signals
*/
-#ifdef DEBUG
-# define DPRINTF(format, ...) printf(format , ## __VA_ARGS__)
-#else
-# define DPRINTF(format, ...) do { } while (0)
-#endif
-
static struct {
hwaddr io_base;
int irq;
@@ -151,8 +144,9 @@ static uint64_t strongarm_pic_mem_read(void *opaque, hwaddr offset,
case ICPR:
return s->pending;
default:
- printf("%s: Bad register offset 0x" HWADDR_FMT_plx "\n",
- __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad register offset 0x"HWADDR_FMT_plx"\n",
+ __func__, offset);
return 0;
}
}
@@ -173,8 +167,9 @@ static void strongarm_pic_mem_write(void *opaque, hwaddr offset,
s->int_idle = (value & 1) ? 0 : ~0;
break;
default:
- printf("%s: Bad register offset 0x" HWADDR_FMT_plx "\n",
- __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad register offset 0x"HWADDR_FMT_plx"\n",
+ __func__, offset);
break;
}
strongarm_pic_update(s);
@@ -333,7 +328,9 @@ static uint64_t strongarm_rtc_read(void *opaque, hwaddr addr,
((qemu_clock_get_ms(rtc_clock) - s->last_hz) << 15) /
(1000 * ((s->rttr & 0xffff) + 1));
default:
- printf("%s: Bad register 0x" HWADDR_FMT_plx "\n", __func__, addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad rtc register read 0x"HWADDR_FMT_plx"\n",
+ __func__, addr);
return 0;
}
}
@@ -375,7 +372,9 @@ static void strongarm_rtc_write(void *opaque, hwaddr addr,
break;
default:
- printf("%s: Bad register 0x" HWADDR_FMT_plx "\n", __func__, addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad rtc register write 0x"HWADDR_FMT_plx"\n",
+ __func__, addr);
}
}
@@ -556,12 +555,12 @@ static uint64_t strongarm_gpio_read(void *opaque, hwaddr offset,
case GPSR: /* GPIO Pin-Output Set registers */
qemu_log_mask(LOG_GUEST_ERROR,
- "strongarm GPIO: read from write only register GPSR\n");
+ "%s: read from write only register GPSR\n", __func__);
return 0;
case GPCR: /* GPIO Pin-Output Clear registers */
qemu_log_mask(LOG_GUEST_ERROR,
- "strongarm GPIO: read from write only register GPCR\n");
+ "%s: read from write only register GPCR\n", __func__);
return 0;
case GRER: /* GPIO Rising-Edge Detect Enable registers */
@@ -581,7 +580,9 @@ static uint64_t strongarm_gpio_read(void *opaque, hwaddr offset,
return s->status;
default:
- printf("%s: Bad offset 0x" HWADDR_FMT_plx "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad gpio read offset 0x"HWADDR_FMT_plx"\n",
+ __func__, offset);
}
return 0;
@@ -626,7 +627,9 @@ static void strongarm_gpio_write(void *opaque, hwaddr offset,
break;
default:
- printf("%s: Bad offset 0x" HWADDR_FMT_plx "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad write offset 0x"HWADDR_FMT_plx"\n",
+ __func__, offset);
}
}
@@ -782,7 +785,9 @@ static uint64_t strongarm_ppc_read(void *opaque, hwaddr offset,
return s->ppfr | ~0x7f001;
default:
- printf("%s: Bad offset 0x" HWADDR_FMT_plx "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad ppc read offset 0x"HWADDR_FMT_plx "\n",
+ __func__, offset);
}
return 0;
@@ -817,7 +822,9 @@ static void strongarm_ppc_write(void *opaque, hwaddr offset,
break;
default:
- printf("%s: Bad offset 0x" HWADDR_FMT_plx "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad ppc write offset 0x"HWADDR_FMT_plx"\n",
+ __func__, offset);
}
}
@@ -1029,8 +1036,13 @@ static void strongarm_uart_update_parameters(StrongARMUARTState *s)
s->char_transmit_time = (NANOSECONDS_PER_SECOND / speed) * frame_size;
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
- DPRINTF(stderr, "%s speed=%d parity=%c data=%d stop=%d\n", s->chr->label,
- speed, parity, data_bits, stop_bits);
+ trace_strongarm_uart_update_parameters((s->chr.chr ?
+ s->chr.chr->label : "NULL") ?:
+ "NULL",
+ speed,
+ parity,
+ data_bits,
+ stop_bits);
}
static void strongarm_uart_rx_to(void *opaque)
@@ -1164,7 +1176,9 @@ static uint64_t strongarm_uart_read(void *opaque, hwaddr addr,
return s->utsr1;
default:
- printf("%s: Bad register 0x" HWADDR_FMT_plx "\n", __func__, addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad uart register read 0x"HWADDR_FMT_plx"\n",
+ __func__, addr);
return 0;
}
}
@@ -1221,7 +1235,9 @@ static void strongarm_uart_write(void *opaque, hwaddr addr,
break;
default:
- printf("%s: Bad register 0x" HWADDR_FMT_plx "\n", __func__, addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad uart register write 0x"HWADDR_FMT_plx"\n",
+ __func__, addr);
}
}
@@ -1434,7 +1450,7 @@ static uint64_t strongarm_ssp_read(void *opaque, hwaddr addr,
return 0xffffffff;
}
if (s->rx_level < 1) {
- printf("%s: SSP Rx Underrun\n", __func__);
+ trace_strongarm_ssp_read_underrun();
return 0xffffffff;
}
s->rx_level--;
@@ -1443,7 +1459,9 @@ static uint64_t strongarm_ssp_read(void *opaque, hwaddr addr,
strongarm_ssp_fifo_update(s);
return retval;
default:
- printf("%s: Bad register 0x" HWADDR_FMT_plx "\n", __func__, addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad ssp register read 0x"HWADDR_FMT_plx"\n",
+ __func__, addr);
break;
}
return 0;
@@ -1458,8 +1476,8 @@ static void strongarm_ssp_write(void *opaque, hwaddr addr,
case SSCR0:
s->sscr[0] = value & 0xffbf;
if ((s->sscr[0] & SSCR0_SSE) && SSCR0_DSS(value) < 4) {
- printf("%s: Wrong data size: %i bits\n", __func__,
- (int)SSCR0_DSS(value));
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Wrong data size: %i bits\n",
+ __func__, (int)SSCR0_DSS(value));
}
if (!(value & SSCR0_SSE)) {
s->sssr = 0;
@@ -1471,7 +1489,9 @@ static void strongarm_ssp_write(void *opaque, hwaddr addr,
case SSCR1:
s->sscr[1] = value & 0x2f;
if (value & SSCR1_LBM) {
- printf("%s: Attempt to use SSP LBM mode\n", __func__);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Attempt to use SSP LBM mode\n",
+ __func__);
}
strongarm_ssp_fifo_update(s);
break;
@@ -1509,7 +1529,9 @@ static void strongarm_ssp_write(void *opaque, hwaddr addr,
break;
default:
- printf("%s: Bad register 0x" HWADDR_FMT_plx "\n", __func__, addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad ssp register write 0x"HWADDR_FMT_plx"\n",
+ __func__, addr);
break;
}
}
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
index cdc1ea0..fd0d927 100644
--- a/hw/arm/trace-events
+++ b/hw/arm/trace-events
@@ -55,3 +55,18 @@ smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint16_t vmid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d vmid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
+# strongarm.c
+strongarm_uart_update_parameters(const char *label, int speed, char parity, int data_bits, int stop_bits) "%s speed=%d parity=%c data=%d stop=%d"
+strongarm_ssp_read_underrun(void) "SSP rx underrun"
+
+# z2.c
+z2_lcd_reg_update(uint8_t cur, uint8_t i_0, uint8_t i_1, uint8_t i_2, uint32_t value) "cur_reg = 0x%x, buf = [0x%x, 0x%x, 0x%x], value = 0x%x"
+z2_lcd_enable_disable_result(const char *result) "LCD %s"
+z2_aer915_send_too_long(int8_t msg) "message too long (%i bytes)"
+z2_aer915_send(uint8_t reg, uint8_t value) "reg %d value 0x%02x"
+z2_aer915_event(int8_t event, int8_t len) "i2c event =0x%x len=%d bytes"
+
+# xen_arm.c
+xen_create_virtio_mmio_devices(int i, int irq, uint64_t base) "Created virtio-mmio device %d: irq %d base 0x%"PRIx64
+xen_init_ram(uint64_t machine_ram_size) "Initialized xen ram with size 0x%"PRIx64
+xen_enable_tpm(uint64_t addr) "Connected tpmdev at address 0x%"PRIx64
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index e5fb3ab..aa5f3ca 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -783,22 +783,30 @@ static void vexpress_class_init(ObjectClass *oc, void *data)
static void vexpress_a9_class_init(ObjectClass *oc, void *data)
{
+ static const char * const valid_cpu_types[] = {
+ ARM_CPU_TYPE_NAME("cortex-a9"),
+ NULL
+ };
MachineClass *mc = MACHINE_CLASS(oc);
VexpressMachineClass *vmc = VEXPRESS_MACHINE_CLASS(oc);
mc->desc = "ARM Versatile Express for Cortex-A9";
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
+ mc->valid_cpu_types = valid_cpu_types;
vmc->daughterboard = &a9_daughterboard;
}
static void vexpress_a15_class_init(ObjectClass *oc, void *data)
{
+ static const char * const valid_cpu_types[] = {
+ ARM_CPU_TYPE_NAME("cortex-a15"),
+ NULL
+ };
MachineClass *mc = MACHINE_CLASS(oc);
VexpressMachineClass *vmc = VEXPRESS_MACHINE_CLASS(oc);
mc->desc = "ARM Versatile Express for Cortex-A15";
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
+ mc->valid_cpu_types = valid_cpu_types;
vmc->daughterboard = &a15_daughterboard;
diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
index a563152..32776d9 100644
--- a/hw/arm/xen_arm.c
+++ b/hw/arm/xen_arm.c
@@ -34,6 +34,7 @@
#include "hw/xen/xen-hvm-common.h"
#include "sysemu/tpm.h"
#include "hw/xen/arch_hvm.h"
+#include "trace.h"
#define TYPE_XEN_ARM MACHINE_TYPE_NAME("xenpvh")
OBJECT_DECLARE_SIMPLE_TYPE(XenArmState, XEN_ARM)
@@ -91,8 +92,9 @@ static void xen_create_virtio_mmio_devices(XenArmState *xam)
sysbus_create_simple("virtio-mmio", base, irq);
- DPRINTF("Created virtio-mmio device %d: irq %d base 0x%lx\n",
- i, GUEST_VIRTIO_MMIO_SPI_FIRST + i, base);
+ trace_xen_create_virtio_mmio_devices(i,
+ GUEST_VIRTIO_MMIO_SPI_FIRST + i,
+ base);
}
}
@@ -101,6 +103,7 @@ static void xen_init_ram(MachineState *machine)
MemoryRegion *sysmem = get_system_memory();
ram_addr_t block_len, ram_size[GUEST_RAM_BANKS];
+ trace_xen_init_ram(machine->ram_size);
if (machine->ram_size <= GUEST_RAM0_SIZE) {
ram_size[0] = machine->ram_size;
ram_size[1] = 0;
@@ -117,15 +120,10 @@ static void xen_init_ram(MachineState *machine)
memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo", &ram_memory,
GUEST_RAM0_BASE, ram_size[0]);
memory_region_add_subregion(sysmem, GUEST_RAM0_BASE, &ram_lo);
- DPRINTF("Initialized region xen.ram.lo: base 0x%llx size 0x%lx\n",
- GUEST_RAM0_BASE, ram_size[0]);
-
if (ram_size[1] > 0) {
memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi", &ram_memory,
GUEST_RAM1_BASE, ram_size[1]);
memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, &ram_hi);
- DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n",
- GUEST_RAM1_BASE, ram_size[1]);
}
}
@@ -158,7 +156,7 @@ static void xen_enable_tpm(XenArmState *xam)
TPMBackend *be = qemu_find_tpm_be("tpm0");
if (be == NULL) {
- DPRINTF("Couldn't fine the backend for tpm0\n");
+ error_report("Couldn't find tmp0 backend");
return;
}
dev = qdev_new(TYPE_TPM_TIS_SYSBUS);
@@ -168,7 +166,7 @@ static void xen_enable_tpm(XenArmState *xam)
sysbus_realize_and_unref(busdev, &error_fatal);
sysbus_mmio_map(busdev, 0, xam->cfg.tpm_base_addr);
- DPRINTF("Connected tpmdev at address 0x%lx\n", xam->cfg.tpm_base_addr);
+ trace_xen_enable_tpm(xam->cfg.tpm_base_addr);
}
#endif
@@ -179,8 +177,9 @@ static void xen_arm_init(MachineState *machine)
xam->state = g_new0(XenIOState, 1);
if (machine->ram_size == 0) {
- DPRINTF("ram_size not specified. QEMU machine started without IOREQ"
- "(no emulated devices including Virtio)\n");
+ warn_report("%s non-zero ram size not specified. QEMU machine started"
+ " without IOREQ (no emulated devices including virtio)",
+ MACHINE_CLASS(object_get_class(OBJECT(machine)))->desc);
return;
}
@@ -194,7 +193,7 @@ static void xen_arm_init(MachineState *machine)
if (xam->cfg.tpm_base_addr) {
xen_enable_tpm(xam);
} else {
- DPRINTF("tpm-base-addr is not provided. TPM will not be enabled\n");
+ warn_report("tpm-base-addr is not provided. TPM will not be enabled");
}
#endif
}
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 35fa804..a41a118 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -352,13 +352,17 @@ static void zynq_init(MachineState *machine)
static void zynq_machine_class_init(ObjectClass *oc, void *data)
{
+ static const char * const valid_cpu_types[] = {
+ ARM_CPU_TYPE_NAME("cortex-a9"),
+ NULL
+ };
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "Xilinx Zynq Platform Baseboard for Cortex-A9";
mc->init = zynq_init;
mc->max_cpus = 1;
mc->no_sdcard = 1;
mc->ignore_memory_transaction_failures = true;
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
+ mc->valid_cpu_types = valid_cpu_types;
mc->default_ram_id = "zynq.ext_ram";
}
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index a67fba2..eb2ff8d 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -27,13 +27,7 @@
#include "exec/address-spaces.h"
#include "qom/object.h"
#include "qapi/error.h"
-
-#ifdef DEBUG_Z2
-#define DPRINTF(fmt, ...) \
- printf(fmt, ## __VA_ARGS__)
-#else
-#define DPRINTF(fmt, ...)
-#endif
+#include "trace.h"
static const struct keymap map[0x100] = {
[0 ... 0xff] = { -1, -1 },
@@ -119,6 +113,8 @@ static uint32_t zipit_lcd_transfer(SSIPeripheral *dev, uint32_t value)
{
ZipitLCD *z = ZIPIT_LCD(dev);
uint16_t val;
+
+ trace_z2_lcd_reg_update(z->cur_reg, z->buf[0], z->buf[1], z->buf[2], value);
if (z->selected) {
z->buf[z->pos] = value & 0xff;
z->pos++;
@@ -126,22 +122,19 @@ static uint32_t zipit_lcd_transfer(SSIPeripheral *dev, uint32_t value)
if (z->pos == 3) {
switch (z->buf[0]) {
case 0x74:
- DPRINTF("%s: reg: 0x%.2x\n", __func__, z->buf[2]);
z->cur_reg = z->buf[2];
break;
case 0x76:
val = z->buf[1] << 8 | z->buf[2];
- DPRINTF("%s: value: 0x%.4x\n", __func__, val);
if (z->cur_reg == 0x22 && val == 0x0000) {
z->enabled = 1;
- printf("%s: LCD enabled\n", __func__);
+ trace_z2_lcd_enable_disable_result("enabled");
} else if (z->cur_reg == 0x10 && val == 0x0000) {
z->enabled = 0;
- printf("%s: LCD disabled\n", __func__);
+ trace_z2_lcd_enable_disable_result("disabled");
}
break;
default:
- DPRINTF("%s: unknown command!\n", __func__);
break;
}
z->pos = 0;
@@ -211,14 +204,12 @@ static int aer915_send(I2CSlave *i2c, uint8_t data)
s->buf[s->len] = data;
if (s->len++ > 2) {
- DPRINTF("%s: message too long (%i bytes)\n",
- __func__, s->len);
+ trace_z2_aer915_send_too_long(s->len);
return 1;
}
if (s->len == 2) {
- DPRINTF("%s: reg %d value 0x%02x\n", __func__,
- s->buf[0], s->buf[1]);
+ trace_z2_aer915_send(s->buf[0], s->buf[1]);
}
return 0;
@@ -228,14 +219,12 @@ static int aer915_event(I2CSlave *i2c, enum i2c_event event)
{
AER915State *s = AER915(i2c);
+ trace_z2_aer915_event(s->len, event);
switch (event) {
case I2C_START_SEND:
s->len = 0;
break;
case I2C_START_RECV:
- if (s->len != 1) {
- DPRINTF("%s: short message!?\n", __func__);
- }
break;
case I2C_FINISH:
break;
diff --git a/hw/core/bus.c b/hw/core/bus.c
index c7831b5..b9d8949 100644
--- a/hw/core/bus.c
+++ b/hw/core/bus.c
@@ -232,57 +232,6 @@ static char *default_bus_get_fw_dev_path(DeviceState *dev)
return g_strdup(object_get_typename(OBJECT(dev)));
}
-/**
- * bus_phases_reset:
- * Transition reset method for buses to allow moving
- * smoothly from legacy reset method to multi-phases
- */
-static void bus_phases_reset(BusState *bus)
-{
- ResettableClass *rc = RESETTABLE_GET_CLASS(bus);
-
- if (rc->phases.enter) {
- rc->phases.enter(OBJECT(bus), RESET_TYPE_COLD);
- }
- if (rc->phases.hold) {
- rc->phases.hold(OBJECT(bus));
- }
- if (rc->phases.exit) {
- rc->phases.exit(OBJECT(bus));
- }
-}
-
-static void bus_transitional_reset(Object *obj)
-{
- BusClass *bc = BUS_GET_CLASS(obj);
-
- /*
- * This will call either @bus_phases_reset (for multi-phases transitioned
- * buses) or a bus's specific method for not-yet transitioned buses.
- * In both case, it does not reset children.
- */
- if (bc->reset) {
- bc->reset(BUS(obj));
- }
-}
-
-/**
- * bus_get_transitional_reset:
- * check if the bus's class is ready for multi-phase
- */
-static ResettableTrFunction bus_get_transitional_reset(Object *obj)
-{
- BusClass *dc = BUS_GET_CLASS(obj);
- if (dc->reset != bus_phases_reset) {
- /*
- * dc->reset has been overridden by a subclass,
- * the bus is not ready for multi phase yet.
- */
- return bus_transitional_reset;
- }
- return NULL;
-}
-
static void bus_class_init(ObjectClass *class, void *data)
{
BusClass *bc = BUS_CLASS(class);
@@ -293,22 +242,6 @@ static void bus_class_init(ObjectClass *class, void *data)
rc->get_state = bus_get_reset_state;
rc->child_foreach = bus_reset_child_foreach;
-
- /*
- * @bus_phases_reset is put as the default reset method below, allowing
- * to do the multi-phase transition from base classes to leaf classes. It
- * allows a legacy-reset Bus class to extend a multi-phases-reset
- * Bus class for the following reason:
- * + If a base class B has been moved to multi-phase, then it does not
- * override this default reset method and may have defined phase methods.
- * + A child class C (extending class B) which uses
- * bus_class_set_parent_reset() (or similar means) to override the
- * reset method will still work as expected. @bus_phases_reset function
- * will be registered as the parent reset method and effectively call
- * parent reset phases.
- */
- bc->reset = bus_phases_reset;
- rc->get_transitional_function = bus_get_transitional_reset;
}
static void qbus_finalize(Object *obj)
diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c
index c86d189..380239a 100644
--- a/hw/hyperv/vmbus.c
+++ b/hw/hyperv/vmbus.c
@@ -2453,9 +2453,9 @@ static void vmbus_unrealize(BusState *bus)
qemu_mutex_destroy(&vmbus->rx_queue_lock);
}
-static void vmbus_reset(BusState *bus)
+static void vmbus_reset_hold(Object *obj)
{
- vmbus_deinit(VMBUS(bus));
+ vmbus_deinit(VMBUS(obj));
}
static char *vmbus_get_dev_path(DeviceState *dev)
@@ -2476,12 +2476,13 @@ static char *vmbus_get_fw_dev_path(DeviceState *dev)
static void vmbus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
k->get_dev_path = vmbus_get_dev_path;
k->get_fw_dev_path = vmbus_get_fw_dev_path;
k->realize = vmbus_realize;
k->unrealize = vmbus_unrealize;
- k->reset = vmbus_reset;
+ rc->phases.hold = vmbus_reset_hold;
}
static int vmbus_pre_load(void *opaque)
diff --git a/hw/input/adb.c b/hw/input/adb.c
index 0f3c73d..98f39b4 100644
--- a/hw/input/adb.c
+++ b/hw/input/adb.c
@@ -231,9 +231,9 @@ static const VMStateDescription vmstate_adb_bus = {
}
};
-static void adb_bus_reset(BusState *qbus)
+static void adb_bus_reset_hold(Object *obj)
{
- ADBBusState *adb_bus = ADB_BUS(qbus);
+ ADBBusState *adb_bus = ADB_BUS(obj);
adb_bus->autopoll_enabled = false;
adb_bus->autopoll_mask = 0xffff;
@@ -262,10 +262,11 @@ static void adb_bus_unrealize(BusState *qbus)
static void adb_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
k->realize = adb_bus_realize;
k->unrealize = adb_bus_unrealize;
- k->reset = adb_bus_reset;
+ rc->phases.hold = adb_bus_reset_hold;
}
static const TypeInfo adb_bus_type_info = {
diff --git a/hw/net/meson.build b/hw/net/meson.build
index 2b426d3..b742687 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -38,7 +38,7 @@ system_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c'))
system_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c'))
system_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
system_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c'))
-system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c'))
+system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c', 'npcm_gmac.c'))
system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
system_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
diff --git a/hw/net/npcm_gmac.c b/hw/net/npcm_gmac.c
new file mode 100644
index 0000000..1b71e25
--- /dev/null
+++ b/hw/net/npcm_gmac.c
@@ -0,0 +1,942 @@
+/*
+ * Nuvoton NPCM7xx/8xx GMAC Module
+ *
+ * Copyright 2024 Google LLC
+ * Authors:
+ * Hao Wu <wuhaotsh@google.com>
+ * Nabih Estefan <nabihestefan@google.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * Unsupported/unimplemented features:
+ * - MII is not implemented, MII_ADDR.BUSY and MII_DATA always return zero
+ * - Precision timestamp (PTP) is not implemented.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/registerfields.h"
+#include "hw/net/mii.h"
+#include "hw/net/npcm_gmac.h"
+#include "migration/vmstate.h"
+#include "net/checksum.h"
+#include "net/eth.h"
+#include "net/net.h"
+#include "qemu/cutils.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "sysemu/dma.h"
+#include "trace.h"
+
+REG32(NPCM_DMA_BUS_MODE, 0x1000)
+REG32(NPCM_DMA_XMT_POLL_DEMAND, 0x1004)
+REG32(NPCM_DMA_RCV_POLL_DEMAND, 0x1008)
+REG32(NPCM_DMA_RX_BASE_ADDR, 0x100c)
+REG32(NPCM_DMA_TX_BASE_ADDR, 0x1010)
+REG32(NPCM_DMA_STATUS, 0x1014)
+REG32(NPCM_DMA_CONTROL, 0x1018)
+REG32(NPCM_DMA_INTR_ENA, 0x101c)
+REG32(NPCM_DMA_MISSED_FRAME_CTR, 0x1020)
+REG32(NPCM_DMA_HOST_TX_DESC, 0x1048)
+REG32(NPCM_DMA_HOST_RX_DESC, 0x104c)
+REG32(NPCM_DMA_CUR_TX_BUF_ADDR, 0x1050)
+REG32(NPCM_DMA_CUR_RX_BUF_ADDR, 0x1054)
+REG32(NPCM_DMA_HW_FEATURE, 0x1058)
+
+REG32(NPCM_GMAC_MAC_CONFIG, 0x0)
+REG32(NPCM_GMAC_FRAME_FILTER, 0x4)
+REG32(NPCM_GMAC_HASH_HIGH, 0x8)
+REG32(NPCM_GMAC_HASH_LOW, 0xc)
+REG32(NPCM_GMAC_MII_ADDR, 0x10)
+REG32(NPCM_GMAC_MII_DATA, 0x14)
+REG32(NPCM_GMAC_FLOW_CTRL, 0x18)
+REG32(NPCM_GMAC_VLAN_FLAG, 0x1c)
+REG32(NPCM_GMAC_VERSION, 0x20)
+REG32(NPCM_GMAC_WAKEUP_FILTER, 0x28)
+REG32(NPCM_GMAC_PMT, 0x2c)
+REG32(NPCM_GMAC_LPI_CTRL, 0x30)
+REG32(NPCM_GMAC_TIMER_CTRL, 0x34)
+REG32(NPCM_GMAC_INT_STATUS, 0x38)
+REG32(NPCM_GMAC_INT_MASK, 0x3c)
+REG32(NPCM_GMAC_MAC0_ADDR_HI, 0x40)
+REG32(NPCM_GMAC_MAC0_ADDR_LO, 0x44)
+REG32(NPCM_GMAC_MAC1_ADDR_HI, 0x48)
+REG32(NPCM_GMAC_MAC1_ADDR_LO, 0x4c)
+REG32(NPCM_GMAC_MAC2_ADDR_HI, 0x50)
+REG32(NPCM_GMAC_MAC2_ADDR_LO, 0x54)
+REG32(NPCM_GMAC_MAC3_ADDR_HI, 0x58)
+REG32(NPCM_GMAC_MAC3_ADDR_LO, 0x5c)
+REG32(NPCM_GMAC_RGMII_STATUS, 0xd8)
+REG32(NPCM_GMAC_WATCHDOG, 0xdc)
+REG32(NPCM_GMAC_PTP_TCR, 0x700)
+REG32(NPCM_GMAC_PTP_SSIR, 0x704)
+REG32(NPCM_GMAC_PTP_STSR, 0x708)
+REG32(NPCM_GMAC_PTP_STNSR, 0x70c)
+REG32(NPCM_GMAC_PTP_STSUR, 0x710)
+REG32(NPCM_GMAC_PTP_STNSUR, 0x714)
+REG32(NPCM_GMAC_PTP_TAR, 0x718)
+REG32(NPCM_GMAC_PTP_TTSR, 0x71c)
+
+/* Register Fields */
+#define NPCM_GMAC_MII_ADDR_BUSY BIT(0)
+#define NPCM_GMAC_MII_ADDR_WRITE BIT(1)
+#define NPCM_GMAC_MII_ADDR_GR(rv) extract16((rv), 6, 5)
+#define NPCM_GMAC_MII_ADDR_PA(rv) extract16((rv), 11, 5)
+
+#define NPCM_GMAC_INT_MASK_LPIIM BIT(10)
+#define NPCM_GMAC_INT_MASK_PMTM BIT(3)
+#define NPCM_GMAC_INT_MASK_RGIM BIT(0)
+
+#define NPCM_DMA_BUS_MODE_SWR BIT(0)
+
+static const uint32_t npcm_gmac_cold_reset_values[NPCM_GMAC_NR_REGS] = {
+ /* Reduce version to 3.2 so that the kernel can enable interrupt. */
+ [R_NPCM_GMAC_VERSION] = 0x00001032,
+ [R_NPCM_GMAC_TIMER_CTRL] = 0x03e80000,
+ [R_NPCM_GMAC_MAC0_ADDR_HI] = 0x8000ffff,
+ [R_NPCM_GMAC_MAC0_ADDR_LO] = 0xffffffff,
+ [R_NPCM_GMAC_MAC1_ADDR_HI] = 0x0000ffff,
+ [R_NPCM_GMAC_MAC1_ADDR_LO] = 0xffffffff,
+ [R_NPCM_GMAC_MAC2_ADDR_HI] = 0x0000ffff,
+ [R_NPCM_GMAC_MAC2_ADDR_LO] = 0xffffffff,
+ [R_NPCM_GMAC_MAC3_ADDR_HI] = 0x0000ffff,
+ [R_NPCM_GMAC_MAC3_ADDR_LO] = 0xffffffff,
+ [R_NPCM_GMAC_PTP_TCR] = 0x00002000,
+ [R_NPCM_DMA_BUS_MODE] = 0x00020101,
+ [R_NPCM_DMA_HW_FEATURE] = 0x100d4f37,
+};
+
+static const uint16_t phy_reg_init[] = {
+ [MII_BMCR] = MII_BMCR_AUTOEN | MII_BMCR_FD | MII_BMCR_SPEED1000,
+ [MII_BMSR] = MII_BMSR_100TX_FD | MII_BMSR_100TX_HD | MII_BMSR_10T_FD |
+ MII_BMSR_10T_HD | MII_BMSR_EXTSTAT | MII_BMSR_AUTONEG |
+ MII_BMSR_LINK_ST | MII_BMSR_EXTCAP,
+ [MII_PHYID1] = 0x0362,
+ [MII_PHYID2] = 0x5e6a,
+ [MII_ANAR] = MII_ANAR_TXFD | MII_ANAR_TX | MII_ANAR_10FD |
+ MII_ANAR_10 | MII_ANAR_CSMACD,
+ [MII_ANLPAR] = MII_ANLPAR_ACK | MII_ANLPAR_PAUSE |
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD,
+ [MII_ANER] = 0x64 | MII_ANER_NWAY,
+ [MII_ANNP] = 0x2001,
+ [MII_CTRL1000] = MII_CTRL1000_FULL,
+ [MII_STAT1000] = MII_STAT1000_FULL,
+ [MII_EXTSTAT] = 0x3000, /* 1000BASTE_T full-duplex capable */
+};
+
+static void npcm_gmac_soft_reset(NPCMGMACState *gmac)
+{
+ memcpy(gmac->regs, npcm_gmac_cold_reset_values,
+ NPCM_GMAC_NR_REGS * sizeof(uint32_t));
+ /* Clear reset bits */
+ gmac->regs[R_NPCM_DMA_BUS_MODE] &= ~NPCM_DMA_BUS_MODE_SWR;
+}
+
+static void gmac_phy_set_link(NPCMGMACState *gmac, bool active)
+{
+ /* Autonegotiation status mirrors link status. */
+ if (active) {
+ gmac->phy_regs[0][MII_BMSR] |= (MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
+ } else {
+ gmac->phy_regs[0][MII_BMSR] &= ~(MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
+ }
+}
+
+static bool gmac_can_receive(NetClientState *nc)
+{
+ NPCMGMACState *gmac = NPCM_GMAC(qemu_get_nic_opaque(nc));
+
+ /* If GMAC receive is disabled. */
+ if (!(gmac->regs[R_NPCM_GMAC_MAC_CONFIG] & NPCM_GMAC_MAC_CONFIG_RX_EN)) {
+ return false;
+ }
+
+ /* If GMAC DMA RX is stopped. */
+ if (!(gmac->regs[R_NPCM_DMA_CONTROL] & NPCM_DMA_CONTROL_START_STOP_RX)) {
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Function that updates the GMAC IRQ
+ * It find the logical OR of the enabled bits for NIS (if enabled)
+ * It find the logical OR of the enabled bits for AIS (if enabled)
+ */
+static void gmac_update_irq(NPCMGMACState *gmac)
+{
+ /*
+ * Check if the normal interrupts summary is enabled
+ * if so, add the bits for the summary that are enabled
+ */
+ if (gmac->regs[R_NPCM_DMA_INTR_ENA] & gmac->regs[R_NPCM_DMA_STATUS] &
+ (NPCM_DMA_INTR_ENAB_NIE_BITS)) {
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_NIS;
+ }
+ /*
+ * Check if the abnormal interrupts summary is enabled
+ * if so, add the bits for the summary that are enabled
+ */
+ if (gmac->regs[R_NPCM_DMA_INTR_ENA] & gmac->regs[R_NPCM_DMA_STATUS] &
+ (NPCM_DMA_INTR_ENAB_AIE_BITS)) {
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_AIS;
+ }
+
+ /* Get the logical OR of both normal and abnormal interrupts */
+ int level = !!((gmac->regs[R_NPCM_DMA_STATUS] &
+ gmac->regs[R_NPCM_DMA_INTR_ENA] &
+ NPCM_DMA_STATUS_NIS) |
+ (gmac->regs[R_NPCM_DMA_STATUS] &
+ gmac->regs[R_NPCM_DMA_INTR_ENA] &
+ NPCM_DMA_STATUS_AIS));
+
+ /* Set the IRQ */
+ trace_npcm_gmac_update_irq(DEVICE(gmac)->canonical_path,
+ gmac->regs[R_NPCM_DMA_STATUS],
+ gmac->regs[R_NPCM_DMA_INTR_ENA],
+ level);
+ qemu_set_irq(gmac->irq, level);
+}
+
+static int gmac_read_rx_desc(dma_addr_t addr, struct NPCMGMACRxDesc *desc)
+{
+ if (dma_memory_read(&address_space_memory, addr, desc,
+ sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
+ HWADDR_PRIx "\n", __func__, addr);
+ return -1;
+ }
+ desc->rdes0 = le32_to_cpu(desc->rdes0);
+ desc->rdes1 = le32_to_cpu(desc->rdes1);
+ desc->rdes2 = le32_to_cpu(desc->rdes2);
+ desc->rdes3 = le32_to_cpu(desc->rdes3);
+ return 0;
+}
+
+static int gmac_write_rx_desc(dma_addr_t addr, struct NPCMGMACRxDesc *desc)
+{
+ struct NPCMGMACRxDesc le_desc;
+ le_desc.rdes0 = cpu_to_le32(desc->rdes0);
+ le_desc.rdes1 = cpu_to_le32(desc->rdes1);
+ le_desc.rdes2 = cpu_to_le32(desc->rdes2);
+ le_desc.rdes3 = cpu_to_le32(desc->rdes3);
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
+ sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
+ HWADDR_PRIx "\n", __func__, addr);
+ return -1;
+ }
+ return 0;
+}
+
+static int gmac_read_tx_desc(dma_addr_t addr, struct NPCMGMACTxDesc *desc)
+{
+ if (dma_memory_read(&address_space_memory, addr, desc,
+ sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
+ HWADDR_PRIx "\n", __func__, addr);
+ return -1;
+ }
+ desc->tdes0 = le32_to_cpu(desc->tdes0);
+ desc->tdes1 = le32_to_cpu(desc->tdes1);
+ desc->tdes2 = le32_to_cpu(desc->tdes2);
+ desc->tdes3 = le32_to_cpu(desc->tdes3);
+ return 0;
+}
+
+static int gmac_write_tx_desc(dma_addr_t addr, struct NPCMGMACTxDesc *desc)
+{
+ struct NPCMGMACTxDesc le_desc;
+ le_desc.tdes0 = cpu_to_le32(desc->tdes0);
+ le_desc.tdes1 = cpu_to_le32(desc->tdes1);
+ le_desc.tdes2 = cpu_to_le32(desc->tdes2);
+ le_desc.tdes3 = cpu_to_le32(desc->tdes3);
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
+ sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
+ HWADDR_PRIx "\n", __func__, addr);
+ return -1;
+ }
+ return 0;
+}
+
+static int gmac_rx_transfer_frame_to_buffer(uint32_t rx_buf_len,
+ uint32_t *left_frame,
+ uint32_t rx_buf_addr,
+ bool *eof_transferred,
+ const uint8_t **frame_ptr,
+ uint16_t *transferred)
+{
+ uint32_t to_transfer;
+ /*
+ * Check that buffer is bigger than the frame being transfered
+ * If bigger then transfer only whats left of frame
+ * Else, fill frame with all the content possible
+ */
+ if (rx_buf_len >= *left_frame) {
+ to_transfer = *left_frame;
+ *eof_transferred = true;
+ } else {
+ to_transfer = rx_buf_len;
+ }
+
+ /* write frame part to memory */
+ if (dma_memory_write(&address_space_memory, (uint64_t) rx_buf_addr,
+ *frame_ptr, to_transfer, MEMTXATTRS_UNSPECIFIED)) {
+ return -1;
+ }
+
+ /* update frame pointer and size of whats left of frame */
+ *frame_ptr += to_transfer;
+ *left_frame -= to_transfer;
+ *transferred += to_transfer;
+
+ return 0;
+}
+
+static void gmac_dma_set_state(NPCMGMACState *gmac, int shift, uint32_t state)
+{
+ gmac->regs[R_NPCM_DMA_STATUS] = deposit32(gmac->regs[R_NPCM_DMA_STATUS],
+ shift, 3, state);
+}
+
+static ssize_t gmac_receive(NetClientState *nc, const uint8_t *buf, size_t len)
+{
+ /*
+ * Comments have steps that relate to the
+ * receiving process steps in pg 386
+ */
+ NPCMGMACState *gmac = NPCM_GMAC(qemu_get_nic_opaque(nc));
+ uint32_t left_frame = len;
+ const uint8_t *frame_ptr = buf;
+ uint32_t desc_addr;
+ uint32_t rx_buf_len, rx_buf_addr;
+ struct NPCMGMACRxDesc rx_desc;
+ uint16_t transferred = 0;
+ bool eof_transferred = false;
+
+ trace_npcm_gmac_packet_receive(DEVICE(gmac)->canonical_path, len);
+ if (!gmac_can_receive(nc)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "GMAC Currently is not able for Rx");
+ return -1;
+ }
+ if (!gmac->regs[R_NPCM_DMA_HOST_RX_DESC]) {
+ gmac->regs[R_NPCM_DMA_HOST_RX_DESC] =
+ NPCM_DMA_HOST_RX_DESC_MASK(gmac->regs[R_NPCM_DMA_RX_BASE_ADDR]);
+ }
+ desc_addr = NPCM_DMA_HOST_RX_DESC_MASK(gmac->regs[R_NPCM_DMA_HOST_RX_DESC]);
+
+ /* step 1 */
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_RUNNING_FETCHING_STATE);
+ trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path, desc_addr);
+ if (gmac_read_rx_desc(desc_addr, &rx_desc)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "RX Descriptor @ 0x%x cant be read\n",
+ desc_addr);
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_SUSPENDED_STATE);
+ return -1;
+ }
+
+ /* step 2 */
+ if (!(rx_desc.rdes0 & RX_DESC_RDES0_OWN)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "RX Descriptor @ 0x%x is owned by software\n",
+ desc_addr);
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RU;
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RI;
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_SUSPENDED_STATE);
+ gmac_update_irq(gmac);
+ return len;
+ }
+ /* step 3 */
+ /*
+ * TODO --
+ * Implement all frame filtering and processing (with its own interrupts)
+ */
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &rx_desc,
+ rx_desc.rdes0, rx_desc.rdes1, rx_desc.rdes2,
+ rx_desc.rdes3);
+ /* Clear rdes0 for the incoming descriptor and set FS in first descriptor.*/
+ rx_desc.rdes0 = RX_DESC_RDES0_FIRST_DESC_MASK;
+
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_RUNNING_TRANSFERRING_STATE);
+
+ /* Pad the frame with FCS as the kernel driver will strip it away. */
+ left_frame += ETH_FCS_LEN;
+
+ /* repeat while we still have frame to transfer to memory */
+ while (!eof_transferred) {
+ /* Return descriptor no matter what happens */
+ rx_desc.rdes0 &= ~RX_DESC_RDES0_OWN;
+ /* Set the frame to be an IPv4/IPv6 frame. */
+ rx_desc.rdes0 |= RX_DESC_RDES0_FRM_TYPE_MASK;
+
+ /* step 4 */
+ rx_buf_len = RX_DESC_RDES1_BFFR1_SZ_MASK(rx_desc.rdes1);
+ rx_buf_addr = rx_desc.rdes2;
+ gmac->regs[R_NPCM_DMA_CUR_RX_BUF_ADDR] = rx_buf_addr;
+ gmac_rx_transfer_frame_to_buffer(rx_buf_len, &left_frame, rx_buf_addr,
+ &eof_transferred, &frame_ptr,
+ &transferred);
+
+ trace_npcm_gmac_packet_receiving_buffer(DEVICE(gmac)->canonical_path,
+ rx_buf_len, rx_buf_addr);
+ /* if we still have frame left and the second buffer is not chained */
+ if (!(rx_desc.rdes1 & RX_DESC_RDES1_SEC_ADDR_CHND_MASK) && \
+ !eof_transferred) {
+ /* repeat process from above on buffer 2 */
+ rx_buf_len = RX_DESC_RDES1_BFFR2_SZ_MASK(rx_desc.rdes1);
+ rx_buf_addr = rx_desc.rdes3;
+ gmac->regs[R_NPCM_DMA_CUR_RX_BUF_ADDR] = rx_buf_addr;
+ gmac_rx_transfer_frame_to_buffer(rx_buf_len, &left_frame,
+ rx_buf_addr, &eof_transferred,
+ &frame_ptr, &transferred);
+ trace_npcm_gmac_packet_receiving_buffer( \
+ DEVICE(gmac)->canonical_path,
+ rx_buf_len, rx_buf_addr);
+ }
+ /* update address for descriptor */
+ gmac->regs[R_NPCM_DMA_HOST_RX_DESC] = rx_buf_addr;
+ /* Return descriptor */
+ rx_desc.rdes0 &= ~RX_DESC_RDES0_OWN;
+ /* Update frame length transferred */
+ rx_desc.rdes0 |= ((uint32_t)transferred)
+ << RX_DESC_RDES0_FRAME_LEN_SHIFT;
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &rx_desc,
+ rx_desc.rdes0, rx_desc.rdes1,
+ rx_desc.rdes2, rx_desc.rdes3);
+
+ /* step 5 */
+ gmac_write_rx_desc(desc_addr, &rx_desc);
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path,
+ &rx_desc, rx_desc.rdes0,
+ rx_desc.rdes1, rx_desc.rdes2,
+ rx_desc.rdes3);
+ /* read new descriptor into rx_desc if needed*/
+ if (!eof_transferred) {
+ /* Get next descriptor address (chained or sequential) */
+ if (rx_desc.rdes1 & RX_DESC_RDES1_RC_END_RING_MASK) {
+ desc_addr = gmac->regs[R_NPCM_DMA_RX_BASE_ADDR];
+ } else if (rx_desc.rdes1 & RX_DESC_RDES1_SEC_ADDR_CHND_MASK) {
+ desc_addr = rx_desc.rdes3;
+ } else {
+ desc_addr += sizeof(rx_desc);
+ }
+ trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path,
+ desc_addr);
+ if (gmac_read_rx_desc(desc_addr, &rx_desc)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "RX Descriptor @ 0x%x cant be read\n",
+ desc_addr);
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RU;
+ gmac_update_irq(gmac);
+ return len;
+ }
+
+ /* step 6 */
+ if (!(rx_desc.rdes0 & RX_DESC_RDES0_OWN)) {
+ if (!(gmac->regs[R_NPCM_DMA_CONTROL] & \
+ NPCM_DMA_CONTROL_FLUSH_MASK)) {
+ rx_desc.rdes0 |= RX_DESC_RDES0_DESC_ERR_MASK;
+ }
+ eof_transferred = true;
+ }
+ /* Clear rdes0 for the incoming descriptor */
+ rx_desc.rdes0 = 0;
+ }
+ }
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_RUNNING_CLOSING_STATE);
+
+ rx_desc.rdes0 |= RX_DESC_RDES0_LAST_DESC_MASK;
+ if (!(rx_desc.rdes1 & RX_DESC_RDES1_DIS_INTR_COMP_MASK)) {
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RI;
+ gmac_update_irq(gmac);
+ }
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &rx_desc,
+ rx_desc.rdes0, rx_desc.rdes1, rx_desc.rdes2,
+ rx_desc.rdes3);
+
+ /* step 8 */
+ gmac->regs[R_NPCM_DMA_CONTROL] |= NPCM_DMA_CONTROL_FLUSH_MASK;
+
+ /* step 9 */
+ trace_npcm_gmac_packet_received(DEVICE(gmac)->canonical_path, left_frame);
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
+ gmac_write_rx_desc(desc_addr, &rx_desc);
+
+ /* Get next descriptor address (chained or sequential) */
+ if (rx_desc.rdes1 & RX_DESC_RDES1_RC_END_RING_MASK) {
+ desc_addr = gmac->regs[R_NPCM_DMA_RX_BASE_ADDR];
+ } else if (rx_desc.rdes1 & RX_DESC_RDES1_SEC_ADDR_CHND_MASK) {
+ desc_addr = rx_desc.rdes3;
+ } else {
+ desc_addr += sizeof(rx_desc);
+ }
+ gmac->regs[R_NPCM_DMA_HOST_RX_DESC] = desc_addr;
+ return len;
+}
+
+static int gmac_tx_get_csum(uint32_t tdes1)
+{
+ uint32_t mask = TX_DESC_TDES1_CHKSM_INS_CTRL_MASK(tdes1);
+ int csum = 0;
+
+ if (likely(mask > 0)) {
+ csum |= CSUM_IP;
+ }
+ if (likely(mask > 1)) {
+ csum |= CSUM_TCP | CSUM_UDP;
+ }
+
+ return csum;
+}
+
+static void gmac_try_send_next_packet(NPCMGMACState *gmac)
+{
+ /*
+ * Comments about steps refer to steps for
+ * transmitting in page 384 of datasheet
+ */
+ uint16_t tx_buffer_size = 2048;
+ g_autofree uint8_t *tx_send_buffer = g_malloc(tx_buffer_size);
+ uint32_t desc_addr;
+ struct NPCMGMACTxDesc tx_desc;
+ uint32_t tx_buf_addr, tx_buf_len;
+ uint16_t length = 0;
+ uint8_t *buf = tx_send_buffer;
+ uint32_t prev_buf_size = 0;
+ int csum = 0;
+
+ /* steps 1&2 */
+ if (!gmac->regs[R_NPCM_DMA_HOST_TX_DESC]) {
+ gmac->regs[R_NPCM_DMA_HOST_TX_DESC] =
+ NPCM_DMA_HOST_TX_DESC_MASK(gmac->regs[R_NPCM_DMA_TX_BASE_ADDR]);
+ }
+ desc_addr = gmac->regs[R_NPCM_DMA_HOST_TX_DESC];
+
+ while (true) {
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_TX_RUNNING_FETCHING_STATE);
+ if (gmac_read_tx_desc(desc_addr, &tx_desc)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "TX Descriptor @ 0x%x can't be read\n",
+ desc_addr);
+ return;
+ }
+ /* step 3 */
+
+ trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path,
+ desc_addr);
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &tx_desc,
+ tx_desc.tdes0, tx_desc.tdes1, tx_desc.tdes2, tx_desc.tdes3);
+
+ /* 1 = DMA Owned, 0 = Software Owned */
+ if (!(tx_desc.tdes0 & TX_DESC_TDES0_OWN)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "TX Descriptor @ 0x%x is owned by software\n",
+ desc_addr);
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_TU;
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_TX_SUSPENDED_STATE);
+ gmac_update_irq(gmac);
+ return;
+ }
+
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_TX_RUNNING_READ_STATE);
+ /* Give the descriptor back regardless of what happens. */
+ tx_desc.tdes0 &= ~TX_DESC_TDES0_OWN;
+
+ if (tx_desc.tdes1 & TX_DESC_TDES1_FIRST_SEG_MASK) {
+ csum = gmac_tx_get_csum(tx_desc.tdes1);
+ }
+
+ /* step 4 */
+ tx_buf_addr = tx_desc.tdes2;
+ gmac->regs[R_NPCM_DMA_CUR_TX_BUF_ADDR] = tx_buf_addr;
+ tx_buf_len = TX_DESC_TDES1_BFFR1_SZ_MASK(tx_desc.tdes1);
+ buf = &tx_send_buffer[prev_buf_size];
+
+ if ((prev_buf_size + tx_buf_len) > sizeof(buf)) {
+ tx_buffer_size = prev_buf_size + tx_buf_len;
+ tx_send_buffer = g_realloc(tx_send_buffer, tx_buffer_size);
+ buf = &tx_send_buffer[prev_buf_size];
+ }
+
+ /* step 5 */
+ if (dma_memory_read(&address_space_memory, tx_buf_addr, buf,
+ tx_buf_len, MEMTXATTRS_UNSPECIFIED)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n",
+ __func__, tx_buf_addr);
+ return;
+ }
+ length += tx_buf_len;
+ prev_buf_size += tx_buf_len;
+
+ /* If not chained we'll have a second buffer. */
+ if (!(tx_desc.tdes1 & TX_DESC_TDES1_SEC_ADDR_CHND_MASK)) {
+ tx_buf_addr = tx_desc.tdes3;
+ gmac->regs[R_NPCM_DMA_CUR_TX_BUF_ADDR] = tx_buf_addr;
+ tx_buf_len = TX_DESC_TDES1_BFFR2_SZ_MASK(tx_desc.tdes1);
+ buf = &tx_send_buffer[prev_buf_size];
+
+ if ((prev_buf_size + tx_buf_len) > sizeof(buf)) {
+ tx_buffer_size = prev_buf_size + tx_buf_len;
+ tx_send_buffer = g_realloc(tx_send_buffer, tx_buffer_size);
+ buf = &tx_send_buffer[prev_buf_size];
+ }
+
+ if (dma_memory_read(&address_space_memory, tx_buf_addr, buf,
+ tx_buf_len, MEMTXATTRS_UNSPECIFIED)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Failed to read packet @ 0x%x\n",
+ __func__, tx_buf_addr);
+ return;
+ }
+ length += tx_buf_len;
+ prev_buf_size += tx_buf_len;
+ }
+ if (tx_desc.tdes1 & TX_DESC_TDES1_LAST_SEG_MASK) {
+ net_checksum_calculate(tx_send_buffer, length, csum);
+ qemu_send_packet(qemu_get_queue(gmac->nic), tx_send_buffer, length);
+ trace_npcm_gmac_packet_sent(DEVICE(gmac)->canonical_path, length);
+ buf = tx_send_buffer;
+ length = 0;
+ }
+
+ /* step 6 */
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_TX_RUNNING_CLOSING_STATE);
+ gmac_write_tx_desc(desc_addr, &tx_desc);
+ if (tx_desc.tdes1 & TX_DESC_TDES1_TX_END_RING_MASK) {
+ desc_addr = gmac->regs[R_NPCM_DMA_TX_BASE_ADDR];
+ } else if (tx_desc.tdes1 & TX_DESC_TDES1_SEC_ADDR_CHND_MASK) {
+ desc_addr = tx_desc.tdes3;
+ } else {
+ desc_addr += sizeof(tx_desc);
+ }
+ gmac->regs[R_NPCM_DMA_HOST_TX_DESC] = desc_addr;
+
+ /* step 7 */
+ if (tx_desc.tdes1 & TX_DESC_TDES1_INTERR_COMP_MASK) {
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_TI;
+ gmac_update_irq(gmac);
+ }
+ }
+}
+
+static void gmac_cleanup(NetClientState *nc)
+{
+ /* Nothing to do yet. */
+}
+
+static void gmac_set_link(NetClientState *nc)
+{
+ NPCMGMACState *gmac = qemu_get_nic_opaque(nc);
+
+ trace_npcm_gmac_set_link(!nc->link_down);
+ gmac_phy_set_link(gmac, !nc->link_down);
+}
+
+static void npcm_gmac_mdio_access(NPCMGMACState *gmac, uint16_t v)
+{
+ bool busy = v & NPCM_GMAC_MII_ADDR_BUSY;
+ uint8_t is_write;
+ uint8_t pa, gr;
+ uint16_t data;
+
+ if (busy) {
+ is_write = v & NPCM_GMAC_MII_ADDR_WRITE;
+ pa = NPCM_GMAC_MII_ADDR_PA(v);
+ gr = NPCM_GMAC_MII_ADDR_GR(v);
+ /* Both pa and gr are 5 bits, so they are less than 32. */
+ g_assert(pa < NPCM_GMAC_MAX_PHYS);
+ g_assert(gr < NPCM_GMAC_MAX_PHY_REGS);
+
+
+ if (v & NPCM_GMAC_MII_ADDR_WRITE) {
+ data = gmac->regs[R_NPCM_GMAC_MII_DATA];
+ /* Clear reset bit for BMCR register */
+ switch (gr) {
+ case MII_BMCR:
+ data &= ~MII_BMCR_RESET;
+ /* Autonegotiation is a W1C bit*/
+ if (data & MII_BMCR_ANRESTART) {
+ /* Tells autonegotiation to not restart again */
+ data &= ~MII_BMCR_ANRESTART;
+ }
+ if ((data & MII_BMCR_AUTOEN) &&
+ !(gmac->phy_regs[pa][MII_BMSR] & MII_BMSR_AN_COMP)) {
+ /* sets autonegotiation as complete */
+ gmac->phy_regs[pa][MII_BMSR] |= MII_BMSR_AN_COMP;
+ /* Resolve AN automatically->need to set this */
+ gmac->phy_regs[0][MII_ANLPAR] = 0x0000;
+ }
+ }
+ gmac->phy_regs[pa][gr] = data;
+ } else {
+ data = gmac->phy_regs[pa][gr];
+ gmac->regs[R_NPCM_GMAC_MII_DATA] = data;
+ }
+ trace_npcm_gmac_mdio_access(DEVICE(gmac)->canonical_path, is_write, pa,
+ gr, data);
+ }
+ gmac->regs[R_NPCM_GMAC_MII_ADDR] = v & ~NPCM_GMAC_MII_ADDR_BUSY;
+}
+
+static uint64_t npcm_gmac_read(void *opaque, hwaddr offset, unsigned size)
+{
+ NPCMGMACState *gmac = opaque;
+ uint32_t v = 0;
+
+ switch (offset) {
+ /* Write only registers */
+ case A_NPCM_DMA_XMT_POLL_DEMAND:
+ case A_NPCM_DMA_RCV_POLL_DEMAND:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Read of write-only reg: offset: 0x%04" HWADDR_PRIx
+ "\n", DEVICE(gmac)->canonical_path, offset);
+ break;
+
+ default:
+ v = gmac->regs[offset / sizeof(uint32_t)];
+ }
+
+ trace_npcm_gmac_reg_read(DEVICE(gmac)->canonical_path, offset, v);
+ return v;
+}
+
+static void npcm_gmac_write(void *opaque, hwaddr offset,
+ uint64_t v, unsigned size)
+{
+ NPCMGMACState *gmac = opaque;
+
+ trace_npcm_gmac_reg_write(DEVICE(gmac)->canonical_path, offset, v);
+
+ switch (offset) {
+ /* Read only registers */
+ case A_NPCM_GMAC_VERSION:
+ case A_NPCM_GMAC_INT_STATUS:
+ case A_NPCM_GMAC_RGMII_STATUS:
+ case A_NPCM_GMAC_PTP_STSR:
+ case A_NPCM_GMAC_PTP_STNSR:
+ case A_NPCM_DMA_MISSED_FRAME_CTR:
+ case A_NPCM_DMA_HOST_TX_DESC:
+ case A_NPCM_DMA_HOST_RX_DESC:
+ case A_NPCM_DMA_CUR_TX_BUF_ADDR:
+ case A_NPCM_DMA_CUR_RX_BUF_ADDR:
+ case A_NPCM_DMA_HW_FEATURE:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Write of read-only reg: offset: 0x%04" HWADDR_PRIx
+ ", value: 0x%04" PRIx64 "\n",
+ DEVICE(gmac)->canonical_path, offset, v);
+ break;
+
+ case A_NPCM_GMAC_MAC_CONFIG:
+ gmac->regs[offset / sizeof(uint32_t)] = v;
+ break;
+
+ case A_NPCM_GMAC_MII_ADDR:
+ npcm_gmac_mdio_access(gmac, v);
+ break;
+
+ case A_NPCM_GMAC_MAC0_ADDR_HI:
+ gmac->regs[offset / sizeof(uint32_t)] = v;
+ gmac->conf.macaddr.a[0] = v >> 8;
+ gmac->conf.macaddr.a[1] = v >> 0;
+ break;
+
+ case A_NPCM_GMAC_MAC0_ADDR_LO:
+ gmac->regs[offset / sizeof(uint32_t)] = v;
+ gmac->conf.macaddr.a[2] = v >> 24;
+ gmac->conf.macaddr.a[3] = v >> 16;
+ gmac->conf.macaddr.a[4] = v >> 8;
+ gmac->conf.macaddr.a[5] = v >> 0;
+ break;
+
+ case A_NPCM_GMAC_MAC1_ADDR_HI:
+ case A_NPCM_GMAC_MAC1_ADDR_LO:
+ case A_NPCM_GMAC_MAC2_ADDR_HI:
+ case A_NPCM_GMAC_MAC2_ADDR_LO:
+ case A_NPCM_GMAC_MAC3_ADDR_HI:
+ case A_NPCM_GMAC_MAC3_ADDR_LO:
+ gmac->regs[offset / sizeof(uint32_t)] = v;
+ qemu_log_mask(LOG_UNIMP,
+ "%s: Only MAC Address 0 is supported. This request "
+ "is ignored.\n", DEVICE(gmac)->canonical_path);
+ break;
+
+ case A_NPCM_DMA_BUS_MODE:
+ gmac->regs[offset / sizeof(uint32_t)] = v;
+ if (v & NPCM_DMA_BUS_MODE_SWR) {
+ npcm_gmac_soft_reset(gmac);
+ }
+ break;
+
+ case A_NPCM_DMA_RCV_POLL_DEMAND:
+ /* We dont actually care about the value */
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
+ break;
+
+ case A_NPCM_DMA_XMT_POLL_DEMAND:
+ /* We dont actually care about the value */
+ gmac_try_send_next_packet(gmac);
+ break;
+
+ case A_NPCM_DMA_CONTROL:
+ gmac->regs[offset / sizeof(uint32_t)] = v;
+ if (v & NPCM_DMA_CONTROL_START_STOP_TX) {
+ gmac_try_send_next_packet(gmac);
+ } else {
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_TX_STOPPED_STATE);
+ }
+ if (v & NPCM_DMA_CONTROL_START_STOP_RX) {
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
+ qemu_flush_queued_packets(qemu_get_queue(gmac->nic));
+ } else {
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_STOPPED_STATE);
+ }
+ break;
+
+ case A_NPCM_DMA_STATUS:
+ /* Check that RO bits are not written to */
+ if (NPCM_DMA_STATUS_RO_MASK(v)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Write of read-only bits of reg: offset: 0x%04"
+ HWADDR_PRIx ", value: 0x%04" PRIx64 "\n",
+ DEVICE(gmac)->canonical_path, offset, v);
+ }
+ /* for W1C bits, implement W1C */
+ gmac->regs[offset / sizeof(uint32_t)] &= ~NPCM_DMA_STATUS_W1C_MASK(v);
+ if (v & NPCM_DMA_STATUS_RU) {
+ /* Clearing RU bit indicates descriptor is owned by DMA again. */
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
+ qemu_flush_queued_packets(qemu_get_queue(gmac->nic));
+ }
+ break;
+
+ default:
+ gmac->regs[offset / sizeof(uint32_t)] = v;
+ break;
+ }
+
+ gmac_update_irq(gmac);
+}
+
+static void npcm_gmac_reset(DeviceState *dev)
+{
+ NPCMGMACState *gmac = NPCM_GMAC(dev);
+
+ npcm_gmac_soft_reset(gmac);
+ memcpy(gmac->phy_regs[0], phy_reg_init, sizeof(phy_reg_init));
+
+ trace_npcm_gmac_reset(DEVICE(gmac)->canonical_path,
+ gmac->phy_regs[0][MII_BMSR]);
+}
+
+static NetClientInfo net_npcm_gmac_info = {
+ .type = NET_CLIENT_DRIVER_NIC,
+ .size = sizeof(NICState),
+ .can_receive = gmac_can_receive,
+ .receive = gmac_receive,
+ .cleanup = gmac_cleanup,
+ .link_status_changed = gmac_set_link,
+};
+
+static const struct MemoryRegionOps npcm_gmac_ops = {
+ .read = npcm_gmac_read,
+ .write = npcm_gmac_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void npcm_gmac_realize(DeviceState *dev, Error **errp)
+{
+ NPCMGMACState *gmac = NPCM_GMAC(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ memory_region_init_io(&gmac->iomem, OBJECT(gmac), &npcm_gmac_ops, gmac,
+ TYPE_NPCM_GMAC, 8 * KiB);
+ sysbus_init_mmio(sbd, &gmac->iomem);
+ sysbus_init_irq(sbd, &gmac->irq);
+
+ qemu_macaddr_default_if_unset(&gmac->conf.macaddr);
+
+ gmac->nic = qemu_new_nic(&net_npcm_gmac_info, &gmac->conf, TYPE_NPCM_GMAC,
+ dev->id, &dev->mem_reentrancy_guard, gmac);
+ qemu_format_nic_info_str(qemu_get_queue(gmac->nic), gmac->conf.macaddr.a);
+ gmac->regs[R_NPCM_GMAC_MAC0_ADDR_HI] = (gmac->conf.macaddr.a[0] << 8) + \
+ gmac->conf.macaddr.a[1];
+ gmac->regs[R_NPCM_GMAC_MAC0_ADDR_LO] = (gmac->conf.macaddr.a[2] << 24) + \
+ (gmac->conf.macaddr.a[3] << 16) + \
+ (gmac->conf.macaddr.a[4] << 8) + \
+ gmac->conf.macaddr.a[5];
+}
+
+static void npcm_gmac_unrealize(DeviceState *dev)
+{
+ NPCMGMACState *gmac = NPCM_GMAC(dev);
+
+ qemu_del_nic(gmac->nic);
+}
+
+static const VMStateDescription vmstate_npcm_gmac = {
+ .name = TYPE_NPCM_GMAC,
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, NPCMGMACState, NPCM_GMAC_NR_REGS),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static Property npcm_gmac_properties[] = {
+ DEFINE_NIC_PROPERTIES(NPCMGMACState, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void npcm_gmac_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
+ dc->desc = "NPCM GMAC Controller";
+ dc->realize = npcm_gmac_realize;
+ dc->unrealize = npcm_gmac_unrealize;
+ dc->reset = npcm_gmac_reset;
+ dc->vmsd = &vmstate_npcm_gmac;
+ device_class_set_props(dc, npcm_gmac_properties);
+}
+
+static const TypeInfo npcm_gmac_types[] = {
+ {
+ .name = TYPE_NPCM_GMAC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(NPCMGMACState),
+ .class_init = npcm_gmac_class_init,
+ },
+};
+DEFINE_TYPES(npcm_gmac_types)
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 387e32e..78efa2e 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -467,6 +467,25 @@ npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=0x%x"
npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int regno) "emc%d: 0x%x = reg[%s/%d]"
npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t value) "emc%d: reg[%s/%d] = 0x%x"
+# npcm_gmac.c
+npcm_gmac_reg_read(const char *name, uint64_t offset, uint32_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx32
+npcm_gmac_reg_write(const char *name, uint64_t offset, uint32_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx32
+npcm_gmac_mdio_access(const char *name, uint8_t is_write, uint8_t pa, uint8_t gr, uint16_t val) "%s: is_write: %" PRIu8 " pa: %" PRIu8 " gr: %" PRIu8 " val: 0x%04" PRIx16
+npcm_gmac_reset(const char *name, uint16_t value) "%s: phy_regs[0][1]: 0x%04" PRIx16
+npcm_gmac_set_link(bool active) "Set link: active=%u"
+npcm_gmac_update_irq(const char *name, uint32_t status, uint32_t intr_en, int level) "%s: Status Reg: 0x%04" PRIX32 " Interrupt Enable Reg: 0x%04" PRIX32 " IRQ Set: %d"
+npcm_gmac_packet_desc_read(const char* name, uint32_t desc_addr) "%s: attempting to read descriptor @0x%04" PRIX32
+npcm_gmac_packet_receive(const char* name, uint32_t len) "%s: RX packet length: 0x%04" PRIX32
+npcm_gmac_packet_receiving_buffer(const char* name, uint32_t buf_len, uint32_t rx_buf_addr) "%s: Receiving into Buffer size: 0x%04" PRIX32 " at address 0x%04" PRIX32
+npcm_gmac_packet_received(const char* name, uint32_t len) "%s: Reception finished, packet left: 0x%04" PRIX32
+npcm_gmac_packet_sent(const char* name, uint16_t len) "%s: TX packet sent!, length: 0x%04" PRIX16
+npcm_gmac_debug_desc_data(const char* name, void* addr, uint32_t des0, uint32_t des1, uint32_t des2, uint32_t des3)"%s: Address: %p Descriptor 0: 0x%04" PRIX32 " Descriptor 1: 0x%04" PRIX32 "Descriptor 2: 0x%04" PRIX32 " Descriptor 3: 0x%04" PRIX32
+npcm_gmac_packet_tx_desc_data(const char* name, uint32_t tdes0, uint32_t tdes1) "%s: Tdes0: 0x%04" PRIX32 " Tdes1: 0x%04" PRIX32
+
+# npcm_pcs.c
+npcm_pcs_reg_read(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
+npcm_pcs_reg_write(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
+
# dp8398x.c
dp8393x_raise_irq(int isr) "raise irq, isr is 0x%04x"
dp8393x_lower_irq(void) "lower irq"
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index dd9e389..c25d50f 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -340,6 +340,8 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
break;
case DESIGNWARE_PCIE_ATU_VIEWPORT:
+ val &= DESIGNWARE_PCIE_ATU_REGION_INBOUND |
+ (DESIGNWARE_PCIE_NUM_VIEWPORTS - 1);
root->atu_viewport = val;
break;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 449abfb..6496d02 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -64,7 +64,7 @@ bool pci_available = true;
static char *pcibus_get_dev_path(DeviceState *dev);
static char *pcibus_get_fw_dev_path(DeviceState *dev);
-static void pcibus_reset(BusState *qbus);
+static void pcibus_reset_hold(Object *obj);
static bool pcie_has_upstream_port(PCIDevice *dev);
static Property pci_props[] = {
@@ -202,13 +202,15 @@ static void pci_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
PCIBusClass *pbc = PCI_BUS_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
k->print_dev = pcibus_dev_print;
k->get_dev_path = pcibus_get_dev_path;
k->get_fw_dev_path = pcibus_get_fw_dev_path;
k->realize = pci_bus_realize;
k->unrealize = pci_bus_unrealize;
- k->reset = pcibus_reset;
+
+ rc->phases.hold = pcibus_reset_hold;
pbc->bus_num = pcibus_num;
pbc->numa_node = pcibus_numa_node;
@@ -424,9 +426,9 @@ void pci_device_reset(PCIDevice *dev)
* Called via bus_cold_reset on RST# assert, after the devices
* have been reset device_cold_reset-ed already.
*/
-static void pcibus_reset(BusState *qbus)
+static void pcibus_reset_hold(Object *obj)
{
- PCIBus *bus = DO_UPCAST(PCIBus, qbus, qbus);
+ PCIBus *bus = PCI_BUS(obj);
int i;
for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
index 15d26ef..34639f2 100644
--- a/hw/s390x/css-bridge.c
+++ b/hw/s390x/css-bridge.c
@@ -56,7 +56,7 @@ static void ccw_device_unplug(HotplugHandler *hotplug_dev,
qdev_unrealize(dev);
}
-static void virtual_css_bus_reset(BusState *qbus)
+static void virtual_css_bus_reset_hold(Object *obj)
{
/* This should actually be modelled via the generic css */
css_reset();
@@ -81,8 +81,9 @@ static char *virtual_css_bus_get_dev_path(DeviceState *dev)
static void virtual_css_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
- k->reset = virtual_css_bus_reset;
+ rc->phases.hold = virtual_css_bus_reset_hold;
k->get_dev_path = virtual_css_bus_get_dev_path;
}
diff --git a/hw/ssi/Kconfig b/hw/ssi/Kconfig
index 7d90a02..83ee53c 100644
--- a/hw/ssi/Kconfig
+++ b/hw/ssi/Kconfig
@@ -20,3 +20,7 @@ config XILINX_SPIPS
config STM32F2XX_SPI
bool
select SSI
+
+config BCM2835_SPI
+ bool
+ select SSI
diff --git a/hw/ssi/bcm2835_spi.c b/hw/ssi/bcm2835_spi.c
new file mode 100644
index 0000000..6ecb42d
--- /dev/null
+++ b/hw/ssi/bcm2835_spi.c
@@ -0,0 +1,288 @@
+/*
+ * BCM2835 SPI Master Controller
+ *
+ * Copyright (c) 2024 Rayhan Faizel <rayhan.faizel@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/fifo8.h"
+#include "hw/ssi/bcm2835_spi.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+
+static void bcm2835_spi_update_int(BCM2835SPIState *s)
+{
+ int do_interrupt = 0;
+
+ /* Interrupt on DONE */
+ if (s->cs & BCM2835_SPI_CS_INTD && s->cs & BCM2835_SPI_CS_DONE) {
+ do_interrupt = 1;
+ }
+ /* Interrupt on RXR */
+ if (s->cs & BCM2835_SPI_CS_INTR && s->cs & BCM2835_SPI_CS_RXR) {
+ do_interrupt = 1;
+ }
+ qemu_set_irq(s->irq, do_interrupt);
+}
+
+static void bcm2835_spi_update_rx_flags(BCM2835SPIState *s)
+{
+ /* Set RXD if RX FIFO is non empty */
+ if (!fifo8_is_empty(&s->rx_fifo)) {
+ s->cs |= BCM2835_SPI_CS_RXD;
+ } else {
+ s->cs &= ~BCM2835_SPI_CS_RXD;
+ }
+
+ /* Set RXF if RX FIFO is full */
+ if (fifo8_is_full(&s->rx_fifo)) {
+ s->cs |= BCM2835_SPI_CS_RXF;
+ } else {
+ s->cs &= ~BCM2835_SPI_CS_RXF;
+ }
+
+ /* Set RXR if RX FIFO is 3/4th used or above */
+ if (fifo8_num_used(&s->rx_fifo) >= FIFO_SIZE_3_4) {
+ s->cs |= BCM2835_SPI_CS_RXR;
+ } else {
+ s->cs &= ~BCM2835_SPI_CS_RXR;
+ }
+}
+
+static void bcm2835_spi_update_tx_flags(BCM2835SPIState *s)
+{
+ /* Set TXD if TX FIFO is not full */
+ if (fifo8_is_full(&s->tx_fifo)) {
+ s->cs &= ~BCM2835_SPI_CS_TXD;
+ } else {
+ s->cs |= BCM2835_SPI_CS_TXD;
+ }
+
+ /* Set DONE if in TA mode and TX FIFO is empty */
+ if (fifo8_is_empty(&s->tx_fifo) && s->cs & BCM2835_SPI_CS_TA) {
+ s->cs |= BCM2835_SPI_CS_DONE;
+ } else {
+ s->cs &= ~BCM2835_SPI_CS_DONE;
+ }
+}
+
+static void bcm2835_spi_flush_tx_fifo(BCM2835SPIState *s)
+{
+ uint8_t tx_byte, rx_byte;
+
+ while (!fifo8_is_empty(&s->tx_fifo) && !fifo8_is_full(&s->rx_fifo)) {
+ tx_byte = fifo8_pop(&s->tx_fifo);
+ rx_byte = ssi_transfer(s->bus, tx_byte);
+ fifo8_push(&s->rx_fifo, rx_byte);
+ }
+
+ bcm2835_spi_update_tx_flags(s);
+ bcm2835_spi_update_rx_flags(s);
+}
+
+static uint64_t bcm2835_spi_read(void *opaque, hwaddr addr, unsigned size)
+{
+ BCM2835SPIState *s = opaque;
+ uint32_t readval = 0;
+
+ switch (addr) {
+ case BCM2835_SPI_CS:
+ readval = s->cs & 0xffffffff;
+ break;
+ case BCM2835_SPI_FIFO:
+ bcm2835_spi_flush_tx_fifo(s);
+ if (s->cs & BCM2835_SPI_CS_RXD) {
+ readval = fifo8_pop(&s->rx_fifo);
+ bcm2835_spi_update_rx_flags(s);
+ }
+
+ bcm2835_spi_update_int(s);
+ break;
+ case BCM2835_SPI_CLK:
+ readval = s->clk & 0xffff;
+ break;
+ case BCM2835_SPI_DLEN:
+ readval = s->dlen & 0xffff;
+ break;
+ case BCM2835_SPI_LTOH:
+ readval = s->ltoh & 0xf;
+ break;
+ case BCM2835_SPI_DC:
+ readval = s->dc & 0xffffffff;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
+ }
+ return readval;
+}
+
+static void bcm2835_spi_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned int size)
+{
+ BCM2835SPIState *s = opaque;
+
+ switch (addr) {
+ case BCM2835_SPI_CS:
+ s->cs = (value & ~RO_MASK) | (s->cs & RO_MASK);
+ if (!(s->cs & BCM2835_SPI_CS_TA)) {
+ /* Clear DONE and RXR if TA is off */
+ s->cs &= ~(BCM2835_SPI_CS_DONE);
+ s->cs &= ~(BCM2835_SPI_CS_RXR);
+ }
+
+ /* Clear RX FIFO */
+ if (s->cs & BCM2835_SPI_CLEAR_RX) {
+ fifo8_reset(&s->rx_fifo);
+ bcm2835_spi_update_rx_flags(s);
+ }
+
+ /* Clear TX FIFO*/
+ if (s->cs & BCM2835_SPI_CLEAR_TX) {
+ fifo8_reset(&s->tx_fifo);
+ bcm2835_spi_update_tx_flags(s);
+ }
+
+ /* Set Transfer Active */
+ if (s->cs & BCM2835_SPI_CS_TA) {
+ bcm2835_spi_update_tx_flags(s);
+ }
+
+ if (s->cs & BCM2835_SPI_CS_DMAEN) {
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "DMA not supported\n", __func__);
+ }
+
+ if (s->cs & BCM2835_SPI_CS_LEN) {
+ qemu_log_mask(LOG_UNIMP, "%s: " \
+ "LoSSI not supported\n", __func__);
+ }
+
+ bcm2835_spi_update_int(s);
+ break;
+ case BCM2835_SPI_FIFO:
+ /*
+ * According to documentation, writes to FIFO without TA controls
+ * CS and DLEN registers. This is supposed to be used in DMA mode
+ * which is currently unimplemented. Moreover, Linux does not make
+ * use of this and directly modifies the CS and DLEN registers.
+ */
+ if (s->cs & BCM2835_SPI_CS_TA) {
+ if (s->cs & BCM2835_SPI_CS_TXD) {
+ fifo8_push(&s->tx_fifo, value & 0xff);
+ bcm2835_spi_update_tx_flags(s);
+ }
+
+ bcm2835_spi_flush_tx_fifo(s);
+ bcm2835_spi_update_int(s);
+ }
+ break;
+ case BCM2835_SPI_CLK:
+ s->clk = value & 0xffff;
+ break;
+ case BCM2835_SPI_DLEN:
+ s->dlen = value & 0xffff;
+ break;
+ case BCM2835_SPI_LTOH:
+ s->ltoh = value & 0xf;
+ break;
+ case BCM2835_SPI_DC:
+ s->dc = value & 0xffffffff;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
+ }
+}
+
+static const MemoryRegionOps bcm2835_spi_ops = {
+ .read = bcm2835_spi_read,
+ .write = bcm2835_spi_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void bcm2835_spi_realize(DeviceState *dev, Error **errp)
+{
+ BCM2835SPIState *s = BCM2835_SPI(dev);
+ s->bus = ssi_create_bus(dev, "spi");
+
+ memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_spi_ops, s,
+ TYPE_BCM2835_SPI, 0x18);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
+
+ fifo8_create(&s->tx_fifo, FIFO_SIZE);
+ fifo8_create(&s->rx_fifo, FIFO_SIZE);
+}
+static void bcm2835_spi_reset(DeviceState *dev)
+{
+ BCM2835SPIState *s = BCM2835_SPI(dev);
+
+ fifo8_reset(&s->tx_fifo);
+ fifo8_reset(&s->rx_fifo);
+
+ /* Reset values according to BCM2835 Peripheral Documentation */
+ s->cs = BCM2835_SPI_CS_TXD | BCM2835_SPI_CS_REN;
+ s->clk = 0;
+ s->dlen = 0;
+ s->ltoh = 0x1;
+ s->dc = 0x30201020;
+}
+
+static const VMStateDescription vmstate_bcm2835_spi = {
+ .name = TYPE_BCM2835_SPI,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]) {
+ VMSTATE_FIFO8(tx_fifo, BCM2835SPIState),
+ VMSTATE_FIFO8(rx_fifo, BCM2835SPIState),
+ VMSTATE_UINT32(cs, BCM2835SPIState),
+ VMSTATE_UINT32(clk, BCM2835SPIState),
+ VMSTATE_UINT32(dlen, BCM2835SPIState),
+ VMSTATE_UINT32(ltoh, BCM2835SPIState),
+ VMSTATE_UINT32(dc, BCM2835SPIState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void bcm2835_spi_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = bcm2835_spi_reset;
+ dc->realize = bcm2835_spi_realize;
+ dc->vmsd = &vmstate_bcm2835_spi;
+}
+
+static const TypeInfo bcm2835_spi_info = {
+ .name = TYPE_BCM2835_SPI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCM2835SPIState),
+ .class_init = bcm2835_spi_class_init,
+};
+
+static void bcm2835_spi_register_types(void)
+{
+ type_register_static(&bcm2835_spi_info);
+}
+
+type_init(bcm2835_spi_register_types)
diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build
index 0aebcdd6..b999aeb 100644
--- a/hw/ssi/meson.build
+++ b/hw/ssi/meson.build
@@ -11,3 +11,4 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-ospi.c'))
system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_spi.c'))
system_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_spi.c'))
system_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_spi_host.c'))
+system_ss.add(when: 'CONFIG_BCM2835_SPI', if_true: files('bcm2835_spi.c'))
diff --git a/hw/xen/trace-events b/hw/xen/trace-events
index 67a6c41..d1b27f6 100644
--- a/hw/xen/trace-events
+++ b/hw/xen/trace-events
@@ -42,7 +42,7 @@ xs_node_vscanf(char *path, char *value) "%s %s"
xs_node_watch(char *path) "%s"
xs_node_unwatch(char *path) "%s"
-# xen-hvm.c
+# xen-hvm-common.c
xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: 0x%lx, size 0x%lx"
xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) "0x%"PRIx64" size 0x%lx, log_dirty %i"
handle_ioreq(void *req, uint32_t type, uint32_t dir, uint32_t df, uint32_t data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) "I/O=%p type=%d dir=%d df=%d ptr=%d port=0x%"PRIx64" data=0x%"PRIx64" count=%d size=%d"
@@ -55,8 +55,27 @@ cpu_ioreq_move(void *req, uint32_t dir, uint32_t df, uint32_t data_is_ptr, uint6
xen_map_resource_ioreq(uint32_t id, void *addr) "id: %u addr: %p"
cpu_ioreq_config_read(void *req, uint32_t sbdf, uint32_t reg, uint32_t size, uint32_t data) "I/O=%p sbdf=0x%x reg=%u size=%u data=0x%x"
cpu_ioreq_config_write(void *req, uint32_t sbdf, uint32_t reg, uint32_t size, uint32_t data) "I/O=%p sbdf=0x%x reg=%u size=%u data=0x%x"
+cpu_get_ioreq_from_shared_memory_req_not_ready(int state, int data_is_ptr, uint64_t addr, uint64_t data, uint32_t count, uint32_t size) "I/O request not ready: 0x%x, ptr: 0x%x, port: 0x%"PRIx64", data: 0x%"PRIx64", count: %u, size: %u"
+xen_main_loop_prepare_init_cpu(int id, void *cpu) "cpu_by_vcpu_id[%d]=%p"
+xen_map_ioreq_server_shared_page(long unsigned int ioreq_pfn) "shared page at pfn 0x%lx"
+xen_map_ioreq_server_buffered_io_page(long unsigned int ioreq_pfn) "buffered io page at pfn 0x%lx"
+xen_map_ioreq_server_buffered_io_evtchn(int bufioreq_evtchn) "buffered io evtchn is 0x%x"
+destroy_hvm_domain_cannot_acquire_handle(void) "Cannot acquire xenctrl handle"
+destroy_hvm_domain_failed_action(const char *action, int sts, char *errno_s) "xc_domain_shutdown failed to issue %s, sts %d, %s"
+destroy_hvm_domain_action(int xen_domid, const char *action) "Issued domain %d %s"
# xen-mapcache.c
xen_map_cache(uint64_t phys_addr) "want 0x%"PRIx64
xen_remap_bucket(uint64_t index) "index 0x%"PRIx64
xen_map_cache_return(void* ptr) "%p"
+xen_map_cache_init(uint64_t nr_buckets, uint64_t size) "nr_buckets = 0x%"PRIx64" size 0x%"PRIx64
+xen_replace_cache_entry_dummy(uint64_t old_phys_addr, uint64_t new_phys_addr) "Replacing a dummy mapcache entry for 0x%"PRIx64" with 0x%"PRIx64
+xen_invalidate_map_cache_entry_unlocked_not_found(void *p) "could not find %p"
+xen_invalidate_map_cache_entry_unlocked_found(uint64_t addr, void *p) " 0x%"PRIx64" -> %p is present"
+xen_invalidate_map_cache_entry_unlocked_miss(void *buffer) "Trying to unmap address %p that is not in the mapcache"
+xen_replace_cache_entry_unlocked_could_not_update_entry(uint64_t old_phys_addr) "Unable to update a mapcache entry for 0x%"PRIx64
+xen_ram_addr_from_mapcache_not_found(void *p) "could not find %p"
+xen_ram_addr_from_mapcache_found(uint64_t addr, void *p) " 0x%"PRIx64" -> %p is present"
+xen_ram_addr_from_mapcache_not_in_cache(void *p) "Trying to find address %p that is not in the mapcache"
+xen_replace_cache_entry_unlocked(uint64_t old_phys_addr) "Trying to update an entry for 0x%"PRIx64" that is not in the mapcache"
+xen_invalidate_map_cache(uint64_t paddr_index, void *vaddr_req) "Locked DMA mapping while invalidating mapcache 0x%"PRIx64" -> %p is present"
diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index 47e6cb1..baa1adb 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -20,8 +20,8 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
if (runstate_check(RUN_STATE_INMIGRATE)) {
/* RAM already populated in Xen */
- fprintf(stderr, "%s: do not alloc "RAM_ADDR_FMT
- " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE\n",
+ warn_report("%s: do not alloc "RAM_ADDR_FMT
+ " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE",
__func__, size, ram_addr);
return;
}
@@ -169,11 +169,12 @@ static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu)
ioreq_t *req = xen_vcpu_ioreq(state->shared_page, vcpu);
if (req->state != STATE_IOREQ_READY) {
- DPRINTF("I/O request not ready: "
- "%x, ptr: %x, port: %"PRIx64", "
- "data: %"PRIx64", count: %u, size: %u\n",
- req->state, req->data_is_ptr, req->addr,
- req->data, req->count, req->size);
+ trace_cpu_get_ioreq_from_shared_memory_req_not_ready(req->state,
+ req->data_is_ptr,
+ req->addr,
+ req->data,
+ req->count,
+ req->size);
return NULL;
}
@@ -551,9 +552,9 @@ static void cpu_handle_ioreq(void *opaque)
req->data = copy.data;
if (req->state != STATE_IOREQ_INPROCESS) {
- fprintf(stderr, "Badness in I/O request ... not in service?!: "
+ warn_report("Badness in I/O request ... not in service?!: "
"%x, ptr: %x, port: %"PRIx64", "
- "data: %"PRIx64", count: %u, size: %u, type: %u\n",
+ "data: %"PRIx64", count: %u, size: %u, type: %u",
req->state, req->data_is_ptr, req->addr,
req->data, req->count, req->size, req->type);
destroy_hvm_domain(false);
@@ -601,10 +602,9 @@ static void xen_main_loop_prepare(XenIOState *state)
if (evtchn_fd != -1) {
CPUState *cpu_state;
- DPRINTF("%s: Init cpu_by_vcpu_id\n", __func__);
CPU_FOREACH(cpu_state) {
- DPRINTF("%s: cpu_by_vcpu_id[%d]=%p\n",
- __func__, cpu_state->cpu_index, cpu_state);
+ trace_xen_main_loop_prepare_init_cpu(cpu_state->cpu_index,
+ cpu_state);
state->cpu_by_vcpu_id[cpu_state->cpu_index] = cpu_state;
}
qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
@@ -681,7 +681,7 @@ static int xen_map_ioreq_server(XenIOState *state)
}
if (state->shared_page == NULL) {
- DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
+ trace_xen_map_ioreq_server_shared_page(ioreq_pfn);
state->shared_page = xenforeignmemory_map(xen_fmem, xen_domid,
PROT_READ | PROT_WRITE,
@@ -693,7 +693,7 @@ static int xen_map_ioreq_server(XenIOState *state)
}
if (state->buffered_io_page == NULL) {
- DPRINTF("buffered io page at pfn %lx\n", bufioreq_pfn);
+ trace_xen_map_ioreq_server_buffered_io_page(bufioreq_pfn);
state->buffered_io_page = xenforeignmemory_map(xen_fmem, xen_domid,
PROT_READ | PROT_WRITE,
@@ -709,7 +709,7 @@ static int xen_map_ioreq_server(XenIOState *state)
return -1;
}
- DPRINTF("buffered io evtchn is %x\n", bufioreq_evtchn);
+ trace_xen_map_ioreq_server_buffered_io_evtchn(bufioreq_evtchn);
state->bufioreq_remote_port = bufioreq_evtchn;
@@ -737,16 +737,17 @@ void destroy_hvm_domain(bool reboot)
xc_handle = xc_interface_open(0, 0, 0);
if (xc_handle == NULL) {
- fprintf(stderr, "Cannot acquire xenctrl handle\n");
+ trace_destroy_hvm_domain_cannot_acquire_handle();
} else {
sts = xc_domain_shutdown(xc_handle, xen_domid, reason);
if (sts != 0) {
- fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
- "sts %d, %s\n", reboot ? "reboot" : "poweroff",
- sts, strerror(errno));
+ trace_destroy_hvm_domain_failed_action(
+ reboot ? "reboot" : "poweroff", sts, strerror(errno)
+ );
} else {
- fprintf(stderr, "Issued domain %d %s\n", xen_domid,
- reboot ? "reboot" : "poweroff");
+ trace_destroy_hvm_domain_action(
+ xen_domid, reboot ? "reboot" : "poweroff"
+ );
}
xc_interface_close(xc_handle);
}
@@ -757,9 +758,9 @@ void xen_shutdown_fatal_error(const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
+ error_vreport(fmt, ap);
va_end(ap);
- fprintf(stderr, "Will destroy the domain.\n");
+ error_report("Will destroy the domain.");
/* destroy the domain */
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_ERROR);
}
diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index f7d9746..4f956d0 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -22,16 +22,6 @@
#include "trace.h"
-//#define MAPCACHE_DEBUG
-
-#ifdef MAPCACHE_DEBUG
-# define DPRINTF(fmt, ...) do { \
- fprintf(stderr, "xen_mapcache: " fmt, ## __VA_ARGS__); \
-} while (0)
-#else
-# define DPRINTF(fmt, ...) do { } while (0)
-#endif
-
#if HOST_LONG_BITS == 32
# define MCACHE_BUCKET_SHIFT 16
# define MCACHE_MAX_SIZE (1UL<<31) /* 2GB Cap */
@@ -145,8 +135,7 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
size = mapcache->nr_buckets * sizeof (MapCacheEntry);
size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
- DPRINTF("%s, nr_buckets = %lx size %lu\n", __func__,
- mapcache->nr_buckets, size);
+ trace_xen_map_cache_init(mapcache->nr_buckets, size);
mapcache->entry = g_malloc0(size);
}
@@ -286,7 +275,9 @@ tryagain:
test_bits(address_offset >> XC_PAGE_SHIFT,
test_bit_size >> XC_PAGE_SHIFT,
mapcache->last_entry->valid_mapping)) {
- trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset);
+ trace_xen_map_cache_return(
+ mapcache->last_entry->vaddr_base + address_offset
+ );
return mapcache->last_entry->vaddr_base + address_offset;
}
@@ -356,9 +347,8 @@ tryagain:
MapCacheRev *reventry = g_new0(MapCacheRev, 1);
entry->lock++;
if (entry->lock == 0) {
- fprintf(stderr,
- "mapcache entry lock overflow: "HWADDR_FMT_plx" -> %p\n",
- entry->paddr_index, entry->vaddr_base);
+ error_report("mapcache entry lock overflow: "HWADDR_FMT_plx" -> %p",
+ entry->paddr_index, entry->vaddr_base);
abort();
}
reventry->dma = dma;
@@ -368,7 +358,9 @@ tryagain:
QTAILQ_INSERT_HEAD(&mapcache->locked_entries, reventry, next);
}
- trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset);
+ trace_xen_map_cache_return(
+ mapcache->last_entry->vaddr_base + address_offset
+ );
return mapcache->last_entry->vaddr_base + address_offset;
}
@@ -402,10 +394,10 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
}
}
if (!found) {
- fprintf(stderr, "%s, could not find %p\n", __func__, ptr);
+ trace_xen_ram_addr_from_mapcache_not_found(ptr);
QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
- DPRINTF(" "HWADDR_FMT_plx" -> %p is present\n", reventry->paddr_index,
- reventry->vaddr_req);
+ trace_xen_ram_addr_from_mapcache_found(reventry->paddr_index,
+ reventry->vaddr_req);
}
abort();
return 0;
@@ -416,7 +408,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
entry = entry->next;
}
if (!entry) {
- DPRINTF("Trying to find address %p that is not in the mapcache!\n", ptr);
+ trace_xen_ram_addr_from_mapcache_not_in_cache(ptr);
raddr = 0;
} else {
raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
@@ -443,9 +435,12 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
}
}
if (!found) {
- DPRINTF("%s, could not find %p\n", __func__, buffer);
+ trace_xen_invalidate_map_cache_entry_unlocked_not_found(buffer);
QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
- DPRINTF(" "HWADDR_FMT_plx" -> %p is present\n", reventry->paddr_index, reventry->vaddr_req);
+ trace_xen_invalidate_map_cache_entry_unlocked_found(
+ reventry->paddr_index,
+ reventry->vaddr_req
+ );
}
return;
}
@@ -463,7 +458,7 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer)
entry = entry->next;
}
if (!entry) {
- DPRINTF("Trying to unmap address %p that is not in the mapcache!\n", buffer);
+ trace_xen_invalidate_map_cache_entry_unlocked_miss(buffer);
return;
}
entry->lock--;
@@ -502,9 +497,8 @@ void xen_invalidate_map_cache(void)
if (!reventry->dma) {
continue;
}
- fprintf(stderr, "Locked DMA mapping while invalidating mapcache!"
- " "HWADDR_FMT_plx" -> %p is present\n",
- reventry->paddr_index, reventry->vaddr_req);
+ trace_xen_invalidate_map_cache(reventry->paddr_index,
+ reventry->vaddr_req);
}
for (i = 0; i < mapcache->nr_buckets; i++) {
@@ -562,24 +556,23 @@ static uint8_t *xen_replace_cache_entry_unlocked(hwaddr old_phys_addr,
entry = entry->next;
}
if (!entry) {
- DPRINTF("Trying to update an entry for "HWADDR_FMT_plx \
- "that is not in the mapcache!\n", old_phys_addr);
+ trace_xen_replace_cache_entry_unlocked(old_phys_addr);
return NULL;
}
address_index = new_phys_addr >> MCACHE_BUCKET_SHIFT;
address_offset = new_phys_addr & (MCACHE_BUCKET_SIZE - 1);
- fprintf(stderr, "Replacing a dummy mapcache entry for "HWADDR_FMT_plx \
- " with "HWADDR_FMT_plx"\n", old_phys_addr, new_phys_addr);
+ trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
xen_remap_bucket(entry, entry->vaddr_base,
cache_size, address_index, false);
if (!test_bits(address_offset >> XC_PAGE_SHIFT,
test_bit_size >> XC_PAGE_SHIFT,
entry->valid_mapping)) {
- DPRINTF("Unable to update a mapcache entry for "HWADDR_FMT_plx"!\n",
- old_phys_addr);
+ trace_xen_replace_cache_entry_unlocked_could_not_update_entry(
+ old_phys_addr
+ );
return NULL;
}