target-arm queue:
* hw/arm: Fix some typos in comments (most found by codespell) * exynos: Fix out-of-bounds access in exynos4210_gcomp_find debug printf * Orangepi-PC, Cubieboard: add Allwinner WDT watchdog emulation * tests/avocado: Add reboot tests to Cubieboard * hw/timer/imx_epit: Fix bugs in timer limit checking * target/arm: Remove KVM AArch32 CPU definitions * hw/arm/virt: Restrict Cortex-A7 check to TCG * target/arm: Initialize debug capabilities only once * target/arm: Implement FEAT_PAN3 * docs/devel/kconfig.rst: Fix incorrect markup * target/arm: Report pauth information to gdb as 'pauth_v2' * mcimxd7-sabre, mcimx6ul-evk: Correctly model the way the PHY on the second ethernet device must be configured via the first one -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmRBDfkZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3rtLD/93hJ+CEUnATXx7Ic7g0EvN eXIMsgd80pd1gn4PKzP9lol6I40VDuozs9mb9jP6+Hc0tEoOua4KlIvyMlYy4wSx eJBqt/gx/N/V+jwVG8seY+ifLIzECMLMOQIRQqQoVk+scENuiJIXcJRH5A1eUWNb iV0QfJa1gQrKyyIG9vNfZ+cS+xy0bl0E9FlZ0ty3zeh0xBaMhUqnpraTVLISWelP OEovcIBEzvD/ngj+7F/xKBGgtSTZ1FuN5p/oOFDCH2Fihe2+wuw7B3Rc1SbHLG7n Wr4JZozdPbnudhrZgn+1A9SCFhH+B8k/QlKY2Qc+w+GrnC0JpJAmqtaF2aIaepPo kfbTUshDstIZ7MnCeAa+SWn2Exgrsn0Gv9nWdOrPgrvo0bqK6ceAhchi5nFmkkaJ MOy+Xx5GIAE91418wR8C2TlrTl58A81s15AYY1D7nZ0GeuZV5io7wPIAOWa14rOQ RdvQ/0rcZ+IkOFXz5Zj/L/Y/W4BpDyfuUVzLAah56zYkuV4im2cLt3YAOMFYZjjO 6W1sdbAcuA5QFmO4v5VmcTU8t/B423QzcnssE6sbM0nazMh/i6kjzvJUhdJTQmi+ lKjIe+MHutTgrbjrwemjiafk3dOpFpKtso/4C/dhP2UfDIcKuGXNpSYxCvoknO2j TWvxRvir/PC7gzUzA4CrwQ== =YUUL -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20230420' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * hw/arm: Fix some typos in comments (most found by codespell) * exynos: Fix out-of-bounds access in exynos4210_gcomp_find debug printf * Orangepi-PC, Cubieboard: add Allwinner WDT watchdog emulation * tests/avocado: Add reboot tests to Cubieboard * hw/timer/imx_epit: Fix bugs in timer limit checking * target/arm: Remove KVM AArch32 CPU definitions * hw/arm/virt: Restrict Cortex-A7 check to TCG * target/arm: Initialize debug capabilities only once * target/arm: Implement FEAT_PAN3 * docs/devel/kconfig.rst: Fix incorrect markup * target/arm: Report pauth information to gdb as 'pauth_v2' * mcimxd7-sabre, mcimx6ul-evk: Correctly model the way the PHY on the second ethernet device must be configured via the first one # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmRBDfkZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3rtLD/93hJ+CEUnATXx7Ic7g0EvN # eXIMsgd80pd1gn4PKzP9lol6I40VDuozs9mb9jP6+Hc0tEoOua4KlIvyMlYy4wSx # eJBqt/gx/N/V+jwVG8seY+ifLIzECMLMOQIRQqQoVk+scENuiJIXcJRH5A1eUWNb # iV0QfJa1gQrKyyIG9vNfZ+cS+xy0bl0E9FlZ0ty3zeh0xBaMhUqnpraTVLISWelP # OEovcIBEzvD/ngj+7F/xKBGgtSTZ1FuN5p/oOFDCH2Fihe2+wuw7B3Rc1SbHLG7n # Wr4JZozdPbnudhrZgn+1A9SCFhH+B8k/QlKY2Qc+w+GrnC0JpJAmqtaF2aIaepPo # kfbTUshDstIZ7MnCeAa+SWn2Exgrsn0Gv9nWdOrPgrvo0bqK6ceAhchi5nFmkkaJ # MOy+Xx5GIAE91418wR8C2TlrTl58A81s15AYY1D7nZ0GeuZV5io7wPIAOWa14rOQ # RdvQ/0rcZ+IkOFXz5Zj/L/Y/W4BpDyfuUVzLAah56zYkuV4im2cLt3YAOMFYZjjO # 6W1sdbAcuA5QFmO4v5VmcTU8t/B423QzcnssE6sbM0nazMh/i6kjzvJUhdJTQmi+ # lKjIe+MHutTgrbjrwemjiafk3dOpFpKtso/4C/dhP2UfDIcKuGXNpSYxCvoknO2j # TWvxRvir/PC7gzUzA4CrwQ== # =YUUL # -----END PGP SIGNATURE----- # gpg: Signature made Thu 20 Apr 2023 11:03:37 AM BST # 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] * tag 'pull-target-arm-20230420' of https://git.linaro.org/people/pmaydell/qemu-arm: (21 commits) arm/mcimx7d-sabre: Set fec2-phy-connected property to false fsl-imx7: Add fec[12]-phy-connected properties arm/mcimx6ul-evk: Set fec1-phy-connected property to false fsl-imx6ul: Add fec[12]-phy-connected properties hw/net/imx_fec: Support two Ethernet interfaces connected to single MDIO bus target/arm: Report pauth information to gdb as 'pauth_v2' docs/devel/kconfig.rst: Fix incorrect markup target/arm: Implement FEAT_PAN3 target/arm: Don't set ISV when reporting stage 1 faults in ESR_EL2 target/arm: Pass ARMMMUFaultInfo to merge_syn_data_abort() target/arm: Initialize debug capabilities only once hw/arm/virt: Restrict Cortex-A7 check to TCG target/arm: Remove KVM AArch32 CPU definitions hw/timer/imx_epit: fix limit check hw/timer/imx_epit: don't shadow variable tests/avocado: Add reboot tests to Cubieboard hw/arm: Add WDT to Allwinner-H3 and Orangepi-PC hw/arm: Add WDT to Allwinner-A10 and Cubieboard hw/watchdog: Allwinner WDT emulation for system reset exynos: Fix out-of-bounds access in exynos4210_gcomp_find debug printf ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
29c343a463
@ -274,7 +274,7 @@ or commenting out lines in the second group.
|
||||
|
||||
It is also possible to run QEMU's configure script with the
|
||||
``--without-default-devices`` option. When this is done, everything defaults
|
||||
to ``n`` unless it is ``select``ed or explicitly switched on in the
|
||||
to ``n`` unless it is ``select``\ ed or explicitly switched on in the
|
||||
``.mak`` files. In other words, ``default`` and ``imply`` directives
|
||||
are disabled. When QEMU is built with this option, the user will probably
|
||||
want to change some lines in the first group, for example like this::
|
||||
|
@ -15,3 +15,4 @@ Emulated devices:
|
||||
- USB controller
|
||||
- SATA controller
|
||||
- TWI (I2C) controller
|
||||
- Watchdog timer
|
||||
|
@ -56,6 +56,7 @@ the following architecture extensions:
|
||||
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
|
||||
- FEAT_PAN (Privileged access never)
|
||||
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
|
||||
- FEAT_PAN3 (Support for SCTLR_ELx.EPAN)
|
||||
- FEAT_PAuth (Pointer authentication)
|
||||
- FEAT_PMULL (PMULL, PMULL2 instructions)
|
||||
- FEAT_PMUv3p1 (PMU Extensions v3.1)
|
||||
|
@ -26,6 +26,7 @@ The Orange Pi PC machine supports the following devices:
|
||||
* System Control module
|
||||
* Security Identifier device
|
||||
* TWI (I2C)
|
||||
* Watchdog timer
|
||||
|
||||
Limitations
|
||||
"""""""""""
|
||||
|
@ -6,7 +6,7 @@
|
||||
notice and this notice are preserved. -->
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.aarch64.pauth">
|
||||
<feature name="org.gnu.gdb.aarch64.pauth_v2">
|
||||
<reg name="pauth_dmask" bitsize="64"/>
|
||||
<reg name="pauth_cmask" bitsize="64"/>
|
||||
<reg name="pauth_dmask_high" bitsize="64"/>
|
||||
|
@ -126,7 +126,7 @@ config OLIMEX_STM32_H405
|
||||
config NSERIES
|
||||
bool
|
||||
select OMAP
|
||||
select TMP105 # tempature sensor
|
||||
select TMP105 # temperature sensor
|
||||
select BLIZZARD # LCD/TV controller
|
||||
select ONENAND
|
||||
select TSC210X # touchscreen/sensors/audio
|
||||
@ -325,6 +325,7 @@ config ALLWINNER_A10
|
||||
select ALLWINNER_A10_PIC
|
||||
select ALLWINNER_A10_CCM
|
||||
select ALLWINNER_A10_DRAMC
|
||||
select ALLWINNER_WDT
|
||||
select ALLWINNER_EMAC
|
||||
select ALLWINNER_I2C
|
||||
select AXP209_PMU
|
||||
@ -336,6 +337,7 @@ config ALLWINNER_H3
|
||||
select ALLWINNER_A10_PIT
|
||||
select ALLWINNER_SUN8I_EMAC
|
||||
select ALLWINNER_I2C
|
||||
select ALLWINNER_WDT
|
||||
select SERIAL
|
||||
select ARM_TIMER
|
||||
select ARM_GIC
|
||||
|
@ -38,6 +38,7 @@
|
||||
#define AW_A10_EHCI_BASE 0x01c14000
|
||||
#define AW_A10_OHCI_BASE 0x01c14400
|
||||
#define AW_A10_SATA_BASE 0x01c18000
|
||||
#define AW_A10_WDT_BASE 0x01c20c90
|
||||
#define AW_A10_RTC_BASE 0x01c20d00
|
||||
#define AW_A10_I2C0_BASE 0x01c2ac00
|
||||
|
||||
@ -92,6 +93,8 @@ static void aw_a10_init(Object *obj)
|
||||
object_initialize_child(obj, "mmc0", &s->mmc0, TYPE_AW_SDHOST_SUN4I);
|
||||
|
||||
object_initialize_child(obj, "rtc", &s->rtc, TYPE_AW_RTC_SUN4I);
|
||||
|
||||
object_initialize_child(obj, "wdt", &s->wdt, TYPE_AW_WDT_SUN4I);
|
||||
}
|
||||
|
||||
static void aw_a10_realize(DeviceState *dev, Error **errp)
|
||||
@ -203,6 +206,10 @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, AW_A10_I2C0_BASE);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0, qdev_get_gpio_in(dev, 7));
|
||||
|
||||
/* WDT */
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_fatal);
|
||||
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->wdt), 0, AW_A10_WDT_BASE, 1);
|
||||
}
|
||||
|
||||
static void aw_a10_class_init(ObjectClass *oc, void *data)
|
||||
|
@ -49,6 +49,7 @@ const hwaddr allwinner_h3_memmap[] = {
|
||||
[AW_H3_DEV_OHCI3] = 0x01c1d400,
|
||||
[AW_H3_DEV_CCU] = 0x01c20000,
|
||||
[AW_H3_DEV_PIT] = 0x01c20c00,
|
||||
[AW_H3_DEV_WDT] = 0x01c20ca0,
|
||||
[AW_H3_DEV_UART0] = 0x01c28000,
|
||||
[AW_H3_DEV_UART1] = 0x01c28400,
|
||||
[AW_H3_DEV_UART2] = 0x01c28800,
|
||||
@ -234,6 +235,8 @@ static void allwinner_h3_init(Object *obj)
|
||||
object_initialize_child(obj, "twi1", &s->i2c1, TYPE_AW_I2C_SUN6I);
|
||||
object_initialize_child(obj, "twi2", &s->i2c2, TYPE_AW_I2C_SUN6I);
|
||||
object_initialize_child(obj, "r_twi", &s->r_twi, TYPE_AW_I2C_SUN6I);
|
||||
|
||||
object_initialize_child(obj, "wdt", &s->wdt, TYPE_AW_WDT_SUN6I);
|
||||
}
|
||||
|
||||
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
|
||||
@ -453,6 +456,11 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->r_twi), 0,
|
||||
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_R_TWI));
|
||||
|
||||
/* WDT */
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_fatal);
|
||||
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->wdt), 0,
|
||||
s->memmap[AW_H3_DEV_WDT], 1);
|
||||
|
||||
/* Unimplemented devices */
|
||||
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
|
||||
create_unimplemented_device(unimplemented[i].device_name,
|
||||
|
@ -326,7 +326,7 @@ static int mapline_size(const int *mapline)
|
||||
|
||||
/*
|
||||
* Initialize board IRQs.
|
||||
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
|
||||
* These IRQs contain split Int/External Combiner and External Gic IRQs.
|
||||
*/
|
||||
static void exynos4210_init_board_irqs(Exynos4210State *s)
|
||||
{
|
||||
@ -744,7 +744,7 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
|
||||
* - SDMA
|
||||
* - ADMA2
|
||||
*
|
||||
* As this part of the Exynos4210 is not publically available,
|
||||
* As this part of the Exynos4210 is not publicly available,
|
||||
* we used the "HS-MMC Controller S3C2416X RISC Microprocessor"
|
||||
* public datasheet which is very similar (implementing
|
||||
* MMC Specification Version 4.0 being the only difference noted)
|
||||
|
@ -407,7 +407,23 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*
|
||||
* We must use two loops since phy_connected affects the other interface
|
||||
* and we have to set all properties before calling sysbus_realize().
|
||||
*/
|
||||
for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
|
||||
object_property_set_bool(OBJECT(&s->eth[i]), "phy-connected",
|
||||
s->phy_connected[i], &error_abort);
|
||||
/*
|
||||
* If the MDIO bus on this controller is not connected, assume the
|
||||
* other controller provides support for it.
|
||||
*/
|
||||
if (!s->phy_connected[i]) {
|
||||
object_property_set_link(OBJECT(&s->eth[1 - i]), "phy-consumer",
|
||||
OBJECT(&s->eth[i]), &error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
|
||||
static const hwaddr FSL_IMX6UL_ENETn_ADDR[FSL_IMX6UL_NUM_ETHS] = {
|
||||
FSL_IMX6UL_ENET1_ADDR,
|
||||
@ -620,6 +636,10 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
|
||||
static Property fsl_imx6ul_properties[] = {
|
||||
DEFINE_PROP_UINT32("fec1-phy-num", FslIMX6ULState, phy_num[0], 0),
|
||||
DEFINE_PROP_UINT32("fec2-phy-num", FslIMX6ULState, phy_num[1], 1),
|
||||
DEFINE_PROP_BOOL("fec1-phy-connected", FslIMX6ULState, phy_connected[0],
|
||||
true),
|
||||
DEFINE_PROP_BOOL("fec2-phy-connected", FslIMX6ULState, phy_connected[1],
|
||||
true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -395,7 +395,23 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*
|
||||
* We must use two loops since phy_connected affects the other interface
|
||||
* and we have to set all properties before calling sysbus_realize().
|
||||
*/
|
||||
for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
|
||||
object_property_set_bool(OBJECT(&s->eth[i]), "phy-connected",
|
||||
s->phy_connected[i], &error_abort);
|
||||
/*
|
||||
* If the MDIO bus on this controller is not connected, assume the
|
||||
* other controller provides support for it.
|
||||
*/
|
||||
if (!s->phy_connected[i]) {
|
||||
object_property_set_link(OBJECT(&s->eth[1 - i]), "phy-consumer",
|
||||
OBJECT(&s->eth[i]), &error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
|
||||
static const hwaddr FSL_IMX7_ENETn_ADDR[FSL_IMX7_NUM_ETHS] = {
|
||||
FSL_IMX7_ENET1_ADDR,
|
||||
@ -601,6 +617,10 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
|
||||
static Property fsl_imx7_properties[] = {
|
||||
DEFINE_PROP_UINT32("fec1-phy-num", FslIMX7State, phy_num[0], 0),
|
||||
DEFINE_PROP_UINT32("fec2-phy-num", FslIMX7State, phy_num[1], 1),
|
||||
DEFINE_PROP_BOOL("fec1-phy-connected", FslIMX7State, phy_connected[0],
|
||||
true),
|
||||
DEFINE_PROP_BOOL("fec2-phy-connected", FslIMX7State, phy_connected[1],
|
||||
true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -41,6 +41,8 @@ static void mcimx6ul_evk_init(MachineState *machine)
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
|
||||
object_property_set_uint(OBJECT(s), "fec1-phy-num", 2, &error_fatal);
|
||||
object_property_set_uint(OBJECT(s), "fec2-phy-num", 1, &error_fatal);
|
||||
object_property_set_bool(OBJECT(s), "fec1-phy-connected", false,
|
||||
&error_fatal);
|
||||
qdev_realize(DEVICE(s), NULL, &error_fatal);
|
||||
|
||||
memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_MMDC_ADDR,
|
||||
|
@ -41,6 +41,8 @@ static void mcimx7d_sabre_init(MachineState *machine)
|
||||
|
||||
s = FSL_IMX7(object_new(TYPE_FSL_IMX7));
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
|
||||
object_property_set_bool(OBJECT(s), "fec2-phy-connected", false,
|
||||
&error_fatal);
|
||||
qdev_realize(DEVICE(s), NULL, &error_fatal);
|
||||
|
||||
memory_region_add_subregion(get_system_memory(), FSL_IMX7_MMDC_ADDR,
|
||||
|
@ -100,7 +100,7 @@
|
||||
#define MP_LCD_SPI_CMD 0x00104011
|
||||
#define MP_LCD_SPI_INVALID 0x00000000
|
||||
|
||||
/* Commmands */
|
||||
/* Commands */
|
||||
#define MP_LCD_INST_SETPAGE0 0xB0
|
||||
/* ... */
|
||||
#define MP_LCD_INST_SETPAGE7 0xB7
|
||||
|
@ -4057,7 +4057,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram,
|
||||
s->led[1] = omap_lpg_init(system_memory,
|
||||
0xfffbd800, omap_findclk(s, "clk32-kHz"));
|
||||
|
||||
/* Register mappings not currenlty implemented:
|
||||
/* Register mappings not currently implemented:
|
||||
* MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310)
|
||||
* MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310)
|
||||
* USB W2FC fffb4000 - fffb47ff
|
||||
|
@ -2523,7 +2523,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram,
|
||||
omap_findclk(s, "func_96m_clk"),
|
||||
omap_findclk(s, "core_l4_iclk"));
|
||||
|
||||
/* All register mappings (includin those not currenlty implemented):
|
||||
/* All register mappings (including those not currently implemented):
|
||||
* SystemControlMod 48000000 - 48000fff
|
||||
* SystemControlL4 48001000 - 48001fff
|
||||
* 32kHz Timer Mod 48004000 - 48004fff
|
||||
|
@ -694,7 +694,7 @@ static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size)
|
||||
build_append_int_noprefix(table_data, 0xE, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, 16, 1); /* Length */
|
||||
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
|
||||
/* Discovery Range Base Addres */
|
||||
/* Discovery Range Base Address */
|
||||
build_append_int_noprefix(table_data, base, 8);
|
||||
build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */
|
||||
}
|
||||
|
@ -204,7 +204,9 @@ static const int a15irqmap[] = {
|
||||
};
|
||||
|
||||
static const char *valid_cpus[] = {
|
||||
#ifdef CONFIG_TCG
|
||||
ARM_CPU_TYPE_NAME("cortex-a7"),
|
||||
#endif
|
||||
ARM_CPU_TYPE_NAME("cortex-a15"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a35"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a53"),
|
||||
@ -2052,7 +2054,7 @@ static void machvirt_init(MachineState *machine)
|
||||
int pa_bits;
|
||||
|
||||
/*
|
||||
* Instanciate a temporary CPU object to find out about what
|
||||
* Instantiate a temporary CPU object to find out about what
|
||||
* we are about to deal with. Once this is done, get rid of
|
||||
* the object.
|
||||
*/
|
||||
|
@ -659,7 +659,7 @@ static void versal_virt_init(MachineState *machine)
|
||||
fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
|
||||
|
||||
/* Make the APU cpu address space visible to virtio and other
|
||||
* modules unaware of muliple address-spaces. */
|
||||
* modules unaware of multiple address-spaces. */
|
||||
memory_region_add_subregion_overlap(get_system_memory(),
|
||||
0, &s->soc.fpd.apu.mr, 0);
|
||||
|
||||
|
@ -282,11 +282,19 @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
|
||||
uint32_t val;
|
||||
uint32_t phy = reg / 32;
|
||||
|
||||
if (phy != s->phy_num) {
|
||||
trace_imx_phy_read_num(phy, s->phy_num);
|
||||
if (!s->phy_connected) {
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
if (phy != s->phy_num) {
|
||||
if (s->phy_consumer && phy == s->phy_consumer->phy_num) {
|
||||
s = s->phy_consumer;
|
||||
} else {
|
||||
trace_imx_phy_read_num(phy, s->phy_num);
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
reg %= 32;
|
||||
|
||||
switch (reg) {
|
||||
@ -343,11 +351,19 @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
|
||||
{
|
||||
uint32_t phy = reg / 32;
|
||||
|
||||
if (phy != s->phy_num) {
|
||||
trace_imx_phy_write_num(phy, s->phy_num);
|
||||
if (!s->phy_connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (phy != s->phy_num) {
|
||||
if (s->phy_consumer && phy == s->phy_consumer->phy_num) {
|
||||
s = s->phy_consumer;
|
||||
} else {
|
||||
trace_imx_phy_write_num(phy, s->phy_num);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
reg %= 32;
|
||||
|
||||
trace_imx_phy_write(val, phy, reg);
|
||||
@ -1327,6 +1343,9 @@ static Property imx_eth_properties[] = {
|
||||
DEFINE_NIC_PROPERTIES(IMXFECState, conf),
|
||||
DEFINE_PROP_UINT32("tx-ring-num", IMXFECState, tx_ring_num, 1),
|
||||
DEFINE_PROP_UINT32("phy-num", IMXFECState, phy_num, 0),
|
||||
DEFINE_PROP_BOOL("phy-connected", IMXFECState, phy_connected, true),
|
||||
DEFINE_PROP_LINK("phy-consumer", IMXFECState, phy_consumer, TYPE_IMX_FEC,
|
||||
IMXFECState *),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -480,11 +480,14 @@ static int32_t exynos4210_gcomp_find(Exynos4210MCTState *s)
|
||||
res = min_comp_i;
|
||||
}
|
||||
|
||||
DPRINTF("found comparator %d: comp 0x%llx distance 0x%llx, gfrc 0x%llx\n",
|
||||
res,
|
||||
s->g_timer.reg.comp[res],
|
||||
distance_min,
|
||||
gfrc);
|
||||
if (res >= 0) {
|
||||
DPRINTF("found comparator %d: "
|
||||
"comp 0x%llx distance 0x%llx, gfrc 0x%llx\n",
|
||||
res,
|
||||
s->g_timer.reg.comp[res],
|
||||
distance_min,
|
||||
gfrc);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ static void imx_epit_update_compare_timer(IMXEPITState *s)
|
||||
* the compare value. Otherwise it may fire at most once in the
|
||||
* current round.
|
||||
*/
|
||||
bool is_oneshot = (limit >= s->cmp);
|
||||
is_oneshot = (limit < s->cmp);
|
||||
if (counter >= s->cmp) {
|
||||
/* The compare timer fires in the current round. */
|
||||
counter -= s->cmp;
|
||||
|
@ -20,3 +20,7 @@ config WDT_IMX2
|
||||
|
||||
config WDT_SBSA
|
||||
bool
|
||||
|
||||
config ALLWINNER_WDT
|
||||
bool
|
||||
select PTIMER
|
||||
|
416
hw/watchdog/allwinner-wdt.c
Normal file
416
hw/watchdog/allwinner-wdt.c
Normal file
@ -0,0 +1,416 @@
|
||||
/*
|
||||
* Allwinner Watchdog emulation
|
||||
*
|
||||
* Copyright (C) 2023 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
|
||||
*
|
||||
* This file is derived from Allwinner RTC,
|
||||
* by Niek Linnenbank.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/module.h"
|
||||
#include "trace.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/registerfields.h"
|
||||
#include "hw/watchdog/allwinner-wdt.h"
|
||||
#include "sysemu/watchdog.h"
|
||||
#include "migration/vmstate.h"
|
||||
|
||||
/* WDT registers */
|
||||
enum {
|
||||
REG_IRQ_EN = 0, /* Watchdog interrupt enable */
|
||||
REG_IRQ_STA, /* Watchdog interrupt status */
|
||||
REG_CTRL, /* Watchdog control register */
|
||||
REG_CFG, /* Watchdog configuration register */
|
||||
REG_MODE, /* Watchdog mode register */
|
||||
};
|
||||
|
||||
/* Universal WDT register flags */
|
||||
#define WDT_RESTART_MASK (1 << 0)
|
||||
#define WDT_EN_MASK (1 << 0)
|
||||
|
||||
/* sun4i specific WDT register flags */
|
||||
#define RST_EN_SUN4I_MASK (1 << 1)
|
||||
#define INTV_VALUE_SUN4I_SHIFT (3)
|
||||
#define INTV_VALUE_SUN4I_MASK (0xfu << INTV_VALUE_SUN4I_SHIFT)
|
||||
|
||||
/* sun6i specific WDT register flags */
|
||||
#define RST_EN_SUN6I_MASK (1 << 0)
|
||||
#define KEY_FIELD_SUN6I_SHIFT (1)
|
||||
#define KEY_FIELD_SUN6I_MASK (0xfffu << KEY_FIELD_SUN6I_SHIFT)
|
||||
#define KEY_FIELD_SUN6I (0xA57u)
|
||||
#define INTV_VALUE_SUN6I_SHIFT (4)
|
||||
#define INTV_VALUE_SUN6I_MASK (0xfu << INTV_VALUE_SUN6I_SHIFT)
|
||||
|
||||
/* Map of INTV_VALUE to 0.5s units. */
|
||||
static const uint8_t allwinner_wdt_count_map[] = {
|
||||
1,
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
8,
|
||||
10,
|
||||
12,
|
||||
16,
|
||||
20,
|
||||
24,
|
||||
28,
|
||||
32
|
||||
};
|
||||
|
||||
/* WDT sun4i register map (offset to name) */
|
||||
const uint8_t allwinner_wdt_sun4i_regmap[] = {
|
||||
[0x0000] = REG_CTRL,
|
||||
[0x0004] = REG_MODE,
|
||||
};
|
||||
|
||||
/* WDT sun6i register map (offset to name) */
|
||||
const uint8_t allwinner_wdt_sun6i_regmap[] = {
|
||||
[0x0000] = REG_IRQ_EN,
|
||||
[0x0004] = REG_IRQ_STA,
|
||||
[0x0010] = REG_CTRL,
|
||||
[0x0014] = REG_CFG,
|
||||
[0x0018] = REG_MODE,
|
||||
};
|
||||
|
||||
static bool allwinner_wdt_sun4i_read(AwWdtState *s, uint32_t offset)
|
||||
{
|
||||
/* no sun4i specific registers currently implemented */
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool allwinner_wdt_sun4i_write(AwWdtState *s, uint32_t offset,
|
||||
uint32_t data)
|
||||
{
|
||||
/* no sun4i specific registers currently implemented */
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool allwinner_wdt_sun4i_can_reset_system(AwWdtState *s)
|
||||
{
|
||||
if (s->regs[REG_MODE] & RST_EN_SUN4I_MASK) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool allwinner_wdt_sun4i_is_key_valid(AwWdtState *s, uint32_t val)
|
||||
{
|
||||
/* sun4i has no key */
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t allwinner_wdt_sun4i_get_intv_value(AwWdtState *s)
|
||||
{
|
||||
return ((s->regs[REG_MODE] & INTV_VALUE_SUN4I_MASK) >>
|
||||
INTV_VALUE_SUN4I_SHIFT);
|
||||
}
|
||||
|
||||
static bool allwinner_wdt_sun6i_read(AwWdtState *s, uint32_t offset)
|
||||
{
|
||||
const AwWdtClass *c = AW_WDT_GET_CLASS(s);
|
||||
|
||||
switch (c->regmap[offset]) {
|
||||
case REG_IRQ_EN:
|
||||
case REG_IRQ_STA:
|
||||
case REG_CFG:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool allwinner_wdt_sun6i_write(AwWdtState *s, uint32_t offset,
|
||||
uint32_t data)
|
||||
{
|
||||
const AwWdtClass *c = AW_WDT_GET_CLASS(s);
|
||||
|
||||
switch (c->regmap[offset]) {
|
||||
case REG_IRQ_EN:
|
||||
case REG_IRQ_STA:
|
||||
case REG_CFG:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool allwinner_wdt_sun6i_can_reset_system(AwWdtState *s)
|
||||
{
|
||||
if (s->regs[REG_CFG] & RST_EN_SUN6I_MASK) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool allwinner_wdt_sun6i_is_key_valid(AwWdtState *s, uint32_t val)
|
||||
{
|
||||
uint16_t key = (val & KEY_FIELD_SUN6I_MASK) >> KEY_FIELD_SUN6I_SHIFT;
|
||||
return (key == KEY_FIELD_SUN6I);
|
||||
}
|
||||
|
||||
static uint8_t allwinner_wdt_sun6i_get_intv_value(AwWdtState *s)
|
||||
{
|
||||
return ((s->regs[REG_MODE] & INTV_VALUE_SUN6I_MASK) >>
|
||||
INTV_VALUE_SUN6I_SHIFT);
|
||||
}
|
||||
|
||||
static void allwinner_wdt_update_timer(AwWdtState *s)
|
||||
{
|
||||
const AwWdtClass *c = AW_WDT_GET_CLASS(s);
|
||||
uint8_t count = c->get_intv_value(s);
|
||||
|
||||
ptimer_transaction_begin(s->timer);
|
||||
ptimer_stop(s->timer);
|
||||
|
||||
/* Use map to convert. */
|
||||
if (count < sizeof(allwinner_wdt_count_map)) {
|
||||
ptimer_set_count(s->timer, allwinner_wdt_count_map[count]);
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: incorrect INTV_VALUE 0x%02x\n",
|
||||
__func__, count);
|
||||
}
|
||||
|
||||
ptimer_run(s->timer, 1);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
|
||||
trace_allwinner_wdt_update_timer(count);
|
||||
}
|
||||
|
||||
static uint64_t allwinner_wdt_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
AwWdtState *s = AW_WDT(opaque);
|
||||
const AwWdtClass *c = AW_WDT_GET_CLASS(s);
|
||||
uint64_t r;
|
||||
|
||||
if (offset >= c->regmap_size) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
|
||||
__func__, (uint32_t)offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (c->regmap[offset]) {
|
||||
case REG_CTRL:
|
||||
case REG_MODE:
|
||||
r = s->regs[c->regmap[offset]];
|
||||
break;
|
||||
default:
|
||||
if (!c->read(s, offset)) {
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
|
||||
__func__, (uint32_t)offset);
|
||||
return 0;
|
||||
}
|
||||
r = s->regs[c->regmap[offset]];
|
||||
break;
|
||||
}
|
||||
|
||||
trace_allwinner_wdt_read(offset, r, size);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void allwinner_wdt_write(void *opaque, hwaddr offset,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
AwWdtState *s = AW_WDT(opaque);
|
||||
const AwWdtClass *c = AW_WDT_GET_CLASS(s);
|
||||
uint32_t old_val;
|
||||
|
||||
if (offset >= c->regmap_size) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
|
||||
__func__, (uint32_t)offset);
|
||||
return;
|
||||
}
|
||||
|
||||
trace_allwinner_wdt_write(offset, val, size);
|
||||
|
||||
switch (c->regmap[offset]) {
|
||||
case REG_CTRL:
|
||||
if (c->is_key_valid(s, val)) {
|
||||
if (val & WDT_RESTART_MASK) {
|
||||
/* Kick timer */
|
||||
allwinner_wdt_update_timer(s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case REG_MODE:
|
||||
old_val = s->regs[REG_MODE];
|
||||
s->regs[REG_MODE] = (uint32_t)val;
|
||||
|
||||
/* Check for rising edge on WDOG_MODE_EN */
|
||||
if ((s->regs[REG_MODE] & ~old_val) & WDT_EN_MASK) {
|
||||
allwinner_wdt_update_timer(s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!c->write(s, offset, val)) {
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
|
||||
__func__, (uint32_t)offset);
|
||||
}
|
||||
s->regs[c->regmap[offset]] = (uint32_t)val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps allwinner_wdt_ops = {
|
||||
.read = allwinner_wdt_read,
|
||||
.write = allwinner_wdt_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.impl.min_access_size = 4,
|
||||
};
|
||||
|
||||
static void allwinner_wdt_expired(void *opaque)
|
||||
{
|
||||
AwWdtState *s = AW_WDT(opaque);
|
||||
const AwWdtClass *c = AW_WDT_GET_CLASS(s);
|
||||
|
||||
bool enabled = s->regs[REG_MODE] & WDT_EN_MASK;
|
||||
bool reset_enabled = c->can_reset_system(s);
|
||||
|
||||
trace_allwinner_wdt_expired(enabled, reset_enabled);
|
||||
|
||||
/* Perform watchdog action if watchdog is enabled and can trigger reset */
|
||||
if (enabled && reset_enabled) {
|
||||
watchdog_perform_action();
|
||||
}
|
||||
}
|
||||
|
||||
static void allwinner_wdt_reset_enter(Object *obj, ResetType type)
|
||||
{
|
||||
AwWdtState *s = AW_WDT(obj);
|
||||
|
||||
trace_allwinner_wdt_reset_enter();
|
||||
|
||||
/* Clear registers */
|
||||
memset(s->regs, 0, sizeof(s->regs));
|
||||
}
|
||||
|
||||
static const VMStateDescription allwinner_wdt_vmstate = {
|
||||
.name = "allwinner-wdt",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_PTIMER(timer, AwWdtState),
|
||||
VMSTATE_UINT32_ARRAY(regs, AwWdtState, AW_WDT_REGS_NUM),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void allwinner_wdt_init(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
AwWdtState *s = AW_WDT(obj);
|
||||
const AwWdtClass *c = AW_WDT_GET_CLASS(s);
|
||||
|
||||
/* Memory mapping */
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_wdt_ops, s,
|
||||
TYPE_AW_WDT, c->regmap_size * 4);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static void allwinner_wdt_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
AwWdtState *s = AW_WDT(dev);
|
||||
|
||||
s->timer = ptimer_init(allwinner_wdt_expired, s,
|
||||
PTIMER_POLICY_NO_IMMEDIATE_TRIGGER |
|
||||
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
|
||||
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
|
||||
|
||||
ptimer_transaction_begin(s->timer);
|
||||
/* Set to 2Hz (0.5s period); other periods are multiples of 0.5s. */
|
||||
ptimer_set_freq(s->timer, 2);
|
||||
ptimer_set_limit(s->timer, 0xff, 1);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
}
|
||||
|
||||
static void allwinner_wdt_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||
|
||||
rc->phases.enter = allwinner_wdt_reset_enter;
|
||||
dc->realize = allwinner_wdt_realize;
|
||||
dc->vmsd = &allwinner_wdt_vmstate;
|
||||
}
|
||||
|
||||
static void allwinner_wdt_sun4i_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
AwWdtClass *awc = AW_WDT_CLASS(klass);
|
||||
|
||||
awc->regmap = allwinner_wdt_sun4i_regmap;
|
||||
awc->regmap_size = sizeof(allwinner_wdt_sun4i_regmap);
|
||||
awc->read = allwinner_wdt_sun4i_read;
|
||||
awc->write = allwinner_wdt_sun4i_write;
|
||||
awc->can_reset_system = allwinner_wdt_sun4i_can_reset_system;
|
||||
awc->is_key_valid = allwinner_wdt_sun4i_is_key_valid;
|
||||
awc->get_intv_value = allwinner_wdt_sun4i_get_intv_value;
|
||||
}
|
||||
|
||||
static void allwinner_wdt_sun6i_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
AwWdtClass *awc = AW_WDT_CLASS(klass);
|
||||
|
||||
awc->regmap = allwinner_wdt_sun6i_regmap;
|
||||
awc->regmap_size = sizeof(allwinner_wdt_sun6i_regmap);
|
||||
awc->read = allwinner_wdt_sun6i_read;
|
||||
awc->write = allwinner_wdt_sun6i_write;
|
||||
awc->can_reset_system = allwinner_wdt_sun6i_can_reset_system;
|
||||
awc->is_key_valid = allwinner_wdt_sun6i_is_key_valid;
|
||||
awc->get_intv_value = allwinner_wdt_sun6i_get_intv_value;
|
||||
}
|
||||
|
||||
static const TypeInfo allwinner_wdt_info = {
|
||||
.name = TYPE_AW_WDT,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_init = allwinner_wdt_init,
|
||||
.instance_size = sizeof(AwWdtState),
|
||||
.class_init = allwinner_wdt_class_init,
|
||||
.class_size = sizeof(AwWdtClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static const TypeInfo allwinner_wdt_sun4i_info = {
|
||||
.name = TYPE_AW_WDT_SUN4I,
|
||||
.parent = TYPE_AW_WDT,
|
||||
.class_init = allwinner_wdt_sun4i_class_init,
|
||||
};
|
||||
|
||||
static const TypeInfo allwinner_wdt_sun6i_info = {
|
||||
.name = TYPE_AW_WDT_SUN6I,
|
||||
.parent = TYPE_AW_WDT,
|
||||
.class_init = allwinner_wdt_sun6i_class_init,
|
||||
};
|
||||
|
||||
static void allwinner_wdt_register(void)
|
||||
{
|
||||
type_register_static(&allwinner_wdt_info);
|
||||
type_register_static(&allwinner_wdt_sun4i_info);
|
||||
type_register_static(&allwinner_wdt_sun6i_info);
|
||||
}
|
||||
|
||||
type_init(allwinner_wdt_register)
|
@ -1,4 +1,5 @@
|
||||
softmmu_ss.add(files('watchdog.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_ALLWINNER_WDT', if_true: files('allwinner-wdt.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_CMSDK_APB_WATCHDOG', if_true: files('cmsdk-apb-watchdog.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_WDT_IB6300ESB', if_true: files('wdt_i6300esb.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_WDT_IB700', if_true: files('wdt_ib700.c'))
|
||||
|
@ -1,5 +1,12 @@
|
||||
# See docs/devel/tracing.rst for syntax documentation.
|
||||
|
||||
# allwinner-wdt.c
|
||||
allwinner_wdt_read(uint64_t offset, uint64_t data, unsigned size) "Allwinner watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
|
||||
allwinner_wdt_write(uint64_t offset, uint64_t data, unsigned size) "Allwinner watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
|
||||
allwinner_wdt_reset_enter(void) "Allwinner watchdog: reset"
|
||||
allwinner_wdt_update_timer(uint8_t count) "Allwinner watchdog: count %" PRIu8
|
||||
allwinner_wdt_expired(bool enabled, bool reset_enabled) "Allwinner watchdog: enabled %u reset_enabled %u"
|
||||
|
||||
# cmsdk-apb-watchdog.c
|
||||
cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
|
||||
cmsdk_apb_watchdog_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "hw/misc/allwinner-a10-ccm.h"
|
||||
#include "hw/misc/allwinner-a10-dramc.h"
|
||||
#include "hw/i2c/allwinner-i2c.h"
|
||||
#include "hw/watchdog/allwinner-wdt.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
#include "target/arm/cpu.h"
|
||||
@ -41,6 +42,7 @@ struct AwA10State {
|
||||
AwSdHostState mmc0;
|
||||
AWI2CState i2c0;
|
||||
AwRtcState rtc;
|
||||
AwWdtState wdt;
|
||||
MemoryRegion sram_a;
|
||||
EHCISysBusState ehci[AW_A10_NUM_USB];
|
||||
OHCISysBusState ohci[AW_A10_NUM_USB];
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "hw/net/allwinner-sun8i-emac.h"
|
||||
#include "hw/rtc/allwinner-rtc.h"
|
||||
#include "hw/i2c/allwinner-i2c.h"
|
||||
#include "hw/watchdog/allwinner-wdt.h"
|
||||
#include "target/arm/cpu.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
@ -96,7 +97,8 @@ enum {
|
||||
AW_H3_DEV_RTC,
|
||||
AW_H3_DEV_CPUCFG,
|
||||
AW_H3_DEV_R_TWI,
|
||||
AW_H3_DEV_SDRAM
|
||||
AW_H3_DEV_SDRAM,
|
||||
AW_H3_DEV_WDT
|
||||
};
|
||||
|
||||
/** Total number of CPU cores in the H3 SoC */
|
||||
@ -141,6 +143,7 @@ struct AwH3State {
|
||||
AWI2CState r_twi;
|
||||
AwSun8iEmacState emac;
|
||||
AwRtcState rtc;
|
||||
AwWdtState wdt;
|
||||
GICState gic;
|
||||
MemoryRegion sram_a1;
|
||||
MemoryRegion sram_a2;
|
||||
|
@ -89,6 +89,7 @@ struct FslIMX6ULState {
|
||||
MemoryRegion ocram_alias;
|
||||
|
||||
uint32_t phy_num[FSL_IMX6UL_NUM_ETHS];
|
||||
bool phy_connected[FSL_IMX6UL_NUM_ETHS];
|
||||
};
|
||||
|
||||
enum FslIMX6ULMemoryMap {
|
||||
|
@ -82,6 +82,7 @@ struct FslIMX7State {
|
||||
ChipideaState usb[FSL_IMX7_NUM_USBS];
|
||||
DesignwarePCIEHost pcie;
|
||||
uint32_t phy_num[FSL_IMX7_NUM_ETHS];
|
||||
bool phy_connected[FSL_IMX7_NUM_ETHS];
|
||||
};
|
||||
|
||||
enum FslIMX7MemoryMap {
|
||||
|
@ -270,6 +270,8 @@ struct IMXFECState {
|
||||
uint32_t phy_int;
|
||||
uint32_t phy_int_mask;
|
||||
uint32_t phy_num;
|
||||
bool phy_connected;
|
||||
struct IMXFECState *phy_consumer;
|
||||
|
||||
bool is_fec;
|
||||
|
||||
|
123
include/hw/watchdog/allwinner-wdt.h
Normal file
123
include/hw/watchdog/allwinner-wdt.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Allwinner Watchdog emulation
|
||||
*
|
||||
* Copyright (C) 2023 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
|
||||
*
|
||||
* This file is derived from Allwinner RTC,
|
||||
* by Niek Linnenbank.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HW_WATCHDOG_ALLWINNER_WDT_H
|
||||
#define HW_WATCHDOG_ALLWINNER_WDT_H
|
||||
|
||||
#include "qom/object.h"
|
||||
#include "hw/ptimer.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
/*
|
||||
* This is a model of the Allwinner watchdog.
|
||||
* Since watchdog registers belong to the timer module (and are shared with the
|
||||
* RTC module), the interrupt line from watchdog is not handled right now.
|
||||
* In QEMU, we just wire up the watchdog reset to watchdog_perform_action(),
|
||||
* at least for the moment.
|
||||
*/
|
||||
|
||||
#define TYPE_AW_WDT "allwinner-wdt"
|
||||
|
||||
/** Allwinner WDT sun4i family (A10, A12), also sun7i (A20) */
|
||||
#define TYPE_AW_WDT_SUN4I TYPE_AW_WDT "-sun4i"
|
||||
|
||||
/** Allwinner WDT sun6i family and newer (A31, H2+, H3, etc) */
|
||||
#define TYPE_AW_WDT_SUN6I TYPE_AW_WDT "-sun6i"
|
||||
|
||||
/** Number of WDT registers */
|
||||
#define AW_WDT_REGS_NUM (5)
|
||||
|
||||
OBJECT_DECLARE_TYPE(AwWdtState, AwWdtClass, AW_WDT)
|
||||
|
||||
/**
|
||||
* Allwinner WDT object instance state.
|
||||
*/
|
||||
struct AwWdtState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
MemoryRegion iomem;
|
||||
struct ptimer_state *timer;
|
||||
|
||||
uint32_t regs[AW_WDT_REGS_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
* Allwinner WDT class-level struct.
|
||||
*
|
||||
* This struct is filled by each sunxi device specific code
|
||||
* such that the generic code can use this struct to support
|
||||
* all devices.
|
||||
*/
|
||||
struct AwWdtClass {
|
||||
/*< private >*/
|
||||
SysBusDeviceClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
/** Defines device specific register map */
|
||||
const uint8_t *regmap;
|
||||
|
||||
/** Size of the regmap in bytes */
|
||||
size_t regmap_size;
|
||||
|
||||
/**
|
||||
* Read device specific register
|
||||
*
|
||||
* @offset: register offset to read
|
||||
* @return true if register read successful, false otherwise
|
||||
*/
|
||||
bool (*read)(AwWdtState *s, uint32_t offset);
|
||||
|
||||
/**
|
||||
* Write device specific register
|
||||
*
|
||||
* @offset: register offset to write
|
||||
* @data: value to set in register
|
||||
* @return true if register write successful, false otherwise
|
||||
*/
|
||||
bool (*write)(AwWdtState *s, uint32_t offset, uint32_t data);
|
||||
|
||||
/**
|
||||
* Check if watchdog can generate system reset
|
||||
*
|
||||
* @return true if watchdog can generate system reset
|
||||
*/
|
||||
bool (*can_reset_system)(AwWdtState *s);
|
||||
|
||||
/**
|
||||
* Check if provided key is valid
|
||||
*
|
||||
* @value: value written to register
|
||||
* @return true if key is valid, false otherwise
|
||||
*/
|
||||
bool (*is_key_valid)(AwWdtState *s, uint32_t val);
|
||||
|
||||
/**
|
||||
* Get current INTV_VALUE setting
|
||||
*
|
||||
* @return current INTV_VALUE (0-15)
|
||||
*/
|
||||
uint8_t (*get_intv_value)(AwWdtState *s);
|
||||
};
|
||||
|
||||
#endif /* HW_WATCHDOG_ALLWINNER_WDT_H */
|
@ -3823,6 +3823,11 @@ static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
|
||||
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_pan3(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 3;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0;
|
||||
|
@ -1302,7 +1302,7 @@ static void aarch64_max_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* FEAT_PAN2 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 3); /* FEAT_PAN3 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */
|
||||
|
@ -546,7 +546,6 @@ static void cortex_a7_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL3);
|
||||
set_feature(&cpu->env, ARM_FEATURE_PMU);
|
||||
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
|
||||
cpu->midr = 0x410fc075;
|
||||
cpu->reset_fpsid = 0x41023075;
|
||||
cpu->isar.mvfr0 = 0x10110222;
|
||||
@ -595,7 +594,6 @@ static void cortex_a15_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL3);
|
||||
set_feature(&cpu->env, ARM_FEATURE_PMU);
|
||||
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
|
||||
/* r4p0 cpu, not requiring expensive tlb flush errata */
|
||||
cpu->midr = 0x414fc0f0;
|
||||
cpu->revidr = 0x0;
|
||||
|
@ -521,18 +521,17 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
|
||||
aarch64_gdb_set_fpu_reg,
|
||||
34, "aarch64-fpu.xml", 0);
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
* GDB versions 9 through 12 have a bug which means they will
|
||||
* crash if they see this XML from QEMU; disable it for the 8.0
|
||||
* release, pending a better solution.
|
||||
* Note that we report pauth information via the feature name
|
||||
* org.gnu.gdb.aarch64.pauth_v2, not org.gnu.gdb.aarch64.pauth.
|
||||
* GDB versions 9 through 12 have a bug where they will crash
|
||||
* if they see the latter XML from QEMU.
|
||||
*/
|
||||
if (isar_feature_aa64_pauth(&cpu->isar)) {
|
||||
gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg,
|
||||
aarch64_gdb_set_pauth_reg,
|
||||
4, "aarch64-pauth.xml", 0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
if (arm_feature(env, ARM_FEATURE_NEON)) {
|
||||
|
@ -124,13 +124,10 @@ MISMATCH_CHECK(QEMU_PSCI_RET_INTERNAL_FAILURE, PSCI_RET_INTERNAL_FAILURE);
|
||||
MISMATCH_CHECK(QEMU_PSCI_RET_NOT_PRESENT, PSCI_RET_NOT_PRESENT);
|
||||
MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED);
|
||||
|
||||
/* Note that KVM uses overlapping values for AArch32 and AArch64
|
||||
* target CPU numbers. AArch32 targets:
|
||||
/*
|
||||
* Note that KVM uses overlapping values for AArch32 and AArch64
|
||||
* target CPU numbers. AArch64 targets:
|
||||
*/
|
||||
#define QEMU_KVM_ARM_TARGET_CORTEX_A15 0
|
||||
#define QEMU_KVM_ARM_TARGET_CORTEX_A7 1
|
||||
|
||||
/* AArch64 targets: */
|
||||
#define QEMU_KVM_ARM_TARGET_AEM_V8 0
|
||||
#define QEMU_KVM_ARM_TARGET_FOUNDATION_V8 1
|
||||
#define QEMU_KVM_ARM_TARGET_CORTEX_A57 2
|
||||
|
@ -280,6 +280,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
}
|
||||
}
|
||||
|
||||
kvm_arm_init_debug(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -74,24 +74,16 @@ GArray *hw_breakpoints, *hw_watchpoints;
|
||||
#define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i))
|
||||
#define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i))
|
||||
|
||||
/**
|
||||
* kvm_arm_init_debug() - check for guest debug capabilities
|
||||
* @cs: CPUState
|
||||
*
|
||||
* kvm_check_extension returns the number of debug registers we have
|
||||
* or 0 if we have none.
|
||||
*
|
||||
*/
|
||||
static void kvm_arm_init_debug(CPUState *cs)
|
||||
void kvm_arm_init_debug(KVMState *s)
|
||||
{
|
||||
have_guest_debug = kvm_check_extension(cs->kvm_state,
|
||||
have_guest_debug = kvm_check_extension(s,
|
||||
KVM_CAP_SET_GUEST_DEBUG);
|
||||
|
||||
max_hw_wps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_WPS);
|
||||
max_hw_wps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_WPS);
|
||||
hw_watchpoints = g_array_sized_new(true, true,
|
||||
sizeof(HWWatchpoint), max_hw_wps);
|
||||
|
||||
max_hw_bps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_BPS);
|
||||
max_hw_bps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_BPS);
|
||||
hw_breakpoints = g_array_sized_new(true, true,
|
||||
sizeof(HWBreakpoint), max_hw_bps);
|
||||
return;
|
||||
@ -920,8 +912,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
}
|
||||
cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK;
|
||||
|
||||
kvm_arm_init_debug(cs);
|
||||
|
||||
/* Check whether user space can specify guest syndrome value */
|
||||
kvm_arm_init_serror_injection(cs);
|
||||
|
||||
|
@ -18,6 +18,14 @@
|
||||
#define KVM_ARM_VGIC_V2 (1 << 0)
|
||||
#define KVM_ARM_VGIC_V3 (1 << 1)
|
||||
|
||||
/**
|
||||
* kvm_arm_init_debug() - initialize guest debug capabilities
|
||||
* @s: KVMState
|
||||
*
|
||||
* Should be called only once before using guest debug capabilities.
|
||||
*/
|
||||
void kvm_arm_init_debug(KVMState *s);
|
||||
|
||||
/**
|
||||
* kvm_arm_vcpu_init:
|
||||
* @cs: CPUState
|
||||
|
@ -947,6 +947,7 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
|
||||
static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
|
||||
int ap, int ns, int xn, int pxn)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
bool is_user = regime_is_user(env, mmu_idx);
|
||||
int prot_rw, user_rw;
|
||||
bool have_wxn;
|
||||
@ -958,8 +959,19 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
|
||||
if (is_user) {
|
||||
prot_rw = user_rw;
|
||||
} else {
|
||||
/*
|
||||
* PAN controls can forbid data accesses but don't affect insn fetch.
|
||||
* Plain PAN forbids data accesses if EL0 has data permissions;
|
||||
* PAN3 forbids data accesses if EL0 has either data or exec perms.
|
||||
* Note that for AArch64 the 'user can exec' case is exactly !xn.
|
||||
* We make the IMPDEF choices that SCR_EL3.SIF and Realm EL2&0
|
||||
* do not affect EPAN.
|
||||
*/
|
||||
if (user_rw && regime_is_pan(env, mmu_idx)) {
|
||||
/* PAN forbids data accesses but doesn't affect insn fetch */
|
||||
prot_rw = 0;
|
||||
} else if (cpu_isar_feature(aa64_pan3, cpu) && is_aa64 &&
|
||||
regime_is_pan(env, mmu_idx) &&
|
||||
(regime_sctlr(env, mmu_idx) & SCTLR_EPAN) && !xn) {
|
||||
prot_rw = 0;
|
||||
} else {
|
||||
prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
|
||||
|
@ -24,16 +24,17 @@ bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||
}
|
||||
|
||||
static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
|
||||
ARMMMUFaultInfo *fi,
|
||||
unsigned int target_el,
|
||||
bool same_el, bool ea,
|
||||
bool s1ptw, bool is_write,
|
||||
bool same_el, bool is_write,
|
||||
int fsc)
|
||||
{
|
||||
uint32_t syn;
|
||||
|
||||
/*
|
||||
* ISV is only set for data aborts routed to EL2 and
|
||||
* never for stage-1 page table walks faulting on stage 2.
|
||||
* ISV is only set for stage-2 data aborts routed to EL2 and
|
||||
* never for stage-1 page table walks faulting on stage 2
|
||||
* or for stage-1 faults.
|
||||
*
|
||||
* Furthermore, ISV is only set for certain kinds of load/stores.
|
||||
* If the template syndrome does not have ISV set, we should leave
|
||||
@ -42,10 +43,16 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
|
||||
* See ARMv8 specs, D7-1974:
|
||||
* ISS encoding for an exception from a Data Abort, the
|
||||
* ISV field.
|
||||
*
|
||||
* TODO: FEAT_LS64/FEAT_LS64_V/FEAT_SL64_ACCDATA: Translation,
|
||||
* Access Flag, and Permission faults caused by LD64B, ST64B,
|
||||
* ST64BV, or ST64BV0 insns report syndrome info even for stage-1
|
||||
* faults and regardless of the target EL.
|
||||
*/
|
||||
if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
|
||||
if (!(template_syn & ARM_EL_ISV) || target_el != 2
|
||||
|| fi->s1ptw || !fi->stage2) {
|
||||
syn = syn_data_abort_no_iss(same_el, 0,
|
||||
ea, 0, s1ptw, is_write, fsc);
|
||||
fi->ea, 0, fi->s1ptw, is_write, fsc);
|
||||
} else {
|
||||
/*
|
||||
* Fields: IL, ISV, SAS, SSE, SRT, SF and AR come from the template
|
||||
@ -54,7 +61,7 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
|
||||
*/
|
||||
syn = syn_data_abort_with_iss(same_el,
|
||||
0, 0, 0, 0, 0,
|
||||
ea, 0, s1ptw, is_write, fsc,
|
||||
fi->ea, 0, fi->s1ptw, is_write, fsc,
|
||||
true);
|
||||
/* Merge the runtime syndrome with the template syndrome. */
|
||||
syn |= template_syn;
|
||||
@ -117,9 +124,8 @@ void arm_deliver_fault(ARMCPU *cpu, vaddr addr,
|
||||
syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc);
|
||||
exc = EXCP_PREFETCH_ABORT;
|
||||
} else {
|
||||
syn = merge_syn_data_abort(env->exception.syndrome, target_el,
|
||||
same_el, fi->ea, fi->s1ptw,
|
||||
access_type == MMU_DATA_STORE,
|
||||
syn = merge_syn_data_abort(env->exception.syndrome, fi, target_el,
|
||||
same_el, access_type == MMU_DATA_STORE,
|
||||
fsc);
|
||||
if (access_type == MMU_DATA_STORE
|
||||
&& arm_feature(env, ARM_FEATURE_V6)) {
|
||||
|
@ -581,7 +581,10 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
'Allwinner sun4i/sun5i')
|
||||
exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
|
||||
'system-control@1c00000')
|
||||
# cubieboard's reboot is not functioning; omit reboot test.
|
||||
exec_command_and_wait_for_pattern(self, 'reboot',
|
||||
'reboot: Restarting system')
|
||||
# Wait for VM to shut down gracefully
|
||||
self.vm.wait()
|
||||
|
||||
def test_arm_cubieboard_sata(self):
|
||||
"""
|
||||
@ -625,7 +628,10 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
'Allwinner sun4i/sun5i')
|
||||
exec_command_and_wait_for_pattern(self, 'cat /proc/partitions',
|
||||
'sda')
|
||||
# cubieboard's reboot is not functioning; omit reboot test.
|
||||
exec_command_and_wait_for_pattern(self, 'reboot',
|
||||
'reboot: Restarting system')
|
||||
# Wait for VM to shut down gracefully
|
||||
self.vm.wait()
|
||||
|
||||
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
|
||||
def test_arm_cubieboard_openwrt_22_03_2(self):
|
||||
@ -672,7 +678,10 @@ class BootLinuxConsole(LinuxKernelTest):
|
||||
|
||||
exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
|
||||
'Allwinner sun4i/sun5i')
|
||||
# cubieboard's reboot is not functioning; omit reboot test.
|
||||
exec_command_and_wait_for_pattern(self, 'reboot',
|
||||
'reboot: Restarting system')
|
||||
# Wait for VM to shut down gracefully
|
||||
self.vm.wait()
|
||||
|
||||
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
|
||||
def test_arm_quanta_gsj(self):
|
||||
|
Loading…
Reference in New Issue
Block a user