1/* SPDX-License-Identifier: GPL-2.0-only */
2#ifndef __KVM_HYP_MEMORY_H
3#define __KVM_HYP_MEMORY_H
4
5#include <asm/kvm_mmu.h>
6#include <asm/page.h>
7
8#include <linux/types.h>
9
10struct hyp_page {
11	unsigned short refcount;
12	unsigned short order;
13};
14
15extern u64 __hyp_vmemmap;
16#define hyp_vmemmap ((struct hyp_page *)__hyp_vmemmap)
17
18#define __hyp_va(phys)	((void *)((phys_addr_t)(phys) - hyp_physvirt_offset))
19
20static inline void *hyp_phys_to_virt(phys_addr_t phys)
21{
22	return __hyp_va(phys);
23}
24
25static inline phys_addr_t hyp_virt_to_phys(void *addr)
26{
27	return __hyp_pa(addr);
28}
29
30#define hyp_phys_to_pfn(phys)	((phys) >> PAGE_SHIFT)
31#define hyp_pfn_to_phys(pfn)	((phys_addr_t)((pfn) << PAGE_SHIFT))
32#define hyp_phys_to_page(phys)	(&hyp_vmemmap[hyp_phys_to_pfn(phys)])
33#define hyp_virt_to_page(virt)	hyp_phys_to_page(__hyp_pa(virt))
34#define hyp_virt_to_pfn(virt)	hyp_phys_to_pfn(__hyp_pa(virt))
35
36#define hyp_page_to_pfn(page)	((struct hyp_page *)(page) - hyp_vmemmap)
37#define hyp_page_to_phys(page)  hyp_pfn_to_phys((hyp_page_to_pfn(page)))
38#define hyp_page_to_virt(page)	__hyp_va(hyp_page_to_phys(page))
39#define hyp_page_to_pool(page)	(((struct hyp_page *)page)->pool)
40
41/*
42 * Refcounting for 'struct hyp_page'.
43 * hyp_pool::lock must be held if atomic access to the refcount is required.
44 */
45static inline int hyp_page_count(void *addr)
46{
47	struct hyp_page *p = hyp_virt_to_page(addr);
48
49	return p->refcount;
50}
51
52static inline void hyp_page_ref_inc(struct hyp_page *p)
53{
54	BUG_ON(p->refcount == USHRT_MAX);
55	p->refcount++;
56}
57
58static inline void hyp_page_ref_dec(struct hyp_page *p)
59{
60	BUG_ON(!p->refcount);
61	p->refcount--;
62}
63
64static inline int hyp_page_ref_dec_and_test(struct hyp_page *p)
65{
66	hyp_page_ref_dec(p);
67	return (p->refcount == 0);
68}
69
70static inline void hyp_set_page_refcounted(struct hyp_page *p)
71{
72	BUG_ON(p->refcount);
73	p->refcount = 1;
74}
75#endif /* __KVM_HYP_MEMORY_H */
76