All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jacky Li <jackyli@google.com>
To: qemu-devel@nongnu.org
Cc: "Paolo Bonzini" <pbonzini@redhat.com>,
	"Zhao Liu" <zhao1.liu@intel.com>,
	"Richard Henderson" <richard.henderson@linaro.org>,
	"Philippe Mathieu-Daudé" <philmd@mailo.com>,
	"Peter Xu" <peterx@redhat.com>,
	kvm@vger.kernel.org, "James Houghton" <jthoughton@google.com>,
	"Mingwei Zhang" <mizhang@google.com>,
	"Dave Hansen" <dave.hansen@linux.intel.com>,
	"Brendan Jackman" <jackmanb@google.com>,
	"Reiji Watanabe" <reijiw@google.com>,
	"Jacky Li" <jackyli@google.com>
Subject: [RFC PATCH 3/6] physmem: Tag guest RAMBlocks with Protection Key
Date: Tue, 18 Aug 2026 20:44:17 +0000	[thread overview]
Message-ID: <20260818-feature-pkey-dev-v1-3-8c0ef96a4da9@google.com> (raw)
In-Reply-To: <20260818-feature-pkey-dev-v1-0-8c0ef96a4da9@google.com>

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 <jackyli@google.com>
---
 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)
 }
 
 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)
 
+static inline int qemu_map_flags_to_prot(uint32_t qemu_map_flags)
+{
+  return PROT_READ | ((qemu_map_flags & QEMU_MAP_READONLY) ? 0 : PROT_WRITE);
+}
+
 #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_size)
     ram_list.num_dirty_blocks = new_num_blocks;
 }
 
+static inline int ramblock_get_prot(const RAMBlock *rb)
+{
+  uint32_t map_flags = (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 = 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 = ramblock_get_prot(new_block);
+        int ret = qemu_pkey_mprotect_guest_memory(new_block->host,
+                                                  new_block->max_length, prot);
+        if (ret != 0) {
+            error_report("qemu_pkey_mprotect failed for guest RAMBlock: %s",
+                         strerror(errno));
+        }
     }
     return;
 
@@ -2624,8 +2637,7 @@ static int qemu_ram_remap_mmap(RAMBlock *block, uint64_t start, size_t length)
     flags = MAP_FIXED | MAP_ANONYMOUS;
     flags |= block->flags & RAM_SHARED ? MAP_SHARED : MAP_PRIVATE;
     flags |= block->flags & RAM_NORESERVE ? MAP_NORESERVE : 0;
-    prot = PROT_READ;
-    prot |= block->flags & RAM_READONLY ? 0 : PROT_WRITE;
+    prot = ramblock_get_prot(block);
     area = mmap(host_startaddr, length, prot, flags, -1, 0);
     return area != 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 = qemu_map_flags & QEMU_MAP_NORESERVE;
-    const bool readonly = qemu_map_flags & QEMU_MAP_READONLY;
     const bool shared = qemu_map_flags & QEMU_MAP_SHARED;
     const bool sync = qemu_map_flags & QEMU_MAP_SYNC;
-    const int prot = PROT_READ | (readonly ? 0 : PROT_WRITE);
+    const int prot = qemu_map_flags_to_prot(qemu_map_flags);
     int map_sync_flags = 0;
     int flags = 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_memory_pkey(void)
     }
 }
 
+__attribute__((target("pku"))) int qemu_pkey_mprotect_guest_memory(void *addr,
+                                                                   size_t len,
+                                                                   int prot)
+{
+    int pkey = guest_memory_pkey;
+    if (pkey == -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_memory_pkey(void)
 
 void qemu_init_guest_memory_pkey(void)
 {}
+
+int qemu_pkey_mprotect_guest_memory(void *addr, size_t len, int prot)
+{
+    return 0;
+}
 #endif

-- 
2.55.0.737.g08866a6d13-goog


  parent reply	other threads:[~2026-08-18 20:44 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-18 20:44 [RFC PATCH 0/6] Protect VMM from speculative attacks using x86 PKRU Jacky Li
2026-08-18 20:44 ` [RFC PATCH 1/6] x86: Introduce basic PKRU hardware wrappers Jacky Li
2026-08-18 20:44 ` [RFC PATCH 2/6] kvm: Add guest memory Pkey initialization Jacky Li
2026-08-18 22:03   ` Dave Hansen
2026-08-18 20:44 ` Jacky Li [this message]
2026-08-18 20:44 ` [RFC PATCH 4/6] kvm: Lock guest RAMBlocks via PKRU during host userspace execution Jacky Li
2026-08-18 20:44 ` [RFC PATCH 5/6] x86: Add xstate parsing and PKRU offset detection Jacky Li
2026-08-18 20:44 ` [RFC PATCH 6/6] kvm: Implement SIGSEGV sentinel for Pkey recovery Jacky Li
2026-08-18 21:55   ` Dave Hansen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260818-feature-pkey-dev-v1-3-8c0ef96a4da9@google.com \
    --to=jackyli@google.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=jackmanb@google.com \
    --cc=jthoughton@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=mizhang@google.com \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    --cc=philmd@mailo.com \
    --cc=qemu-devel@nongnu.org \
    --cc=reijiw@google.com \
    --cc=richard.henderson@linaro.org \
    --cc=zhao1.liu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.