xref: /OK3568_Linux_fs/kernel/arch/arm64/kvm/hyp/nvhe/mem_protect.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2020 Google LLC
4*4882a593Smuzhiyun  * Author: Quentin Perret <qperret@google.com>
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/kvm_host.h>
8*4882a593Smuzhiyun #include <asm/kvm_emulate.h>
9*4882a593Smuzhiyun #include <asm/kvm_hyp.h>
10*4882a593Smuzhiyun #include <asm/kvm_mmu.h>
11*4882a593Smuzhiyun #include <asm/kvm_pgtable.h>
12*4882a593Smuzhiyun #include <asm/stage2_pgtable.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <hyp/switch.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <nvhe/gfp.h>
17*4882a593Smuzhiyun #include <nvhe/memory.h>
18*4882a593Smuzhiyun #include <nvhe/mem_protect.h>
19*4882a593Smuzhiyun #include <nvhe/mm.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define KVM_HOST_S2_FLAGS (KVM_PGTABLE_S2_NOFWB | KVM_PGTABLE_S2_IDMAP)
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun extern unsigned long hyp_nr_cpus;
24*4882a593Smuzhiyun struct host_kvm host_kvm;
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun static struct hyp_pool host_s2_mem;
27*4882a593Smuzhiyun static struct hyp_pool host_s2_dev;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun  * Copies of the host's CPU features registers holding sanitized values.
31*4882a593Smuzhiyun  */
32*4882a593Smuzhiyun u64 id_aa64mmfr0_el1_sys_val;
33*4882a593Smuzhiyun u64 id_aa64mmfr1_el1_sys_val;
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun static const u8 pkvm_hyp_id = 1;
36*4882a593Smuzhiyun 
host_s2_zalloc_pages_exact(size_t size)37*4882a593Smuzhiyun static void *host_s2_zalloc_pages_exact(size_t size)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	void *addr = hyp_alloc_pages(&host_s2_mem, get_order(size));
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	hyp_split_page(hyp_virt_to_page(addr));
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	/*
44*4882a593Smuzhiyun 	 * The size of concatenated PGDs is always a power of two of PAGE_SIZE,
45*4882a593Smuzhiyun 	 * so there should be no need to free any of the tail pages to make the
46*4882a593Smuzhiyun 	 * allocation exact.
47*4882a593Smuzhiyun 	 */
48*4882a593Smuzhiyun 	WARN_ON(size != (PAGE_SIZE << get_order(size)));
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	return addr;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
host_s2_zalloc_page(void * pool)53*4882a593Smuzhiyun static void *host_s2_zalloc_page(void *pool)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	return hyp_alloc_pages(pool, 0);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
prepare_s2_pools(void * mem_pgt_pool,void * dev_pgt_pool)58*4882a593Smuzhiyun static int prepare_s2_pools(void *mem_pgt_pool, void *dev_pgt_pool)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	unsigned long nr_pages, pfn;
61*4882a593Smuzhiyun 	int ret;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	pfn = hyp_virt_to_pfn(mem_pgt_pool);
64*4882a593Smuzhiyun 	nr_pages = host_s2_mem_pgtable_pages();
65*4882a593Smuzhiyun 	ret = hyp_pool_init(&host_s2_mem, pfn, nr_pages, 0);
66*4882a593Smuzhiyun 	if (ret)
67*4882a593Smuzhiyun 		return ret;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	pfn = hyp_virt_to_pfn(dev_pgt_pool);
70*4882a593Smuzhiyun 	nr_pages = host_s2_dev_pgtable_pages();
71*4882a593Smuzhiyun 	ret = hyp_pool_init(&host_s2_dev, pfn, nr_pages, 0);
72*4882a593Smuzhiyun 	if (ret)
73*4882a593Smuzhiyun 		return ret;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	host_kvm.mm_ops = (struct kvm_pgtable_mm_ops) {
76*4882a593Smuzhiyun 		.zalloc_pages_exact = host_s2_zalloc_pages_exact,
77*4882a593Smuzhiyun 		.zalloc_page = host_s2_zalloc_page,
78*4882a593Smuzhiyun 		.phys_to_virt = hyp_phys_to_virt,
79*4882a593Smuzhiyun 		.virt_to_phys = hyp_virt_to_phys,
80*4882a593Smuzhiyun 		.page_count = hyp_page_count,
81*4882a593Smuzhiyun 		.get_page = hyp_get_page,
82*4882a593Smuzhiyun 		.put_page = hyp_put_page,
83*4882a593Smuzhiyun 	};
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	return 0;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
prepare_host_vtcr(void)88*4882a593Smuzhiyun static void prepare_host_vtcr(void)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	u32 parange, phys_shift;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	/* The host stage 2 is id-mapped, so use parange for T0SZ */
93*4882a593Smuzhiyun 	parange = kvm_get_parange(id_aa64mmfr0_el1_sys_val);
94*4882a593Smuzhiyun 	phys_shift = id_aa64mmfr0_parange_to_phys_shift(parange);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	host_kvm.arch.vtcr = kvm_get_vtcr(id_aa64mmfr0_el1_sys_val,
97*4882a593Smuzhiyun 					  id_aa64mmfr1_el1_sys_val, phys_shift);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun 
kvm_host_prepare_stage2(void * mem_pgt_pool,void * dev_pgt_pool)100*4882a593Smuzhiyun int kvm_host_prepare_stage2(void *mem_pgt_pool, void *dev_pgt_pool)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	struct kvm_s2_mmu *mmu = &host_kvm.arch.mmu;
103*4882a593Smuzhiyun 	int ret;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	prepare_host_vtcr();
106*4882a593Smuzhiyun 	hyp_spin_lock_init(&host_kvm.lock);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	ret = prepare_s2_pools(mem_pgt_pool, dev_pgt_pool);
109*4882a593Smuzhiyun 	if (ret)
110*4882a593Smuzhiyun 		return ret;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	ret = kvm_pgtable_stage2_init_flags(&host_kvm.pgt, &host_kvm.arch,
113*4882a593Smuzhiyun 					    &host_kvm.mm_ops, KVM_HOST_S2_FLAGS);
114*4882a593Smuzhiyun 	if (ret)
115*4882a593Smuzhiyun 		return ret;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	mmu->pgd_phys = __hyp_pa(host_kvm.pgt.pgd);
118*4882a593Smuzhiyun 	mmu->arch = &host_kvm.arch;
119*4882a593Smuzhiyun 	mmu->pgt = &host_kvm.pgt;
120*4882a593Smuzhiyun 	mmu->vmid.vmid_gen = 0;
121*4882a593Smuzhiyun 	mmu->vmid.vmid = 0;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	return 0;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
__pkvm_prot_finalize(void)126*4882a593Smuzhiyun int __pkvm_prot_finalize(void)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	struct kvm_s2_mmu *mmu = &host_kvm.arch.mmu;
129*4882a593Smuzhiyun 	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	params->vttbr = kvm_get_vttbr(mmu);
132*4882a593Smuzhiyun 	params->vtcr = host_kvm.arch.vtcr;
133*4882a593Smuzhiyun 	params->hcr_el2 |= HCR_VM;
134*4882a593Smuzhiyun 	kvm_flush_dcache_to_poc(params, sizeof(*params));
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	write_sysreg(params->hcr_el2, hcr_el2);
137*4882a593Smuzhiyun 	__load_stage2(&host_kvm.arch.mmu, host_kvm.arch.vtcr);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	/*
140*4882a593Smuzhiyun 	 * Make sure to have an ISB before the TLB maintenance below but only
141*4882a593Smuzhiyun 	 * when __load_stage2() doesn't include one already.
142*4882a593Smuzhiyun 	 */
143*4882a593Smuzhiyun 	asm(ALTERNATIVE("isb", "nop", ARM64_WORKAROUND_SPECULATIVE_AT));
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	/* Invalidate stale HCR bits that may be cached in TLBs */
146*4882a593Smuzhiyun 	__tlbi(vmalls12e1);
147*4882a593Smuzhiyun 	dsb(nsh);
148*4882a593Smuzhiyun 	isb();
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	return 0;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
host_stage2_unmap_dev_all(void)153*4882a593Smuzhiyun static int host_stage2_unmap_dev_all(void)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	struct kvm_pgtable *pgt = &host_kvm.pgt;
156*4882a593Smuzhiyun 	struct memblock_region *reg;
157*4882a593Smuzhiyun 	u64 addr = 0;
158*4882a593Smuzhiyun 	int i, ret;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	/* Unmap all non-memory regions to recycle the pages */
161*4882a593Smuzhiyun 	for (i = 0; i < hyp_memblock_nr; i++, addr = reg->base + reg->size) {
162*4882a593Smuzhiyun 		reg = &hyp_memory[i];
163*4882a593Smuzhiyun 		ret = kvm_pgtable_stage2_unmap(pgt, addr, reg->base - addr);
164*4882a593Smuzhiyun 		if (ret)
165*4882a593Smuzhiyun 			return ret;
166*4882a593Smuzhiyun 	}
167*4882a593Smuzhiyun 	return kvm_pgtable_stage2_unmap(pgt, addr, BIT(pgt->ia_bits) - addr);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
find_mem_range(phys_addr_t addr,struct kvm_mem_range * range)170*4882a593Smuzhiyun static bool find_mem_range(phys_addr_t addr, struct kvm_mem_range *range)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	int cur, left = 0, right = hyp_memblock_nr;
173*4882a593Smuzhiyun 	struct memblock_region *reg;
174*4882a593Smuzhiyun 	phys_addr_t end;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	range->start = 0;
177*4882a593Smuzhiyun 	range->end = ULONG_MAX;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	/* The list of memblock regions is sorted, binary search it */
180*4882a593Smuzhiyun 	while (left < right) {
181*4882a593Smuzhiyun 		cur = (left + right) >> 1;
182*4882a593Smuzhiyun 		reg = &hyp_memory[cur];
183*4882a593Smuzhiyun 		end = reg->base + reg->size;
184*4882a593Smuzhiyun 		if (addr < reg->base) {
185*4882a593Smuzhiyun 			right = cur;
186*4882a593Smuzhiyun 			range->end = reg->base;
187*4882a593Smuzhiyun 		} else if (addr >= end) {
188*4882a593Smuzhiyun 			left = cur + 1;
189*4882a593Smuzhiyun 			range->start = end;
190*4882a593Smuzhiyun 		} else {
191*4882a593Smuzhiyun 			range->start = reg->base;
192*4882a593Smuzhiyun 			range->end = end;
193*4882a593Smuzhiyun 			return true;
194*4882a593Smuzhiyun 		}
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	return false;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
range_is_memory(u64 start,u64 end)200*4882a593Smuzhiyun static bool range_is_memory(u64 start, u64 end)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	struct kvm_mem_range r1, r2;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	if (!find_mem_range(start, &r1) || !find_mem_range(end - 1, &r2))
205*4882a593Smuzhiyun 		return false;
206*4882a593Smuzhiyun 	if (r1.start != r2.start)
207*4882a593Smuzhiyun 		return false;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	return true;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
__host_stage2_idmap(u64 start,u64 end,enum kvm_pgtable_prot prot,struct hyp_pool * pool)212*4882a593Smuzhiyun static inline int __host_stage2_idmap(u64 start, u64 end,
213*4882a593Smuzhiyun 				      enum kvm_pgtable_prot prot,
214*4882a593Smuzhiyun 				      struct hyp_pool *pool)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	return kvm_pgtable_stage2_map(&host_kvm.pgt, start, end - start, start,
217*4882a593Smuzhiyun 				      prot, pool);
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun 
host_stage2_idmap(u64 addr)220*4882a593Smuzhiyun static int host_stage2_idmap(u64 addr)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W;
223*4882a593Smuzhiyun 	struct kvm_mem_range range;
224*4882a593Smuzhiyun 	bool is_memory = find_mem_range(addr, &range);
225*4882a593Smuzhiyun 	struct hyp_pool *pool = is_memory ? &host_s2_mem : &host_s2_dev;
226*4882a593Smuzhiyun 	int ret;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	if (is_memory)
229*4882a593Smuzhiyun 		prot |= KVM_PGTABLE_PROT_X;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	hyp_spin_lock(&host_kvm.lock);
232*4882a593Smuzhiyun 	ret = kvm_pgtable_stage2_find_range(&host_kvm.pgt, addr, prot, &range);
233*4882a593Smuzhiyun 	if (ret)
234*4882a593Smuzhiyun 		goto unlock;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	ret = __host_stage2_idmap(range.start, range.end, prot, pool);
237*4882a593Smuzhiyun 	if (is_memory || ret != -ENOMEM)
238*4882a593Smuzhiyun 		goto unlock;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	/*
241*4882a593Smuzhiyun 	 * host_s2_mem has been provided with enough pages to cover all of
242*4882a593Smuzhiyun 	 * memory with page granularity, so we should never hit the ENOMEM case.
243*4882a593Smuzhiyun 	 * However, it is difficult to know how much of the MMIO range we will
244*4882a593Smuzhiyun 	 * need to cover upfront, so we may need to 'recycle' the pages if we
245*4882a593Smuzhiyun 	 * run out.
246*4882a593Smuzhiyun 	 */
247*4882a593Smuzhiyun 	ret = host_stage2_unmap_dev_all();
248*4882a593Smuzhiyun 	if (ret)
249*4882a593Smuzhiyun 		goto unlock;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	ret = __host_stage2_idmap(range.start, range.end, prot, pool);
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun unlock:
254*4882a593Smuzhiyun 	hyp_spin_unlock(&host_kvm.lock);
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	return ret;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
__pkvm_mark_hyp(phys_addr_t start,phys_addr_t end)259*4882a593Smuzhiyun int __pkvm_mark_hyp(phys_addr_t start, phys_addr_t end)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	int ret;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	/*
264*4882a593Smuzhiyun 	 * host_stage2_unmap_dev_all() currently relies on MMIO mappings being
265*4882a593Smuzhiyun 	 * non-persistent, so don't allow changing page ownership in MMIO range.
266*4882a593Smuzhiyun 	 */
267*4882a593Smuzhiyun 	if (!range_is_memory(start, end))
268*4882a593Smuzhiyun 		return -EINVAL;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	hyp_spin_lock(&host_kvm.lock);
271*4882a593Smuzhiyun 	ret = kvm_pgtable_stage2_set_owner(&host_kvm.pgt, start, end - start,
272*4882a593Smuzhiyun 					   &host_s2_mem, pkvm_hyp_id);
273*4882a593Smuzhiyun 	hyp_spin_unlock(&host_kvm.lock);
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	return ret != -EAGAIN ? ret : 0;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun 
handle_host_mem_abort(struct kvm_cpu_context * host_ctxt)278*4882a593Smuzhiyun void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	struct kvm_vcpu_fault_info fault;
281*4882a593Smuzhiyun 	u64 esr, addr;
282*4882a593Smuzhiyun 	int ret = 0;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	esr = read_sysreg_el2(SYS_ESR);
285*4882a593Smuzhiyun 	if (!__get_fault_info(esr, &fault))
286*4882a593Smuzhiyun 		hyp_panic();
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	addr = (fault.hpfar_el2 & HPFAR_MASK) << 8;
289*4882a593Smuzhiyun 	ret = host_stage2_idmap(addr);
290*4882a593Smuzhiyun 	if (ret && ret != -EAGAIN)
291*4882a593Smuzhiyun 		hyp_panic();
292*4882a593Smuzhiyun }
293