From: hshoexer Subject: Re: SEV-SNP: bus_dma(9): Rescind and claim DMA bounce buffer To: tech@openbsd.org Date: Thu, 24 Sep 2026 20:43:15 +0200 On Thu, Sep 24, 2026 at 07:33:39PM +0200, Mark Kettenis wrote: > > Date: Thu, 24 Sep 2026 18:14:41 +0200 > > From: hshoexer > > > > Hi, > > > > when creating DMA maps, rescind DMA bounce buffer pages to the > > hypervisor. When destroying DMA maps, claim these pages back from > > the hypervisor. > > > > ok? > > Sorry, too much jargon I'm not familliar with. Can you explain what > does actually does? sure: With SEV and SEV-ES: For pages to be shared with the hypervisor the guest maps them without the crypt bit (PMAP_NOCRYPT). That's what we do when setting up pages to be used as bounce buffers. However, the hypervisor can still access "private" pages, e.g. pages that are mapped encrypted by setting the crypt bit in the PTE. This corrupts the cipher text, pages are not integrity protected. SEV and SEV-ES only provide "privacy". SEV-SNP provides integrity protection. All physcal pages are managed with the so called Reverse Mapping Table (RMP). The MMU not only uses the information from the page table but also from the RMP. Pages have to be either assigned to the Hypervisor/Host OS or the guest (VM). Note: There are more possible page "owners", I'm simplifying a bit. When the hypervisor touches a guest owned page, #GP is raised. When a page is owned by the hypervisor, the guest is allowed to touch this page as long as it is mapped unencrypted. This is what we want to do for bounce buffering. When the hypervisor forcefully withdraws a page from the guest, the page is "invalidated". When the guest touches such a page, a #VC trap is raised in the guest. This allows the guest to detect this "corruption". That's the integrity protection, SEV-SNP provides. On guest launch the guest firmware -- SEV-SNP enable OVMF for qemu/KVM -- "claims" all pages assigned to the VM with these steps: 1) Remove the mapping for unencrypted access, i.e. map it encrypted 2) Request the hypervisor to set "assigned" to "guest owned", using the GHCB protocol function "page stage change" 3) "validate" the page using the pvalidate instruction. Afte that these pages are marked in the RMP to be owned by the guest, the hypervisor can not access these pages anymore without raising #GP. To share pages with the hypervisor the -- for bounce buffering -- the guest "rescinds" pages back to the hypervisor with these three steps: 1) Set "validate" in the RMP to 0 using pvalidate instruction. 2) Request the hypervisor to set "assigned" in the RMP to "hypervisor owned", using the GHCB protocol "page state change" 3) Establish a mapping with the C-bit cleared; with this mapping the page can be accessed unencrypted. So, when setting up bounce buffers on dmamap creation, the guest "rescinds" pages. When destroying the dmamap the guest "claims" the pages again. Claim and resincd is implemented in diff #1. Naming is hard. Take care, HJ. > > Take care, > > HJ. > > --- > > sys/arch/amd64/amd64/bus_dma.c | 5 +++++ > > 1 file changed, 5 insertions(+) > > > > diff --git a/sys/arch/amd64/amd64/bus_dma.c b/sys/arch/amd64/amd64/bus_dma.c > > index f4efff95a18..2e69319739c 100644 > > --- a/sys/arch/amd64/amd64/bus_dma.c > > +++ b/sys/arch/amd64/amd64/bus_dma.c > > @@ -100,6 +100,7 @@ > > #endif > > > > #include > > +#include > > > > #include > > > > @@ -255,6 +256,8 @@ _bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments, > > return (ENOMEM); > > } > > > > + snp_rescind_pages(&mlist); > > + > > sva = va; > > ssize = sz; > > pgnext = TAILQ_FIRST(&mlist); > > @@ -269,6 +272,7 @@ _bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments, > > map->_dm_npages = 0; > > km_free((void *)sva, ssize, &kv_any, &kp_none); > > free(map, M_DEVBUF, mapsize); > > + snp_claim_pages(&mlist); > > uvm_pglistfree(&mlist); > > return (ENOMEM); > > } > > @@ -307,6 +311,7 @@ _bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map) > > for (pg = map->_dm_pages; map->_dm_npages--; pg++) { > > TAILQ_INSERT_TAIL(&mlist, *pg, pageq); > > } > > + snp_claim_pages(&mlist); > > uvm_pglistfree(&mlist); > > } > > > > -- > > 2.47.3 > > > >