]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Drivers: hv: Allocate encrypted buffers when requested
authorRoman Kisel <romank@linux.microsoft.com>
Wed, 8 Oct 2025 23:34:15 +0000 (16:34 -0700)
committerWei Liu <wei.liu@kernel.org>
Sat, 15 Nov 2025 06:18:15 +0000 (06:18 +0000)
Confidential VMBus is built around using buffers not shared with
the host.

Support allocating encrypted buffers when requested.

Signed-off-by: Roman Kisel <romank@linux.microsoft.com>
Reviewed-by: Tianyu Lan <tiala@microsoft.com>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
drivers/hv/channel.c
drivers/hv/hyperv_vmbus.h
drivers/hv/ring_buffer.c

index 162d6aeece7b3b6e4c321b07008efac49c253af4..d69713201beffd9e62c6c7ab0b116763daf1c835 100644 (file)
@@ -444,20 +444,23 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
                return ret;
        }
 
-       /*
-        * Set the "decrypted" flag to true for the set_memory_decrypted()
-        * success case. In the failure case, the encryption state of the
-        * memory is unknown. Leave "decrypted" as true to ensure the
-        * memory will be leaked instead of going back on the free list.
-        */
-       gpadl->decrypted = true;
-       ret = set_memory_decrypted((unsigned long)kbuffer,
-                                  PFN_UP(size));
-       if (ret) {
-               dev_warn(&channel->device_obj->device,
-                        "Failed to set host visibility for new GPADL %d.\n",
-                        ret);
-               return ret;
+       gpadl->decrypted = !((channel->co_external_memory && type == HV_GPADL_BUFFER) ||
+               (channel->co_ring_buffer && type == HV_GPADL_RING));
+       if (gpadl->decrypted) {
+               /*
+                * The "decrypted" flag being true assumes that set_memory_decrypted() succeeds.
+                * But if it fails, the encryption state of the memory is unknown. In that case,
+                * leave "decrypted" as true to ensure the memory is leaked instead of going back
+                * on the free list.
+                */
+               ret = set_memory_decrypted((unsigned long)kbuffer,
+                                       PFN_UP(size));
+               if (ret) {
+                       dev_warn(&channel->device_obj->device,
+                               "Failed to set host visibility for new GPADL %d.\n",
+                               ret);
+                       return ret;
+               }
        }
 
        init_completion(&msginfo->waitevent);
@@ -545,8 +548,10 @@ cleanup:
                 * left as true so the memory is leaked instead of being
                 * put back on the free list.
                 */
-               if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size)))
-                       gpadl->decrypted = false;
+               if (gpadl->decrypted) {
+                       if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size)))
+                               gpadl->decrypted = false;
+               }
        }
 
        return ret;
@@ -677,12 +682,13 @@ static int __vmbus_open(struct vmbus_channel *newchannel,
                goto error_clean_ring;
 
        err = hv_ringbuffer_init(&newchannel->outbound,
-                                page, send_pages, 0);
+                                page, send_pages, 0, newchannel->co_ring_buffer);
        if (err)
                goto error_free_gpadl;
 
        err = hv_ringbuffer_init(&newchannel->inbound, &page[send_pages],
-                                recv_pages, newchannel->max_pkt_size);
+                                recv_pages, newchannel->max_pkt_size,
+                                newchannel->co_ring_buffer);
        if (err)
                goto error_free_gpadl;
 
@@ -863,8 +869,11 @@ post_msg_err:
 
        kfree(info);
 
-       ret = set_memory_encrypted((unsigned long)gpadl->buffer,
-                                  PFN_UP(gpadl->size));
+       if (gpadl->decrypted)
+               ret = set_memory_encrypted((unsigned long)gpadl->buffer,
+                                       PFN_UP(gpadl->size));
+       else
+               ret = 0;
        if (ret)
                pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);
 
index 552ed782bcfc8aeddd296996504036c70d3afdd3..f7fc2630c054d05ba04134077b54517b6293c271 100644 (file)
@@ -201,7 +201,8 @@ extern int hv_synic_cleanup(unsigned int cpu);
 void hv_ringbuffer_pre_init(struct vmbus_channel *channel);
 
 int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
-                      struct page *pages, u32 pagecnt, u32 max_pkt_size);
+                      struct page *pages, u32 pagecnt, u32 max_pkt_size,
+                          bool confidential);
 
 void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
 
index 23ce1fb70de143b249b3ce956adf2c27e3116d10..3c421a7f78c004a1e728a63a5b0e818f2acfbac2 100644 (file)
@@ -184,7 +184,8 @@ void hv_ringbuffer_pre_init(struct vmbus_channel *channel)
 
 /* Initialize the ring buffer. */
 int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
-                      struct page *pages, u32 page_cnt, u32 max_pkt_size)
+                      struct page *pages, u32 page_cnt, u32 max_pkt_size,
+                          bool confidential)
 {
        struct page **pages_wraparound;
        int i;
@@ -208,7 +209,7 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
 
        ring_info->ring_buffer = (struct hv_ring_buffer *)
                vmap(pages_wraparound, page_cnt * 2 - 1, VM_MAP,
-                       pgprot_decrypted(PAGE_KERNEL));
+                       confidential ? PAGE_KERNEL : pgprot_decrypted(PAGE_KERNEL));
 
        kfree(pages_wraparound);
        if (!ring_info->ring_buffer)