From nobody Mon Sep 28 00:09:30 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1787118910; cv=none; d=zohomail.com; s=zohoarc; b=UWRG4V51+RH8CRCvZul9PfdRn/RG8SOFy/qnrnVxeitLqk1nlJ7N4p5aX/WKtOLLgHCo0/Ay3gohppUTucxzWuHt8NocM33iuaIM4WvsaL/a8TR1O46qkncfMaAtv/p8+Te8EQw1D1yplAhm4a45EIHS51x/guruRZk+dJJSopU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787118910; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=08nTZ8BlEZVF2fG/KvaQ5nP1tNkYkFgXiPifhkCCDBg=; b=AdZkDCcjc/1uPtUTFcy2pcRtZuI5opQGY3Q7Ek0Ce+KsYowVHiko8Ezr868YDVuanhhCr2G4FKUqoFfrb0+6bM61mcoVNQDLt/hlThN8aXFUsdaXNKTmJr1mDiUaV/3jlYG0Nm5l+oVYYya4OCUhHaYbbQyuZwyizTBw5qNvmX4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787118910383847.7898130587621; Tue, 18 Aug 2026 22:55:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wwZFe-0001SV-R5; Wed, 19 Aug 2026 01:54:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3O8SEagcKCjIXOQYmZWUccUZS.QcaeSai-RSjSZbcbUbi.cfU@flex--jackyli.bounces.google.com>) id 1wwQfx-0005zK-Ih for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:51 -0400 Received: from mail-pf1-x447.google.com ([2607:f8b0:4864:20::447]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3O8SEagcKCjIXOQYmZWUccUZS.QcaeSai-RSjSZbcbUbi.cfU@flex--jackyli.bounces.google.com>) id 1wwQfv-0007Ks-LP for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:49 -0400 Received: by mail-pf1-x447.google.com with SMTP id d2e1a72fcca58-84857446424so588677b3a.1 for ; Tue, 18 Aug 2026 13:44:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1787085883; x=1787690683; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=08nTZ8BlEZVF2fG/KvaQ5nP1tNkYkFgXiPifhkCCDBg=; b=p8HtCjK0+NcoDqzXHjps1fUQ/Z1vdcglmVYW6RaMwjuu69G6LBDFmJX6yCQXDgnRhu EIJ99kxR/54kGeNGQky0V0po2ibfo8ORcpfHLgfh89g2/BS8NvXekgS+ETELTZsxSnGG 3KiPqL5HTfO+fgPAUc7Tj69GDOoLm+/2KlZfU5f6RFKrm6pPqhrserEQZgKLV9dc31Ub XpQCrYN28T5lec8J76adjcIyueDcgUkfwjFKHazK2X1EbPqjqLVljxl8ukSEl4TsAqG0 UzLBoF6UxATQXSZcRxgJTEgV6Go8czQiH7fYVdVbjSF6yMal5JobN4a9yHIzSCyZbfta 0Bcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787085883; x=1787690683; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=08nTZ8BlEZVF2fG/KvaQ5nP1tNkYkFgXiPifhkCCDBg=; b=fiQ/o7FSyVMgjKncHGD0lBK91/IW1cpAaP08ocQBWiQexTdjjpXNOv96Drazjl+NZv yc9faD+OWtGr2/ITJYLeaA0qJqTyyD9ej2IlRdELBvJlan0xnoKEa4bRsNHRL579+2bS 7S1TV6iZc28jkNWyRlmHfbbwQB3nkjU/XJv2VBUmtJ3as39ph2tAuXk8dFZavg+Yexl5 I+F7cnqc8NgtM0zkATlO0xgDuYUnQS2mE+HAAFA0jhUcOE3xLkb9WTpurJ6KPCtK1Liy VDdDl978CSdsJi+w55UgB+iRFbPalhhVvxjEXwcOubr6tXTCxfZLA/Foc6BgHxFLUYBF pgRw== X-Gm-Message-State: AOJu0Yx0Np5++IjXJAAqrqLCNjILKaiKBqUq3kN0YwNMUI6xUCG2mnlJ tZr5shLIXjvYwV67go7+wlvFGOasEki7YXVQYBp8QZ9c/uWkYEodVrBi1DGhIMUlnifD1eW6o3/ P/QWTN7BSr5BRVUvRy7L26msZ9mM1b4c7eCeCaYqWKMcSeuu4IydILK+PLczdMQB4QAHLCRRJQQ kPG4NRLgmZrL/UFXW1KuGrOqg7xvjy8Hh1m+m1DEU= X-Received: from pfnv20.prod.google.com ([2002:aa7:8514:0:b0:84b:57b7:60c5]) (user=jackyli job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:4094:b0:848:4859:a45 with SMTP id d2e1a72fcca58-851cd954427mr1821986b3a.2.1787085883244; Tue, 18 Aug 2026 13:44:43 -0700 (PDT) Date: Tue, 18 Aug 2026 20:44:15 +0000 In-Reply-To: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> Mime-Version: 1.0 References: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> X-Mailer: b4 0.14.3 Message-ID: <20260818-feature-pkey-dev-v1-1-8c0ef96a4da9@google.com> Subject: [RFC PATCH 1/6] x86: Introduce basic PKRU hardware wrappers From: Jacky Li To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Zhao Liu , Richard Henderson , "=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?=" , Peter Xu , kvm@vger.kernel.org, James Houghton , Mingwei Zhang , Dave Hansen , Brendan Jackman , Reiji Watanabe , Jacky Li Content-Type: text/plain; charset="utf-8" Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::447; envelope-from=3O8SEagcKCjIXOQYmZWUccUZS.QcaeSai-RSjSZbcbUbi.cfU@flex--jackyli.bounces.google.com; helo=mail-pf1-x447.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 19 Aug 2026 01:54:07 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1787118911697158500 Content-Transfer-Encoding: quoted-printable Introduce basic hardware instruction wrappers and helper functions for interacting with x86 Protection Keys for Userspace (PKRU / MPK) in QEMU. Signed-off-by: Jacky Li --- MAINTAINERS | 1 + util/pkey.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 97 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b51f5c3e60..5a31c45963 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -156,6 +156,7 @@ F: target/i386/meson.build F: tools/i386/ F: tests/functional/i386/ F: tests/functional/x86_64/ +F: util/pkey.c =20 X86 VM file descriptor change on reset test M: Ani Sinha diff --git a/util/pkey.c b/util/pkey.c new file mode 100644 index 0000000000..4f14a72151 --- /dev/null +++ b/util/pkey.c @@ -0,0 +1,96 @@ +/* + * QEMU guest memory protection key helpers + * + * Copyright (c) 2026 Google LLC + * + * Author: + * Jacky Li + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "exec/cpu-common.h" +#include "qemu/error-report.h" + +#if defined(HOST_X86_64) && defined(CONFIG_LINUX) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qemu/atomic.h" + +#ifndef PR_SET_SPECULATION_CTRL +#define PR_SET_SPECULATION_CTRL 53 +#endif +#ifndef PR_SPEC_INDIRECT_BRANCH +#define PR_SPEC_INDIRECT_BRANCH 1 +#endif +#ifndef PR_SPEC_DISABLE +#define PR_SPEC_DISABLE (1UL << 2) +#endif + +#ifndef PKEY_DISABLE_ACCESS +#define PKEY_DISABLE_ACCESS 0x1 +#endif + +/* Each protection key occupies exactly 2 bits in the PKRU register. */ +#define BITS_PER_KEY 2 +/* The mask used to extract/write the 2-bit permission flags. */ +#define KEY_MASK 3U +/* Max protection keys supported on x86_64 */ +#define KEY_COUNT 16 + +static inline __attribute__((target("pku"), always_inline)) +uint32_t rdpkru(void) +{ + return _rdpkru_u32(); +} + +static inline __attribute__((target("pku"), always_inline)) void wrpkru( + uint32_t pkru) +{ + _wrpkru(pkru); +} + +static inline __attribute__((target("pku"), always_inline)) int inline_pke= y_get( + int pkey) +{ + uint32_t pkru =3D rdpkru(); + return (pkru >> (pkey * BITS_PER_KEY)) & KEY_MASK; +} + +static inline __attribute__((target("pku"), always_inline)) void +inline_pkey_set(int pkey, unsigned int access_rights) +{ + uint32_t pkru =3D rdpkru(); + pkru &=3D ~(KEY_MASK << (pkey * BITS_PER_KEY)); + pkru |=3D ((access_rights & KEY_MASK) << (pkey * BITS_PER_KEY)); + wrpkru(pkru); +} + +static inline __attribute__((always_inline)) intptr_t local_syscall3( + intptr_t num, intptr_t arg1, intptr_t arg2, intptr_t arg3) +{ + intptr_t ret =3D num; + asm volatile("syscall\n" + : "+a"(ret) + : "D"(arg1), "S"(arg2), "d"(arg3) + : "rcx", "r11", "memory"); + return ret; +} + +#else +/* Dummy implementations for all other configurations (non-x86_64 Linux, */ +/* Windows, macOS, etc.) */ +#if defined(CONFIG_LINUX) +#include +#include +#endif +#endif --=20 2.55.0.737.g08866a6d13-goog From nobody Mon Sep 28 00:09:30 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1787118910; cv=none; d=zohomail.com; s=zohoarc; b=EZGA+8UR8ttt8AtDjMikHr9b/77n3pF+tgUFIE3tlxRjUxElWigr9eqhL9soGiOKxctV46wF4DEii8caE1iN5mtWewhKGfV5tf+H1kaPQd8PIy3vZR6P2UzCG420YksrEdkE87R+AUbPAB5lWkSOK9jvsQti9EuFwQj2AMGPxt0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787118910; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=NzXfJ7GrXHwgFSyfN75/LYVcSrb54eTxnKJjh2ZDD8c=; b=b2RFbx/h/cTizlwdGT/x1oGRNEhbnjM2jQ/cfWobfwyMZ8oClU+vCaqhzX16n2J3Gqov/mtDcuOtnJWvjADn2C1oMUDoa0pxzdFhf4bfPOMkqXYVNosAKkD71796oXj/PYqhEdAcobhyBktBpPKU33Ut6a6TyRmUt0qE88AYCrU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787118910487832.7709469064976; Tue, 18 Aug 2026 22:55:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wwZFh-0001TJ-En; Wed, 19 Aug 2026 01:54:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3PMSEagcKCjMYPRZnaXVddVaT.RdbfTbj-STkTacdcVcj.dgV@flex--jackyli.bounces.google.com>) id 1wwQfx-0005zM-It for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:51 -0400 Received: from mail-pg1-x547.google.com ([2607:f8b0:4864:20::547]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3PMSEagcKCjMYPRZnaXVddVaT.RdbfTbj-STkTacdcVcj.dgV@flex--jackyli.bounces.google.com>) id 1wwQfv-0007L3-T1 for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:49 -0400 Received: by mail-pg1-x547.google.com with SMTP id 41be03b00d2f7-cbbb9c9bfc3so129335a12.1 for ; Tue, 18 Aug 2026 13:44:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1787085885; x=1787690685; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=NzXfJ7GrXHwgFSyfN75/LYVcSrb54eTxnKJjh2ZDD8c=; b=Yv0P4pe56246bV6ZyvdREpwXX/0XCMK83XVa1mvRoCuL7J/0mGgUjSE/piKFOOlb7j H9nT1zbMrlbRWfWJsFShvvb0Aschi9GhrNp076Lb/KfQSJ0+5nOndQUtOlhqU3i9N525 O6UcDb31AohUUANXbVyUKyyES8DilhKQ8qOEctD+exsIR35gLKE2KMnaCeRfcfovjkK8 61ENYwJ97h+Lj8mQcKGwzKvf/TjskParbVYZ3MIr1OH/kd9eUAvUTZr1B39sgZwVOECF 2pgXLybkyw8VIootBbPPojxUiZ4pXVt7txsLm09aeQMzYGAKkRIWDj6UotCkqFNF6MnD HDpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787085885; x=1787690685; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=NzXfJ7GrXHwgFSyfN75/LYVcSrb54eTxnKJjh2ZDD8c=; b=rFUR9j5kFY2sTq8ZHBRt83ImytwNepTDCJiHoRMRnXCEQRBl0t8bysD5HEpVLMZN1e RNarJ1Qqkwz1OkAZSaZcag7v32gdWPOFQVmwnkFiqYqqCCn7JnYsR1B/GL3+rsrzdtEP B7DVNzcecNU9glJxoClgMLpyrvYXH0eNot51Abm7Vb04iCpu45v8VUxO+dFJulRj9m8w lCtF2UCKqQPFvl5fM7yypxmUtVWR7tOzlxlH24yzqV9mmy54kjEXUwienYPHgqWxiYIn M8BhBN6LkqkIY85mERzc6WCwGMIVARZMOFFRKJbKHc0s7k6ows9r4vLn/tiaZBBIzDH8 yqmw== X-Gm-Message-State: AOJu0Yzmy8yC2ng3NNi98OShF1JqMda+wp9ZowqhoTJ0t55XJ+UFInd1 gN23y4CwKcUhDKw22c2OyrN1ypRS2BDWcLOPI4b4knnZhAilgSkkT16PYfeYgDcNGRqzcTRN3ox yvW7LAurqAyy+W6D1gHTO/TTT3v6woHw1lkAPNg3xkViL3xWxLtusYQuG+sVE/1dNKfUStFpto8 elQAVMc6sWpL25iHe0ri4JA/TRTD0IDZGbvlW1NmA= X-Received: from pfbem53.prod.google.com ([2002:a05:6a00:3775:b0:851:8c82:93ea]) (user=jackyli job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:9a1:b0:84e:24f:2667 with SMTP id d2e1a72fcca58-851cd7a9ccemr1725750b3a.8.1787085884306; Tue, 18 Aug 2026 13:44:44 -0700 (PDT) Date: Tue, 18 Aug 2026 20:44:16 +0000 In-Reply-To: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> Mime-Version: 1.0 References: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> X-Mailer: b4 0.14.3 Message-ID: <20260818-feature-pkey-dev-v1-2-8c0ef96a4da9@google.com> Subject: [RFC PATCH 2/6] kvm: Add guest memory Pkey initialization From: Jacky Li To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Zhao Liu , Richard Henderson , "=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?=" , Peter Xu , kvm@vger.kernel.org, James Houghton , Mingwei Zhang , Dave Hansen , Brendan Jackman , Reiji Watanabe , Jacky Li Content-Type: text/plain; charset="utf-8" Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::547; envelope-from=3PMSEagcKCjMYPRZnaXVddVaT.RdbfTbj-STkTacdcVcj.dgV@flex--jackyli.bounces.google.com; helo=mail-pg1-x547.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 19 Aug 2026 01:54:07 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1787118911875158500 Content-Transfer-Encoding: quoted-printable Add initialization logic during early QEMU startup to allocate a dedicated userspace protection key (Pkey) for protecting guest physical memory when enabled via QEMU_ENABLE_PKEY_GUEST_MEMORY. Signed-off-by: Jacky Li --- include/exec/cpu-common.h | 1 + system/vl.c | 1 + util/meson.build | 2 +- util/pkey.c | 23 +++++++++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 6594f7fa1b..5ede0c65dc 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -112,4 +112,5 @@ static inline CPUState *env_cpu(CPUArchState *env) return (CPUState *)env_cpu_const(env); } =20 +void qemu_init_guest_memory_pkey(void); #endif /* CPU_COMMON_H */ diff --git a/system/vl.c b/system/vl.c index 061cbdf860..e49c6fed39 100644 --- a/system/vl.c +++ b/system/vl.c @@ -2907,6 +2907,7 @@ void qemu_init(int argc, char **argv) module_allow_arch(target_name()); =20 qemu_init_subsystems(); + qemu_init_guest_memory_pkey(); =20 /* first pass of option parsing */ optind =3D 1; diff --git a/util/meson.build b/util/meson.build index fa174c07a5..682a078a3d 100644 --- a/util/meson.build +++ b/util/meson.build @@ -9,7 +9,7 @@ if host_os !=3D 'windows' util_ss.add(files('compatfd.c')) util_ss.add(files('event_notifier-posix.c')) if host_os !=3D 'emscripten' - util_ss.add(files('mmap-alloc.c')) + util_ss.add(files('mmap-alloc.c', 'pkey.c')) endif freebsd_dep =3D [] if host_os =3D=3D 'freebsd' diff --git a/util/pkey.c b/util/pkey.c index 4f14a72151..249e36d508 100644 --- a/util/pkey.c +++ b/util/pkey.c @@ -40,6 +40,8 @@ #define PKEY_DISABLE_ACCESS 0x1 #endif =20 +static int guest_memory_pkey =3D -1; + /* Each protection key occupies exactly 2 bits in the PKRU register. */ #define BITS_PER_KEY 2 /* The mask used to extract/write the 2-bit permission flags. */ @@ -86,6 +88,24 @@ static inline __attribute__((always_inline)) intptr_t lo= cal_syscall3( return ret; } =20 +__attribute__((target("pku"))) void qemu_init_guest_memory_pkey(void) +{ + if (guest_memory_pkey !=3D -1) { + return; + } + + const char *enable_pkey =3D getenv("QEMU_ENABLE_PKEY_GUEST_MEMORY"); + if (enable_pkey && strcmp(enable_pkey, "1") =3D=3D 0) { + int pkey =3D pkey_alloc(0, 0); + if (pkey =3D=3D -1) { + error_report("pkey_alloc failed for guest memory: %s", + strerror(errno)); + } else { + guest_memory_pkey =3D pkey; + } + } +} + #else /* Dummy implementations for all other configurations (non-x86_64 Linux, */ /* Windows, macOS, etc.) */ @@ -93,4 +113,7 @@ static inline __attribute__((always_inline)) intptr_t lo= cal_syscall3( #include #include #endif + +void qemu_init_guest_memory_pkey(void) +{} #endif --=20 2.55.0.737.g08866a6d13-goog From nobody Mon Sep 28 00:09:30 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1787118910; cv=none; d=zohomail.com; s=zohoarc; b=nIEGYNiNiT8pgJpDjkKhT/ilwFap1DxLBzuK+waU9wH8mhpGjAhprZ64w1fTl8ZTwaWQUXULZdPHrotFPNplkaky4f723HVQUwIWK/fTxAdrEnOIVuYPjc85LZjEVpO7Dk8qKkoOt9vIXG77EvYEogPYYLydQ4han4H8Hx5vl7E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787118910; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=XSfBO46rQqbTNTbJ8xMsfzE0sjSykEikLSHsdbiM95o=; b=n4tHJ7LflEKMZu75nvY8Jkoy9TO22RcYMEGZfnqsW4e8K62HFMW7CDLBe1i27kvl+oO1B0JMAdLBav0TdSsCICjDDH59KhA3bMNHs9oW9h2UQlKzIOTyJhYqn9nsrrQ+09CzQKeIJCPfY9qJ+9jNkDj4fszsAZIlw6c4ptqO9tQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787118910027564.359225450861; Tue, 18 Aug 2026 22:55:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wwZFe-0001S5-0y; Wed, 19 Aug 2026 01:54:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3PcSEagcKCjQZQSaobYWeeWbU.SecgUck-TUlUbdedWdk.ehW@flex--jackyli.bounces.google.com>) id 1wwQg1-0005zi-Jp for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:53 -0400 Received: from mail-pl1-x648.google.com ([2607:f8b0:4864:20::648]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3PcSEagcKCjQZQSaobYWeeWbU.SecgUck-TUlUbdedWdk.ehW@flex--jackyli.bounces.google.com>) id 1wwQfw-0007L9-ID for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:50 -0400 Received: by mail-pl1-x648.google.com with SMTP id d9443c01a7336-2cfa55c9430so2324745ad.0 for ; Tue, 18 Aug 2026 13:44:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1787085886; x=1787690686; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=XSfBO46rQqbTNTbJ8xMsfzE0sjSykEikLSHsdbiM95o=; b=wDkJ5/vxoINJvcQEUVriaNpNFmk/cKSYKjeq6Q/TqodTysmCIU0MCiefYUQ0JDJjd0 +ByArmvqfAS4TkaCPlUep8ozubfnlgjuLQvAYlWSIE8NcS/As0KPMSw1bk5FppeHlP9X j//9XzXHiXZ9WganUhmtS97Id7LWNAgRGjnBW1xAirQWuIOMxVV6xZFkdHUrUPAITd5I NqySrTCR0mRY4QkmPLdptvldf34OP70aEyFVo9xhAFYCMv8YNN65kPViB9bSso5KGbt1 CIDsfGWvz6biHIhNVUhhdFj2nrV7wzVQdR/HiBCRSAw9OsgCPx4HjyG4ieLYimQxmjgf Y6Jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787085886; x=1787690686; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=XSfBO46rQqbTNTbJ8xMsfzE0sjSykEikLSHsdbiM95o=; b=J1SuC9UxiaZeNUrQiOxMahsdpLrm+aKx5blHDsejDwVj+PM+aDLwY2c+AGXqasucBE lGF66UIyfNOdVNpx42+VWsbTtsqBi3YfKYh+5qEoq2sNNA6Fu6s654lxPGItvtYm7GXe 9TpeG05fBdxf229KmzZsn8gLCH2HTf3nRx3FfzA0k6r8lRceqbShADFPdlp812iMAlaE jbONwue/3qHEs8J3/+jc15ihS643LqpPdet6V3H3sep73irAc9lC+L7RXvM0KihNO0Xd ZgDKCeo45o0eake8xmMQZ4NzJMUkFc70q7cBAPvRmgcPhvSA+5znHZsopa81cWSYf4tH BX8A== X-Gm-Message-State: AOJu0YwZ30enAaX9HtT+6Ei5zr2XtNC8ddmTYqPBlqcDWX2ga2n6o+hA fLOWVvANqqdPlaiEG/+AoTGsPbdkPSAUmT79xmSiF1fBjOHpC9m2Pn/ObTzrtYlnK+e4KEwmZEv isSljBzPH7s0zwKv5axCS+4AYnn7HC42xkGVEGgfdHejLa7rVUxEhlr0HIZ4Oi3C80KjgjufzuU ceYXpO3fywwhs5fQ52BCrfxvmY4DCS2VAX8vWGnco= X-Received: from pglg36.prod.google.com ([2002:a63:1124:0:b0:cc1:522f:464c]) (user=jackyli job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:cd96:b0:3bf:6d96:ac40 with SMTP id adf61e73a8af0-3ccfef7af73mr837294637.12.1787085885436; Tue, 18 Aug 2026 13:44:45 -0700 (PDT) Date: Tue, 18 Aug 2026 20:44:17 +0000 In-Reply-To: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> Mime-Version: 1.0 References: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> X-Mailer: b4 0.14.3 Message-ID: <20260818-feature-pkey-dev-v1-3-8c0ef96a4da9@google.com> Subject: [RFC PATCH 3/6] physmem: Tag guest RAMBlocks with Protection Key From: Jacky Li To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Zhao Liu , Richard Henderson , "=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?=" , Peter Xu , kvm@vger.kernel.org, James Houghton , Mingwei Zhang , Dave Hansen , Brendan Jackman , Reiji Watanabe , Jacky Li Content-Type: text/plain; charset="utf-8" Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::648; envelope-from=3PcSEagcKCjQZQSaobYWeeWbU.SecgUck-TUlUbdedWdk.ehW@flex--jackyli.bounces.google.com; helo=mail-pl1-x648.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 19 Aug 2026 01:54:07 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1787118911712158500 Content-Transfer-Encoding: quoted-printable Apply the allocated guest memory protection key to all guest RAMBlocks using `pkey_mprotect()` to enforce hardware-assisted access control. This ensures that guest physical RAM mappings are tagged with our dedicated Pkey in the host page tables, allowing the PKRU register to dynamically permit or block access to guest memory. Signed-off-by: Jacky Li --- include/exec/cpu-common.h | 1 + include/qemu/mmap-alloc.h | 5 +++++ system/physmem.c | 16 ++++++++++++++-- util/mmap-alloc.c | 3 +-- util/pkey.c | 16 ++++++++++++++++ 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 5ede0c65dc..28399088f6 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -113,4 +113,5 @@ static inline CPUState *env_cpu(CPUArchState *env) } =20 void qemu_init_guest_memory_pkey(void); +int qemu_pkey_mprotect_guest_memory(void *addr, size_t len, int prot); #endif /* CPU_COMMON_H */ diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h index 8344daaa03..82fe7f0c3d 100644 --- a/include/qemu/mmap-alloc.h +++ b/include/qemu/mmap-alloc.h @@ -63,4 +63,9 @@ void qemu_ram_munmap(int fd, void *ptr, size_t size); */ #define QEMU_MAP_NORESERVE (1 << 3) =20 +static inline int qemu_map_flags_to_prot(uint32_t qemu_map_flags) +{ + return PROT_READ | ((qemu_map_flags & QEMU_MAP_READONLY) ? 0 : PROT_WRIT= E); +} + #endif diff --git a/system/physmem.c b/system/physmem.c index 362a00f76c..9f5a0f194c 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -2144,6 +2144,12 @@ static void dirty_memory_extend(ram_addr_t new_ram_s= ize) ram_list.num_dirty_blocks =3D new_num_blocks; } =20 +static inline int ramblock_get_prot(const RAMBlock *rb) +{ + uint32_t map_flags =3D (rb->flags & RAM_READONLY) ? QEMU_MAP_READONLY : = 0; + return qemu_map_flags_to_prot(map_flags); +} + static void ram_block_add(RAMBlock *new_block, Error **errp) { const bool noreserve =3D qemu_ram_is_noreserve(new_block); @@ -2282,6 +2288,13 @@ static void ram_block_add(RAMBlock *new_block, Error= **errp) } ram_block_notify_add(new_block->host, new_block->used_length, new_block->max_length); + int prot =3D ramblock_get_prot(new_block); + int ret =3D qemu_pkey_mprotect_guest_memory(new_block->host, + new_block->max_length, p= rot); + if (ret !=3D 0) { + error_report("qemu_pkey_mprotect failed for guest RAMBlock: %s= ", + strerror(errno)); + } } return; =20 @@ -2624,8 +2637,7 @@ static int qemu_ram_remap_mmap(RAMBlock *block, uint6= 4_t start, size_t length) flags =3D MAP_FIXED | MAP_ANONYMOUS; flags |=3D block->flags & RAM_SHARED ? MAP_SHARED : MAP_PRIVATE; flags |=3D block->flags & RAM_NORESERVE ? MAP_NORESERVE : 0; - prot =3D PROT_READ; - prot |=3D block->flags & RAM_READONLY ? 0 : PROT_WRITE; + prot =3D ramblock_get_prot(block); area =3D mmap(host_startaddr, length, prot, flags, -1, 0); return area !=3D host_startaddr ? -errno : 0; } diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c index ed14f9c64d..0dc8e8275d 100644 --- a/util/mmap-alloc.c +++ b/util/mmap-alloc.c @@ -185,10 +185,9 @@ static void *mmap_activate(void *ptr, size_t size, int= fd, uint32_t qemu_map_flags, off_t map_offset) { const bool noreserve =3D qemu_map_flags & QEMU_MAP_NORESERVE; - const bool readonly =3D qemu_map_flags & QEMU_MAP_READONLY; const bool shared =3D qemu_map_flags & QEMU_MAP_SHARED; const bool sync =3D qemu_map_flags & QEMU_MAP_SYNC; - const int prot =3D PROT_READ | (readonly ? 0 : PROT_WRITE); + const int prot =3D qemu_map_flags_to_prot(qemu_map_flags); int map_sync_flags =3D 0; int flags =3D MAP_FIXED; void *activated_ptr; diff --git a/util/pkey.c b/util/pkey.c index 249e36d508..0151714f32 100644 --- a/util/pkey.c +++ b/util/pkey.c @@ -106,6 +106,17 @@ __attribute__((target("pku"))) void qemu_init_guest_me= mory_pkey(void) } } =20 +__attribute__((target("pku"))) int qemu_pkey_mprotect_guest_memory(void *a= ddr, + size_t = len, + int pro= t) +{ + int pkey =3D guest_memory_pkey; + if (pkey =3D=3D -1) { + return 0; + } + return pkey_mprotect(addr, len, prot, pkey); +} + #else /* Dummy implementations for all other configurations (non-x86_64 Linux, */ /* Windows, macOS, etc.) */ @@ -116,4 +127,9 @@ __attribute__((target("pku"))) void qemu_init_guest_mem= ory_pkey(void) =20 void qemu_init_guest_memory_pkey(void) {} + +int qemu_pkey_mprotect_guest_memory(void *addr, size_t len, int prot) +{ + return 0; +} #endif --=20 2.55.0.737.g08866a6d13-goog From nobody Mon Sep 28 00:09:30 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1787118910; cv=none; d=zohomail.com; s=zohoarc; b=BX5j3oJqSX8tDKNh/gS9mLIDW+5FGDRUWHMExnAPlXkNhpUyGYWvLzsYnt9Nz4P+g3GH6fjLT5N/WZ68irE8GOOjGZ68vl6cbXo4Fdr+JJ7wtvLpGcbS17a4XHcUX0+lLGOSIK12ZPJBh/3TsEEt88kxs9Aqo32kKlIG30MkNso= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787118910; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=PQq0Bm6wEPPaaVqXBMNHqZK4usIK/j6tgDNzvWv82vs=; b=ApRmHVBzqple5hSLoRIMLj7Ciiv5TAWU1/oMB6iBCef0dMSxVkq6Qu9z73qmVqYeZ9tGbmjrBiaaLe67HPV0x4SHG3kR1Bp1jPJGFZVpiMGi3mEp3RzUfojhRu0ldbIZfHb2DS6Jbkbqbd7QobwYAS3mbUcLhltTRbZGfmVGNp0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787118910076923.6347440528543; Tue, 18 Aug 2026 22:55:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wwZFc-0001R1-EG; Wed, 19 Aug 2026 01:54:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3PsSEagcKCjUaRTbpcZXffXcV.TfdhVdl-UVmVcefeXel.fiX@flex--jackyli.bounces.google.com>) id 1wwQg1-0005zh-K1 for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:53 -0400 Received: from mail-pf1-x446.google.com ([2607:f8b0:4864:20::446]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3PsSEagcKCjUaRTbpcZXffXcV.TfdhVdl-UVmVcefeXel.fiX@flex--jackyli.bounces.google.com>) id 1wwQfx-0007LP-0T for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:50 -0400 Received: by mail-pf1-x446.google.com with SMTP id d2e1a72fcca58-84f7002f9afso276424b3a.3 for ; Tue, 18 Aug 2026 13:44:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1787085887; x=1787690687; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=PQq0Bm6wEPPaaVqXBMNHqZK4usIK/j6tgDNzvWv82vs=; b=YgbZrx2oAhW7uDFtnYc7orJPUsahuCXTMM6VKJpMnGbPWvguvIvCvZnHfoDpVL2Hl8 cMdHNCBYqmqf5W1SY3jAwb70NTadGIWr0CkTD+O2gyCT7+eUsV9pBHg5S0k9hFLTvVut HMBxjMRGCI2v9FkrfObPOtDbzA+fnmUFEl8PM3J7wIDC8g4anKMvZfTg3bieV9772LAH SSf3Far5OIptyUdqLMbsKyjaQfTYA4Y9x+hZ2gHHKtRRIvnCjTxTgn7CT1iZcZSwVfFm pnS8sQGOI/TCWqqo7dDGQ8wg3Yavf1d99KEYOttBELjml0Yvv/l4Wq9J70e7sxiCRSbq zZLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787085887; x=1787690687; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=PQq0Bm6wEPPaaVqXBMNHqZK4usIK/j6tgDNzvWv82vs=; b=ByZF0ne4Y5hQgn0UMV8QzZaOmzSjRd8sCtwnlZia8/mdu6+xdHGTs3gQ97UY+qJGfL AGedRmUPnS4mgZTSgXYonapi+ALh7biNNqNiLBX0g1tzgN64FE5Ao16MUFGLjoh1nZmf cy3r6vrFlXtfQ1nELNw+0ePUNR9LE3oo3PIHAAiUw0rJfV89T613a5uuRmSxaNd21Wow bMOojyXELuvaKifN4KU8iQaQvAmgLy90rGNZS6l+b6Ko8sdRdXxHNAdoC8AbRFFCR3NA oS0RYfgUuiquueHAV4w0hc2KoODYZb1oy+o6wKk3O4Uyf+Nkry5aNL2IX9uGCGaTgU+y pi5A== X-Gm-Message-State: AOJu0YzXCCb70dO7zoWtBgp9urDXXGVZ7oGP4I8tU7pieFUEX/Jp8+o7 h4Ye/hvTjKbq5111FlBiv8hqVpPEk0RidO7eWB0+FFIfjcbjzFWjPAvHY2xyMFD0boToxNy/RdY eAN/cOUbIteAyN2fh5J+mKsFcaSaCrV6UR3zJYlevnUuAE4UwECtLZ8oRO49pc3QNp9qOvMXZ0f LQzazFPTNmyRL/8oMvCmKEYx/lU8ROsb21RJ4Ehz0= X-Received: from pfbim15.prod.google.com ([2002:a05:6a00:8d8f:b0:84e:46f:f15e]) (user=jackyli job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2e19:b0:847:97a4:d6b3 with SMTP id d2e1a72fcca58-851cd8346efmr1708280b3a.16.1787085886501; Tue, 18 Aug 2026 13:44:46 -0700 (PDT) Date: Tue, 18 Aug 2026 20:44:18 +0000 In-Reply-To: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> Mime-Version: 1.0 References: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> X-Mailer: b4 0.14.3 Message-ID: <20260818-feature-pkey-dev-v1-4-8c0ef96a4da9@google.com> Subject: [RFC PATCH 4/6] kvm: Lock guest RAMBlocks via PKRU during host userspace execution From: Jacky Li To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Zhao Liu , Richard Henderson , "=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?=" , Peter Xu , kvm@vger.kernel.org, James Houghton , Mingwei Zhang , Dave Hansen , Brendan Jackman , Reiji Watanabe , Jacky Li Content-Type: text/plain; charset="utf-8" Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::446; envelope-from=3PsSEagcKCjUaRTbpcZXffXcV.TfdhVdl-UVmVcefeXel.fiX@flex--jackyli.bounces.google.com; helo=mail-pf1-x446.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 19 Aug 2026 01:54:09 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1787118911695158500 Content-Transfer-Encoding: quoted-printable Protect guest RAMBlocks from host-side speculative execution attacks by locking and unlocking the guest memory protection key before and after `KVM_RUN`. Signed-off-by: Jacky Li --- accel/kvm/kvm-all.c | 7 ++++++- include/exec/cpu-common.h | 2 ++ system/physmem.c | 6 +++++- util/pkey.c | 45 +++++++++++++++++++++++++++++++++++++++++++= ++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 83cbd120a8..ae395cd374 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -19,6 +19,7 @@ =20 #include =20 +#include "exec/cpu-common.h" #include "qemu/atomic.h" #include "qemu/option.h" #include "qemu/config-file.h" @@ -3666,7 +3667,11 @@ int kvm_vcpu_ioctl(CPUState *cpu, unsigned long type= , ...) =20 trace_kvm_vcpu_ioctl(cpu->cpu_index, type, arg); accel_cpu_ioctl_begin(cpu); - ret =3D ioctl(cpu->kvm_fd, type, arg); + if (type =3D=3D KVM_RUN) { + ret =3D qemu_pkey_kvm_run(cpu->kvm_fd, arg); + } else { + ret =3D ioctl(cpu->kvm_fd, type, arg); + } accel_cpu_ioctl_end(cpu); if (ret =3D=3D -1) { ret =3D -errno; diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 28399088f6..90047128de 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -114,4 +114,6 @@ static inline CPUState *env_cpu(CPUArchState *env) =20 void qemu_init_guest_memory_pkey(void); int qemu_pkey_mprotect_guest_memory(void *addr, size_t len, int prot); +void qemu_reset_pkey_with_ibpb(void); +int qemu_pkey_kvm_run(int fd, void *arg); #endif /* CPU_COMMON_H */ diff --git a/system/physmem.c b/system/physmem.c index 9f5a0f194c..c7101f6841 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -2755,7 +2755,11 @@ static void *qemu_ram_ptr_length(RAMBlock *block, ra= m_addr_t addr, 1, lock, is_write); } =20 - return ramblock_ptr(block, addr); + void *ptr =3D ramblock_ptr(block, addr); + if (ptr) { + qemu_reset_pkey_with_ibpb(); + } + return ptr; } =20 /* diff --git a/util/pkey.c b/util/pkey.c index 0151714f32..2e42da7d9c 100644 --- a/util/pkey.c +++ b/util/pkey.c @@ -117,17 +117,62 @@ __attribute__((target("pku"))) int qemu_pkey_mprotect= _guest_memory(void *addr, return pkey_mprotect(addr, len, prot, pkey); } =20 +__attribute__((target("pku"))) void qemu_reset_pkey_with_ibpb(void) +{ + int pkey =3D guest_memory_pkey; + if (pkey =3D=3D -1) { + return; + } + if (inline_pkey_get(pkey) =3D=3D 0) { + return; + } + + /* IBPB */ + prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABL= E, 0, + 0); + + inline_pkey_set(pkey, 0); +} + +__attribute__((target("pku"))) int qemu_pkey_kvm_run(int fd, void *arg) +{ + int pkey =3D guest_memory_pkey; + if (pkey =3D=3D -1) { + return ioctl(fd, KVM_RUN, arg); + } + + assert(pkey >=3D 0 && pkey < KEY_COUNT); + + inline_pkey_set(pkey, 0); + + intptr_t ret =3D local_syscall3(__NR_ioctl, fd, KVM_RUN, (intptr_t)arg= ); + + inline_pkey_set(pkey, PKEY_DISABLE_ACCESS); + + if (ret < 0) { + errno =3D -ret; + ret =3D -1; + } + return (int)ret; +} + #else /* Dummy implementations for all other configurations (non-x86_64 Linux, */ /* Windows, macOS, etc.) */ #if defined(CONFIG_LINUX) #include #include + +int qemu_pkey_kvm_run(int fd, void *arg) +{ return ioctl(fd, KVM_RUN, arg); } #endif =20 void qemu_init_guest_memory_pkey(void) {} =20 +void qemu_reset_pkey_with_ibpb(void) +{} + int qemu_pkey_mprotect_guest_memory(void *addr, size_t len, int prot) { return 0; --=20 2.55.0.737.g08866a6d13-goog From nobody Mon Sep 28 00:09:30 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1787118923; cv=none; d=zohomail.com; s=zohoarc; b=NSglHZMcxg3ZfMT7v7wcatLy4k1Z9/jbYyRvHnCE6AD42gZ7ncx6nyZriEzD8tDneuWBIDhnmr73W7F7LASkNWDmHskjk/cr6s4A6SuNgGLjgqi65CjU2/KM25nCUV77odCMdMm6vTJRzHXjt/1qvFfcmSxApFcdXPzI2qtOwvE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787118923; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=rmFVlsgAYCtkRLriUR3Oc/OpxK2wKe12tzMJ0rDrbCg=; b=RAH886laB61BgAMwYPC4pStRR/bJDm3sVUFatEkw8B9nD4RrKSsGT0+/uf8C/syVN46bi18xEYMxaUbZ645RZt4I3nWG7EWC5u6q/dvO9bpThmYqFC8FyYDYC3m8ORkjZ4OA5gmDcp/JQAPWs+yLpY/9p68vceGRzItMTpaSFUk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787118923788305.7855427666482; Tue, 18 Aug 2026 22:55:23 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wwZFd-0001RF-AB; Wed, 19 Aug 2026 01:54:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3P8SEagcKCjYbSUcqdaYggYdW.UgeiWem-VWnWdfgfYfm.gjY@flex--jackyli.bounces.google.com>) id 1wwQg9-00060j-O6 for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:45:03 -0400 Received: from mail-pf1-x447.google.com ([2607:f8b0:4864:20::447]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3P8SEagcKCjYbSUcqdaYggYdW.UgeiWem-VWnWdfgfYfm.gjY@flex--jackyli.bounces.google.com>) id 1wwQfz-0007Lq-G8 for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:54 -0400 Received: by mail-pf1-x447.google.com with SMTP id d2e1a72fcca58-8487eb67173so498047b3a.2 for ; Tue, 18 Aug 2026 13:44:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1787085888; x=1787690688; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=rmFVlsgAYCtkRLriUR3Oc/OpxK2wKe12tzMJ0rDrbCg=; b=uHOCCmsFVh9PG58iJTR+7D67uOZxTUE1D2GyPrX6ehCLpiX7F0gimv6PcmpaCblN5G cyoMesetbQ6RQISzpq0J6mYNJe8eVYMbtIUQFqnUPzx+dmfVIX5hOyFbcZX1vWfWtyuQ n9AFfPCeBIW4/fQcNhWipdTFG3Bm0H38PE6+iXYWTnchM8GeT/SW1CcILWwvsVrDPuv9 xLeJAAO7yYMjy4m2jn1WJJISbK2xeiOSTns6+A4JY9cYOzcy0Z91+899sQgQodTv6J5Z 85mbD4EZKeaS9TiDVEldIN0c8Wf++Mr+767AzPqrQnHz0UT5lZytU2n1TELAOMKWEbqS X4bQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787085888; x=1787690688; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=rmFVlsgAYCtkRLriUR3Oc/OpxK2wKe12tzMJ0rDrbCg=; b=ClfQ5Xenp2p/LUvwPtY+wKcIiU1jjhQvU9kpddhCbhE8Y7a850h7agxwJfEwnNIOfu oe30LgjK+qX1mOk9TXKCavBwcw4bA9F1r9a2XofdOuFJzD8rIicdKBJP8idOs0dIlWUf 4HV3ec7sNw/Rsg+bUW3hptaqteP0LUwIeBFPGbQ85HtmhdB3n0u+YyW1Ifb/DvYDMJM/ 2KjTReSgNJs08+nQt6GtouhPvb0KrogsgaZVJGiopu/74EBF4fHBT9x2kyZXU5lZIesn P/kgJIcozUr8J3BJlbOFU+84ZGHNBihEhveni9QXcBtl1PD9Eejn0qOVA3Gg6vGaXpwn PUgQ== X-Gm-Message-State: AOJu0YwjauswBzqO6V1jpEcYcRS83kXN5Ypur13iq6zIYMkrE6h6IORw 0b0ZdSi3r5Yng0ZsZDPlfVreWnIHJJudEvH5wLqa/RlUQ6dI2mTcWGedQdT0x17W20Dn/Z0LCNa vZmyy659L0RDqKNJDyen/qKDCIzP1gaPFwyE/m1wXmcMAYJYta5bFnb34wmC9hIkewVVRpDZzS0 7N+UaFLmPRSh3M6P/hGhgdZyGq6khM5eLZEEzmgpg= X-Received: from pfew19-n2.prod.google.com ([2002:a05:6a00:c1d3:20b0:84f:dde6:e818]) (user=jackyli job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:c91:b0:847:9015:e68c with SMTP id d2e1a72fcca58-851cdaad991mr1536495b3a.17.1787085887607; Tue, 18 Aug 2026 13:44:47 -0700 (PDT) Date: Tue, 18 Aug 2026 20:44:19 +0000 In-Reply-To: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> Mime-Version: 1.0 References: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> X-Mailer: b4 0.14.3 Message-ID: <20260818-feature-pkey-dev-v1-5-8c0ef96a4da9@google.com> Subject: [RFC PATCH 5/6] x86: Add xstate parsing and PKRU offset detection From: Jacky Li To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Zhao Liu , Richard Henderson , "=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?=" , Peter Xu , kvm@vger.kernel.org, James Houghton , Mingwei Zhang , Dave Hansen , Brendan Jackman , Reiji Watanabe , Jacky Li Content-Type: text/plain; charset="utf-8" Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::447; envelope-from=3P8SEagcKCjYbSUcqdaYggYdW.UgeiWem-VWnWdfgfYfm.gjY@flex--jackyli.bounces.google.com; helo=mail-pf1-x447.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 19 Aug 2026 01:54:10 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1787118925208158500 Content-Transfer-Encoding: quoted-printable Add data structures and CPUID detection routines to locate the PKRU register inside the Linux x86_64 signal frame extended state (`xstate`). Signed-off-by: Jacky Li --- util/pkey.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/util/pkey.c b/util/pkey.c index 2e42da7d9c..21b41f928e 100644 --- a/util/pkey.c +++ b/util/pkey.c @@ -88,6 +88,59 @@ static inline __attribute__((always_inline)) intptr_t lo= cal_syscall3( return ret; } =20 +/* + * Custom structures to parse FPU xstate and extract the PKRU register. + * These match the Linux kernel x86_64 signal frame ABI. + */ +struct fpstate_64 { + uint16_t cwd; + uint16_t swd; + uint16_t twd; + uint16_t fop; + uint64_t rip; + uint64_t rdp; + uint32_t mxcsr; + uint32_t mxcsr_mask; + uint32_t st_space[32]; /* 8x FP registers, 16 bytes each */ + uint32_t xmm_space[64]; /* 16x XMM registers, 16 bytes each */ + uint32_t reserved1[12]; + union { + uint32_t reserved2[12]; + struct { + uint32_t magic1; + uint32_t extended_size; + uint64_t xstate_bv; + uint32_t xstate_size; + uint32_t padding[7]; + } sw_reserved; /* Extended state is encoded here */ + }; +}; + +#define FP_XSTATE_MAGIC1 0x46505853U +#define FP_XSTATE_MAGIC2 0x46505845U +#define XFEATURE_PKRU 9 +#define XSTATE_PKRU (1ULL << XFEATURE_PKRU) + +static int pkru_offset =3D -2; /* -2 means uninitialized */ + +static int __attribute__((unused)) get_pkru_offset(void) +{ + uint32_t eax, ebx, ecx, edx; + __cpuid_count(0xd, XFEATURE_PKRU, eax, ebx, ecx, edx); + if (ebx =3D=3D 0) { + return -1; + } + return (int)ebx; +} + +static int __attribute__((unused)) qemu_get_pkru_offset(void) +{ + if (pkru_offset =3D=3D -2) { + pkru_offset =3D get_pkru_offset(); + } + return pkru_offset; +} + __attribute__((target("pku"))) void qemu_init_guest_memory_pkey(void) { if (guest_memory_pkey !=3D -1) { --=20 2.55.0.737.g08866a6d13-goog From nobody Mon Sep 28 00:09:30 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1787118923; cv=none; d=zohomail.com; s=zohoarc; b=ExfjsBIIS1nv8kkSroFsy3U0sWvrgvGP9dbBUIu3Gor73e368LJAjkN4lXTWNhfUyUzrM9bHnHYJSo4hC8+ux0JaFlIvrwHKz2Cxrf42uyuFf9tBZ3qmSiD6Y6cpcePb3A6B5QMq9hQv2KuwHFMEs0p2FSpFbZbqaXbq359cBVI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787118923; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=4FKKUj8w/BG3XrvFfnyuNucawzEx5NoiVOq2alPXUU0=; b=llQG//wGjeWadjrlJtTsIInF/xqm3oNPeHtSrN4GEeCMi+u7qiCcv76oZq+R01whS0QWR7SIxegONxJfqopbQ5twZqAVajXrSi0d2Qno2FFGWbE+ohKiyCiGNsIPlgIfAF61MJeELBCdpOPuDJX1TYeHLNRTt0LYvDOsonySs8Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 178711892320249.04516560045295; Tue, 18 Aug 2026 22:55:23 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wwZFd-0001Rz-LY; Wed, 19 Aug 2026 01:54:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3QMSEagcKCjccTVdrebZhhZeX.VhfjXfn-WXoXeghgZgn.hkZ@flex--jackyli.bounces.google.com>) id 1wwQgB-00060l-3t for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:45:03 -0400 Received: from mail-pf1-x448.google.com ([2607:f8b0:4864:20::448]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3QMSEagcKCjccTVdrebZhhZeX.VhfjXfn-WXoXeghgZgn.hkZ@flex--jackyli.bounces.google.com>) id 1wwQg1-0007MK-Lu for qemu-devel@nongnu.org; Tue, 18 Aug 2026 16:44:57 -0400 Received: by mail-pf1-x448.google.com with SMTP id d2e1a72fcca58-84857446424so589028b3a.1 for ; Tue, 18 Aug 2026 13:44:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1787085889; x=1787690689; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=4FKKUj8w/BG3XrvFfnyuNucawzEx5NoiVOq2alPXUU0=; b=VpchsuTK9WAiCTb/m7jlmRCy6Jy8zZvE6Ma/hgNuiekvBLeXriDueZQ4TTvSxSPrvX i0wsdE29mpehfie5h2L5jQEI2fJBI9pDacs1dbqxLCg582/89y98wVr6ApDymKRhuiMn GXnbPcYOodX1tyKl5VdnjFgc7jsweszc9soOmzsVE/nYZ/SpPPwvOSGOQG45KmspLM+U U3riDdF4PbdwQDjBtbM14ZtTfcQKVb3Yv0TfCw7IY0/J+6644aisYirJHyb4LD2UXpvi BsF6HN0hppoKG+yTBfkCO9S/Nnq44ZPjrLbrk9C9+tz8SHPt794FhCf6raGwOjS9F03E 1cZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787085889; x=1787690689; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=4FKKUj8w/BG3XrvFfnyuNucawzEx5NoiVOq2alPXUU0=; b=fcq+WZbKQLWw+oVN3fYBxnwmxlZicJcFOEfXj8X65MHHN8tVaGOpWH8LjE9TMeYqDs cVCjaXgRsYdftZPv5oho4PtOxxvIk+/wT/ZDrertYPyCOaXaHOfgqRkIFGIq01wAE9bx f9hzDSBmm4Y6IBLOr0jw/cvczvTuNCZ07uQrwESeSXu84XLrjH0JJi4OXXLCu0KktqLA uk4GJlGpE8JLtEBRBpjm392567x8Lg15TwdsztwpTTXr8oT+VYg3/E19ll7JKQDvhv1M Ab2v+Ej3si2EK2nhTq/vERo0nUX8okRZHsdpWjbEZsSvo5pyWDra9PwaDz98J7EtTcIW j0PQ== X-Gm-Message-State: AOJu0YzePayX+R4IXznI/F9rJCyPiuiojxxonBkBEuC9m9ttVVUM17e0 lwtF+cw05hikI5ESLJn+CIfppZOyoBZxNgC4O18Oua9nz/mC/GK4WcWTCNBLRwaMB2kkc0ZdG+0 AgiD3o7eBnjBxaH6CyCM9oaWk1ZyKKaAWzeGmgriNxhf/1Bho5BHp8XoQ7h7ehbK8xVGDB43ayE HO0Rk8tV0dXEqCk55lryK74mAumXydoTdvqYB26n8= X-Received: from pfbfn22.prod.google.com ([2002:a05:6a00:2fd6:b0:84c:2e88:693d]) (user=jackyli job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:4fc9:b0:847:982e:cca0 with SMTP id d2e1a72fcca58-851cda94536mr1368944b3a.19.1787085888702; Tue, 18 Aug 2026 13:44:48 -0700 (PDT) Date: Tue, 18 Aug 2026 20:44:20 +0000 In-Reply-To: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> Mime-Version: 1.0 References: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com> X-Mailer: b4 0.14.3 Message-ID: <20260818-feature-pkey-dev-v1-6-8c0ef96a4da9@google.com> Subject: [RFC PATCH 6/6] kvm: Implement SIGSEGV sentinel for Pkey recovery From: Jacky Li To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Zhao Liu , Richard Henderson , "=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?=" , Peter Xu , kvm@vger.kernel.org, James Houghton , Mingwei Zhang , Dave Hansen , Brendan Jackman , Reiji Watanabe , Jacky Li Content-Type: text/plain; charset="utf-8" Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::448; envelope-from=3QMSEagcKCjccTVdrebZhhZeX.VhfjXfn-WXoXeghgZgn.hkZ@flex--jackyli.bounces.google.com; helo=mail-pf1-x448.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 19 Aug 2026 01:54:09 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1787118925278158500 Content-Transfer-Encoding: quoted-printable Implement a fallback `SIGSEGV` signal handler (`qemu_pkey_sigsegv_handler`) to recover from legitimate host accesses to Pkey-protected guest memory when locked. Signed-off-by: Jacky Li --- util/pkey.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 155 insertions(+), 2 deletions(-) diff --git a/util/pkey.c b/util/pkey.c index 21b41f928e..689fec8003 100644 --- a/util/pkey.c +++ b/util/pkey.c @@ -123,7 +123,7 @@ struct fpstate_64 { =20 static int pkru_offset =3D -2; /* -2 means uninitialized */ =20 -static int __attribute__((unused)) get_pkru_offset(void) +static int get_pkru_offset(void) { uint32_t eax, ebx, ecx, edx; __cpuid_count(0xd, XFEATURE_PKRU, eax, ebx, ecx, edx); @@ -133,7 +133,7 @@ static int __attribute__((unused)) get_pkru_offset(void) return (int)ebx; } =20 -static int __attribute__((unused)) qemu_get_pkru_offset(void) +static int qemu_get_pkru_offset(void) { if (pkru_offset =3D=3D -2) { pkru_offset =3D get_pkru_offset(); @@ -141,6 +141,155 @@ static int __attribute__((unused)) qemu_get_pkru_offs= et(void) return pkru_offset; } =20 +static __attribute__((target("pku"))) bool do_qemu_pkey_sigsegv_recovery( + const siginfo_t *si, ucontext_t *ucontext, int pkey) +{ + if (pkey < 0 || pkey >=3D KEY_COUNT) { + return false; + } + + if (!ucontext) { + return false; + } + + void *fpstate =3D ucontext->uc_mcontext.fpregs; + if (fpstate =3D=3D NULL) { + return false; + } + + struct fpstate_64 *fpstate_64 =3D (struct fpstate_64 *)fpstate; + + if (fpstate_64->sw_reserved.magic1 !=3D FP_XSTATE_MAGIC1) { + return false; + } + + uint32_t *magic2 =3D + (uint32_t *)((char *)fpstate + fpstate_64->sw_reserved.xstate_= size); + if (*magic2 !=3D FP_XSTATE_MAGIC2) { + return false; + } + + if ((fpstate_64->sw_reserved.xstate_bv & XSTATE_PKRU) =3D=3D 0) { + return false; + } + + int pkr_offset =3D qemu_get_pkru_offset(); + if (pkr_offset < 0 || pkr_offset >=3D fpstate_64->sw_reserved.xstate_s= ize) { + return false; + } + + uint32_t *pkru =3D (uint32_t *)((char *)fpstate + pkr_offset); + + uint32_t access_rights =3D (*pkru >> (pkey * BITS_PER_KEY)) & KEY_MASK; + if (access_rights =3D=3D 0) { + return false; + } + + /* + * Flush microarchitectural state (IBPB) before returning to avoid + * speculative execution. + */ + prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABL= E, 0, + 0); + + /* + * Clear bits in the saved PKRU so that access is unrestricted upon + * returning from the signal handler. + */ + *pkru &=3D ~(KEY_MASK << (pkey * BITS_PER_KEY)); + + return true; +} + +static void (*old_sigaction_func)(int, siginfo_t *, void *); +static void (*old_sighandler_func)(int); + +static int pkey_recovery_handler_installed; +static int pkey_for_recovery =3D -1; + +static void qemu_pkey_sigsegv_handler(int si_signo, siginfo_t *si, + void *raw_ucontext) +{ + ucontext_t *const ucontext =3D (ucontext_t *)raw_ucontext; + + if (si_signo =3D=3D SIGSEGV && si !=3D NULL && si->si_code =3D=3D SEGV= _PKUERR) { + int pkey =3D qatomic_read(&pkey_for_recovery); + if (pkey >=3D 0 && do_qemu_pkey_sigsegv_recovery(si, ucontext, pke= y)) { + return; + } + } + + void (*old_sigaction)(int, siginfo_t *, void *) =3D + qatomic_read(&old_sigaction_func); + if (old_sigaction !=3D NULL) { + old_sigaction(si_signo, si, raw_ucontext); + return; + } + + void (*old_sighandler)(int) =3D qatomic_read(&old_sighandler_func); + if (old_sighandler !=3D NULL && old_sighandler !=3D SIG_DFL && + old_sighandler !=3D SIG_IGN) +{ + old_sighandler(si_signo); + return; + } + + /* Fallback: abort */ + const char msg[] =3D "QEMU: Received unexpected Pkey SIGSEGV\n"; + int unused __attribute__((unused)) =3D + write(STDERR_FILENO, msg, sizeof(msg) - 1); + abort(); +} + +static void qemu_register_pkey_recovery_handler(void) +{ + struct sigaction old_sigact =3D {0}; + struct sigaction new_sigact =3D {0}; + + if (qatomic_xchg(&pkey_recovery_handler_installed, 1)) { + return; /* Already installed */ + } + + if (sigaction(SIGSEGV, NULL, &old_sigact) < 0) { + error_report("QEMU Pkey: Failed to get current SIGSEGV handler"); + qatomic_set(&pkey_recovery_handler_installed, 0); + return; + } + + if (old_sigact.sa_flags & SA_RESETHAND) { + error_report( + "QEMU Pkey: Incompatible SA_RESETHAND flags in old handler"); + qatomic_set(&pkey_recovery_handler_installed, 0); + return; + } + + if (old_sigact.sa_flags & SA_SIGINFO) { + qatomic_set(&old_sigaction_func, old_sigact.sa_sigaction); + } else { + qatomic_set(&old_sighandler_func, old_sigact.sa_handler); + } + + new_sigact =3D old_sigact; + new_sigact.sa_flags |=3D SA_SIGINFO; + new_sigact.sa_sigaction =3D &qemu_pkey_sigsegv_handler; + + if (sigaction(SIGSEGV, &new_sigact, &old_sigact) < 0) { + error_report("QEMU Pkey: Failed to register SIGSEGV handler"); + qatomic_set(&pkey_recovery_handler_installed, 0); + return; + } +} + +static void qemu_add_pkey_for_recovery(int pkey) +{ + int expected =3D -1; + /* We only support one recovery pkey at a time */ + if (qatomic_cmpxchg(&pkey_for_recovery, expected, pkey) !=3D expected)= { + error_report("QEMU Pkey: Recovery Pkey already set to %d", + pkey_for_recovery); + } +} + __attribute__((target("pku"))) void qemu_init_guest_memory_pkey(void) { if (guest_memory_pkey !=3D -1) { @@ -154,6 +303,10 @@ __attribute__((target("pku"))) void qemu_init_guest_me= mory_pkey(void) error_report("pkey_alloc failed for guest memory: %s", strerror(errno)); } else { + /* Register recovery signal handler and add pkey for recovery.= */ + qemu_register_pkey_recovery_handler(); + qemu_add_pkey_for_recovery(pkey); + guest_memory_pkey =3D pkey; } } --=20 2.55.0.737.g08866a6d13-goog