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