diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-07-04 08:58:27 -0400 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2025-07-04 08:58:27 -0400 |
commit | a876b05d38c813501e60fb50c8a45b30a965e902 (patch) | |
tree | 97f541131a77aa32473253047eb5638760bf32df /tests | |
parent | c77283dd5d79149f4e7e9edd00f65416c648ee59 (diff) | |
parent | 3a34dad2c0d25cebafed40696bbbdeb7ff4b9c7d (diff) | |
download | qemu-a876b05d38c813501e60fb50c8a45b30a965e902.zip qemu-a876b05d38c813501e60fb50c8a45b30a965e902.tar.gz qemu-a876b05d38c813501e60fb50c8a45b30a965e902.tar.bz2 |
Merge tag 'pull-aspeed-20250704' of https://github.com/legoater/qemu into staging
aspeed queue:
* Improved AST2700 SoC modeling (SDMC, SCU)
* Fixed hardware strapping of 'bletchley-bmc' machine
* Added new Meta 'catalina-bmc' machine and functional test using OpenBMC
* Improved AST2600 SCU protection key modeling
* Introduced AST2600 SCU unit tests
* Deprecated 'ast2700a0-evb' machine
* Added new NVIDIA 'gb200-bmc' machine and functional test using OpenBMC
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmhnknUACgkQUaNDx8/7
# 7KFPDBAAiHW7cu64JszAPk3SBHR8b021JpOrnF9Xp/UHMjNt0Kuazm6jkc/FeOJf
# yOKGfvuZUiLLcTrN8iCrVjjxIMKlzQP4KQEFaAPyxvKZo6j4czFZQ7AHS3G28w8l
# qrF4UsOhgQ6TL6fXMyqzDSLDEf5o/1ZCn1t+wkuDeVR7YVoAFj/si/A+qmIGQODJ
# egVmBopUzGrnGCcZREcKfJKmx1JOfVGFpm5HHPlazCaNTyKynd4rm2qP2St1eDEQ
# vOvSBZXKUHmpV9ckdY+Hp0VHvO2oIifDTN+Zbd2XT9RxO36VMnQxiSxOZOj/aRWa
# dc87OprPKjjS7Tbg7SZF7ySgfOShXWtNOwLuyrlw6BFsaHtwU2VP/mYR/Tfz/1Lw
# 57ufAj04nh8bWp7LApXyui53/1X431oBFji6agWnonMut+e5Xv0JKdBeCu2y8Fj4
# wPpiNcaa8AgHUuJ8T/WXrogeAYXYPI7z1iCY5tX9xffvcL6B3cVLGlI+mXoCIK7O
# MTuS5d8CB0gQondLS0Y86ls5pM3RkW6izragH38ukuubKIRq1hjxFDBnF8AQJl7A
# pUWTTxhxNZaJie0F5grD7aCVPCSSr1ck1V3zbW/ffVX+7kEtCBW/Zk4qfw9/SGxd
# 2QKbstRPNgTl78EKquYwipFVNyHTP/W8iXfxwpFALKBJFkmzAjQ=
# =i7wx
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 04 Jul 2025 04:36:05 EDT
# gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full]
# gpg: aka "Cédric Le Goater <clg@kaod.org>" [full]
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1
* tag 'pull-aspeed-20250704' of https://github.com/legoater/qemu:
tests/functional: Add gb200 tests
hw/arm/aspeed: Add GB200 BMC target
docs: add support for gb200-bmc
hw/arm/aspeed: Add second SPI chip to Aspeed model
aspeed: Deprecate the ast2700a0-evb machine
tests/qtest: Add test for ASPEED SCU
hw/misc/aspeed_scu: Handle AST2600 protection key registers correctly
hw/arm/aspeed: add Catalina machine type
hw/arm/aspeed: bletchley: update hw strap values
hw/misc/aspeed_scu: Support the Frequency Counter Control register for AST2700
hw/misc/aspeed_sdmc: Skipping dram_init in u-boot for AST2700
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/functional/aspeed.py | 9 | ||||
-rw-r--r-- | tests/functional/meson.build | 4 | ||||
-rwxr-xr-x | tests/functional/test_arm_aspeed_catalina.py | 25 | ||||
-rw-r--r-- | tests/functional/test_arm_aspeed_gb200nvl_bmc.py | 26 | ||||
-rw-r--r-- | tests/qtest/aspeed_scu-test.c | 231 | ||||
-rw-r--r-- | tests/qtest/meson.build | 1 |
6 files changed, 294 insertions, 2 deletions
diff --git a/tests/functional/aspeed.py b/tests/functional/aspeed.py index 7a40d5d..b131703 100644 --- a/tests/functional/aspeed.py +++ b/tests/functional/aspeed.py @@ -8,8 +8,13 @@ from qemu_test import LinuxKernelTest class AspeedTest(LinuxKernelTest): def do_test_arm_aspeed_openbmc(self, machine, image, uboot='2019.04', - cpu_id='0x0', soc='AST2500 rev A1'): - hostname = machine.removesuffix('-bmc') + cpu_id='0x0', soc='AST2500 rev A1', + image_hostname=None): + # Allow for the image hostname to not end in "-bmc" + if image_hostname is not None: + hostname = image_hostname + else: + hostname = machine.removesuffix('-bmc') self.set_machine(machine) self.vm.set_console() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index b542b3a..050c900 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -32,6 +32,8 @@ test_timeouts = { 'arm_aspeed_ast2500' : 720, 'arm_aspeed_ast2600' : 1200, 'arm_aspeed_bletchley' : 480, + 'arm_aspeed_catalina' : 480, + 'arm_aspeed_gb200nvl_bmc' : 480, 'arm_aspeed_rainier' : 480, 'arm_bpim2u' : 500, 'arm_collie' : 180, @@ -127,6 +129,8 @@ tests_arm_system_thorough = [ 'arm_aspeed_ast2500', 'arm_aspeed_ast2600', 'arm_aspeed_bletchley', + 'arm_aspeed_catalina', + 'arm_aspeed_gb200nvl_bmc', 'arm_aspeed_rainier', 'arm_bpim2u', 'arm_canona1100', diff --git a/tests/functional/test_arm_aspeed_catalina.py b/tests/functional/test_arm_aspeed_catalina.py new file mode 100755 index 0000000..dc2f24e --- /dev/null +++ b/tests/functional/test_arm_aspeed_catalina.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class CatalinaMachine(AspeedTest): + + ASSET_CATALINA_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/a866feb5ef81245b4827a214584bf6bcc72939f6/images/catalina-bmc/obmc-phosphor-image-catalina-20250619123021.static.mtd.xz', + '287402e1ba021991e06be1d098f509444a02a3d81a73a932f66528b159e864f9') + + def test_arm_ast2600_catalina_openbmc(self): + image_path = self.uncompress(self.ASSET_CATALINA_FLASH) + + self.do_test_arm_aspeed_openbmc('catalina-bmc', image=image_path, + uboot='2019.04', cpu_id='0xf00', + soc='AST2600 rev A3') + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/test_arm_aspeed_gb200nvl_bmc.py b/tests/functional/test_arm_aspeed_gb200nvl_bmc.py new file mode 100644 index 0000000..8e8e3f0 --- /dev/null +++ b/tests/functional/test_arm_aspeed_gb200nvl_bmc.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class GB200Machine(AspeedTest): + + ASSET_GB200_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/refs/heads/master/images/gb200nvl-obmc/obmc-phosphor-image-gb200nvl-obmc-20250702182348.static.mtd.xz', + 'b84819317cb3dc762895ad507705978ef000bfc77c50c33a63bdd37921db0dbc') + + def test_arm_aspeed_gb200_openbmc(self): + image_path = self.uncompress(self.ASSET_GB200_FLASH) + + self.do_test_arm_aspeed_openbmc('gb200nvl-bmc', image=image_path, + uboot='2019.04', cpu_id='0xf00', + soc='AST2600 rev A3', + image_hostname='gb200nvl-obmc') + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/qtest/aspeed_scu-test.c b/tests/qtest/aspeed_scu-test.c new file mode 100644 index 0000000..ca09f91 --- /dev/null +++ b/tests/qtest/aspeed_scu-test.c @@ -0,0 +1,231 @@ +/* + * QTest testcase for the ASPEED AST2500 and AST2600 SCU. + * + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2025 Tan Siewert + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +/* + * SCU base, as well as protection key are + * the same on AST2500 and 2600. + */ +#define AST_SCU_BASE 0x1E6E2000 +#define AST_SCU_PROT_LOCK_STATE 0x0 +#define AST_SCU_PROT_LOCK_VALUE 0x2 +#define AST_SCU_PROT_UNLOCK_STATE 0x1 +#define AST_SCU_PROT_UNLOCK_VALUE 0x1688A8A8 + +#define AST2500_MACHINE "-machine ast2500-evb" +#define AST2500_SCU_PROT_REG 0x00 +#define AST2500_SCU_MISC_2_CONTROL_REG 0x4C + +#define AST2600_MACHINE "-machine ast2600-evb" +/* AST2600 has two protection registers */ +#define AST2600_SCU_PROT_REG 0x000 +#define AST2600_SCU_PROT_REG2 0x010 +#define AST2600_SCU_MISC_2_CONTROL_REG 0x0C4 + +#define TEST_LOCK_ARBITRARY_VALUE 0xABCDEFAB + +/** + * Assert that a given register matches an expected value. + * + * Reads the register and checks if its value equals the expected value. + * + * @param *s - QTest machine state + * @param reg - Address of the register to be checked + * @param expected - Expected register value + */ +static inline void assert_register_eq(QTestState *s, + uint32_t reg, + uint32_t expected) +{ + uint32_t value = qtest_readl(s, reg); + g_assert_cmphex(value, ==, expected); +} + +/** + * Assert that a given register does not match a specific value. + * + * Reads the register and checks that its value is not equal to the + * provided value. + * + * @param *s - QTest machine state + * @param reg - Address of the register to be checked + * @param not_expected - Value the register must not contain + */ +static inline void assert_register_neq(QTestState *s, + uint32_t reg, + uint32_t not_expected) +{ + uint32_t value = qtest_readl(s, reg); + g_assert_cmphex(value, !=, not_expected); +} + +/** + * Test whether the SCU can be locked and unlocked correctly. + * + * When testing multiple registers, this function assumes that writing + * to the first register also affects the others. However, writing to + * any other register only affects itself. + * + * @param *machine - input machine configuration, passed directly + * to QTest + * @param regs[] - List of registers to be checked + * @param regc - amount of arguments for registers to be checked + */ +static void test_protection_register(const char *machine, + const uint32_t regs[], + const int regc) +{ + QTestState *s = qtest_init(machine); + + for (int i = 0; i < regc; i++) { + uint32_t reg = regs[i]; + + qtest_writel(s, reg, AST_SCU_PROT_UNLOCK_VALUE); + assert_register_eq(s, reg, AST_SCU_PROT_UNLOCK_STATE); + + /** + * Check that other registers are unlocked too, if more + * than one is available. + */ + if (regc > 1 && i == 0) { + /* Initialise at 1 instead of 0 to skip first */ + for (int j = 1; j < regc; j++) { + uint32_t add_reg = regs[j]; + assert_register_eq(s, add_reg, AST_SCU_PROT_UNLOCK_STATE); + } + } + + /* Lock the register again */ + qtest_writel(s, reg, AST_SCU_PROT_LOCK_VALUE); + assert_register_eq(s, reg, AST_SCU_PROT_LOCK_STATE); + + /* And the same for locked state */ + if (regc > 1 && i == 0) { + /* Initialise at 1 instead of 0 to skip first */ + for (int j = 1; j < regc; j++) { + uint32_t add_reg = regs[j]; + assert_register_eq(s, add_reg, AST_SCU_PROT_LOCK_STATE); + } + } + } + + qtest_quit(s); +} + +static void test_2500_protection_register(void) +{ + uint32_t regs[] = { AST_SCU_BASE + AST2500_SCU_PROT_REG }; + + test_protection_register(AST2500_MACHINE, + regs, + ARRAY_SIZE(regs)); +} + +static void test_2600_protection_register(void) +{ + /** + * The AST2600 has two protection registers, both + * being required to be unlocked to do any operation. + * + * Modifying SCU000 also modifies SCU010, but modifying + * SCU010 only will keep SCU000 untouched. + */ + uint32_t regs[] = { AST_SCU_BASE + AST2600_SCU_PROT_REG, + AST_SCU_BASE + AST2600_SCU_PROT_REG2 }; + + test_protection_register(AST2600_MACHINE, + regs, + ARRAY_SIZE(regs)); +} + +/** + * Test if SCU register writes are correctly allowed or blocked + * depending on the protection register state. + * + * The test first locks the protection register and verifies that + * writes to the target SCU register are rejected. It then unlocks + * the protection register and confirms that the written value is + * retained when unlocked. + * + * @param *machine - input machine configuration, passed directly + * to QTest + * @param protection_register - first SCU protection key register + * (only one for keeping it simple) + * @param test_register - Register to be used for writing arbitrary + * values + */ +static void test_write_permission_lock_state(const char *machine, + const uint32_t protection_register, + const uint32_t test_register) +{ + QTestState *s = qtest_init(machine); + + /* Arbitrary value to lock provided SCU protection register */ + qtest_writel(s, protection_register, AST_SCU_PROT_LOCK_VALUE); + + /* Ensure that the SCU is really locked */ + assert_register_eq(s, protection_register, AST_SCU_PROT_LOCK_STATE); + + /* Write a known arbitrary value to test that the write is blocked */ + qtest_writel(s, test_register, TEST_LOCK_ARBITRARY_VALUE); + + /* We do not want to have the written value to be saved */ + assert_register_neq(s, test_register, TEST_LOCK_ARBITRARY_VALUE); + + /** + * Unlock the SCU and verify that it can be written to. + * Assumes that the first SCU protection register is sufficient to + * unlock all protection registers, if multiple are present. + */ + qtest_writel(s, protection_register, AST_SCU_PROT_UNLOCK_VALUE); + assert_register_eq(s, protection_register, AST_SCU_PROT_UNLOCK_STATE); + + /* Write a known arbitrary value to test that the write works */ + qtest_writel(s, test_register, TEST_LOCK_ARBITRARY_VALUE); + + /* Ensure that the written value is retained */ + assert_register_eq(s, test_register, TEST_LOCK_ARBITRARY_VALUE); + + qtest_quit(s); +} + +static void test_2500_write_permission_lock_state(void) +{ + test_write_permission_lock_state( + AST2500_MACHINE, + AST_SCU_BASE + AST2500_SCU_PROT_REG, + AST_SCU_BASE + AST2500_SCU_MISC_2_CONTROL_REG + ); +} + +static void test_2600_write_permission_lock_state(void) +{ + test_write_permission_lock_state( + AST2600_MACHINE, + AST_SCU_BASE + AST2600_SCU_PROT_REG, + AST_SCU_BASE + AST2600_SCU_MISC_2_CONTROL_REG + ); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/ast2500/scu/protection_register", + test_2500_protection_register); + qtest_add_func("/ast2600/scu/protection_register", + test_2600_protection_register); + + qtest_add_func("/ast2500/scu/write_permission_lock_state", + test_2500_write_permission_lock_state); + qtest_add_func("/ast2600/scu/write_permission_lock_state", + test_2600_write_permission_lock_state); + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 8ad8490..91b4a71 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -215,6 +215,7 @@ qtests_npcm8xx = \ qtests_aspeed = \ ['aspeed_gpio-test', 'aspeed_hace-test', + 'aspeed_scu-test', 'aspeed_smc-test'] qtests_aspeed64 = \ ['ast2700-gpio-test', |