1 1.29 riastrad /* $NetBSD: xenfunc.c,v 1.29 2022/08/20 23:48:51 riastradh Exp $ */ 2 1.2 bouyer 3 1.2 bouyer /* 4 1.2 bouyer * Copyright (c) 2004 Christian Limpach. 5 1.2 bouyer * All rights reserved. 6 1.2 bouyer * 7 1.2 bouyer * Redistribution and use in source and binary forms, with or without 8 1.2 bouyer * modification, are permitted provided that the following conditions 9 1.2 bouyer * are met: 10 1.2 bouyer * 1. Redistributions of source code must retain the above copyright 11 1.2 bouyer * notice, this list of conditions and the following disclaimer. 12 1.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright 13 1.2 bouyer * notice, this list of conditions and the following disclaimer in the 14 1.2 bouyer * documentation and/or other materials provided with the distribution. 15 1.2 bouyer * 16 1.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.2 bouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.2 bouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.2 bouyer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.2 bouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.2 bouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.2 bouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.2 bouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.2 bouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.2 bouyer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.2 bouyer */ 27 1.2 bouyer 28 1.4 bouyer #include <sys/cdefs.h> 29 1.29 riastrad __KERNEL_RCSID(0, "$NetBSD: xenfunc.c,v 1.29 2022/08/20 23:48:51 riastradh Exp $"); 30 1.4 bouyer 31 1.2 bouyer #include <sys/param.h> 32 1.2 bouyer 33 1.2 bouyer #include <uvm/uvm_extern.h> 34 1.2 bouyer 35 1.2 bouyer #include <machine/intr.h> 36 1.2 bouyer #include <machine/vmparam.h> 37 1.2 bouyer #include <machine/pmap.h> 38 1.29 riastrad #include <machine/pmap_private.h> 39 1.2 bouyer #include <xen/xen.h> 40 1.2 bouyer #include <xen/hypervisor.h> 41 1.2 bouyer //#include <xen/evtchn.h> 42 1.2 bouyer #include <xen/xenpmap.h> 43 1.2 bouyer #include <machine/pte.h> 44 1.2 bouyer 45 1.22 cherry #define MAX_XEN_IDT 128 46 1.22 cherry 47 1.2 bouyer void xen_set_ldt(vaddr_t, uint32_t); 48 1.2 bouyer 49 1.2 bouyer void 50 1.24 cherry invlpg(vaddr_t addr) 51 1.2 bouyer { 52 1.18 jdolecek int s = splvm(); /* XXXSMP */ 53 1.2 bouyer xpq_queue_invlpg(addr); 54 1.2 bouyer splx(s); 55 1.2 bouyer } 56 1.2 bouyer 57 1.2 bouyer void 58 1.24 cherry lidt(struct region_descriptor *rd) 59 1.20 cherry { 60 1.20 cherry /* 61 1.20 cherry * We need to do this because we can't assume kmem_alloc(9) 62 1.20 cherry * will be available at the boot stage when this is called. 63 1.20 cherry */ 64 1.20 cherry static char xen_idt_page[PAGE_SIZE] __attribute__((__aligned__ (PAGE_SIZE))); 65 1.27 bouyer #if defined(__x86_64__) 66 1.27 bouyer kpreempt_disable(); 67 1.27 bouyer #endif 68 1.22 cherry memset(xen_idt_page, 0, PAGE_SIZE); 69 1.22 cherry 70 1.20 cherry struct trap_info *xen_idt = (void * )xen_idt_page; 71 1.20 cherry int xen_idt_idx = 0; 72 1.20 cherry 73 1.20 cherry struct trap_info * idd = (void *) rd->rd_base; 74 1.20 cherry const int nidt = rd->rd_limit / (sizeof *idd); 75 1.20 cherry 76 1.20 cherry int i; 77 1.20 cherry 78 1.20 cherry /* 79 1.20 cherry * Sweep in all initialised entries, consolidate them back to 80 1.20 cherry * back in the requestor array. 81 1.20 cherry */ 82 1.20 cherry for (i = 0; i < nidt; i++) { 83 1.22 cherry if (idd[i].address == 0) /* Skip gap */ 84 1.20 cherry continue; 85 1.22 cherry KASSERT(xen_idt_idx < MAX_XEN_IDT); 86 1.20 cherry /* Copy over entry */ 87 1.20 cherry xen_idt[xen_idt_idx++] = idd[i]; 88 1.20 cherry } 89 1.20 cherry 90 1.21 cherry #if defined(__x86_64__) 91 1.20 cherry /* page needs to be r/o */ 92 1.20 cherry pmap_changeprot_local((vaddr_t) xen_idt, VM_PROT_READ); 93 1.21 cherry #endif /* __x86_64 */ 94 1.20 cherry 95 1.20 cherry /* Hook it up in the hypervisor */ 96 1.20 cherry if (HYPERVISOR_set_trap_table(xen_idt)) 97 1.20 cherry panic("HYPERVISOR_set_trap_table() failed"); 98 1.20 cherry 99 1.21 cherry #if defined(__x86_64__) 100 1.20 cherry /* reset */ 101 1.20 cherry pmap_changeprot_local((vaddr_t) xen_idt, VM_PROT_READ|VM_PROT_WRITE); 102 1.27 bouyer kpreempt_enable(); 103 1.21 cherry #endif /* __x86_64 */ 104 1.20 cherry } 105 1.20 cherry 106 1.20 cherry void 107 1.24 cherry lldt(u_short sel) 108 1.2 bouyer { 109 1.11 jym #ifndef __x86_64__ 110 1.7 ad struct cpu_info *ci; 111 1.2 bouyer 112 1.7 ad ci = curcpu(); 113 1.7 ad 114 1.7 ad if (ci->ci_curldt == sel) 115 1.7 ad return; 116 1.2 bouyer if (sel == GSEL(GLDT_SEL, SEL_KPL)) 117 1.16 maxv xen_set_ldt((vaddr_t)ldtstore, NLDT); 118 1.2 bouyer else 119 1.7 ad xen_set_ldt(ci->ci_gdt[IDXSELN(sel)].ld.ld_base, 120 1.7 ad ci->ci_gdt[IDXSELN(sel)].ld.ld_entries); 121 1.7 ad ci->ci_curldt = sel; 122 1.11 jym #endif 123 1.2 bouyer } 124 1.2 bouyer 125 1.2 bouyer void 126 1.24 cherry ltr(u_short sel) 127 1.2 bouyer { 128 1.12 cherry panic("XXX ltr not supported\n"); 129 1.2 bouyer } 130 1.2 bouyer 131 1.2 bouyer void 132 1.25 maxv lcr0(register_t val) 133 1.2 bouyer { 134 1.12 cherry panic("XXX lcr0 not supported\n"); 135 1.2 bouyer } 136 1.2 bouyer 137 1.25 maxv register_t 138 1.24 cherry rcr0(void) 139 1.2 bouyer { 140 1.12 cherry /* XXX: handle X86_CR0_TS ? */ 141 1.2 bouyer return 0; 142 1.2 bouyer } 143 1.2 bouyer 144 1.2 bouyer #ifndef __x86_64__ 145 1.2 bouyer void 146 1.26 kre lcr3(register_t val) 147 1.2 bouyer { 148 1.28 bouyer int s = splvm(); 149 1.2 bouyer xpq_queue_pt_switch(xpmap_ptom_masked(val)); 150 1.2 bouyer splx(s); 151 1.2 bouyer } 152 1.2 bouyer #endif 153 1.2 bouyer 154 1.2 bouyer void 155 1.24 cherry tlbflush(void) 156 1.2 bouyer { 157 1.28 bouyer int s = splvm(); 158 1.2 bouyer xpq_queue_tlb_flush(); 159 1.2 bouyer splx(s); 160 1.2 bouyer } 161 1.2 bouyer 162 1.2 bouyer void 163 1.24 cherry tlbflushg(void) 164 1.2 bouyer { 165 1.2 bouyer tlbflush(); 166 1.2 bouyer } 167 1.2 bouyer 168 1.15 kamil register_t 169 1.24 cherry rdr0(void) 170 1.14 kamil { 171 1.14 kamil 172 1.14 kamil return HYPERVISOR_get_debugreg(0); 173 1.14 kamil } 174 1.14 kamil 175 1.14 kamil void 176 1.24 cherry ldr0(register_t val) 177 1.14 kamil { 178 1.14 kamil 179 1.14 kamil HYPERVISOR_set_debugreg(0, val); 180 1.14 kamil } 181 1.14 kamil 182 1.15 kamil register_t 183 1.24 cherry rdr1(void) 184 1.14 kamil { 185 1.14 kamil 186 1.14 kamil return HYPERVISOR_get_debugreg(1); 187 1.14 kamil } 188 1.14 kamil 189 1.14 kamil void 190 1.24 cherry ldr1(register_t val) 191 1.14 kamil { 192 1.14 kamil 193 1.14 kamil HYPERVISOR_set_debugreg(1, val); 194 1.14 kamil } 195 1.14 kamil 196 1.15 kamil register_t 197 1.24 cherry rdr2(void) 198 1.14 kamil { 199 1.14 kamil 200 1.14 kamil return HYPERVISOR_get_debugreg(2); 201 1.14 kamil } 202 1.14 kamil 203 1.14 kamil void 204 1.24 cherry ldr2(register_t val) 205 1.14 kamil { 206 1.14 kamil 207 1.14 kamil HYPERVISOR_set_debugreg(2, val); 208 1.14 kamil } 209 1.14 kamil 210 1.15 kamil register_t 211 1.24 cherry rdr3(void) 212 1.14 kamil { 213 1.14 kamil 214 1.14 kamil return HYPERVISOR_get_debugreg(3); 215 1.14 kamil } 216 1.14 kamil 217 1.14 kamil void 218 1.24 cherry ldr3(register_t val) 219 1.14 kamil { 220 1.14 kamil 221 1.14 kamil HYPERVISOR_set_debugreg(3, val); 222 1.14 kamil } 223 1.15 kamil register_t 224 1.24 cherry rdr6(void) 225 1.2 bouyer { 226 1.2 bouyer 227 1.14 kamil return HYPERVISOR_get_debugreg(6); 228 1.2 bouyer } 229 1.2 bouyer 230 1.2 bouyer void 231 1.24 cherry ldr6(register_t val) 232 1.2 bouyer { 233 1.2 bouyer 234 1.2 bouyer HYPERVISOR_set_debugreg(6, val); 235 1.2 bouyer } 236 1.2 bouyer 237 1.15 kamil register_t 238 1.24 cherry rdr7(void) 239 1.14 kamil { 240 1.14 kamil 241 1.14 kamil return HYPERVISOR_get_debugreg(7); 242 1.14 kamil } 243 1.14 kamil 244 1.14 kamil void 245 1.24 cherry ldr7(register_t val) 246 1.14 kamil { 247 1.14 kamil 248 1.14 kamil HYPERVISOR_set_debugreg(7, val); 249 1.14 kamil } 250 1.14 kamil 251 1.2 bouyer void 252 1.24 cherry wbinvd(void) 253 1.2 bouyer { 254 1.2 bouyer 255 1.2 bouyer xpq_flush_cache(); 256 1.2 bouyer } 257 1.2 bouyer 258 1.25 maxv register_t 259 1.24 cherry rcr2(void) 260 1.2 bouyer { 261 1.5 cegger return curcpu()->ci_vcpu->arch.cr2; 262 1.2 bouyer } 263 1.17 maxv 264 1.27 bouyer void 265 1.27 bouyer lcr2(register_t v) 266 1.27 bouyer { 267 1.27 bouyer curcpu()->ci_vcpu->arch.cr2 = v; 268 1.27 bouyer } 269 1.27 bouyer 270 1.17 maxv #ifdef __x86_64__ 271 1.17 maxv void 272 1.24 cherry setusergs(int gssel) 273 1.17 maxv { 274 1.17 maxv HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, gssel); 275 1.17 maxv } 276 1.17 maxv #endif 277