Thread (41 messages) flat view 41 messages, 3 authors, 29d ago

Re: [PATCH v4 17/17] KVM: arm64: Alloc simple_buffer_page using pKVM hyp allocator

From: Fuad Tabba <fuad.tabba@linux.dev>
Date: 2026-08-17 14:16:18
Also in: kvmarm

On Fri, 31 Jul 2026 at 15:36, Vincent Donnefort [off-list ref] wrote:
In protected mode, transition the allocation of the simple_ring_buffer
structures from the host to the hypervisor using the new pKVM heap
allocator.

Previously, the host allocated and donated a contiguous backing memory
for these structures. In pKVM the hypervisor can now allocate them
dynamically.

Use the pkvm_call_hyp_req() wrapper in the host to invoke
__tracing_load, which automatically handles any top-up requests if the
hypervisor runs out of heap memory during allocation.

Tested-by: Fuad Tabba <fuad.tabba@linux.dev>
Signed-off-by: Vincent Donnefort <redacted>

Reviewed-by: Fuad Tabba <fuad.tabba@linux.dev>

Cheers,
/fuad
quoted hunk ↗ jump to hunk
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 9bab1e802281..ec5bb8541ceb 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -750,7 +750,7 @@ static void handle___tracing_load(struct kvm_cpu_context *host_ctxt)
        DECLARE_REG(unsigned long, desc_hva, host_ctxt, 1);
        DECLARE_REG(size_t, desc_size, host_ctxt, 2);

-       cpu_reg(host_ctxt, 1) = __tracing_load(desc_hva, desc_size);
+       errno_to_smccc(__tracing_load(desc_hva, desc_size), host_ctxt);
 }

 static void handle___tracing_unload(struct kvm_cpu_context *host_ctxt)
diff --git a/arch/arm64/kvm/hyp/nvhe/trace.c b/arch/arm64/kvm/hyp/nvhe/trace.c
index 96afa3d6de2f..5ff19d210508 100644
--- a/arch/arm64/kvm/hyp/nvhe/trace.c
+++ b/arch/arm64/kvm/hyp/nvhe/trace.c
@@ -4,6 +4,7 @@
  * Author: Vincent Donnefort <vdonnefort@google.com>
  */

+#include <nvhe/alloc.h>
 #include <nvhe/clock.h>
 #include <nvhe/mem_protect.h>
 #include <nvhe/mm.h>
@@ -62,18 +63,34 @@ static void __release_host_mem(void *start, u64 size)
        WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(start), size >> PAGE_SHIFT));
 }

-static int hyp_trace_buffer_load_bpage_backing(struct hyp_trace_buffer *trace_buffer,
-                                              struct hyp_trace_desc *desc)
+static int hyp_trace_buffer_alloc_bpages(struct hyp_trace_buffer *trace_buffer,
+                                        struct hyp_trace_desc *desc)
 {
-       void *start = (void *)kern_hyp_va(desc->bpages_backing_start);
-       size_t size = desc->bpages_backing_size;
+       void *start;
+       size_t size;
        int ret;

-       ret = __admit_host_mem(start, size);
-       if (ret)
-               return ret;
+       if (is_protected_kvm_enabled()) {
+               struct ring_buffer_desc *rb_desc;
+               int cpu;

-       memset(start, 0, size);
+               size = 0;
+               for_each_ring_buffer_desc(rb_desc, cpu, &desc->trace_buffer_desc)
+                       size += rb_desc->nr_page_va * sizeof(struct simple_buffer_page);
+
+               start = hyp_alloc(size);
+               if (!start)
+                       return hyp_alloc_errno();
+       } else {
+               start = (void *)kern_hyp_va(desc->bpages_backing_start);
+               size = desc->bpages_backing_size;
+
+               ret = __admit_host_mem(start, size);
+               if (ret)
+                       return ret;
+
+               memset(start, 0, size);
+       }

        trace_buffer->bpages_backing_start = start;
        trace_buffer->bpages_backing_size = size;
@@ -81,7 +98,7 @@ static int hyp_trace_buffer_load_bpage_backing(struct hyp_trace_buffer *trace_bu
        return 0;
 }

-static void hyp_trace_buffer_unload_bpage_backing(struct hyp_trace_buffer *trace_buffer)
+static void hyp_trace_buffer_free_bpages(struct hyp_trace_buffer *trace_buffer)
 {
        void *start = trace_buffer->bpages_backing_start;
        size_t size = trace_buffer->bpages_backing_size;
@@ -89,9 +106,12 @@ static void hyp_trace_buffer_unload_bpage_backing(struct hyp_trace_buffer *trace
        if (!size)
                return;

-       memset(start, 0, size);
-
-       __release_host_mem(start, size);
+       if (is_protected_kvm_enabled()) {
+               hyp_free(start);
+       } else {
+               memset(start, 0, size);
+               __release_host_mem(start, size);
+       }

        trace_buffer->bpages_backing_start = 0;
        trace_buffer->bpages_backing_size = 0;
@@ -128,7 +148,7 @@ static void hyp_trace_buffer_unload(struct hyp_trace_buffer *trace_buffer)
                simple_ring_buffer_unload_mm(per_cpu_ptr(trace_buffer->simple_rbs, cpu),
                                             __unpin_shared_page);

-       hyp_trace_buffer_unload_bpage_backing(trace_buffer);
+       hyp_trace_buffer_free_bpages(trace_buffer);
 }

 static int hyp_trace_buffer_load(struct hyp_trace_buffer *trace_buffer,
@@ -143,7 +163,7 @@ static int hyp_trace_buffer_load(struct hyp_trace_buffer *trace_buffer,
        if (hyp_trace_buffer_loaded(trace_buffer))
                return -EINVAL;

-       ret = hyp_trace_buffer_load_bpage_backing(trace_buffer, desc);
+       ret = hyp_trace_buffer_alloc_bpages(trace_buffer, desc);
        if (ret)
                return ret;
@@ -168,18 +188,16 @@ static bool hyp_trace_desc_is_valid(struct hyp_trace_desc *desc, size_t desc_siz
 {
        struct ring_buffer_desc *rb_desc;
        unsigned int cpu;
-       size_t nr_bpages;
        void *desc_end;

        if (!is_protected_kvm_enabled())
                return true;

        /*
-        * Both desc_size and bpages_backing_size are untrusted host-provided
-        * values. We rely on __pkvm_host_donate_hyp() to enforce their validity.
+        * desc_size is an untrusted host-provided value. We rely on
+        * __pkvm_host_donate_hyp() to enforce its validity.
         */
        desc_end = (void *)desc + desc_size;
-       nr_bpages = desc->bpages_backing_size / sizeof(struct simple_buffer_page);

        if (desc->trace_buffer_desc.nr_cpus != hyp_nr_cpus)
                return false;
@@ -197,17 +215,8 @@ static bool hyp_trace_desc_is_valid(struct hyp_trace_desc *desc, size_t desc_siz
                if ((void *)rb_desc + struct_size(rb_desc, page_va, rb_desc->nr_page_va) > desc_end)
                        return false;

-               /* Overflow bpages backing memory? */
-               if (nr_bpages < rb_desc->nr_page_va)
-                       return false;
-
-               if (cpu >= hyp_nr_cpus)
-                       return false;
-
                if (cpu != rb_desc->cpu)
                        return false;
-
-               nr_bpages -= rb_desc->nr_page_va;
        }

        return true;
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 2411b4c32932..859a926c815f 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -13,6 +13,7 @@
 #include <asm/kvm_host.h>
 #include <asm/kvm_hyptrace.h>
 #include <asm/kvm_mmu.h>
+#include <asm/kvm_pkvm.h>

 #include "hyp_trace.h"
@@ -157,10 +158,17 @@ static void __unshare_page(unsigned long va)

 static int hyp_trace_buffer_alloc_bpages_backing(struct hyp_trace_buffer *trace_buffer, size_t size)
 {
-       int nr_bpages = (PAGE_ALIGN(size) / PAGE_SIZE) + 1;
        size_t backing_size;
+       int nr_bpages;
        void *start;

+       if (is_protected_kvm_enabled()) {
+               trace_buffer->desc->bpages_backing_start = 0;
+               trace_buffer->desc->bpages_backing_size = 0;
+               return 0;
+       }
+
+       nr_bpages = (PAGE_ALIGN(size) / PAGE_SIZE) + 1;
        backing_size = PAGE_ALIGN(sizeof(struct simple_buffer_page) * nr_bpages *
                                  num_possible_cpus());
@@ -176,6 +184,9 @@ static int hyp_trace_buffer_alloc_bpages_backing(struct hyp_trace_buffer *trace_

 static void hyp_trace_buffer_free_bpages_backing(struct hyp_trace_buffer *trace_buffer)
 {
+       if (!trace_buffer->desc->bpages_backing_start)
+               return;
+
        free_pages_exact((void *)trace_buffer->desc->bpages_backing_start,
                         trace_buffer->desc->bpages_backing_size);
 }
@@ -264,7 +275,7 @@ static struct trace_buffer_desc *hyp_trace_load(unsigned long size, void *priv)
        if (ret)
                goto err_free_buffer;

-       ret = kvm_call_hyp_nvhe(__tracing_load, (unsigned long)desc, desc_size);
+       ret = pkvm_call_hyp_req(__tracing_load, (unsigned long)desc, desc_size);
        if (ret)
                goto err_unload_pages;

--
2.55.0.508.g3f0d502094-goog
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help