In confidential computing environments (CC_ATTR_GUEST_MEM_ENCRYPT),
virtio devices require VIRTIO_F_ACCESS_PLATFORM to negotiate restricted
memory access and DMA bounce buffering for virtqueue rings and
metadata buffers.

Currently, virtballoon_validate() unconditionally clears
VIRTIO_F_ACCESS_PLATFORM, causing virtio_features_ok() to reject probing
the balloon device (-ENODEV) when restricted memory access is active.

Preserve VIRTIO_F_ACCESS_PLATFORM in virtballoon_validate() when
CC_ATTR_GUEST_MEM_ENCRYPT is active, clear VIRTIO_BALLOON_F_FREE_PAGE_HINT
in CoCo since free_page_vq maps MAX_PAGE_ORDER blocks through standard DMA
ops without unaccepting them. Reject probing (-ENODEV) on CoCo
platforms where balloon page state transitions are unsupported.

Signed-off-by: Kevin Loughlin <[email protected]>
---
 drivers/virtio/virtio_balloon.c | 36 ++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 217431e75751..ae011636c07f 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -1311,6 +1311,14 @@ static int virtballoon_restore(struct virtio_device 
*vdev)
 }
 #endif
 
+static bool virtballoon_cc_supported(void)
+{
+       if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+               return has_unaccepted_memory();
+
+       return cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT);
+}
+
 static int virtballoon_validate(struct virtio_device *vdev)
 {
        /*
@@ -1318,7 +1326,17 @@ static int virtballoon_validate(struct virtio_device 
*vdev)
         * initialized. If we cannot do that then we should disable
         * page reporting as it could potentially change the contents
         * of our free pages.
+        *
+        * In encrypted guests without unaccepted memory (e.g. SEV-ES), the
+        * hypervisor cannot populate discarded pages with guest-encrypted
+        * poison/zero values and the guest does not re-initialize reported
+        * pages on return. Clear VIRTIO_BALLOON_F_PAGE_POISON so reporting
+        * is disabled when init_on_free or page_poison is active.
         */
+       if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) &&
+           !has_unaccepted_memory())
+               __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_PAGE_POISON);
+
        if (!want_init_on_free() && !page_poisoning_enabled_static())
                __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_PAGE_POISON);
        else if (!virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON))
@@ -1329,7 +1347,23 @@ static int virtballoon_validate(struct virtio_device 
*vdev)
         * virtqueue_add during page reporting.
         */
        __virtio_clear_bit(vdev, VIRTIO_RING_F_INDIRECT_DESC);
-       __virtio_clear_bit(vdev, VIRTIO_F_ACCESS_PLATFORM);
+
+       /*
+        * The balloon bypasses the DMA API for page addresses and cannot
+        * support a physical or virtual IOMMU on non-CoCo guests. In CoCo
+        * guests, VIRTIO_F_ACCESS_PLATFORM is required for bounce-buffering
+        * virtqueue rings and metadata. Disable free page hinting in CoCo
+        * guests as free_page_vq maps MAX_PAGE_ORDER blocks through standard
+        * DMA ops, and reject probing on CoCo platforms where balloon page
+        * state transitions are not supported.
+        */
+       if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
+               __virtio_clear_bit(vdev, VIRTIO_F_ACCESS_PLATFORM);
+       } else {
+               if (!virtballoon_cc_supported())
+                       return -ENODEV;
+               __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT);
+       }
        return 0;
 }
 
-- 
2.56.0.307.g5fe7bd680c-goog


Reply via email to