From nobody Sun May 24 20:33:11 2026 Received: from mail-pf1-f170.google.com (mail-pf1-f170.google.com [209.85.210.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4CE5733F58A for ; Sat, 23 May 2026 11:14:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534895; cv=none; b=YnBqyUytTC2qv48TQQv9RIf8TCeJNx7SPZzZADwCAkNCWGZwebz2CvIERNrHZ5t86vFZQn8ekgHyo3n6WSuBgXcARnqGzdPAC5F371RVDIX1Wt9yzTLyvqsEA430cXu0i2vQVWvwkBbl969T+0NSLq+hp+uu3A3FqkpGpblmSSQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534895; c=relaxed/simple; bh=O0Dzr9y6cFVg8qYMI2oqsWYDxzwPFiV1IZwYIsniE4Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rsZVz7dQaYAiXRlLzNljp8rqunihfBbywmkOJ9+HyvG/pF/qYfi2YlBTtEEiDgX99ALYuFWKjgCsoWsHrhR5VXwIYEvy1T7eSoGwKWCzKksN6VngP6XGvn8tlgkkenx0kCI+F+SOB/Ts5PAgEix4/7X/NNg1eEdziICYdGzTj8Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dCKVdMSk; arc=none smtp.client-ip=209.85.210.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dCKVdMSk" Received: by mail-pf1-f170.google.com with SMTP id d2e1a72fcca58-835c98b659eso6937985b3a.0 for ; Sat, 23 May 2026 04:14:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779534893; x=1780139693; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oMG8EtROF9Cg3C7hjmtqqGx+u6sXMBdHtk9UvMaumUw=; b=dCKVdMSk7dxwUeBz7HstIJ86CerA0/tX+YyCNWN415jO0+kD3XKVUcbLkd8mOEWP7B +z0EdDzT4RgrflHlKjyIGAW6mcMEyHc6N0iTIVvhCgqrgpzzCGsNkX2tmvXv22qivhuA NyEYM0tZb+AOENToTXwBDWQ/pDsYM+pNoolWf3Fg2N9P6LWjWNc1sn/BzP2P3O5K1PiQ SHbZMpklXXHvP/k5C/jhoulFQzgJx/WPSxxpVC59inLgrzrTi2wEkAkmgcNpxLgaD+lN 0Z/agdnKx3E4Ylzuh1SzUKEz1ELsK7sYNSA2CUwlMahzW1pPwXHC5souhNyDWSKgmsdJ ed4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779534893; x=1780139693; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=oMG8EtROF9Cg3C7hjmtqqGx+u6sXMBdHtk9UvMaumUw=; b=Kq1W7PeGELImKh4dWT0Ceh8Ek10P4yBaY7tOVJZMxzop7W4PwLyDjA2hGah+nZI+OB 4MhUUs0c2LLkxUtacAvB1oJ/MBqQB9ssN0oXbDIhlpW8OlsKE+PcTShr5qzAjNqlHAQU F25xB6yO9R9Wdtle3jQ6To18sr9UPJDK/eHJMTj4Cqvlzt3jzGQiZmkS0wW8ZkBV3MbQ cC//vcL/EfEBCA6oUPn6oTZbk6xa2YYV6o8nQZUGD43Ro5U8lZ+KyEi9uyC58rdSoi0W 5MoKwSVAmn7S6t1GGel9DS3HjbPPh8f90s5Sq2X2lfK0XpmYeAAhTuQT/PWWinudG5Gu LDOQ== X-Forwarded-Encrypted: i=1; AFNElJ8PKpSgtVld1LbGx2R1r67wxHSDFnebibpJ1cO0kg9a0oafTmx29zYDMbKwc3/UFpeDwnD/3NZbjxYhu78=@vger.kernel.org X-Gm-Message-State: AOJu0YxRrjPIP6EMjgDUAdWInF0TyyGOcmxgcPTinvRcp2s1j7AB0mtn fQ2yY4PGqj27Q9S8qziAg7i//VvFngnPSZuBsaMEkytdR9+j/m2TVhzI X-Gm-Gg: Acq92OGJM3GfoGVpGBg3KCIfaI7OCFD3zk+s/J2qLOUzJC8hHgc0um2nkQYyTuM6Be/ jDaob9iayD2NyHt8var2U3LnGGYt/Fm8RvmK1b+hXNd1r0c3IKGrGbLaG7hjkSu1eXB+DB/RqxH 8WA5q2dlCHJN6fFfI7Gx/EI6jsAlpu+bO67MAktUFmADanke68UzEETLXXQvKU6eQdFA9UaVdcK iCQdgRaQ2MZgEKuIwNVga09wEw7SOJ35j5kZranoK9cEe+l20JUdESge8mZLEBtlrN1jhmXWnW4 1hXv+zpFlpJPZ07GLcVi5t5VfSp3Ne53sOXDlRGX4RMcThWrnGWvQmeL27cPEbzTOMBcUcdFhj5 NJkE7f1Ug3Ydq3zXxdEeWsgJ908gdEklf37M0YicwLNX0KBvQ6a7FTBL35/8lnJsNuEF9Vuj55t O46v6Jslv5Y89rKOn9VRZyBy46XAbifB1uvVmWjYE= X-Received: by 2002:a05:6a00:94fc:b0:82c:6683:b866 with SMTP id d2e1a72fcca58-8415f121b9bmr7424451b3a.4.1779534893432; Sat, 23 May 2026 04:14:53 -0700 (PDT) Received: from Mac.ibm.com ([49.205.216.49]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84164ac9c77sm5249140b3a.2.2026.05.23.04.14.48 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 23 May 2026 04:14:52 -0700 (PDT) From: "Ritesh Harjani (IBM)" To: kvm@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org, Madhavan Srinivasan , Harsh Prateek Bora , Christophe Leroy , Venkat Rao Bagalkote , Nicholas Piggin , Misbah Anjum N , Anushree Mathur , Michael Ellerman , linux-kernel@vger.kernel.org, "Ritesh Harjani (IBM)" Subject: [RFC v2 1/5] KVM: selftests: Move pgd_created check into virt_pgd_alloc Date: Sat, 23 May 2026 16:44:20 +0530 Message-ID: X-Mailer: git-send-email 2.50.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin virt_arch_pgd_alloc all do the same test and set pgd_created. Move this into common code - except for x86's virt_arch_pgd_alloc() -> virt_mmu_init() - because this can also be called from it's tdp_mmu_init() call for setting up it's stage-2 mmu. Signed-off-by: Nicholas Piggin [Rebased to latest mainline tree and removed x86 case] Signed-off-by: Ritesh Harjani (IBM) --- tools/testing/selftests/kvm/include/kvm_util.h | 5 +++++ tools/testing/selftests/kvm/lib/arm64/processor.c | 4 ---- tools/testing/selftests/kvm/lib/loongarch/processor.c | 4 ---- tools/testing/selftests/kvm/lib/riscv/processor.c | 4 ---- tools/testing/selftests/kvm/lib/s390/processor.c | 4 ---- 5 files changed, 5 insertions(+), 16 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index 2ecaaa0e9965..3666a8530f31 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -1197,7 +1197,12 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm); =20 static inline void virt_pgd_alloc(struct kvm_vm *vm) { + if (vm->mmu.pgd_created) + return; + virt_arch_pgd_alloc(vm); + + vm->mmu.pgd_created =3D true; } =20 /* diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/test= ing/selftests/kvm/lib/arm64/processor.c index 01325bf4d36f..498fbcb0ea16 100644 --- a/tools/testing/selftests/kvm/lib/arm64/processor.c +++ b/tools/testing/selftests/kvm/lib/arm64/processor.c @@ -112,13 +112,9 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm) { size_t nr_pages =3D vm_page_align(vm, ptrs_per_pgd(vm) * 8) / vm->page_si= ze; =20 - if (vm->mmu.pgd_created) - return; - vm->mmu.pgd =3D vm_phy_pages_alloc(vm, nr_pages, KVM_GUEST_PAGE_TABLE_MIN_PADDR, vm->memslots[MEM_REGION_PT]); - vm->mmu.pgd_created =3D true; } =20 static void _virt_pg_map(struct kvm_vm *vm, gva_t gva, gpa_t gpa, diff --git a/tools/testing/selftests/kvm/lib/loongarch/processor.c b/tools/= testing/selftests/kvm/lib/loongarch/processor.c index 64d91fb76522..207055db5f5d 100644 --- a/tools/testing/selftests/kvm/lib/loongarch/processor.c +++ b/tools/testing/selftests/kvm/lib/loongarch/processor.c @@ -51,9 +51,6 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm) int i; gpa_t child, table; =20 - if (vm->mmu.pgd_created) - return; - child =3D table =3D 0; for (i =3D 0; i < vm->mmu.pgtable_levels; i++) { invalid_pgtable[i] =3D child; @@ -64,7 +61,6 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm) child =3D table; } vm->mmu.pgd =3D table; - vm->mmu.pgd_created =3D true; } =20 static int virt_pte_none(u64 *ptep, int level) diff --git a/tools/testing/selftests/kvm/lib/riscv/processor.c b/tools/test= ing/selftests/kvm/lib/riscv/processor.c index ded5429f3448..75a5d4c46001 100644 --- a/tools/testing/selftests/kvm/lib/riscv/processor.c +++ b/tools/testing/selftests/kvm/lib/riscv/processor.c @@ -66,13 +66,9 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm) { size_t nr_pages =3D vm_page_align(vm, ptrs_per_pte(vm) * 8) / vm->page_si= ze; =20 - if (vm->mmu.pgd_created) - return; - vm->mmu.pgd =3D vm_phy_pages_alloc(vm, nr_pages, KVM_GUEST_PAGE_TABLE_MIN_PADDR, vm->memslots[MEM_REGION_PT]); - vm->mmu.pgd_created =3D true; } =20 void virt_arch_pg_map(struct kvm_vm *vm, gva_t gva, gpa_t gpa) diff --git a/tools/testing/selftests/kvm/lib/s390/processor.c b/tools/testi= ng/selftests/kvm/lib/s390/processor.c index a9adb3782b35..342b7c92463e 100644 --- a/tools/testing/selftests/kvm/lib/s390/processor.c +++ b/tools/testing/selftests/kvm/lib/s390/processor.c @@ -17,16 +17,12 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm) TEST_ASSERT(vm->page_size =3D=3D PAGE_SIZE, "Unsupported page size: 0x%x", vm->page_size); =20 - if (vm->mmu.pgd_created) - return; - gpa =3D vm_phy_pages_alloc(vm, PAGES_PER_REGION, KVM_GUEST_PAGE_TABLE_MIN_PADDR, vm->memslots[MEM_REGION_PT]); memset(addr_gpa2hva(vm, gpa), 0xff, PAGES_PER_REGION * vm->page_size); =20 vm->mmu.pgd =3D gpa; - vm->mmu.pgd_created =3D true; } =20 /* --=20 2.39.5 From nobody Sun May 24 20:33:11 2026 Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F15533F58A for ; Sat, 23 May 2026 11:15:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534901; cv=none; b=OnBaC4s2ayfFyPdLjtJTtplPR058nC6Uw0bheFfES05u3xmxBUemBlM1FOpkpG6TyWoUeypcxC5k+75mtLiFZJMDS4Uy2JFKblqKyN2k2y5udOAyF3khcdVMr7y12G8PqkcvzLn/eKIycUP9fCs0SMqe3UykZavgRCFggBghoIM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534901; c=relaxed/simple; bh=tG/vwPXG+NgCJqpeTpzbd4mkkNiN98tDPGGb1Pn/dzg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=md6K0K/yI5CttE/I+LwWa45fqyqOE6b9pCdK/9R0p8fJWkHFdPHzD93MD1PKqFQnBwOfB/hDcDwzJ+MCasTdeM2PcmRKLQvw/yqU+Wz3i6MHnQfIvCVw2dXCppSzgjc57Thv/olfNDsgJFkNgnRBauYXnTWaTuY7leSN6s4wAtU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=svdZHpeA; arc=none smtp.client-ip=209.85.210.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="svdZHpeA" Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-8367df48711so3586919b3a.1 for ; Sat, 23 May 2026 04:15:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779534900; x=1780139700; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dYv7n7MNQFWGtdjlWPVxo0rnA4k4aMTlnbBv8oYiho8=; b=svdZHpeA+lDg3VjDzv6nvdBatOGYY6ugw2mv/hPC0vEBGor2sP/eh2fONZVhVvQSSX jIPQc0ahWDQXh53mH9WzUhMTRyk+P4gLViB8b/l4vBhqBrMiy7EfbCEZ4eshV4znPzj5 PkbBxlIEykUa2+XZDlTkfZws1PPkEIXVYsYT9PJTDw7Ulqnh/gdeLWO5eHmpu0czfvzC NIELraDD0bmbPoGYpTnrmvbTKaovCZ3+rKN+SoIV8ECMR4qgdWGPhtvld1evtnbiv/8+ hkssuFWQt3EmKVCYX2/iyMauJ8rI9q43xkQcMAm9B04uOX0rdWWPCYXwPq8V6GBP8VMl i1gQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779534900; x=1780139700; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=dYv7n7MNQFWGtdjlWPVxo0rnA4k4aMTlnbBv8oYiho8=; b=PM6RoH5o5+0KhftXyAWrPkl2UM0/j2vkAqsWUdSUHKqyqqMEiWlDe+Dsz14GWK0MK3 DK9hnbtt1HN0JINBcarW+mf5dZiLqausTiwlCOWu/5Wz0JFu8iTDAw70s+E3Vm74bufd 4HVCYCNLLw+EO3IbHl20qEZZD/LYTYJtErfdhvOi5lv+4PLFik3UpJY1mT+zIsZM3Cjt 6XKX/exrZG8g65JlUi3fydUR9YS5ME2EZSaUXMaf0tfa7pwjUhUGfbFjxdAvp53Ld9Y/ djFJi5g6F9EUN3aW+XmnE0ke9TQZ2CVmGil1kX0OpYOudVw1Ag5cvYwm+T3OWq2MOcxu 8z3A== X-Forwarded-Encrypted: i=1; AFNElJ9gEypc9XU8FxJ/rclPF4RzGZyUuN0vQqWKHfOb2AvuT2HgFQV/keHRTX2lcUTS2pdwO1bVMKfNP/gGLSI=@vger.kernel.org X-Gm-Message-State: AOJu0YxzhavLg5PNM3vDWZ9xRqx+kuUmNNvLn6US0MK9jZMxk8r3cqry /lgTKaCUFtfb4PDJ8vL2DsxYvqdJCvGN2HySHYrMipJjZCfDJ2fU2V35 X-Gm-Gg: Acq92OFE43FVj65cVHoD2W8XQoZR0QW4Dy1p01O2N1rLyyAxsgl32JsbRvxgMN7B2RE jOqDGx7I5PI809nLTujB/ULfQJefn0FcBsPvp5yXHBeGRL0oJ2Y5v0qxWoTzuSvFOw2NPBMZPz3 7nl3x1LuQsAf3zHCPyQA7TmCnnfm2s8/6Qn4JpvTxG4B+oiqZD1WwpfXYTC/dcKsDD7ioj+32+N C2e5+zFIL4TwtzqcVHYm19pXu5tfbqP4a3WYJWYH9knvWOc4JOA5Y2pp3zHOWI6VheQvJRsD5HN 6aH1kMEp3i9nIXENYSfBNJC8dZ2V8yG2wyzcbIpfuqEJyrOd5BVXjCEpeuC/TbOJ9Wb80XGIL/h ERlzSnyKKXhRdexQRtlg7P2q0yDTFdxSZyIn7Cvc4geEmZ0HhaF7phqVs1bLMdUmvEc498qoLbi ynNu7EbrvN0kvkSii5gJ0PCx8oV5RLKXgIDPorpIo= X-Received: by 2002:a05:6a00:1c8a:b0:82f:4f67:1ff6 with SMTP id d2e1a72fcca58-8415f2dca4cmr7587485b3a.4.1779534899815; Sat, 23 May 2026 04:14:59 -0700 (PDT) Received: from Mac.ibm.com ([49.205.216.49]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84164ac9c77sm5249140b3a.2.2026.05.23.04.14.53 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 23 May 2026 04:14:59 -0700 (PDT) From: "Ritesh Harjani (IBM)" To: kvm@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org, Madhavan Srinivasan , Harsh Prateek Bora , Christophe Leroy , Venkat Rao Bagalkote , Nicholas Piggin , Misbah Anjum N , Anushree Mathur , Michael Ellerman , linux-kernel@vger.kernel.org, "Ritesh Harjani (IBM)" Subject: [RFC v2 2/5] KVM: selftests: Add aligned guest physical page allocator Date: Sat, 23 May 2026 16:44:21 +0530 Message-ID: <0fcea77119a6f4e0554f8bc0b258a54c2fe9d49f.1779524962.git.ritesh.list@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin powerpc will require this to allocate MMU tables in guest memory that are larger than guest base page size. Signed-off-by: Nicholas Piggin [Rebased to latest mainline tree] Signed-off-by: Ritesh Harjani (IBM) --- .../testing/selftests/kvm/include/kvm_util.h | 20 +++++++++-- tools/testing/selftests/kvm/lib/kvm_util.c | 33 +++++++++---------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index 3666a8530f31..c515c918c2c9 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -991,8 +991,8 @@ void kvm_gsi_routing_write(struct kvm_vm *vm, struct kv= m_irq_routing *routing); const char *exit_reason_str(unsigned int exit_reason); =20 gpa_t vm_phy_page_alloc(struct kvm_vm *vm, gpa_t min_gpa, u32 memslot); -gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, gpa_t min_gpa, - u32 memslot, bool protected); +gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, size_t align, + gpa_t min_gpa, u32 memslot, bool protected); gpa_t vm_alloc_page_table(struct kvm_vm *vm); =20 static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, @@ -1003,10 +1003,24 @@ static inline gpa_t vm_phy_pages_alloc(struct kvm_v= m *vm, size_t num, * protected memory, as the majority of memory for such VMs is * protected, i.e. using shared memory is effectively opt-in. */ - return __vm_phy_pages_alloc(vm, num, min_gpa, memslot, + return __vm_phy_pages_alloc(vm, num, 1, min_gpa, memslot, vm_arch_has_protected_memory(vm)); } =20 +static inline gpa_t vm_phy_pages_alloc_align(struct kvm_vm *vm, size_t num, + size_t align, gpa_t min_gpa, + u32 memslot) +{ + /* + * By default, allocate memory as protected for VMs that support + * protected memory, as the majority of memory for such VMs is + * protected, i.e. using shared memory is effectively opt-in. + */ + return __vm_phy_pages_alloc(vm, num, align, min_gpa, memslot, + vm_arch_has_protected_memory(vm)); +} + + /* * ____vm_create() does KVM_CREATE_VM and little else. __vm_create() also * loads the test binary into guest memory and creates an IRQ chip (x86 on= ly). diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 2a76eca7029d..cdb004c9ba56 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1442,7 +1442,7 @@ static gva_t ____vm_alloc(struct kvm_vm *vm, size_t s= z, gva_t min_gva, u64 pages =3D (sz >> vm->page_shift) + ((sz % vm->page_size) !=3D 0); =20 virt_pgd_alloc(vm); - gpa_t gpa =3D __vm_phy_pages_alloc(vm, pages, + gpa_t gpa =3D __vm_phy_pages_alloc(vm, pages, 1, KVM_UTIL_MIN_PFN * vm->page_size, vm->memslots[type], protected); =20 @@ -2021,7 +2021,7 @@ const char *exit_reason_str(unsigned int exit_reason) * and their base address is returned. A TEST_ASSERT failure occurs if * not enough pages are available at or above min_gpa. */ -gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, +gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, size_t align, gpa_t min_gpa, u32 memslot, bool protected) { @@ -2039,23 +2039,22 @@ gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_= t num, TEST_ASSERT(!protected || region->protected_phy_pages, "Region doesn't support protected memory"); =20 - base =3D pg =3D min_gpa >> vm->page_shift; - do { - for (; pg < base + num; ++pg) { - if (!sparsebit_is_set(region->unused_phy_pages, pg)) { - base =3D pg =3D sparsebit_next_set(region->unused_phy_pages, pg); - break; + base =3D min_gpa >> vm->page_shift; +again: + base =3D (base + align - 1) & ~(align - 1); + for (pg =3D base; pg < base + num; ++pg) { + if (!sparsebit_is_set(region->unused_phy_pages, pg)) { + base =3D sparsebit_next_set(region->unused_phy_pages, pg); + if (!base) { + fprintf(stderr, "No guest physical page available, " + "min_gpa: 0x%lx page_size: 0x%x memslot: %u\n", + min_gpa, vm->page_size, memslot); + fputs("---- vm dump ----\n", stderr); + vm_dump(stderr, vm, 2); + abort(); } + goto again; } - } while (pg && pg !=3D base + num); - - if (pg =3D=3D 0) { - fprintf(stderr, "No guest physical page available, " - "min_gpa: 0x%lx page_size: 0x%x memslot: %u\n", - min_gpa, vm->page_size, memslot); - fputs("---- vm dump ----\n", stderr); - vm_dump(stderr, vm, 2); - abort(); } =20 for (pg =3D base; pg < base + num; ++pg) { --=20 2.39.5 From nobody Sun May 24 20:33:11 2026 Received: from mail-pf1-f177.google.com (mail-pf1-f177.google.com [209.85.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1E989388378 for ; Sat, 23 May 2026 11:15:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534910; cv=none; b=kNqiRfirQqIOdn0I9WQQ2bUTHw/84YQ5piMnt+Alt4N5S1qkeCmZc39rGnWTupkWGN/TsMam44LeyrZqbs/4aSjzE9m/plYIgay5cDVfSQqVGoJMgmBz6lzvArXNCkWiC4WdfmnBExUegV1Vv7q8Rxa1rGufXpANgpkdunDpPLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534910; c=relaxed/simple; bh=6uL+NceEBTWBkKYPa1jZqW4Hj8A4q2YnWhPufbln7r8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sdSvaY08WbpxlWVmwtgvqM0qEmTiiQtvwRnsXSuEAbCan/3S4eeewe4/4XSWtkDg3iBo69Q6qShd6PSscwl3rh3tADWRXXuik+7Nhy9JbrSLZ0syhzs97NSaat4C40UnpuL9+udVLtUUjELscYpTQ+PXI9XuVSADaNjdVUfjTqE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TCJR5jDp; arc=none smtp.client-ip=209.85.210.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TCJR5jDp" Received: by mail-pf1-f177.google.com with SMTP id d2e1a72fcca58-837b39eb078so5572889b3a.2 for ; Sat, 23 May 2026 04:15:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779534906; x=1780139706; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FQ9oe+X1QrAi8pMjejbPrYtVteMsIofRM/P68r1ErNE=; b=TCJR5jDpIUDkfy97fu0Hzb+lXDw0gPLKIIgnUbvFMKsaNUY4X8KtET4NSmGHASl6JT KSFkyK4zukz+YYj11I9vAQ2u9HF9CxEjVTZwuHMcmUmDUYXEJjyKJXed1eo0zhW3N6oa z2q7RFBZT2u0VDw7gVEYrT/2bqG68KqwB5iIQul6CYger5cVzbYyMC8Ws5SRmLF/id0x yFix2ZN9VVgiqjnzGBPYfzfRrSkMcYPjhYR/0vVJvZ/4jyZluQcw2atAUVzq1LDGWn78 SiEz8Iow0ATO12H79BxCQBwfUGbzZlyQq64eLv+2v9skDG6fgTgvUE39UNqMxdOyUff1 jC+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779534906; x=1780139706; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=FQ9oe+X1QrAi8pMjejbPrYtVteMsIofRM/P68r1ErNE=; b=XRHg+6rcyr+Qrwq1/iMqCPvT0ybYFtfikq2E+4CmAoGzTTAl+dIzSEbYv9U08F+SCb sr2KIljMOj5QGE96wi+/1qpTyLFC0FLTDfojsI7NFhQmoSOkbSumIKwjmubEgUAXcDOK BYJ4k7XUPdfd0ZoQjq6Tz1FXyBkiIAuUl2G02VdTMXudJGMlIBF5ytNlAbgDJlgmX+Pt HK/nPRelU+JCFoYdTrGNMtnyEgrWglfydLFzIqNgcMaIblpb8dW4ctIKx7jUqhHIm+8h EObKJwiIHIWJcmP6xaTzYkEkMNy0inBM2Wr7yuqmM2nqxLlUnx4tCIEtpIg1Ugb+KMuw v5dw== X-Forwarded-Encrypted: i=1; AFNElJ/zEAOy9d/3suGGJGH7qKH2J+1a/OqYM7MgR6Xy1funML6rPTOPIPW29pqbox+I1WG+IaBhTjdn28QpZW0=@vger.kernel.org X-Gm-Message-State: AOJu0YyAvkIlV9yqZins3Jt2JqNNEjqF0I0Yxc/Zs9adg7PrbhyicyhN tHJUOqSchDVsFQ0t5E15QYxdeHxGbPLJDwWOehATMcaY199isITsJtHj X-Gm-Gg: Acq92OGbjo4rdwGDMFS21PwXPUAnexfTP6auC20CSYPab9OuEYGChfHUKYBGgto99eW s7GPmItneCmTVKcYinwp7Fs2avdAHjPaqXF6Km4ddt+26CIbxetKw39jK7fJ9jrzYzN/wJ6O2uH 4TAPu/RJujdD5EQOuEF7nqiFkToQsFgIEW5eDqz5qAtrKOj7wLR69b8dT1UTilVc4H2L8ODfXO3 ywjYpsa7VQBSdy2O5hwP0c1YbkcIrsqOjlF70/zSjhpixIVTcxvz3YT3Dz0YGOCakD4D5rp6T8c hZGqch6r73PaK/ySSkSCNZT17S5zx9kN8XKKGaVNJ75T0nZbTa5ZxRW3IGZ9PAuW8Nd6KW4jDRB 33xrU6BV7cMcfimuG3IGqahd0gVoEQEtivl8/5K+0HNPoQf7VuVi5Aoq2x08tcVuA8WRvwNilMq p6w6Cir33tYMSdyR9F3csxO2g8qLbwDC5BOew0yHCsk3rXWg4kfA== X-Received: by 2002:a05:6a00:4196:b0:82f:3ecc:c42f with SMTP id d2e1a72fcca58-8415f65a2a7mr6651228b3a.40.1779534906019; Sat, 23 May 2026 04:15:06 -0700 (PDT) Received: from Mac.ibm.com ([49.205.216.49]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84164ac9c77sm5249140b3a.2.2026.05.23.04.15.00 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 23 May 2026 04:15:05 -0700 (PDT) From: "Ritesh Harjani (IBM)" To: kvm@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org, Madhavan Srinivasan , Harsh Prateek Bora , Christophe Leroy , Venkat Rao Bagalkote , Nicholas Piggin , Misbah Anjum N , Anushree Mathur , Michael Ellerman , linux-kernel@vger.kernel.org, "Ritesh Harjani (IBM)" Subject: [RFC v2 3/5] KVM: PPC: selftests: add support for powerpc Date: Sat, 23 May 2026 16:44:22 +0530 Message-ID: <6e0c74f1273a4baf652d84820ae83696e77263d9.1779524962.git.ritesh.list@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin Implement KVM selftests support for powerpc (Book3S-64). ucalls are implemented with an unsupported PAPR hcall number which will always cause KVM to exit to userspace. Virtual memory is implemented for the radix MMU, and only a base page size is supported (both 4K and 64K). Guest interrupts are taken in real-mode, so require a page allocated at gRA 0x0. Interrupt entry is complicated because gVA:gRA is not 1:1 mapped (like the kernel is), so the MMU can not just be switched on and off. Signed-off-by: Nicholas Piggin [Rebased to latest mainline tree, add "cc" to clobber list and fix the pagesize calculation in kvm_arch_vm_post_create()] Signed-off-by: Ritesh Harjani (IBM) --- MAINTAINERS | 2 + tools/testing/selftests/kvm/Makefile | 2 +- tools/testing/selftests/kvm/Makefile.kvm | 10 + .../testing/selftests/kvm/include/kvm_util.h | 9 + .../selftests/kvm/include/powerpc/hcall.h | 17 + .../kvm/include/powerpc/kvm_util_arch.h | 22 + .../selftests/kvm/include/powerpc/ppc_asm.h | 32 ++ .../selftests/kvm/include/powerpc/processor.h | 38 ++ .../selftests/kvm/include/powerpc/ucall.h | 21 + tools/testing/selftests/kvm/lib/guest_modes.c | 20 +- tools/testing/selftests/kvm/lib/kvm_util.c | 8 + .../selftests/kvm/lib/powerpc/handlers.S | 93 ++++ .../testing/selftests/kvm/lib/powerpc/hcall.c | 45 ++ .../selftests/kvm/lib/powerpc/processor.c | 484 ++++++++++++++++++ .../testing/selftests/kvm/lib/powerpc/ucall.c | 22 + 15 files changed, 822 insertions(+), 3 deletions(-) create mode 100644 tools/testing/selftests/kvm/include/powerpc/hcall.h create mode 100644 tools/testing/selftests/kvm/include/powerpc/kvm_util_ar= ch.h create mode 100644 tools/testing/selftests/kvm/include/powerpc/ppc_asm.h create mode 100644 tools/testing/selftests/kvm/include/powerpc/processor.h create mode 100644 tools/testing/selftests/kvm/include/powerpc/ucall.h create mode 100644 tools/testing/selftests/kvm/lib/powerpc/handlers.S create mode 100644 tools/testing/selftests/kvm/lib/powerpc/hcall.c create mode 100644 tools/testing/selftests/kvm/lib/powerpc/processor.c create mode 100644 tools/testing/selftests/kvm/lib/powerpc/ucall.c diff --git a/MAINTAINERS b/MAINTAINERS index f1e5e4258e7b..3c876ea1198e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14118,6 +14118,8 @@ F: arch/powerpc/include/asm/kvm* F: arch/powerpc/include/uapi/asm/kvm* F: arch/powerpc/kernel/kvm* F: arch/powerpc/kvm/ +F: tools/testing/selftests/kvm/*/powerpc/ +F: tools/testing/selftests/kvm/powerpc/ =20 KERNEL VIRTUAL MACHINE FOR RISC-V (KVM/riscv) M: Anup Patel diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests= /kvm/Makefile index f2b223072b62..03d91f00092f 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -3,7 +3,7 @@ top_srcdir =3D ../../../.. include $(top_srcdir)/scripts/subarch.include ARCH ?=3D $(SUBARCH) =20 -ifeq ($(ARCH),$(filter $(ARCH),arm64 s390 riscv x86 x86_64 loongarch)) +ifeq ($(ARCH),$(filter $(ARCH),arm64 s390 riscv x86 x86_64 loongarch power= pc)) # Top-level selftests allows ARCH=3Dx86_64 :-( ifeq ($(ARCH),x86_64) override ARCH :=3D x86 diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 9118a5a51b89..825bea7f851d 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -52,6 +52,11 @@ LIBKVM_loongarch +=3D lib/loongarch/processor.c LIBKVM_loongarch +=3D lib/loongarch/ucall.c LIBKVM_loongarch +=3D lib/loongarch/exception.S =20 +LIBKVM_powerpc +=3D lib/powerpc/handlers.S +LIBKVM_powerpc +=3D lib/powerpc/processor.c +LIBKVM_powerpc +=3D lib/powerpc/ucall.c +LIBKVM_powerpc +=3D lib/powerpc/hcall.c + # Non-compiled test targets TEST_PROGS_x86 +=3D x86/nx_huge_pages_test.sh =20 @@ -239,6 +244,11 @@ TEST_GEN_PROGS_loongarch +=3D memslot_perf_test TEST_GEN_PROGS_loongarch +=3D set_memory_region_test TEST_GEN_PROGS_loongarch +=3D steal_time =20 +TEST_GEN_PROGS_powerpc =3D $(TEST_GEN_PROGS_COMMON) +TEST_GEN_PROGS_powerpc +=3D access_tracking_perf_test +TEST_GEN_PROGS_powerpc +=3D dirty_log_perf_test +TEST_GEN_PROGS_powerpc +=3D hardware_disable_test + SPLIT_TESTS +=3D arch_timer SPLIT_TESTS +=3D get-reg-list =20 diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index c515c918c2c9..10f03a182c8b 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -209,6 +209,9 @@ enum vm_guest_mode { VM_MODE_P41V48_4K, VM_MODE_P41V39_4K, =20 + VM_MODE_P52V52_4K, /* For powerpc64 */ + VM_MODE_P52V52_64K, + NUM_VM_MODES, }; =20 @@ -268,6 +271,12 @@ extern enum vm_guest_mode vm_mode_default; #define MIN_PAGE_SHIFT 12U #define ptes_per_page(page_size) ((page_size) / 8) =20 +#elif defined(__powerpc64__) + +#define VM_MODE_DEFAULT vm_mode_default +#define MIN_PAGE_SHIFT 12U +#define ptes_per_page(page_size) ((page_size) / 8) + #endif =20 #define VM_SHAPE_DEFAULT VM_SHAPE(VM_MODE_DEFAULT) diff --git a/tools/testing/selftests/kvm/include/powerpc/hcall.h b/tools/te= sting/selftests/kvm/include/powerpc/hcall.h new file mode 100644 index 000000000000..4028baa6c5d8 --- /dev/null +++ b/tools/testing/selftests/kvm/include/powerpc/hcall.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * powerpc hcall defines + */ +#ifndef SELFTEST_KVM_HCALL_H +#define SELFTEST_KVM_HCALL_H + +#include + +/* Ucalls use unimplemented PAPR hcall 0 which exits KVM */ +#define H_UCALL 0 + +int64_t hcall0(uint64_t token); +int64_t hcall1(uint64_t token, uint64_t arg1); +int64_t hcall2(uint64_t token, uint64_t arg1, uint64_t arg2); + +#endif diff --git a/tools/testing/selftests/kvm/include/powerpc/kvm_util_arch.h b/= tools/testing/selftests/kvm/include/powerpc/kvm_util_arch.h new file mode 100644 index 000000000000..5d45c25cd299 --- /dev/null +++ b/tools/testing/selftests/kvm/include/powerpc/kvm_util_arch.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_KVM_UTIL_ARCH_H +#define SELFTEST_KVM_UTIL_ARCH_H + +#include + +#include "kvm_util_types.h" + +struct kvm_mmu_arch {}; + +/* Page table fragment cache for guest page tables < page size */ +struct vm_pt_frag_cache { + gpa_t page; + size_t page_nr_used; +}; + +struct kvm_vm_arch { + gpa_t prtb; /* process table */ + struct vm_pt_frag_cache pt_frag_cache[2]; /* 256B and 4KB PT caches */ +}; + +#endif /* SELFTEST_KVM_UTIL_ARCH_H */ diff --git a/tools/testing/selftests/kvm/include/powerpc/ppc_asm.h b/tools/= testing/selftests/kvm/include/powerpc/ppc_asm.h new file mode 100644 index 000000000000..b9df64659792 --- /dev/null +++ b/tools/testing/selftests/kvm/include/powerpc/ppc_asm.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * powerpc asm specific defines + */ +#ifndef SELFTEST_KVM_PPC_ASM_H +#define SELFTEST_KVM_PPC_ASM_H + +#define STACK_FRAME_MIN_SIZE 112 /* Could be 32 on ELFv2 */ +#define STACK_REDZONE_SIZE 512 + +#define INT_FRAME_SIZE (STACK_FRAME_MIN_SIZE + STACK_REDZONE_SIZE) + +#define SPR_SRR0 0x01a +#define SPR_SRR1 0x01b +#define SPR_CFAR 0x01c + +#define MSR_SF 0x8000000000000000ULL +#define MSR_HV 0x1000000000000000ULL +#define MSR_VEC 0x0000000002000000ULL +#define MSR_VSX 0x0000000000800000ULL +#define MSR_EE 0x0000000000008000ULL +#define MSR_PR 0x0000000000004000ULL +#define MSR_FP 0x0000000000002000ULL +#define MSR_ME 0x0000000000001000ULL +#define MSR_IR 0x0000000000000020ULL +#define MSR_DR 0x0000000000000010ULL +#define MSR_RI 0x0000000000000002ULL +#define MSR_LE 0x0000000000000001ULL + +#define LPCR_ILE 0x0000000002000000ULL + +#endif diff --git a/tools/testing/selftests/kvm/include/powerpc/processor.h b/tool= s/testing/selftests/kvm/include/powerpc/processor.h new file mode 100644 index 000000000000..cb75b77c33bb --- /dev/null +++ b/tools/testing/selftests/kvm/include/powerpc/processor.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * powerpc processor specific defines + */ +#ifndef SELFTEST_KVM_PROCESSOR_H +#define SELFTEST_KVM_PROCESSOR_H + +#include +#include "ppc_asm.h" + +extern unsigned char __interrupts_start[]; +extern unsigned char __interrupts_end[]; + +struct kvm_vm; +struct kvm_vcpu; + +struct ex_regs { + uint64_t gprs[32]; + uint64_t nia; + uint64_t msr; + uint64_t cfar; + uint64_t lr; + uint64_t ctr; + uint64_t xer; + uint32_t cr; + uint32_t trap; + uint64_t vaddr; /* vaddr of this struct */ +}; + +void vm_install_exception_handler(struct kvm_vm *vm, int vector, + void (*handler)(struct ex_regs *)); + +static inline void cpu_relax(void) +{ + asm volatile("" ::: "memory"); +} + +#endif diff --git a/tools/testing/selftests/kvm/include/powerpc/ucall.h b/tools/te= sting/selftests/kvm/include/powerpc/ucall.h new file mode 100644 index 000000000000..e0dbe91e8848 --- /dev/null +++ b/tools/testing/selftests/kvm/include/powerpc/ucall.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_KVM_UCALL_H +#define SELFTEST_KVM_UCALL_H + +#include "hcall.h" + +#define UCALL_EXIT_REASON KVM_EXIT_PAPR_HCALL + +#define UCALL_R4_UCALL 0x5715 /* regular ucall, r5 contains ucall pointer = */ +#define UCALL_R4_SIMPLE 0x0000 /* simple exit usable by asm with no ucall = data */ + +static inline void ucall_arch_init(struct kvm_vm *vm, gpa_t mmio_gpa) +{ +} + +static inline void ucall_arch_do_ucall(gva_t uc) +{ + hcall2(H_UCALL, UCALL_R4_UCALL, (uintptr_t)(uc)); +} + +#endif diff --git a/tools/testing/selftests/kvm/lib/guest_modes.c b/tools/testing/= selftests/kvm/lib/guest_modes.c index 7a96c43b5704..439766fad693 100644 --- a/tools/testing/selftests/kvm/lib/guest_modes.c +++ b/tools/testing/selftests/kvm/lib/guest_modes.c @@ -4,16 +4,20 @@ */ #include "guest_modes.h" =20 -#if defined(__aarch64__) || defined(__riscv) +#if defined(__aarch64__) || defined(__riscv) || defined(__powerpc64__) #include "processor.h" enum vm_guest_mode vm_mode_default; #endif =20 +#if defined(__powerpc64__) +#include +#endif + struct guest_mode guest_modes[NUM_VM_MODES]; =20 void guest_modes_append_default(void) { -#if !defined(__aarch64__) && !defined(__riscv) +#if !defined(__aarch64__) && !defined(__riscv) && !defined(__powerpc64__) guest_mode_append(VM_MODE_DEFAULT, true); #endif =20 @@ -108,6 +112,18 @@ void guest_modes_append_default(void) TEST_ASSERT(vm_mode_default !=3D NUM_VM_MODES, "No supported mode!"); } #endif +#ifdef __powerpc64__ + { + TEST_REQUIRE(kvm_has_cap(KVM_CAP_PPC_MMU_RADIX)); + /* Radix guest EA and RA are 52-bit on POWER9 and POWER10 */ + if (sysconf(_SC_PAGESIZE) =3D=3D 4096) + vm_mode_default =3D VM_MODE_P52V52_4K; + else + vm_mode_default =3D VM_MODE_P52V52_64K; + guest_mode_append(VM_MODE_P52V52_4K, true); + guest_mode_append(VM_MODE_P52V52_64K, true); + } +#endif } =20 void for_each_guest_mode(void (*func)(enum vm_guest_mode, void *), void *a= rg) diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index cdb004c9ba56..0dc67c1502cf 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -218,6 +218,8 @@ const char *vm_guest_mode_string(u32 i) [VM_MODE_P41V57_4K] =3D "PA-bits:41, VA-bits:57, 4K pages", [VM_MODE_P41V48_4K] =3D "PA-bits:41, VA-bits:48, 4K pages", [VM_MODE_P41V39_4K] =3D "PA-bits:41, VA-bits:39, 4K pages", + [VM_MODE_P52V52_4K] =3D "PA-bits:52, VA-bits:52, 4K pages", + [VM_MODE_P52V52_64K] =3D "PA-bits:52, VA-bits:52, 64K pages", }; _Static_assert(sizeof(strings)/sizeof(char *) =3D=3D NUM_VM_MODES, "Missing new mode strings?"); @@ -254,6 +256,8 @@ const struct vm_guest_mode_params vm_guest_mode_params[= ] =3D { [VM_MODE_P41V57_4K] =3D { 41, 57, 0x1000, 12 }, [VM_MODE_P41V48_4K] =3D { 41, 48, 0x1000, 12 }, [VM_MODE_P41V39_4K] =3D { 41, 39, 0x1000, 12 }, + [VM_MODE_P52V52_4K] =3D { 52, 52, 0x1000, 12 }, + [VM_MODE_P52V52_64K] =3D { 52, 52, 0x10000, 16 }, }; _Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_pa= rams) =3D=3D NUM_VM_MODES, "Missing new mode params?"); @@ -371,6 +375,10 @@ struct kvm_vm *____vm_create(struct vm_shape shape) case VM_MODE_P41V39_4K: vm->mmu.pgtable_levels =3D 3; break; + case VM_MODE_P52V52_4K: + case VM_MODE_P52V52_64K: + vm->mmu.pgtable_levels =3D 4; + break; default: TEST_FAIL("Unknown guest mode: 0x%x", vm->mode); } diff --git a/tools/testing/selftests/kvm/lib/powerpc/handlers.S b/tools/tes= ting/selftests/kvm/lib/powerpc/handlers.S new file mode 100644 index 000000000000..b860f6a520a1 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/powerpc/handlers.S @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include + +.macro INTERRUPT vec +. =3D __interrupts_start + \vec + std %r0,(0*8)(%r13) + std %r3,(3*8)(%r13) + mfspr %r0,SPR_CFAR + li %r3,\vec + b handle_interrupt +.endm + +.balign 0x1000 +.global __interrupts_start +__interrupts_start: +INTERRUPT 0x100 +INTERRUPT 0x200 +INTERRUPT 0x300 +INTERRUPT 0x380 +INTERRUPT 0x400 +INTERRUPT 0x480 +INTERRUPT 0x500 +INTERRUPT 0x600 +INTERRUPT 0x700 +INTERRUPT 0x800 +INTERRUPT 0x900 +INTERRUPT 0xa00 +INTERRUPT 0xc00 +INTERRUPT 0xd00 +INTERRUPT 0xf00 +INTERRUPT 0xf20 +INTERRUPT 0xf40 +INTERRUPT 0xf60 + +virt_handle_interrupt: + stdu %r1,-INT_FRAME_SIZE(%r1) + mr %r3,%r31 + bl route_interrupt + ld %r4,(32*8)(%r31) /* NIA */ + ld %r5,(33*8)(%r31) /* MSR */ + ld %r6,(35*8)(%r31) /* LR */ + ld %r7,(36*8)(%r31) /* CTR */ + ld %r8,(37*8)(%r31) /* XER */ + lwz %r9,(38*8)(%r31) /* CR */ + mtspr SPR_SRR0,%r4 + mtspr SPR_SRR1,%r5 + mtlr %r6 + mtctr %r7 + mtxer %r8 + mtcr %r9 +reg=3D4 + ld %r0,(0*8)(%r31) + ld %r3,(3*8)(%r31) +.rept 28 + ld reg,(reg*8)(%r31) + reg=3Dreg+1 +.endr + addi %r1,%r1,INT_FRAME_SIZE + rfid + +virt_handle_interrupt_p: + .llong virt_handle_interrupt + +handle_interrupt: +reg=3D4 +.rept 28 + std reg,(reg*8)(%r13) + reg=3Dreg+1 +.endr + mfspr %r4,SPR_SRR0 + mfspr %r5,SPR_SRR1 + mflr %r6 + mfctr %r7 + mfxer %r8 + mfcr %r9 + std %r4,(32*8)(%r13) /* NIA */ + std %r5,(33*8)(%r13) /* MSR */ + std %r0,(34*8)(%r13) /* CFAR */ + std %r6,(35*8)(%r13) /* LR */ + std %r7,(36*8)(%r13) /* CTR */ + std %r8,(37*8)(%r13) /* XER */ + stw %r9,(38*8 + 0)(%r13) /* CR */ + stw %r3,(38*8 + 4)(%r13) /* TRAP */ + + ld %r31,(39*8)(%r13) /* vaddr */ + ld %r4,virt_handle_interrupt_p - __interrupts_start(0) + mtspr SPR_SRR0,%r4 + /* Reuse SRR1 */ + + rfid +.global __interrupts_end +__interrupts_end: diff --git a/tools/testing/selftests/kvm/lib/powerpc/hcall.c b/tools/testin= g/selftests/kvm/lib/powerpc/hcall.c new file mode 100644 index 000000000000..efb4318252be --- /dev/null +++ b/tools/testing/selftests/kvm/lib/powerpc/hcall.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PAPR (pseries) hcall support. + */ +#include "kvm_util.h" +#include "hcall.h" + +int64_t hcall0(uint64_t token) +{ + register uintptr_t r3 asm ("r3") =3D token; + + asm volatile("sc 1" : "+r"(r3) : + : "r0", "r4", "r5", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "ctr", "xer", + "cc", "memory"); + + return r3; +} + +int64_t hcall1(uint64_t token, uint64_t arg1) +{ + register uintptr_t r3 asm ("r3") =3D token; + register uintptr_t r4 asm ("r4") =3D arg1; + + asm volatile("sc 1" : "+r"(r3), "+r"(r4) : + : "r0", "r5", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "ctr", "xer", + "cc", "memory"); + + return r3; +} + +int64_t hcall2(uint64_t token, uint64_t arg1, uint64_t arg2) +{ + register uintptr_t r3 asm ("r3") =3D token; + register uintptr_t r4 asm ("r4") =3D arg1; + register uintptr_t r5 asm ("r5") =3D arg2; + + asm volatile("sc 1" : "+r"(r3), "+r"(r4), "+r"(r5) : + : "r0", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "ctr", "xer", + "cc", "memory"); + + return r3; +} diff --git a/tools/testing/selftests/kvm/lib/powerpc/processor.c b/tools/te= sting/selftests/kvm/lib/powerpc/processor.c new file mode 100644 index 000000000000..310c67a00b95 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/powerpc/processor.c @@ -0,0 +1,484 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * KVM selftest powerpc library code - CPU-related functions (page tables.= ..) + */ + +#include + +#include "processor.h" +#include "kvm_util.h" +#include "ucall_common.h" +#include "guest_modes.h" +#include "hcall.h" + +#define RADIX_TREE_SIZE ((0x2UL << 61) | (0x5UL << 5)) /* 52-bits */ +#define RADIX_PGD_INDEX_SIZE 13 + +static void set_proc_table(struct kvm_vm *vm, int pid, uint64_t dw0, uint6= 4_t dw1) +{ + uint64_t *proc_table; + + proc_table =3D addr_gpa2hva(vm, vm->arch.prtb); + proc_table[pid * 2 + 0] =3D cpu_to_be64(dw0); + proc_table[pid * 2 + 1] =3D cpu_to_be64(dw1); +} + +static void set_radix_proc_table(struct kvm_vm *vm, int pid, gpa_t pgd) +{ + set_proc_table(vm, pid, pgd | RADIX_TREE_SIZE | RADIX_PGD_INDEX_SIZE, 0); +} + +void virt_arch_pgd_alloc(struct kvm_vm *vm) +{ + struct kvm_ppc_mmuv3_cfg mmu_cfg; + gpa_t prtb, pgtb; + size_t pgd_pages; + + TEST_ASSERT((vm->mode =3D=3D VM_MODE_P52V52_4K) || + (vm->mode =3D=3D VM_MODE_P52V52_64K), + "Unsupported guest mode, mode: 0x%x", vm->mode); + + prtb =3D vm_phy_page_alloc(vm, KVM_GUEST_PAGE_TABLE_MIN_PADDR, + vm->memslots[MEM_REGION_PT]); + vm->arch.prtb =3D prtb; + + pgd_pages =3D (1UL << (RADIX_PGD_INDEX_SIZE + 3)) >> vm->page_shift; + if (!pgd_pages) + pgd_pages =3D 1; + pgtb =3D vm_phy_pages_alloc_align(vm, pgd_pages, pgd_pages, + KVM_GUEST_PAGE_TABLE_MIN_PADDR, + vm->memslots[MEM_REGION_PT]); + vm->mmu.pgd =3D pgtb; + + /* Set the base page directory in the proc table */ + set_radix_proc_table(vm, 0, pgtb); + + if (vm->mode =3D=3D VM_MODE_P52V52_4K) + mmu_cfg.process_table =3D prtb | 0x8000000000000000UL | 0x0; /* 4K size = */ + else /* vm->mode =3D=3D VM_MODE_P52V52_64K */ + mmu_cfg.process_table =3D prtb | 0x8000000000000000UL | 0x4; /* 64K size= */ + mmu_cfg.flags =3D KVM_PPC_MMUV3_RADIX | KVM_PPC_MMUV3_GTSE; + + vm_ioctl(vm, KVM_PPC_CONFIGURE_V3_MMU, &mmu_cfg); +} + +static int pt_shift(struct kvm_vm *vm, int level) +{ + switch (level) { + case 1: + return 13; + case 2: + case 3: + return 9; + case 4: + if (vm->mode =3D=3D VM_MODE_P52V52_4K) + return 9; + else /* vm->mode =3D=3D VM_MODE_P52V52_64K */ + return 5; + default: + TEST_ASSERT(false, "Invalid page table level %d\n", level); + return 0; + } +} + +static uint64_t pt_entry_coverage(struct kvm_vm *vm, int level) +{ + uint64_t size =3D vm->page_size; + + if (level =3D=3D 4) + return size; + size <<=3D pt_shift(vm, 4); + if (level =3D=3D 3) + return size; + size <<=3D pt_shift(vm, 3); + if (level =3D=3D 2) + return size; + size <<=3D pt_shift(vm, 2); + return size; +} + +static int pt_idx(struct kvm_vm *vm, uint64_t vaddr, int level, uint64_t *= nls) +{ + switch (level) { + case 1: + if (nls) + *nls =3D 0x9; + return (vaddr >> 39) & 0x1fff; + case 2: + if (nls) + *nls =3D 0x9; + return (vaddr >> 30) & 0x1ff; + case 3: + if (vm->mode =3D=3D VM_MODE_P52V52_4K) { + if (nls) + *nls =3D 0x9; + } else { /* vm->mode =3D=3D VM_MODE_P52V52_64K */ + if (nls) + *nls =3D 0x5; + } + return (vaddr >> 21) & 0x1ff; + case 4: + if (vm->mode =3D=3D VM_MODE_P52V52_4K) + return (vaddr >> 12) & 0x1ff; + else /* vm->mode =3D=3D VM_MODE_P52V52_64K */ + return (vaddr >> 16) & 0x1f; + default: + TEST_ASSERT(false, "Invalid page table level %d\n", level); + return 0; + } +} + +static uint64_t *virt_get_pte(struct kvm_vm *vm, gpa_t pt, + uint64_t vaddr, int level, uint64_t *nls) +{ + int idx =3D pt_idx(vm, vaddr, level, nls); + uint64_t *ptep =3D addr_gpa2hva(vm, pt + idx * 8); + + return ptep; +} + +#define PTE_VALID 0x8000000000000000ull +#define PTE_LEAF 0x4000000000000000ull +#define PTE_REFERENCED 0x0000000000000100ull +#define PTE_CHANGED 0x0000000000000080ull +#define PTE_PRIV 0x0000000000000008ull +#define PTE_READ 0x0000000000000004ull +#define PTE_RW 0x0000000000000002ull +#define PTE_EXEC 0x0000000000000001ull +#define PTE_PAGE_MASK 0x01fffffffffff000ull + +#define PDE_VALID PTE_VALID +#define PDE_NLS 0x0000000000000011ull +#define PDE_PT_MASK 0x0fffffffffffff00ull + +static gpa_t __vm_alloc_pt(struct kvm_vm *vm, uint64_t pt_shift) +{ + gpa_t pt; + + if (pt_shift >=3D vm->page_shift) { + size_t pt_pages =3D 1ULL << (pt_shift - vm->page_shift); + + pt =3D vm_phy_pages_alloc_align(vm, pt_pages, pt_pages, + KVM_GUEST_PAGE_TABLE_MIN_PADDR, + vm->memslots[MEM_REGION_PT]); + } else { + struct vm_pt_frag_cache *pt_frag_cache; + + if (pt_shift =3D=3D 8) { + pt_frag_cache =3D &vm->arch.pt_frag_cache[0]; + } else if (pt_shift =3D=3D 12) { + pt_frag_cache =3D &vm->arch.pt_frag_cache[1]; + } else { + TEST_ASSERT(0, "Invalid pt_shift:%lu\n", pt_shift); + return 0; + } + + if (!pt_frag_cache->page) { + pt_frag_cache->page =3D vm_phy_pages_alloc_align(vm, 1, 1, + KVM_GUEST_PAGE_TABLE_MIN_PADDR, + vm->memslots[MEM_REGION_PT]); + } + pt =3D pt_frag_cache->page + pt_frag_cache->page_nr_used; + pt_frag_cache->page_nr_used +=3D (1 << pt_shift); + if (pt_frag_cache->page_nr_used =3D=3D vm->page_size) { + pt_frag_cache->page =3D 0; + pt_frag_cache->page_nr_used =3D 0; + } + } + + return pt; +} + +void virt_arch_pg_map(struct kvm_vm *vm, uint64_t gva, uint64_t gpa) +{ + gpa_t pt =3D vm->mmu.pgd; + uint64_t *ptep, pte; + int level; + + for (level =3D 1; level <=3D 3; level++) { + uint64_t nls; + uint64_t *pdep =3D virt_get_pte(vm, pt, gva, level, &nls); + uint64_t pde =3D be64_to_cpu(*pdep); + + if (pde) { + TEST_ASSERT((pde & PDE_VALID) && !(pde & PTE_LEAF), + "Invalid PDE at level: %u gva: 0x%lx pde:0x%lx\n", + level, gva, pde); + pt =3D pde & PDE_PT_MASK; + continue; + } + + pt =3D __vm_alloc_pt(vm, nls + 3); + pde =3D PDE_VALID | nls | pt; + *pdep =3D cpu_to_be64(pde); + } + + ptep =3D virt_get_pte(vm, pt, gva, level, NULL); + pte =3D be64_to_cpu(*ptep); + + TEST_ASSERT(!pte, "PTE already present at level: %u gva: 0x%lx pte:0x%lx\= n", + level, gva, pte); + + pte =3D PTE_VALID | PTE_LEAF | PTE_REFERENCED | PTE_CHANGED | PTE_PRIV | + PTE_READ | PTE_RW | PTE_EXEC | (gpa & PTE_PAGE_MASK); + *ptep =3D cpu_to_be64(pte); +} + +gpa_t addr_arch_gva2gpa(struct kvm_vm *vm, gva_t gva) +{ + gpa_t pt =3D vm->mmu.pgd; + uint64_t *ptep, pte; + int level; + + for (level =3D 1; level <=3D 3; level++) { + uint64_t nls; + uint64_t *pdep =3D virt_get_pte(vm, pt, gva, level, &nls); + uint64_t pde =3D be64_to_cpu(*pdep); + + TEST_ASSERT((pde & PDE_VALID) && !(pde & PTE_LEAF), + "PDE not present at level: %u gva: 0x%lx pde:0x%lx\n", + level, gva, pde); + pt =3D pde & PDE_PT_MASK; + } + + ptep =3D virt_get_pte(vm, pt, gva, level, NULL); + pte =3D be64_to_cpu(*ptep); + + TEST_ASSERT(pte, + "PTE not present at level: %u gva: 0x%lx pte:0x%lx\n", + level, gva, pte); + + TEST_ASSERT((pte & PTE_VALID) && (pte & PTE_LEAF) && + (pte & PTE_READ) && (pte & PTE_RW) && (pte & PTE_EXEC), + "PTE not valid at level: %u gva: 0x%lx pte:0x%lx\n", + level, gva, pte); + + return (pte & PTE_PAGE_MASK) + (gva & (vm->page_size - 1)); +} + +static void virt_dump_pt(FILE *stream, struct kvm_vm *vm, gpa_t pt, + gva_t va, int level, uint8_t indent) +{ + int size, idx; + + size =3D 1U << (pt_shift(vm, level) + 3); + + for (idx =3D 0; idx < size; idx +=3D 8, va +=3D pt_entry_coverage(vm, lev= el)) { + uint64_t *page_table =3D addr_gpa2hva(vm, pt + idx); + uint64_t pte =3D be64_to_cpu(*page_table); + + if (!(pte & PTE_VALID)) + continue; + + if (pte & PTE_LEAF) { + fprintf(stream, + "%*s PTE[%d] gVA:0x%016lx -> gRA:0x%016llx\n", + indent, "", idx / 8, va, pte & PTE_PAGE_MASK); + } else { + fprintf(stream, "%*sPDE%d[%d] gVA:0x%016lx\n", + indent, "", level, idx / 8, va); + virt_dump_pt(stream, vm, pte & PDE_PT_MASK, va, + level + 1, indent + 2); + } + } + +} + +void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent) +{ + gpa_t pt =3D vm->mmu.pgd; + + if (!vm->mmu.pgd_created) + return; + + virt_dump_pt(stream, vm, pt, 0, 1, indent); +} + +static unsigned long get_r2(void) +{ + unsigned long r2; + + asm("mr %0,%%r2" : "=3Dr"(r2)); + + return r2; +} + +void vcpu_arch_set_entry_point(struct kvm_vcpu *vcpu, void *guest_code) +{ + struct kvm_regs regs; + + vcpu_regs_get(vcpu, ®s); + regs.pc =3D (uintptr_t)guest_code; + regs.gpr[12] =3D (uintptr_t)guest_code; + vcpu_regs_set(vcpu, ®s); +} + +struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id) +{ + const size_t stack_size =3D SZ_64K; + gva_t stack_vaddr, ex_regs_vaddr; + gpa_t ex_regs_paddr; + struct ex_regs *ex_regs; + struct kvm_regs regs; + struct kvm_vcpu *vcpu; + uint64_t lpcr; + + stack_vaddr =3D __vm_alloc(vm, stack_size, + DEFAULT_GUEST_STACK_VADDR_MIN, + MEM_REGION_DATA); + + ex_regs_vaddr =3D __vm_alloc(vm, stack_size, + DEFAULT_GUEST_STACK_VADDR_MIN, + MEM_REGION_DATA); + ex_regs_paddr =3D addr_gva2gpa(vm, ex_regs_vaddr); + ex_regs =3D addr_gpa2hva(vm, ex_regs_paddr); + ex_regs->vaddr =3D ex_regs_vaddr; + + vcpu =3D __vm_vcpu_add(vm, vcpu_id); + + vcpu_enable_cap(vcpu, KVM_CAP_PPC_PAPR, 1); + + /* Setup guest registers */ + vcpu_regs_get(vcpu, ®s); + lpcr =3D vcpu_get_reg(vcpu, KVM_REG_PPC_LPCR_64); + + regs.gpr[1] =3D stack_vaddr + stack_size - 256; + regs.gpr[2] =3D (uintptr_t)get_r2(); + regs.gpr[13] =3D (uintptr_t)ex_regs_paddr; + + regs.msr =3D MSR_SF | MSR_VEC | MSR_VSX | MSR_FP | + MSR_ME | MSR_IR | MSR_DR | MSR_RI; + + if (BYTE_ORDER =3D=3D LITTLE_ENDIAN) { + regs.msr |=3D MSR_LE; + lpcr |=3D LPCR_ILE; + } else { + lpcr &=3D ~LPCR_ILE; + } + + vcpu_regs_set(vcpu, ®s); + vcpu_set_reg(vcpu, KVM_REG_PPC_LPCR_64, lpcr); + + return vcpu; +} + +void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...) +{ + va_list ap; + struct kvm_regs regs; + int i; + + TEST_ASSERT(num >=3D 1 && num <=3D 5, "Unsupported number of args: %u\n", + num); + + va_start(ap, num); + vcpu_regs_get(vcpu, ®s); + + for (i =3D 0; i < num; i++) + regs.gpr[i + 3] =3D va_arg(ap, uint64_t); + + vcpu_regs_set(vcpu, ®s); + va_end(ap); +} + +void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu, uint8_t indent) +{ + struct kvm_regs regs; + + vcpu_regs_get(vcpu, ®s); + + fprintf(stream, "%*sNIA: 0x%016llx MSR: 0x%016llx\n", + indent, "", regs.pc, regs.msr); + fprintf(stream, "%*sLR: 0x%016llx CTR :0x%016llx\n", + indent, "", regs.lr, regs.ctr); + fprintf(stream, "%*sCR: 0x%08llx XER :0x%016llx\n", + indent, "", regs.cr, regs.xer); +} + +void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus) +{ + size_t excp_size =3D __interrupts_end - __interrupts_start; + size_t excp_pages =3D (excp_size + vm->page_size - 1) / vm->page_size; + gpa_t excp_paddr; + void *mem; + + excp_paddr =3D vm_phy_pages_alloc(vm, excp_pages, 0, + vm->memslots[MEM_REGION_DATA]); + + TEST_ASSERT(excp_paddr =3D=3D 0, + "Interrupt vectors not allocated at gPA address 0: (0x%lx)", + excp_paddr); + + mem =3D addr_gpa2hva(vm, excp_paddr); + memcpy(mem, __interrupts_start, excp_size); +} + +void assert_on_unhandled_exception(struct kvm_vcpu *vcpu) +{ + struct ucall uc; + + if (get_ucall(vcpu, &uc) =3D=3D UCALL_UNHANDLED) { + gpa_t ex_regs_paddr; + struct ex_regs *ex_regs; + struct kvm_regs regs; + + vcpu_regs_get(vcpu, ®s); + ex_regs_paddr =3D (gpa_t)regs.gpr[13]; + ex_regs =3D addr_gpa2hva(vcpu->vm, ex_regs_paddr); + + TEST_FAIL("Unexpected interrupt in guest NIA:0x%016lx MSR:0x%016lx TRAP:= 0x%04x", + ex_regs->nia, ex_regs->msr, ex_regs->trap); + } +} + +struct handler { + void (*fn)(struct ex_regs *regs); + int trap; +}; + +#define NR_HANDLERS 10 +static struct handler handlers[NR_HANDLERS]; + +void route_interrupt(struct ex_regs *regs) +{ + int i; + + for (i =3D 0; i < NR_HANDLERS; i++) { + if (handlers[i].trap =3D=3D regs->trap) { + handlers[i].fn(regs); + return; + } + } + + ucall(UCALL_UNHANDLED, 0); +} + +void vm_install_exception_handler(struct kvm_vm *vm, int trap, + void (*fn)(struct ex_regs *)) +{ + int i; + + for (i =3D 0; i < NR_HANDLERS; i++) { + if (!handlers[i].trap || handlers[i].trap =3D=3D trap) { + if (fn =3D=3D NULL) + trap =3D 0; /* Clear handler */ + handlers[i].trap =3D trap; + handlers[i].fn =3D fn; + sync_global_to_guest(vm, handlers[i]); + return; + } + } + + TEST_FAIL("Out of exception handlers"); +} + +void kvm_selftest_arch_init(void) +{ + TEST_REQUIRE(kvm_has_cap(KVM_CAP_PPC_MMU_RADIX)); + + /* + * powerpc default mode is set by host page size and not static, + * so start by computing that early. + */ + guest_modes_append_default(); +} diff --git a/tools/testing/selftests/kvm/lib/powerpc/ucall.c b/tools/testin= g/selftests/kvm/lib/powerpc/ucall.c new file mode 100644 index 000000000000..3481a7a0b850 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/powerpc/ucall.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ucall support. A ucall is a "hypercall to host userspace". + */ +#include "kvm_util.h" +#include "ucall_common.h" +#include "hcall.h" + +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run =3D vcpu->run; + + if (run->exit_reason =3D=3D UCALL_EXIT_REASON && + run->papr_hcall.nr =3D=3D H_UCALL) { + struct kvm_regs regs; + + vcpu_regs_get(vcpu, ®s); + if (regs.gpr[4] =3D=3D UCALL_R4_UCALL) + return (void *)regs.gpr[5]; + } + return NULL; +} --=20 2.39.5 From nobody Sun May 24 20:33:11 2026 Received: from mail-pf1-f176.google.com (mail-pf1-f176.google.com [209.85.210.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6217938756E for ; Sat, 23 May 2026 11:15:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534913; cv=none; b=g8FID1Kj9bb51Io4BjTWeI9VSmeUTR/J3kWWsXlSvxWbwzbtOaTQPxsbRC1w91yNGykoZs2iQDFpeWn91f3sqOkkkzVNF7q4P5sicVjW4v6sE7GIzX32ThJb8/BvECrH3uGcVpCCZGm3jLdJoCp4fG6xTbabds5EtJ0kkF1TStM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534913; c=relaxed/simple; bh=CkqwvECTMAFehZ2OT21YjJpmutFK8TTNcnulnKesIu8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LYLwlPvP6S2yVqTF5gNrtSJpb0FJOcRl6RDTZdu28rtlFLGCUJKpo0BS/llycSP0KUMJf/OBMZlvH82M4t3EMPjsV2Tg4uYqWVd8feWyqwBTEII83EyxOQiXlzhj8DkV1IvtiEc+IPAj3YFCtt8gtqFAxsT0PwjFgbBqg+LKoLw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dlbv/S1P; arc=none smtp.client-ip=209.85.210.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dlbv/S1P" Received: by mail-pf1-f176.google.com with SMTP id d2e1a72fcca58-824c9da9928so3629733b3a.3 for ; Sat, 23 May 2026 04:15:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779534912; x=1780139712; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WHUxe7lnPztFxDQVjPCLiqbcKDb3U3X7b1X5k1GLWTA=; b=dlbv/S1Pnr71XvLhS5Ack3ziGHo0J9nskFswkxecBzlw3ve+A6qiOVcP4hQQn4Z6L5 pmutIh/obD595aEzz4ZRImnmVBQNxT06Y5hYYcNL903X7xkabwdEn57xrCVuuIoSLQvI 4SIy2viVR+uuMFogLsjzO+QOLX+RpXtHLFCRfFMbM5MIEmTnKDdW3/wjzbduvSqJ/+du /nZs/bx84CGvIlLQtDhNztNsiNTnHpShYhy+cJlRmkAlcwSEsQw3r0xBSMGqsnta4xED j4+quCQ4v2gG/7L4mAeClL44Vns9THEvsIxs0e5ZU61LTqsIgdGYY9siElfKWvDMz+IZ mO3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779534912; x=1780139712; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=WHUxe7lnPztFxDQVjPCLiqbcKDb3U3X7b1X5k1GLWTA=; b=ZQDJTLHzLyBg3+kR5vDlprXlcTejgCHQ9KHP+Fewwiy57AxSsKAbrjrb/1jLP2HHWN 1FHZJ+cYlXBjfMlnpoD2y2Pkg+1DwJdq1wlyX14ZW55/wpBe3hgmt3w5ODu0nzK9AaAJ H/ldfYFoKiMEQxg1R4E7yIJuD5xyWgd3pnipUrYm9HiyL34syvfLBP8Vcs9csBwMJZiN Toww6Nti/0QCj7s4e1Zg5zhMKQCMWXcrYFZVCTKgcQICgLj4kYp5rZmFZydEYD9YkxWF hHuZqsgpdgaZXrGrDccHDy++4nh1jHQ9Kh0ODS4xkbagqe2LJ+p8nEjZxWs/Gd6YpnM+ jARw== X-Forwarded-Encrypted: i=1; AFNElJ/f8C7Oe/ni+M7pdT9mSOsPXagfLqRgYgL8Y403c1d82VbI9wRBoUSYf4e4Ge54uUYmI8Bm1bHpWmJfD7A=@vger.kernel.org X-Gm-Message-State: AOJu0Yw1ZieSIDouq5gktIjtUdFZB2diXxGeAgvh6JuZYeOaqBTxNoST KtDKcnut0UV/a9hfljMMcNHX/AnSk/cbHnPNqLuFRY2HJDyqtAL7Hovu X-Gm-Gg: Acq92OFFM88TVEkbVjKWm0fXDYhCz8Kg/HAVFxKV1p9mj+3kQINBX+fTcSSWp50L5P5 Gx2DtvollF/KI66v4bNrFC+FUS0ASc/+9Nt1teLGnYDRc5P7UDjNzSwk1+Q0x0g80GZMNXtX8bH gJAbn+X0I2FhJKs17zKpXtzRhQvvsmZAp5C4Y/ELeqZsXFIAiA1eTi+rZT7bBl/4LgzJybZ66jA UTNyy7bkj4Nunb7O/4Ng5n/7HWXHJ5jtsms9b4QstNCzTRMRGk2TIobb5HijA53V4/8e0n00fqK WrTO/FkF4y/nT38PbDYBmanETEmoCKURPn9Vid/WGPre7GPtnFBRj/VrsePKpxJEP8R/FGEYf7L ojwWVbrxTcrt4Pd7jxGFlyabPjXYagM3WD9zubfU5LOZy1i1qau2NtySlbIETtzkZg/5DH+O41i hJEmh6f/lbSl9dpFZma88/HJNnY+o2HVamiUqyXrQ= X-Received: by 2002:a05:6a00:bd0e:b0:81e:f1c3:89df with SMTP id d2e1a72fcca58-8415f3f73b2mr7274322b3a.50.1779534911562; Sat, 23 May 2026 04:15:11 -0700 (PDT) Received: from Mac.ibm.com ([49.205.216.49]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84164ac9c77sm5249140b3a.2.2026.05.23.04.15.06 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 23 May 2026 04:15:11 -0700 (PDT) From: "Ritesh Harjani (IBM)" To: kvm@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org, Madhavan Srinivasan , Harsh Prateek Bora , Christophe Leroy , Venkat Rao Bagalkote , Nicholas Piggin , Misbah Anjum N , Anushree Mathur , Michael Ellerman , linux-kernel@vger.kernel.org, "Ritesh Harjani (IBM)" Subject: [RFC v2 4/5] KVM: PPC: selftests: powerpc enable kvm_create_max_vcpus test Date: Sat, 23 May 2026 16:44:23 +0530 Message-ID: X-Mailer: git-send-email 2.50.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Nicholas Piggin powerpc's maximum permitted vCPU ID depends on the VM's SMT mode, and the maximum reported by KVM_CAP_MAX_VCPU_ID exceeds a simple non-SMT VM's limit. The powerpc KVM selftest port uses non-SMT VMs, so add a workaround to the kvm_create_max_vcpus test case to limit vCPU IDs to KVM_CAP_MAX_VCPUS on powerpc. Signed-off-by: Nicholas Piggin [Rebased to latest mainline tree] Signed-off-by: Ritesh Harjani (IBM) --- tools/testing/selftests/kvm/kvm_create_max_vcpus.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/testing/selftests/kvm/kvm_create_max_vcpus.c b/tools/tes= ting/selftests/kvm/kvm_create_max_vcpus.c index c5310736ed06..a82c13d6cdf5 100644 --- a/tools/testing/selftests/kvm/kvm_create_max_vcpus.c +++ b/tools/testing/selftests/kvm/kvm_create_max_vcpus.c @@ -56,6 +56,15 @@ int main(int argc, char *argv[]) "KVM_MAX_VCPU_IDS (%d) must be at least as large as KVM_MAX_VCPUS (%= d).", kvm_max_vcpu_id, kvm_max_vcpus); +#ifdef __powerpc64__ + /* + * powerpc has a particular format for the vcpu ID that depends on + * the guest SMT mode, and the max ID cap is too large for non-SMT + * modes, where the maximum ID is the same as the maximum vCPUs. + */ + kvm_max_vcpu_id =3D kvm_max_vcpus; +#endif + test_vcpu_creation(0, kvm_max_vcpus); if (kvm_max_vcpu_id > kvm_max_vcpus) -- 2.39.5 From nobody Sun May 24 20:33:11 2026 Received: from mail-pf1-f171.google.com (mail-pf1-f171.google.com [209.85.210.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 906373890FD for ; Sat, 23 May 2026 11:15:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534920; cv=none; b=NMWNHhtFAG5sBs71xST0hbuZfeVcAnSrTSPWNdYCcTVo+WwwCN7LsAyhZIEQz6kgow7mvk/JQv1pbuvQ6PfNqfy1m+4d3zWBX9Pjc7U/PCPFOWnrQbA3+Zn35Y4Th5l6fSWpb+vmgMEXCCEKmGRvehbbTDupdFLpEwdFhl6tXpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779534920; c=relaxed/simple; bh=a7mQhiqXWN/25mXiIq3tddj8NgbgZO493+WAfl016O4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZL7OJP4xL6rOfMyA/IEvJHKsp6HlqNJK8B1iHS3yaybqGdgLve37S57K4rLCLqbrP1NAhzj+uxqd2xttRw+hc1CR0dZSGBhxSC4ptoxxWbp9yT3Now17Sbc1ilktzsmYoB3kYf4OQK+kbRrM6GiQ71TrAByTZ09TUKjgaq6qM/E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=omvgpJAK; arc=none smtp.client-ip=209.85.210.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="omvgpJAK" Received: by mail-pf1-f171.google.com with SMTP id d2e1a72fcca58-834f1075805so6345149b3a.2 for ; Sat, 23 May 2026 04:15:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779534918; x=1780139718; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vTfV5I/6+8PKgpUetxyiP6m2rwpoR69hVt3JVVxbU6o=; b=omvgpJAKIN7TtEVwLwgmRV+/BpLhcsM7iinpuapGMZNJE2s1zdQp0q/kFFihepbBQm M+ytKvtVXx7XpHqM8eyJDm+7fML5mjwPgm9/L85A0c6LHEn6hGDxzInYF31QG1pRX/Y9 jYsURFL51qFbu9pL8EU2XIfmTLSP7rsFAEIy5g+CNyFL8Xqr1MT+YhoJBlQTHrG/1zL8 7KxW+DCK+YvtZAiKRLm6+Xydmz4t3QtpoHu5JpotEU6JwZCtbP2ybZ970TMH9mKrNo+h tTTBybdJ+DmymZY7DtWwIW3UM59XgCoe+YTUjQyG8NM6B2NLKgdUyiT0yq1316X580LL IB1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779534918; x=1780139718; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=vTfV5I/6+8PKgpUetxyiP6m2rwpoR69hVt3JVVxbU6o=; b=bZB6pn3tW0BWAtdmld0Q4Lk/7FeT+3i19bEDOgmUVgCq5g8c+beJ94NZq5X2Bpg+Gv ASbm6EC2nkrqyx90lIreHmg+CjAOmB2TV7bPF5T/q8BPZSyqZmVQowm+IYgsG27HH8uh vaub8kEFD0noa1cQMxY1y0eJgffLh/cY8YKynbDbESAGjvq2Ui+7m9Brgw7W0S0kQhCR uPLgmGz02KmbuG5QN+97TNwsYNUMha+2dHkcYHF7LvqcEoFzkxRpbzKlgE9dEdhJXC3i 4aDPtUhC+40fKmm0z0/6TIvMnR7kfTdZBz/wNqILs90RBWbYDHRU9JR6tYO38w84UICh Nfzg== X-Forwarded-Encrypted: i=1; AFNElJ9tt+ZzuQbuSv4ZN+Y6Iyeb+tn9+6b05sZh2VPo4kt/ENC0SeVhzVktbQNRDerdJZjUC7LUHha7PJcQNNY=@vger.kernel.org X-Gm-Message-State: AOJu0YzsYT3N2N9W9KsHBkXANpLqRy9PxWyjZ+B1a9+7J06JQESn45H9 bU6G+/GoiENqeFXhY2wD7+IOR5p4piN7vL2D5gZCx9jr2nzFxrEOwqw+ X-Gm-Gg: Acq92OGNtg+Whci0AJHQaAO/C23D67J9fE/45N776HP7U1duA17G1ODjv5X8k+mgb8j pIbg2ejKpxT9J611kBk7/gJhKwfn9Orf05cB4s0vCYi8qwjNbvkJyljWbuxBjuUBPq9dzB69sAW V7iqPG61c7udjqpYXU26JzDAYV1E3GhWjyQvAespQ/J579WcleZPWJdYO4c/27L0K98oBaS0hEO yJ2MOLuvUKpPZRQALCQCfti9j78BJIXt6X635LQWvKFS/dZoL1eqot/2UpjFJmFFugl/qbdsRp2 uAeBbIdvYY/+XGSsAI6ESZ7AAVyV4jJG9e8ysl+AtlEF0fNxf47RJNXKHqVSXzxJQ+0/2jeTC3E 3si2rzsrwHhPKeMKjVTVUlHEp0Om2xpVaz1EIAZ+KBXq8gHtdxckgR4OpyCDy5aH7pBepT5sdaJ PAHvDQDVPq6y0BeQy6q4qwPG25N6DhDC7Tsh5Yotg= X-Received: by 2002:a05:6a00:3d08:b0:83e:f75d:828d with SMTP id d2e1a72fcca58-8415f15a770mr7487815b3a.16.1779534917676; Sat, 23 May 2026 04:15:17 -0700 (PDT) Received: from Mac.ibm.com ([49.205.216.49]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84164ac9c77sm5249140b3a.2.2026.05.23.04.15.12 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 23 May 2026 04:15:17 -0700 (PDT) From: "Ritesh Harjani (IBM)" To: kvm@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org, Madhavan Srinivasan , Harsh Prateek Bora , Christophe Leroy , Venkat Rao Bagalkote , Nicholas Piggin , Misbah Anjum N , Anushree Mathur , Michael Ellerman , linux-kernel@vger.kernel.org, "Ritesh Harjani (IBM)" Subject: [RFC v2 5/5] KVM: selftests: Print the vcpu_id when KVM_CREATE_VCPU ioctl fails Date: Sat, 23 May 2026 16:44:24 +0530 Message-ID: <12184d5eda089814659d5a861b3ebc30d42733a3.1779524962.git.ritesh.list@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Print the vcpu_id and errno when the KVM_CREATE_VCPU ioctl fails, for debug purposes. This helped in debugging an issue with KVM on PowerVM, where KVM_CREATE_VCPU only supports max 2048 vcpus, because the PAPR_HCALL H_GUEST_CREATE_VCPU ("Documentation/arch/powerpc/kvm-nested.rst") supports only up to 0-2047 vcpu_id. However KVM_CAP_MAX_VCPUS capability extension always reports max_= vcpus as NR_CPUS of the host. Signed-off-by: Ritesh Harjani (IBM) --- tools/testing/selftests/kvm/lib/kvm_util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 0dc67c1502cf..6a0ee6803623 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1354,6 +1354,9 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, u32= vcpu_id) vcpu->vm =3D vm; vcpu->id =3D vcpu_id; vcpu->fd =3D __vm_ioctl(vm, KVM_CREATE_VCPU, (void *)(unsigned long)vcpu_= id); + if (vcpu->fd < 0) + pr_info("Failed KVM_CREATE_VCPU for vcpu_id %u with errno %d\n", + vcpu_id, errno); TEST_ASSERT_VM_VCPU_IOCTL(vcpu->fd >=3D 0, KVM_CREATE_VCPU, vcpu->fd, vm); TEST_ASSERT(vcpu_mmap_sz() >=3D sizeof(*vcpu->run), "vcpu mmap size " -- 2.39.5