nvmm - Use a critical section around the vmrun again
[dragonfly.git] / sys / dev / virtual / nvmm / nvmm_os.h
1 /*
2  * Copyright (c) 2021 Maxime Villard, m00nbsd.net
3  * Copyright (c) 2021 The DragonFly Project.
4  * All rights reserved.
5  *
6  * This code is part of the NVMM hypervisor.
7  *
8  * This code is derived from software contributed to The DragonFly Project
9  * by Aaron LI <aly@aaronly.me>
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #ifndef _NVMM_OS_H_
34 #define _NVMM_OS_H_
35
36 #ifndef _KERNEL
37 #error "This file should not be included by userland programs."
38 #endif
39
40 #if defined(__NetBSD__)
41 #include <sys/cpu.h>
42 #include <uvm/uvm_object.h>
43 #include <uvm/uvm_extern.h>
44 #include <uvm/uvm_page.h>
45 #elif defined(__DragonFly__)
46 #include <sys/lock.h>
47 #include <sys/malloc.h> /* contigmalloc, contigfree */
48 #include <sys/proc.h> /* LWP_MP_URETMASK */
49 #include <vm/vm.h>
50 #include <vm/vm_extern.h>
51 #include <vm/vm_map.h>
52 #include <vm/vm_object.h>
53 #include <vm/vm_page.h>
54 #include <vm/vm_pager.h>
55 #include <vm/vm_param.h> /* KERN_SUCCESS, etc. */
56 #include <vm/pmap.h> /* pmap_ept_transform, pmap_npt_transform */
57 #include <machine/cpu.h> /* hvm_break_wanted */
58 #include <machine/cpufunc.h> /* ffsl, ffs, etc. */
59 #endif
60
61 /* Types. */
62 #if defined(__NetBSD__)
63 typedef struct vmspace          os_vmspace_t;
64 typedef struct uvm_object       os_vmobj_t;
65 typedef krwlock_t               os_rwl_t;
66 typedef kmutex_t                os_mtx_t;
67 #elif defined(__DragonFly__)
68 typedef struct vmspace          os_vmspace_t;
69 typedef struct vm_object        os_vmobj_t;
70 typedef struct lock             os_rwl_t;
71 typedef struct lock             os_mtx_t;
72 /* A few standard types. */
73 typedef vm_offset_t             vaddr_t;
74 typedef vm_offset_t             voff_t;
75 typedef vm_size_t               vsize_t;
76 typedef vm_paddr_t              paddr_t;
77 #endif
78
79 /* Attributes. */
80 #if defined(__DragonFly__)
81 #define DIAGNOSTIC              INVARIANTS
82 #define __cacheline_aligned     __cachealign
83 #define __diagused              __debugvar
84 #endif
85
86 /* Macros. */
87 #if defined(__DragonFly__)
88 #define __arraycount(__x)       (sizeof(__x) / sizeof(__x[0]))
89 #define __insn_barrier()        __asm __volatile("":::"memory")
90 #endif
91
92 /* Bitops. */
93 #if defined(__NetBSD__)
94 #include <sys/bitops.h>
95 #elif defined(__DragonFly__)
96 #include <sys/bitops.h>
97 #ifdef __x86_64__
98 #undef  __BIT
99 #define __BIT(__n)              __BIT64(__n)
100 #undef  __BITS
101 #define __BITS(__m, __n)        __BITS64(__m, __n)
102 #endif /* __x86_64__ */
103 #endif
104
105 /* Maps. */
106 #if defined(__NetBSD__) || defined(__DragonFly__)
107 #define os_kernel_map           kernel_map
108 #define os_curproc_map          &curproc->p_vmspace->vm_map
109 #endif
110
111 /* R/W locks. */
112 #if defined(__NetBSD__)
113 #define os_rwl_init(lock)       rw_init(lock)
114 #define os_rwl_destroy(lock)    rw_destroy(lock)
115 #define os_rwl_rlock(lock)      rw_enter(lock, RW_READER);
116 #define os_rwl_wlock(lock)      rw_enter(lock, RW_WRITER);
117 #define os_rwl_unlock(lock)     rw_exit(lock)
118 #define os_rwl_wheld(lock)      rw_write_held(lock)
119 #elif defined(__DragonFly__)
120 #define os_rwl_init(lock)       lockinit(lock, "nvmmrw", 0, 0)
121 #define os_rwl_destroy(lock)    lockuninit(lock)
122 #define os_rwl_rlock(lock)      lockmgr(lock, LK_SHARED);
123 #define os_rwl_wlock(lock)      lockmgr(lock, LK_EXCLUSIVE);
124 #define os_rwl_unlock(lock)     lockmgr(lock, LK_RELEASE)
125 #define os_rwl_wheld(lock)      (lockstatus(lock, curthread) == LK_EXCLUSIVE)
126 #endif
127
128 /* Mutexes. */
129 #if defined(__NetBSD__)
130 #define os_mtx_init(lock)       mutex_init(lock, MUTEX_DEFAULT, IPL_NONE)
131 #define os_mtx_destroy(lock)    mutex_destroy(lock)
132 #define os_mtx_lock(lock)       mutex_enter(lock)
133 #define os_mtx_unlock(lock)     mutex_exit(lock)
134 #define os_mtx_owned(lock)      mutex_owned(lock)
135 #elif defined(__DragonFly__)
136 #define os_mtx_init(lock)       lockinit(lock, "nvmmmtx", 0, 0)
137 #define os_mtx_destroy(lock)    lockuninit(lock)
138 #define os_mtx_lock(lock)       lockmgr(lock, LK_EXCLUSIVE)
139 #define os_mtx_unlock(lock)     lockmgr(lock, LK_RELEASE)
140 #define os_mtx_owned(lock)      (lockstatus(lock, curthread) == LK_EXCLUSIVE)
141 #endif
142
143 /* Malloc. */
144 #if defined(__NetBSD__)
145 #include <sys/kmem.h>
146 #define os_mem_alloc(size)      kmem_alloc(size, KM_SLEEP)
147 #define os_mem_zalloc(size)     kmem_zalloc(size, KM_SLEEP)
148 #define os_mem_free(ptr, size)  kmem_free(ptr, size)
149 #elif defined(__DragonFly__)
150 #include <sys/malloc.h>
151 MALLOC_DECLARE(M_NVMM);
152 #define os_mem_alloc(size)      kmalloc(size, M_NVMM, M_WAITOK)
153 #define os_mem_zalloc(size)     kmalloc(size, M_NVMM, M_WAITOK | M_ZERO)
154 #define os_mem_free(ptr, size)  kfree(ptr, M_NVMM)
155 #endif
156
157 /* Printf. */
158 #if defined(__NetBSD__)
159 #define os_printf               printf
160 #elif defined(__DragonFly__)
161 #define os_printf               kprintf
162 #endif
163
164 /* Atomics. */
165 #if defined(__NetBSD__)
166 #include <sys/atomic.h>
167 #define os_atomic_inc_uint(x)   atomic_inc_uint(x)
168 #define os_atomic_dec_uint(x)   atomic_dec_uint(x)
169 #define os_atomic_load_uint(x)  atomic_load_relaxed(x)
170 #define os_atomic_inc_64(x)     atomic_inc_64(x)
171 #elif defined(__DragonFly__)
172 #include <machine/atomic.h>
173 #define os_atomic_inc_uint(x)   atomic_add_int(x, 1)
174 #define os_atomic_dec_uint(x)   atomic_subtract_int(x, 1)
175 #define os_atomic_load_uint(x)  atomic_load_acq_int(x)
176 #define os_atomic_inc_64(x)     atomic_add_64(x, 1)
177 #endif
178
179 /* Pmap. */
180 #if defined(__NetBSD__)
181 extern bool pmap_ept_has_ad;
182 #define os_vmspace_pmap(vm)     ((vm)->vm_map.pmap)
183 #define os_vmspace_pdirpa(vm)   ((vm)->vm_map.pmap->pm_pdirpa[0])
184 #define os_pmap_mach(pm)        ((pm)->pm_data)
185 #elif defined(__DragonFly__)
186 #define os_vmspace_pmap(vm)     vmspace_pmap(vm)
187 #define os_vmspace_pdirpa(vm)   (vtophys(vmspace_pmap(vm)->pm_pml4))
188 #endif
189
190 /* CPU. */
191 #if defined(__NetBSD__)
192 #include <sys/cpu.h>
193 typedef struct cpu_info         os_cpu_t;
194 #define OS_MAXCPUS              MAXCPUS
195 #define OS_CPU_FOREACH(cpu)     for (CPU_INFO_FOREACH(, cpu))
196 #define os_cpu_number(cpu)      cpu_index(cpu)
197 #define os_curcpu()             curcpu()
198 #define os_curcpu_number()      cpu_number()
199 #define os_curcpu_tss_sel()     curcpu()->ci_tss_sel
200 #define os_curcpu_tss()         curcpu()->ci_tss
201 #define os_curcpu_gdt()         curcpu()->ci_gdt
202 #define os_curcpu_idt()         curcpu()->ci_idtvec.iv_idt
203 #elif defined(__DragonFly__)
204 #include <sys/globaldata.h>
205 #include <machine/segments.h>
206 typedef struct globaldata       os_cpu_t;
207 #define OS_MAXCPUS              SMP_MAXCPU
208 #define OS_CPU_FOREACH(cpu)     \
209         for (int idx = 0; idx < ncpus && (cpu = globaldata_find(idx)); idx++)
210 #define os_cpu_number(cpu)      (cpu)->gd_cpuid
211 #define os_curcpu()             mycpu
212 #define os_curcpu_number()      mycpuid
213 #define os_curcpu_tss_sel()     GSEL(GPROC0_SEL, SEL_KPL)
214 #define os_curcpu_tss()         &mycpu->gd_prvspace->common_tss
215 #define os_curcpu_gdt()         mdcpu->gd_gdt
216 #define os_curcpu_idt()         r_idt_arr[mycpuid].rd_base
217 #endif
218
219 /* Cpusets. */
220 #if defined(__NetBSD__)
221 #include <sys/kcpuset.h>
222 typedef kcpuset_t               os_cpuset_t;
223 #define os_cpuset_init(s)       kcpuset_create(s, true)
224 #define os_cpuset_destroy(s)    kcpuset_destroy(s)
225 #define os_cpuset_isset(s, c)   kcpuset_isset(s, c)
226 #define os_cpuset_clear(s, c)   kcpuset_clear(s, c)
227 #define os_cpuset_setrunning(s) kcpuset_copy(s, kcpuset_running)
228 #elif defined(__DragonFly__)
229 #include <sys/cpumask.h>
230 #include <machine/smp.h> /* smp_active_mask */
231 typedef cpumask_t               os_cpuset_t;
232 #define os_cpuset_init(s)       \
233         ({ *(s) = kmalloc(sizeof(cpumask_t), M_NVMM, M_WAITOK | M_ZERO); })
234 #define os_cpuset_destroy(s)    kfree((s), M_NVMM)
235 #define os_cpuset_isset(s, c)   CPUMASK_TESTBIT(*(s), c)
236 #define os_cpuset_clear(s, c)   ATOMIC_CPUMASK_NANDBIT(*(s), c)
237 #define os_cpuset_setrunning(s) ATOMIC_CPUMASK_ORMASK(*(s), smp_active_mask)
238 #endif
239
240 /* Preemption. */
241 #if defined(__NetBSD__)
242 #define os_preempt_disable()    kpreempt_disable()
243 #define os_preempt_enable()     kpreempt_enable()
244 #define os_preempt_disabled()   kpreempt_disabled()
245 #elif defined(__DragonFly__)
246 /*
247  * In DragonFly, a thread in kernel mode will not be preemptively migrated
248  * to another CPU or preemptively switched to another normal kernel thread,
249  * but can be preemptively switched to an interrupt thread (which switches
250  * back to the kernel thread it preempted the instant it is done or blocks).
251  *
252  * However, we still need to use a critical section to prevent this nominal
253  * interrupt thread preemption to avoid exposing interrupt threads to
254  * guest DB and FP register state.  We operate under the assumption that
255  * the hard interrupt code won't mess with this state.
256  */
257 #define os_preempt_disable()    crit_enter()
258 #define os_preempt_enable()     crit_exit()
259 #define os_preempt_disabled()   (curthread->td_critcount != 0)
260 #endif
261
262 /* Asserts. */
263 #if defined(__NetBSD__)
264 #define OS_ASSERT               KASSERT
265 #elif defined(__DragonFly__)
266 #define OS_ASSERT               KKASSERT
267 #endif
268
269 /* Misc. */
270 #if defined(__DragonFly__)
271 #define ilog2(n)                ((sizeof(n) > 4 ? ffsl(n) : ffs(n)) - 1)
272 #define uimin(a, b)             ((u_int)a < (u_int)b ? (u_int)a : (u_int)b)
273 #endif
274
275 /* -------------------------------------------------------------------------- */
276
277 os_vmspace_t *  os_vmspace_create(vaddr_t, vaddr_t);
278 void            os_vmspace_destroy(os_vmspace_t *);
279 int             os_vmspace_fault(os_vmspace_t *, vaddr_t, vm_prot_t);
280
281 os_vmobj_t *    os_vmobj_create(voff_t);
282 void            os_vmobj_ref(os_vmobj_t *);
283 void            os_vmobj_rel(os_vmobj_t *);
284
285 int             os_vmobj_map(struct vm_map *, vaddr_t *, vsize_t, os_vmobj_t *,
286                     voff_t, bool, bool, bool, int, int);
287 void            os_vmobj_unmap(struct vm_map *map, vaddr_t, vaddr_t, bool);
288
289 void *          os_pagemem_zalloc(size_t);
290 void            os_pagemem_free(void *, size_t);
291
292 paddr_t         os_pa_zalloc(void);
293 void            os_pa_free(paddr_t);
294
295 int             os_contigpa_zalloc(paddr_t *, vaddr_t *, size_t);
296 void            os_contigpa_free(paddr_t, vaddr_t, size_t);
297
298 static inline bool
299 os_return_needed(void)
300 {
301 #if defined(__NetBSD__)
302         if (preempt_needed()) {
303                 return true;
304         }
305         if (curlwp->l_flag & LW_USERRET) {
306                 return true;
307         }
308         return false;
309 #elif defined(__DragonFly__)
310         if (__predict_false(hvm_break_wanted())) {
311                 return true;
312         }
313         if (__predict_false(curthread->td_lwp->lwp_mpflags & LWP_MP_URETMASK)) {
314                 return true;
315         }
316         return false;
317 #endif
318 }
319
320 /* -------------------------------------------------------------------------- */
321
322 /* IPIs. */
323
324 #if defined(__NetBSD__)
325
326 #include <sys/xcall.h>
327 #define OS_IPI_FUNC(func)       void func(void *arg, void *unused)
328
329 static inline void
330 os_ipi_unicast(os_cpu_t *cpu, void (*func)(void *, void *), void *arg)
331 {
332         xc_wait(xc_unicast(XC_HIGHPRI, func, arg, NULL, cpu));
333 }
334
335 static inline void
336 os_ipi_broadcast(void (*func)(void *, void *), void *arg)
337 {
338         xc_wait(xc_broadcast(0, func, arg, NULL));
339 }
340
341 static inline void
342 os_ipi_kickall(void)
343 {
344         /*
345          * XXX: this is probably too expensive. NetBSD should have a dummy
346          * interrupt handler that just IRETs without doing anything.
347          */
348         pmap_tlb_shootdown(pmap_kernel(), -1, PTE_G, TLBSHOOT_NVMM);
349 }
350
351 #elif defined(__DragonFly__)
352
353 #include <sys/thread2.h>
354 #define OS_IPI_FUNC(func)       void func(void *arg)
355
356 static inline void
357 os_ipi_unicast(os_cpu_t *cpu, void (*func)(void *), void *arg)
358 {
359         int seq;
360
361         seq = lwkt_send_ipiq(cpu, func, arg);
362         lwkt_wait_ipiq(cpu, seq);
363 }
364
365 static inline void
366 os_ipi_broadcast(void (*func)(void *), void *arg)
367 {
368         cpumask_t mask;
369         int i;
370
371         for (i = 0; i < ncpus; i++) {
372                 CPUMASK_ASSBIT(mask, i);
373                 lwkt_cpusync_simple(mask, func, arg);
374         }
375 }
376
377 /*
378  * On DragonFly, no need to bind the thread, because any normal kernel
379  * thread will not migrate to another CPU or be preempted (except by an
380  * interrupt thread).
381  */
382 #define curlwp_bind()           ((int)0)
383 #define curlwp_bindx(bound)     /* nothing */
384
385 #endif /* __NetBSD__ */
386
387 #endif /* _NVMM_OS_H_ */