1e7596040SQuentin Perret /* SPDX-License-Identifier: GPL-2.0-only */
2e7596040SQuentin Perret #ifndef __KVM_HYP_MEMORY_H
3e7596040SQuentin Perret #define __KVM_HYP_MEMORY_H
4e7596040SQuentin Perret 
55c92a764SMarc Zyngier #include <asm/kvm_mmu.h>
6e7596040SQuentin Perret #include <asm/page.h>
7e7596040SQuentin Perret 
8e7596040SQuentin Perret #include <linux/types.h>
9e7596040SQuentin Perret 
108e17c662SQuentin Perret struct hyp_page {
116929586dSQuentin Perret 	unsigned short refcount;
1287ec0606SQuentin Perret 	unsigned short order;
138e17c662SQuentin Perret };
148e17c662SQuentin Perret 
158e17c662SQuentin Perret extern u64 __hyp_vmemmap;
168e17c662SQuentin Perret #define hyp_vmemmap ((struct hyp_page *)__hyp_vmemmap)
17e7596040SQuentin Perret 
18e7596040SQuentin Perret #define __hyp_va(phys)	((void *)((phys_addr_t)(phys) - hyp_physvirt_offset))
19e7596040SQuentin Perret 
hyp_phys_to_virt(phys_addr_t phys)20e7596040SQuentin Perret static inline void *hyp_phys_to_virt(phys_addr_t phys)
21e7596040SQuentin Perret {
22e7596040SQuentin Perret 	return __hyp_va(phys);
23e7596040SQuentin Perret }
24e7596040SQuentin Perret 
hyp_virt_to_phys(void * addr)25e7596040SQuentin Perret static inline phys_addr_t hyp_virt_to_phys(void *addr)
26e7596040SQuentin Perret {
27e7596040SQuentin Perret 	return __hyp_pa(addr);
28e7596040SQuentin Perret }
29e7596040SQuentin Perret 
308e17c662SQuentin Perret #define hyp_phys_to_pfn(phys)	((phys) >> PAGE_SHIFT)
318e17c662SQuentin Perret #define hyp_pfn_to_phys(pfn)	((phys_addr_t)((pfn) << PAGE_SHIFT))
328e17c662SQuentin Perret #define hyp_phys_to_page(phys)	(&hyp_vmemmap[hyp_phys_to_pfn(phys)])
338e17c662SQuentin Perret #define hyp_virt_to_page(virt)	hyp_phys_to_page(__hyp_pa(virt))
348e17c662SQuentin Perret #define hyp_virt_to_pfn(virt)	hyp_phys_to_pfn(__hyp_pa(virt))
358e17c662SQuentin Perret 
368e17c662SQuentin Perret #define hyp_page_to_pfn(page)	((struct hyp_page *)(page) - hyp_vmemmap)
378e17c662SQuentin Perret #define hyp_page_to_phys(page)  hyp_pfn_to_phys((hyp_page_to_pfn(page)))
388e17c662SQuentin Perret #define hyp_page_to_virt(page)	__hyp_va(hyp_page_to_phys(page))
398e17c662SQuentin Perret #define hyp_page_to_pool(page)	(((struct hyp_page *)page)->pool)
408e17c662SQuentin Perret 
410f4f7ae1SQuentin Perret /*
420f4f7ae1SQuentin Perret  * Refcounting for 'struct hyp_page'.
430f4f7ae1SQuentin Perret  * hyp_pool::lock must be held if atomic access to the refcount is required.
440f4f7ae1SQuentin Perret  */
hyp_page_count(void * addr)458e17c662SQuentin Perret static inline int hyp_page_count(void *addr)
468e17c662SQuentin Perret {
478e17c662SQuentin Perret 	struct hyp_page *p = hyp_virt_to_page(addr);
488e17c662SQuentin Perret 
498e17c662SQuentin Perret 	return p->refcount;
508e17c662SQuentin Perret }
518e17c662SQuentin Perret 
hyp_page_ref_inc(struct hyp_page * p)520f4f7ae1SQuentin Perret static inline void hyp_page_ref_inc(struct hyp_page *p)
530f4f7ae1SQuentin Perret {
540f4f7ae1SQuentin Perret 	BUG_ON(p->refcount == USHRT_MAX);
550f4f7ae1SQuentin Perret 	p->refcount++;
560f4f7ae1SQuentin Perret }
570f4f7ae1SQuentin Perret 
hyp_page_ref_dec(struct hyp_page * p)58*9926cfceSQuentin Perret static inline void hyp_page_ref_dec(struct hyp_page *p)
590f4f7ae1SQuentin Perret {
600f4f7ae1SQuentin Perret 	BUG_ON(!p->refcount);
610f4f7ae1SQuentin Perret 	p->refcount--;
62*9926cfceSQuentin Perret }
63*9926cfceSQuentin Perret 
hyp_page_ref_dec_and_test(struct hyp_page * p)64*9926cfceSQuentin Perret static inline int hyp_page_ref_dec_and_test(struct hyp_page *p)
65*9926cfceSQuentin Perret {
66*9926cfceSQuentin Perret 	hyp_page_ref_dec(p);
670f4f7ae1SQuentin Perret 	return (p->refcount == 0);
680f4f7ae1SQuentin Perret }
690f4f7ae1SQuentin Perret 
hyp_set_page_refcounted(struct hyp_page * p)700f4f7ae1SQuentin Perret static inline void hyp_set_page_refcounted(struct hyp_page *p)
710f4f7ae1SQuentin Perret {
720f4f7ae1SQuentin Perret 	BUG_ON(p->refcount);
730f4f7ae1SQuentin Perret 	p->refcount = 1;
740f4f7ae1SQuentin Perret }
75e7596040SQuentin Perret #endif /* __KVM_HYP_MEMORY_H */
76