xref: /netbsd-src/sys/arch/xen/x86/xenfunc.c (revision 8f18579d5d3b839aa8bc589e81898b445652fa31)
1*8f18579dSriastradh /*	$NetBSD: xenfunc.c,v 1.29 2022/08/20 23:48:51 riastradh Exp $	*/
24e541343Sbouyer 
34e541343Sbouyer /*
44e541343Sbouyer  * Copyright (c) 2004 Christian Limpach.
54e541343Sbouyer  * All rights reserved.
64e541343Sbouyer  *
74e541343Sbouyer  * Redistribution and use in source and binary forms, with or without
84e541343Sbouyer  * modification, are permitted provided that the following conditions
94e541343Sbouyer  * are met:
104e541343Sbouyer  * 1. Redistributions of source code must retain the above copyright
114e541343Sbouyer  *    notice, this list of conditions and the following disclaimer.
124e541343Sbouyer  * 2. Redistributions in binary form must reproduce the above copyright
134e541343Sbouyer  *    notice, this list of conditions and the following disclaimer in the
144e541343Sbouyer  *    documentation and/or other materials provided with the distribution.
154e541343Sbouyer  *
164e541343Sbouyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
174e541343Sbouyer  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
184e541343Sbouyer  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
194e541343Sbouyer  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
204e541343Sbouyer  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
214e541343Sbouyer  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
224e541343Sbouyer  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
234e541343Sbouyer  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
244e541343Sbouyer  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
254e541343Sbouyer  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
264e541343Sbouyer  */
274e541343Sbouyer 
28a9cd1764Sbouyer #include <sys/cdefs.h>
29*8f18579dSriastradh __KERNEL_RCSID(0, "$NetBSD: xenfunc.c,v 1.29 2022/08/20 23:48:51 riastradh Exp $");
30a9cd1764Sbouyer 
314e541343Sbouyer #include <sys/param.h>
324e541343Sbouyer 
334e541343Sbouyer #include <uvm/uvm_extern.h>
344e541343Sbouyer 
354e541343Sbouyer #include <machine/intr.h>
364e541343Sbouyer #include <machine/vmparam.h>
374e541343Sbouyer #include <machine/pmap.h>
38*8f18579dSriastradh #include <machine/pmap_private.h>
394e541343Sbouyer #include <xen/xen.h>
404e541343Sbouyer #include <xen/hypervisor.h>
414e541343Sbouyer //#include <xen/evtchn.h>
424e541343Sbouyer #include <xen/xenpmap.h>
434e541343Sbouyer #include <machine/pte.h>
444e541343Sbouyer 
450e975399Scherry #define MAX_XEN_IDT 128
460e975399Scherry 
474e541343Sbouyer void xen_set_ldt(vaddr_t, uint32_t);
484e541343Sbouyer 
494e541343Sbouyer void
invlpg(vaddr_t addr)50afc14682Scherry invlpg(vaddr_t addr)
514e541343Sbouyer {
528c3f6558Sjdolecek 	int s = splvm(); /* XXXSMP */
534e541343Sbouyer 	xpq_queue_invlpg(addr);
544e541343Sbouyer 	splx(s);
554e541343Sbouyer }
564e541343Sbouyer 
574e541343Sbouyer void
lidt(struct region_descriptor * rd)58afc14682Scherry lidt(struct region_descriptor *rd)
594281462fScherry {
604281462fScherry 	/*
614281462fScherry 	 * We need to do this because we can't assume kmem_alloc(9)
624281462fScherry 	 * will be available at the boot stage when this is called.
634281462fScherry 	 */
644281462fScherry 	static char xen_idt_page[PAGE_SIZE] __attribute__((__aligned__ (PAGE_SIZE)));
65c24c993fSbouyer #if defined(__x86_64__)
66c24c993fSbouyer 	kpreempt_disable();
67c24c993fSbouyer #endif
680e975399Scherry 	memset(xen_idt_page, 0, PAGE_SIZE);
694281462fScherry 
704281462fScherry 	struct trap_info *xen_idt = (void * )xen_idt_page;
714281462fScherry 	int xen_idt_idx = 0;
724281462fScherry 
734281462fScherry 	struct trap_info * idd = (void *) rd->rd_base;
744281462fScherry 	const int nidt = rd->rd_limit / (sizeof *idd);
754281462fScherry 
764281462fScherry 	int i;
774281462fScherry 
784281462fScherry 	/*
794281462fScherry 	 * Sweep in all initialised entries, consolidate them back to
804281462fScherry 	 * back in the requestor array.
814281462fScherry 	 */
824281462fScherry 	for (i = 0; i < nidt; i++) {
830e975399Scherry 		if (idd[i].address == 0) /* Skip gap */
844281462fScherry 			continue;
850e975399Scherry 		KASSERT(xen_idt_idx < MAX_XEN_IDT);
864281462fScherry 		/* Copy over entry */
874281462fScherry 		xen_idt[xen_idt_idx++] = idd[i];
884281462fScherry 	}
894281462fScherry 
9000cd7c0dScherry #if defined(__x86_64__)
914281462fScherry 	/* page needs to be r/o */
924281462fScherry 	pmap_changeprot_local((vaddr_t) xen_idt, VM_PROT_READ);
9300cd7c0dScherry #endif /* __x86_64 */
944281462fScherry 
954281462fScherry 	/* Hook it up in the hypervisor */
964281462fScherry 	if (HYPERVISOR_set_trap_table(xen_idt))
974281462fScherry 		panic("HYPERVISOR_set_trap_table() failed");
984281462fScherry 
9900cd7c0dScherry #if defined(__x86_64__)
1004281462fScherry 	/* reset */
1014281462fScherry 	pmap_changeprot_local((vaddr_t) xen_idt, VM_PROT_READ|VM_PROT_WRITE);
102c24c993fSbouyer 	kpreempt_enable();
10300cd7c0dScherry #endif /* __x86_64 */
1044281462fScherry }
1054281462fScherry 
1064281462fScherry void
lldt(u_short sel)107afc14682Scherry lldt(u_short sel)
1084e541343Sbouyer {
109d9474223Sjym #ifndef __x86_64__
110b698c03cSad 	struct cpu_info *ci;
1114e541343Sbouyer 
112b698c03cSad 	ci = curcpu();
113b698c03cSad 
114b698c03cSad 	if (ci->ci_curldt == sel)
115b698c03cSad 		return;
1164e541343Sbouyer 	if (sel == GSEL(GLDT_SEL, SEL_KPL))
1176c9d31edSmaxv 		xen_set_ldt((vaddr_t)ldtstore, NLDT);
1184e541343Sbouyer 	else
119b698c03cSad 		xen_set_ldt(ci->ci_gdt[IDXSELN(sel)].ld.ld_base,
120b698c03cSad 		    ci->ci_gdt[IDXSELN(sel)].ld.ld_entries);
121b698c03cSad 	ci->ci_curldt = sel;
1224e541343Sbouyer #endif
123d9474223Sjym }
1244e541343Sbouyer 
1254e541343Sbouyer void
ltr(u_short sel)126afc14682Scherry ltr(u_short sel)
1274e541343Sbouyer {
12892ccc4eaScherry 	panic("XXX ltr not supported\n");
1294e541343Sbouyer }
1304e541343Sbouyer 
1314e541343Sbouyer void
lcr0(register_t val)1321554c1fbSmaxv lcr0(register_t val)
1334e541343Sbouyer {
13492ccc4eaScherry 	panic("XXX lcr0 not supported\n");
1354e541343Sbouyer }
1364e541343Sbouyer 
1371554c1fbSmaxv register_t
rcr0(void)138afc14682Scherry rcr0(void)
1394e541343Sbouyer {
14092ccc4eaScherry 	/* XXX: handle X86_CR0_TS ? */
1414e541343Sbouyer 	return 0;
1424e541343Sbouyer }
1434e541343Sbouyer 
1444e541343Sbouyer #ifndef __x86_64__
1454e541343Sbouyer void
lcr3(register_t val)14630031e47Skre lcr3(register_t val)
1474e541343Sbouyer {
1480eef747dSbouyer 	int s = splvm();
1494e541343Sbouyer 	xpq_queue_pt_switch(xpmap_ptom_masked(val));
1504e541343Sbouyer 	splx(s);
1514e541343Sbouyer }
1524e541343Sbouyer #endif
1534e541343Sbouyer 
1544e541343Sbouyer void
tlbflush(void)155afc14682Scherry tlbflush(void)
1564e541343Sbouyer {
1570eef747dSbouyer 	int s = splvm();
1584e541343Sbouyer 	xpq_queue_tlb_flush();
1594e541343Sbouyer 	splx(s);
1604e541343Sbouyer }
1614e541343Sbouyer 
1624e541343Sbouyer void
tlbflushg(void)163afc14682Scherry tlbflushg(void)
1644e541343Sbouyer {
1654e541343Sbouyer 	tlbflush();
1664e541343Sbouyer }
1674e541343Sbouyer 
1689b94e002Skamil register_t
rdr0(void)169afc14682Scherry rdr0(void)
170266caf90Skamil {
171266caf90Skamil 
172266caf90Skamil 	return HYPERVISOR_get_debugreg(0);
173266caf90Skamil }
174266caf90Skamil 
175266caf90Skamil void
ldr0(register_t val)176afc14682Scherry ldr0(register_t val)
177266caf90Skamil {
178266caf90Skamil 
179266caf90Skamil 	HYPERVISOR_set_debugreg(0, val);
180266caf90Skamil }
181266caf90Skamil 
1829b94e002Skamil register_t
rdr1(void)183afc14682Scherry rdr1(void)
184266caf90Skamil {
185266caf90Skamil 
186266caf90Skamil 	return HYPERVISOR_get_debugreg(1);
187266caf90Skamil }
188266caf90Skamil 
189266caf90Skamil void
ldr1(register_t val)190afc14682Scherry ldr1(register_t val)
191266caf90Skamil {
192266caf90Skamil 
193266caf90Skamil 	HYPERVISOR_set_debugreg(1, val);
194266caf90Skamil }
195266caf90Skamil 
1969b94e002Skamil register_t
rdr2(void)197afc14682Scherry rdr2(void)
198266caf90Skamil {
199266caf90Skamil 
200266caf90Skamil 	return HYPERVISOR_get_debugreg(2);
201266caf90Skamil }
202266caf90Skamil 
203266caf90Skamil void
ldr2(register_t val)204afc14682Scherry ldr2(register_t val)
205266caf90Skamil {
206266caf90Skamil 
207266caf90Skamil 	HYPERVISOR_set_debugreg(2, val);
208266caf90Skamil }
209266caf90Skamil 
2109b94e002Skamil register_t
rdr3(void)211afc14682Scherry rdr3(void)
212266caf90Skamil {
213266caf90Skamil 
214266caf90Skamil 	return HYPERVISOR_get_debugreg(3);
215266caf90Skamil }
216266caf90Skamil 
217266caf90Skamil void
ldr3(register_t val)218afc14682Scherry ldr3(register_t val)
219266caf90Skamil {
220266caf90Skamil 
221266caf90Skamil 	HYPERVISOR_set_debugreg(3, val);
222266caf90Skamil }
2239b94e002Skamil register_t
rdr6(void)224afc14682Scherry rdr6(void)
2254e541343Sbouyer {
2264e541343Sbouyer 
227266caf90Skamil 	return HYPERVISOR_get_debugreg(6);
2284e541343Sbouyer }
2294e541343Sbouyer 
2304e541343Sbouyer void
ldr6(register_t val)231afc14682Scherry ldr6(register_t val)
2324e541343Sbouyer {
2334e541343Sbouyer 
2344e541343Sbouyer 	HYPERVISOR_set_debugreg(6, val);
2354e541343Sbouyer }
2364e541343Sbouyer 
2379b94e002Skamil register_t
rdr7(void)238afc14682Scherry rdr7(void)
239266caf90Skamil {
240266caf90Skamil 
241266caf90Skamil 	return HYPERVISOR_get_debugreg(7);
242266caf90Skamil }
243266caf90Skamil 
244266caf90Skamil void
ldr7(register_t val)245afc14682Scherry ldr7(register_t val)
246266caf90Skamil {
247266caf90Skamil 
248266caf90Skamil 	HYPERVISOR_set_debugreg(7, val);
249266caf90Skamil }
250266caf90Skamil 
2514e541343Sbouyer void
wbinvd(void)252afc14682Scherry wbinvd(void)
2534e541343Sbouyer {
2544e541343Sbouyer 
2554e541343Sbouyer 	xpq_flush_cache();
2564e541343Sbouyer }
2574e541343Sbouyer 
2581554c1fbSmaxv register_t
rcr2(void)259afc14682Scherry rcr2(void)
2604e541343Sbouyer {
26120161b72Scegger 	return curcpu()->ci_vcpu->arch.cr2;
2624e541343Sbouyer }
263395f5383Smaxv 
264c24c993fSbouyer void
lcr2(register_t v)265c24c993fSbouyer lcr2(register_t v)
266c24c993fSbouyer {
267c24c993fSbouyer 	curcpu()->ci_vcpu->arch.cr2 = v;
268c24c993fSbouyer }
269c24c993fSbouyer 
270395f5383Smaxv #ifdef __x86_64__
271395f5383Smaxv void
setusergs(int gssel)272afc14682Scherry setusergs(int gssel)
273395f5383Smaxv {
274395f5383Smaxv 	HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, gssel);
275395f5383Smaxv }
276395f5383Smaxv #endif
277