ANDROID: KVM: arm64: Add __pkvm_hyp_donate_guest()
Add a new function to donate memory from hyp to guests, this will be used to move devices MMIO from the intermediate state of being owned by hyp to the guest. Bug: 357781595 Bug: 348382247 Change-Id: Ib17ca14c5880bab6e2ffcc7d78f0fd4d080a58a0 Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
@@ -71,6 +71,8 @@ int __pkvm_host_lazy_pte(u64 pfn, u64 nr_pages, bool enable);
|
||||
u64 __pkvm_ptdump_get_config(pkvm_handle_t handle, enum pkvm_ptdump_ops op);
|
||||
u64 __pkvm_ptdump_walk_range(pkvm_handle_t handle, struct pkvm_ptdump_log_hdr *log_hva);
|
||||
|
||||
int pkvm_hyp_donate_guest(struct pkvm_hyp_vcpu *vcpu, u64 pfn, u64 gfn);
|
||||
|
||||
bool addr_is_memory(phys_addr_t phys);
|
||||
int host_stage2_idmap_locked(phys_addr_t addr, u64 size,
|
||||
enum kvm_pgtable_prot prot,
|
||||
|
||||
@@ -565,6 +565,18 @@ static enum kvm_pgtable_prot default_hyp_prot(phys_addr_t phys)
|
||||
return addr_is_memory(phys) ? PAGE_HYP : PAGE_HYP_DEVICE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use NORMAL_NC for guest MMIO, when a guest has:
|
||||
* No FWB: It will combined with stage-1 attrs where device has precedence over normal.
|
||||
* FWB: With MT_S2_FWB_NORMAL_NC encoding, results in device if stage-1 used device attr.
|
||||
* otherwise NC.
|
||||
*/
|
||||
static enum kvm_pgtable_prot default_guest_prot(bool is_memory)
|
||||
{
|
||||
return is_memory ? KVM_PGTABLE_PROT_RWX :
|
||||
KVM_PGTABLE_PROT_RW | KVM_PGTABLE_PROT_NORMAL_NC;
|
||||
}
|
||||
|
||||
bool addr_is_memory(phys_addr_t phys)
|
||||
{
|
||||
struct kvm_mem_range range;
|
||||
@@ -1387,6 +1399,38 @@ int ___pkvm_host_donate_hyp(u64 pfn, u64 nr_pages, bool accept_mmio)
|
||||
default_hyp_prot(hyp_pfn_to_phys(pfn)));
|
||||
}
|
||||
|
||||
int pkvm_hyp_donate_guest(struct pkvm_hyp_vcpu *vcpu, u64 pfn, u64 gfn)
|
||||
{
|
||||
struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
|
||||
u64 phys = hyp_pfn_to_phys(pfn);
|
||||
u64 ipa = hyp_pfn_to_phys(gfn);
|
||||
u64 hyp_addr = (u64)__hyp_va(phys);
|
||||
size_t size = PAGE_SIZE;
|
||||
enum kvm_pgtable_prot prot;
|
||||
int ret;
|
||||
|
||||
hyp_lock_component();
|
||||
guest_lock_component(vm);
|
||||
|
||||
ret = __hyp_check_page_state_range(hyp_addr, size, PKVM_PAGE_OWNED);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
ret = __guest_check_page_state_range(vcpu, ipa, size, PKVM_NOPAGE);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
WARN_ON(kvm_pgtable_hyp_unmap(&pkvm_pgtable, hyp_addr, size) != size);
|
||||
prot = pkvm_mkstate(default_guest_prot(addr_is_memory(phys)), PKVM_PAGE_OWNED);
|
||||
WARN_ON(kvm_pgtable_stage2_map(&vm->pgt, ipa, size, phys, prot,
|
||||
&vcpu->vcpu.arch.stage2_mc, 0));
|
||||
|
||||
unlock:
|
||||
guest_unlock_component(vm);
|
||||
hyp_unlock_component();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __pkvm_host_donate_hyp_locked(u64 pfn, u64 nr_pages, enum kvm_pgtable_prot prot)
|
||||
{
|
||||
u64 size, phys = hyp_pfn_to_phys(pfn);
|
||||
|
||||
Reference in New Issue
Block a user