1df3af4c9SAaron LI /*
2df3af4c9SAaron LI * Copyright (c) 2021 Maxime Villard, m00nbsd.net
3df3af4c9SAaron LI * All rights reserved.
4df3af4c9SAaron LI *
5df3af4c9SAaron LI * This code is part of the NVMM hypervisor.
6df3af4c9SAaron LI *
7df3af4c9SAaron LI * Redistribution and use in source and binary forms, with or without
8df3af4c9SAaron LI * modification, are permitted provided that the following conditions
9df3af4c9SAaron LI * are met:
10df3af4c9SAaron LI * 1. Redistributions of source code must retain the above copyright
11df3af4c9SAaron LI * notice, this list of conditions and the following disclaimer.
12df3af4c9SAaron LI * 2. Redistributions in binary form must reproduce the above copyright
13df3af4c9SAaron LI * notice, this list of conditions and the following disclaimer in the
14df3af4c9SAaron LI * documentation and/or other materials provided with the distribution.
15df3af4c9SAaron LI *
16df3af4c9SAaron LI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17df3af4c9SAaron LI * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18df3af4c9SAaron LI * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19df3af4c9SAaron LI * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20df3af4c9SAaron LI * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21df3af4c9SAaron LI * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22df3af4c9SAaron LI * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23df3af4c9SAaron LI * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24df3af4c9SAaron LI * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25df3af4c9SAaron LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26df3af4c9SAaron LI * SUCH DAMAGE.
27df3af4c9SAaron LI */
28df3af4c9SAaron LI
29df3af4c9SAaron LI #include <sys/param.h>
30df3af4c9SAaron LI #include <sys/systm.h>
31df3af4c9SAaron LI #include <sys/kernel.h>
32df3af4c9SAaron LI #include <sys/mman.h>
33df3af4c9SAaron LI
34*8a0a54bfSAaron LI #include "nvmm.h"
35df3af4c9SAaron LI #include "nvmm_os.h"
36*8a0a54bfSAaron LI #include "nvmm_internal.h"
37df3af4c9SAaron LI
38df3af4c9SAaron LI os_vmspace_t *
os_vmspace_create(vaddr_t vmin,vaddr_t vmax)39df3af4c9SAaron LI os_vmspace_create(vaddr_t vmin, vaddr_t vmax)
40df3af4c9SAaron LI {
41df3af4c9SAaron LI return uvmspace_alloc(vmin, vmax, false);
42df3af4c9SAaron LI }
43df3af4c9SAaron LI
44df3af4c9SAaron LI void
os_vmspace_destroy(os_vmspace_t * vm)45df3af4c9SAaron LI os_vmspace_destroy(os_vmspace_t *vm)
46df3af4c9SAaron LI {
47df3af4c9SAaron LI uvmspace_free(vm);
48df3af4c9SAaron LI }
49df3af4c9SAaron LI
50df3af4c9SAaron LI int
os_vmspace_fault(os_vmspace_t * vm,vaddr_t va,vm_prot_t prot)51df3af4c9SAaron LI os_vmspace_fault(os_vmspace_t *vm, vaddr_t va, vm_prot_t prot)
52df3af4c9SAaron LI {
53df3af4c9SAaron LI return uvm_fault(&vm->vm_map, va, prot);
54df3af4c9SAaron LI }
55df3af4c9SAaron LI
56df3af4c9SAaron LI os_vmobj_t *
os_vmobj_create(voff_t size)57df3af4c9SAaron LI os_vmobj_create(voff_t size)
58df3af4c9SAaron LI {
59df3af4c9SAaron LI return uao_create(size, 0);
60df3af4c9SAaron LI }
61df3af4c9SAaron LI
62df3af4c9SAaron LI void
os_vmobj_ref(os_vmobj_t * vmobj)63df3af4c9SAaron LI os_vmobj_ref(os_vmobj_t *vmobj)
64df3af4c9SAaron LI {
65df3af4c9SAaron LI uao_reference(vmobj);
66df3af4c9SAaron LI }
67df3af4c9SAaron LI
68df3af4c9SAaron LI void
os_vmobj_rel(os_vmobj_t * vmobj)69df3af4c9SAaron LI os_vmobj_rel(os_vmobj_t *vmobj)
70df3af4c9SAaron LI {
71df3af4c9SAaron LI uao_detach(vmobj);
72df3af4c9SAaron LI }
73df3af4c9SAaron LI
74df3af4c9SAaron LI int
os_vmobj_map(struct vm_map * map,vaddr_t * addr,vsize_t size,os_vmobj_t * vmobj,voff_t offset,bool wired,bool fixed,bool shared,int prot,int maxprot)75df3af4c9SAaron LI os_vmobj_map(struct vm_map *map, vaddr_t *addr, vsize_t size, os_vmobj_t *vmobj,
76df3af4c9SAaron LI voff_t offset, bool wired, bool fixed, bool shared, int prot, int maxprot)
77df3af4c9SAaron LI {
78df3af4c9SAaron LI uvm_flag_t uflags, uprot, umaxprot;
79df3af4c9SAaron LI int error;
80df3af4c9SAaron LI
81df3af4c9SAaron LI /* Convert prot. */
82df3af4c9SAaron LI uprot = 0;
83df3af4c9SAaron LI if (prot & PROT_READ)
84df3af4c9SAaron LI uprot |= UVM_PROT_R;
85df3af4c9SAaron LI if (prot & PROT_WRITE)
86df3af4c9SAaron LI uprot |= UVM_PROT_W;
87df3af4c9SAaron LI if (prot & PROT_EXEC)
88df3af4c9SAaron LI uprot |= UVM_PROT_X;
89df3af4c9SAaron LI
90df3af4c9SAaron LI /* Convert maxprot. */
91df3af4c9SAaron LI umaxprot = 0;
92df3af4c9SAaron LI if (maxprot & PROT_READ)
93df3af4c9SAaron LI umaxprot |= UVM_PROT_R;
94df3af4c9SAaron LI if (maxprot & PROT_WRITE)
95df3af4c9SAaron LI umaxprot |= UVM_PROT_W;
96df3af4c9SAaron LI if (maxprot & PROT_EXEC)
97df3af4c9SAaron LI umaxprot |= UVM_PROT_X;
98df3af4c9SAaron LI
99df3af4c9SAaron LI uflags = UVM_MAPFLAG(uprot, umaxprot,
100df3af4c9SAaron LI shared ? UVM_INH_SHARE : UVM_INH_NONE, UVM_ADV_RANDOM,
101df3af4c9SAaron LI fixed ? (UVM_FLAG_FIXED | UVM_FLAG_UNMAP) : 0);
102df3af4c9SAaron LI
103df3af4c9SAaron LI if (!fixed) {
104df3af4c9SAaron LI /* Need to provide a hint. */
105df3af4c9SAaron LI if (map == os_curproc_map) {
106df3af4c9SAaron LI *addr = curproc->p_emul->e_vm_default_addr(curproc,
107df3af4c9SAaron LI (vaddr_t)curproc->p_vmspace->vm_daddr, size,
108df3af4c9SAaron LI curproc->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN);
109df3af4c9SAaron LI } else {
110df3af4c9SAaron LI *addr = 0;
111df3af4c9SAaron LI }
112df3af4c9SAaron LI }
113df3af4c9SAaron LI
114df3af4c9SAaron LI /* Get a reference to the object. */
115df3af4c9SAaron LI os_vmobj_ref(vmobj);
116df3af4c9SAaron LI
117df3af4c9SAaron LI /*
118df3af4c9SAaron LI * Map the object. This consumes the reference on success only. On
119df3af4c9SAaron LI * failure we must drop the reference manually.
120df3af4c9SAaron LI */
121df3af4c9SAaron LI error = uvm_map(map, addr, size, vmobj, offset, 0, uflags);
122df3af4c9SAaron LI if (error) {
123df3af4c9SAaron LI /* Drop the ref. */
124df3af4c9SAaron LI os_vmobj_rel(vmobj);
125df3af4c9SAaron LI return error;
126df3af4c9SAaron LI }
127df3af4c9SAaron LI
128df3af4c9SAaron LI if (wired) {
129df3af4c9SAaron LI error = uvm_map_pageable(map, *addr, *addr + size, false, 0);
130df3af4c9SAaron LI if (error) {
131df3af4c9SAaron LI os_vmobj_unmap(map, *addr, *addr + size, false);
132df3af4c9SAaron LI return error;
133df3af4c9SAaron LI }
134df3af4c9SAaron LI }
135df3af4c9SAaron LI
136df3af4c9SAaron LI return 0;
137df3af4c9SAaron LI }
138df3af4c9SAaron LI
139df3af4c9SAaron LI void
os_vmobj_unmap(struct vm_map * map,vaddr_t start,vaddr_t end,bool wired __unused)140df3af4c9SAaron LI os_vmobj_unmap(struct vm_map *map, vaddr_t start, vaddr_t end,
141df3af4c9SAaron LI bool wired __unused)
142df3af4c9SAaron LI {
143df3af4c9SAaron LI uvm_unmap(map, start, end);
144df3af4c9SAaron LI }
145df3af4c9SAaron LI
146df3af4c9SAaron LI void *
os_pagemem_zalloc(size_t size)147df3af4c9SAaron LI os_pagemem_zalloc(size_t size)
148df3af4c9SAaron LI {
149df3af4c9SAaron LI void *ret;
150df3af4c9SAaron LI
151df3af4c9SAaron LI ret = (void *)uvm_km_alloc(kernel_map, roundup(size, PAGE_SIZE), 0,
152df3af4c9SAaron LI UVM_KMF_WIRED | UVM_KMF_ZERO);
153df3af4c9SAaron LI
154df3af4c9SAaron LI OS_ASSERT((uintptr_t)ret % PAGE_SIZE == 0);
155df3af4c9SAaron LI
156df3af4c9SAaron LI return ret;
157df3af4c9SAaron LI }
158df3af4c9SAaron LI
159df3af4c9SAaron LI void
os_pagemem_free(void * ptr,size_t size)160df3af4c9SAaron LI os_pagemem_free(void *ptr, size_t size)
161df3af4c9SAaron LI {
162df3af4c9SAaron LI uvm_km_free(kernel_map, (vaddr_t)ptr, roundup(size, PAGE_SIZE),
163df3af4c9SAaron LI UVM_KMF_WIRED);
164df3af4c9SAaron LI }
165df3af4c9SAaron LI
166df3af4c9SAaron LI paddr_t
os_pa_zalloc(void)167df3af4c9SAaron LI os_pa_zalloc(void)
168df3af4c9SAaron LI {
169df3af4c9SAaron LI struct vm_page *pg;
170df3af4c9SAaron LI
171df3af4c9SAaron LI pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
172df3af4c9SAaron LI
173df3af4c9SAaron LI return VM_PAGE_TO_PHYS(pg);
174df3af4c9SAaron LI }
175df3af4c9SAaron LI
176df3af4c9SAaron LI void
os_pa_free(paddr_t pa)177df3af4c9SAaron LI os_pa_free(paddr_t pa)
178df3af4c9SAaron LI {
179df3af4c9SAaron LI uvm_pagefree(PHYS_TO_VM_PAGE(pa));
180df3af4c9SAaron LI }
181df3af4c9SAaron LI
182df3af4c9SAaron LI int
os_contigpa_zalloc(paddr_t * pa,vaddr_t * va,size_t npages)183df3af4c9SAaron LI os_contigpa_zalloc(paddr_t *pa, vaddr_t *va, size_t npages)
184df3af4c9SAaron LI {
185df3af4c9SAaron LI struct pglist pglist;
186df3af4c9SAaron LI paddr_t _pa;
187df3af4c9SAaron LI vaddr_t _va;
188df3af4c9SAaron LI size_t i;
189df3af4c9SAaron LI int ret;
190df3af4c9SAaron LI
191df3af4c9SAaron LI ret = uvm_pglistalloc(npages * PAGE_SIZE, 0, ~0UL, PAGE_SIZE, 0,
192df3af4c9SAaron LI &pglist, 1, 0);
193df3af4c9SAaron LI if (ret != 0)
194df3af4c9SAaron LI return ENOMEM;
195df3af4c9SAaron LI _pa = VM_PAGE_TO_PHYS(TAILQ_FIRST(&pglist));
196df3af4c9SAaron LI _va = uvm_km_alloc(kernel_map, npages * PAGE_SIZE, 0,
197df3af4c9SAaron LI UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
198df3af4c9SAaron LI if (_va == 0)
199df3af4c9SAaron LI goto error;
200df3af4c9SAaron LI
201df3af4c9SAaron LI for (i = 0; i < npages; i++) {
202df3af4c9SAaron LI pmap_kenter_pa(_va + i * PAGE_SIZE, _pa + i * PAGE_SIZE,
203df3af4c9SAaron LI VM_PROT_READ | VM_PROT_WRITE, PMAP_WRITE_BACK);
204df3af4c9SAaron LI }
205df3af4c9SAaron LI pmap_update(pmap_kernel());
206df3af4c9SAaron LI
207df3af4c9SAaron LI memset((void *)_va, 0, npages * PAGE_SIZE);
208df3af4c9SAaron LI
209df3af4c9SAaron LI *pa = _pa;
210df3af4c9SAaron LI *va = _va;
211df3af4c9SAaron LI return 0;
212df3af4c9SAaron LI
213df3af4c9SAaron LI error:
214df3af4c9SAaron LI for (i = 0; i < npages; i++) {
215df3af4c9SAaron LI uvm_pagefree(PHYS_TO_VM_PAGE(_pa + i * PAGE_SIZE));
216df3af4c9SAaron LI }
217df3af4c9SAaron LI return ENOMEM;
218df3af4c9SAaron LI }
219df3af4c9SAaron LI
220df3af4c9SAaron LI void
os_contigpa_free(paddr_t pa,vaddr_t va,size_t npages)221df3af4c9SAaron LI os_contigpa_free(paddr_t pa, vaddr_t va, size_t npages)
222df3af4c9SAaron LI {
223df3af4c9SAaron LI size_t i;
224df3af4c9SAaron LI
225df3af4c9SAaron LI pmap_kremove(va, npages * PAGE_SIZE);
226df3af4c9SAaron LI pmap_update(pmap_kernel());
227df3af4c9SAaron LI uvm_km_free(kernel_map, va, npages * PAGE_SIZE, UVM_KMF_VAONLY);
228df3af4c9SAaron LI for (i = 0; i < npages; i++) {
229df3af4c9SAaron LI uvm_pagefree(PHYS_TO_VM_PAGE(pa + i * PAGE_SIZE));
230df3af4c9SAaron LI }
231df3af4c9SAaron LI }
232*8a0a54bfSAaron LI
233*8a0a54bfSAaron LI /* -------------------------------------------------------------------------- */
234*8a0a54bfSAaron LI
235*8a0a54bfSAaron LI #include <sys/conf.h>
236*8a0a54bfSAaron LI #include <sys/device.h>
237*8a0a54bfSAaron LI #include <sys/file.h>
238*8a0a54bfSAaron LI #include <sys/filedesc.h>
239*8a0a54bfSAaron LI #include <sys/module.h>
240*8a0a54bfSAaron LI
241*8a0a54bfSAaron LI #include "ioconf.h"
242*8a0a54bfSAaron LI
243*8a0a54bfSAaron LI static dev_type_open(nbsd_nvmm_open);
244*8a0a54bfSAaron LI static int nbsd_nvmm_ioctl(file_t *, u_long, void *);
245*8a0a54bfSAaron LI static int nbsd_nvmm_close(file_t *);
246*8a0a54bfSAaron LI
247*8a0a54bfSAaron LI const struct cdevsw nvmm_cdevsw = {
248*8a0a54bfSAaron LI .d_open = nbsd_nvmm_open,
249*8a0a54bfSAaron LI .d_close = noclose,
250*8a0a54bfSAaron LI .d_read = noread,
251*8a0a54bfSAaron LI .d_write = nowrite,
252*8a0a54bfSAaron LI .d_ioctl = noioctl,
253*8a0a54bfSAaron LI .d_stop = nostop,
254*8a0a54bfSAaron LI .d_tty = notty,
255*8a0a54bfSAaron LI .d_poll = nopoll,
256*8a0a54bfSAaron LI .d_mmap = nommap,
257*8a0a54bfSAaron LI .d_kqfilter = nokqfilter,
258*8a0a54bfSAaron LI .d_discard = nodiscard,
259*8a0a54bfSAaron LI .d_flag = D_OTHER | D_MPSAFE
260*8a0a54bfSAaron LI };
261*8a0a54bfSAaron LI
262*8a0a54bfSAaron LI static const struct fileops nvmm_fileops = {
263*8a0a54bfSAaron LI .fo_read = fbadop_read,
264*8a0a54bfSAaron LI .fo_write = fbadop_write,
265*8a0a54bfSAaron LI .fo_ioctl = nbsd_nvmm_ioctl,
266*8a0a54bfSAaron LI .fo_fcntl = fnullop_fcntl,
267*8a0a54bfSAaron LI .fo_poll = fnullop_poll,
268*8a0a54bfSAaron LI .fo_stat = fbadop_stat,
269*8a0a54bfSAaron LI .fo_close = nbsd_nvmm_close,
270*8a0a54bfSAaron LI .fo_kqfilter = fnullop_kqfilter,
271*8a0a54bfSAaron LI .fo_restart = fnullop_restart,
272*8a0a54bfSAaron LI .fo_mmap = NULL,
273*8a0a54bfSAaron LI };
274*8a0a54bfSAaron LI
275*8a0a54bfSAaron LI static int
nbsd_nvmm_open(dev_t dev,int flags,int type,struct lwp * l)276*8a0a54bfSAaron LI nbsd_nvmm_open(dev_t dev, int flags, int type, struct lwp *l)
277*8a0a54bfSAaron LI {
278*8a0a54bfSAaron LI struct nvmm_owner *owner;
279*8a0a54bfSAaron LI struct file *fp;
280*8a0a54bfSAaron LI int error, fd;
281*8a0a54bfSAaron LI
282*8a0a54bfSAaron LI if (__predict_false(nvmm_impl == NULL))
283*8a0a54bfSAaron LI return ENXIO;
284*8a0a54bfSAaron LI if (minor(dev) != 0)
285*8a0a54bfSAaron LI return EXDEV;
286*8a0a54bfSAaron LI if (!(flags & O_CLOEXEC))
287*8a0a54bfSAaron LI return EINVAL;
288*8a0a54bfSAaron LI error = fd_allocfile(&fp, &fd);
289*8a0a54bfSAaron LI if (error)
290*8a0a54bfSAaron LI return error;
291*8a0a54bfSAaron LI
292*8a0a54bfSAaron LI if (OFLAGS(flags) & O_WRONLY) {
293*8a0a54bfSAaron LI owner = &nvmm_root_owner;
294*8a0a54bfSAaron LI } else {
295*8a0a54bfSAaron LI owner = os_mem_alloc(sizeof(*owner));
296*8a0a54bfSAaron LI owner->pid = l->l_proc->p_pid;
297*8a0a54bfSAaron LI }
298*8a0a54bfSAaron LI
299*8a0a54bfSAaron LI return fd_clone(fp, fd, flags, &nvmm_fileops, owner);
300*8a0a54bfSAaron LI }
301*8a0a54bfSAaron LI
302*8a0a54bfSAaron LI static int
nbsd_nvmm_ioctl(file_t * fp,u_long cmd,void * data)303*8a0a54bfSAaron LI nbsd_nvmm_ioctl(file_t *fp, u_long cmd, void *data)
304*8a0a54bfSAaron LI {
305*8a0a54bfSAaron LI struct nvmm_owner *owner = fp->f_data;
306*8a0a54bfSAaron LI
307*8a0a54bfSAaron LI OS_ASSERT(owner != NULL);
308*8a0a54bfSAaron LI
309*8a0a54bfSAaron LI return nvmm_ioctl(owner, cmd, data);
310*8a0a54bfSAaron LI }
311*8a0a54bfSAaron LI
312*8a0a54bfSAaron LI static int
nbsd_nvmm_close(file_t * fp)313*8a0a54bfSAaron LI nbsd_nvmm_close(file_t *fp)
314*8a0a54bfSAaron LI {
315*8a0a54bfSAaron LI struct nvmm_owner *owner = fp->f_data;
316*8a0a54bfSAaron LI
317*8a0a54bfSAaron LI OS_ASSERT(owner != NULL);
318*8a0a54bfSAaron LI nvmm_kill_machines(owner);
319*8a0a54bfSAaron LI if (owner != &nvmm_root_owner) {
320*8a0a54bfSAaron LI os_mem_free(owner, sizeof(*owner));
321*8a0a54bfSAaron LI }
322*8a0a54bfSAaron LI fp->f_data = NULL;
323*8a0a54bfSAaron LI
324*8a0a54bfSAaron LI return 0;
325*8a0a54bfSAaron LI }
326*8a0a54bfSAaron LI
327*8a0a54bfSAaron LI /* -------------------------------------------------------------------------- */
328*8a0a54bfSAaron LI
329*8a0a54bfSAaron LI static int nvmm_match(device_t, cfdata_t, void *);
330*8a0a54bfSAaron LI static void nvmm_attach(device_t, device_t, void *);
331*8a0a54bfSAaron LI static int nvmm_detach(device_t, int);
332*8a0a54bfSAaron LI
333*8a0a54bfSAaron LI extern struct cfdriver nvmm_cd;
334*8a0a54bfSAaron LI
335*8a0a54bfSAaron LI CFATTACH_DECL_NEW(nvmm, 0, nvmm_match, nvmm_attach, nvmm_detach, NULL);
336*8a0a54bfSAaron LI
337*8a0a54bfSAaron LI static struct cfdata nvmm_cfdata[] = {
338*8a0a54bfSAaron LI {
339*8a0a54bfSAaron LI .cf_name = "nvmm",
340*8a0a54bfSAaron LI .cf_atname = "nvmm",
341*8a0a54bfSAaron LI .cf_unit = 0,
342*8a0a54bfSAaron LI .cf_fstate = FSTATE_STAR,
343*8a0a54bfSAaron LI .cf_loc = NULL,
344*8a0a54bfSAaron LI .cf_flags = 0,
345*8a0a54bfSAaron LI .cf_pspec = NULL,
346*8a0a54bfSAaron LI },
347*8a0a54bfSAaron LI { NULL, NULL, 0, FSTATE_NOTFOUND, NULL, 0, NULL }
348*8a0a54bfSAaron LI };
349*8a0a54bfSAaron LI
350*8a0a54bfSAaron LI static int
nvmm_match(device_t self,cfdata_t cfdata,void * arg)351*8a0a54bfSAaron LI nvmm_match(device_t self, cfdata_t cfdata, void *arg)
352*8a0a54bfSAaron LI {
353*8a0a54bfSAaron LI return 1;
354*8a0a54bfSAaron LI }
355*8a0a54bfSAaron LI
356*8a0a54bfSAaron LI static void
nvmm_attach(device_t parent,device_t self,void * aux)357*8a0a54bfSAaron LI nvmm_attach(device_t parent, device_t self, void *aux)
358*8a0a54bfSAaron LI {
359*8a0a54bfSAaron LI int error;
360*8a0a54bfSAaron LI
361*8a0a54bfSAaron LI error = nvmm_init();
362*8a0a54bfSAaron LI if (error)
363*8a0a54bfSAaron LI panic("%s: impossible", __func__);
364*8a0a54bfSAaron LI aprint_normal_dev(self, "attached, using backend %s\n",
365*8a0a54bfSAaron LI nvmm_impl->name);
366*8a0a54bfSAaron LI }
367*8a0a54bfSAaron LI
368*8a0a54bfSAaron LI static int
nvmm_detach(device_t self,int flags)369*8a0a54bfSAaron LI nvmm_detach(device_t self, int flags)
370*8a0a54bfSAaron LI {
371*8a0a54bfSAaron LI if (os_atomic_load_uint(&nmachines) > 0)
372*8a0a54bfSAaron LI return EBUSY;
373*8a0a54bfSAaron LI nvmm_fini();
374*8a0a54bfSAaron LI return 0;
375*8a0a54bfSAaron LI }
376*8a0a54bfSAaron LI
377*8a0a54bfSAaron LI void
nvmmattach(int nunits)378*8a0a54bfSAaron LI nvmmattach(int nunits)
379*8a0a54bfSAaron LI {
380*8a0a54bfSAaron LI /* nothing */
381*8a0a54bfSAaron LI }
382*8a0a54bfSAaron LI
383*8a0a54bfSAaron LI MODULE(MODULE_CLASS_DRIVER, nvmm, NULL);
384*8a0a54bfSAaron LI
385*8a0a54bfSAaron LI #if defined(_MODULE)
386*8a0a54bfSAaron LI CFDRIVER_DECL(nvmm, DV_VIRTUAL, NULL);
387*8a0a54bfSAaron LI #endif
388*8a0a54bfSAaron LI
389*8a0a54bfSAaron LI static int
nvmm_modcmd(modcmd_t cmd,void * arg)390*8a0a54bfSAaron LI nvmm_modcmd(modcmd_t cmd, void *arg)
391*8a0a54bfSAaron LI {
392*8a0a54bfSAaron LI #if defined(_MODULE)
393*8a0a54bfSAaron LI devmajor_t bmajor = NODEVMAJOR;
394*8a0a54bfSAaron LI devmajor_t cmajor = 345;
395*8a0a54bfSAaron LI #endif
396*8a0a54bfSAaron LI int error;
397*8a0a54bfSAaron LI
398*8a0a54bfSAaron LI switch (cmd) {
399*8a0a54bfSAaron LI case MODULE_CMD_INIT:
400*8a0a54bfSAaron LI if (nvmm_ident() == NULL) {
401*8a0a54bfSAaron LI aprint_error("%s: cpu not supported\n",
402*8a0a54bfSAaron LI nvmm_cd.cd_name);
403*8a0a54bfSAaron LI return ENOTSUP;
404*8a0a54bfSAaron LI }
405*8a0a54bfSAaron LI #if defined(_MODULE)
406*8a0a54bfSAaron LI error = config_cfdriver_attach(&nvmm_cd);
407*8a0a54bfSAaron LI if (error)
408*8a0a54bfSAaron LI return error;
409*8a0a54bfSAaron LI #endif
410*8a0a54bfSAaron LI error = config_cfattach_attach(nvmm_cd.cd_name, &nvmm_ca);
411*8a0a54bfSAaron LI if (error) {
412*8a0a54bfSAaron LI config_cfdriver_detach(&nvmm_cd);
413*8a0a54bfSAaron LI aprint_error("%s: config_cfattach_attach failed\n",
414*8a0a54bfSAaron LI nvmm_cd.cd_name);
415*8a0a54bfSAaron LI return error;
416*8a0a54bfSAaron LI }
417*8a0a54bfSAaron LI
418*8a0a54bfSAaron LI error = config_cfdata_attach(nvmm_cfdata, 1);
419*8a0a54bfSAaron LI if (error) {
420*8a0a54bfSAaron LI config_cfattach_detach(nvmm_cd.cd_name, &nvmm_ca);
421*8a0a54bfSAaron LI config_cfdriver_detach(&nvmm_cd);
422*8a0a54bfSAaron LI aprint_error("%s: unable to register cfdata\n",
423*8a0a54bfSAaron LI nvmm_cd.cd_name);
424*8a0a54bfSAaron LI return error;
425*8a0a54bfSAaron LI }
426*8a0a54bfSAaron LI
427*8a0a54bfSAaron LI if (config_attach_pseudo(nvmm_cfdata) == NULL) {
428*8a0a54bfSAaron LI aprint_error("%s: config_attach_pseudo failed\n",
429*8a0a54bfSAaron LI nvmm_cd.cd_name);
430*8a0a54bfSAaron LI config_cfattach_detach(nvmm_cd.cd_name, &nvmm_ca);
431*8a0a54bfSAaron LI config_cfdriver_detach(&nvmm_cd);
432*8a0a54bfSAaron LI return ENXIO;
433*8a0a54bfSAaron LI }
434*8a0a54bfSAaron LI
435*8a0a54bfSAaron LI #if defined(_MODULE)
436*8a0a54bfSAaron LI /* mknod /dev/nvmm c 345 0 */
437*8a0a54bfSAaron LI error = devsw_attach(nvmm_cd.cd_name, NULL, &bmajor,
438*8a0a54bfSAaron LI &nvmm_cdevsw, &cmajor);
439*8a0a54bfSAaron LI if (error) {
440*8a0a54bfSAaron LI aprint_error("%s: unable to register devsw\n",
441*8a0a54bfSAaron LI nvmm_cd.cd_name);
442*8a0a54bfSAaron LI config_cfattach_detach(nvmm_cd.cd_name, &nvmm_ca);
443*8a0a54bfSAaron LI config_cfdriver_detach(&nvmm_cd);
444*8a0a54bfSAaron LI return error;
445*8a0a54bfSAaron LI }
446*8a0a54bfSAaron LI #endif
447*8a0a54bfSAaron LI return 0;
448*8a0a54bfSAaron LI case MODULE_CMD_FINI:
449*8a0a54bfSAaron LI error = config_cfdata_detach(nvmm_cfdata);
450*8a0a54bfSAaron LI if (error)
451*8a0a54bfSAaron LI return error;
452*8a0a54bfSAaron LI error = config_cfattach_detach(nvmm_cd.cd_name, &nvmm_ca);
453*8a0a54bfSAaron LI if (error)
454*8a0a54bfSAaron LI return error;
455*8a0a54bfSAaron LI #if defined(_MODULE)
456*8a0a54bfSAaron LI config_cfdriver_detach(&nvmm_cd);
457*8a0a54bfSAaron LI devsw_detach(NULL, &nvmm_cdevsw);
458*8a0a54bfSAaron LI #endif
459*8a0a54bfSAaron LI return 0;
460*8a0a54bfSAaron LI case MODULE_CMD_AUTOUNLOAD:
461*8a0a54bfSAaron LI return EBUSY;
462*8a0a54bfSAaron LI default:
463*8a0a54bfSAaron LI return ENOTTY;
464*8a0a54bfSAaron LI }
465*8a0a54bfSAaron LI }
466