xref: /freebsd/sys/arm64/vmm/vmm_nvhe.c (revision 7861ecd18b6f15cfe37fc6f51f6ba89b92398648)
13d61bcf1SAndrew Turner /*-
23d61bcf1SAndrew Turner  * SPDX-License-Identifier: BSD-2-Clause
33d61bcf1SAndrew Turner  *
44b6c9f84SAndrew Turner  * Copyright (c) 2021 Andrew Turner
53d61bcf1SAndrew Turner  * Copyright (c) 2024 Arm Ltd
63d61bcf1SAndrew Turner  *
74b6c9f84SAndrew Turner  * This work was supported by Innovate UK project 105694, "Digital Security
84b6c9f84SAndrew Turner  * by Design (DSbD) Technology Platform Prototype".
94b6c9f84SAndrew Turner  *
103d61bcf1SAndrew Turner  * Redistribution and use in source and binary forms, with or without
113d61bcf1SAndrew Turner  * modification, are permitted provided that the following conditions
123d61bcf1SAndrew Turner  * are met:
133d61bcf1SAndrew Turner  * 1. Redistributions of source code must retain the above copyright
143d61bcf1SAndrew Turner  *    notice, this list of conditions and the following disclaimer.
153d61bcf1SAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright
163d61bcf1SAndrew Turner  *    notice, this list of conditions and the following disclaimer in the
173d61bcf1SAndrew Turner  *    documentation and/or other materials provided with the distribution.
183d61bcf1SAndrew Turner  *
193d61bcf1SAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
203d61bcf1SAndrew Turner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
213d61bcf1SAndrew Turner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
223d61bcf1SAndrew Turner  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
233d61bcf1SAndrew Turner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
243d61bcf1SAndrew Turner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
253d61bcf1SAndrew Turner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
263d61bcf1SAndrew Turner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
273d61bcf1SAndrew Turner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
283d61bcf1SAndrew Turner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
293d61bcf1SAndrew Turner  * SUCH DAMAGE.
303d61bcf1SAndrew Turner  */
313d61bcf1SAndrew Turner 
323d61bcf1SAndrew Turner #define	VMM_STATIC	static
333d61bcf1SAndrew Turner #define	VMM_HYP_FUNC(func)	vmm_nvhe_ ## func
343d61bcf1SAndrew Turner 
35*7861ecd1SAndrew Turner #define	guest_or_nonvhe(guest)	(true)
36*7861ecd1SAndrew Turner #define	EL1_REG(reg)		MRS_REG_ALT_NAME(reg ## _EL1)
37*7861ecd1SAndrew Turner #define	EL0_REG(reg)		MRS_REG_ALT_NAME(reg ## _EL0)
38*7861ecd1SAndrew Turner 
393d61bcf1SAndrew Turner #include "vmm_hyp.c"
404b6c9f84SAndrew Turner 
414b6c9f84SAndrew Turner uint64_t vmm_hyp_enter(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
424b6c9f84SAndrew Turner     uint64_t, uint64_t, uint64_t);
434b6c9f84SAndrew Turner 
444b6c9f84SAndrew Turner /*
454b6c9f84SAndrew Turner  * Handlers for EL2 addres space. Only needed by non-VHE code as in VHE the
464b6c9f84SAndrew Turner  * kernel is in EL2 so pmap will manage the address space.
474b6c9f84SAndrew Turner  */
484b6c9f84SAndrew Turner static int
vmm_dc_civac(uint64_t start,uint64_t len)494b6c9f84SAndrew Turner vmm_dc_civac(uint64_t start, uint64_t len)
504b6c9f84SAndrew Turner {
514b6c9f84SAndrew Turner 	size_t line_size, end;
524b6c9f84SAndrew Turner 	uint64_t ctr;
534b6c9f84SAndrew Turner 
544b6c9f84SAndrew Turner 	ctr = READ_SPECIALREG(ctr_el0);
554b6c9f84SAndrew Turner 	line_size = sizeof(int) << CTR_DLINE_SIZE(ctr);
564b6c9f84SAndrew Turner 	end = start + len;
574b6c9f84SAndrew Turner 	dsb(ishst);
584b6c9f84SAndrew Turner 	/* Clean and Invalidate the D-cache */
594b6c9f84SAndrew Turner 	for (; start < end; start += line_size)
604b6c9f84SAndrew Turner 		__asm __volatile("dc	civac, %0" :: "r" (start) : "memory");
614b6c9f84SAndrew Turner 	dsb(ish);
624b6c9f84SAndrew Turner 	return (0);
634b6c9f84SAndrew Turner }
644b6c9f84SAndrew Turner 
654b6c9f84SAndrew Turner static int
vmm_el2_tlbi(uint64_t type,uint64_t start,uint64_t len)664b6c9f84SAndrew Turner vmm_el2_tlbi(uint64_t type, uint64_t start, uint64_t len)
674b6c9f84SAndrew Turner {
684b6c9f84SAndrew Turner 	uint64_t end, r;
694b6c9f84SAndrew Turner 
704b6c9f84SAndrew Turner 	dsb(ishst);
714b6c9f84SAndrew Turner 	switch (type) {
724b6c9f84SAndrew Turner 	default:
734b6c9f84SAndrew Turner 	case HYP_EL2_TLBI_ALL:
744b6c9f84SAndrew Turner 		__asm __volatile("tlbi	alle2" ::: "memory");
754b6c9f84SAndrew Turner 		break;
764b6c9f84SAndrew Turner 	case HYP_EL2_TLBI_VA:
774b6c9f84SAndrew Turner 		end = TLBI_VA(start + len);
784b6c9f84SAndrew Turner 		start = TLBI_VA(start);
794b6c9f84SAndrew Turner 		for (r = start; r < end; r += TLBI_VA_L3_INCR) {
804b6c9f84SAndrew Turner 			__asm __volatile("tlbi	vae2is, %0" :: "r"(r));
814b6c9f84SAndrew Turner 		}
824b6c9f84SAndrew Turner 		break;
834b6c9f84SAndrew Turner 	}
844b6c9f84SAndrew Turner 	dsb(ish);
854b6c9f84SAndrew Turner 
864b6c9f84SAndrew Turner 	return (0);
874b6c9f84SAndrew Turner }
884b6c9f84SAndrew Turner 
894b6c9f84SAndrew Turner uint64_t
vmm_hyp_enter(uint64_t handle,uint64_t x1,uint64_t x2,uint64_t x3,uint64_t x4,uint64_t x5,uint64_t x6,uint64_t x7)904b6c9f84SAndrew Turner vmm_hyp_enter(uint64_t handle, uint64_t x1, uint64_t x2, uint64_t x3,
914b6c9f84SAndrew Turner     uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7)
924b6c9f84SAndrew Turner {
934b6c9f84SAndrew Turner 	switch (handle) {
944b6c9f84SAndrew Turner 	case HYP_ENTER_GUEST:
954b6c9f84SAndrew Turner 		return (VMM_HYP_FUNC(enter_guest)((struct hyp *)x1,
964b6c9f84SAndrew Turner 		    (struct hypctx *)x2));
974b6c9f84SAndrew Turner 	case HYP_READ_REGISTER:
984b6c9f84SAndrew Turner 		return (VMM_HYP_FUNC(read_reg)(x1));
994b6c9f84SAndrew Turner 	case HYP_CLEAN_S2_TLBI:
1004b6c9f84SAndrew Turner 		VMM_HYP_FUNC(clean_s2_tlbi());
1014b6c9f84SAndrew Turner 		return (0);
1024b6c9f84SAndrew Turner 	case HYP_DC_CIVAC:
1034b6c9f84SAndrew Turner 		return (vmm_dc_civac(x1, x2));
1044b6c9f84SAndrew Turner 	case HYP_EL2_TLBI:
1054b6c9f84SAndrew Turner 		return (vmm_el2_tlbi(x1, x2, x3));
1064b6c9f84SAndrew Turner 	case HYP_S2_TLBI_RANGE:
1074b6c9f84SAndrew Turner 		VMM_HYP_FUNC(s2_tlbi_range)(x1, x2, x3, x4);
1084b6c9f84SAndrew Turner 		return (0);
1094b6c9f84SAndrew Turner 	case HYP_S2_TLBI_ALL:
1104b6c9f84SAndrew Turner 		VMM_HYP_FUNC(s2_tlbi_all)(x1);
1114b6c9f84SAndrew Turner 		return (0);
1124b6c9f84SAndrew Turner 	case HYP_CLEANUP:	/* Handled in vmm_hyp_exception.S */
1134b6c9f84SAndrew Turner 	default:
1144b6c9f84SAndrew Turner 		break;
1154b6c9f84SAndrew Turner 	}
1164b6c9f84SAndrew Turner 
1174b6c9f84SAndrew Turner 	return (0);
1184b6c9f84SAndrew Turner }
119