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 lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6B8EA1093178 for ; Fri, 20 Mar 2026 05:24:24 +0000 (UTC) Received: from boromir.ozlabs.org (localhost [127.0.0.1]) by lists.ozlabs.org (Postfix) with ESMTP id 4fcWFy5Zlsz2yY1; Fri, 20 Mar 2026 16:24:22 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; arc=none smtp.remote-ip="2607:f8b0:4864:20::42f" ARC-Seal: i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1773984262; cv=none; b=mC87wmmCP4Zimum66JdrqH53MsHkwlSzKmEoIK5pDo1+dIUY0Vc8TcUgT2EM8jHfD2vowD1+fhtaAch6stuFA6DhDD+H1ugL+5681ssKmEWqotOfcnshRdoHynJnGmrX4VQi86A0V7bbWVyKFIw6jCISxl/Fgx6rFqLP5yi/nTT+tnLIUC3FnQnRiWFB8xM9Y/YK56fp4jqvLEb8hcJSj5X2GLvY5ulLIBGYHopaR85WUNGqmOkcy8+4tdyNQfmPw1Jksi4XJg2ET5I1Yv6hhSE9iTRV5WbBtbaX3HUr4NcjcxV6BUtH+5QXHZc5LKtWwCJgiXOTKF3UcKUYOyCM8g== ARC-Message-Signature: i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1773984262; c=relaxed/relaxed; bh=wLeUwMCfEp8eEcDYTzjt0sXlpqSHQtTVQ6yFHJWh/lI=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=ZVuSlzEpBXXyJlKkcB8AtfzGgcFUxPRdusmCNE6Vc6xPd/o5xCbwvyrLL+CxT94aIZMya/hbT6oXy/gIPhFBhaN2oQSgND26aNbOT9Bdbrae8nF3REYVQi0n2tIzL7j13/lglUxpr5DhS9ZfRO8hME7ARI4qgOwcPWcBy9/eB4t78CiLph8LKFhNZGLcqUcWwWctCaYvd6UT8zl0eW2ZkF4DXbRQXT7sSPcQYsqXMcKBoE/pXUzNx98H5ap3wYrLnYbJcCvfkV3hucwUKVRSPFmqZnWNJ0TSMG2yH4uHXYKrILe2cRglxrFXwapucwXV9Ft2m5LRBs9vntso++TWHA== ARC-Authentication-Results: i=1; lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=AHnD8Ggr; dkim-atps=neutral; spf=pass (client-ip=2607:f8b0:4864:20::42f; helo=mail-pf1-x42f.google.com; envelope-from=mkchauras@gmail.com; receiver=lists.ozlabs.org) smtp.mailfrom=gmail.com Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=AHnD8Ggr; dkim-atps=neutral Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::42f; helo=mail-pf1-x42f.google.com; envelope-from=mkchauras@gmail.com; receiver=lists.ozlabs.org) Received: from mail-pf1-x42f.google.com (mail-pf1-x42f.google.com [IPv6:2607:f8b0:4864:20::42f]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4fcWFx1zz4z2yWK for ; Fri, 20 Mar 2026 16:24:20 +1100 (AEDT) Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-829865a8471so252501b3a.3 for ; Thu, 19 Mar 2026 22:24:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773984257; x=1774589057; darn=lists.ozlabs.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=wLeUwMCfEp8eEcDYTzjt0sXlpqSHQtTVQ6yFHJWh/lI=; b=AHnD8GgrHk6Hk44w1mv3U1TJ0Ggxuv+YyEEukWy9pSNUZa/W3/kxs1HqJALWxguMwA QzdUf7I+OEt5+lOXe9EL0vfYkOthf7QRRCTSySSZIc9IRNhCmrSQHdZxNzXE0RJDLviX xfTpGNl4sfooIdBCqMAPF1r2e+GmjXqtA1UeX3P+bvpehBHLywTFFbad8IXnPDbYNz6O PoMzyUb9k1IqEmQFGNEatdSTIFiC4fjmsn8DDMeEwLkroEV+tXyE0kMiKYZpw/ywNQQl 5q/ek0HC/0ZdZG6E0IOOrcn3EnDMVsw6gwDbE5yr3g4oQYo9aHiN4szXrjLum1dJTP4n afpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773984257; x=1774589057; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=wLeUwMCfEp8eEcDYTzjt0sXlpqSHQtTVQ6yFHJWh/lI=; b=KRbxR55WXDqlmbHoL+TPungGDoNjzzrzJMK9nlslnbxR9DV5+nEgko5InkRPB6xECw KN1uHMi5AuMZmNT3aBGBP7IAYqYtWKZWmcNZhMgXAc+DCj39js7nZ/H762gTY50iNI9A O6XcIc5fn1ER/a63KkKgK/stB8oanrUxJ98YKb52jirHX2JFLpSi1CpHYbQOj8P1p9zn jN5qgVPA/VZ8X1xsq8FeMW/LIS0FF0Phpijx2Zu98mumN/IPATGBwLT7FbbbbIcmdDa+ bmkd+mnrYLrjxXXvLN9j2Q/zEKfHToYUjQBYMomtxYLb8MvsotE+MB5AFpLQeECz13fF L76A== X-Forwarded-Encrypted: i=1; AJvYcCWHt0ZhWlEbmNrF1QMi0Z3pbMZk5dM7PeRDHtBaeX2gAJ1W8O3l3fdPVR481h1a83IDyrVUHeuqLVGowdM=@lists.ozlabs.org X-Gm-Message-State: AOJu0YyqGbTZUmCBJBIYOpeuo2LIo5PCnbsObxFH66o/rrvZtLrF0HDG Jq7Dn8ioU7OW8mbUzFVQa1AJ+PYIKz8kVrzwfhncPIZZcH7XTC91bdAq X-Gm-Gg: ATEYQzwUO6/URfIYHhjc3WRT9tvwbkvO3ZTl8cU+Z3p0xYJo8OZdpDC7xukwE9C4uEu ZzgeLmm1cNxW+C7ZSn5J7cuEsn1IT/yvcrQuNaBz4D7PHm/Pw4mtzPKNJBcRGftpE//H+/EiPCR YWyGsLiZcoLKIZfJzf9Ffw+u/UxLmJTpCKqwSjU5ZvAvfHwdmD20NO4gBnhW+2Xps1IdbwEXz9a hoC2aOBHEHD6pXDegEwCzSfS+otmHALfD/exUsg5ik+xOk+SUjlkUVxcGbkIQLAAXQxlRXYumqH Bbiz+umotenKGPBjozwl6wVm7OOZS1w4vvNZ1MTzbucpQqSdzprKpiQqQY1Jjy4I0CRZiLOuOre nEeEtI+aS+VExGar2+FYgc3x4dxt1r1U3oxPIySlTujpq2SlNG5PZ12lHztzlohhlGtFTwOZiyF FJuUAwzMM3Qjr/5+WyBLW/SOtVXfmDvHfmY7bPRrh45fJ6ya4cpcNjeoDfnc+futHXyFi8tug= X-Received: by 2002:a05:6a00:328c:b0:81f:3fa0:8c38 with SMTP id d2e1a72fcca58-82a8c285868mr1577867b3a.20.1773984256943; Thu, 19 Mar 2026 22:24:16 -0700 (PDT) Received: from li-1a3e774c-28e4-11b2-a85c-acc9f2883e29.ibm.com ([49.207.193.112]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82b0409c11asm802316b3a.30.2026.03.19.22.24.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2026 22:24:16 -0700 (PDT) From: "Mukesh Kumar Chaurasiya (IBM)" To: maddy@linux.ibm.com, mpe@ellerman.id.au, npiggin@gmail.com, chleroy@kernel.org, mkchauras@gmail.com, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org Subject: [PATCH] powerpc/xive: KUnit tests for xive interrupt controller Date: Fri, 20 Mar 2026 10:54:00 +0530 Message-ID: <20260320052400.3230999-1-mkchauras@gmail.com> X-Mailer: git-send-email 2.53.0 X-Mailing-List: linuxppc-dev@lists.ozlabs.org List-Id: List-Help: List-Owner: List-Post: List-Archive: , List-Subscribe: , , List-Unsubscribe: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Kunit tests for xive interrupt controller. Signed-off-by: Mukesh Kumar Chaurasiya (IBM) --- arch/powerpc/sysdev/xive/.kunitconfig | 4 + arch/powerpc/sysdev/xive/Kconfig | 9 + arch/powerpc/sysdev/xive/Makefile | 7 +- arch/powerpc/sysdev/xive/xive-test.c | 294 ++++++++++++++++++++++++++ 4 files changed, 311 insertions(+), 3 deletions(-) create mode 100644 arch/powerpc/sysdev/xive/.kunitconfig create mode 100644 arch/powerpc/sysdev/xive/xive-test.c diff --git a/arch/powerpc/sysdev/xive/.kunitconfig b/arch/powerpc/sysdev/xive/.kunitconfig new file mode 100644 index 000000000000..ea6634bb0718 --- /dev/null +++ b/arch/powerpc/sysdev/xive/.kunitconfig @@ -0,0 +1,4 @@ +CONFIG_KUNIT=y +CONFIG_PPC_PSERIES=y +CONFIG_PPC_XIVE_SPAPR=y +CONFIG_PPC_XIVE_KUNIT_TEST=y \ No newline at end of file diff --git a/arch/powerpc/sysdev/xive/Kconfig b/arch/powerpc/sysdev/xive/Kconfig index 785c292d104b..81727b9c22b7 100644 --- a/arch/powerpc/sysdev/xive/Kconfig +++ b/arch/powerpc/sysdev/xive/Kconfig @@ -12,3 +12,12 @@ config PPC_XIVE_NATIVE config PPC_XIVE_SPAPR bool select PPC_XIVE + +config PPC_XIVE_KUNIT_TEST + tristate "KUnit tests for XIVE interrupt controller" if !KUNIT_ALL_TESTS + depends on KUNIT && PPC_XIVE + default KUNIT_ALL_TESTS + help + This builds unit tests for the XIVE interrupt controller. + + If unsure, say N. diff --git a/arch/powerpc/sysdev/xive/Makefile b/arch/powerpc/sysdev/xive/Makefile index e5108883894a..e1f9f513af09 100644 --- a/arch/powerpc/sysdev/xive/Makefile +++ b/arch/powerpc/sysdev/xive/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y += common.o -obj-$(CONFIG_PPC_XIVE_NATIVE) += native.o -obj-$(CONFIG_PPC_XIVE_SPAPR) += spapr.o +obj-y += common.o +obj-$(CONFIG_PPC_XIVE_NATIVE) += native.o +obj-$(CONFIG_PPC_XIVE_SPAPR) += spapr.o +obj-$(CONFIG_PPC_XIVE_KUNIT_TEST) += xive-test.o diff --git a/arch/powerpc/sysdev/xive/xive-test.c b/arch/powerpc/sysdev/xive/xive-test.c new file mode 100644 index 000000000000..ee08f18af864 --- /dev/null +++ b/arch/powerpc/sysdev/xive/xive-test.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * KUnit tests for XIVE interrupt controller + * + * Copyright 2026 IBM Corporation. + */ + +#include +#include +#include +#include +#include + +/* + * Mock xive_try_pick_target for testing + * The real function checks queue capacity, we simplify for testing + */ +static bool xive_try_pick_target(int cpu) +{ + /* For testing, accept any online CPU */ + return cpu_online(cpu); +} + +/* + * Copy of xive_find_target_in_mask from common.c for testing + * This allows us to test the static function without modifying source + */ +static int xive_find_target_in_mask(const struct cpumask *mask, + unsigned int fuzz) +{ + int cpu, first; + + /* Pick up a starting point CPU in the mask based on fuzz */ + fuzz %= cpumask_weight(mask); + first = cpumask_nth(fuzz, mask); + WARN_ON(first >= nr_cpu_ids); + + /* + * Now go through the entire mask until we find a valid + * target. + */ + for_each_cpu_wrap(cpu, mask, first) { + if (cpu_online(cpu) && xive_try_pick_target(cpu)) + return cpu; + } + + return -1; +} + +/* + * Test: Empty CPU mask + * Expected: Should return -1 when the mask contains no CPUs + */ +static void xive_test_find_target_empty_mask(struct kunit *test) +{ + struct cpumask empty_mask; + int result; + + cpumask_clear(&empty_mask); + + result = xive_find_target_in_mask(&empty_mask, 0); + + KUNIT_EXPECT_EQ(test, result, -1); +} + +/* + * Test: Single CPU in mask + * Expected: Should return that CPU if it's online + */ +static void xive_test_find_target_single_cpu(struct kunit *test) +{ + struct cpumask single_mask; + int cpu = 0; + int result; + + /* Skip test if CPU 0 is not online */ + if (!cpu_online(0)) + kunit_skip(test, "CPU 0 is not online"); + + cpumask_clear(&single_mask); + cpumask_set_cpu(cpu, &single_mask); + + result = xive_find_target_in_mask(&single_mask, 0); + + KUNIT_EXPECT_EQ(test, result, cpu); +} + +/* + * Test: Multiple CPUs in mask with fuzz=0 + * Expected: Should return a valid CPU from the mask + */ +static void xive_test_find_target_multiple_cpus(struct kunit *test) +{ + struct cpumask multi_mask; + int result; + int cpu; + int count = 0; + + cpumask_clear(&multi_mask); + + /* Add first 4 online CPUs to the mask */ + for_each_online_cpu(cpu) { + cpumask_set_cpu(cpu, &multi_mask); + count++; + if (count >= 4) + break; + } + + if (count == 0) + kunit_skip(test, "No online CPUs available"); + + result = xive_find_target_in_mask(&multi_mask, 0); + + /* Result should be a valid CPU in the mask */ + KUNIT_EXPECT_NE(test, result, -1); + KUNIT_EXPECT_TRUE(test, cpumask_test_cpu(result, &multi_mask)); + KUNIT_EXPECT_TRUE(test, cpu_online(result)); +} + +/* + * Test: Fuzz parameter affects starting point + * Expected: Different fuzz values may select different CPUs + */ +static void xive_test_find_target_fuzz_variation(struct kunit *test) +{ + struct cpumask multi_mask; + int result1, result2; + int cpu; + int count = 0; + + cpumask_clear(&multi_mask); + + /* Add multiple online CPUs to the mask */ + for_each_online_cpu(cpu) { + cpumask_set_cpu(cpu, &multi_mask); + count++; + if (count >= 4) + break; + } + + if (count < 2) + kunit_skip(test, "Need at least 2 online CPUs for this test"); + + result1 = xive_find_target_in_mask(&multi_mask, 0); + result2 = xive_find_target_in_mask(&multi_mask, 1); + + /* Both results should be valid CPUs in the mask */ + KUNIT_EXPECT_NE(test, result1, -1); + KUNIT_EXPECT_NE(test, result2, -1); + KUNIT_EXPECT_TRUE(test, cpumask_test_cpu(result1, &multi_mask)); + KUNIT_EXPECT_TRUE(test, cpumask_test_cpu(result2, &multi_mask)); +} + +/* + * Test: Large fuzz value (modulo behavior) + * Expected: Should handle fuzz values larger than mask weight correctly + */ +static void xive_test_find_target_large_fuzz(struct kunit *test) +{ + struct cpumask multi_mask; + int result; + int cpu; + int count = 0; + unsigned int large_fuzz = 1000; + + cpumask_clear(&multi_mask); + + /* Add online CPUs to the mask */ + for_each_online_cpu(cpu) { + cpumask_set_cpu(cpu, &multi_mask); + count++; + if (count >= 3) + break; + } + + if (count == 0) + kunit_skip(test, "No online CPUs available"); + + result = xive_find_target_in_mask(&multi_mask, large_fuzz); + + /* Result should be a valid CPU in the mask */ + KUNIT_EXPECT_NE(test, result, -1); + KUNIT_EXPECT_TRUE(test, cpumask_test_cpu(result, &multi_mask)); + KUNIT_EXPECT_TRUE(test, cpu_online(result)); +} + +/* + * Test: Wrap-around behavior at mask boundary + * Expected: Should correctly wrap around when starting near the end + */ +static void xive_test_find_target_wrap_around(struct kunit *test) +{ + struct cpumask wrap_mask; + int result; + int cpu; + int count = 0; + unsigned int weight; + + cpumask_clear(&wrap_mask); + + /* Add online CPUs to the mask */ + for_each_online_cpu(cpu) { + cpumask_set_cpu(cpu, &wrap_mask); + count++; + if (count >= 4) + break; + } + + if (count < 2) + kunit_skip(test, "Need at least 2 online CPUs for this test"); + + weight = cpumask_weight(&wrap_mask); + + /* Test with fuzz at the boundary */ + result = xive_find_target_in_mask(&wrap_mask, weight - 1); + + KUNIT_EXPECT_NE(test, result, -1); + KUNIT_EXPECT_TRUE(test, cpumask_test_cpu(result, &wrap_mask)); + KUNIT_EXPECT_TRUE(test, cpu_online(result)); +} + +/* + * Test: Using cpu_online_mask + * Expected: Should handle the system's online CPU mask correctly + */ +static void xive_test_find_target_online_mask(struct kunit *test) +{ + int result; + + if (cpumask_empty(cpu_online_mask)) + kunit_skip(test, "No online CPUs in system"); + + result = xive_find_target_in_mask(cpu_online_mask, 0); + + KUNIT_EXPECT_NE(test, result, -1); + KUNIT_EXPECT_TRUE(test, cpu_online(result)); +} + +/* + * Test: Fuzz value equal to mask weight + * Expected: Should wrap to first CPU (fuzz % weight == 0) + */ +static void xive_test_find_target_fuzz_equals_weight(struct kunit *test) +{ + struct cpumask test_mask; + int result; + int cpu; + int count = 0; + unsigned int weight; + + cpumask_clear(&test_mask); + + /* Add online CPUs to the mask */ + for_each_online_cpu(cpu) { + cpumask_set_cpu(cpu, &test_mask); + count++; + if (count >= 3) + break; + } + + if (count == 0) + kunit_skip(test, "No online CPUs available"); + + weight = cpumask_weight(&test_mask); + + /* Fuzz equal to weight should wrap to start */ + result = xive_find_target_in_mask(&test_mask, weight); + + KUNIT_EXPECT_NE(test, result, -1); + KUNIT_EXPECT_TRUE(test, cpumask_test_cpu(result, &test_mask)); +} + +static struct kunit_case xive_test_cases[] = { + KUNIT_CASE(xive_test_find_target_empty_mask), + KUNIT_CASE(xive_test_find_target_single_cpu), + KUNIT_CASE(xive_test_find_target_multiple_cpus), + KUNIT_CASE(xive_test_find_target_fuzz_variation), + KUNIT_CASE(xive_test_find_target_large_fuzz), + KUNIT_CASE(xive_test_find_target_wrap_around), + KUNIT_CASE(xive_test_find_target_online_mask), + KUNIT_CASE(xive_test_find_target_fuzz_equals_weight), + {} +}; + +static struct kunit_suite xive_test_suite = { + .name = "xive_find_target_in_mask", + .test_cases = xive_test_cases, +}; + +kunit_test_suites(&xive_test_suite); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("KUnit tests for XIVE interrupt controller"); +MODULE_AUTHOR("Mukesh Kumar Chaurasiya (IBM) "); -- 2.53.0