diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 44a326fddc5bd5d0fd261b68faa26dd5484a646e..a19683f1e953dffa829bf96602708de7051baa63 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -2142,6 +2142,7 @@ enum csv3_cmd_id { KVM_CSV3_SEND_ENCRYPT_CONTEXT, KVM_CSV3_RECEIVE_ENCRYPT_DATA, KVM_CSV3_RECEIVE_ENCRYPT_CONTEXT, + KVM_CSV3_HANDLE_MEMORY, KVM_CSV3_SET_GUEST_PRIVATE_MEMORY = 0xc8, @@ -2190,6 +2191,14 @@ struct kvm_csv3_receive_encrypt_context { __u32 trans_len; }; +#define KVM_CSV3_RELEASE_SHARED_MEMORY (0x0001) + +struct kvm_csv3_handle_memory { + __u64 gpa; + __u32 num_pages; + __u32 opcode; +}; + #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) #define KVM_DEV_ASSIGN_MASK_INTX (1 << 2) diff --git a/target/i386/csv-sysemu-stub.c b/target/i386/csv-sysemu-stub.c index e49755da5c45d4dcb4d045cfde439ade7f466dc5..735cce0e4b78c5e13818a8c508c1d5f4304432b5 100644 --- a/target/i386/csv-sysemu-stub.c +++ b/target/i386/csv-sysemu-stub.c @@ -40,6 +40,11 @@ void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end) } +void csv3_shared_region_release(uint64_t gpa, uint32_t num_pages) +{ + +} + int csv3_set_guest_private_memory(Error **errp) { g_assert_not_reached(); diff --git a/target/i386/csv.c b/target/i386/csv.c index d9b50040a36db3fdd6e474384f21c4a6fe4e14f2..b229f7c317789abb5f72ea5f7a959ed259c915a7 100644 --- a/target/i386/csv.c +++ b/target/i386/csv.c @@ -270,6 +270,40 @@ end: return ret; } +void csv3_shared_region_release(uint64_t gpa, uint32_t num_pages) +{ + struct kvm_csv3_handle_memory mem = { 0 }; + MemoryRegion *mr = NULL; + void *hva; + int ret; + + if (!csv3_enabled()) + return; + + if (!gpa || !num_pages) + return; + + mem.gpa = (__u64)gpa; + mem.num_pages = (__u32)num_pages; + mem.opcode = (__u32)KVM_CSV3_RELEASE_SHARED_MEMORY; + + /* unpin the pages */ + ret = csv3_ioctl(KVM_CSV3_HANDLE_MEMORY, &mem, NULL); + if (ret <= 0) { + if (ret < 0) + error_report("%s: CSV3 unpin failed ret %d", __func__, ret); + return; + } + + /* drop the pages */ + hva = gpa2hva(&mr, gpa, num_pages << TARGET_PAGE_BITS, NULL); + if (hva) { + ret = madvise(hva, num_pages << TARGET_PAGE_BITS, MADV_DONTNEED); + if (ret) + error_report("%s: madvise failed %d", __func__, ret); + } +} + void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end) { MemoryRegionSection section; diff --git a/target/i386/csv.h b/target/i386/csv.h index fb669279a873c33e71343f067ba55d414cca1f66..70f9933d3b29d83b5e88bf4b17b26e8df4ca0986 100644 --- a/target/i386/csv.h +++ b/target/i386/csv.h @@ -124,6 +124,7 @@ int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp); int csv3_shared_region_dma_map(uint64_t start, uint64_t end); void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end); +void csv3_shared_region_release(uint64_t gpa, uint32_t num_pages); int csv3_load_incoming_page(QEMUFile *f, uint8_t *ptr); int csv3_load_incoming_context(QEMUFile *f); int csv3_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr); diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index a867512822ab2ad1b0056758fd48012b61b6c819..2df3ff99c3423f1c0ecd88ebbd30c0c546679779 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -5099,6 +5099,7 @@ static int kvm_handle_exit_hypercall(X86CPU *cpu, struct kvm_run *run) if (enc) { sev_remove_shared_regions_list(gfn_start, gfn_end); csv3_shared_region_dma_unmap(gpa, gfn_end << TARGET_PAGE_BITS); + csv3_shared_region_release(gpa, npages); } else { sev_add_shared_regions_list(gfn_start, gfn_end); csv3_shared_region_dma_map(gpa, gfn_end << TARGET_PAGE_BITS);