mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 23:33:54 -06:00
target-arm queue:
* hw/arm/npcm8xx_boards: Correct valid_cpu_types setting of NPCM8XX SoC * arm/hvf: fix crashes when using gdbstub * target/arm/ptw: fix arm_cpu_get_phys_page_attrs_debug * hw/arm/virt: Remove deprecated old versions of 'virt' machine * tests/functional: Add test for imx8mp-evk board with USDHC coverage * hw/arm: Attach PSPI module to NPCM8XX SoC * target/arm: Don't assert() for ISB/SB inside IT block * docs: Don't define duplicate label in qemu-block-drivers.rst.inc * target/arm/kvm: Drop support for kernels without KVM_ARM_PREFERRED_TARGET * hw/pci-host/designware: Fix viewport configuration * hw/gpio/imx_gpio: Fix interpretation of GDIR polarity -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmgaH50ZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3l4ED/0QOV6oev1ILqA1INBjY7Ct VrjzjsynFnUkyU0MLKyuK+mBRYmeR1OWtIRTkbgIsRA23XqV4de/BhGsVCGrRA0r VS/hV2kTQM0GYU2dCr9LpOC3jX0dDzft5uW9GjW/sW9infAwXRwKhGgkIV6q/G5V Y6cMN7UXrOnomF8Spk5VvK8HH9OHV/fuSlWenk9X1bXPpVQ3jymqZ1eRSDXOzDdM uP6lVdI3oHCpRPeXKa1EA8cfQa9M/y9XSzDIrF8OTZKVcIzbX8/XR+y74e4UMIvK DD3nAuAXcezy3286Pu7OfciRBJfq3eFHZVXOKfQWFI3MStPmexKqoHm8JtQxXJOT uJdaugItLahlPtNk41nAydYzYimK/MBKCWAfTqecEhZ9Cd64jeOPM9zXwRkXwyuu n9XQUhm5Ll22urd4q2M8cCxKBP2OoaEBFS4Hn9uDpVDcWpRMLe2DP7ywzZjdLU9b jLSlana5+wpMuwIasXlNzWgT37RA+xlDE2Snaz7K/Z3JV/XNZAZD6WXV72zTzhFs EI10edHI+JXXlbT1Ev/yVv4cN9h/Kr3hyoOKat2ySaomW26H27wNPuvPTto4rCYU 6VQJmJvwPSBWELI5eRbcN269K0ar1UXUsvDsy97cq35me3gFvfAZFksLpnPWKef6 pvwwPuxLWQXs+chepuQyXA== =c21p -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20250506' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * hw/arm/npcm8xx_boards: Correct valid_cpu_types setting of NPCM8XX SoC * arm/hvf: fix crashes when using gdbstub * target/arm/ptw: fix arm_cpu_get_phys_page_attrs_debug * hw/arm/virt: Remove deprecated old versions of 'virt' machine * tests/functional: Add test for imx8mp-evk board with USDHC coverage * hw/arm: Attach PSPI module to NPCM8XX SoC * target/arm: Don't assert() for ISB/SB inside IT block * docs: Don't define duplicate label in qemu-block-drivers.rst.inc * target/arm/kvm: Drop support for kernels without KVM_ARM_PREFERRED_TARGET * hw/pci-host/designware: Fix viewport configuration * hw/gpio/imx_gpio: Fix interpretation of GDIR polarity # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmgaH50ZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3l4ED/0QOV6oev1ILqA1INBjY7Ct # VrjzjsynFnUkyU0MLKyuK+mBRYmeR1OWtIRTkbgIsRA23XqV4de/BhGsVCGrRA0r # VS/hV2kTQM0GYU2dCr9LpOC3jX0dDzft5uW9GjW/sW9infAwXRwKhGgkIV6q/G5V # Y6cMN7UXrOnomF8Spk5VvK8HH9OHV/fuSlWenk9X1bXPpVQ3jymqZ1eRSDXOzDdM # uP6lVdI3oHCpRPeXKa1EA8cfQa9M/y9XSzDIrF8OTZKVcIzbX8/XR+y74e4UMIvK # DD3nAuAXcezy3286Pu7OfciRBJfq3eFHZVXOKfQWFI3MStPmexKqoHm8JtQxXJOT # uJdaugItLahlPtNk41nAydYzYimK/MBKCWAfTqecEhZ9Cd64jeOPM9zXwRkXwyuu # n9XQUhm5Ll22urd4q2M8cCxKBP2OoaEBFS4Hn9uDpVDcWpRMLe2DP7ywzZjdLU9b # jLSlana5+wpMuwIasXlNzWgT37RA+xlDE2Snaz7K/Z3JV/XNZAZD6WXV72zTzhFs # EI10edHI+JXXlbT1Ev/yVv4cN9h/Kr3hyoOKat2ySaomW26H27wNPuvPTto4rCYU # 6VQJmJvwPSBWELI5eRbcN269K0ar1UXUsvDsy97cq35me3gFvfAZFksLpnPWKef6 # pvwwPuxLWQXs+chepuQyXA== # =c21p # -----END PGP SIGNATURE----- # gpg: Signature made Tue 06 May 2025 10:41:33 EDT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [unknown] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20250506' of https://git.linaro.org/people/pmaydell/qemu-arm: (32 commits) hw/arm/virt: Remove deprecated virt-4.0 machine hw/arm/virt: Remove deprecated virt-3.1 machine hw/arm/virt: Remove deprecated virt-3.0 machine hw/arm/virt: Update comment about Multiprocessor Affinity Register hw/gpio/imx_gpio: Fix interpretation of GDIR polarity hw/pci-host/designware: Fix viewport configuration hw/pci-host/designware: Remove unused include target/arm/kvm: Drop support for kernels without KVM_ARM_PREFERRED_TARGET docs: Don't define duplicate label in qemu-block-drivers.rst.inc target/arm: Don't assert() for ISB/SB inside IT block hw/arm: Attach PSPI module to NPCM8XX SoC tests/functional: Add test for imx8mp-evk board with USDHC coverage hw/arm/virt: Remove VirtMachineClass::no_highmem_ecam field hw/arm/virt: Remove deprecated virt-2.12 machine hw/arm/virt: Remove VirtMachineClass::smbios_old_sys_ver field hw/arm/virt: Remove deprecated virt-2.11 machine hw/arm/virt: Remove deprecated virt-2.10 machine hw/arm/virt: Remove deprecated virt-2.9 machine hw/arm/virt: Remove VirtMachineClass::claim_edge_triggered_timers field hw/arm/virt: Remove deprecated virt-2.8 machine ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
57b6f8d07f
20 changed files with 188 additions and 249 deletions
|
@ -842,6 +842,7 @@ F: include/hw/arm/fsl-imx8mp.h
|
|||
F: include/hw/misc/imx8mp_*.h
|
||||
F: include/hw/pci-host/fsl_imx8m_phy.h
|
||||
F: docs/system/arm/imx8mp-evk.rst
|
||||
F: tests/functional/test_aarch64_imx8mp_evk.py
|
||||
F: tests/qtest/rs5c372-test.c
|
||||
|
||||
MPS2 / MPS3
|
||||
|
|
|
@ -58,8 +58,13 @@ int hvf_sw_breakpoints_active(CPUState *cpu)
|
|||
return !QTAILQ_EMPTY(&hvf_state->hvf_sw_breakpoints);
|
||||
}
|
||||
|
||||
int hvf_update_guest_debug(CPUState *cpu)
|
||||
static void do_hvf_update_guest_debug(CPUState *cpu, run_on_cpu_data arg)
|
||||
{
|
||||
hvf_arch_update_guest_debug(cpu);
|
||||
}
|
||||
|
||||
int hvf_update_guest_debug(CPUState *cpu)
|
||||
{
|
||||
run_on_cpu(cpu, do_hvf_update_guest_debug, RUN_ON_CPU_NULL);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ yet, so sometimes the source code is all you have.
|
|||
* `monitor <https://gitlab.com/qemu-project/qemu/-/tree/master/monitor>`_:
|
||||
`Monitor <QEMU monitor>` implementation (HMP & QMP).
|
||||
* `nbd <https://gitlab.com/qemu-project/qemu/-/tree/master/nbd>`_:
|
||||
QEMU `NBD (Network Block Device) <nbd>` server.
|
||||
QEMU NBD (Network Block Device) server.
|
||||
* `net <https://gitlab.com/qemu-project/qemu/-/tree/master/net>`_:
|
||||
Network (host) support.
|
||||
* `pc-bios <https://gitlab.com/qemu-project/qemu/-/tree/master/pc-bios>`_:
|
||||
|
|
|
@ -500,8 +500,6 @@ What you should *never* do:
|
|||
- expect it to work when loadvm'ing
|
||||
- write to the FAT directory on the host system while accessing it with the guest system
|
||||
|
||||
.. _nbd:
|
||||
|
||||
NBD access
|
||||
~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -67,6 +67,9 @@
|
|||
/* SDHCI Modules */
|
||||
#define NPCM8XX_MMC_BA 0xf0842000
|
||||
|
||||
/* PSPI Modules */
|
||||
#define NPCM8XX_PSPI_BA 0xf0201000
|
||||
|
||||
/* Run PLL1 at 1600 MHz */
|
||||
#define NPCM8XX_PLLCON1_FIXUP_VAL 0x00402101
|
||||
/* Run the CPU from PLL1 and UART from PLL2 */
|
||||
|
@ -83,6 +86,7 @@ enum NPCM8xxInterrupt {
|
|||
NPCM8XX_PECI_IRQ = 6,
|
||||
NPCM8XX_KCS_HIB_IRQ = 9,
|
||||
NPCM8XX_MMC_IRQ = 26,
|
||||
NPCM8XX_PSPI_IRQ = 28,
|
||||
NPCM8XX_TIMER0_IRQ = 32, /* Timer Module 0 */
|
||||
NPCM8XX_TIMER1_IRQ,
|
||||
NPCM8XX_TIMER2_IRQ,
|
||||
|
@ -441,6 +445,7 @@ static void npcm8xx_init(Object *obj)
|
|||
}
|
||||
|
||||
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
|
||||
object_initialize_child(obj, "pspi", &s->pspi, TYPE_NPCM_PSPI);
|
||||
}
|
||||
|
||||
static void npcm8xx_realize(DeviceState *dev, Error **errp)
|
||||
|
@ -705,6 +710,11 @@ static void npcm8xx_realize(DeviceState *dev, Error **errp)
|
|||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0,
|
||||
npcm8xx_irq(s, NPCM8XX_MMC_IRQ));
|
||||
|
||||
/* PSPI */
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->pspi), &error_abort);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->pspi), 0, NPCM8XX_PSPI_BA);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pspi), 0,
|
||||
npcm8xx_irq(s, NPCM8XX_PSPI_IRQ));
|
||||
|
||||
create_unimplemented_device("npcm8xx.shm", 0xc0001000, 4 * KiB);
|
||||
create_unimplemented_device("npcm8xx.gicextra", 0xdfffa000, 24 * KiB);
|
||||
|
@ -720,7 +730,6 @@ static void npcm8xx_realize(DeviceState *dev, Error **errp)
|
|||
create_unimplemented_device("npcm8xx.siox[1]", 0xf0101000, 4 * KiB);
|
||||
create_unimplemented_device("npcm8xx.siox[2]", 0xf0102000, 4 * KiB);
|
||||
create_unimplemented_device("npcm8xx.tmps", 0xf0188000, 4 * KiB);
|
||||
create_unimplemented_device("npcm8xx.pspi", 0xf0201000, 4 * KiB);
|
||||
create_unimplemented_device("npcm8xx.viru1", 0xf0204000, 4 * KiB);
|
||||
create_unimplemented_device("npcm8xx.viru2", 0xf0205000, 4 * KiB);
|
||||
create_unimplemented_device("npcm8xx.jtm1", 0xf0208000, 4 * KiB);
|
||||
|
|
|
@ -213,7 +213,7 @@ static void npcm8xx_machine_class_init(ObjectClass *oc, const void *data)
|
|||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
static const char * const valid_cpu_types[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-a9"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a35"),
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -537,15 +537,12 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
static void
|
||||
build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
{
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
||||
/*
|
||||
* Table 5-117 Flag Definitions
|
||||
* set only "Timer interrupt Mode" and assume "Timer Interrupt
|
||||
* polarity" bit as '0: Interrupt is Active high'
|
||||
*/
|
||||
uint32_t irqflags = vmc->claim_edge_triggered_timers ?
|
||||
1 : /* Interrupt is Edge triggered */
|
||||
0; /* Interrupt is Level triggered */
|
||||
const uint32_t irqflags = 0; /* Interrupt is Level triggered */
|
||||
AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
|
||||
.oem_table_id = vms->oem_table_id };
|
||||
|
||||
|
@ -670,7 +667,6 @@ static void
|
|||
build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
{
|
||||
int i;
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
||||
const MemMapEntry *memmap = vms->memmap;
|
||||
AcpiTable table = { .sig = "APIC", .rev = 4, .oem_id = vms->oem_id,
|
||||
.oem_table_id = vms->oem_table_id };
|
||||
|
@ -741,7 +737,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
memmap[VIRT_HIGH_GIC_REDIST2].size);
|
||||
}
|
||||
|
||||
if (its_class_name() && !vmc->no_its) {
|
||||
if (its_class_name()) {
|
||||
/*
|
||||
* ACPI spec, Revision 6.0 Errata A
|
||||
* (original 6.0 definition has invalid Length)
|
||||
|
@ -973,7 +969,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
|||
vms->oem_table_id);
|
||||
}
|
||||
|
||||
if (its_class_name() && !vmc->no_its) {
|
||||
if (its_class_name()) {
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_iort(tables_blob, tables->linker, vms);
|
||||
}
|
||||
|
|
153
hw/arm/virt.c
153
hw/arm/virt.c
|
@ -370,14 +370,9 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
|
|||
* the correct information.
|
||||
*/
|
||||
ARMCPU *armcpu;
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
||||
uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
|
||||
MachineState *ms = MACHINE(vms);
|
||||
|
||||
if (vmc->claim_edge_triggered_timers) {
|
||||
irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
|
||||
}
|
||||
|
||||
if (vms->gic_version == VIRT_GIC_VERSION_2) {
|
||||
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
|
||||
GIC_FDT_IRQ_PPI_CPU_WIDTH,
|
||||
|
@ -1704,7 +1699,6 @@ static void virt_build_smbios(VirtMachineState *vms)
|
|||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(vms);
|
||||
MachineState *ms = MACHINE(vms);
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
||||
uint8_t *smbios_tables, *smbios_anchor;
|
||||
size_t smbios_tables_len, smbios_anchor_len;
|
||||
struct smbios_phys_mem_area mem_array;
|
||||
|
@ -1714,8 +1708,7 @@ static void virt_build_smbios(VirtMachineState *vms)
|
|||
product = "KVM Virtual Machine";
|
||||
}
|
||||
|
||||
smbios_set_defaults("QEMU", product,
|
||||
vmc->smbios_old_sys_ver ? "1.0" : mc->name);
|
||||
smbios_set_defaults("QEMU", product, mc->name);
|
||||
|
||||
/* build the array of physical mem area from base_memmap */
|
||||
mem_array.address = vms->memmap[VIRT_MEM].base;
|
||||
|
@ -1770,24 +1763,18 @@ void virt_machine_done(Notifier *notifier, void *data)
|
|||
|
||||
static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
|
||||
{
|
||||
uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
||||
uint8_t clustersz;
|
||||
|
||||
if (!vmc->disallow_affinity_adjustment) {
|
||||
/* Adjust MPIDR like 64-bit KVM hosts, which incorporate the
|
||||
* GIC's target-list limitations. 32-bit KVM hosts currently
|
||||
* always create clusters of 4 CPUs, but that is expected to
|
||||
* change when they gain support for gicv3. When KVM is enabled
|
||||
* it will override the changes we make here, therefore our
|
||||
* purposes are to make TCG consistent (with 64-bit KVM hosts)
|
||||
* and to improve SGI efficiency.
|
||||
*/
|
||||
if (vms->gic_version == VIRT_GIC_VERSION_2) {
|
||||
clustersz = GIC_TARGETLIST_BITS;
|
||||
} else {
|
||||
clustersz = GICV3_TARGETLIST_BITS;
|
||||
}
|
||||
/*
|
||||
* Adjust MPIDR to make TCG consistent (with 64-bit KVM hosts)
|
||||
* and to improve SGI efficiency.
|
||||
*/
|
||||
if (vms->gic_version == VIRT_GIC_VERSION_2) {
|
||||
clustersz = GIC_TARGETLIST_BITS;
|
||||
} else {
|
||||
clustersz = GICV3_TARGETLIST_BITS;
|
||||
}
|
||||
|
||||
return arm_build_mp_affinity(idx, clustersz);
|
||||
}
|
||||
|
||||
|
@ -2273,10 +2260,6 @@ static void machvirt_init(MachineState *machine)
|
|||
object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL);
|
||||
}
|
||||
|
||||
if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) {
|
||||
object_property_set_bool(cpuobj, "pmu", false, NULL);
|
||||
}
|
||||
|
||||
if (vmc->no_tcg_lpa2 && object_property_find(cpuobj, "lpa2")) {
|
||||
object_property_set_bool(cpuobj, "lpa2", false, NULL);
|
||||
}
|
||||
|
@ -3348,21 +3331,17 @@ static void virt_instance_init(Object *obj)
|
|||
vms->highmem_compact = !vmc->no_highmem_compact;
|
||||
vms->gic_version = VIRT_GIC_VERSION_NOSEL;
|
||||
|
||||
vms->highmem_ecam = !vmc->no_highmem_ecam;
|
||||
vms->highmem_ecam = true;
|
||||
vms->highmem_mmio = true;
|
||||
vms->highmem_redists = true;
|
||||
|
||||
if (vmc->no_its) {
|
||||
vms->its = false;
|
||||
} else {
|
||||
/* Default allows ITS instantiation */
|
||||
vms->its = true;
|
||||
/* Default allows ITS instantiation */
|
||||
vms->its = true;
|
||||
|
||||
if (vmc->no_tcg_its) {
|
||||
vms->tcg_its = false;
|
||||
} else {
|
||||
vms->tcg_its = true;
|
||||
}
|
||||
if (vmc->no_tcg_its) {
|
||||
vms->tcg_its = false;
|
||||
} else {
|
||||
vms->tcg_its = true;
|
||||
}
|
||||
|
||||
/* Default disallows iommu instantiation */
|
||||
|
@ -3583,99 +3562,3 @@ static void virt_machine_4_1_options(MachineClass *mc)
|
|||
mc->auto_enable_numa_with_memhp = false;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(4, 1)
|
||||
|
||||
static void virt_machine_4_0_options(MachineClass *mc)
|
||||
{
|
||||
virt_machine_4_1_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(4, 0)
|
||||
|
||||
static void virt_machine_3_1_options(MachineClass *mc)
|
||||
{
|
||||
virt_machine_4_0_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(3, 1)
|
||||
|
||||
static void virt_machine_3_0_options(MachineClass *mc)
|
||||
{
|
||||
virt_machine_3_1_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(3, 0)
|
||||
|
||||
static void virt_machine_2_12_options(MachineClass *mc)
|
||||
{
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
|
||||
|
||||
virt_machine_3_0_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_2_12, hw_compat_2_12_len);
|
||||
vmc->no_highmem_ecam = true;
|
||||
mc->max_cpus = 255;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 12)
|
||||
|
||||
static void virt_machine_2_11_options(MachineClass *mc)
|
||||
{
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
|
||||
|
||||
virt_machine_2_12_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len);
|
||||
vmc->smbios_old_sys_ver = true;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 11)
|
||||
|
||||
static void virt_machine_2_10_options(MachineClass *mc)
|
||||
{
|
||||
virt_machine_2_11_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len);
|
||||
/* before 2.11 we never faulted accesses to bad addresses */
|
||||
mc->ignore_memory_transaction_failures = true;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 10)
|
||||
|
||||
static void virt_machine_2_9_options(MachineClass *mc)
|
||||
{
|
||||
virt_machine_2_10_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 9)
|
||||
|
||||
static void virt_machine_2_8_options(MachineClass *mc)
|
||||
{
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
|
||||
|
||||
virt_machine_2_9_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len);
|
||||
/* For 2.8 and earlier we falsely claimed in the DT that
|
||||
* our timers were edge-triggered, not level-triggered.
|
||||
*/
|
||||
vmc->claim_edge_triggered_timers = true;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 8)
|
||||
|
||||
static void virt_machine_2_7_options(MachineClass *mc)
|
||||
{
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
|
||||
|
||||
virt_machine_2_8_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len);
|
||||
/* ITS was introduced with 2.8 */
|
||||
vmc->no_its = true;
|
||||
/* Stick with 1K pages for migration compatibility */
|
||||
mc->minimum_page_bits = 0;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 7)
|
||||
|
||||
static void virt_machine_2_6_options(MachineClass *mc)
|
||||
{
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
|
||||
|
||||
virt_machine_2_7_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len);
|
||||
vmc->disallow_affinity_adjustment = true;
|
||||
/* Disable PMU for 2.6 as PMU support was first introduced in 2.7 */
|
||||
vmc->no_pmu = true;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 6)
|
||||
|
|
|
@ -72,7 +72,7 @@ static void imx_gpio_update_int(IMXGPIOState *s)
|
|||
static void imx_gpio_set_int_line(IMXGPIOState *s, int line, IMXGPIOLevel level)
|
||||
{
|
||||
/* if this signal isn't configured as an input signal, nothing to do */
|
||||
if (!extract32(s->gdir, line, 1)) {
|
||||
if (extract32(s->gdir, line, 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "hw/pci/msi.h"
|
||||
|
@ -349,14 +348,14 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
|
|||
|
||||
case DESIGNWARE_PCIE_ATU_LOWER_BASE:
|
||||
case DESIGNWARE_PCIE_ATU_UPPER_BASE:
|
||||
viewport->base = deposit64(root->msi.base,
|
||||
viewport->base = deposit64(viewport->base,
|
||||
address == DESIGNWARE_PCIE_ATU_LOWER_BASE
|
||||
? 0 : 32, 32, val);
|
||||
break;
|
||||
|
||||
case DESIGNWARE_PCIE_ATU_LOWER_TARGET:
|
||||
case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
|
||||
viewport->target = deposit64(root->msi.base,
|
||||
viewport->target = deposit64(viewport->target,
|
||||
address == DESIGNWARE_PCIE_ATU_LOWER_TARGET
|
||||
? 0 : 32, 32, val);
|
||||
break;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "hw/usb/hcd-ehci.h"
|
||||
#include "hw/usb/hcd-ohci.h"
|
||||
#include "target/arm/cpu.h"
|
||||
#include "hw/ssi/npcm_pspi.h"
|
||||
|
||||
#define NPCM8XX_MAX_NUM_CPUS (4)
|
||||
|
||||
|
@ -99,6 +100,7 @@ struct NPCM8xxState {
|
|||
OHCISysBusState ohci[2];
|
||||
NPCM7xxFIUState fiu[3];
|
||||
NPCM7xxSDHCIState mmc;
|
||||
NPCMPSPIState pspi;
|
||||
};
|
||||
|
||||
struct NPCM8xxClass {
|
||||
|
|
|
@ -117,14 +117,8 @@ typedef enum VirtGICType {
|
|||
|
||||
struct VirtMachineClass {
|
||||
MachineClass parent;
|
||||
bool disallow_affinity_adjustment;
|
||||
bool no_its;
|
||||
bool no_tcg_its;
|
||||
bool no_pmu;
|
||||
bool claim_edge_triggered_timers;
|
||||
bool smbios_old_sys_ver;
|
||||
bool no_highmem_compact;
|
||||
bool no_highmem_ecam;
|
||||
bool no_ged; /* Machines < 4.2 have no support for ACPI GED device */
|
||||
bool kvm_no_adjvtime;
|
||||
bool no_kvm_steal_time;
|
||||
|
|
|
@ -46,7 +46,7 @@ static inline void gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3)
|
|||
#ifdef CONFIG_KVM
|
||||
int fdarray[3];
|
||||
|
||||
if (!kvm_arm_create_scratch_host_vcpu(NULL, fdarray, NULL)) {
|
||||
if (!kvm_arm_create_scratch_host_vcpu(fdarray, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -2278,28 +2278,23 @@ static inline bool hvf_arm_hw_debug_active(CPUState *cpu)
|
|||
return ((cur_hw_wps > 0) || (cur_hw_bps > 0));
|
||||
}
|
||||
|
||||
static void hvf_arch_set_traps(void)
|
||||
static void hvf_arch_set_traps(CPUState *cpu)
|
||||
{
|
||||
CPUState *cpu;
|
||||
bool should_enable_traps = false;
|
||||
hv_return_t r = HV_SUCCESS;
|
||||
|
||||
/* Check whether guest debugging is enabled for at least one vCPU; if it
|
||||
* is, enable exiting the guest on all vCPUs */
|
||||
CPU_FOREACH(cpu) {
|
||||
should_enable_traps |= cpu->accel->guest_debug_enabled;
|
||||
}
|
||||
CPU_FOREACH(cpu) {
|
||||
/* Set whether debug exceptions exit the guest */
|
||||
r = hv_vcpu_set_trap_debug_exceptions(cpu->accel->fd,
|
||||
should_enable_traps);
|
||||
assert_hvf_ok(r);
|
||||
should_enable_traps |= cpu->accel->guest_debug_enabled;
|
||||
/* Set whether debug exceptions exit the guest */
|
||||
r = hv_vcpu_set_trap_debug_exceptions(cpu->accel->fd,
|
||||
should_enable_traps);
|
||||
assert_hvf_ok(r);
|
||||
|
||||
/* Set whether accesses to debug registers exit the guest */
|
||||
r = hv_vcpu_set_trap_debug_reg_accesses(cpu->accel->fd,
|
||||
should_enable_traps);
|
||||
assert_hvf_ok(r);
|
||||
}
|
||||
/* Set whether accesses to debug registers exit the guest */
|
||||
r = hv_vcpu_set_trap_debug_reg_accesses(cpu->accel->fd,
|
||||
should_enable_traps);
|
||||
assert_hvf_ok(r);
|
||||
}
|
||||
|
||||
void hvf_arch_update_guest_debug(CPUState *cpu)
|
||||
|
@ -2340,7 +2335,7 @@ void hvf_arch_update_guest_debug(CPUState *cpu)
|
|||
deposit64(env->cp15.mdscr_el1, MDSCR_EL1_MDE_SHIFT, 1, 0);
|
||||
}
|
||||
|
||||
hvf_arch_set_traps();
|
||||
hvf_arch_set_traps(cpu);
|
||||
}
|
||||
|
||||
bool hvf_arch_supports_guest_debug(void)
|
||||
|
|
|
@ -100,8 +100,7 @@ static int kvm_arm_vcpu_finalize(ARMCPU *cpu, int feature)
|
|||
return kvm_vcpu_ioctl(CPU(cpu), KVM_ARM_VCPU_FINALIZE, &feature);
|
||||
}
|
||||
|
||||
bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
|
||||
int *fdarray,
|
||||
bool kvm_arm_create_scratch_host_vcpu(int *fdarray,
|
||||
struct kvm_vcpu_init *init)
|
||||
{
|
||||
int ret = 0, kvmfd = -1, vmfd = -1, cpufd = -1;
|
||||
|
@ -150,40 +149,13 @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
|
|||
struct kvm_vcpu_init preferred;
|
||||
|
||||
ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &preferred);
|
||||
if (!ret) {
|
||||
init->target = preferred.target;
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
init->target = preferred.target;
|
||||
}
|
||||
if (ret >= 0) {
|
||||
ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
} else if (cpus_to_try) {
|
||||
/* Old kernel which doesn't know about the
|
||||
* PREFERRED_TARGET ioctl: we know it will only support
|
||||
* creating one kind of guest CPU which is its preferred
|
||||
* CPU type.
|
||||
*/
|
||||
struct kvm_vcpu_init try;
|
||||
|
||||
while (*cpus_to_try != QEMU_KVM_ARM_TARGET_NONE) {
|
||||
try.target = *cpus_to_try++;
|
||||
memcpy(try.features, init->features, sizeof(init->features));
|
||||
ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, &try);
|
||||
if (ret >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
init->target = try.target;
|
||||
} else {
|
||||
/* Treat a NULL cpus_to_try argument the same as an empty
|
||||
* list, which means we will fail the call since this must
|
||||
* be an old kernel which doesn't support PREFERRED_TARGET.
|
||||
*/
|
||||
ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -259,17 +231,6 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
|||
uint64_t features = 0;
|
||||
int err;
|
||||
|
||||
/* Old kernels may not know about the PREFERRED_TARGET ioctl: however
|
||||
* we know these will only support creating one kind of guest CPU,
|
||||
* which is its preferred CPU type. Fortunately these old kernels
|
||||
* support only a very limited number of CPUs.
|
||||
*/
|
||||
static const uint32_t cpus_to_try[] = {
|
||||
KVM_ARM_TARGET_AEM_V8,
|
||||
KVM_ARM_TARGET_FOUNDATION_V8,
|
||||
KVM_ARM_TARGET_CORTEX_A57,
|
||||
QEMU_KVM_ARM_TARGET_NONE
|
||||
};
|
||||
/*
|
||||
* target = -1 informs kvm_arm_create_scratch_host_vcpu()
|
||||
* to use the preferred target
|
||||
|
@ -300,7 +261,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
|||
features |= 1ULL << ARM_FEATURE_PMU;
|
||||
}
|
||||
|
||||
if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
|
||||
if (!kvm_arm_create_scratch_host_vcpu(fdarray, &init)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1835,7 +1796,7 @@ uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu)
|
|||
|
||||
probed = true;
|
||||
|
||||
if (!kvm_arm_create_scratch_host_vcpu(NULL, fdarray, &init)) {
|
||||
if (!kvm_arm_create_scratch_host_vcpu(fdarray, &init)) {
|
||||
error_report("failed to create scratch VCPU with SVE enabled");
|
||||
abort();
|
||||
}
|
||||
|
|
|
@ -97,10 +97,6 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu);
|
|||
#ifdef CONFIG_KVM
|
||||
/**
|
||||
* kvm_arm_create_scratch_host_vcpu:
|
||||
* @cpus_to_try: array of QEMU_KVM_ARM_TARGET_* values (terminated with
|
||||
* QEMU_KVM_ARM_TARGET_NONE) to try as fallback if the kernel does not
|
||||
* know the PREFERRED_TARGET ioctl. Passing NULL is the same as passing
|
||||
* an empty array.
|
||||
* @fdarray: filled in with kvmfd, vmfd, cpufd file descriptors in that order
|
||||
* @init: filled in with the necessary values for creating a host
|
||||
* vcpu. If NULL is provided, will not init the vCPU (though the cpufd
|
||||
|
@ -113,8 +109,7 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu);
|
|||
* Returns: true on success (and fdarray and init are filled in),
|
||||
* false on failure (and fdarray and init are not valid).
|
||||
*/
|
||||
bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
|
||||
int *fdarray,
|
||||
bool kvm_arm_create_scratch_host_vcpu(int *fdarray,
|
||||
struct kvm_vcpu_init *init);
|
||||
|
||||
/**
|
||||
|
|
|
@ -3551,13 +3551,9 @@ bool get_phys_addr_with_space_nogpc(CPUARMState *env, vaddr address,
|
|||
memop, result, fi);
|
||||
}
|
||||
|
||||
bool get_phys_addr(CPUARMState *env, vaddr address,
|
||||
MMUAccessType access_type, MemOp memop, ARMMMUIdx mmu_idx,
|
||||
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
|
||||
static ARMSecuritySpace
|
||||
arm_mmu_idx_to_security_space(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||
{
|
||||
S1Translate ptw = {
|
||||
.in_mmu_idx = mmu_idx,
|
||||
};
|
||||
ARMSecuritySpace ss;
|
||||
|
||||
switch (mmu_idx) {
|
||||
|
@ -3618,32 +3614,67 @@ bool get_phys_addr(CPUARMState *env, vaddr address,
|
|||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
ptw.in_space = ss;
|
||||
return ss;
|
||||
}
|
||||
|
||||
bool get_phys_addr(CPUARMState *env, vaddr address,
|
||||
MMUAccessType access_type, MemOp memop, ARMMMUIdx mmu_idx,
|
||||
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
|
||||
{
|
||||
S1Translate ptw = {
|
||||
.in_mmu_idx = mmu_idx,
|
||||
.in_space = arm_mmu_idx_to_security_space(env, mmu_idx),
|
||||
};
|
||||
|
||||
return get_phys_addr_gpc(env, &ptw, address, access_type,
|
||||
memop, result, fi);
|
||||
}
|
||||
|
||||
static hwaddr arm_cpu_get_phys_page(CPUARMState *env, vaddr addr,
|
||||
MemTxAttrs *attrs, ARMMMUIdx mmu_idx)
|
||||
{
|
||||
S1Translate ptw = {
|
||||
.in_mmu_idx = mmu_idx,
|
||||
.in_space = arm_mmu_idx_to_security_space(env, mmu_idx),
|
||||
.in_debug = true,
|
||||
};
|
||||
GetPhysAddrResult res = {};
|
||||
ARMMMUFaultInfo fi = {};
|
||||
bool ret = get_phys_addr_gpc(env, &ptw, addr, MMU_DATA_LOAD, 0, &res, &fi);
|
||||
*attrs = res.f.attrs;
|
||||
|
||||
if (ret) {
|
||||
return -1;
|
||||
}
|
||||
return res.f.phys_addr;
|
||||
}
|
||||
|
||||
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
|
||||
MemTxAttrs *attrs)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
CPUARMState *env = &cpu->env;
|
||||
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
|
||||
ARMSecuritySpace ss = arm_security_space(env);
|
||||
S1Translate ptw = {
|
||||
.in_mmu_idx = mmu_idx,
|
||||
.in_space = ss,
|
||||
.in_debug = true,
|
||||
};
|
||||
GetPhysAddrResult res = {};
|
||||
ARMMMUFaultInfo fi = {};
|
||||
bool ret;
|
||||
|
||||
ret = get_phys_addr_gpc(env, &ptw, addr, MMU_DATA_LOAD, 0, &res, &fi);
|
||||
*attrs = res.f.attrs;
|
||||
hwaddr res = arm_cpu_get_phys_page(env, addr, attrs, mmu_idx);
|
||||
|
||||
if (ret) {
|
||||
if (res != -1) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory may be accessible for an "unprivileged load/store" variant.
|
||||
* In this case, get_a64_user_mem_index function generates an op using an
|
||||
* unprivileged mmu idx, so we need to try with it.
|
||||
*/
|
||||
switch (mmu_idx) {
|
||||
case ARMMMUIdx_E10_1:
|
||||
case ARMMMUIdx_E10_1_PAN:
|
||||
return arm_cpu_get_phys_page(env, addr, attrs, ARMMMUIdx_E10_0);
|
||||
case ARMMMUIdx_E20_2:
|
||||
case ARMMMUIdx_E20_2_PAN:
|
||||
return arm_cpu_get_phys_page(env, addr, attrs, ARMMMUIdx_E20_0);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return res.f.phys_addr;
|
||||
}
|
||||
|
|
|
@ -7760,7 +7760,8 @@ static bool arm_check_ss_active(DisasContext *dc)
|
|||
|
||||
static void arm_post_translate_insn(DisasContext *dc)
|
||||
{
|
||||
if (dc->condjmp && dc->base.is_jmp == DISAS_NEXT) {
|
||||
if (dc->condjmp &&
|
||||
(dc->base.is_jmp == DISAS_NEXT || dc->base.is_jmp == DISAS_TOO_MANY)) {
|
||||
if (dc->pc_save != dc->condlabel.pc_save) {
|
||||
gen_update_pc(dc, dc->condlabel.pc_save - dc->pc_save);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ endif
|
|||
test_timeouts = {
|
||||
'aarch64_aspeed_ast2700' : 600,
|
||||
'aarch64_aspeed_ast2700fc' : 600,
|
||||
'aarch64_imx8mp_evk' : 240,
|
||||
'aarch64_raspi4' : 480,
|
||||
'aarch64_reverse_debug' : 180,
|
||||
'aarch64_rme_virt' : 1200,
|
||||
|
@ -82,6 +83,7 @@ tests_aarch64_system_quick = [
|
|||
tests_aarch64_system_thorough = [
|
||||
'aarch64_aspeed_ast2700',
|
||||
'aarch64_aspeed_ast2700fc',
|
||||
'aarch64_imx8mp_evk',
|
||||
'aarch64_raspi3',
|
||||
'aarch64_raspi4',
|
||||
'aarch64_replay',
|
||||
|
|
67
tests/functional/test_aarch64_imx8mp_evk.py
Executable file
67
tests/functional/test_aarch64_imx8mp_evk.py
Executable file
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Functional test that boots a Linux kernel and checks the console
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
|
||||
|
||||
class Imx8mpEvkMachine(LinuxKernelTest):
|
||||
|
||||
ASSET_IMAGE = Asset(
|
||||
('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/'
|
||||
'debian-12-generic-arm64-20231210-1590.tar.xz'),
|
||||
'7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359')
|
||||
|
||||
KERNEL_OFFSET = 0x51000000
|
||||
KERNEL_SIZE = 32622528
|
||||
INITRD_OFFSET = 0x76000000
|
||||
INITRD_SIZE = 30987766
|
||||
DTB_OFFSET = 0x64F51000
|
||||
DTB_SIZE = 45 * 1024
|
||||
|
||||
def extract(self, in_path, out_path, offset, size):
|
||||
try:
|
||||
with open(in_path, "rb") as source:
|
||||
source.seek(offset)
|
||||
data = source.read(size)
|
||||
with open(out_path, "wb") as target:
|
||||
target.write(data)
|
||||
except (IOError, ValueError) as e:
|
||||
self.log.error(f"Failed to extract {out_path}: {e}")
|
||||
raise
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
self.image_path = self.scratch_file("disk.raw")
|
||||
self.kernel_path = self.scratch_file("linux")
|
||||
self.initrd_path = self.scratch_file("initrd.zstd")
|
||||
self.dtb_path = self.scratch_file("imx8mp-evk.dtb")
|
||||
|
||||
self.archive_extract(self.ASSET_IMAGE)
|
||||
self.extract(self.image_path, self.kernel_path,
|
||||
self.KERNEL_OFFSET, self.KERNEL_SIZE)
|
||||
self.extract(self.image_path, self.initrd_path,
|
||||
self.INITRD_OFFSET, self.INITRD_SIZE)
|
||||
self.extract(self.image_path, self.dtb_path,
|
||||
self.DTB_OFFSET, self.DTB_SIZE)
|
||||
|
||||
def test_aarch64_imx8mp_evk_usdhc(self):
|
||||
self.set_machine('imx8mp-evk')
|
||||
self.vm.set_console(console_index=1)
|
||||
self.vm.add_args('-m', '2G',
|
||||
'-smp', '4',
|
||||
'-kernel', self.kernel_path,
|
||||
'-initrd', self.initrd_path,
|
||||
'-dtb', self.dtb_path,
|
||||
'-append', 'root=/dev/mmcblk2p1',
|
||||
'-drive', f'file={self.image_path},if=sd,bus=2,'
|
||||
'format=raw,id=mmcblk2,snapshot=on')
|
||||
|
||||
self.vm.launch()
|
||||
self.wait_for_console_pattern('Welcome to ')
|
||||
|
||||
if __name__ == '__main__':
|
||||
LinuxKernelTest.main()
|
Loading…
Add table
Add a link
Reference in a new issue