aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel/kvm/kvm-all.c47
-rw-r--r--docs/about/deprecated.rst27
-rw-r--r--docs/devel/rust.rst1
-rw-r--r--hmp-commands-info.hx19
-rw-r--r--hw/arm/aspeed.c36
-rw-r--r--hw/arm/aspeed_ast10x0.c89
-rw-r--r--hw/arm/aspeed_ast2400.c94
-rw-r--r--hw/arm/aspeed_ast2600.c121
-rw-r--r--hw/arm/aspeed_ast27x0-fc.c33
-rw-r--r--hw/arm/aspeed_ast27x0-ssp.c74
-rw-r--r--hw/arm/aspeed_ast27x0-tsp.c74
-rw-r--r--hw/arm/aspeed_ast27x0.c107
-rw-r--r--hw/arm/aspeed_coprocessor_common.c49
-rw-r--r--hw/arm/aspeed_soc_common.c63
-rw-r--r--hw/arm/fby35.c10
-rw-r--r--hw/arm/meson.build7
-rw-r--r--hw/core/machine-hmp-cmds.c23
-rw-r--r--hw/core/machine-qmp-cmds.c24
-rw-r--r--hw/display/xenfb.c3
-rw-r--r--hw/hppa/machine.c102
-rw-r--r--hw/intc/apic.c2
-rw-r--r--hw/loongarch/boot.c7
-rw-r--r--hw/net/can/xlnx-versal-canfd.c4
-rw-r--r--hw/ppc/ppce500_spin.c3
-rw-r--r--hw/s390x/sclp.c18
-rw-r--r--hw/sparc/leon3.c2
-rw-r--r--hw/vmapple/vmapple.c2
-rw-r--r--hw/xtensa/xtfpga.c2
-rw-r--r--include/hw/arm/aspeed_coprocessor.h61
-rw-r--r--include/hw/arm/aspeed_soc.h48
-rw-r--r--include/monitor/hmp.h2
-rw-r--r--include/qemu/timer.h6
-rw-r--r--include/system/kvm.h18
-rw-r--r--qapi/accelerator.json47
-rw-r--r--rust/Cargo.lock3
-rw-r--r--rust/bql/Cargo.toml1
-rw-r--r--rust/bql/meson.build1
-rw-r--r--rust/bql/src/cell.rs23
-rw-r--r--rust/hw/char/pl011/src/registers.rs1
-rw-r--r--rust/hw/timer/hpet/src/fw_cfg.rs4
-rw-r--r--rust/meson.build2
-rw-r--r--rust/migration/Cargo.toml2
-rw-r--r--rust/migration/meson.build7
-rw-r--r--rust/migration/src/lib.rs5
-rw-r--r--rust/migration/src/migratable.rs442
-rw-r--r--rust/migration/src/vmstate.rs86
-rw-r--r--rust/qemu-macros/src/lib.rs97
-rw-r--r--rust/qemu-macros/src/migration_state.rs298
-rw-r--r--rust/qemu-macros/src/tests.rs113
-rw-r--r--target/arm/kvm.c2
-rw-r--r--target/i386/cpu.c23
-rw-r--r--target/i386/cpu.h8
-rw-r--r--target/i386/helper.c4
-rw-r--r--target/i386/kvm/kvm.c23
-rw-r--r--target/i386/tcg/decode-new.c.inc2
-rw-r--r--target/i386/tcg/seg_helper.c2
-rw-r--r--target/i386/tcg/system/excp_helper.c3
-rw-r--r--target/i386/tcg/system/seg_helper.c1
-rw-r--r--target/i386/tcg/system/smm_helper.c10
-rw-r--r--target/loongarch/kvm/kvm.c4
-rw-r--r--target/mips/kvm.c6
-rw-r--r--target/ppc/kvm.c2
-rw-r--r--target/riscv/kvm/kvm-cpu.c2
-rw-r--r--target/s390x/kvm/kvm.c2
-rwxr-xr-xtests/functional/aarch64/test_aspeed_ast2700.py60
-rwxr-xr-xtests/functional/aarch64/test_aspeed_ast2700fc.py13
-rw-r--r--tests/functional/arm/meson.build6
-rwxr-xr-xtests/functional/arm/test_aspeed_ast1030.py17
-rwxr-xr-xtests/functional/arm/test_aspeed_ast2500.py8
-rwxr-xr-xtests/functional/arm/test_aspeed_ast2600_buildroot.py (renamed from tests/functional/arm/test_aspeed_ast2600.py)74
-rwxr-xr-xtests/functional/arm/test_aspeed_ast2600_sdk.py94
-rw-r--r--util/async.c11
-rw-r--r--util/qemu-timer.c8
73 files changed, 2001 insertions, 694 deletions
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 58802f7..5603192 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -2937,22 +2937,32 @@ void kvm_cpu_synchronize_state(CPUState *cpu)
}
}
-static void do_kvm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg)
+static bool kvm_cpu_synchronize_put(CPUState *cpu, KvmPutState state,
+ const char *desc)
{
Error *err = NULL;
- int ret = kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE, &err);
+ int ret = kvm_arch_put_registers(cpu, state, &err);
if (ret) {
if (err) {
- error_reportf_err(err, "Restoring resisters after reset: ");
+ error_reportf_err(err, "Restoring resisters %s: ", desc);
} else {
- error_report("Failed to put registers after reset: %s",
+ error_report("Failed to put registers %s: %s", desc,
strerror(-ret));
}
- cpu_dump_state(cpu, stderr, CPU_DUMP_CODE);
- vm_stop(RUN_STATE_INTERNAL_ERROR);
+ return false;
}
cpu->vcpu_dirty = false;
+
+ return true;
+}
+
+static void do_kvm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg)
+{
+ if (!kvm_cpu_synchronize_put(cpu, KVM_PUT_RESET_STATE, "after reset")) {
+ cpu_dump_state(cpu, stderr, CPU_DUMP_CODE);
+ vm_stop(RUN_STATE_INTERNAL_ERROR);
+ }
}
void kvm_cpu_synchronize_post_reset(CPUState *cpu)
@@ -2966,19 +2976,9 @@ void kvm_cpu_synchronize_post_reset(CPUState *cpu)
static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg)
{
- Error *err = NULL;
- int ret = kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE, &err);
- if (ret) {
- if (err) {
- error_reportf_err(err, "Putting registers after init: ");
- } else {
- error_report("Failed to put registers after init: %s",
- strerror(-ret));
- }
+ if (!kvm_cpu_synchronize_put(cpu, KVM_PUT_FULL_STATE, "after init")) {
exit(1);
}
-
- cpu->vcpu_dirty = false;
}
void kvm_cpu_synchronize_post_init(CPUState *cpu)
@@ -3168,20 +3168,11 @@ int kvm_cpu_exec(CPUState *cpu)
MemTxAttrs attrs;
if (cpu->vcpu_dirty) {
- Error *err = NULL;
- ret = kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE, &err);
- if (ret) {
- if (err) {
- error_reportf_err(err, "Putting registers after init: ");
- } else {
- error_report("Failed to put registers after init: %s",
- strerror(-ret));
- }
+ if (!kvm_cpu_synchronize_put(cpu, KVM_PUT_RUNTIME_STATE,
+ "at runtime")) {
ret = -1;
break;
}
-
- cpu->vcpu_dirty = false;
}
kvm_arch_pre_run(cpu, run);
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 67e5277..98361f5 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -285,6 +285,33 @@ and serves as the initial engineering sample rather than a production version.
A newer revision, A1, is now supported, and the ``ast2700a1-evb`` should
replace the older A0 version.
+Arm ``sonorapass-bmc`` machine (since 10.2)
+'''''''''''''''''''''''''''''''''''''''''''
+
+The ``sonorapass-bmc`` machine represents a lab server that never
+entered production. Since it does not rely on any specific device
+models, it can be replaced by the ``ast2500-evb`` machine using the
+``fmc-model`` option to specify the flash type. The I2C devices
+connected to the board can be defined via the QEMU command line.
+
+Arm ``qcom-dc-scm-v1-bmc`` and ``qcom-firework-bmc`` machine (since 10.2)
+'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+The ``qcom-dc-scm-v1-bmc`` and ``qcom-firework-bmc`` represent lab
+servers that never entered production. Since they do not rely on any
+specific device models, they can be replaced by the ``ast2600-evb``
+machine using the ``fmc-model`` option to specify the flash type. The
+I2C devices connected to the board can be defined via the QEMU command
+line.
+
+Arm ``fp5280g2-bmc`` machine (since 10.2)
+'''''''''''''''''''''''''''''''''''''''''''
+
+The ``fp5280g2-bmc`` machine does not rely on any specific device
+models, it can be replaced by the ``ast2500-evb`` machine using the
+``fmc-model`` option to specify the flash type. The I2C devices
+connected to the board can be defined via the QEMU command line.
+
RISC-V default machine option (since 10.0)
''''''''''''''''''''''''''''''''''''''''''
diff --git a/docs/devel/rust.rst b/docs/devel/rust.rst
index 2f0ab2e..79c26d9 100644
--- a/docs/devel/rust.rst
+++ b/docs/devel/rust.rst
@@ -155,6 +155,7 @@ module status
``hwcore::irq`` complete
``hwcore::qdev`` stable
``hwcore::sysbus`` stable
+``migration::migratable`` proof of concept
``migration::vmstate`` stable
``qom`` stable
``system::memory`` stable
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index eaaa880..25b4aed 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -271,12 +271,12 @@ ERST
.name = "accel",
.args_type = "",
.params = "",
- .help = "show accelerator info",
+ .help = "show accelerator statistics",
},
SRST
``info accel``
- Show accelerator info.
+ Show accelerator statistics.
ERST
SRST
@@ -308,16 +308,21 @@ SRST
ERST
{
- .name = "mshv",
+ .name = "accelerators",
.args_type = "",
.params = "",
- .help = "show MSHV information",
- .cmd = hmp_info_mshv,
+ .help = "show present and enabled information",
+ .cmd = hmp_info_accelerators,
},
SRST
- ``info mshv``
- Show MSHV information.
+ ``info accelerators``
+ Show which accelerators are compiled into a QEMU binary, and what accelerator
+ is in use. For example::
+
+ kvm qtest [tcg]
+
+ indicates that TCG in use, and that KVM and qtest are also available.
ERST
{
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 6046ec0..21ee62f 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -299,12 +299,14 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc)
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default;
- aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0));
+ aspeed_soc_uart_set_chr(s->uart, uart_chosen, sc->uarts_base,
+ sc->uarts_num, serial_hd(0));
for (int i = 1, uart = sc->uarts_base; i < sc->uarts_num; uart++) {
if (uart == uart_chosen) {
continue;
}
- aspeed_soc_uart_set_chr(s, uart, serial_hd(i++));
+ aspeed_soc_uart_set_chr(s->uart, uart, sc->uarts_base, sc->uarts_num,
+ serial_hd(i++));
}
}
@@ -1310,8 +1312,8 @@ static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp)
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name));
int val;
- int uart_first = aspeed_uart_first(sc);
- int uart_last = aspeed_uart_last(sc);
+ int uart_first = aspeed_uart_first(sc->uarts_base);
+ int uart_last = aspeed_uart_last(sc->uarts_base, sc->uarts_num);
if (sscanf(value, "uart%u", &val) != 1) {
error_setg(errp, "Bad value for \"uart\" property");
@@ -1418,7 +1420,6 @@ static void aspeed_machine_palmetto_class_init(ObjectClass *oc,
amc->spi_model = "mx25l25635f";
amc->num_cs = 1;
amc->i2c_init = palmetto_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 256 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1436,7 +1437,6 @@ static void aspeed_machine_quanta_q71l_class_init(ObjectClass *oc,
amc->spi_model = "mx25l25635e";
amc->num_cs = 1;
amc->i2c_init = quanta_q71l_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 128 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
}
@@ -1455,7 +1455,6 @@ static void aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc,
amc->num_cs = 1;
amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
amc->i2c_init = palmetto_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 256 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
}
@@ -1474,7 +1473,6 @@ static void aspeed_machine_supermicro_x11spi_bmc_class_init(ObjectClass *oc,
amc->num_cs = 1;
amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
amc->i2c_init = palmetto_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 512 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
}
@@ -1492,7 +1490,6 @@ static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc,
amc->spi_model = "mx25l25635f";
amc->num_cs = 1;
amc->i2c_init = ast2500_evb_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 512 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1511,7 +1508,6 @@ static void aspeed_machine_yosemitev2_class_init(ObjectClass *oc,
amc->spi_model = "mx25l25635e";
amc->num_cs = 2;
amc->i2c_init = yosemitev2_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 512 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1529,7 +1525,6 @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc,
amc->spi_model = "mx66l1g45g";
amc->num_cs = 2;
amc->i2c_init = romulus_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 512 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1548,7 +1543,6 @@ static void aspeed_machine_tiogapass_class_init(ObjectClass *oc,
amc->spi_model = "mx25l25635e";
amc->num_cs = 2;
amc->i2c_init = tiogapass_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1560,13 +1554,13 @@ static void aspeed_machine_sonorapass_class_init(ObjectClass *oc,
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
mc->desc = "OCP SonoraPass BMC (ARM1176)";
+ mc->deprecation_reason = "use 'ast2500-evb' instead";
amc->soc_name = "ast2500-a1";
amc->hw_strap1 = SONORAPASS_BMC_HW_STRAP1;
amc->fmc_model = "mx66l1g45g";
amc->spi_model = "mx66l1g45g";
amc->num_cs = 2;
amc->i2c_init = sonorapass_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 512 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1584,7 +1578,6 @@ static void aspeed_machine_witherspoon_class_init(ObjectClass *oc,
amc->spi_model = "mx66l1g45g";
amc->num_cs = 2;
amc->i2c_init = witherspoon_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 512 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1606,7 +1599,6 @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc,
ASPEED_MAC3_ON;
amc->sdhci_wp_inverted = true;
amc->i2c_init = ast2600_evb_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
aspeed_machine_ast2600_class_emmc_init(oc);
@@ -1625,7 +1617,6 @@ static void aspeed_machine_g220a_class_init(ObjectClass *oc, const void *data)
amc->num_cs = 2;
amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
amc->i2c_init = g220a_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 1024 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1637,6 +1628,7 @@ static void aspeed_machine_fp5280g2_class_init(ObjectClass *oc,
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
mc->desc = "Inspur FP5280G2 BMC (ARM1176)";
+ mc->deprecation_reason = "use 'ast2500-evb' instead";
amc->soc_name = "ast2500-a1";
amc->hw_strap1 = FP5280G2_BMC_HW_STRAP1;
amc->fmc_model = "n25q512a";
@@ -1644,7 +1636,6 @@ static void aspeed_machine_fp5280g2_class_init(ObjectClass *oc,
amc->num_cs = 2;
amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
amc->i2c_init = fp5280g2_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 512 * MiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1663,7 +1654,6 @@ static void aspeed_machine_rainier_class_init(ObjectClass *oc, const void *data)
amc->num_cs = 2;
amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
amc->i2c_init = rainier_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
aspeed_machine_ast2600_class_emmc_init(oc);
@@ -1686,7 +1676,6 @@ static void aspeed_machine_fuji_class_init(ObjectClass *oc, const void *data)
amc->macs_mask = ASPEED_MAC3_ON;
amc->i2c_init = fuji_bmc_i2c_init;
amc->uart_default = ASPEED_DEV_UART1;
- mc->auto_create_sdcard = true;
mc->default_ram_size = FUJI_BMC_RAM_SIZE;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1708,7 +1697,6 @@ static void aspeed_machine_bletchley_class_init(ObjectClass *oc,
amc->num_cs = 2;
amc->macs_mask = ASPEED_MAC2_ON;
amc->i2c_init = bletchley_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = BLETCHLEY_BMC_RAM_SIZE;
aspeed_machine_class_init_cpus_defaults(mc);
}
@@ -1728,7 +1716,6 @@ static void aspeed_machine_catalina_class_init(ObjectClass *oc,
amc->num_cs = 2;
amc->macs_mask = ASPEED_MAC2_ON;
amc->i2c_init = catalina_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = CATALINA_BMC_RAM_SIZE;
aspeed_machine_class_init_cpus_defaults(mc);
aspeed_machine_ast2600_class_emmc_init(oc);
@@ -1796,7 +1783,6 @@ static void aspeed_machine_fby35_class_init(ObjectClass *oc, const void *data)
amc->num_cs = 2;
amc->macs_mask = ASPEED_MAC3_ON;
amc->i2c_init = fby35_i2c_init;
- mc->auto_create_sdcard = true;
/* FIXME: Replace this macro with something more general */
mc->default_ram_size = FUJI_BMC_RAM_SIZE;
aspeed_machine_class_init_cpus_defaults(mc);
@@ -1909,7 +1895,6 @@ static void aspeed_machine_ast2700a0_evb_class_init(ObjectClass *oc,
amc->uart_default = ASPEED_DEV_UART12;
amc->i2c_init = ast2700_evb_i2c_init;
amc->vbootrom = true;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
}
@@ -1932,7 +1917,6 @@ static void aspeed_machine_ast2700a1_evb_class_init(ObjectClass *oc,
amc->uart_default = ASPEED_DEV_UART12;
amc->i2c_init = ast2700_evb_i2c_init;
amc->vbootrom = true;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
}
@@ -1945,6 +1929,7 @@ static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
mc->desc = "Qualcomm DC-SCM V1 BMC (Cortex A7)";
+ mc->deprecation_reason = "use 'ast2600-evb' instead";
amc->soc_name = "ast2600-a3";
amc->hw_strap1 = QCOM_DC_SCM_V1_BMC_HW_STRAP1;
amc->hw_strap2 = QCOM_DC_SCM_V1_BMC_HW_STRAP2;
@@ -1953,7 +1938,6 @@ static void aspeed_machine_qcom_dc_scm_v1_class_init(ObjectClass *oc,
amc->num_cs = 2;
amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
amc->i2c_init = qcom_dc_scm_bmc_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
@@ -1965,6 +1949,7 @@ static void aspeed_machine_qcom_firework_class_init(ObjectClass *oc,
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
mc->desc = "Qualcomm DC-SCM V1/Firework BMC (Cortex A7)";
+ mc->deprecation_reason = "use 'ast2600-evb' instead";
amc->soc_name = "ast2600-a3";
amc->hw_strap1 = QCOM_DC_SCM_V1_BMC_HW_STRAP1;
amc->hw_strap2 = QCOM_DC_SCM_V1_BMC_HW_STRAP2;
@@ -1973,7 +1958,6 @@ static void aspeed_machine_qcom_firework_class_init(ObjectClass *oc,
amc->num_cs = 2;
amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
amc->i2c_init = qcom_dc_scm_firework_i2c_init;
- mc->auto_create_sdcard = true;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
};
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index c446e70..7f49c13 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -192,6 +192,7 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
DeviceState *armv7m;
Error *err = NULL;
+ int uart;
int i;
g_autofree char *sram_name = NULL;
@@ -201,17 +202,20 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
}
/* General I/O memory space to catch all unimplemented device */
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->iomem),
+ "aspeed.io",
sc->memmap[ASPEED_DEV_IOMEM],
ASPEED_SOC_IOMEM_SIZE);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->sbc_unimplemented),
+ aspeed_mmio_map_unimplemented(s->memory,
+ SYS_BUS_DEVICE(&s->sbc_unimplemented),
"aspeed.sbc", sc->memmap[ASPEED_DEV_SBC],
0x40000);
/* AST1030 CPU Core */
armv7m = DEVICE(&a->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 256);
- qdev_prop_set_string(armv7m, "cpu-type", aspeed_soc_cpu_type(sc));
+ qdev_prop_set_string(armv7m, "cpu-type",
+ aspeed_soc_cpu_type(sc->valid_cpu_types));
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
object_property_set_link(OBJECT(&a->armv7m), "memory",
OBJECT(s->memory), &error_abort);
@@ -241,7 +245,8 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
+ sc->memmap[ASPEED_DEV_SCU]);
/* I2C */
@@ -250,7 +255,8 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->i2c), 0,
+ sc->memmap[ASPEED_DEV_I2C]);
for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) {
qemu_irq irq = qdev_get_gpio_in(DEVICE(&a->armv7m),
sc->irqmap[ASPEED_DEV_I2C] + i);
@@ -262,7 +268,8 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->i3c), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->i3c), 0, sc->memmap[ASPEED_DEV_I3C]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->i3c), 0,
+ sc->memmap[ASPEED_DEV_I3C]);
for (i = 0; i < ASPEED_I3C_NR_DEVICES; i++) {
qemu_irq irq = qdev_get_gpio_in(DEVICE(&a->armv7m),
sc->irqmap[ASPEED_DEV_I3C] + i);
@@ -274,20 +281,21 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->peci), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->peci), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->peci), 0,
sc->memmap[ASPEED_DEV_PECI]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_PECI));
+ aspeed_soc_ast1030_get_irq(s, ASPEED_DEV_PECI));
/* LPC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->lpc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->lpc), 0, sc->memmap[ASPEED_DEV_LPC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->lpc), 0,
+ sc->memmap[ASPEED_DEV_LPC]);
/* Connect the LPC IRQ to the GIC. It is otherwise unused. */
sysbus_connect_irq(SYS_BUS_DEVICE(&s->lpc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_LPC));
+ aspeed_soc_ast1030_get_irq(s, ASPEED_DEV_LPC));
/*
* On the AST1030 LPC subdevice IRQs are connected straight to the GIC.
@@ -309,8 +317,13 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
sc->irqmap[ASPEED_DEV_KCS] + aspeed_lpc_kcs_4));
/* UART */
- if (!aspeed_soc_uart_realize(s, errp)) {
- return;
+ for (i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
+ if (!aspeed_soc_uart_realize(s->memory, &s->uart[i],
+ sc->memmap[uart], errp)) {
+ return;
+ }
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+ aspeed_soc_ast1030_get_irq(s, uart));
}
/* Timer */
@@ -319,10 +332,10 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timerctrl), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->timerctrl), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->timerctrl), 0,
sc->memmap[ASPEED_DEV_TIMER1]);
for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
- qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i);
+ qemu_irq irq = aspeed_soc_ast1030_get_irq(s, ASPEED_DEV_TIMER1 + i);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
}
@@ -330,9 +343,10 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->adc), 0, sc->memmap[ASPEED_DEV_ADC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->adc), 0,
+ sc->memmap[ASPEED_DEV_ADC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
+ aspeed_soc_ast1030_get_irq(s, ASPEED_DEV_ADC));
/* FMC, The number of CS is set at the board level */
object_property_set_link(OBJECT(&s->fmc), "dram", OBJECT(&s->sram),
@@ -340,11 +354,12 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_DEV_FMC]);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 1,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->fmc), 0,
+ sc->memmap[ASPEED_DEV_FMC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->fmc), 1,
ASPEED_SMC_GET_CLASS(&s->fmc)->flash_window_base);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
+ aspeed_soc_ast1030_get_irq(s, ASPEED_DEV_FMC));
/* SPI */
for (i = 0; i < sc->spis_num; i++) {
@@ -353,9 +368,9 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->spi[i]), 0,
sc->memmap[ASPEED_DEV_SPI1 + i]);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 1,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->spi[i]), 1,
ASPEED_SMC_GET_CLASS(&s->spi[i])->flash_window_base);
}
@@ -363,7 +378,8 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sbc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sbc), 0, sc->memmap[ASPEED_DEV_SBC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sbc), 0,
+ sc->memmap[ASPEED_DEV_SBC]);
/* HACE */
object_property_set_link(OBJECT(&s->hace), "dram", OBJECT(&s->sram),
@@ -371,10 +387,10 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->hace), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->hace), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->hace), 0,
sc->memmap[ASPEED_DEV_HACE]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_HACE));
+ aspeed_soc_ast1030_get_irq(s, ASPEED_DEV_HACE));
/* Watch dog */
for (i = 0; i < sc->wdts_num; i++) {
@@ -386,32 +402,38 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
}
/* GPIO */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->gpio), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->gpio), 0,
sc->memmap[ASPEED_DEV_GPIO]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_GPIO));
+ aspeed_soc_ast1030_get_irq(s, ASPEED_DEV_GPIO));
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->pwm), "aspeed.pwm",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->pwm),
+ "aspeed.pwm",
sc->memmap[ASPEED_DEV_PWM], 0x100);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->espi), "aspeed.espi",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->espi),
+ "aspeed.espi",
sc->memmap[ASPEED_DEV_ESPI], 0x800);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->udc), "aspeed.udc",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->udc),
+ "aspeed.udc",
sc->memmap[ASPEED_DEV_UDC], 0x1000);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->sgpiom), "aspeed.sgpiom",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->sgpiom),
+ "aspeed.sgpiom",
sc->memmap[ASPEED_DEV_SGPIOM], 0x100);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->jtag[0]), "aspeed.jtag",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->jtag[0]),
+ "aspeed.jtag",
sc->memmap[ASPEED_DEV_JTAG0], 0x20);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->jtag[1]), "aspeed.jtag",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->jtag[1]),
+ "aspeed.jtag",
sc->memmap[ASPEED_DEV_JTAG1], 0x20);
}
@@ -441,7 +463,6 @@ static void aspeed_soc_ast1030_class_init(ObjectClass *klass, const void *data)
sc->irqmap = aspeed_soc_ast1030_irqmap;
sc->memmap = aspeed_soc_ast1030_memmap;
sc->num_cpus = 1;
- sc->get_irq = aspeed_soc_ast1030_get_irq;
}
static const TypeInfo aspeed_soc_ast10x0_types[] = {
diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index c7b0f21..b1b826b 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -157,7 +157,7 @@ static void aspeed_ast2400_soc_init(Object *obj)
for (i = 0; i < sc->num_cpus; i++) {
object_initialize_child(obj, "cpu[*]", &a->cpu[i],
- aspeed_soc_cpu_type(sc));
+ aspeed_soc_cpu_type(sc->valid_cpu_types));
}
snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);
@@ -251,6 +251,7 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
AspeedSoCState *s = ASPEED_SOC(dev);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
g_autofree char *sram_name = NULL;
+ int uart;
/* Default boot region (SPI memory or ROMs) */
memory_region_init(&s->spi_boot_container, OBJECT(s),
@@ -259,12 +260,14 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
&s->spi_boot_container);
/* IO space */
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->iomem),
+ "aspeed.io",
sc->memmap[ASPEED_DEV_IOMEM],
ASPEED_SOC_IOMEM_SIZE);
/* Video engine stub */
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->video), "aspeed.video",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->video),
+ "aspeed.video",
sc->memmap[ASPEED_DEV_VIDEO], 0x1000);
/* CPU */
@@ -289,13 +292,15 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
+ sc->memmap[ASPEED_DEV_SCU]);
/* VIC */
if (!sysbus_realize(SYS_BUS_DEVICE(&a->vic), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->vic), 0, sc->memmap[ASPEED_DEV_VIC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->vic), 0,
+ sc->memmap[ASPEED_DEV_VIC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&a->vic), 0,
qdev_get_gpio_in(DEVICE(&a->cpu), ARM_CPU_IRQ));
sysbus_connect_irq(SYS_BUS_DEVICE(&a->vic), 1,
@@ -305,9 +310,10 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->rtc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->rtc), 0, sc->memmap[ASPEED_DEV_RTC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->rtc), 0,
+ sc->memmap[ASPEED_DEV_RTC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_RTC));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_RTC));
/* Timer */
object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu),
@@ -315,10 +321,10 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timerctrl), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->timerctrl), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->timerctrl), 0,
sc->memmap[ASPEED_DEV_TIMER1]);
for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
- qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i);
+ qemu_irq irq = aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_TIMER1 + i);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
}
@@ -326,13 +332,19 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->adc), 0, sc->memmap[ASPEED_DEV_ADC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->adc), 0,
+ sc->memmap[ASPEED_DEV_ADC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_ADC));
/* UART */
- if (!aspeed_soc_uart_realize(s, errp)) {
- return;
+ for (i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
+ if (!aspeed_soc_uart_realize(s->memory, &s->uart[i],
+ sc->memmap[uart], errp)) {
+ return;
+ }
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+ aspeed_soc_ast2400_get_irq(s, uart));
}
/* I2C */
@@ -341,18 +353,19 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->i2c), 0,
+ sc->memmap[ASPEED_DEV_I2C]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_I2C));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_I2C));
/* PECI */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->peci), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->peci), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->peci), 0,
sc->memmap[ASPEED_DEV_PECI]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_PECI));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_PECI));
/* FMC, The number of CS is set at the board level */
object_property_set_link(OBJECT(&s->fmc), "dram", OBJECT(s->dram_mr),
@@ -360,11 +373,12 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_DEV_FMC]);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 1,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->fmc), 0,
+ sc->memmap[ASPEED_DEV_FMC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->fmc), 1,
ASPEED_SMC_GET_CLASS(&s->fmc)->flash_window_base);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_FMC));
/* Set up an alias on the FMC CE0 region (boot default) */
MemoryRegion *fmc0_mmio = &s->fmc.flashes[0].mmio;
@@ -377,9 +391,9 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->spi[i]), 0,
sc->memmap[ASPEED_DEV_SPI1 + i]);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 1,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->spi[i]), 1,
ASPEED_SMC_GET_CLASS(&s->spi[i])->flash_window_base);
}
@@ -388,17 +402,18 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->ehci[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->ehci[i]), 0,
sc->memmap[ASPEED_DEV_EHCI1 + i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_EHCI1 + i));
+ aspeed_soc_ast2400_get_irq(s,
+ ASPEED_DEV_EHCI1 + i));
}
/* SDMC - SDRAM Memory Controller */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdmc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sdmc), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sdmc), 0,
sc->memmap[ASPEED_DEV_SDMC]);
/* Watch dog */
@@ -411,7 +426,7 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
}
/* RAM */
@@ -426,48 +441,49 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->ftgmac100[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
sc->memmap[ASPEED_DEV_ETH1 + i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_ETH1 + i));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_ETH1 + i));
}
/* XDMA */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->xdma), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->xdma), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->xdma), 0,
sc->memmap[ASPEED_DEV_XDMA]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_XDMA));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_XDMA));
/* GPIO */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->gpio), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->gpio), 0,
sc->memmap[ASPEED_DEV_GPIO]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_GPIO));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_GPIO));
/* SDHCI */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sdhci), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sdhci), 0,
sc->memmap[ASPEED_DEV_SDHCI]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_SDHCI));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_SDHCI));
/* LPC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->lpc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->lpc), 0, sc->memmap[ASPEED_DEV_LPC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->lpc), 0,
+ sc->memmap[ASPEED_DEV_LPC]);
/* Connect the LPC IRQ to the VIC */
sysbus_connect_irq(SYS_BUS_DEVICE(&s->lpc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_LPC));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_LPC));
/*
* On the AST2400 and AST2500 the one LPC IRQ is shared between all of the
@@ -496,10 +512,10 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->hace), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->hace), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->hace), 0,
sc->memmap[ASPEED_DEV_HACE]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_HACE));
+ aspeed_soc_ast2400_get_irq(s, ASPEED_DEV_HACE));
}
static void aspeed_soc_ast2400_class_init(ObjectClass *oc, const void *data)
@@ -527,7 +543,6 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, const void *data)
sc->irqmap = aspeed_soc_ast2400_irqmap;
sc->memmap = aspeed_soc_ast2400_memmap;
sc->num_cpus = 1;
- sc->get_irq = aspeed_soc_ast2400_get_irq;
}
static void aspeed_soc_ast2500_class_init(ObjectClass *oc, const void *data)
@@ -555,7 +570,6 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, const void *data)
sc->irqmap = aspeed_soc_ast2500_irqmap;
sc->memmap = aspeed_soc_ast2500_memmap;
sc->num_cpus = 1;
- sc->get_irq = aspeed_soc_ast2400_get_irq;
}
static const TypeInfo aspeed_soc_ast2400_types[] = {
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 03e5df9..498d1ec 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -167,7 +167,7 @@ static void aspeed_soc_ast2600_init(Object *obj)
for (i = 0; i < sc->num_cpus; i++) {
object_initialize_child(obj, "cpu[*]", &a->cpu[i],
- aspeed_soc_cpu_type(sc));
+ aspeed_soc_cpu_type(sc->valid_cpu_types));
}
snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);
@@ -324,7 +324,7 @@ static bool aspeed_soc_ast2600_pcie_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy[0]), errp)) {
return false;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->pcie_phy[0]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->pcie_phy[0]), 0,
sc->memmap[ASPEED_DEV_PCIE_PHY1]);
object_property_set_int(OBJECT(&s->pcie[0]), "dram-base",
@@ -335,7 +335,7 @@ static bool aspeed_soc_ast2600_pcie_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie[0]), errp)) {
return false;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->pcie[0]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->pcie[0]), 0,
sc->memmap[ASPEED_DEV_PCIE0]);
irq = qdev_get_gpio_in(DEVICE(&a->a7mpcore),
@@ -362,6 +362,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
qemu_irq irq;
g_autofree char *sram_name = NULL;
+ int uart;
/* Default boot region (SPI memory or ROMs) */
memory_region_init(&s->spi_boot_container, OBJECT(s),
@@ -370,16 +371,19 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
&s->spi_boot_container);
/* IO space */
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->iomem),
+ "aspeed.io",
sc->memmap[ASPEED_DEV_IOMEM],
ASPEED_SOC_IOMEM_SIZE);
/* Video engine stub */
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->video), "aspeed.video",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->video),
+ "aspeed.video",
sc->memmap[ASPEED_DEV_VIDEO], 0x1000);
/* eMMC Boot Controller stub */
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->emmc_boot_controller),
+ aspeed_mmio_map_unimplemented(s->memory,
+ SYS_BUS_DEVICE(&s->emmc_boot_controller),
"aspeed.emmc-boot-controller",
sc->memmap[ASPEED_DEV_EMMC_BC], 0x1000);
@@ -414,7 +418,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
&error_abort);
sysbus_realize(SYS_BUS_DEVICE(&a->a7mpcore), &error_abort);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->a7mpcore), 0, ASPEED_A7MPCORE_ADDR);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->a7mpcore), 0,
+ ASPEED_A7MPCORE_ADDR);
for (i = 0; i < sc->num_cpus; i++) {
SysBusDevice *sbd = SYS_BUS_DEVICE(&a->a7mpcore);
@@ -440,7 +445,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
sc->memmap[ASPEED_DEV_SRAM], &s->sram);
/* DPMCU */
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->dpmcu), "aspeed.dpmcu",
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->dpmcu),
+ "aspeed.dpmcu",
sc->memmap[ASPEED_DEV_DPMCU],
ASPEED_SOC_DPMCU_SIZE);
@@ -448,15 +454,17 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
+ sc->memmap[ASPEED_DEV_SCU]);
/* RTC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->rtc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->rtc), 0, sc->memmap[ASPEED_DEV_RTC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->rtc), 0,
+ sc->memmap[ASPEED_DEV_RTC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_RTC));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_RTC));
/* Timer */
object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu),
@@ -464,10 +472,10 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timerctrl), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->timerctrl), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->timerctrl), 0,
sc->memmap[ASPEED_DEV_TIMER1]);
for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
- irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i);
+ irq = aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_TIMER1 + i);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
}
@@ -475,13 +483,19 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->adc), 0, sc->memmap[ASPEED_DEV_ADC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->adc), 0,
+ sc->memmap[ASPEED_DEV_ADC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_ADC));
/* UART */
- if (!aspeed_soc_uart_realize(s, errp)) {
- return;
+ for (i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
+ if (!aspeed_soc_uart_realize(s->memory, &s->uart[i],
+ sc->memmap[uart], errp)) {
+ return;
+ }
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+ aspeed_soc_ast2600_get_irq(s, uart));
}
/* I2C */
@@ -490,7 +504,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->i2c), 0,
+ sc->memmap[ASPEED_DEV_I2C]);
for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) {
irq = qdev_get_gpio_in(DEVICE(&a->a7mpcore),
sc->irqmap[ASPEED_DEV_I2C] + i);
@@ -502,10 +517,10 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->peci), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->peci), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->peci), 0,
sc->memmap[ASPEED_DEV_PECI]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peci), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_PECI));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_PECI));
/* PCIe Root Complex (RC) */
if (!aspeed_soc_ast2600_pcie_realize(dev, errp)) {
@@ -518,11 +533,12 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_DEV_FMC]);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 1,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->fmc), 0,
+ sc->memmap[ASPEED_DEV_FMC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->fmc), 1,
ASPEED_SMC_GET_CLASS(&s->fmc)->flash_window_base);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_FMC));
/* Set up an alias on the FMC CE0 region (boot default) */
MemoryRegion *fmc0_mmio = &s->fmc.flashes[0].mmio;
@@ -537,9 +553,9 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->spi[i]), 0,
sc->memmap[ASPEED_DEV_SPI1 + i]);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 1,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->spi[i]), 1,
ASPEED_SMC_GET_CLASS(&s->spi[i])->flash_window_base);
}
@@ -548,17 +564,18 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->ehci[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->ehci[i]), 0,
sc->memmap[ASPEED_DEV_EHCI1 + i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_EHCI1 + i));
+ aspeed_soc_ast2600_get_irq(s,
+ ASPEED_DEV_EHCI1 + i));
}
/* SDMC - SDRAM Memory Controller */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdmc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sdmc), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sdmc), 0,
sc->memmap[ASPEED_DEV_SDMC]);
/* Watch dog */
@@ -571,7 +588,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
}
/* RAM */
@@ -586,10 +603,10 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->ftgmac100[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
sc->memmap[ASPEED_DEV_ETH1 + i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_ETH1 + i));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_ETH1 + i));
object_property_set_link(OBJECT(&s->mii[i]), "nic",
OBJECT(&s->ftgmac100[i]), &error_abort);
@@ -597,7 +614,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->mii[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->mii[i]), 0,
sc->memmap[ASPEED_DEV_MII1 + i]);
}
@@ -605,55 +622,56 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->xdma), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->xdma), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->xdma), 0,
sc->memmap[ASPEED_DEV_XDMA]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_XDMA));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_XDMA));
/* GPIO */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->gpio), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->gpio), 0,
sc->memmap[ASPEED_DEV_GPIO]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_GPIO));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_GPIO));
if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio_1_8v), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->gpio_1_8v), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->gpio_1_8v), 0,
sc->memmap[ASPEED_DEV_GPIO_1_8V]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio_1_8v), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_GPIO_1_8V));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_GPIO_1_8V));
/* SDHCI */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sdhci), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sdhci), 0,
sc->memmap[ASPEED_DEV_SDHCI]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_SDHCI));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_SDHCI));
/* eMMC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->emmc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->emmc), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->emmc), 0,
sc->memmap[ASPEED_DEV_EMMC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_EMMC));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_EMMC));
/* LPC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->lpc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->lpc), 0, sc->memmap[ASPEED_DEV_LPC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->lpc), 0,
+ sc->memmap[ASPEED_DEV_LPC]);
/* Connect the LPC IRQ to the GIC. It is otherwise unused. */
sysbus_connect_irq(SYS_BUS_DEVICE(&s->lpc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_LPC));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_LPC));
/*
* On the AST2600 LPC subdevice IRQs are connected straight to the GIC.
@@ -685,16 +703,17 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->hace), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->hace), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->hace), 0,
sc->memmap[ASPEED_DEV_HACE]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_HACE));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_HACE));
/* I3C */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->i3c), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->i3c), 0, sc->memmap[ASPEED_DEV_I3C]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->i3c), 0,
+ sc->memmap[ASPEED_DEV_I3C]);
for (i = 0; i < ASPEED_I3C_NR_DEVICES; i++) {
irq = qdev_get_gpio_in(DEVICE(&a->a7mpcore),
sc->irqmap[ASPEED_DEV_I3C] + i);
@@ -706,17 +725,18 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sbc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sbc), 0, sc->memmap[ASPEED_DEV_SBC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sbc), 0,
+ sc->memmap[ASPEED_DEV_SBC]);
/* FSI */
for (i = 0; i < ASPEED_FSI_NUM; i++) {
if (!sysbus_realize(SYS_BUS_DEVICE(&s->fsi[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fsi[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->fsi[i]), 0,
sc->memmap[ASPEED_DEV_FSI1 + i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fsi[i]), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_FSI1 + i));
+ aspeed_soc_ast2600_get_irq(s, ASPEED_DEV_FSI1 + i));
}
}
@@ -752,7 +772,6 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, const void *data)
sc->irqmap = aspeed_soc_ast2600_irqmap;
sc->memmap = aspeed_soc_ast2600_memmap;
sc->num_cpus = 2;
- sc->get_irq = aspeed_soc_ast2600_get_irq;
sc->boot_from_emmc = aspeed_soc_ast2600_boot_from_emmc;
}
diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c
index 2e16a03..a61ecff 100644
--- a/hw/arm/aspeed_ast27x0-fc.c
+++ b/hw/arm/aspeed_ast27x0-fc.c
@@ -21,7 +21,7 @@
#include "hw/loader.h"
#include "hw/arm/boot.h"
#include "hw/block/flash.h"
-
+#include "hw/arm/aspeed_coprocessor.h"
#define TYPE_AST2700A1FC MACHINE_TYPE_NAME("ast2700fc")
OBJECT_DECLARE_SIMPLE_TYPE(Ast2700FCState, AST2700A1FC);
@@ -42,8 +42,8 @@ struct Ast2700FCState {
Clock *tsp_sysclk;
Aspeed27x0SoCState ca35;
- Aspeed27x0SSPSoCState ssp;
- Aspeed27x0TSPSoCState tsp;
+ Aspeed27x0CoprocessorState ssp;
+ Aspeed27x0CoprocessorState tsp;
bool mmio_exec;
};
@@ -91,7 +91,8 @@ static bool ast2700fc_ca35_init(MachineState *machine, Error **errp)
AST2700FC_HW_STRAP1, &error_abort);
object_property_set_int(OBJECT(&s->ca35), "hw-strap2",
AST2700FC_HW_STRAP2, &error_abort);
- aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART12, serial_hd(0));
+ aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART12, sc->uarts_base,
+ sc->uarts_num, serial_hd(0));
if (!qdev_realize(DEVICE(&s->ca35), NULL, errp)) {
return false;
}
@@ -114,12 +115,14 @@ static bool ast2700fc_ca35_init(MachineState *machine, Error **errp)
static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
{
- AspeedSoCState *soc;
+ AspeedCoprocessorState *soc;
+ AspeedCoprocessorClass *sc;
Ast2700FCState *s = AST2700A1FC(machine);
s->ssp_sysclk = clock_new(OBJECT(s), "SSP_SYSCLK");
clock_set_hz(s->ssp_sysclk, 200000000ULL);
- object_initialize_child(OBJECT(s), "ssp", &s->ssp, TYPE_ASPEED27X0SSP_SOC);
+ object_initialize_child(OBJECT(s), "ssp", &s->ssp,
+ TYPE_ASPEED27X0SSP_COPROCESSOR);
memory_region_init(&s->ssp_memory, OBJECT(&s->ssp), "ssp-memory",
UINT64_MAX);
@@ -127,8 +130,10 @@ static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
object_property_set_link(OBJECT(&s->ssp), "memory",
OBJECT(&s->ssp_memory), &error_abort);
- soc = ASPEED_SOC(&s->ssp);
- aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART4, serial_hd(1));
+ soc = ASPEED_COPROCESSOR(&s->ssp);
+ sc = ASPEED_COPROCESSOR_GET_CLASS(soc);
+ aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART4, sc->uarts_base,
+ sc->uarts_num, serial_hd(1));
if (!qdev_realize(DEVICE(&s->ssp), NULL, errp)) {
return false;
}
@@ -138,12 +143,14 @@ static bool ast2700fc_ssp_init(MachineState *machine, Error **errp)
static bool ast2700fc_tsp_init(MachineState *machine, Error **errp)
{
- AspeedSoCState *soc;
+ AspeedCoprocessorState *soc;
+ AspeedCoprocessorClass *sc;
Ast2700FCState *s = AST2700A1FC(machine);
s->tsp_sysclk = clock_new(OBJECT(s), "TSP_SYSCLK");
clock_set_hz(s->tsp_sysclk, 200000000ULL);
- object_initialize_child(OBJECT(s), "tsp", &s->tsp, TYPE_ASPEED27X0TSP_SOC);
+ object_initialize_child(OBJECT(s), "tsp", &s->tsp,
+ TYPE_ASPEED27X0TSP_COPROCESSOR);
memory_region_init(&s->tsp_memory, OBJECT(&s->tsp), "tsp-memory",
UINT64_MAX);
@@ -151,8 +158,10 @@ static bool ast2700fc_tsp_init(MachineState *machine, Error **errp)
object_property_set_link(OBJECT(&s->tsp), "memory",
OBJECT(&s->tsp_memory), &error_abort);
- soc = ASPEED_SOC(&s->tsp);
- aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART7, serial_hd(2));
+ soc = ASPEED_COPROCESSOR(&s->tsp);
+ sc = ASPEED_COPROCESSOR_GET_CLASS(soc);
+ aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART7, sc->uarts_base,
+ sc->uarts_num, serial_hd(2));
if (!qdev_realize(DEVICE(&s->tsp), NULL, errp)) {
return false;
}
diff --git a/hw/arm/aspeed_ast27x0-ssp.c b/hw/arm/aspeed_ast27x0-ssp.c
index 80ec599..936c7c7 100644
--- a/hw/arm/aspeed_ast27x0-ssp.c
+++ b/hw/arm/aspeed_ast27x0-ssp.c
@@ -1,5 +1,5 @@
/*
- * ASPEED Ast27x0 SSP SoC
+ * ASPEED Ast27x0 SSP Coprocessor
*
* Copyright (C) 2025 ASPEED Technology Inc.
*
@@ -14,6 +14,7 @@
#include "hw/qdev-clock.h"
#include "hw/misc/unimp.h"
#include "hw/arm/aspeed_soc.h"
+#include "hw/arm/aspeed_coprocessor.h"
#define AST2700_SSP_RAM_SIZE (32 * MiB)
@@ -104,10 +105,11 @@ static struct nvic_intc_irq_info ast2700_ssp_intcmap[] = {
{136, 0, 9, NULL},
};
-static qemu_irq aspeed_soc_ast27x0ssp_get_irq(AspeedSoCState *s, int dev)
+static qemu_irq aspeed_soc_ast27x0ssp_get_irq(AspeedCoprocessorState *s,
+ int dev)
{
- Aspeed27x0SSPSoCState *a = ASPEED27X0SSP_SOC(s);
- AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+ Aspeed27x0CoprocessorState *a = ASPEED27X0SSP_COPROCESSOR(s);
+ AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
int or_idx;
int idx;
@@ -128,9 +130,9 @@ static qemu_irq aspeed_soc_ast27x0ssp_get_irq(AspeedSoCState *s, int dev)
static void aspeed_soc_ast27x0ssp_init(Object *obj)
{
- Aspeed27x0SSPSoCState *a = ASPEED27X0SSP_SOC(obj);
- AspeedSoCState *s = ASPEED_SOC(obj);
- AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+ Aspeed27x0CoprocessorState *a = ASPEED27X0SSP_COPROCESSOR(obj);
+ AspeedCoprocessorState *s = ASPEED_COPROCESSOR(obj);
+ AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
int i;
object_initialize_child(obj, "armv7m", &a->armv7m, TYPE_ARMV7M);
@@ -159,11 +161,12 @@ static void aspeed_soc_ast27x0ssp_init(Object *obj)
static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
{
- Aspeed27x0SSPSoCState *a = ASPEED27X0SSP_SOC(dev_soc);
- AspeedSoCState *s = ASPEED_SOC(dev_soc);
- AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+ Aspeed27x0CoprocessorState *a = ASPEED27X0SSP_COPROCESSOR(dev_soc);
+ AspeedCoprocessorState *s = ASPEED_COPROCESSOR(dev_soc);
+ AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
DeviceState *armv7m;
g_autofree char *sram_name = NULL;
+ int uart;
int i;
if (!clock_has_source(s->sysclk)) {
@@ -174,7 +177,8 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
/* AST27X0 SSP Core */
armv7m = DEVICE(&a->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 256);
- qdev_prop_set_string(armv7m, "cpu-type", aspeed_soc_cpu_type(sc));
+ qdev_prop_set_string(armv7m, "cpu-type",
+ aspeed_soc_cpu_type(sc->valid_cpu_types));
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
object_property_set_link(OBJECT(&a->armv7m), "memory",
OBJECT(s->memory), &error_abort);
@@ -183,8 +187,8 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
sram_name = g_strdup_printf("aspeed.dram.%d",
CPU(a->armv7m.cpu)->cpu_index);
- if (!memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size,
- errp)) {
+ if (!memory_region_init_ram(&s->sram, OBJECT(s), sram_name,
+ AST2700_SSP_RAM_SIZE, errp)) {
return;
}
memory_region_add_subregion(s->memory,
@@ -195,14 +199,15 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
+ sc->memmap[ASPEED_DEV_SCU]);
/* INTC */
if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[0]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[0]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intc[0]), 0,
sc->memmap[ASPEED_DEV_INTC]);
/* INTCIO */
@@ -210,7 +215,7 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[1]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intc[1]), 0,
sc->memmap[ASPEED_DEV_INTCIO]);
/* irq source orgates -> INTC0 */
@@ -235,57 +240,56 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp)
qdev_get_gpio_in(DEVICE(&a->intc[0].orgates[0]), i));
}
/* UART */
- if (!aspeed_soc_uart_realize(s, errp)) {
- return;
+ for (i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
+ if (!aspeed_soc_uart_realize(s->memory, &s->uart[i],
+ sc->memmap[uart], errp)) {
+ return;
+ }
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+ aspeed_soc_ast27x0ssp_get_irq(s, uart));
}
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->timerctrl),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->timerctrl),
"aspeed.timerctrl",
sc->memmap[ASPEED_DEV_TIMER1], 0x200);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&a->ipc[0]),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->ipc[0]),
"aspeed.ipc0",
sc->memmap[ASPEED_DEV_IPC0], 0x1000);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&a->ipc[1]),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->ipc[1]),
"aspeed.ipc1",
sc->memmap[ASPEED_DEV_IPC1], 0x1000);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&a->scuio),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->scuio),
"aspeed.scuio",
sc->memmap[ASPEED_DEV_SCUIO], 0x1000);
}
-static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass, const void *data)
+static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass,
+ const void *data)
{
static const char * const valid_cpu_types[] = {
ARM_CPU_TYPE_NAME("cortex-m4"), /* TODO: cortex-m4f */
NULL
};
DeviceClass *dc = DEVICE_CLASS(klass);
- AspeedSoCClass *sc = ASPEED_SOC_CLASS(dc);
+ AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_CLASS(dc);
- /* Reason: The Aspeed SoC can only be instantiated from a board */
+ /* Reason: The Aspeed Coprocessor can only be instantiated from a board */
dc->user_creatable = false;
dc->realize = aspeed_soc_ast27x0ssp_realize;
sc->valid_cpu_types = valid_cpu_types;
sc->silicon_rev = AST2700_A1_SILICON_REV;
- sc->sram_size = AST2700_SSP_RAM_SIZE;
- sc->spis_num = 0;
- sc->ehcis_num = 0;
- sc->wdts_num = 0;
- sc->macs_num = 0;
sc->uarts_num = 13;
sc->uarts_base = ASPEED_DEV_UART0;
sc->irqmap = aspeed_soc_ast27x0ssp_irqmap;
sc->memmap = aspeed_soc_ast27x0ssp_memmap;
- sc->num_cpus = 1;
- sc->get_irq = aspeed_soc_ast27x0ssp_get_irq;
}
static const TypeInfo aspeed_soc_ast27x0ssp_types[] = {
{
- .name = TYPE_ASPEED27X0SSP_SOC,
- .parent = TYPE_ASPEED_SOC,
- .instance_size = sizeof(Aspeed27x0SSPSoCState),
+ .name = TYPE_ASPEED27X0SSP_COPROCESSOR,
+ .parent = TYPE_ASPEED_COPROCESSOR,
+ .instance_size = sizeof(Aspeed27x0CoprocessorState),
.instance_init = aspeed_soc_ast27x0ssp_init,
.class_init = aspeed_soc_ast27x0ssp_class_init,
},
diff --git a/hw/arm/aspeed_ast27x0-tsp.c b/hw/arm/aspeed_ast27x0-tsp.c
index 4e0efae..9318f8c 100644
--- a/hw/arm/aspeed_ast27x0-tsp.c
+++ b/hw/arm/aspeed_ast27x0-tsp.c
@@ -1,5 +1,5 @@
/*
- * ASPEED Ast27x0 TSP SoC
+ * ASPEED Ast27x0 TSP Coprocessor
*
* Copyright (C) 2025 ASPEED Technology Inc.
*
@@ -14,6 +14,7 @@
#include "hw/qdev-clock.h"
#include "hw/misc/unimp.h"
#include "hw/arm/aspeed_soc.h"
+#include "hw/arm/aspeed_coprocessor.h"
#define AST2700_TSP_RAM_SIZE (32 * MiB)
@@ -104,10 +105,11 @@ static struct nvic_intc_irq_info ast2700_tsp_intcmap[] = {
{136, 0, 9, NULL},
};
-static qemu_irq aspeed_soc_ast27x0tsp_get_irq(AspeedSoCState *s, int dev)
+static qemu_irq aspeed_soc_ast27x0tsp_get_irq(AspeedCoprocessorState *s,
+ int dev)
{
- Aspeed27x0TSPSoCState *a = ASPEED27X0TSP_SOC(s);
- AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+ Aspeed27x0CoprocessorState *a = ASPEED27X0TSP_COPROCESSOR(s);
+ AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
int or_idx;
int idx;
@@ -128,9 +130,9 @@ static qemu_irq aspeed_soc_ast27x0tsp_get_irq(AspeedSoCState *s, int dev)
static void aspeed_soc_ast27x0tsp_init(Object *obj)
{
- Aspeed27x0TSPSoCState *a = ASPEED27X0TSP_SOC(obj);
- AspeedSoCState *s = ASPEED_SOC(obj);
- AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+ Aspeed27x0CoprocessorState *a = ASPEED27X0TSP_COPROCESSOR(obj);
+ AspeedCoprocessorState *s = ASPEED_COPROCESSOR(obj);
+ AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
int i;
object_initialize_child(obj, "armv7m", &a->armv7m, TYPE_ARMV7M);
@@ -159,11 +161,12 @@ static void aspeed_soc_ast27x0tsp_init(Object *obj)
static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
{
- Aspeed27x0TSPSoCState *a = ASPEED27X0TSP_SOC(dev_soc);
- AspeedSoCState *s = ASPEED_SOC(dev_soc);
- AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+ Aspeed27x0CoprocessorState *a = ASPEED27X0TSP_COPROCESSOR(dev_soc);
+ AspeedCoprocessorState *s = ASPEED_COPROCESSOR(dev_soc);
+ AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_GET_CLASS(s);
DeviceState *armv7m;
g_autofree char *sram_name = NULL;
+ int uart;
int i;
if (!clock_has_source(s->sysclk)) {
@@ -174,7 +177,8 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
/* AST27X0 TSP Core */
armv7m = DEVICE(&a->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 256);
- qdev_prop_set_string(armv7m, "cpu-type", aspeed_soc_cpu_type(sc));
+ qdev_prop_set_string(armv7m, "cpu-type",
+ aspeed_soc_cpu_type(sc->valid_cpu_types));
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
object_property_set_link(OBJECT(&a->armv7m), "memory",
OBJECT(s->memory), &error_abort);
@@ -183,8 +187,8 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
sram_name = g_strdup_printf("aspeed.dram.%d",
CPU(a->armv7m.cpu)->cpu_index);
- if (!memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size,
- errp)) {
+ if (!memory_region_init_ram(&s->sram, OBJECT(s), sram_name,
+ AST2700_TSP_RAM_SIZE, errp)) {
return;
}
memory_region_add_subregion(s->memory,
@@ -195,14 +199,15 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
+ sc->memmap[ASPEED_DEV_SCU]);
/* INTC */
if (!sysbus_realize(SYS_BUS_DEVICE(&a->intc[0]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[0]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intc[0]), 0,
sc->memmap[ASPEED_DEV_INTC]);
/* INTCIO */
@@ -210,7 +215,7 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[1]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intc[1]), 0,
sc->memmap[ASPEED_DEV_INTCIO]);
/* irq source orgates -> INTC */
@@ -235,57 +240,56 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp)
qdev_get_gpio_in(DEVICE(&a->intc[0].orgates[0]), i));
}
/* UART */
- if (!aspeed_soc_uart_realize(s, errp)) {
- return;
+ for (i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
+ if (!aspeed_soc_uart_realize(s->memory, &s->uart[i],
+ sc->memmap[uart], errp)) {
+ return;
+ }
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+ aspeed_soc_ast27x0tsp_get_irq(s, uart));
}
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->timerctrl),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->timerctrl),
"aspeed.timerctrl",
sc->memmap[ASPEED_DEV_TIMER1], 0x200);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&a->ipc[0]),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->ipc[0]),
"aspeed.ipc0",
sc->memmap[ASPEED_DEV_IPC0], 0x1000);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&a->ipc[1]),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->ipc[1]),
"aspeed.ipc1",
sc->memmap[ASPEED_DEV_IPC1], 0x1000);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&a->scuio),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->scuio),
"aspeed.scuio",
sc->memmap[ASPEED_DEV_SCUIO], 0x1000);
}
-static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass, const void *data)
+static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass,
+ const void *data)
{
static const char * const valid_cpu_types[] = {
ARM_CPU_TYPE_NAME("cortex-m4"), /* TODO cortex-m4f */
NULL
};
DeviceClass *dc = DEVICE_CLASS(klass);
- AspeedSoCClass *sc = ASPEED_SOC_CLASS(dc);
+ AspeedCoprocessorClass *sc = ASPEED_COPROCESSOR_CLASS(dc);
- /* Reason: The Aspeed SoC can only be instantiated from a board */
+ /* Reason: The Aspeed Coprocessor can only be instantiated from a board */
dc->user_creatable = false;
dc->realize = aspeed_soc_ast27x0tsp_realize;
sc->valid_cpu_types = valid_cpu_types;
sc->silicon_rev = AST2700_A1_SILICON_REV;
- sc->sram_size = AST2700_TSP_RAM_SIZE;
- sc->spis_num = 0;
- sc->ehcis_num = 0;
- sc->wdts_num = 0;
- sc->macs_num = 0;
sc->uarts_num = 13;
sc->uarts_base = ASPEED_DEV_UART0;
sc->irqmap = aspeed_soc_ast27x0tsp_irqmap;
sc->memmap = aspeed_soc_ast27x0tsp_memmap;
- sc->num_cpus = 1;
- sc->get_irq = aspeed_soc_ast27x0tsp_get_irq;
}
static const TypeInfo aspeed_soc_ast27x0tsp_types[] = {
{
- .name = TYPE_ASPEED27X0TSP_SOC,
- .parent = TYPE_ASPEED_SOC,
- .instance_size = sizeof(Aspeed27x0TSPSoCState),
+ .name = TYPE_ASPEED27X0TSP_COPROCESSOR,
+ .parent = TYPE_ASPEED_COPROCESSOR,
+ .instance_size = sizeof(Aspeed27x0CoprocessorState),
.instance_init = aspeed_soc_ast27x0tsp_init,
.class_init = aspeed_soc_ast27x0tsp_class_init,
},
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index 8533391..c484bcd 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -436,7 +436,7 @@ static void aspeed_soc_ast2700_init(Object *obj)
for (i = 0; i < sc->num_cpus; i++) {
object_initialize_child(obj, "cpu[*]", &a->cpu[i],
- aspeed_soc_cpu_type(sc));
+ aspeed_soc_cpu_type(sc->valid_cpu_types));
}
object_initialize_child(obj, "gic", &a->gic, gicv3_class_name());
@@ -589,9 +589,9 @@ static bool aspeed_soc_ast2700_gic_realize(DeviceState *dev, Error **errp)
return false;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->gic), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->gic), 0,
sc->memmap[ASPEED_GIC_DIST]);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->gic), 1,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->gic), 1,
sc->memmap[ASPEED_GIC_REDIST]);
for (i = 0; i < sc->num_cpus; i++) {
@@ -647,7 +647,7 @@ static bool aspeed_soc_ast2700_pcie_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy[i]), errp)) {
return false;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->pcie_phy[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->pcie_phy[i]), 0,
sc->memmap[ASPEED_DEV_PCIE_PHY0 + i]);
object_property_set_int(OBJECT(&s->pcie[i]), "dram-base",
@@ -658,9 +658,9 @@ static bool aspeed_soc_ast2700_pcie_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie[i]), errp)) {
return false;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->pcie[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->pcie[i]), 0,
sc->memmap[ASPEED_DEV_PCIE0 + i]);
- irq = aspeed_soc_get_irq(s, ASPEED_DEV_PCIE0 + i);
+ irq = aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_PCIE0 + i);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie[i].rc), 0, irq);
mmio_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pcie[i].rc), 1);
@@ -687,6 +687,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
AspeedINTCClass *icio = ASPEED_INTC_GET_CLASS(&a->intc[1]);
g_autofree char *name = NULL;
qemu_irq irq;
+ int uart;
/* Default boot region (SPI memory or ROMs) */
memory_region_init(&s->spi_boot_container, OBJECT(s),
@@ -719,7 +720,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[0]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intc[0]), 0,
sc->memmap[ASPEED_DEV_INTC]);
/* INTCIO */
@@ -727,7 +728,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&a->intc[1]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intc[1]), 0,
sc->memmap[ASPEED_DEV_INTCIO]);
/* irq sources -> orgates -> INTC */
@@ -777,18 +778,24 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scu), 0,
+ sc->memmap[ASPEED_DEV_SCU]);
/* SCU1 */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scuio), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->scuio), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->scuio), 0,
sc->memmap[ASPEED_DEV_SCUIO]);
/* UART */
- if (!aspeed_soc_uart_realize(s, errp)) {
- return;
+ for (i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
+ if (!aspeed_soc_uart_realize(s->memory, &s->uart[i],
+ sc->memmap[uart], errp)) {
+ return;
+ }
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+ aspeed_soc_ast2700_get_irq(s, uart));
}
/* FMC, The number of CS is set at the board level */
@@ -800,11 +807,12 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_DEV_FMC]);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fmc), 1,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->fmc), 0,
+ sc->memmap[ASPEED_DEV_FMC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->fmc), 1,
ASPEED_SMC_GET_CLASS(&s->fmc)->flash_window_base);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
+ aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_FMC));
/* Set up an alias on the FMC CE0 region (boot default) */
MemoryRegion *fmc0_mmio = &s->fmc.flashes[0].mmio;
@@ -819,9 +827,9 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->spi[i]), 0,
sc->memmap[ASPEED_DEV_SPI0 + i]);
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->spi[i]), 1,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->spi[i]), 1,
ASPEED_SMC_GET_CLASS(&s->spi[i])->flash_window_base);
}
@@ -830,10 +838,11 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->ehci[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->ehci[i]), 0,
sc->memmap[ASPEED_DEV_EHCI1 + i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_EHCI1 + i));
+ aspeed_soc_ast2700_get_irq(s,
+ ASPEED_DEV_EHCI1 + i));
}
/*
@@ -848,7 +857,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdmc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sdmc), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sdmc), 0,
sc->memmap[ASPEED_DEV_SDMC]);
/* RAM */
@@ -865,10 +874,10 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->ftgmac100[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
sc->memmap[ASPEED_DEV_ETH1 + i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_ETH1 + i));
+ aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_ETH1 + i));
object_property_set_link(OBJECT(&s->mii[i]), "nic",
OBJECT(&s->ftgmac100[i]), &error_abort);
@@ -876,7 +885,7 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->mii[i]), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->mii[i]), 0,
sc->memmap[ASPEED_DEV_MII1 + i]);
}
@@ -890,28 +899,30 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->wdt[i]), 0, wdt_offset);
}
/* SLI */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sli), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sli), 0, sc->memmap[ASPEED_DEV_SLI]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sli), 0,
+ sc->memmap[ASPEED_DEV_SLI]);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sliio), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sliio), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sliio), 0,
sc->memmap[ASPEED_DEV_SLIIO]);
/* ADC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->adc), 0, sc->memmap[ASPEED_DEV_ADC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->adc), 0,
+ sc->memmap[ASPEED_DEV_ADC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
+ aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_ADC));
/* I2C */
object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr),
@@ -919,7 +930,8 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->i2c), 0,
+ sc->memmap[ASPEED_DEV_I2C]);
for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) {
/*
* The AST2700 I2C controller has one source INTC per bus.
@@ -948,36 +960,37 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->gpio), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->gpio), 0,
sc->memmap[ASPEED_DEV_GPIO]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_GPIO));
+ aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_GPIO));
/* RTC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->rtc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->rtc), 0, sc->memmap[ASPEED_DEV_RTC]);
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->rtc), 0,
+ sc->memmap[ASPEED_DEV_RTC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_RTC));
+ aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_RTC));
/* SDHCI */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sdhci), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->sdhci), 0,
sc->memmap[ASPEED_DEV_SDHCI]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_SDHCI));
+ aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_SDHCI));
/* eMMC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->emmc), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->emmc), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->emmc), 0,
sc->memmap[ASPEED_DEV_EMMC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_EMMC));
+ aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_EMMC));
/* Timer */
object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu),
@@ -985,10 +998,10 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timerctrl), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->timerctrl), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->timerctrl), 0,
sc->memmap[ASPEED_DEV_TIMER1]);
for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
- irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i);
+ irq = aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_TIMER1 + i);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
}
@@ -998,33 +1011,33 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(&s->hace), errp)) {
return;
}
- aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->hace), 0,
+ aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&s->hace), 0,
sc->memmap[ASPEED_DEV_HACE]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0,
- aspeed_soc_get_irq(s, ASPEED_DEV_HACE));
+ aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_HACE));
/* PCIe Root Complex (RC) */
if (!aspeed_soc_ast2700_pcie_realize(dev, errp)) {
return;
}
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->dpmcu),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->dpmcu),
"aspeed.dpmcu",
sc->memmap[ASPEED_DEV_DPMCU],
AST2700_SOC_DPMCU_SIZE);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->ltpi),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->ltpi),
"aspeed.ltpi",
sc->memmap[ASPEED_DEV_LTPI],
AST2700_SOC_LTPI_SIZE);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->iomem),
"aspeed.io",
sc->memmap[ASPEED_DEV_IOMEM],
AST2700_SOC_IO_SIZE);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem0),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->iomem0),
"aspeed.iomem0",
sc->memmap[ASPEED_DEV_IOMEM0],
AST2700_SOC_IOMEM_SIZE);
- aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem1),
+ aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->iomem1),
"aspeed.iomem1",
sc->memmap[ASPEED_DEV_IOMEM1],
AST2700_SOC_IOMEM_SIZE);
@@ -1056,7 +1069,6 @@ static void aspeed_soc_ast2700a0_class_init(ObjectClass *oc, const void *data)
sc->uarts_base = ASPEED_DEV_UART0;
sc->irqmap = aspeed_soc_ast2700a0_irqmap;
sc->memmap = aspeed_soc_ast2700_memmap;
- sc->get_irq = aspeed_soc_ast2700_get_irq;
}
static void aspeed_soc_ast2700a1_class_init(ObjectClass *oc, const void *data)
@@ -1085,7 +1097,6 @@ static void aspeed_soc_ast2700a1_class_init(ObjectClass *oc, const void *data)
sc->uarts_base = ASPEED_DEV_UART0;
sc->irqmap = aspeed_soc_ast2700a1_irqmap;
sc->memmap = aspeed_soc_ast2700_memmap;
- sc->get_irq = aspeed_soc_ast2700_get_irq;
}
static const TypeInfo aspeed_soc_ast27x0_types[] = {
diff --git a/hw/arm/aspeed_coprocessor_common.c b/hw/arm/aspeed_coprocessor_common.c
new file mode 100644
index 0000000..8a94b44
--- /dev/null
+++ b/hw/arm/aspeed_coprocessor_common.c
@@ -0,0 +1,49 @@
+/*
+ * ASPEED Coprocessor
+ *
+ * Copyright (C) 2025 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "system/memory.h"
+#include "hw/qdev-properties.h"
+#include "hw/arm/aspeed_coprocessor.h"
+
+static void aspeed_coprocessor_realize(DeviceState *dev, Error **errp)
+{
+ AspeedCoprocessorState *s = ASPEED_COPROCESSOR(dev);
+
+ if (!s->memory) {
+ error_setg(errp, "'memory' link is not set");
+ return;
+ }
+}
+
+static const Property aspeed_coprocessor_properties[] = {
+ DEFINE_PROP_LINK("memory", AspeedCoprocessorState, memory,
+ TYPE_MEMORY_REGION, MemoryRegion *),
+};
+
+static void aspeed_coprocessor_class_init(ObjectClass *oc, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = aspeed_coprocessor_realize;
+ device_class_set_props(dc, aspeed_coprocessor_properties);
+}
+
+static const TypeInfo aspeed_coprocessor_types[] = {
+ {
+ .name = TYPE_ASPEED_COPROCESSOR,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(AspeedCoprocessorState),
+ .class_size = sizeof(AspeedCoprocessorClass),
+ .class_init = aspeed_coprocessor_class_init,
+ .abstract = true,
+ },
+};
+
+DEFINE_TYPES(aspeed_coprocessor_types)
diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c
index bc70e86..78b6ae1 100644
--- a/hw/arm/aspeed_soc_common.c
+++ b/hw/arm/aspeed_soc_common.c
@@ -22,52 +22,39 @@
#include "qemu/datadir.h"
-const char *aspeed_soc_cpu_type(AspeedSoCClass *sc)
+const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types)
{
- assert(sc->valid_cpu_types);
- assert(sc->valid_cpu_types[0]);
- assert(!sc->valid_cpu_types[1]);
- return sc->valid_cpu_types[0];
+ assert(valid_cpu_types);
+ assert(valid_cpu_types[0]);
+ assert(!valid_cpu_types[1]);
+ return valid_cpu_types[0];
}
-qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev)
+bool aspeed_soc_uart_realize(MemoryRegion *memory, SerialMM *smm,
+ const hwaddr addr, Error **errp)
{
- return ASPEED_SOC_GET_CLASS(s)->get_irq(s, dev);
-}
-
-bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp)
-{
- AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
- SerialMM *smm;
-
- for (int i = 0, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) {
- smm = &s->uart[i];
-
- /* Chardev property is set by the machine. */
- qdev_prop_set_uint8(DEVICE(smm), "regshift", 2);
- qdev_prop_set_uint32(DEVICE(smm), "baudbase", 38400);
- qdev_set_legacy_instance_id(DEVICE(smm), sc->memmap[uart], 2);
- qdev_prop_set_uint8(DEVICE(smm), "endianness", DEVICE_LITTLE_ENDIAN);
- if (!sysbus_realize(SYS_BUS_DEVICE(smm), errp)) {
- return false;
- }
-
- sysbus_connect_irq(SYS_BUS_DEVICE(smm), 0, aspeed_soc_get_irq(s, uart));
- aspeed_mmio_map(s, SYS_BUS_DEVICE(smm), 0, sc->memmap[uart]);
+ /* Chardev property is set by the machine. */
+ qdev_prop_set_uint8(DEVICE(smm), "regshift", 2);
+ qdev_prop_set_uint32(DEVICE(smm), "baudbase", 38400);
+ qdev_set_legacy_instance_id(DEVICE(smm), addr, 2);
+ qdev_prop_set_uint8(DEVICE(smm), "endianness", DEVICE_LITTLE_ENDIAN);
+ if (!sysbus_realize(SYS_BUS_DEVICE(smm), errp)) {
+ return false;
}
+ aspeed_mmio_map(memory, SYS_BUS_DEVICE(smm), 0, addr);
return true;
}
-void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr)
+void aspeed_soc_uart_set_chr(SerialMM *uart, int dev, int uarts_base,
+ int uarts_num, Chardev *chr)
{
- AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
- int uart_first = aspeed_uart_first(sc);
+ int uart_first = aspeed_uart_first(uarts_base);
int uart_index = aspeed_uart_index(dev);
int i = uart_index - uart_first;
- g_assert(0 <= i && i < ARRAY_SIZE(s->uart) && i < sc->uarts_num);
- qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
+ g_assert(0 <= i && i < ASPEED_UARTS_NUM && i < uarts_num);
+ qdev_prop_set_chr(DEVICE(&uart[i]), "chardev", chr);
}
/*
@@ -111,20 +98,20 @@ bool aspeed_soc_dram_init(AspeedSoCState *s, Error **errp)
return true;
}
-void aspeed_mmio_map(AspeedSoCState *s, SysBusDevice *dev, int n, hwaddr addr)
+void aspeed_mmio_map(MemoryRegion *memory, SysBusDevice *dev, int n,
+ hwaddr addr)
{
- memory_region_add_subregion(s->memory, addr,
- sysbus_mmio_get_region(dev, n));
+ memory_region_add_subregion(memory, addr, sysbus_mmio_get_region(dev, n));
}
-void aspeed_mmio_map_unimplemented(AspeedSoCState *s, SysBusDevice *dev,
+void aspeed_mmio_map_unimplemented(MemoryRegion *memory, SysBusDevice *dev,
const char *name, hwaddr addr, uint64_t size)
{
qdev_prop_set_string(DEVICE(dev), "name", name);
qdev_prop_set_uint64(DEVICE(dev), "size", size);
sysbus_realize(dev, &error_abort);
- memory_region_add_subregion_overlap(s->memory, addr,
+ memory_region_add_subregion_overlap(memory, addr,
sysbus_mmio_get_region(dev, 0), -1000);
}
diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c
index c14fc2e..5a94c84 100644
--- a/hw/arm/fby35.c
+++ b/hw/arm/fby35.c
@@ -71,9 +71,11 @@ static void fby35_bmc_write_boot_rom(DriveInfo *dinfo, MemoryRegion *mr,
static void fby35_bmc_init(Fby35State *s)
{
AspeedSoCState *soc;
+ AspeedSoCClass *sc;
object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3");
soc = ASPEED_SOC(&s->bmc);
+ sc = ASPEED_SOC_GET_CLASS(soc);
memory_region_init(&s->bmc_memory, OBJECT(&s->bmc), "bmc-memory",
UINT64_MAX);
@@ -91,7 +93,8 @@ static void fby35_bmc_init(Fby35State *s)
&error_abort);
object_property_set_int(OBJECT(&s->bmc), "hw-strap2", 0x00000003,
&error_abort);
- aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART5, serial_hd(0));
+ aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART5, sc->uarts_base,
+ sc->uarts_num, serial_hd(0));
qdev_realize(DEVICE(&s->bmc), NULL, &error_abort);
aspeed_board_init_flashes(&soc->fmc, "n25q00", 2, 0);
@@ -118,12 +121,14 @@ static void fby35_bmc_init(Fby35State *s)
static void fby35_bic_init(Fby35State *s)
{
AspeedSoCState *soc;
+ AspeedSoCClass *sc;
s->bic_sysclk = clock_new(OBJECT(s), "SYSCLK");
clock_set_hz(s->bic_sysclk, 200000000ULL);
object_initialize_child(OBJECT(s), "bic", &s->bic, "ast1030-a1");
soc = ASPEED_SOC(&s->bic);
+ sc = ASPEED_SOC_GET_CLASS(soc);
memory_region_init(&s->bic_memory, OBJECT(&s->bic), "bic-memory",
UINT64_MAX);
@@ -131,7 +136,8 @@ static void fby35_bic_init(Fby35State *s)
qdev_connect_clock_in(DEVICE(&s->bic), "sysclk", s->bic_sysclk);
object_property_set_link(OBJECT(&s->bic), "memory", OBJECT(&s->bic_memory),
&error_abort);
- aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART5, serial_hd(1));
+ aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART5, sc->uarts_base,
+ sc->uarts_num, serial_hd(1));
qdev_realize(DEVICE(&s->bic), NULL, &error_abort);
aspeed_board_init_flashes(&soc->fmc, "sst25vf032b", 2, 2);
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index dc683913..b88b5b0 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -45,14 +45,15 @@ arm_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
'aspeed_soc_common.c',
'aspeed_ast2400.c',
'aspeed_ast2600.c',
- 'aspeed_ast27x0-ssp.c',
- 'aspeed_ast27x0-tsp.c',
'aspeed_ast10x0.c',
'aspeed_eeprom.c',
'fby35.c'))
arm_common_ss.add(when: ['CONFIG_ASPEED_SOC', 'TARGET_AARCH64'], if_true: files(
'aspeed_ast27x0.c',
- 'aspeed_ast27x0-fc.c',))
+ 'aspeed_ast27x0-fc.c',
+ 'aspeed_ast27x0-ssp.c',
+ 'aspeed_ast27x0-tsp.c',
+ 'aspeed_coprocessor_common.c'))
arm_common_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2.c'))
arm_common_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2-tz.c'))
arm_common_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c'))
diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c
index 682ed9f..74a5660 100644
--- a/hw/core/machine-hmp-cmds.c
+++ b/hw/core/machine-hmp-cmds.c
@@ -163,19 +163,22 @@ void hmp_info_kvm(Monitor *mon, const QDict *qdict)
qapi_free_KvmInfo(info);
}
-void hmp_info_mshv(Monitor *mon, const QDict *qdict)
+void hmp_info_accelerators(Monitor *mon, const QDict *qdict)
{
- MshvInfo *info;
-
- info = qmp_query_mshv(NULL);
- monitor_printf(mon, "mshv support: ");
- if (info->present) {
- monitor_printf(mon, "%s\n", info->enabled ? "enabled" : "disabled");
- } else {
- monitor_printf(mon, "not compiled\n");
+ AcceleratorInfo *info;
+ AcceleratorList *accel;
+
+ info = qmp_query_accelerators(NULL);
+ for (accel = info->present; accel; accel = accel->next) {
+ char trail = accel->next ? ' ' : '\n';
+ if (info->enabled == accel->value) {
+ monitor_printf(mon, "[%s]%c", Accelerator_str(accel->value), trail);
+ } else {
+ monitor_printf(mon, "%s%c", Accelerator_str(accel->value), trail);
+ }
}
- qapi_free_MshvInfo(info);
+ qapi_free_AcceleratorInfo(info);
}
void hmp_info_uuid(Monitor *mon, const QDict *qdict)
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index e24bf0d..51d5c23 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -31,15 +31,25 @@
#include <sys/stat.h>
/*
- * QMP query for MSHV
+ * QMP query for enabled and present accelerators
*/
-MshvInfo *qmp_query_mshv(Error **errp)
+AcceleratorInfo *qmp_query_accelerators(Error **errp)
{
- MshvInfo *info = g_malloc0(sizeof(*info));
-
- info->enabled = mshv_enabled();
- info->present = accel_find("mshv");
-
+ AcceleratorInfo *info = g_malloc0(sizeof(*info));
+ AccelClass *current_class = ACCEL_GET_CLASS(current_accel());
+ int i;
+
+ for (i = ACCELERATOR__MAX; i-- > 0; ) {
+ const char *s = Accelerator_str(i);
+ AccelClass *this_class = accel_find(s);
+
+ if (this_class) {
+ QAPI_LIST_PREPEND(info->present, i);
+ if (this_class == current_class) {
+ info->enabled = i;
+ }
+ }
+ }
return info;
}
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 22822fe..164fd0b 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -283,8 +283,7 @@ static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src,
scale = surface_height(surface) - 1;
break;
default:
- scale = 0x8000;
- break;
+ g_assert_not_reached();
}
xenfb->axis[move->axis] = move->value * scale / 0x7fff;
}
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index dacedc5..cddca69 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -36,6 +36,13 @@
#include "net/net.h"
#include "qemu/log.h"
+#define TYPE_HPPA_COMMON_MACHINE MACHINE_TYPE_NAME("hppa-common")
+OBJECT_DECLARE_SIMPLE_TYPE(HppaMachineState, HPPA_COMMON_MACHINE)
+
+struct HppaMachineState {
+ MachineState parent_obj;
+};
+
#define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
@@ -345,16 +352,11 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
TranslateFn *translate)
{
const char *kernel_filename = machine->kernel_filename;
- const char *kernel_cmdline = machine->kernel_cmdline;
- const char *initrd_filename = machine->initrd_filename;
- const char *firmware = machine->firmware;
MachineClass *mc = MACHINE_GET_CLASS(machine);
DeviceState *dev;
PCIDevice *pci_dev;
- char *firmware_filename;
- uint64_t firmware_low, firmware_high;
long size;
- uint64_t kernel_entry = 0, kernel_low, kernel_high;
+ uint64_t kernel_entry = 0;
MemoryRegion *addr_space = get_system_memory();
MemoryRegion *rom_region;
SysBusDevice *s;
@@ -424,6 +426,10 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
firmware on 64-bit machines by default if not specified
on command line. */
if (!qtest_enabled()) {
+ const char *firmware = machine->firmware;
+ uint64_t firmware_low, firmware_high;
+ char *firmware_filename;
+
if (!firmware) {
firmware = lasi_dev ? "hppa-firmware.img" : "hppa-firmware64.img";
}
@@ -460,6 +466,10 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
/* Load kernel */
if (kernel_filename) {
+ const char *kernel_cmdline = machine->kernel_cmdline;
+ const char *initrd_filename = machine->initrd_filename;
+ uint64_t kernel_low, kernel_high;
+
size = load_elf(kernel_filename, NULL, linux_kernel_virt_to_phys,
NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
ELFDATA2MSB, EM_PARISC, 0, 0);
@@ -683,6 +693,22 @@ static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
}
}
+static void hppa_machine_common_class_init(ObjectClass *oc, const void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ NMIClass *nc = NMI_CLASS(oc);
+
+ mc->reset = hppa_machine_reset;
+ mc->block_default_type = IF_SCSI;
+ mc->default_cpus = 1;
+ mc->max_cpus = HPPA_MAX_CPUS;
+ mc->default_boot_order = "cd";
+ mc->default_ram_id = "ram";
+ mc->default_nic = "tulip";
+
+ nc->nmi_monitor_handler = hppa_nmi;
+}
+
static void HP_B160L_machine_init_class_init(ObjectClass *oc, const void *data)
{
static const char * const valid_cpu_types[] = {
@@ -690,35 +716,15 @@ static void HP_B160L_machine_init_class_init(ObjectClass *oc, const void *data)
NULL
};
MachineClass *mc = MACHINE_CLASS(oc);
- NMIClass *nc = NMI_CLASS(oc);
mc->desc = "HP B160L workstation";
mc->default_cpu_type = TYPE_HPPA_CPU;
mc->valid_cpu_types = valid_cpu_types;
mc->init = machine_HP_B160L_init;
- mc->reset = hppa_machine_reset;
- mc->block_default_type = IF_SCSI;
- mc->max_cpus = HPPA_MAX_CPUS;
- mc->default_cpus = 1;
mc->is_default = true;
mc->default_ram_size = 512 * MiB;
- mc->default_boot_order = "cd";
- mc->default_ram_id = "ram";
- mc->default_nic = "tulip";
-
- nc->nmi_monitor_handler = hppa_nmi;
}
-static const TypeInfo HP_B160L_machine_init_typeinfo = {
- .name = MACHINE_TYPE_NAME("B160L"),
- .parent = TYPE_MACHINE,
- .class_init = HP_B160L_machine_init_class_init,
- .interfaces = (const InterfaceInfo[]) {
- { TYPE_NMI },
- { }
- },
-};
-
static void HP_C3700_machine_init_class_init(ObjectClass *oc, const void *data)
{
static const char * const valid_cpu_types[] = {
@@ -726,39 +732,35 @@ static void HP_C3700_machine_init_class_init(ObjectClass *oc, const void *data)
NULL
};
MachineClass *mc = MACHINE_CLASS(oc);
- NMIClass *nc = NMI_CLASS(oc);
mc->desc = "HP C3700 workstation";
mc->default_cpu_type = TYPE_HPPA64_CPU;
mc->valid_cpu_types = valid_cpu_types;
mc->init = machine_HP_C3700_init;
- mc->reset = hppa_machine_reset;
- mc->block_default_type = IF_SCSI;
mc->max_cpus = HPPA_MAX_CPUS;
- mc->default_cpus = 1;
- mc->is_default = false;
mc->default_ram_size = 1024 * MiB;
- mc->default_boot_order = "cd";
- mc->default_ram_id = "ram";
- mc->default_nic = "tulip";
-
- nc->nmi_monitor_handler = hppa_nmi;
}
-static const TypeInfo HP_C3700_machine_init_typeinfo = {
- .name = MACHINE_TYPE_NAME("C3700"),
- .parent = TYPE_MACHINE,
- .class_init = HP_C3700_machine_init_class_init,
- .interfaces = (const InterfaceInfo[]) {
- { TYPE_NMI },
- { }
+static const TypeInfo hppa_machine_types[] = {
+ {
+ .name = TYPE_HPPA_COMMON_MACHINE,
+ .parent = TYPE_MACHINE,
+ .instance_size = sizeof(HppaMachineState),
+ .class_init = hppa_machine_common_class_init,
+ .abstract = true,
+ .interfaces = (const InterfaceInfo[]) {
+ { TYPE_NMI },
+ { }
+ },
+ }, {
+ .name = MACHINE_TYPE_NAME("B160L"),
+ .parent = TYPE_HPPA_COMMON_MACHINE,
+ .class_init = HP_B160L_machine_init_class_init,
+ }, {
+ .name = MACHINE_TYPE_NAME("C3700"),
+ .parent = TYPE_HPPA_COMMON_MACHINE,
+ .class_init = HP_C3700_machine_init_class_init,
},
};
-static void hppa_machine_init_register_types(void)
-{
- type_register_static(&HP_B160L_machine_init_typeinfo);
- type_register_static(&HP_C3700_machine_init_typeinfo);
-}
-
-type_init(hppa_machine_init_register_types)
+DEFINE_TYPES(hppa_machine_types)
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 6d78596..c768033 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -646,8 +646,6 @@ void apic_sipi(DeviceState *dev)
{
APICCommonState *s = APIC(dev);
- cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
-
if (!s->wait_for_sipi)
return;
cpu_x86_load_seg_cache_sipi(s->cpu, s->sipi_vector);
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
index a516415..3dd48cb 100644
--- a/hw/loongarch/boot.c
+++ b/hw/loongarch/boot.c
@@ -306,7 +306,7 @@ static ram_addr_t alloc_initrd_memory(struct loongarch_boot_info *info,
static int64_t load_kernel_info(struct loongarch_boot_info *info)
{
uint64_t kernel_entry, kernel_low, kernel_high, initrd_offset = 0;
- ssize_t kernel_size, initrd_size;
+ ssize_t kernel_size;
kernel_size = load_elf(info->kernel_filename, NULL,
cpu_loongarch_virt_to_phys, NULL,
@@ -328,7 +328,8 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
}
if (info->initrd_filename) {
- initrd_size = get_image_size(info->initrd_filename);
+ ssize_t initrd_size = get_image_size(info->initrd_filename);
+
if (initrd_size > 0) {
initrd_offset = ROUND_UP(kernel_high + 4 * kernel_size, 64 * KiB);
initrd_offset = alloc_initrd_memory(info, initrd_offset,
@@ -337,7 +338,7 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
initrd_offset, initrd_size);
}
- if (initrd_size == (target_ulong)-1) {
+ if (initrd_size == -1) {
error_report("could not load initial ram disk '%s'",
info->initrd_filename);
exit(1);
diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
index 3eb1119..3433486 100644
--- a/hw/net/can/xlnx-versal-canfd.c
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -35,12 +35,8 @@
#include "hw/irq.h"
#include "hw/register.h"
#include "qapi/error.h"
-#include "qemu/bitops.h"
#include "qemu/log.h"
-#include "qemu/cutils.h"
-#include "qemu/event_notifier.h"
#include "hw/qdev-properties.h"
-#include "qom/object_interfaces.h"
#include "migration/vmstate.h"
#include "hw/net/xlnx-versal-canfd.h"
#include "trace.h"
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
index 2310f62..bc70e50 100644
--- a/hw/ppc/ppce500_spin.c
+++ b/hw/ppc/ppce500_spin.c
@@ -99,8 +99,7 @@ static void spin_kick(CPUState *cs, run_on_cpu_data data)
cs->halted = 0;
cs->exception_index = -1;
- cs->stopped = false;
- qemu_cpu_kick(cs);
+ cpu_resume(cs);
}
static void spin_write(void *opaque, hwaddr addr, uint64_t value,
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 51e88ba..8602a56 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -306,6 +306,7 @@ int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code)
g_autofree SCCB *work_sccb = NULL;
AddressSpace *as = CPU(cpu)->as;
const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
+ MemTxResult ret;
/* first some basic checks on program checks */
if (env->psw.mask & PSW_MASK_PSTATE) {
@@ -320,7 +321,10 @@ int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code)
}
/* the header contains the actual length of the sccb */
- address_space_read(as, sccb, attrs, &header, sizeof(SCCBHeader));
+ ret = address_space_read(as, sccb, attrs, &header, sizeof(SCCBHeader));
+ if (ret != MEMTX_OK) {
+ return -PGM_ADDRESSING;
+ }
/* Valid sccb sizes */
if (be16_to_cpu(header.length) < sizeof(SCCBHeader)) {
@@ -333,7 +337,11 @@ int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code)
* the host has checked the values
*/
work_sccb = g_malloc0(be16_to_cpu(header.length));
- address_space_read(as, sccb, attrs, work_sccb, be16_to_cpu(header.length));
+ ret = address_space_read(as, sccb, attrs,
+ work_sccb, be16_to_cpu(header.length));
+ if (ret != MEMTX_OK) {
+ return -PGM_ADDRESSING;
+ }
if (!sclp_command_code_valid(code)) {
work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
@@ -347,7 +355,11 @@ int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code)
sclp_c->execute(sclp, work_sccb, code);
out_write:
- address_space_write(as, sccb, attrs, work_sccb, be16_to_cpu(header.length));
+ ret = address_space_write(as, sccb, attrs,
+ work_sccb, be16_to_cpu(header.length));
+ if (ret != MEMTX_OK) {
+ return -PGM_PROTECTION;
+ }
sclp_c->service_interrupt(sclp, sccb);
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 0aeaad3..09d2cec 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -192,7 +192,7 @@ static void leon3_cache_control_int(CPUSPARCState *env)
static void leon3_irq_ack(CPUSPARCState *env, int intno)
{
- CPUState *cpu = CPU(env_cpu(env));
+ CPUState *cpu = env_cpu(env);
grlib_irqmp_ack(env->irq_manager, cpu->cpu_index, intno);
}
diff --git a/hw/vmapple/vmapple.c b/hw/vmapple/vmapple.c
index 16e6110..1e4365f 100644
--- a/hw/vmapple/vmapple.c
+++ b/hw/vmapple/vmapple.c
@@ -51,6 +51,8 @@
#include "system/reset.h"
#include "system/runstate.h"
#include "system/system.h"
+#include "target/arm/gtimer.h"
+#include "target/arm/cpu.h"
struct VMAppleMachineState {
MachineState parent;
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index 6efffae..55de1a7 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -268,7 +268,7 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
/* Need MMU initialized prior to ELF loading,
* so that ELF gets loaded into virtual addresses
*/
- cpu_reset(CPU(cpu));
+ reset_mmu(cenv);
}
if (smp_cpus > 1) {
extints = xtensa_mx_pic_get_extints(mx_pic);
diff --git a/include/hw/arm/aspeed_coprocessor.h b/include/hw/arm/aspeed_coprocessor.h
new file mode 100644
index 0000000..d77655d
--- /dev/null
+++ b/include/hw/arm/aspeed_coprocessor.h
@@ -0,0 +1,61 @@
+/*
+ * ASPEED Coprocessor
+ *
+ * Copyright (C) 2025 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef ASPEED_COPROCESSOR_H
+#define ASPEED_COPROCESSOR_H
+
+#include "qom/object.h"
+#include "hw/arm/aspeed_soc.h"
+
+struct AspeedCoprocessorState {
+ DeviceState parent;
+
+ MemoryRegion *memory;
+ MemoryRegion sram;
+ Clock *sysclk;
+
+ AspeedSCUState scu;
+ AspeedSCUState scuio;
+ AspeedTimerCtrlState timerctrl;
+ SerialMM uart[ASPEED_UARTS_NUM];
+};
+
+#define TYPE_ASPEED_COPROCESSOR "aspeed-coprocessor"
+OBJECT_DECLARE_TYPE(AspeedCoprocessorState, AspeedCoprocessorClass,
+ ASPEED_COPROCESSOR)
+
+struct AspeedCoprocessorClass {
+ DeviceClass parent_class;
+
+ /** valid_cpu_types: NULL terminated array of a single CPU type. */
+ const char * const *valid_cpu_types;
+ uint32_t silicon_rev;
+ const hwaddr *memmap;
+ const int *irqmap;
+ int uarts_base;
+ int uarts_num;
+};
+
+struct Aspeed27x0CoprocessorState {
+ AspeedCoprocessorState parent;
+ AspeedINTCState intc[2];
+ UnimplementedDeviceState ipc[2];
+ UnimplementedDeviceState scuio;
+
+ ARMv7MState armv7m;
+};
+
+#define TYPE_ASPEED27X0SSP_COPROCESSOR "aspeed27x0ssp-coprocessor"
+OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0CoprocessorState,
+ ASPEED27X0SSP_COPROCESSOR)
+
+#define TYPE_ASPEED27X0TSP_COPROCESSOR "aspeed27x0tsp-coprocessor"
+DECLARE_OBJ_CHECKERS(Aspeed27x0CoprocessorState, AspeedCoprocessorClass,
+ ASPEED27X0TSP_COPROCESSOR, TYPE_ASPEED27X0TSP_COPROCESSOR)
+
+#endif /* ASPEED_COPROCESSOR_H */
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index ed32efb..4b8e599 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -153,30 +153,6 @@ struct Aspeed10x0SoCState {
ARMv7MState armv7m;
};
-struct Aspeed27x0SSPSoCState {
- AspeedSoCState parent;
- AspeedINTCState intc[2];
- UnimplementedDeviceState ipc[2];
- UnimplementedDeviceState scuio;
-
- ARMv7MState armv7m;
-};
-
-#define TYPE_ASPEED27X0SSP_SOC "aspeed27x0ssp-soc"
-OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0SSPSoCState, ASPEED27X0SSP_SOC)
-
-struct Aspeed27x0TSPSoCState {
- AspeedSoCState parent;
- AspeedINTCState intc[2];
- UnimplementedDeviceState ipc[2];
- UnimplementedDeviceState scuio;
-
- ARMv7MState armv7m;
-};
-
-#define TYPE_ASPEED27X0TSP_SOC "aspeed27x0tsp-soc"
-OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0TSPSoCState, ASPEED27X0TSP_SOC)
-
#define TYPE_ASPEED10X0_SOC "aspeed10x0-soc"
OBJECT_DECLARE_SIMPLE_TYPE(Aspeed10x0SoCState, ASPEED10X0_SOC)
@@ -198,12 +174,9 @@ struct AspeedSoCClass {
const int *irqmap;
const hwaddr *memmap;
uint32_t num_cpus;
- qemu_irq (*get_irq)(AspeedSoCState *s, int dev);
bool (*boot_from_emmc)(AspeedSoCState *s);
};
-const char *aspeed_soc_cpu_type(AspeedSoCClass *sc);
-
enum {
ASPEED_DEV_VBOOTROM,
ASPEED_DEV_SPI_BOOT,
@@ -304,12 +277,15 @@ enum {
ASPEED_DEV_IPC1,
};
-qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
-bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
-void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
+const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types);
+bool aspeed_soc_uart_realize(MemoryRegion *memory, SerialMM *smm,
+ const hwaddr addr, Error **errp);
+void aspeed_soc_uart_set_chr(SerialMM *uart, int dev, int uarts_base,
+ int uarts_num, Chardev *chr);
bool aspeed_soc_dram_init(AspeedSoCState *s, Error **errp);
-void aspeed_mmio_map(AspeedSoCState *s, SysBusDevice *dev, int n, hwaddr addr);
-void aspeed_mmio_map_unimplemented(AspeedSoCState *s, SysBusDevice *dev,
+void aspeed_mmio_map(MemoryRegion *memory, SysBusDevice *dev, int n,
+ hwaddr addr);
+void aspeed_mmio_map_unimplemented(MemoryRegion *memory, SysBusDevice *dev,
const char *name, hwaddr addr,
uint64_t size);
void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
@@ -326,14 +302,14 @@ static inline int aspeed_uart_index(int uart_dev)
return uart_dev - ASPEED_DEV_UART0;
}
-static inline int aspeed_uart_first(AspeedSoCClass *sc)
+static inline int aspeed_uart_first(int uarts_base)
{
- return aspeed_uart_index(sc->uarts_base);
+ return aspeed_uart_index(uarts_base);
}
-static inline int aspeed_uart_last(AspeedSoCClass *sc)
+static inline int aspeed_uart_last(int uarts_base, int uarts_num)
{
- return aspeed_uart_first(sc) + sc->uarts_num - 1;
+ return aspeed_uart_first(uarts_base) + uarts_num - 1;
}
#endif /* ASPEED_SOC_H */
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index 31bd812..897dfaa 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -24,7 +24,7 @@ strList *hmp_split_at_comma(const char *str);
void hmp_info_name(Monitor *mon, const QDict *qdict);
void hmp_info_version(Monitor *mon, const QDict *qdict);
void hmp_info_kvm(Monitor *mon, const QDict *qdict);
-void hmp_info_mshv(Monitor *mon, const QDict *qdict);
+void hmp_info_accelerators(Monitor *mon, const QDict *qdict);
void hmp_info_status(Monitor *mon, const QDict *qdict);
void hmp_info_uuid(Monitor *mon, const QDict *qdict);
void hmp_info_chardev(Monitor *mon, const QDict *qdict);
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index abd2204..aec730a 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -699,7 +699,7 @@ void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time);
*
* Returns: true if the timer is pending
*/
-bool timer_pending(QEMUTimer *ts);
+bool timer_pending(const QEMUTimer *ts);
/**
* timer_expired:
@@ -710,7 +710,7 @@ bool timer_pending(QEMUTimer *ts);
*
* Returns: true if the timer has expired
*/
-bool timer_expired(QEMUTimer *timer_head, int64_t current_time);
+bool timer_expired(const QEMUTimer *timer_head, int64_t current_time);
/**
* timer_expire_time_ns:
@@ -720,7 +720,7 @@ bool timer_expired(QEMUTimer *timer_head, int64_t current_time);
*
* Returns: the expiry time in nanoseconds
*/
-uint64_t timer_expire_time_ns(QEMUTimer *ts);
+uint64_t timer_expire_time_ns(const QEMUTimer *ts);
/**
* timer_get:
diff --git a/include/system/kvm.h b/include/system/kvm.h
index 4fc09e3..8f9eecf 100644
--- a/include/system/kvm.h
+++ b/include/system/kvm.h
@@ -340,14 +340,16 @@ int kvm_arch_process_async_events(CPUState *cpu);
int kvm_arch_get_registers(CPUState *cpu, Error **errp);
-/* state subset only touched by the VCPU itself during runtime */
-#define KVM_PUT_RUNTIME_STATE 1
-/* state subset modified during VCPU reset */
-#define KVM_PUT_RESET_STATE 2
-/* full state set, modified during initialization or on vmload */
-#define KVM_PUT_FULL_STATE 3
-
-int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp);
+typedef enum kvm_put_state {
+ /* state subset only touched by the VCPU itself during runtime */
+ KVM_PUT_RUNTIME_STATE = 1,
+ /* state subset modified during VCPU reset */
+ KVM_PUT_RESET_STATE = 2,
+ /* full state set, modified during initialization or on vmload */
+ KVM_PUT_FULL_STATE = 3,
+} KvmPutState;
+
+int kvm_arch_put_registers(CPUState *cpu, KvmPutState level, Error **errp);
int kvm_arch_get_default_type(MachineState *ms);
diff --git a/qapi/accelerator.json b/qapi/accelerator.json
index 664e027..2b92060 100644
--- a/qapi/accelerator.json
+++ b/qapi/accelerator.json
@@ -56,30 +56,55 @@
'features': [ 'unstable' ] }
##
-# @MshvInfo:
+# @Accelerator:
#
# Information about support for MSHV acceleration
#
-# @enabled: true if MSHV acceleration is active
+# @hvf: Apple Hypervisor.framework
#
-# @present: true if MSHV acceleration is built into this executable
+# @kvm: KVM
+#
+# @mshv: Hyper-V
+#
+# @nvmm: NetBSD NVMM
+#
+# @qtest: QTest (dummy accelerator)
+#
+# @tcg: TCG (dynamic translation)
+#
+# @whpx: Windows Hypervisor Platform
+#
+# @xen: Xen
+#
+# Since: 10.2.0
+##
+{ 'enum': 'Accelerator', 'data': ['hvf', 'kvm', 'mshv', 'nvmm', 'qtest', 'tcg', 'whpx', 'xen'] }
+
+##
+# @AcceleratorInfo:
+#
+# Information about support for various accelerators
+#
+# @enabled: the accelerator that is in use
+#
+# @present: the list of accelerators that are built into this executable
#
# Since: 10.2.0
##
-{ 'struct': 'MshvInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
+{ 'struct': 'AcceleratorInfo', 'data': {'enabled': 'Accelerator', 'present': ['Accelerator']} }
##
-# @query-mshv:
+# @query-accelerators:
#
-# Return information about MSHV acceleration
+# Return information about accelerators
#
-# Returns: @MshvInfo
+# Returns: @AcceleratorInfo
#
-# Since: 10.0.92
+# Since: 10.2.0
#
# .. qmp-example::
#
-# -> { "execute": "query-mshv" }
-# <- { "return": { "enabled": true, "present": true } }
+# -> { "execute": "query-accelerators" }
+# <- { "return": { "enabled": "mshv", "present": ["kvm", "mshv", "qtest", "tcg"] } }
##
-{ 'command': 'query-mshv', 'returns': 'MshvInfo' }
+{ 'command': 'query-accelerators', 'returns': 'AcceleratorInfo' }
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index 1108513..0c1df62 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -59,7 +59,6 @@ name = "bql"
version = "0.1.0"
dependencies = [
"glib-sys",
- "migration",
]
[[package]]
@@ -198,8 +197,10 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
name = "migration"
version = "0.1.0"
dependencies = [
+ "bql",
"common",
"glib-sys",
+ "qemu_macros",
"util",
]
diff --git a/rust/bql/Cargo.toml b/rust/bql/Cargo.toml
index d5177e5..8fd8131 100644
--- a/rust/bql/Cargo.toml
+++ b/rust/bql/Cargo.toml
@@ -13,7 +13,6 @@ repository.workspace = true
rust-version.workspace = true
[dependencies]
-migration = { path = "../migration" }
glib-sys.workspace = true
[features]
diff --git a/rust/bql/meson.build b/rust/bql/meson.build
index 22d7c9b..091372d 100644
--- a/rust/bql/meson.build
+++ b/rust/bql/meson.build
@@ -37,7 +37,6 @@ _bql_rs = static_library(
override_options: ['rust_std=2021', 'build.rust_std=2021'],
rust_abi: 'rust',
rust_args: _bql_cfg,
- link_with: [_migration_rs],
dependencies: [glib_sys_rs],
)
diff --git a/rust/bql/src/cell.rs b/rust/bql/src/cell.rs
index 24ab294..8ade7db 100644
--- a/rust/bql/src/cell.rs
+++ b/rust/bql/src/cell.rs
@@ -151,8 +151,6 @@ use std::{
ptr::NonNull,
};
-use migration::impl_vmstate_transparent;
-
/// A mutable memory location that is protected by the Big QEMU Lock.
///
/// # Memory layout
@@ -364,8 +362,6 @@ impl<T: Default> BqlCell<T> {
}
}
-impl_vmstate_transparent!(crate::cell::BqlCell<T> where T: VMState);
-
/// A mutable memory location with dynamically checked borrow rules,
/// protected by the Big QEMU Lock.
///
@@ -580,6 +576,23 @@ impl<T> BqlRefCell<T> {
}
}
+ /// Returns a mutable reference to the underlying data in this cell,
+ /// while the owner already has a mutable reference to the cell.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use bql::BqlRefCell;
+ ///
+ /// let mut c = BqlRefCell::new(5);
+ ///
+ /// *c.get_mut() = 10;
+ /// ```
+ #[inline]
+ pub const fn get_mut(&mut self) -> &mut T {
+ self.value.get_mut()
+ }
+
/// Returns a raw pointer to the underlying data in this cell.
///
/// # Examples
@@ -674,8 +687,6 @@ impl<T> From<T> for BqlRefCell<T> {
}
}
-impl_vmstate_transparent!(crate::cell::BqlRefCell<T> where T: VMState);
-
struct BorrowRef<'b> {
borrow: &'b Cell<BorrowFlag>,
}
diff --git a/rust/hw/char/pl011/src/registers.rs b/rust/hw/char/pl011/src/registers.rs
index 0c3a4d7..fa57281 100644
--- a/rust/hw/char/pl011/src/registers.rs
+++ b/rust/hw/char/pl011/src/registers.rs
@@ -255,6 +255,7 @@ pub enum Mode {
#[bitsize(2)]
#[derive(Clone, Copy, Debug, Eq, FromBits, PartialEq)]
+#[allow(clippy::enum_variant_names)]
/// `WLEN` Word length, field of [Line Control register](LineControl).
///
/// These bits indicate the number of data bits transmitted or received in a
diff --git a/rust/hw/timer/hpet/src/fw_cfg.rs b/rust/hw/timer/hpet/src/fw_cfg.rs
index e569b57..bb4ea89 100644
--- a/rust/hw/timer/hpet/src/fw_cfg.rs
+++ b/rust/hw/timer/hpet/src/fw_cfg.rs
@@ -40,7 +40,7 @@ impl HPETFwConfig {
assert!(bql::is_locked());
// SAFETY: all accesses go through these methods, which guarantee
// that the accesses are protected by the BQL.
- let mut fw_cfg = unsafe { *addr_of_mut!(hpet_fw_cfg) };
+ let fw_cfg = unsafe { &mut *addr_of_mut!(hpet_fw_cfg) };
if fw_cfg.count == u8::MAX {
// first instance
@@ -60,7 +60,7 @@ impl HPETFwConfig {
assert!(bql::is_locked());
// SAFETY: all accesses go through these methods, which guarantee
// that the accesses are protected by the BQL.
- let mut fw_cfg = unsafe { *addr_of_mut!(hpet_fw_cfg) };
+ let fw_cfg = unsafe { &mut *addr_of_mut!(hpet_fw_cfg) };
fw_cfg.hpet[hpet_id].event_timer_block_id = timer_block_id;
fw_cfg.hpet[hpet_id].address = address;
diff --git a/rust/meson.build b/rust/meson.build
index 6ba075c..76e1069 100644
--- a/rust/meson.build
+++ b/rust/meson.build
@@ -29,8 +29,8 @@ subdir('qemu-macros')
subdir('common')
subdir('bits')
subdir('util')
-subdir('migration')
subdir('bql')
+subdir('migration')
subdir('qom')
subdir('system')
subdir('chardev')
diff --git a/rust/migration/Cargo.toml b/rust/migration/Cargo.toml
index 94504f3..4154574 100644
--- a/rust/migration/Cargo.toml
+++ b/rust/migration/Cargo.toml
@@ -13,7 +13,9 @@ repository.workspace = true
rust-version.workspace = true
[dependencies]
+bql = { path = "../bql" }
common = { path = "../common" }
+qemu_macros = { path = "../qemu-macros" }
util = { path = "../util" }
glib-sys.workspace = true
diff --git a/rust/migration/meson.build b/rust/migration/meson.build
index 18be65c..4444947 100644
--- a/rust/migration/meson.build
+++ b/rust/migration/meson.build
@@ -31,18 +31,19 @@ _migration_rs = static_library(
[
'src/lib.rs',
'src/bindings.rs',
+ 'src/migratable.rs',
'src/vmstate.rs',
],
{'.' : _migration_bindings_inc_rs},
),
override_options: ['rust_std=2021', 'build.rust_std=2021'],
rust_abi: 'rust',
- link_with: [_util_rs],
- dependencies: [common_rs, glib_sys_rs],
+ link_with: [_util_rs, _bql_rs],
+ dependencies: [common_rs, glib_sys_rs, qemu_macros],
)
migration_rs = declare_dependency(link_with: [_migration_rs],
- dependencies: [migration, qemuutil])
+ dependencies: [bql_rs, migration, qemuutil])
# Doctests are essentially integration tests, so they need the same dependencies.
# Note that running them requires the object files for C code, so place them
diff --git a/rust/migration/src/lib.rs b/rust/migration/src/lib.rs
index 5f51dde..c9bdf0d 100644
--- a/rust/migration/src/lib.rs
+++ b/rust/migration/src/lib.rs
@@ -2,5 +2,10 @@
pub mod bindings;
+pub use qemu_macros::ToMigrationState;
+
+pub mod migratable;
+pub use migratable::*;
+
pub mod vmstate;
pub use vmstate::*;
diff --git a/rust/migration/src/migratable.rs b/rust/migration/src/migratable.rs
new file mode 100644
index 0000000..ded6fe8
--- /dev/null
+++ b/rust/migration/src/migratable.rs
@@ -0,0 +1,442 @@
+// Copyright 2025 Red Hat, Inc.
+// Author(s): Paolo Bonzini <pbonzini@redhat.com>
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+use std::{
+ fmt,
+ mem::size_of,
+ ptr::{self, addr_of, NonNull},
+ sync::{Arc, Mutex},
+};
+
+use bql::{BqlCell, BqlRefCell};
+use common::Zeroable;
+
+use crate::{
+ bindings, vmstate_fields_ref, vmstate_of, InvalidError, VMState, VMStateDescriptionBuilder,
+};
+
+/// Enables QEMU migration support even when a type is wrapped with
+/// synchronization primitives (like `Mutex`) that the C migration
+/// code cannot directly handle. The trait provides methods to
+/// extract essential state for migration and restore it after
+/// migration completes.
+///
+/// On top of extracting data from synchronization wrappers during save
+/// and restoring it during load, it's also possible to use `ToMigrationState`
+/// to convert runtime representations to migration-safe formats.
+///
+/// # Examples
+///
+/// ```
+/// use bql::BqlCell;
+/// use migration::{InvalidError, ToMigrationState, VMState};
+/// # use migration::VMStateField;
+///
+/// # #[derive(Debug, PartialEq, Eq)]
+/// struct DeviceState {
+/// counter: BqlCell<u32>,
+/// enabled: bool,
+/// }
+///
+/// # #[derive(Debug)]
+/// #[derive(Default)]
+/// struct DeviceMigrationState {
+/// counter: u32,
+/// enabled: bool,
+/// }
+///
+/// # unsafe impl VMState for DeviceMigrationState {
+/// # const BASE: VMStateField = ::common::Zeroable::ZERO;
+/// # }
+/// impl ToMigrationState for DeviceState {
+/// type Migrated = DeviceMigrationState;
+///
+/// fn snapshot_migration_state(
+/// &self,
+/// target: &mut Self::Migrated,
+/// ) -> Result<(), InvalidError> {
+/// target.counter = self.counter.get();
+/// target.enabled = self.enabled;
+/// Ok(())
+/// }
+///
+/// fn restore_migrated_state_mut(
+/// &mut self,
+/// source: Self::Migrated,
+/// _version_id: u8,
+/// ) -> Result<(), InvalidError> {
+/// self.counter.set(source.counter);
+/// self.enabled = source.enabled;
+/// Ok(())
+/// }
+/// }
+/// # bql::start_test();
+/// # let dev = DeviceState { counter: 10.into(), enabled: true };
+/// # let mig = dev.to_migration_state().unwrap();
+/// # assert!(matches!(*mig, DeviceMigrationState { counter: 10, enabled: true }));
+/// # let mut dev2 = DeviceState { counter: 42.into(), enabled: false };
+/// # dev2.restore_migrated_state_mut(*mig, 1).unwrap();
+/// # assert_eq!(dev2, dev);
+/// ```
+///
+/// More commonly, the trait is derived through the
+/// [`derive(ToMigrationState)`](qemu_macros::ToMigrationState) procedural
+/// macro.
+pub trait ToMigrationState {
+ /// The type used to represent the migrated state.
+ type Migrated: Default + VMState;
+
+ /// Capture the current state into a migration-safe format, failing
+ /// if the state cannot be migrated.
+ fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError>;
+
+ /// Restores state from a migrated representation, failing if the
+ /// state cannot be restored.
+ fn restore_migrated_state_mut(
+ &mut self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError>;
+
+ /// Convenience method to combine allocation and state capture
+ /// into a single operation.
+ fn to_migration_state(&self) -> Result<Box<Self::Migrated>, InvalidError> {
+ let mut migrated = Box::<Self::Migrated>::default();
+ self.snapshot_migration_state(&mut migrated)?;
+ Ok(migrated)
+ }
+}
+
+// Implementations for primitive types. Do not use a blanket implementation
+// for all Copy types, because [T; N] is Copy if T is Copy; that would conflict
+// with the below implementation for arrays.
+macro_rules! impl_for_primitive {
+ ($($t:ty),*) => {
+ $(
+ impl ToMigrationState for $t {
+ type Migrated = Self;
+
+ fn snapshot_migration_state(
+ &self,
+ target: &mut Self::Migrated,
+ ) -> Result<(), InvalidError> {
+ *target = *self;
+ Ok(())
+ }
+
+ fn restore_migrated_state_mut(
+ &mut self,
+ source: Self::Migrated,
+ _version_id: u8,
+ ) -> Result<(), InvalidError> {
+ *self = source;
+ Ok(())
+ }
+ }
+ )*
+ };
+}
+
+impl_for_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, bool);
+
+impl<T: ToMigrationState, const N: usize> ToMigrationState for [T; N]
+where
+ [T::Migrated; N]: Default,
+{
+ type Migrated = [T::Migrated; N];
+
+ fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError> {
+ for (item, target_item) in self.iter().zip(target.iter_mut()) {
+ item.snapshot_migration_state(target_item)?;
+ }
+ Ok(())
+ }
+
+ fn restore_migrated_state_mut(
+ &mut self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError> {
+ for (item, source_item) in self.iter_mut().zip(source) {
+ item.restore_migrated_state_mut(source_item, version_id)?;
+ }
+ Ok(())
+ }
+}
+
+impl<T: ToMigrationState> ToMigrationState for Mutex<T> {
+ type Migrated = T::Migrated;
+
+ fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError> {
+ self.lock().unwrap().snapshot_migration_state(target)
+ }
+
+ fn restore_migrated_state_mut(
+ &mut self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError> {
+ self.get_mut()
+ .unwrap()
+ .restore_migrated_state_mut(source, version_id)
+ }
+}
+
+impl<T: ToMigrationState> ToMigrationState for BqlRefCell<T> {
+ type Migrated = T::Migrated;
+
+ fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError> {
+ self.borrow().snapshot_migration_state(target)
+ }
+
+ fn restore_migrated_state_mut(
+ &mut self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError> {
+ self.get_mut()
+ .restore_migrated_state_mut(source, version_id)
+ }
+}
+
+/// Extension trait for types that support migration state restoration
+/// through interior mutability.
+///
+/// This trait extends [`ToMigrationState`] for types that can restore
+/// their state without requiring mutable access. While user structs
+/// will generally use `ToMigrationState`, the device will have multiple
+/// references and therefore the device struct has to employ an interior
+/// mutability wrapper like [`Mutex`] or [`BqlRefCell`].
+///
+/// Anything that implements this trait can in turn be used within
+/// [`Migratable<T>`], which makes no assumptions on how to achieve mutable
+/// access to the runtime state.
+///
+/// # Examples
+///
+/// ```
+/// use std::sync::Mutex;
+///
+/// use migration::ToMigrationStateShared;
+///
+/// let device_state = Mutex::new(42);
+/// // Can restore without &mut access
+/// device_state.restore_migrated_state(100, 1).unwrap();
+/// assert_eq!(*device_state.lock().unwrap(), 100);
+/// ```
+pub trait ToMigrationStateShared: ToMigrationState {
+ /// Restores state from a migrated representation to an interior-mutable
+ /// object. Similar to `restore_migrated_state_mut`, but requires a
+ /// shared reference; therefore it can be used to restore a device's
+ /// state even though devices have multiple references to them.
+ fn restore_migrated_state(
+ &self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError>;
+}
+
+impl<T: ToMigrationStateShared, const N: usize> ToMigrationStateShared for [T; N]
+where
+ [T::Migrated; N]: Default,
+{
+ fn restore_migrated_state(
+ &self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError> {
+ for (item, source_item) in self.iter().zip(source) {
+ item.restore_migrated_state(source_item, version_id)?;
+ }
+ Ok(())
+ }
+}
+
+// Arc requires the contained object to be interior-mutable
+impl<T: ToMigrationStateShared> ToMigrationState for Arc<T> {
+ type Migrated = T::Migrated;
+
+ fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError> {
+ (**self).snapshot_migration_state(target)
+ }
+
+ fn restore_migrated_state_mut(
+ &mut self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError> {
+ (**self).restore_migrated_state(source, version_id)
+ }
+}
+
+impl<T: ToMigrationStateShared> ToMigrationStateShared for Arc<T> {
+ fn restore_migrated_state(
+ &self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError> {
+ (**self).restore_migrated_state(source, version_id)
+ }
+}
+
+// Interior-mutable types. Note how they only require ToMigrationState for
+// the inner type!
+
+impl<T: ToMigrationState> ToMigrationStateShared for Mutex<T> {
+ fn restore_migrated_state(
+ &self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError> {
+ self.lock()
+ .unwrap()
+ .restore_migrated_state_mut(source, version_id)
+ }
+}
+
+impl<T: ToMigrationState> ToMigrationStateShared for BqlRefCell<T> {
+ fn restore_migrated_state(
+ &self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), InvalidError> {
+ self.borrow_mut()
+ .restore_migrated_state_mut(source, version_id)
+ }
+}
+
+/// A wrapper that enables QEMU migration for types with shared state.
+///
+/// `Migratable<T>` provides a bridge between Rust types that use interior
+/// mutability (like `Mutex<T>`) and QEMU's C-based migration infrastructure.
+/// It manages the lifecycle of migration state and provides automatic
+/// conversion between runtime and migration representations.
+///
+/// ```
+/// # use std::sync::Mutex;
+/// # use migration::{Migratable, ToMigrationState, VMState, VMStateField};
+///
+/// #[derive(ToMigrationState)]
+/// pub struct DeviceRegs {
+/// status: u32,
+/// }
+/// # unsafe impl VMState for DeviceRegsMigration {
+/// # const BASE: VMStateField = ::common::Zeroable::ZERO;
+/// # }
+///
+/// pub struct SomeDevice {
+/// // ...
+/// registers: Migratable<Mutex<DeviceRegs>>,
+/// }
+/// ```
+#[repr(C)]
+pub struct Migratable<T: ToMigrationStateShared> {
+ /// Pointer to migration state, valid only during migration operations.
+ /// C vmstate does not support NULL pointers, so no `Option<Box<>>`.
+ migration_state: BqlCell<*mut T::Migrated>,
+
+ /// The runtime state that can be accessed during normal operation
+ runtime_state: T,
+}
+
+impl<T: ToMigrationStateShared> std::ops::Deref for Migratable<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.runtime_state
+ }
+}
+
+impl<T: ToMigrationStateShared> std::ops::DerefMut for Migratable<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.runtime_state
+ }
+}
+
+impl<T: ToMigrationStateShared> Migratable<T> {
+ /// Creates a new `Migratable` wrapper around the given runtime state.
+ ///
+ /// # Returns
+ /// A new `Migratable` instance ready for use and migration
+ pub fn new(runtime_state: T) -> Self {
+ Self {
+ migration_state: BqlCell::new(ptr::null_mut()),
+ runtime_state,
+ }
+ }
+
+ fn pre_save(&self) -> Result<(), InvalidError> {
+ let state = self.runtime_state.to_migration_state()?;
+ self.migration_state.set(Box::into_raw(state));
+ Ok(())
+ }
+
+ fn post_save(&self) -> Result<(), InvalidError> {
+ let state = unsafe { Box::from_raw(self.migration_state.replace(ptr::null_mut())) };
+ drop(state);
+ Ok(())
+ }
+
+ fn pre_load(&self) -> Result<(), InvalidError> {
+ self.migration_state
+ .set(Box::into_raw(Box::<T::Migrated>::default()));
+ Ok(())
+ }
+
+ fn post_load(&self, version_id: u8) -> Result<(), InvalidError> {
+ let state = unsafe { Box::from_raw(self.migration_state.replace(ptr::null_mut())) };
+ self.runtime_state
+ .restore_migrated_state(*state, version_id)
+ }
+}
+
+impl<T: ToMigrationStateShared + fmt::Debug> fmt::Debug for Migratable<T>
+where
+ T::Migrated: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut struct_f = f.debug_struct("Migratable");
+ struct_f.field("runtime_state", &self.runtime_state);
+
+ let state = NonNull::new(self.migration_state.get()).map(|x| unsafe { x.as_ref() });
+ struct_f.field("migration_state", &state);
+ struct_f.finish()
+ }
+}
+
+impl<T: ToMigrationStateShared + Default> Default for Migratable<T> {
+ fn default() -> Self {
+ Self::new(T::default())
+ }
+}
+
+impl<T: 'static + ToMigrationStateShared> Migratable<T> {
+ const FIELD: bindings::VMStateField = vmstate_of!(Self, migration_state);
+
+ const FIELDS: &[bindings::VMStateField] = vmstate_fields_ref! {
+ Migratable::<T>::FIELD
+ };
+
+ const VMSD: &'static bindings::VMStateDescription = VMStateDescriptionBuilder::<Self>::new()
+ .version_id(1)
+ .minimum_version_id(1)
+ .pre_save(&Self::pre_save)
+ .pre_load(&Self::pre_load)
+ .post_save(&Self::post_save)
+ .post_load(&Self::post_load)
+ .fields(Self::FIELDS)
+ .build()
+ .as_ref();
+}
+
+unsafe impl<T: 'static + ToMigrationStateShared> VMState for Migratable<T> {
+ const BASE: bindings::VMStateField = {
+ bindings::VMStateField {
+ vmsd: addr_of!(*Self::VMSD),
+ size: size_of::<Self>(),
+ flags: bindings::VMStateFlags::VMS_STRUCT,
+ ..Zeroable::ZERO
+ }
+ };
+}
diff --git a/rust/migration/src/vmstate.rs b/rust/migration/src/vmstate.rs
index e04b19b..42e5df8d 100644
--- a/rust/migration/src/vmstate.rs
+++ b/rust/migration/src/vmstate.rs
@@ -72,6 +72,7 @@ macro_rules! call_func_with_field {
($func:expr, $typ:ty, $($field:tt).+) => {
$func(loop {
#![allow(unreachable_code)]
+ #![allow(unused_variables)]
const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> { ::core::marker::PhantomData }
// Unreachable code is exempt from checks on uninitialized values.
// Use that trick to infer the type of this PhantomData.
@@ -275,6 +276,8 @@ macro_rules! impl_vmstate_transparent {
};
}
+impl_vmstate_transparent!(bql::BqlCell<T> where T: VMState);
+impl_vmstate_transparent!(bql::BqlRefCell<T> where T: VMState);
impl_vmstate_transparent!(std::cell::Cell<T> where T: VMState);
impl_vmstate_transparent!(std::cell::UnsafeCell<T> where T: VMState);
impl_vmstate_transparent!(std::pin::Pin<T> where T: VMState);
@@ -293,6 +296,25 @@ macro_rules! impl_vmstate_bitsized {
as ::bilge::prelude::Number>::UnderlyingType
as $crate::vmstate::VMState>::VARRAY_FLAG;
}
+
+ impl $crate::migratable::ToMigrationState for $type {
+ type Migrated = <<$type as ::bilge::prelude::Bitsized>::ArbitraryInt
+ as ::bilge::prelude::Number>::UnderlyingType;
+
+ fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), $crate::InvalidError> {
+ *target = Self::Migrated::from(*self);
+ Ok(())
+ }
+
+ fn restore_migrated_state_mut(
+ &mut self,
+ source: Self::Migrated,
+ version_id: u8,
+ ) -> Result<(), $crate::InvalidError> {
+ *self = Self::from(source);
+ Ok(())
+ }
+ }
};
}
@@ -411,20 +433,31 @@ macro_rules! vmstate_exist_fn {
}};
}
+/// Add a terminator to the fields in the arguments, and return
+/// a reference to the resulting array of values.
+#[macro_export]
+macro_rules! vmstate_fields_ref {
+ ($($field:expr),*$(,)*) => {
+ &[
+ $($field),*,
+ $crate::bindings::VMStateField {
+ flags: $crate::bindings::VMStateFlags::VMS_END,
+ ..::common::zeroable::Zeroable::ZERO
+ }
+ ]
+ }
+}
+
/// Helper macro to declare a list of
/// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and return
/// a pointer to the array of values it created.
#[macro_export]
macro_rules! vmstate_fields {
($($field:expr),*$(,)*) => {{
- static _FIELDS: &[$crate::bindings::VMStateField] = &[
+ static _FIELDS: &[$crate::bindings::VMStateField] = $crate::vmstate_fields_ref!(
$($field),*,
- $crate::bindings::VMStateField {
- flags: $crate::bindings::VMStateFlags::VMS_END,
- ..::common::zeroable::Zeroable::ZERO
- }
- ];
- _FIELDS.as_ptr()
+ );
+ _FIELDS
}}
}
@@ -469,33 +502,21 @@ macro_rules! impl_vmstate_struct {
};
}
-/// A transparent wrapper type for the `subsections` field of
-/// [`VMStateDescription`].
-///
-/// This is necessary to be able to declare subsection descriptions as statics,
-/// because the only way to implement `Sync` for a foreign type (and `*const`
-/// pointers are foreign types in Rust) is to create a wrapper struct and
-/// `unsafe impl Sync` for it.
-///
-/// This struct is used in the
-/// [`vm_state_subsections`](crate::vmstate_subsections) macro implementation.
-#[repr(transparent)]
-pub struct VMStateSubsectionsWrapper(pub &'static [*const crate::bindings::VMStateDescription]);
-
-unsafe impl Sync for VMStateSubsectionsWrapper {}
+/// The type returned by [`vmstate_subsections!`](crate::vmstate_subsections).
+pub type VMStateSubsections = &'static [Option<&'static crate::bindings::VMStateDescription>];
/// Helper macro to declare a list of subsections ([`VMStateDescription`])
/// into a static and return a pointer to the array of pointers it created.
#[macro_export]
macro_rules! vmstate_subsections {
($($subsection:expr),*$(,)*) => {{
- static _SUBSECTIONS: $crate::vmstate::VMStateSubsectionsWrapper = $crate::vmstate::VMStateSubsectionsWrapper(&[
+ static _SUBSECTIONS: $crate::vmstate::VMStateSubsections = &[
$({
static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection.get();
- ::core::ptr::addr_of!(_SUBSECTION)
+ Some(&_SUBSECTION)
}),*,
- ::core::ptr::null()
- ]);
+ None,
+ ];
&_SUBSECTIONS
}}
}
@@ -676,14 +697,21 @@ impl<T> VMStateDescriptionBuilder<T> {
}
#[must_use]
- pub const fn fields(mut self, fields: *const VMStateField) -> Self {
- self.0.fields = fields;
+ pub const fn fields(mut self, fields: &'static [VMStateField]) -> Self {
+ if fields[fields.len() - 1].flags.0 != VMStateFlags::VMS_END.0 {
+ panic!("fields are not terminated, use vmstate_fields!");
+ }
+ self.0.fields = fields.as_ptr();
self
}
#[must_use]
- pub const fn subsections(mut self, subs: &'static VMStateSubsectionsWrapper) -> Self {
- self.0.subsections = subs.0.as_ptr();
+ pub const fn subsections(mut self, subs: &'static VMStateSubsections) -> Self {
+ if subs[subs.len() - 1].is_some() {
+ panic!("subsections are not terminated, use vmstate_subsections!");
+ }
+ let subs: *const Option<&bindings::VMStateDescription> = subs.as_ptr();
+ self.0.subsections = subs.cast::<*const bindings::VMStateDescription>();
self
}
diff --git a/rust/qemu-macros/src/lib.rs b/rust/qemu-macros/src/lib.rs
index 3e21b67..50239f2 100644
--- a/rust/qemu-macros/src/lib.rs
+++ b/rust/qemu-macros/src/lib.rs
@@ -13,9 +13,13 @@ use syn::{
Attribute, Data, DeriveInput, Error, Field, Fields, FieldsUnnamed, Ident, Meta, Path, Token,
Variant,
};
+
mod bits;
use bits::BitsConstInternal;
+mod migration_state;
+use migration_state::MigrationStateDerive;
+
#[cfg(test)]
mod tests;
@@ -401,7 +405,98 @@ pub fn bits_const_internal(ts: TokenStream) -> TokenStream {
let ts = proc_macro2::TokenStream::from(ts);
let mut it = ts.into_iter();
- BitsConstInternal::parse(&mut it)
+ let out = BitsConstInternal::parse(&mut it).unwrap_or_else(syn::Error::into_compile_error);
+
+ // https://github.com/rust-lang/rust-clippy/issues/15852
+ quote! {
+ {
+ #[allow(clippy::double_parens)]
+ #out
+ }
+ }
+ .into()
+}
+
+/// Derive macro for generating migration state structures and trait
+/// implementations.
+///
+/// This macro generates a migration state struct and implements the
+/// `ToMigrationState` trait for the annotated struct, enabling state
+/// serialization and restoration. Note that defining a `VMStateDescription`
+/// for the migration state struct is left to the user.
+///
+/// # Container attributes
+///
+/// The following attributes can be applied to the struct:
+///
+/// - `#[migration_state(rename = CustomName)]` - Customizes the name of the
+/// generated migration struct. By default, the generated struct is named
+/// `{OriginalName}Migration`.
+///
+/// # Field attributes
+///
+/// The following attributes can be applied to individual fields:
+///
+/// - `#[migration_state(omit)]` - Excludes the field from the migration state
+/// entirely.
+///
+/// - `#[migration_state(into(Type))]` - Converts the field using `.into()`
+/// during both serialization and restoration.
+///
+/// - `#[migration_state(try_into(Type))]` - Converts the field using
+/// `.try_into()` during both serialization and restoration. Returns
+/// `InvalidError` on conversion failure.
+///
+/// - `#[migration_state(clone)]` - Clones the field value.
+///
+/// Fields without any attributes use `ToMigrationState` recursively; note that
+/// this is a simple copy for types that implement `Copy`.
+///
+/// # Attribute compatibility
+///
+/// - `omit` cannot be used with any other attributes
+/// - only one of `into(Type)`, `try_into(Type)` can be used, but they can be
+/// coupled with `clone`.
+///
+/// # Examples
+///
+/// Basic usage:
+/// ```ignore
+/// #[derive(ToMigrationState)]
+/// struct MyStruct {
+/// field1: u32,
+/// field2: Timer,
+/// }
+/// ```
+///
+/// With attributes:
+/// ```ignore
+/// #[derive(ToMigrationState)]
+/// #[migration_state(rename = CustomMigration)]
+/// struct MyStruct {
+/// #[migration_state(omit)]
+/// runtime_field: u32,
+///
+/// #[migration_state(clone)]
+/// shared_data: String,
+///
+/// #[migration_state(into(Cow<'static, str>), clone)]
+/// converted_field: String,
+///
+/// #[migration_state(try_into(i8))]
+/// fallible_field: u32,
+///
+/// // Default: use ToMigrationState trait recursively
+/// nested_field: NestedStruct,
+///
+/// // Primitive types have a default implementation of ToMigrationState
+/// simple_field: u32,
+/// }
+/// ```
+#[proc_macro_derive(ToMigrationState, attributes(migration_state))]
+pub fn derive_to_migration_state(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+ MigrationStateDerive::expand(input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
diff --git a/rust/qemu-macros/src/migration_state.rs b/rust/qemu-macros/src/migration_state.rs
new file mode 100644
index 0000000..5edf0ef
--- /dev/null
+++ b/rust/qemu-macros/src/migration_state.rs
@@ -0,0 +1,298 @@
+use std::borrow::Cow;
+
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote, ToTokens};
+use syn::{spanned::Spanned, DeriveInput, Error, Field, Ident, Result, Type};
+
+use crate::get_fields;
+
+#[derive(Debug, Default)]
+enum ConversionMode {
+ #[default]
+ None,
+ Omit,
+ Into(Type),
+ TryInto(Type),
+ ToMigrationState,
+}
+
+impl ConversionMode {
+ fn target_type(&self, original_type: &Type) -> TokenStream {
+ match self {
+ ConversionMode::Into(ty) | ConversionMode::TryInto(ty) => ty.to_token_stream(),
+ ConversionMode::ToMigrationState => {
+ quote! { <#original_type as ToMigrationState>::Migrated }
+ }
+ _ => original_type.to_token_stream(),
+ }
+ }
+}
+
+#[derive(Debug, Default)]
+struct ContainerAttrs {
+ rename: Option<Ident>,
+}
+
+impl ContainerAttrs {
+ fn parse_from(&mut self, attrs: &[syn::Attribute]) -> Result<()> {
+ use attrs::{set, with, Attrs};
+ Attrs::new()
+ .once("rename", with::eq(set::parse(&mut self.rename)))
+ .parse_attrs("migration_state", attrs)?;
+ Ok(())
+ }
+
+ fn parse(attrs: &[syn::Attribute]) -> Result<Self> {
+ let mut container_attrs = Self::default();
+ container_attrs.parse_from(attrs)?;
+ Ok(container_attrs)
+ }
+}
+
+#[derive(Debug, Default)]
+struct FieldAttrs {
+ conversion: ConversionMode,
+ clone: bool,
+}
+
+impl FieldAttrs {
+ fn parse_from(&mut self, attrs: &[syn::Attribute]) -> Result<()> {
+ let mut omit_flag = false;
+ let mut into_type: Option<Type> = None;
+ let mut try_into_type: Option<Type> = None;
+
+ use attrs::{set, with, Attrs};
+ Attrs::new()
+ .once("omit", set::flag(&mut omit_flag))
+ .once("into", with::paren(set::parse(&mut into_type)))
+ .once("try_into", with::paren(set::parse(&mut try_into_type)))
+ .once("clone", set::flag(&mut self.clone))
+ .parse_attrs("migration_state", attrs)?;
+
+ self.conversion = match (omit_flag, into_type, try_into_type, self.clone) {
+ // Valid combinations of attributes first...
+ (true, None, None, false) => ConversionMode::Omit,
+ (false, Some(ty), None, _) => ConversionMode::Into(ty),
+ (false, None, Some(ty), _) => ConversionMode::TryInto(ty),
+ (false, None, None, true) => ConversionMode::None, // clone without conversion
+ (false, None, None, false) => ConversionMode::ToMigrationState, // default behavior
+
+ // ... then the error cases
+ (true, _, _, _) => {
+ return Err(Error::new(
+ attrs[0].span(),
+ "ToMigrationState: omit cannot be used with other attributes",
+ ));
+ }
+ (_, Some(_), Some(_), _) => {
+ return Err(Error::new(
+ attrs[0].span(),
+ "ToMigrationState: into and try_into attributes cannot be used together",
+ ));
+ }
+ };
+
+ Ok(())
+ }
+
+ fn parse(attrs: &[syn::Attribute]) -> Result<Self> {
+ let mut field_attrs = Self::default();
+ field_attrs.parse_from(attrs)?;
+ Ok(field_attrs)
+ }
+}
+
+#[derive(Debug)]
+struct MigrationStateField {
+ name: Ident,
+ original_type: Type,
+ attrs: FieldAttrs,
+}
+
+impl MigrationStateField {
+ fn maybe_clone(&self, mut value: TokenStream) -> TokenStream {
+ if self.attrs.clone {
+ value = quote! { #value.clone() };
+ }
+ value
+ }
+
+ fn generate_migration_state_field(&self) -> TokenStream {
+ let name = &self.name;
+ let field_type = self.attrs.conversion.target_type(&self.original_type);
+
+ quote! {
+ pub #name: #field_type,
+ }
+ }
+
+ fn generate_snapshot_field(&self) -> TokenStream {
+ let name = &self.name;
+ let value = self.maybe_clone(quote! { self.#name });
+
+ match &self.attrs.conversion {
+ ConversionMode::Omit => {
+ unreachable!("Omitted fields are filtered out during processing")
+ }
+ ConversionMode::None => quote! {
+ target.#name = #value;
+ },
+ ConversionMode::Into(_) => quote! {
+ target.#name = #value.into();
+ },
+ ConversionMode::TryInto(_) => quote! {
+ target.#name = #value.try_into().map_err(|_| migration::InvalidError)?;
+ },
+ ConversionMode::ToMigrationState => quote! {
+ self.#name.snapshot_migration_state(&mut target.#name)?;
+ },
+ }
+ }
+
+ fn generate_restore_field(&self) -> TokenStream {
+ let name = &self.name;
+
+ match &self.attrs.conversion {
+ ConversionMode::Omit => {
+ unreachable!("Omitted fields are filtered out during processing")
+ }
+ ConversionMode::None => quote! {
+ self.#name = #name;
+ },
+ ConversionMode::Into(_) => quote! {
+ self.#name = #name.into();
+ },
+ ConversionMode::TryInto(_) => quote! {
+ self.#name = #name.try_into().map_err(|_| migration::InvalidError)?;
+ },
+ ConversionMode::ToMigrationState => quote! {
+ self.#name.restore_migrated_state_mut(#name, _version_id)?;
+ },
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct MigrationStateDerive {
+ input: DeriveInput,
+ fields: Vec<MigrationStateField>,
+ container_attrs: ContainerAttrs,
+}
+
+impl MigrationStateDerive {
+ fn parse(input: DeriveInput) -> Result<Self> {
+ let container_attrs = ContainerAttrs::parse(&input.attrs)?;
+ let fields = get_fields(&input, "ToMigrationState")?;
+ let fields = Self::process_fields(fields)?;
+
+ Ok(Self {
+ input,
+ fields,
+ container_attrs,
+ })
+ }
+
+ fn process_fields(
+ fields: &syn::punctuated::Punctuated<Field, syn::token::Comma>,
+ ) -> Result<Vec<MigrationStateField>> {
+ let processed = fields
+ .iter()
+ .map(|field| {
+ let attrs = FieldAttrs::parse(&field.attrs)?;
+ Ok((field, attrs))
+ })
+ .collect::<Result<Vec<_>>>()?
+ .into_iter()
+ .filter(|(_, attrs)| !matches!(attrs.conversion, ConversionMode::Omit))
+ .map(|(field, attrs)| MigrationStateField {
+ name: field.ident.as_ref().unwrap().clone(),
+ original_type: field.ty.clone(),
+ attrs,
+ })
+ .collect();
+
+ Ok(processed)
+ }
+
+ fn migration_state_name(&self) -> Cow<'_, Ident> {
+ match &self.container_attrs.rename {
+ Some(rename) => Cow::Borrowed(rename),
+ None => Cow::Owned(format_ident!("{}Migration", &self.input.ident)),
+ }
+ }
+
+ fn generate_migration_state_struct(&self) -> TokenStream {
+ let name = self.migration_state_name();
+ let fields = self
+ .fields
+ .iter()
+ .map(MigrationStateField::generate_migration_state_field);
+
+ quote! {
+ #[derive(Default)]
+ pub struct #name {
+ #(#fields)*
+ }
+ }
+ }
+
+ fn generate_snapshot_migration_state(&self) -> TokenStream {
+ let fields = self
+ .fields
+ .iter()
+ .map(MigrationStateField::generate_snapshot_field);
+
+ quote! {
+ fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), migration::InvalidError> {
+ #(#fields)*
+ Ok(())
+ }
+ }
+ }
+
+ fn generate_restore_migrated_state(&self) -> TokenStream {
+ let names: Vec<_> = self.fields.iter().map(|f| &f.name).collect();
+ let fields = self
+ .fields
+ .iter()
+ .map(MigrationStateField::generate_restore_field);
+
+ // version_id could be used or not depending on conversion attributes
+ quote! {
+ #[allow(clippy::used_underscore_binding)]
+ fn restore_migrated_state_mut(&mut self, source: Self::Migrated, _version_id: u8) -> Result<(), migration::InvalidError> {
+ let Self::Migrated { #(#names),* } = source;
+ #(#fields)*
+ Ok(())
+ }
+ }
+ }
+
+ fn generate(&self) -> TokenStream {
+ let struct_name = &self.input.ident;
+ let generics = &self.input.generics;
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+ let name = self.migration_state_name();
+ let migration_state_struct = self.generate_migration_state_struct();
+ let snapshot_impl = self.generate_snapshot_migration_state();
+ let restore_impl = self.generate_restore_migrated_state();
+
+ quote! {
+ #migration_state_struct
+
+ impl #impl_generics ToMigrationState for #struct_name #ty_generics #where_clause {
+ type Migrated = #name;
+
+ #snapshot_impl
+
+ #restore_impl
+ }
+ }
+ }
+
+ pub fn expand(input: DeriveInput) -> Result<TokenStream> {
+ let tokens = Self::parse(input)?.generate();
+ Ok(tokens)
+ }
+}
diff --git a/rust/qemu-macros/src/tests.rs b/rust/qemu-macros/src/tests.rs
index ac998d2..6569141 100644
--- a/rust/qemu-macros/src/tests.rs
+++ b/rust/qemu-macros/src/tests.rs
@@ -7,7 +7,7 @@ use quote::quote;
use super::*;
macro_rules! derive_compile_fail {
- ($derive_fn:ident, $input:expr, $($error_msg:expr),+ $(,)?) => {{
+ ($derive_fn:path, $input:expr, $($error_msg:expr),+ $(,)?) => {{
let input: proc_macro2::TokenStream = $input;
let error_msg = &[$( quote! { ::core::compile_error! { $error_msg } } ),*];
let derive_fn: fn(input: syn::DeriveInput) -> Result<proc_macro2::TokenStream, syn::Error> =
@@ -24,7 +24,7 @@ macro_rules! derive_compile_fail {
}
macro_rules! derive_compile {
- ($derive_fn:ident, $input:expr, $($expected:tt)*) => {{
+ ($derive_fn:path, $input:expr, $($expected:tt)*) => {{
let input: proc_macro2::TokenStream = $input;
let expected: proc_macro2::TokenStream = $($expected)*;
let derive_fn: fn(input: syn::DeriveInput) -> Result<proc_macro2::TokenStream, syn::Error> =
@@ -345,3 +345,112 @@ fn test_derive_tryinto() {
}
);
}
+
+#[test]
+fn test_derive_to_migration_state() {
+ derive_compile_fail!(
+ MigrationStateDerive::expand,
+ quote! {
+ struct MyStruct {
+ #[migration_state(omit, clone)]
+ bad: u32,
+ }
+ },
+ "ToMigrationState: omit cannot be used with other attributes"
+ );
+ derive_compile_fail!(
+ MigrationStateDerive::expand,
+ quote! {
+ struct MyStruct {
+ #[migration_state(into)]
+ bad: u32,
+ }
+ },
+ "unexpected end of input, expected parentheses"
+ );
+ derive_compile_fail!(
+ MigrationStateDerive::expand,
+ quote! {
+ struct MyStruct {
+ #[migration_state(into(String), try_into(String))]
+ bad: &'static str,
+ }
+ },
+ "ToMigrationState: into and try_into attributes cannot be used together"
+ );
+ derive_compile!(
+ MigrationStateDerive::expand,
+ quote! {
+ #[migration_state(rename = CustomMigration)]
+ struct MyStruct {
+ #[migration_state(omit)]
+ runtime_field: u32,
+
+ #[migration_state(clone)]
+ shared_data: String,
+
+ #[migration_state(into(Cow<'static, str>), clone)]
+ converted_field: String,
+
+ #[migration_state(try_into(i8))]
+ fallible_field: u32,
+
+ nested_field: NestedStruct,
+ simple_field: u32,
+ }
+ },
+ quote! {
+ #[derive(Default)]
+ pub struct CustomMigration {
+ pub shared_data: String,
+ pub converted_field: Cow<'static, str>,
+ pub fallible_field: i8,
+ pub nested_field: <NestedStruct as ToMigrationState>::Migrated,
+ pub simple_field: <u32 as ToMigrationState>::Migrated,
+ }
+ impl ToMigrationState for MyStruct {
+ type Migrated = CustomMigration;
+ fn snapshot_migration_state(
+ &self,
+ target: &mut Self::Migrated
+ ) -> Result<(), migration::InvalidError> {
+ target.shared_data = self.shared_data.clone();
+ target.converted_field = self.converted_field.clone().into();
+ target.fallible_field = self
+ .fallible_field
+ .try_into()
+ .map_err(|_| migration::InvalidError)?;
+ self.nested_field
+ .snapshot_migration_state(&mut target.nested_field)?;
+ self.simple_field
+ .snapshot_migration_state(&mut target.simple_field)?;
+ Ok(())
+ }
+ #[allow(clippy::used_underscore_binding)]
+ fn restore_migrated_state_mut(
+ &mut self,
+ source: Self::Migrated,
+ _version_id: u8
+ ) -> Result<(), migration::InvalidError> {
+ let Self::Migrated {
+ shared_data,
+ converted_field,
+ fallible_field,
+ nested_field,
+ simple_field
+ } = source;
+ self.shared_data = shared_data;
+ self.converted_field = converted_field.into();
+ self.fallible_field = fallible_field
+ .try_into()
+ .map_err(|_| migration::InvalidError)?;
+ self.nested_field
+ .restore_migrated_state_mut(nested_field, _version_id)?;
+ self.simple_field
+ .restore_migrated_state_mut(simple_field, _version_id)?;
+ Ok(())
+ }
+ }
+ }
+ );
+}
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 4f769d6..0d57081 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -2123,7 +2123,7 @@ static int kvm_arch_put_sve(CPUState *cs)
return 0;
}
-int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
+int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)
{
uint64_t val;
uint32_t fpr;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ab18de8..455caff 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1397,7 +1397,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.type = CPUID_FEATURE_WORD,
.feat_names = {
"no-nested-data-bp", "fs-gs-base-ns", "lfence-always-serializing", NULL,
- NULL, NULL, "null-sel-clr-base", NULL,
+ NULL, "verw-clear", "null-sel-clr-base", NULL,
"auto-ibrs", NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
@@ -1415,6 +1415,22 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.tcg_features = 0,
.unmigratable_flags = 0,
},
+ [FEAT_8000_0021_ECX] = {
+ .type = CPUID_FEATURE_WORD,
+ .feat_names = {
+ NULL, "tsa-sq-no", "tsa-l1-no", NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ },
+ .cpuid = { .eax = 0x80000021, .reg = R_ECX, },
+ .tcg_features = 0,
+ .unmigratable_flags = 0,
+ },
[FEAT_8000_0022_EAX] = {
.type = CPUID_FEATURE_WORD,
.feat_names = {
@@ -8526,6 +8542,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*eax = *ebx = *ecx = *edx = 0;
*eax = env->features[FEAT_8000_0021_EAX];
*ebx = env->features[FEAT_8000_0021_EBX];
+ *ecx = env->features[FEAT_8000_0021_ECX];
break;
case 0x80000022:
*eax = *ebx = *ecx = *edx = 0;
@@ -8632,7 +8649,11 @@ static void x86_cpu_reset_hold(Object *obj, ResetType type)
env->idt.limit = 0xffff;
env->gdt.limit = 0xffff;
+#if defined(CONFIG_USER_ONLY)
+ env->ldt.limit = 0;
+#else
env->ldt.limit = 0xffff;
+#endif
env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
env->tr.limit = 0xffff;
env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 8b7c173..ce94886 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -643,6 +643,7 @@ typedef enum FeatureWord {
FEAT_8000_0008_EBX, /* CPUID[8000_0008].EBX */
FEAT_8000_0021_EAX, /* CPUID[8000_0021].EAX */
FEAT_8000_0021_EBX, /* CPUID[8000_0021].EBX */
+ FEAT_8000_0021_ECX, /* CPUID[8000_0021].ECX */
FEAT_8000_0022_EAX, /* CPUID[8000_0022].EAX */
FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
FEAT_KVM, /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
@@ -1103,6 +1104,8 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
#define CPUID_8000_0021_EAX_FS_GS_BASE_NS (1U << 1)
/* LFENCE is always serializing */
#define CPUID_8000_0021_EAX_LFENCE_ALWAYS_SERIALIZING (1U << 2)
+/* Memory form of VERW mitigates TSA */
+#define CPUID_8000_0021_EAX_VERW_CLEAR (1U << 5)
/* Null Selector Clears Base */
#define CPUID_8000_0021_EAX_NULL_SEL_CLR_BASE (1U << 6)
/* Automatic IBRS */
@@ -1126,6 +1129,11 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
*/
#define CPUID_8000_0021_EBX_RAPSIZE (8U << 16)
+/* CPU is not vulnerable TSA SA-SQ attack */
+#define CPUID_8000_0021_ECX_TSA_SQ_NO (1U << 1)
+/* CPU is not vulnerable TSA SA-L1 attack */
+#define CPUID_8000_0021_ECX_TSA_L1_NO (1U << 2)
+
/* Performance Monitoring Version 2 */
#define CPUID_8000_0022_EAX_PERFMON_V2 (1U << 0)
diff --git a/target/i386/helper.c b/target/i386/helper.c
index 651041c..72b2e19 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -621,6 +621,10 @@ void do_cpu_init(X86CPU *cpu)
void do_cpu_sipi(X86CPU *cpu)
{
+ CPUX86State *env = &cpu->env;
+ if (env->hflags & HF_SMM_MASK) {
+ return;
+ }
apic_sipi(cpu->apic_state);
}
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index db40caa..309f043 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -653,6 +653,23 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index)
must_be_one = (uint32_t)value;
can_be_one = (uint32_t)(value >> 32);
return can_be_one & ~must_be_one;
+ case MSR_IA32_ARCH_CAPABILITIES:
+ /*
+ * Special handling for fb-clear bit in ARCH_CAPABILITIES MSR.
+ * KVM will only report the bit if it is enabled in the host,
+ * but, for live migration capability purposes, we want to
+ * expose the bit to the guest even if it is disabled in the
+ * host, as long as the host itself is not vulnerable to
+ * the issue that the fb-clear bit is meant to mitigate.
+ */
+ if ((value & MSR_ARCH_CAP_MDS_NO) &&
+ (value & MSR_ARCH_CAP_TAA_NO) &&
+ (value & MSR_ARCH_CAP_SBDR_SSDP_NO) &&
+ (value & MSR_ARCH_CAP_FBSDP_NO) &&
+ (value & MSR_ARCH_CAP_PSDP_NO)) {
+ value |= MSR_ARCH_CAP_FB_CLEAR;
+ }
+ return value;
default:
return value;
@@ -3907,7 +3924,7 @@ static void kvm_init_msrs(X86CPU *cpu)
assert(kvm_buf_set_msrs(cpu) == 0);
}
-static int kvm_put_msrs(X86CPU *cpu, int level)
+static int kvm_put_msrs(X86CPU *cpu, KvmPutState level)
{
CPUX86State *env = &cpu->env;
int i;
@@ -5027,7 +5044,7 @@ static int kvm_get_apic(X86CPU *cpu)
return 0;
}
-static int kvm_put_vcpu_events(X86CPU *cpu, int level)
+static int kvm_put_vcpu_events(X86CPU *cpu, KvmPutState level)
{
CPUState *cs = CPU(cpu);
CPUX86State *env = &cpu->env;
@@ -5270,7 +5287,7 @@ static int kvm_get_nested_state(X86CPU *cpu)
return ret;
}
-int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp)
+int kvm_arch_put_registers(CPUState *cpu, KvmPutState level, Error **errp)
{
X86CPU *x86_cpu = X86_CPU(cpu);
int ret;
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 5103865..a50f57d 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1541,7 +1541,7 @@ static void decode_group4_5(DisasContext *s, CPUX86State *env, X86OpEntry *entry
[0x0b] = X86_OP_ENTRYr(CALLF_m, M,p),
[0x0c] = X86_OP_ENTRYr(JMP_m, E,f64, zextT0),
[0x0d] = X86_OP_ENTRYr(JMPF_m, M,p),
- [0x0e] = X86_OP_ENTRYr(PUSH, E,f64),
+ [0x0e] = X86_OP_ENTRYr(PUSH, E,d64),
};
int w = (*b & 1);
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 071f3fb..f49fe85 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -456,7 +456,7 @@ static void switch_tss_ra(CPUX86State *env, int tss_selector,
new_segs[i] = access_ldw(&new, tss_base + (0x48 + i * 4));
}
new_ldt = access_ldw(&new, tss_base + 0x60);
- new_trap = access_ldl(&new, tss_base + 0x64);
+ new_trap = access_ldw(&new, tss_base + 0x64) & 1;
} else {
/* 16 bit */
new_cr3 = 0;
diff --git a/target/i386/tcg/system/excp_helper.c b/target/i386/tcg/system/excp_helper.c
index 50040f6..f622b5d 100644
--- a/target/i386/tcg/system/excp_helper.c
+++ b/target/i386/tcg/system/excp_helper.c
@@ -592,7 +592,8 @@ static bool get_physical_address(CPUX86State *env, vaddr addr,
if (sext != 0 && sext != -1) {
*err = (TranslateFault){
.exception_index = EXCP0D_GPF,
- .cr2 = addr,
+ /* non-canonical #GP doesn't change CR2 */
+ .cr2 = env->cr[2],
};
return false;
}
diff --git a/target/i386/tcg/system/seg_helper.c b/target/i386/tcg/system/seg_helper.c
index 38072e5..8c7856b 100644
--- a/target/i386/tcg/system/seg_helper.c
+++ b/target/i386/tcg/system/seg_helper.c
@@ -182,6 +182,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
apic_poll_irq(cpu->apic_state);
break;
case CPU_INTERRUPT_SIPI:
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_SIPI);
do_cpu_sipi(cpu);
break;
case CPU_INTERRUPT_SMI:
diff --git a/target/i386/tcg/system/smm_helper.c b/target/i386/tcg/system/smm_helper.c
index 251eb78..fb028a8 100644
--- a/target/i386/tcg/system/smm_helper.c
+++ b/target/i386/tcg/system/smm_helper.c
@@ -168,7 +168,7 @@ void do_smm_enter(X86CPU *cpu)
env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK |
CR0_PG_MASK));
cpu_x86_update_cr4(env, 0);
- env->dr[7] = 0x00000400;
+ helper_set_dr(env, 7, 0x00000400);
cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
0xffffffff,
@@ -233,8 +233,8 @@ void helper_rsm(CPUX86State *env)
env->eip = x86_ldq_phys(cs, sm_state + 0x7f78);
cpu_load_eflags(env, x86_ldl_phys(cs, sm_state + 0x7f70),
~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
- env->dr[6] = x86_ldl_phys(cs, sm_state + 0x7f68);
- env->dr[7] = x86_ldl_phys(cs, sm_state + 0x7f60);
+ helper_set_dr(env, 6, x86_ldl_phys(cs, sm_state + 0x7f68));
+ helper_set_dr(env, 7, x86_ldl_phys(cs, sm_state + 0x7f60));
cpu_x86_update_cr4(env, x86_ldl_phys(cs, sm_state + 0x7f48));
cpu_x86_update_cr3(env, x86_ldq_phys(cs, sm_state + 0x7f50));
@@ -268,8 +268,8 @@ void helper_rsm(CPUX86State *env)
env->regs[R_EDX] = x86_ldl_phys(cs, sm_state + 0x7fd8);
env->regs[R_ECX] = x86_ldl_phys(cs, sm_state + 0x7fd4);
env->regs[R_EAX] = x86_ldl_phys(cs, sm_state + 0x7fd0);
- env->dr[6] = x86_ldl_phys(cs, sm_state + 0x7fcc);
- env->dr[7] = x86_ldl_phys(cs, sm_state + 0x7fc8);
+ helper_set_dr(env, 6, x86_ldl_phys(cs, sm_state + 0x7fcc));
+ helper_set_dr(env, 7, x86_ldl_phys(cs, sm_state + 0x7fc8));
env->tr.selector = x86_ldl_phys(cs, sm_state + 0x7fc4) & 0xffff;
env->tr.base = x86_ldl_phys(cs, sm_state + 0x7f64);
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index e5ea2db..4e4f4e7 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -325,7 +325,7 @@ static int kvm_loongarch_get_csr(CPUState *cs)
return ret;
}
-static int kvm_loongarch_put_csr(CPUState *cs, int level)
+static int kvm_loongarch_put_csr(CPUState *cs, KvmPutState level)
{
int ret = 0;
CPULoongArchState *env = cpu_env(cs);
@@ -763,7 +763,7 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp)
return ret;
}
-int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
+int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)
{
int ret;
static int once;
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
index 450947c..912cd5d 100644
--- a/target/mips/kvm.c
+++ b/target/mips/kvm.c
@@ -590,7 +590,7 @@ static void kvm_mips_update_state(void *opaque, bool running, RunState state)
}
}
-static int kvm_mips_put_fpu_registers(CPUState *cs, int level)
+static int kvm_mips_put_fpu_registers(CPUState *cs, KvmPutState level)
{
CPUMIPSState *env = cpu_env(cs);
int err, ret = 0;
@@ -749,7 +749,7 @@ static int kvm_mips_get_fpu_registers(CPUState *cs)
}
-static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
+static int kvm_mips_put_cp0_registers(CPUState *cs, KvmPutState level)
{
CPUMIPSState *env = cpu_env(cs);
int err, ret = 0;
@@ -1177,7 +1177,7 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
return ret;
}
-int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
+int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)
{
CPUMIPSState *env = cpu_env(cs);
struct kvm_regs regs;
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 2521ff6..cd60893 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -907,7 +907,7 @@ int kvmppc_put_books_sregs(PowerPCCPU *cpu)
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs);
}
-int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
+int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 187c2c9..75ca3fb 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -1369,7 +1369,7 @@ int kvm_riscv_sync_mpstate_to_kvm(RISCVCPU *cpu, int state)
return 0;
}
-int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
+int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)
{
int ret = 0;
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index 491cc5f..916dac1 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -468,7 +468,7 @@ static int can_sync_regs(CPUState *cs, int regs)
#define KVM_SYNC_REQUIRED_REGS (KVM_SYNC_GPRS | KVM_SYNC_ACRS | \
KVM_SYNC_CRS | KVM_SYNC_PREFIX)
-int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
+int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)
{
CPUS390XState *env = cpu_env(cs);
struct kvm_fpu fpu = {};
diff --git a/tests/functional/aarch64/test_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py
index a3db267..0ced1a2 100755
--- a/tests/functional/aarch64/test_aspeed_ast2700.py
+++ b/tests/functional/aarch64/test_aspeed_ast2700.py
@@ -37,26 +37,21 @@ class AST2x00MachineSDK(QemuSystemTest):
wait_for_console_pattern(self, 'done')
wait_for_console_pattern(self, 'Jumping to BL31 (Trusted Firmware-A)')
- def verify_openbmc_boot_and_login(self, name):
+ def verify_openbmc_boot_start(self):
wait_for_console_pattern(self, 'U-Boot 2023.10')
wait_for_console_pattern(self, '## Loading kernel from FIT Image')
- wait_for_console_pattern(self, 'Starting kernel ...')
+ wait_for_console_pattern(self, 'Linux version ')
+
+ def verify_openbmc_boot_and_login(self, name):
+ self.verify_openbmc_boot_start()
wait_for_console_pattern(self, f'{name} login:')
exec_command_and_wait_for_pattern(self, 'root', 'Password:')
exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#')
- ASSET_SDK_V906_AST2700 = Asset(
- 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2700-a0-default-obmc.tar.gz',
- '7247b6f19dbfb700686f8d9f723ac23f3eb229226c0589cb9b06b80d1b61f3cb')
-
- ASSET_SDK_V906_AST2700A1 = Asset(
- 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2700-default-obmc.tar.gz',
- 'f1d53e0be8a404ecce3e105f72bc50fa4e090ad13160ffa91b10a6e0233a9dc6')
-
- ASSET_SDK_V907_AST2700A1_VBOOROM = Asset(
- 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.07/ast2700-default-obmc.tar.gz',
- '6e9e0c4b13e0f26040eca3f4a7f17cf09fc0f5c37c820500ff79370cc3c44add')
+ ASSET_SDK_V908_AST2700A1 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2700-default-obmc.tar.gz',
+ 'eac3dc409b7ea3cd4b03d4792d3cebd469792ad893cb51e1d15f0fc20bd1e2cd')
def do_ast2700_i2c_test(self):
exec_command_and_wait_for_pattern(self,
@@ -69,6 +64,19 @@ class AST2x00MachineSDK(QemuSystemTest):
exec_command_and_wait_for_pattern(self,
'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000')
+ def do_ast2700_pcie_test(self):
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 0002:00:00.0',
+ '0002:00:00.0 PCI bridge: '
+ 'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 0002:01:00.0',
+ '0002:01:00.0 Ethernet controller: '
+ 'Intel Corporation 82574L Gigabit Network Connection')
+ exec_command_and_wait_for_pattern(self,
+ 'ip addr show dev eth2',
+ 'inet 10.0.2.15/24')
+
def start_ast2700_test(self, name):
num_cpu = 4
uboot_size = os.path.getsize(self.scratch_file(name,
@@ -115,30 +123,28 @@ class AST2x00MachineSDK(QemuSystemTest):
self.do_test_aarch64_aspeed_sdk_start(
self.scratch_file(name, 'image-bmc'))
- def test_aarch64_ast2700a0_evb_sdk_v09_06(self):
- self.set_machine('ast2700a0-evb')
-
- self.archive_extract(self.ASSET_SDK_V906_AST2700)
- self.start_ast2700_test('ast2700-a0-default')
- self.verify_openbmc_boot_and_login('ast2700-a0-default')
- self.do_ast2700_i2c_test()
-
- def test_aarch64_ast2700a1_evb_sdk_v09_06(self):
+ def test_aarch64_ast2700a1_evb_sdk_v09_08(self):
self.set_machine('ast2700a1-evb')
+ self.require_netdev('user')
- self.archive_extract(self.ASSET_SDK_V906_AST2700A1)
+ self.archive_extract(self.ASSET_SDK_V908_AST2700A1)
+ self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2')
+ self.vm.add_args('-netdev', 'user,id=net1')
self.start_ast2700_test('ast2700-default')
self.verify_openbmc_boot_and_login('ast2700-default')
self.do_ast2700_i2c_test()
+ self.do_ast2700_pcie_test()
- def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_07(self):
+ def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_08(self):
self.set_machine('ast2700a1-evb')
+ self.require_netdev('user')
- self.archive_extract(self.ASSET_SDK_V907_AST2700A1_VBOOROM)
+ self.archive_extract(self.ASSET_SDK_V908_AST2700A1)
+ self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2')
+ self.vm.add_args('-netdev', 'user,id=net1')
self.start_ast2700_test_vbootrom('ast2700-default')
self.verify_vbootrom_firmware_flow()
- self.verify_openbmc_boot_and_login('ast2700-default')
- self.do_ast2700_i2c_test()
+ self.verify_openbmc_boot_start()
if __name__ == '__main__':
QemuSystemTest.main()
diff --git a/tests/functional/aarch64/test_aspeed_ast2700fc.py b/tests/functional/aarch64/test_aspeed_ast2700fc.py
index b85370e..28b6661 100755
--- a/tests/functional/aarch64/test_aspeed_ast2700fc.py
+++ b/tests/functional/aarch64/test_aspeed_ast2700fc.py
@@ -20,6 +20,8 @@ class AST2x00MachineSDK(QemuSystemTest):
self.vm.set_console()
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
+ self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2')
+ self.vm.add_args('-netdev', 'user,id=net1')
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
'-net', 'nic', '-net', 'user', '-snapshot')
@@ -49,6 +51,16 @@ class AST2x00MachineSDK(QemuSystemTest):
exec_command_and_wait_for_pattern(self,
'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000')
+ def do_ast2700_pcie_test(self):
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 0002:00:00.0',
+ '0002:00:00.0 PCI bridge: '
+ 'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 0002:01:00.0',
+ '0002:01:00.0 Ethernet controller: '
+ 'Intel Corporation 82574L Gigabit Network Connection')
+
def do_ast2700fc_ssp_test(self):
self.vm.shutdown()
self.vm.set_console(console_index=1)
@@ -128,6 +140,7 @@ class AST2x00MachineSDK(QemuSystemTest):
self.start_ast2700fc_test('ast2700-default')
self.verify_openbmc_boot_and_login('ast2700-default')
self.do_ast2700_i2c_test()
+ self.do_ast2700_pcie_test()
self.do_ast2700fc_ssp_test()
self.do_ast2700fc_tsp_test()
diff --git a/tests/functional/arm/meson.build b/tests/functional/arm/meson.build
index e4e7dba..d1ed076 100644
--- a/tests/functional/arm/meson.build
+++ b/tests/functional/arm/meson.build
@@ -5,7 +5,8 @@ test_arm_timeouts = {
'aspeed_romulus' : 120,
'aspeed_witherspoon' : 120,
'aspeed_ast2500' : 720,
- 'aspeed_ast2600' : 1200,
+ 'aspeed_ast2600_buildroot' : 720,
+ 'aspeed_ast2600_sdk' : 1200,
'aspeed_bletchley' : 480,
'aspeed_catalina' : 480,
'aspeed_gb200nvl_bmc' : 480,
@@ -31,7 +32,8 @@ tests_arm_system_thorough = [
'aspeed_romulus',
'aspeed_witherspoon',
'aspeed_ast2500',
- 'aspeed_ast2600',
+ 'aspeed_ast2600_buildroot',
+ 'aspeed_ast2600_sdk',
'aspeed_bletchley',
'aspeed_catalina',
'aspeed_gb200nvl_bmc',
diff --git a/tests/functional/arm/test_aspeed_ast1030.py b/tests/functional/arm/test_aspeed_ast1030.py
index e47b597..60e2b02 100755
--- a/tests/functional/arm/test_aspeed_ast1030.py
+++ b/tests/functional/arm/test_aspeed_ast1030.py
@@ -13,17 +13,17 @@ from qemu_test import exec_command_and_wait_for_pattern
class AST1030Machine(AspeedTest):
- ASSET_ZEPHYR_3_02 = Asset(
+ ASSET_ZEPHYR_3_03 = Asset(
('https://github.com/AspeedTech-BMC'
- '/zephyr/releases/download/v00.03.02/ast1030-evb-demo.zip'),
- '1ec83caab3ddd5d09481772801be7210e222cb015ce22ec6fffb8a76956dcd4f')
+ '/zephyr/releases/download/v00.03.03/ast1030-evb-demo.zip'),
+ '27cd73cdee6374bceb4ee58b3ace87989fa3f0684f4e612510804b588b24d4e0')
- def test_arm_ast1030_zephyros_3_02(self):
+ def test_arm_ast1030_zephyros_3_03(self):
self.set_machine('ast1030-evb')
- kernel_name = "ast1030-evb-demo-3/zephyr.elf"
+ kernel_name = "ast1030-evb-demo/zephyr.elf"
kernel_file = self.archive_extract(
- self.ASSET_ZEPHYR_3_02, member=kernel_name)
+ self.ASSET_ZEPHYR_3_03, member=kernel_name)
self.vm.set_console()
self.vm.add_args('-kernel', kernel_file, '-nographic')
@@ -72,8 +72,9 @@ class AST1030Machine(AspeedTest):
def test_arm_ast1030_otp_blockdev_device(self):
self.vm.set_machine("ast1030-evb")
- kernel_name = "ast1030-evb-demo-3/zephyr.elf"
- kernel_file = self.archive_extract(self.ASSET_ZEPHYR_3_02, member=kernel_name)
+ kernel_name = "ast1030-evb-demo/zephyr.elf"
+ kernel_file = self.archive_extract(self.ASSET_ZEPHYR_3_03,
+ member=kernel_name)
otp_img = self.generate_otpmem_image()
self.vm.set_console()
diff --git a/tests/functional/arm/test_aspeed_ast2500.py b/tests/functional/arm/test_aspeed_ast2500.py
index 4fdd81e..5efd104 100755
--- a/tests/functional/arm/test_aspeed_ast2500.py
+++ b/tests/functional/arm/test_aspeed_ast2500.py
@@ -37,14 +37,14 @@ class AST2500Machine(AspeedTest):
self.do_test_arm_aspeed_buildroot_poweroff()
- ASSET_SDK_V907_AST2500 = Asset(
- 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.07/ast2500-default-obmc.tar.gz',
- 'd52bcc279a37c8d7679b3e4ef22cc77c36f0f6624c687b37334f798828afb077')
+ ASSET_SDK_V908_AST2500 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2500-default-obmc.tar.gz',
+ 'c0a2ba169efd19be5eb77c50ec2a6afd9d826e196a0be3432f969fc72d4b7c0e')
def test_arm_ast2500_evb_sdk(self):
self.set_machine('ast2500-evb')
- self.archive_extract(self.ASSET_SDK_V907_AST2500)
+ self.archive_extract(self.ASSET_SDK_V908_AST2500)
self.do_test_arm_aspeed_sdk_start(
self.scratch_file("ast2500-default", "image-bmc"))
diff --git a/tests/functional/arm/test_aspeed_ast2600.py b/tests/functional/arm/test_aspeed_ast2600_buildroot.py
index f655c0b..51f2676 100755
--- a/tests/functional/arm/test_aspeed_ast2600.py
+++ b/tests/functional/arm/test_aspeed_ast2600_buildroot.py
@@ -97,80 +97,6 @@ class AST2600Machine(AspeedTest):
self.do_test_arm_aspeed_buildroot_poweroff()
- ASSET_SDK_V907_AST2600 = Asset(
- 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.07/ast2600-default-obmc.tar.gz',
- 'cb6c08595bcbba1672ce716b068ba4e48eda1ed9abe78a07b30392ba2278feba')
-
- def do_ast2600_pcie_test(self):
- exec_command_and_wait_for_pattern(self,
- 'lspci -s 80:00.0',
- '80:00.0 Host bridge: '
- 'ASPEED Technology, Inc. Device 2600')
- exec_command_and_wait_for_pattern(self,
- 'lspci -s 80:08.0',
- '80:08.0 PCI bridge: '
- 'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge')
- exec_command_and_wait_for_pattern(self,
- 'lspci -s 81:00.0',
- '81:00.0 Ethernet controller: '
- 'Intel Corporation 82574L Gigabit Network Connection')
- exec_command_and_wait_for_pattern(self,
- 'ip addr show dev eth4',
- 'inet 10.0.2.15/24')
-
- def test_arm_ast2600_evb_sdk(self):
- self.set_machine('ast2600-evb')
- self.require_netdev('user')
-
- self.archive_extract(self.ASSET_SDK_V907_AST2600)
-
- self.vm.add_args('-device',
- 'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test')
- self.vm.add_args('-device',
- 'ds1338,bus=aspeed.i2c.bus.5,address=0x32')
- self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.0')
- self.vm.add_args('-netdev', 'user,id=net1')
- self.do_test_arm_aspeed_sdk_start(
- self.scratch_file("ast2600-default", "image-bmc"))
-
- self.wait_for_console_pattern('ast2600-default login:')
-
- exec_command_and_wait_for_pattern(self, 'root', 'Password:')
- exec_command_and_wait_for_pattern(self, '0penBmc',
- 'root@ast2600-default:~#')
-
- exec_command_and_wait_for_pattern(self,
- 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device',
- 'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d')
- exec_command_and_wait_for_pattern(self,
- 'cat /sys/class/hwmon/hwmon19/temp1_input', '0')
- self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
- property='temperature', value=18000)
- exec_command_and_wait_for_pattern(self,
- 'cat /sys/class/hwmon/hwmon19/temp1_input', '18000')
-
- exec_command_and_wait_for_pattern(self,
- 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device',
- 'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32')
- year = time.strftime("%Y")
- exec_command_and_wait_for_pattern(self,
- '/sbin/hwclock -f /dev/rtc1', year)
- self.do_ast2600_pcie_test()
-
- def test_arm_ast2600_otp_blockdev_device(self):
- self.vm.set_machine("ast2600-evb")
-
- image_path = self.archive_extract(self.ASSET_SDK_V907_AST2600)
- otp_img = self.generate_otpmem_image()
-
- self.vm.set_console()
- self.vm.add_args(
- "-blockdev", f"driver=file,filename={otp_img},node-name=otp",
- "-global", "aspeed-otp.drive=otp",
- )
- self.do_test_arm_aspeed_sdk_start(
- self.scratch_file("ast2600-default", "image-bmc"))
- self.wait_for_console_pattern("ast2600-default login:")
if __name__ == '__main__':
AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_ast2600_sdk.py b/tests/functional/arm/test_aspeed_ast2600_sdk.py
new file mode 100755
index 0000000..e3d4ed0
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_ast2600_sdk.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import time
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+from qemu_test import exec_command_and_wait_for_pattern
+
+
+class AST2600Machine(AspeedTest):
+
+ ASSET_SDK_V908_AST2600 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2600-default-obmc.tar.gz',
+ 'a0414f14ad696550efe083c2156dbeda855c08cc9ae7f40fe1b41bf292295f82')
+
+ def do_ast2600_pcie_test(self):
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 80:00.0',
+ '80:00.0 Host bridge: '
+ 'ASPEED Technology, Inc. Device 2600')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 80:08.0',
+ '80:08.0 PCI bridge: '
+ 'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 81:00.0',
+ '81:00.0 Ethernet controller: '
+ 'Intel Corporation 82574L Gigabit Network Connection')
+ exec_command_and_wait_for_pattern(self,
+ 'ip addr show dev eth4',
+ 'inet 10.0.2.15/24')
+
+ def test_arm_ast2600_evb_sdk(self):
+ self.set_machine('ast2600-evb')
+ self.require_netdev('user')
+
+ self.archive_extract(self.ASSET_SDK_V908_AST2600)
+
+ self.vm.add_args('-device',
+ 'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test')
+ self.vm.add_args('-device',
+ 'ds1338,bus=aspeed.i2c.bus.5,address=0x32')
+ self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.0')
+ self.vm.add_args('-netdev', 'user,id=net1')
+ self.do_test_arm_aspeed_sdk_start(
+ self.scratch_file("ast2600-default", "image-bmc"))
+
+ self.wait_for_console_pattern('ast2600-default login:')
+
+ exec_command_and_wait_for_pattern(self, 'root', 'Password:')
+ exec_command_and_wait_for_pattern(self, '0penBmc',
+ 'root@ast2600-default:~#')
+
+ exec_command_and_wait_for_pattern(self,
+ 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device',
+ 'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d')
+ exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon19/temp1_input', '0')
+ self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
+ property='temperature', value=18000)
+ exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon19/temp1_input', '18000')
+
+ exec_command_and_wait_for_pattern(self,
+ 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device',
+ 'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32')
+ year = time.strftime("%Y")
+ exec_command_and_wait_for_pattern(self,
+ '/sbin/hwclock -f /dev/rtc1', year)
+ self.do_ast2600_pcie_test()
+
+ def test_arm_ast2600_otp_blockdev_device(self):
+ self.vm.set_machine("ast2600-evb")
+
+ image_path = self.archive_extract(self.ASSET_SDK_V908_AST2600)
+ otp_img = self.generate_otpmem_image()
+
+ self.vm.set_console()
+ self.vm.add_args(
+ "-blockdev", f"driver=file,filename={otp_img},node-name=otp",
+ "-global", "aspeed-otp.drive=otp",
+ )
+ self.do_test_arm_aspeed_sdk_start(
+ self.scratch_file("ast2600-default", "image-bmc"))
+ self.wait_for_console_pattern("ast2600-default login:")
+
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/util/async.c b/util/async.c
index 2719c62..a736d2c 100644
--- a/util/async.c
+++ b/util/async.c
@@ -256,8 +256,9 @@ static int64_t aio_compute_bh_timeout(BHList *head, int timeout)
QEMUBH *bh;
QSLIST_FOREACH_RCU(bh, head, next) {
- if ((bh->flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
- if (bh->flags & BH_IDLE) {
+ int flags = qatomic_load_acquire(&bh->flags);
+ if ((flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
+ if (flags & BH_IDLE) {
/* idle bottom halves will be polled at least
* every 10ms */
timeout = 10000000;
@@ -335,14 +336,16 @@ aio_ctx_check(GSource *source)
aio_notify_accept(ctx);
QSLIST_FOREACH_RCU(bh, &ctx->bh_list, next) {
- if ((bh->flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
+ int flags = qatomic_load_acquire(&bh->flags);
+ if ((flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
return true;
}
}
QSIMPLEQ_FOREACH(s, &ctx->bh_slice_list, next) {
QSLIST_FOREACH_RCU(bh, &s->bh_list, next) {
- if ((bh->flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
+ int flags = qatomic_load_acquire(&bh->flags);
+ if ((flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
return true;
}
}
diff --git a/util/qemu-timer.c b/util/qemu-timer.c
index 1fb48be..56f11b6 100644
--- a/util/qemu-timer.c
+++ b/util/qemu-timer.c
@@ -89,7 +89,7 @@ static inline QEMUClock *qemu_clock_ptr(QEMUClockType type)
return &qemu_clocks[type];
}
-static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
+static bool timer_expired_ns(const QEMUTimer *timer_head, int64_t current_time)
{
return timer_head && (timer_head->expire_time <= current_time);
}
@@ -475,12 +475,12 @@ void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time)
timer_mod_anticipate_ns(ts, expire_time * ts->scale);
}
-bool timer_pending(QEMUTimer *ts)
+bool timer_pending(const QEMUTimer *ts)
{
return ts->expire_time >= 0;
}
-bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
+bool timer_expired(const QEMUTimer *timer_head, int64_t current_time)
{
return timer_expired_ns(timer_head, current_time * timer_head->scale);
}
@@ -649,7 +649,7 @@ void init_clocks(QEMUTimerListNotifyCB *notify_cb)
#endif
}
-uint64_t timer_expire_time_ns(QEMUTimer *ts)
+uint64_t timer_expire_time_ns(const QEMUTimer *ts)
{
return timer_pending(ts) ? ts->expire_time : -1;
}