From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id E18A8C433EF for ; Mon, 4 Jul 2022 13:59:36 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 802C76B0072; Mon, 4 Jul 2022 09:59:36 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 7B1746B0078; Mon, 4 Jul 2022 09:59:36 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 604BF6B007B; Mon, 4 Jul 2022 09:59:36 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 4C6F46B0072 for ; Mon, 4 Jul 2022 09:59:36 -0400 (EDT) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 2248434453 for ; Mon, 4 Jul 2022 13:59:36 +0000 (UTC) X-FDA: 79649575152.11.14878FE Received: from mail-vs1-f51.google.com (mail-vs1-f51.google.com [209.85.217.51]) by imf03.hostedemail.com (Postfix) with ESMTP id B572B20003 for ; Mon, 4 Jul 2022 13:59:35 +0000 (UTC) Received: by mail-vs1-f51.google.com with SMTP id j1so9071339vsj.12 for ; Mon, 04 Jul 2022 06:59:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=eclypsium.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=z0DiM2QAFWfRCxyX4K2DXOUSOAXhJvDrH/Deu05TYDY=; b=cMagWlDmtdm3o1f6Pp61sL3GddrPHHQmPJWDvSTOuRfLNvZ4cPGhTJfzZcNjMxrfjr sEbPLuO9RK2jvBXKZnS9xayzZJumnLdPqvIynQ9cWked5s3vnTxQdeo28d4/wfb8C+zL +VqvZGqgvnIkqw2lFDv9JbvIbcCYWy3hB/iNAJspkY9a7o4Q1VoIgfVn/623KrxQ6I8u eBXrG3RP91GB1gMw5zXSyVmi+899r4kspuuZqoR6lSx57tZplo1sbF5vEuTQ+y2qVoe1 Uleb7KRX5XfIrNZYJg5CDMbrmtp+/rvl0vg6DLjHMniyMb0Rvs4lD12kZGILIPOpk4sW U/4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=z0DiM2QAFWfRCxyX4K2DXOUSOAXhJvDrH/Deu05TYDY=; b=ojRv58jQBLGSt7wNdfo6c261m2dGJluA0DHDkUwnVMeX/p2BWJIsYrPDIwSIz5KeyX nNxMRhUMObRRgbV/ZImzoPk34NJ85i8w3quQQHKCQoW4LIHlPeRihtYyv3P2KhomheNh zM6hlzaryeCnldhYCF8hqnA3aE0KycdanFPBA51Ldm2PCl/fNSmN5pIzicomece+9REW R8eetMy6dOUOfoSxSLT0sJi73Uc74fmqawknekHd5hU5YmOD8jFHAhm8KddG6JGl6prO EnDleXsCzP/lsk2ZxLGFY4IfHMxHyMYLGnSxptxGRc34BWjAzz1WpIqkZDnTdOq0UTWn LI5g== X-Gm-Message-State: AJIora+ed0Mc6gqnoaVdKoFATtuxdhtTXy39WhWYxw/Wmf1zST1Y8upO fJeVBN6KAmTnzn7Vmz1t1nkl0Q== X-Google-Smtp-Source: AGRyM1sE6muSOvx2k+xe3UnPJZ2WVCBPj7qW4PpsjOJJKZzXCsbFp4uxqOIHZ9lHyDxUhrjpJWshnQ== X-Received: by 2002:a67:eb0b:0:b0:354:5c77:775c with SMTP id a11-20020a67eb0b000000b003545c77775cmr17327338vso.46.1656943175020; Mon, 04 Jul 2022 06:59:35 -0700 (PDT) Received: from localhost ([181.97.174.128]) by smtp.gmail.com with ESMTPSA id x24-20020ab036f8000000b0038296f80d22sm724438uau.8.2022.07.04.06.59.29 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 04 Jul 2022 06:59:34 -0700 (PDT) From: Martin Fernandez To: linux-kernel@vger.kernel.org, linux-efi@vger.kernel.org, platform-driver-x86@vger.kernel.org, linux-mm@kvack.org, kunit-dev@googlegroups.com, linux-kselftest@vger.kernel.org Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, ardb@kernel.org, dvhart@infradead.org, andy@infradead.org, gregkh@linuxfoundation.org, rafael@kernel.org, rppt@kernel.org, akpm@linux-foundation.org, daniel.gutson@eclypsium.com, hughsient@gmail.com, alex.bazhaniuk@eclypsium.com, alison.schofield@intel.com, keescook@chromium.org, Martin Fernandez Subject: [PATCH v9 7/9] x86/e820: Add unit tests for e820_range_* functions Date: Mon, 4 Jul 2022 10:58:31 -0300 Message-Id: <20220704135833.1496303-8-martin.fernandez@eclypsium.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220704135833.1496303-1-martin.fernandez@eclypsium.com> References: <20220704135833.1496303-1-martin.fernandez@eclypsium.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1656943175; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=z0DiM2QAFWfRCxyX4K2DXOUSOAXhJvDrH/Deu05TYDY=; b=U1V7jTEk5Yr1xk0v9N9vWsMVhEMegTerLGo5nrsgnZlQNbLOa2SPVgtQqmcxYyFDrdTRWj oJ8ZLbL8N3cbBvBZt/QVSUBSWnu2AbOzQmp8wQdbnaFhoF7BmX9gSAVfSsf8B+9ci2eO2R p4dkFAbIXESxZBtx6nZA8UOoB5OEQFs= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1656943175; a=rsa-sha256; cv=none; b=vrKzVTokjI/z46C/kLcMM99L0T1fdP9ECGAxcJLdVvVNDNRd6PTr9utdMg6FrrOJ1YihhB 7dvIAl4UZ/GeQJ/mwVaG5i0dW+oPzBJQz6jjbo0RlnJGMVo9ZhAaTq5k1W+c3zuQZxcHpR WnYQTlT+QtgwQYfxkFRzUM3PjIrj+Po= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=pass header.d=eclypsium.com header.s=google header.b=cMagWlDm; dmarc=pass (policy=quarantine) header.from=eclypsium.com; spf=pass (imf03.hostedemail.com: domain of martin.fernandez@eclypsium.com designates 209.85.217.51 as permitted sender) smtp.mailfrom=martin.fernandez@eclypsium.com X-Stat-Signature: 68x5ig73e1pyqxdi1a7kk41omz633nzi X-Rspamd-Queue-Id: B572B20003 X-Rspam-User: Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=eclypsium.com header.s=google header.b=cMagWlDm; dmarc=pass (policy=quarantine) header.from=eclypsium.com; spf=pass (imf03.hostedemail.com: domain of martin.fernandez@eclypsium.com designates 209.85.217.51 as permitted sender) smtp.mailfrom=martin.fernandez@eclypsium.com X-Rspamd-Server: rspam06 X-HE-Tag: 1656943175-338427 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Add KUnit tests for the e820_range_* functions. Signed-off-by: Martin Fernandez --- arch/x86/Kconfig.debug | 10 ++ arch/x86/kernel/e820.c | 5 + arch/x86/kernel/e820_test.c | 249 ++++++++++++++++++++++++++++++++++++ 3 files changed, 264 insertions(+) create mode 100644 arch/x86/kernel/e820_test.c diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index d872a7522e55..b5040d345fb4 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -225,6 +225,16 @@ config PUNIT_ATOM_DEBUG The current power state can be read from /sys/kernel/debug/punit_atom/dev_power_state +config E820_KUNIT_TEST + tristate "Tests for E820" if !KUNIT_ALL_TESTS + depends on KUNIT=y + default KUNIT_ALL_TESTS + help + This option enables unit tests for the e820.c code. It + should be enabled only in development environments. + + If unsure, say N. + choice prompt "Choose kernel unwinder" default UNWINDER_ORC if X86_64 diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index dade59758b9f..a6ced3e306dd 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1546,3 +1546,8 @@ void __init e820__memblock_setup(void) memblock_dump_all(); } + +#ifdef CONFIG_E820_KUNIT_TEST +/* Let e820_test have access the static functions in this file */ +#include "e820_test.c" +#endif diff --git a/arch/x86/kernel/e820_test.c b/arch/x86/kernel/e820_test.c new file mode 100644 index 000000000000..6b28ea131380 --- /dev/null +++ b/arch/x86/kernel/e820_test.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include + +#include +#include + +#define KUNIT_EXPECT_E820_ENTRY_EQ(_test, _entry, _addr, _size, _type, \ + _crypto_capable) \ + do { \ + KUNIT_EXPECT_EQ((_test), (_entry).addr, (_addr)); \ + KUNIT_EXPECT_EQ((_test), (_entry).size, (_size)); \ + KUNIT_EXPECT_EQ((_test), (_entry).type, (_type)); \ + KUNIT_EXPECT_EQ((_test), (_entry).crypto_capable, \ + (_crypto_capable)); \ + } while (0) + +struct e820_table test_table __initdata; + +static void __init test_e820_range_add(struct kunit *test) +{ + u32 full = ARRAY_SIZE(test_table.entries); + /* Add last entry. */ + test_table.nr_entries = full - 1; + __e820__range_add(&test_table, 0, 15, 0, 0); + KUNIT_EXPECT_EQ(test, test_table.nr_entries, full); + /* Skip new entry when full. */ + __e820__range_add(&test_table, 0, 15, 0, 0); + KUNIT_EXPECT_EQ(test, test_table.nr_entries, full); +} + +static void __init test_e820_range_update(struct kunit *test) +{ + u64 entry_size = 15; + u64 updated_size = 0; + /* Initialize table */ + test_table.nr_entries = 0; + __e820__range_add(&test_table, 0, entry_size, E820_TYPE_RAM, + E820_NOT_CRYPTO_CAPABLE); + __e820__range_add(&test_table, entry_size, entry_size, E820_TYPE_RAM, + E820_NOT_CRYPTO_CAPABLE); + __e820__range_add(&test_table, entry_size * 2, entry_size, + E820_TYPE_ACPI, E820_NOT_CRYPTO_CAPABLE); + + updated_size = __e820__range_update(&test_table, 0, entry_size * 2, + E820_TYPE_RAM, E820_TYPE_RESERVED); + + /* The first 2 regions were updated */ + KUNIT_EXPECT_EQ(test, updated_size, entry_size * 2); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[0], 0, entry_size, + E820_TYPE_RESERVED, E820_NOT_CRYPTO_CAPABLE); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[1], entry_size, + entry_size, E820_TYPE_RESERVED, + E820_NOT_CRYPTO_CAPABLE); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[2], entry_size * 2, + entry_size, E820_TYPE_ACPI, + E820_NOT_CRYPTO_CAPABLE); + + updated_size = __e820__range_update(&test_table, 0, entry_size * 3, + E820_TYPE_RESERVED, E820_TYPE_RAM); + + /* + * Only the first 2 regions were updated, + * since E820_TYPE_ACPI > E820_TYPE_RESERVED + */ + KUNIT_EXPECT_EQ(test, updated_size, entry_size * 2); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[0], 0, entry_size, + E820_TYPE_RAM, E820_NOT_CRYPTO_CAPABLE); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[1], entry_size, + entry_size, E820_TYPE_RAM, + E820_NOT_CRYPTO_CAPABLE); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[2], entry_size * 2, + entry_size, E820_TYPE_ACPI, + E820_NOT_CRYPTO_CAPABLE); +} + +static void __init test_e820_range_remove(struct kunit *test) +{ + u64 entry_size = 15; + u64 removed_size = 0; + + struct e820_entry_updater updater = { .should_update = + remover__should_update, + .update = remover__update, + .new = NULL }; + + struct e820_remover_data data = { .check_type = true, + .old_type = E820_TYPE_RAM }; + + /* Initialize table */ + test_table.nr_entries = 0; + __e820__range_add(&test_table, 0, entry_size, E820_TYPE_RAM, + E820_NOT_CRYPTO_CAPABLE); + __e820__range_add(&test_table, entry_size, entry_size, E820_TYPE_RAM, + E820_NOT_CRYPTO_CAPABLE); + __e820__range_add(&test_table, entry_size * 2, entry_size, + E820_TYPE_ACPI, E820_NOT_CRYPTO_CAPABLE); + + /* + * Need to use __e820__handle_range_update because + * e820__range_remove doesn't ask for the table + */ + removed_size = __e820__handle_range_update(&test_table, + 0, entry_size * 2, + &updater, &data); + + /* The first two regions were removed */ + KUNIT_EXPECT_EQ(test, removed_size, entry_size * 2); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[0], 0, 0, 0, 0); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[1], 0, 0, 0, 0); + + removed_size = __e820__handle_range_update(&test_table, + 0, entry_size * 3, + &updater, &data); + + /* Nothing was removed, since nothing matched the target type */ + KUNIT_EXPECT_EQ(test, removed_size, 0); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[0], 0, 0, 0, 0); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[1], 0, 0, 0, 0); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[2], entry_size * 2, + entry_size, E820_TYPE_ACPI, + E820_NOT_CRYPTO_CAPABLE); +} + +static void __init test_e820_range_crypto_update(struct kunit *test) +{ + u64 entry_size = 15; + u64 updated_size = 0; + /* Initialize table */ + test_table.nr_entries = 0; + __e820__range_add(&test_table, 0, entry_size, E820_TYPE_RAM, + E820_CRYPTO_CAPABLE); + __e820__range_add(&test_table, entry_size, entry_size, E820_TYPE_RAM, + E820_NOT_CRYPTO_CAPABLE); + __e820__range_add(&test_table, entry_size * 2, entry_size, + E820_TYPE_RAM, E820_CRYPTO_CAPABLE); + + updated_size = __e820__range_update_crypto(&test_table, + 0, entry_size * 3, + E820_CRYPTO_CAPABLE); + + /* Only the region in the middle was updated */ + KUNIT_EXPECT_EQ(test, updated_size, entry_size); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[0], 0, entry_size, + E820_TYPE_RAM, E820_CRYPTO_CAPABLE); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[1], entry_size, + entry_size, E820_TYPE_RAM, + E820_CRYPTO_CAPABLE); + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[2], entry_size * 2, + entry_size, E820_TYPE_RAM, + E820_CRYPTO_CAPABLE); +} + +static void __init test_e820_handle_range_update_intersection(struct kunit *test) +{ + struct e820_entry_updater updater = { + .should_update = type_updater__should_update, + .update = type_updater__update, + .new = type_updater__new + }; + + struct e820_type_updater_data data = { .old_type = E820_TYPE_RAM, + .new_type = E820_TYPE_RESERVED }; + + u64 entry_size = 15; + u64 intersection_size = 2; + u64 updated_size = 0; + /* Initialize table */ + test_table.nr_entries = 0; + __e820__range_add(&test_table, 0, entry_size, E820_TYPE_RAM, + E820_NOT_CRYPTO_CAPABLE); + + updated_size = + __e820__handle_range_update(&test_table, 0, + entry_size - intersection_size, + &updater, &data); + + KUNIT_EXPECT_EQ(test, updated_size, entry_size - intersection_size); + + /* There is a new entry */ + KUNIT_EXPECT_EQ(test, test_table.nr_entries, intersection_size); + + /* The original entry now is moved */ + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[0], + entry_size - intersection_size, + intersection_size, E820_TYPE_RAM, + E820_NOT_CRYPTO_CAPABLE); + + /* The new entry has the correct values */ + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[1], 0, + entry_size - intersection_size, + E820_TYPE_RESERVED, E820_NOT_CRYPTO_CAPABLE); +} + +static void __init test_e820_handle_range_update_inside(struct kunit *test) +{ + struct e820_entry_updater updater = { + .should_update = type_updater__should_update, + .update = type_updater__update, + .new = type_updater__new + }; + + struct e820_type_updater_data data = { .old_type = E820_TYPE_RAM, + .new_type = E820_TYPE_RESERVED }; + + u64 entry_size = 15; + u64 updated_size = 0; + /* Initialize table */ + test_table.nr_entries = 0; + __e820__range_add(&test_table, 0, entry_size, E820_TYPE_RAM, + E820_NOT_CRYPTO_CAPABLE); + + updated_size = __e820__handle_range_update(&test_table, 5, + entry_size - 10, + &updater, &data); + + KUNIT_EXPECT_EQ(test, updated_size, entry_size - 10); + + /* There are two new entrie */ + KUNIT_EXPECT_EQ(test, test_table.nr_entries, 3); + + /* The original entry now shrunk */ + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[0], 0, 5, + E820_TYPE_RAM, E820_NOT_CRYPTO_CAPABLE); + + /* The new entries have the correct values */ + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[1], 5, + entry_size - 10, E820_TYPE_RESERVED, + E820_NOT_CRYPTO_CAPABLE); + /* Left over of the original region */ + KUNIT_EXPECT_E820_ENTRY_EQ(test, test_table.entries[2], entry_size - 5, + 5, E820_TYPE_RAM, E820_NOT_CRYPTO_CAPABLE); +} + +static struct kunit_case e820_test_cases[] __initdata = { + KUNIT_CASE(test_e820_range_add), + KUNIT_CASE(test_e820_range_update), + KUNIT_CASE(test_e820_range_remove), + KUNIT_CASE(test_e820_range_crypto_update), + KUNIT_CASE(test_e820_handle_range_update_intersection), + KUNIT_CASE(test_e820_handle_range_update_inside), + {} +}; + +static struct kunit_suite e820_test_suite __initdata = { + .name = "e820", + .test_cases = e820_test_cases, +}; + +kunit_test_init_section_suite(e820_test_suite); -- 2.30.2