1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2021 Andrew Turner
5 * Copyright (c) 2024 Arm Ltd
6 *
7 * This work was supported by Innovate UK project 105694, "Digital Security
8 * by Design (DSbD) Technology Platform Prototype".
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #define VMM_STATIC static
33 #define VMM_HYP_FUNC(func) vmm_nvhe_ ## func
34
35 #define guest_or_nonvhe(guest) (true)
36 #define EL1_REG(reg) MRS_REG_ALT_NAME(reg ## _EL1)
37 #define EL0_REG(reg) MRS_REG_ALT_NAME(reg ## _EL0)
38
39 #include "vmm_hyp.c"
40
41 uint64_t vmm_hyp_enter(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
42 uint64_t, uint64_t, uint64_t);
43
44 /*
45 * Handlers for EL2 addres space. Only needed by non-VHE code as in VHE the
46 * kernel is in EL2 so pmap will manage the address space.
47 */
48 static int
vmm_dc_civac(uint64_t start,uint64_t len)49 vmm_dc_civac(uint64_t start, uint64_t len)
50 {
51 size_t line_size, end;
52 uint64_t ctr;
53
54 ctr = READ_SPECIALREG(ctr_el0);
55 line_size = sizeof(int) << CTR_DLINE_SIZE(ctr);
56 end = start + len;
57 dsb(ishst);
58 /* Clean and Invalidate the D-cache */
59 for (; start < end; start += line_size)
60 __asm __volatile("dc civac, %0" :: "r" (start) : "memory");
61 dsb(ish);
62 return (0);
63 }
64
65 static int
vmm_el2_tlbi(uint64_t type,uint64_t start,uint64_t len)66 vmm_el2_tlbi(uint64_t type, uint64_t start, uint64_t len)
67 {
68 uint64_t end, r;
69
70 dsb(ishst);
71 switch (type) {
72 default:
73 case HYP_EL2_TLBI_ALL:
74 __asm __volatile("tlbi alle2" ::: "memory");
75 break;
76 case HYP_EL2_TLBI_VA:
77 end = TLBI_VA(start + len);
78 start = TLBI_VA(start);
79 for (r = start; r < end; r += TLBI_VA_L3_INCR) {
80 __asm __volatile("tlbi vae2is, %0" :: "r"(r));
81 }
82 break;
83 }
84 dsb(ish);
85
86 return (0);
87 }
88
89 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)90 vmm_hyp_enter(uint64_t handle, uint64_t x1, uint64_t x2, uint64_t x3,
91 uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7)
92 {
93 switch (handle) {
94 case HYP_ENTER_GUEST:
95 return (VMM_HYP_FUNC(enter_guest)((struct hyp *)x1,
96 (struct hypctx *)x2));
97 case HYP_READ_REGISTER:
98 return (VMM_HYP_FUNC(read_reg)(x1));
99 case HYP_CLEAN_S2_TLBI:
100 VMM_HYP_FUNC(clean_s2_tlbi());
101 return (0);
102 case HYP_DC_CIVAC:
103 return (vmm_dc_civac(x1, x2));
104 case HYP_EL2_TLBI:
105 return (vmm_el2_tlbi(x1, x2, x3));
106 case HYP_S2_TLBI_RANGE:
107 VMM_HYP_FUNC(s2_tlbi_range)(x1, x2, x3, x4);
108 return (0);
109 case HYP_S2_TLBI_ALL:
110 VMM_HYP_FUNC(s2_tlbi_all)(x1);
111 return (0);
112 case HYP_CLEANUP: /* Handled in vmm_hyp_exception.S */
113 default:
114 break;
115 }
116
117 return (0);
118 }
119