kernel - Refactor phys_avail[] and dump_avail[]
[dragonfly.git] / sys / platform / vkernel64 / platform / init.c
1 /*
2  * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include <sys/types.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/stat.h>
39 #include <sys/mman.h>
40 #include <sys/cons.h>
41 #include <sys/random.h>
42 #include <sys/vkernel.h>
43 #include <sys/tls.h>
44 #include <sys/reboot.h>
45 #include <sys/proc.h>
46 #include <sys/msgbuf.h>
47 #include <sys/vmspace.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/sysctl.h>
51 #include <sys/un.h>
52 #include <vm/vm_page.h>
53 #include <vm/vm_map.h>
54 #include <sys/mplock2.h>
55 #include <sys/wait.h>
56 #include <sys/vmm.h>
57
58 #include <machine/cpu.h>
59 #include <machine/globaldata.h>
60 #include <machine/tls.h>
61 #include <machine/md_var.h>
62 #include <machine/vmparam.h>
63 #include <cpu/specialreg.h>
64
65 #include <net/if.h>
66 #include <net/if_arp.h>
67 #include <net/ethernet.h>
68 #include <net/bridge/if_bridgevar.h>
69 #include <netinet/in.h>
70 #include <arpa/inet.h>
71 #include <net/if_var.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <stdarg.h>
76 #include <stdbool.h>
77 #include <unistd.h>
78 #include <fcntl.h>
79 #include <string.h>
80 #include <err.h>
81 #include <errno.h>
82 #include <assert.h>
83 #include <sysexits.h>
84
85 #define EX_VKERNEL_REBOOT       32
86
87 vm_phystable_t phys_avail[16];
88 vm_paddr_t Maxmem;
89 vm_paddr_t Maxmem_bytes;
90 long physmem;
91 int MemImageFd = -1;
92 struct vkdisk_info DiskInfo[VKDISK_MAX];
93 int DiskNum;
94 struct vknetif_info NetifInfo[VKNETIF_MAX];
95 int NetifNum;
96 char *pid_file;
97 vm_offset_t KvaStart;
98 vm_offset_t KvaEnd;
99 vm_offset_t KvaSize;
100 vm_offset_t virtual_start;
101 vm_offset_t virtual_end;
102 vm_offset_t virtual2_start;
103 vm_offset_t virtual2_end;
104 vm_offset_t kernel_vm_end;
105 vm_offset_t crashdumpmap;
106 vm_offset_t clean_sva;
107 vm_offset_t clean_eva;
108 struct msgbuf *msgbufp;
109 caddr_t ptvmmap;
110 vpte_t  *KernelPTD;
111 vpte_t  *KernelPTA;     /* Warning: Offset for direct VA translation */
112 void *dmap_min_address;
113 void *vkernel_stack;
114 u_int cpu_feature;      /* XXX */
115 int tsc_present;
116 int tsc_invariant;
117 int tsc_mpsync;
118 int64_t tsc_frequency;
119 int optcpus;            /* number of cpus - see mp_start() */
120 int lwp_cpu_lock;       /* if/how to lock virtual CPUs to real CPUs */
121 int real_ncpus;         /* number of real CPUs */
122 int next_cpu;           /* next real CPU to lock a virtual CPU to */
123 int vkernel_b_arg;      /* no of logical CPU bits - only SMP */
124 int vkernel_B_arg;      /* no of core bits - only SMP */
125 int vmm_enabled;        /* VMM HW assisted enable */
126 struct privatespace *CPU_prvspace;
127
128 extern uint64_t KPML4phys;      /* phys addr of kernel level 4 */
129
130 static struct trapframe proc0_tf;
131 static void *proc0paddr;
132
133 static void init_sys_memory(char *imageFile);
134 static void init_kern_memory(void);
135 static void init_kern_memory_vmm(void);
136 static void init_globaldata(void);
137 static void init_vkernel(void);
138 static void init_disk(char **diskExp, int *diskFlags, int diskFileNum, enum vkdisk_type type);
139 static void init_netif(char *netifExp[], int netifFileNum);
140 static void writepid(void);
141 static void cleanpid(void);
142 static int unix_connect(const char *path);
143 static void usage_err(const char *ctl, ...);
144 static void usage_help(_Bool);
145 static void init_locks(void);
146 static void handle_term(int);
147
148 pid_t childpid;
149
150 static int save_ac;
151 static char **save_av;
152
153 /*
154  * Kernel startup for virtual kernels - standard main()
155  */
156 int
157 main(int ac, char **av)
158 {
159         char *memImageFile = NULL;
160         char *netifFile[VKNETIF_MAX];
161         char *diskFile[VKDISK_MAX];
162         char *cdFile[VKDISK_MAX];
163         char *suffix;
164         char *endp;
165         char *tmp;
166         char *tok;
167         int diskFlags[VKDISK_MAX];
168         int netifFileNum = 0;
169         int diskFileNum = 0;
170         int cdFileNum = 0;
171         int bootOnDisk = -1;    /* set below to vcd (0) or vkd (1) */
172         int c;
173         int i;
174         int j;
175         int n;
176         int isq;
177         int pos;
178         int eflag;
179         int dflag = 0;          /* disable vmm */
180         int real_vkernel_enable;
181         int supports_sse;
182         uint32_t mxcsr_mask;
183         size_t vsize;
184         size_t msize;
185         size_t kenv_size;
186         size_t kenv_size2;
187         int status;
188         struct sigaction sa;
189
190         /*
191          * Currently a bad hack but rtld-elf needs LD_SHAREDLIB_BASE to
192          * be set to force it to mmap() shared libraries into low memory,
193          * so our module loader can link against the related symbols.
194          */
195         if (getenv("LD_SHAREDLIB_BASE") == NULL) {
196                 setenv("LD_SHAREDLIB_BASE", "0x10000000", 1);
197                 execv(av[0], av);
198                 fprintf(stderr, "Must run %s with full path\n", av[0]);
199                 exit(1);
200         }
201
202         while ((childpid = fork()) != 0) {
203                 /* Ignore signals */
204                 bzero(&sa, sizeof(sa));
205                 sigemptyset(&sa.sa_mask);
206                 sa.sa_handler = SIG_IGN;
207                 sigaction(SIGINT, &sa, NULL);
208                 sigaction(SIGQUIT, &sa, NULL);
209                 sigaction(SIGHUP, &sa, NULL);
210
211                 /*
212                  * Forward SIGTERM to the child so that
213                  * the shutdown process initiates correctly.
214                  */
215                 sa.sa_handler = handle_term;
216                 sigaction(SIGTERM, &sa, NULL);
217
218                 /*
219                  * Wait for child to terminate, exit if
220                  * someone stole our child.
221                  */
222                 while (waitpid(childpid, &status, 0) != childpid) {
223                         if (errno == ECHILD)
224                                 exit(1);
225                 }
226                 if (WEXITSTATUS(status) != EX_VKERNEL_REBOOT)
227                         return 0;
228         }
229
230         /*
231          * Starting for real
232          */
233         save_ac = ac;
234         save_av = av;
235         eflag = 0;
236         pos = 0;
237         kenv_size = 0;
238         /*
239          * Process options
240          */
241         kernel_mem_readonly = 1;
242         optcpus = 2;
243         vkernel_b_arg = 0;
244         vkernel_B_arg = 0;
245         lwp_cpu_lock = LCL_NONE;
246
247         real_vkernel_enable = 0;
248         vsize = sizeof(real_vkernel_enable);
249         sysctlbyname("vm.vkernel_enable", &real_vkernel_enable, &vsize, NULL,0);
250
251         if (real_vkernel_enable == 0) {
252                 errx(1, "vm.vkernel_enable is 0, must be set "
253                         "to 1 to execute a vkernel!");
254         }
255
256         real_ncpus = 1;
257         vsize = sizeof(real_ncpus);
258         sysctlbyname("hw.ncpu", &real_ncpus, &vsize, NULL, 0);
259
260         if (ac < 2)
261                 usage_help(false);
262
263         while ((c = getopt(ac, av, "c:hsvl:m:n:r:R:e:i:p:I:Ud")) != -1) {
264                 switch(c) {
265                 case 'd':
266                         dflag = 1;
267                         break;
268                 case 'e':
269                         /*
270                          * name=value:name=value:name=value...
271                          * name="value"...
272                          *
273                          * Allow values to be quoted but note that shells
274                          * may remove the quotes, so using this feature
275                          * to embed colons may require a backslash.
276                          */
277                         n = strlen(optarg);
278                         isq = 0;
279
280                         if (eflag == 0) {
281                                 kenv_size = n + 2;
282                                 kern_envp = malloc(kenv_size);
283                                 if (kern_envp == NULL)
284                                         errx(1, "Couldn't allocate %zd bytes for kern_envp", kenv_size);
285                         } else {
286                                 kenv_size2 = kenv_size + n + 1;
287                                 pos = kenv_size - 1;
288                                 if ((tmp = realloc(kern_envp, kenv_size2)) == NULL)
289                                         errx(1, "Couldn't reallocate %zd bytes for kern_envp", kenv_size2);
290                                 kern_envp = tmp;
291                                 kenv_size = kenv_size2;
292                         }
293
294                         for (i = 0, j = pos; i < n; ++i) {
295                                 if (optarg[i] == '"')
296                                         isq ^= 1;
297                                 else if (optarg[i] == '\'')
298                                         isq ^= 2;
299                                 else if (isq == 0 && optarg[i] == ':')
300                                         kern_envp[j++] = 0;
301                                 else
302                                         kern_envp[j++] = optarg[i];
303                         }
304                         kern_envp[j++] = 0;
305                         kern_envp[j++] = 0;
306                         eflag++;
307                         break;
308                 case 's':
309                         boothowto |= RB_SINGLE;
310                         break;
311                 case 'v':
312                         bootverbose = 1;
313                         break;
314                 case 'i':
315                         memImageFile = optarg;
316                         break;
317                 case 'I':
318                         if (netifFileNum < VKNETIF_MAX)
319                                 netifFile[netifFileNum++] = strdup(optarg);
320                         break;
321                 case 'r':
322                 case 'R':
323                         if (bootOnDisk < 0)
324                                 bootOnDisk = 1;
325                         if (diskFileNum + cdFileNum < VKDISK_MAX) {
326                                 diskFile[diskFileNum] = strdup(optarg);
327                                 diskFlags[diskFileNum] = (c == 'R');
328                                 ++diskFileNum;
329                         }
330                         break;
331                 case 'c':
332                         if (bootOnDisk < 0)
333                                 bootOnDisk = 0;
334                         if (diskFileNum + cdFileNum < VKDISK_MAX)
335                                 cdFile[cdFileNum++] = strdup(optarg);
336                         break;
337                 case 'm':
338                         Maxmem_bytes = strtoull(optarg, &suffix, 0);
339                         if (suffix) {
340                                 switch(*suffix) {
341                                 case 'g':
342                                 case 'G':
343                                         Maxmem_bytes <<= 30;
344                                         break;
345                                 case 'm':
346                                 case 'M':
347                                         Maxmem_bytes <<= 20;
348                                         break;
349                                 case 'k':
350                                 case 'K':
351                                         Maxmem_bytes <<= 10;
352                                         break;
353                                 default:
354                                         Maxmem_bytes = 0;
355                                         usage_err("Bad maxmem option");
356                                         /* NOT REACHED */
357                                         break;
358                                 }
359                         }
360                         break;
361                 case 'l':
362                         next_cpu = -1;
363                         if (strncmp("map", optarg, 3) == 0) {
364                                 lwp_cpu_lock = LCL_PER_CPU;
365                                 if (optarg[3] == ',') {
366                                         next_cpu = strtol(optarg+4, &endp, 0);
367                                         if (*endp != '\0')
368                                                 usage_err("Bad target CPU number at '%s'", endp);
369                                 } else {
370                                         next_cpu = 0;
371                                 }
372                                 if (next_cpu < 0 || next_cpu > real_ncpus - 1)
373                                         usage_err("Bad target CPU, valid range is 0-%d", real_ncpus - 1);
374                         } else if (strncmp("any", optarg, 3) == 0) {
375                                 lwp_cpu_lock = LCL_NONE;
376                         } else {
377                                 lwp_cpu_lock = LCL_SINGLE_CPU;
378                                 next_cpu = strtol(optarg, &endp, 0);
379                                 if (*endp != '\0')
380                                         usage_err("Bad target CPU number at '%s'", endp);
381                                 if (next_cpu < 0 || next_cpu > real_ncpus - 1)
382                                         usage_err("Bad target CPU, valid range is 0-%d", real_ncpus - 1);
383                         }
384                         break;
385                 case 'n':
386                         /*
387                          * This value is set up by mp_start(), don't just
388                          * set ncpus here.
389                          */
390                         tok = strtok(optarg, ":");
391                         optcpus = strtol(tok, NULL, 0);
392                         if (optcpus < 1 || optcpus > MAXCPU)
393                                 usage_err("Bad ncpus, valid range is 1-%d", MAXCPU);
394
395                         /* :lbits argument */
396                         tok = strtok(NULL, ":");
397                         if (tok != NULL) {
398                                 vkernel_b_arg = strtol(tok, NULL, 0);
399
400                                 /* :cbits argument */
401                                 tok = strtok(NULL, ":");
402                                 if (tok != NULL) {
403                                         vkernel_B_arg = strtol(tok, NULL, 0);
404                                 }
405
406                         }
407                         break;
408                 case 'p':
409                         pid_file = optarg;
410                         break;
411                 case 'U':
412                         kernel_mem_readonly = 0;
413                         break;
414                 case 'h':
415                         usage_help(true);
416                         break;
417                 default:
418                         usage_help(false);
419                 }
420         }
421
422         /*
423          * Check VMM presence
424          */
425         vsize = sizeof(vmm_enabled);
426         sysctlbyname("hw.vmm.enable", &vmm_enabled, &vsize, NULL, 0);
427         vmm_enabled = (vmm_enabled && !dflag);
428
429         writepid();
430         cpu_disable_intr();
431         if (vmm_enabled) {
432                 /* use a MAP_ANON directly */
433                 init_kern_memory_vmm();
434         } else {
435                 init_sys_memory(memImageFile);
436                 init_kern_memory();
437         }
438         init_globaldata();
439         init_vkernel();
440         setrealcpu();
441         init_kqueue();
442
443         vmm_guest = VMM_GUEST_VKERNEL;
444
445         /*
446          * Check TSC
447          */
448         vsize = sizeof(tsc_present);
449         sysctlbyname("hw.tsc_present", &tsc_present, &vsize, NULL, 0);
450         vsize = sizeof(tsc_invariant);
451         sysctlbyname("hw.tsc_invariant", &tsc_invariant, &vsize, NULL, 0);
452         vsize = sizeof(tsc_mpsync);
453         sysctlbyname("hw.tsc_mpsync", &tsc_mpsync, &vsize, NULL, 0);
454         vsize = sizeof(tsc_frequency);
455         sysctlbyname("hw.tsc_frequency", &tsc_frequency, &vsize, NULL, 0);
456         if (tsc_present)
457                 cpu_feature |= CPUID_TSC;
458
459         /*
460          * Check SSE
461          */
462         vsize = sizeof(supports_sse);
463         supports_sse = 0;
464         sysctlbyname("hw.instruction_sse", &supports_sse, &vsize, NULL, 0);
465         sysctlbyname("hw.mxcsr_mask", &mxcsr_mask, &msize, NULL, 0);
466         init_fpu(supports_sse);
467         if (supports_sse)
468                 cpu_feature |= CPUID_SSE | CPUID_FXSR;
469
470         /*
471          * We boot from the first installed disk.
472          */
473         if (bootOnDisk == 1) {
474                 init_disk(diskFile, diskFlags, diskFileNum, VKD_DISK);
475                 init_disk(cdFile, NULL, cdFileNum, VKD_CD);
476         } else {
477                 init_disk(cdFile, NULL, cdFileNum, VKD_CD);
478                 init_disk(diskFile, diskFlags, diskFileNum, VKD_DISK);
479         }
480
481         init_netif(netifFile, netifFileNum);
482         init_exceptions();
483         mi_startup();
484         /* NOT REACHED */
485         exit(EX_SOFTWARE);
486 }
487
488 /* SIGTERM handler */
489 static
490 void
491 handle_term(int sig)
492 {
493         kill(childpid, sig);
494 }
495
496 /*
497  * Initialize system memory.  This is the virtual kernel's 'RAM'.
498  */
499 static
500 void
501 init_sys_memory(char *imageFile)
502 {
503         struct stat st;
504         int i;
505         int fd;
506
507         /*
508          * Figure out the system memory image size.  If an image file was
509          * specified and -m was not specified, use the image file's size.
510          */
511         if (imageFile && stat(imageFile, &st) == 0 && Maxmem_bytes == 0)
512                 Maxmem_bytes = (vm_paddr_t)st.st_size;
513         if ((imageFile == NULL || stat(imageFile, &st) < 0) &&
514             Maxmem_bytes == 0) {
515                 errx(1, "Cannot create new memory file %s unless "
516                        "system memory size is specified with -m",
517                        imageFile);
518                 /* NOT REACHED */
519         }
520
521         /*
522          * Maxmem must be known at this time
523          */
524         if (Maxmem_bytes < 64 * 1024 * 1024 || (Maxmem_bytes & SEG_MASK)) {
525                 errx(1, "Bad maxmem specification: 64MB minimum, "
526                        "multiples of %dMB only",
527                        SEG_SIZE / 1024 / 1024);
528                 /* NOT REACHED */
529         }
530
531         /*
532          * Generate an image file name if necessary, then open/create the
533          * file exclusively locked.  Do not allow multiple virtual kernels
534          * to use the same image file.
535          *
536          * Don't iterate through a million files if we do not have write
537          * access to the directory, stop if our open() failed on a
538          * non-existant file.  Otherwise opens can fail for any number
539          */
540         if (imageFile == NULL) {
541                 for (i = 0; i < 1000000; ++i) {
542                         asprintf(&imageFile, "/var/vkernel/memimg.%06d", i);
543                         fd = open(imageFile,
544                                   O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
545                         if (fd < 0 && stat(imageFile, &st) == 0) {
546                                 free(imageFile);
547                                 continue;
548                         }
549                         break;
550                 }
551         } else {
552                 fd = open(imageFile, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
553         }
554         fprintf(stderr, "Using memory file: %s\n", imageFile);
555         if (fd < 0 || fstat(fd, &st) < 0) {
556                 err(1, "Unable to open/create %s", imageFile);
557                 /* NOT REACHED */
558         }
559
560         /*
561          * Truncate or extend the file as necessary.  Clean out the contents
562          * of the file, we want it to be full of holes so we don't waste
563          * time reading in data from an old file that we no longer care
564          * about.
565          */
566         ftruncate(fd, 0);
567         ftruncate(fd, Maxmem_bytes);
568
569         MemImageFd = fd;
570         Maxmem = Maxmem_bytes >> PAGE_SHIFT;
571         physmem = Maxmem;
572 }
573
574 /*
575  * Initialize kernel memory.  This reserves kernel virtual memory by using
576  * MAP_VPAGETABLE
577  */
578
579 static
580 void
581 init_kern_memory(void)
582 {
583         void *base;
584         int i;
585         void *firstfree;
586
587         /*
588          * Memory map our kernel virtual memory space.  Note that the
589          * kernel image itself is not made part of this memory for the
590          * moment.
591          *
592          * The memory map must be segment-aligned so we can properly
593          * offset KernelPTD.
594          *
595          * If the system kernel has a different MAXDSIZ, it might not
596          * be possible to map kernel memory in its prefered location.
597          * Try a number of different locations.
598          */
599
600         base = mmap((void*)KERNEL_KVA_START, KERNEL_KVA_SIZE, PROT_READ|PROT_WRITE,
601                     MAP_FILE|MAP_SHARED|MAP_VPAGETABLE|MAP_FIXED|MAP_TRYFIXED,
602                     MemImageFd, (off_t)KERNEL_KVA_START);
603
604         if (base == MAP_FAILED) {
605                 err(1, "Unable to mmap() kernel virtual memory!");
606                 /* NOT REACHED */
607         }
608         madvise(base, KERNEL_KVA_SIZE, MADV_NOSYNC);
609         KvaStart = (vm_offset_t)base;
610         KvaSize = KERNEL_KVA_SIZE;
611         KvaEnd = KvaStart + KvaSize;
612
613         /* cannot use kprintf yet */
614         printf("KVM mapped at %p-%p\n", (void *)KvaStart, (void *)KvaEnd);
615
616         /* MAP_FILE? */
617         dmap_min_address = mmap(0, DMAP_SIZE, PROT_READ|PROT_WRITE,
618                                 MAP_NOCORE|MAP_NOSYNC|MAP_SHARED,
619                                 MemImageFd, 0);
620         if (dmap_min_address == MAP_FAILED) {
621                 err(1, "Unable to mmap() kernel DMAP region!");
622                 /* NOT REACHED */
623         }
624
625         /*
626          * Bootstrap the kernel_pmap
627          */
628         firstfree = NULL;
629         pmap_bootstrap((vm_paddr_t *)&firstfree, (int64_t)base);
630
631         mcontrol(base, KERNEL_KVA_SIZE, MADV_SETMAP,
632                  0 | VPTE_RW | VPTE_V);
633
634         /*
635          * phys_avail[] represents unallocated physical memory.  MI code
636          * will use phys_avail[] to create the vm_page array.
637          */
638         phys_avail[0].phys_beg = (vm_paddr_t)firstfree;
639         phys_avail[0].phys_beg = (phys_avail[0].phys_beg + PAGE_MASK) &
640                                  ~(vm_paddr_t)PAGE_MASK;
641         phys_avail[0].phys_end = Maxmem_bytes;
642
643 #if JGV
644         /*
645          * (virtual_start, virtual_end) represent unallocated kernel virtual
646          * memory.  MI code will create kernel_map using these parameters.
647          */
648         virtual_start = KvaStart + (long)firstfree;
649         virtual_start = (virtual_start + PAGE_MASK) & ~(vm_offset_t)PAGE_MASK;
650         virtual_end = KvaStart + KERNEL_KVA_SIZE;
651 #endif
652
653         /*
654          * pmap_growkernel() will set the correct value.
655          */
656         kernel_vm_end = 0;
657
658         /*
659          * Allocate space for process 0's UAREA.
660          */
661         proc0paddr = (void *)virtual_start;
662         for (i = 0; i < UPAGES; ++i) {
663                 pmap_kenter_quick(virtual_start, phys_avail[0].phys_beg);
664                 virtual_start += PAGE_SIZE;
665                 phys_avail[0].phys_beg += PAGE_SIZE;
666         }
667
668         /*
669          * crashdumpmap
670          */
671         crashdumpmap = virtual_start;
672         virtual_start += MAXDUMPPGS * PAGE_SIZE;
673
674         /*
675          * msgbufp maps the system message buffer
676          */
677         assert((MSGBUF_SIZE & PAGE_MASK) == 0);
678         msgbufp = (void *)virtual_start;
679         for (i = 0; i < (MSGBUF_SIZE >> PAGE_SHIFT); ++i) {
680                 pmap_kenter_quick(virtual_start, phys_avail[0].phys_beg);
681                 virtual_start += PAGE_SIZE;
682                 phys_avail[0].phys_beg += PAGE_SIZE;
683         }
684         msgbufinit(msgbufp, MSGBUF_SIZE);
685
686         /*
687          * used by kern_memio for /dev/mem access
688          */
689         ptvmmap = (caddr_t)virtual_start;
690         virtual_start += PAGE_SIZE;
691 }
692
693 static
694 void
695 init_kern_memory_vmm(void)
696 {
697         int i;
698         void *firstfree;
699         struct vmm_guest_options options;
700         void *dmap_address;
701
702         KvaStart = (vm_offset_t)KERNEL_KVA_START;
703         KvaSize = KERNEL_KVA_SIZE;
704         KvaEnd = KvaStart + KvaSize;
705
706         Maxmem = Maxmem_bytes >> PAGE_SHIFT;
707         physmem = Maxmem;
708
709         if (Maxmem_bytes < 64 * 1024 * 1024 || (Maxmem_bytes & SEG_MASK)) {
710                 errx(1, "Bad maxmem specification: 64MB minimum, "
711                        "multiples of %dMB only",
712                        SEG_SIZE / 1024 / 1024);
713                 /* NOT REACHED */
714         }
715
716         /* Call the vmspace_create to allocate the internal
717          * vkernel structures. Won't do anything else (no new
718          * vmspace)
719          */
720         if (vmspace_create(NULL, 0, NULL) < 0)
721                 panic("vmspace_create() failed");
722
723
724         /*
725          * MAP_ANON the region of the VKERNEL phyisical memory
726          * (known as GPA - Guest Physical Address
727          */
728         dmap_address = mmap(NULL, Maxmem_bytes, PROT_READ|PROT_WRITE|PROT_EXEC,
729             MAP_ANON|MAP_SHARED, -1, 0);
730         if (dmap_address == MAP_FAILED) {
731                 err(1, "Unable to mmap() RAM region!");
732                 /* NOT REACHED */
733         }
734         /* bzero(dmap_address, Maxmem_bytes); */
735
736         /* Alloc a new stack in the lowmem */
737         vkernel_stack = mmap(NULL, KERNEL_STACK_SIZE,
738             PROT_READ|PROT_WRITE|PROT_EXEC,
739             MAP_ANON, -1, 0);
740         if (vkernel_stack == MAP_FAILED) {
741                 err(1, "Unable to allocate stack\n");
742         }
743
744         /*
745          * Bootstrap the kernel_pmap
746          */
747         firstfree = dmap_address;
748         dmap_min_address = NULL; /* VIRT == PHYS in the first 512G */
749         pmap_bootstrap((vm_paddr_t *)&firstfree, (uint64_t)KvaStart);
750
751         /*
752          * Enter VMM mode
753          */
754         options.guest_cr3 = (register_t) KPML4phys;
755         options.new_stack = (uint64_t) vkernel_stack + KERNEL_STACK_SIZE;
756         options.master = 1;
757         if (vmm_guest_ctl(VMM_GUEST_RUN, &options)) {
758                 err(1, "Unable to enter VMM mode.");
759         }
760
761         /*
762          * phys_avail[] represents unallocated physical memory.  MI code
763          * will use phys_avail[] to create the vm_page array.
764          */
765         phys_avail[0].phys_beg = (vm_paddr_t)firstfree;
766         phys_avail[0].phys_beg = (phys_avail[0].phys_beg + PAGE_MASK) &
767                                  ~(vm_paddr_t)PAGE_MASK;
768         phys_avail[0].phys_end = (vm_paddr_t)dmap_address + Maxmem_bytes;
769
770         /*
771          * pmap_growkernel() will set the correct value.
772          */
773         kernel_vm_end = 0;
774
775         /*
776          * Allocate space for process 0's UAREA.
777          */
778         proc0paddr = (void *)virtual_start;
779         for (i = 0; i < UPAGES; ++i) {
780                 pmap_kenter_quick(virtual_start, phys_avail[0].phys_beg);
781                 virtual_start += PAGE_SIZE;
782                 phys_avail[0].phys_beg += PAGE_SIZE;
783         }
784
785         /*
786          * crashdumpmap
787          */
788         crashdumpmap = virtual_start;
789         virtual_start += MAXDUMPPGS * PAGE_SIZE;
790
791         /*
792          * msgbufp maps the system message buffer
793          */
794         assert((MSGBUF_SIZE & PAGE_MASK) == 0);
795         msgbufp = (void *)virtual_start;
796         for (i = 0; i < (MSGBUF_SIZE >> PAGE_SHIFT); ++i) {
797
798                 pmap_kenter_quick(virtual_start, phys_avail[0].phys_beg);
799                 virtual_start += PAGE_SIZE;
800                 phys_avail[0].phys_beg += PAGE_SIZE;
801         }
802
803         msgbufinit(msgbufp, MSGBUF_SIZE);
804
805         /*
806          * used by kern_memio for /dev/mem access
807          */
808         ptvmmap = (caddr_t)virtual_start;
809         virtual_start += PAGE_SIZE;
810
811         printf("vmm: Hardware pagetable enabled for guest\n");
812 }
813
814
815 /*
816  * Map the per-cpu globaldata for cpu #0.  Allocate the space using
817  * virtual_start and phys_avail[0]
818  */
819 static
820 void
821 init_globaldata(void)
822 {
823         int i;
824         vm_paddr_t pa;
825         vm_offset_t va;
826
827         /*
828          * Reserve enough KVA to cover possible cpus.  This is a considerable
829          * amount of KVA since the privatespace structure includes two
830          * whole page table mappings.
831          */
832         virtual_start = (virtual_start + SEG_MASK) & ~(vm_offset_t)SEG_MASK;
833         CPU_prvspace = (void *)virtual_start;
834         virtual_start += sizeof(struct privatespace) * SMP_MAXCPU;
835
836         /*
837          * Allocate enough physical memory to cover the mdglobaldata
838          * portion of the space and the idle stack and map the pages
839          * into KVA.  For cpu #0 only.
840          */
841         for (i = 0; i < sizeof(struct mdglobaldata); i += PAGE_SIZE) {
842                 pa = phys_avail[0].phys_beg;
843                 va = (vm_offset_t)&CPU_prvspace[0].mdglobaldata + i;
844                 pmap_kenter_quick(va, pa);
845                 phys_avail[0].phys_beg += PAGE_SIZE;
846         }
847         for (i = 0; i < sizeof(CPU_prvspace[0].idlestack); i += PAGE_SIZE) {
848                 pa = phys_avail[0].phys_beg;
849                 va = (vm_offset_t)&CPU_prvspace[0].idlestack + i;
850                 pmap_kenter_quick(va, pa);
851                 phys_avail[0].phys_beg += PAGE_SIZE;
852         }
853
854         /*
855          * Setup the %gs for cpu #0.  The mycpu macro works after this
856          * point.  Note that %fs is used by pthreads.
857          */
858         tls_set_gs(&CPU_prvspace[0], sizeof(struct privatespace));
859 }
860
861
862 /*
863  * Initialize pool tokens and other necessary locks
864  */
865 static void
866 init_locks(void)
867 {
868
869         /*
870          * Get the initial mplock with a count of 1 for the BSP.
871          * This uses a LOGICAL cpu ID, ie BSP == 0.
872          */
873         cpu_get_initial_mplock();
874
875         /* our token pool needs to work early */
876         lwkt_token_pool_init();
877
878 }
879
880
881 /*
882  * Initialize very low level systems including thread0, proc0, etc.
883  */
884 static
885 void
886 init_vkernel(void)
887 {
888         struct mdglobaldata *gd;
889
890         gd = &CPU_prvspace[0].mdglobaldata;
891         bzero(gd, sizeof(*gd));
892
893         gd->mi.gd_curthread = &thread0;
894         thread0.td_gd = &gd->mi;
895         ncpus = 1;
896         ncpus2 = 1;     /* rounded down power of 2 */
897         ncpus_fit = 1;  /* rounded up power of 2 */
898         /* ncpus2_mask and ncpus_fit_mask are 0 */
899         init_param1();
900         gd->mi.gd_prvspace = &CPU_prvspace[0];
901         mi_gdinit(&gd->mi, 0);
902         cpu_gdinit(gd, 0);
903         mi_proc0init(&gd->mi, proc0paddr);
904         lwp0.lwp_md.md_regs = &proc0_tf;
905
906         init_locks();
907         cninit();
908         rand_initialize();
909 #if 0   /* #ifdef DDB */
910         kdb_init();
911         if (boothowto & RB_KDB)
912                 Debugger("Boot flags requested debugger");
913 #endif
914         identcpu();
915 #if 0
916         initializecpu();        /* Initialize CPU registers */
917 #endif
918         init_param2((phys_avail[0].phys_end -
919                      phys_avail[0].phys_beg) / PAGE_SIZE);
920
921 #if 0
922         /*
923          * Map the message buffer
924          */
925         for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
926                 pmap_kenter((vm_offset_t)msgbufp + off, avail_end + off);
927         msgbufinit(msgbufp, MSGBUF_SIZE);
928 #endif
929 #if 0
930         thread0.td_pcb_cr3 ... MMU
931         lwp0.lwp_md.md_regs = &proc0_tf;
932 #endif
933 }
934
935 /*
936  * Filesystem image paths for the virtual kernel are optional.
937  * If specified they each should point to a disk image,
938  * the first of which will become the root disk.
939  *
940  * The virtual kernel caches data from our 'disk' just like a normal kernel,
941  * so we do not really want the real kernel to cache the data too.  Use
942  * O_DIRECT to remove the duplication.
943  */
944 static
945 void
946 init_disk(char **diskExp, int *diskFlags, int diskFileNum, enum vkdisk_type type)
947 {
948         char *serno;
949         int i;
950
951         if (diskFileNum == 0)
952                 return;
953
954         for (i=0; i < diskFileNum; i++){
955                 char *fname;
956                 fname = diskExp[i];
957
958                 if (fname == NULL) {
959                         warnx("Invalid argument to '-r'");
960                         continue;
961                 }
962                 /*
963                  * Check for a serial number for the virtual disk
964                  * passed from the command line.
965                  */
966                 serno = fname;
967                 strsep(&serno, ":");
968
969                 if (DiskNum < VKDISK_MAX) {
970                         struct stat st;
971                         struct vkdisk_info *info = NULL;
972                         int fd;
973                         size_t l = 0;
974
975                         if (type == VKD_DISK)
976                             fd = open(fname, O_RDWR|O_DIRECT, 0644);
977                         else
978                             fd = open(fname, O_RDONLY|O_DIRECT, 0644);
979                         if (fd < 0 || fstat(fd, &st) < 0) {
980                                 err(1, "Unable to open/create %s", fname);
981                                 /* NOT REACHED */
982                         }
983                         if (S_ISREG(st.st_mode) && (diskFlags[i] & 1) == 0) {
984                                 if (flock(fd, LOCK_EX|LOCK_NB) < 0) {
985                                         errx(1, "Disk image %s is already "
986                                                 "in use\n", fname);
987                                         /* NOT REACHED */
988                                 }
989                         }
990
991                         info = &DiskInfo[DiskNum];
992                         l = strlen(fname);
993
994                         info->unit = i;
995                         info->fd = fd;
996                         info->type = type;
997                         info->flags = diskFlags[i];
998                         memcpy(info->fname, fname, l);
999                         info->serno = NULL;
1000                         if (serno) {
1001                                 if ((info->serno = malloc(SERNOLEN)) != NULL)
1002                                         strlcpy(info->serno, serno, SERNOLEN);
1003                                 else
1004                                         warnx("Couldn't allocate memory for the operation");
1005                         }
1006
1007                         if (DiskNum == 0) {
1008                                 if (type == VKD_CD) {
1009                                         rootdevnames[0] = "cd9660:vcd0";
1010                                 } else if (type == VKD_DISK) {
1011                                         rootdevnames[0] = "ufs:vkd0s0a";
1012                                         rootdevnames[1] = "ufs:vkd0s1a";
1013                                 }
1014                         }
1015
1016                         DiskNum++;
1017                 } else {
1018                         warnx("vkd%d (%s) > VKDISK_MAX", DiskNum, fname);
1019                         continue;
1020                 }
1021         }
1022 }
1023
1024 static
1025 int
1026 netif_set_tapflags(int tap_unit, int f, int s)
1027 {
1028         struct ifreq ifr;
1029         int flags;
1030
1031         bzero(&ifr, sizeof(ifr));
1032
1033         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tap%d", tap_unit);
1034         if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
1035                 warn("tap%d: ioctl(SIOCGIFFLAGS) failed", tap_unit);
1036                 return -1;
1037         }
1038
1039         /*
1040          * Adjust if_flags
1041          *
1042          * If the flags are already set/cleared, then we return
1043          * immediately to avoid extra syscalls
1044          */
1045         flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
1046         if (f < 0) {
1047                 /* Turn off flags */
1048                 f = -f;
1049                 if ((flags & f) == 0)
1050                         return 0;
1051                 flags &= ~f;
1052         } else {
1053                 /* Turn on flags */
1054                 if (flags & f)
1055                         return 0;
1056                 flags |= f;
1057         }
1058
1059         /*
1060          * Fix up ifreq.ifr_name, since it may be trashed
1061          * in previous ioctl(SIOCGIFFLAGS)
1062          */
1063         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tap%d", tap_unit);
1064
1065         ifr.ifr_flags = flags & 0xffff;
1066         ifr.ifr_flagshigh = flags >> 16;
1067         if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
1068                 warn("tap%d: ioctl(SIOCSIFFLAGS) failed", tap_unit);
1069                 return -1;
1070         }
1071         return 0;
1072 }
1073
1074 static
1075 int
1076 netif_set_tapaddr(int tap_unit, in_addr_t addr, in_addr_t mask, int s)
1077 {
1078         struct ifaliasreq ifra;
1079         struct sockaddr_in *in;
1080
1081         bzero(&ifra, sizeof(ifra));
1082         snprintf(ifra.ifra_name, sizeof(ifra.ifra_name), "tap%d", tap_unit);
1083
1084         /* Setup address */
1085         in = (struct sockaddr_in *)&ifra.ifra_addr;
1086         in->sin_family = AF_INET;
1087         in->sin_len = sizeof(*in);
1088         in->sin_addr.s_addr = addr;
1089
1090         if (mask != 0) {
1091                 /* Setup netmask */
1092                 in = (struct sockaddr_in *)&ifra.ifra_mask;
1093                 in->sin_len = sizeof(*in);
1094                 in->sin_addr.s_addr = mask;
1095         }
1096
1097         if (ioctl(s, SIOCAIFADDR, &ifra) < 0) {
1098                 warn("tap%d: ioctl(SIOCAIFADDR) failed", tap_unit);
1099                 return -1;
1100         }
1101         return 0;
1102 }
1103
1104 static
1105 int
1106 netif_add_tap2brg(int tap_unit, const char *ifbridge, int s)
1107 {
1108         struct ifbreq ifbr;
1109         struct ifdrv ifd;
1110
1111         bzero(&ifbr, sizeof(ifbr));
1112         snprintf(ifbr.ifbr_ifsname, sizeof(ifbr.ifbr_ifsname),
1113                  "tap%d", tap_unit);
1114
1115         bzero(&ifd, sizeof(ifd));
1116         strlcpy(ifd.ifd_name, ifbridge, sizeof(ifd.ifd_name));
1117         ifd.ifd_cmd = BRDGADD;
1118         ifd.ifd_len = sizeof(ifbr);
1119         ifd.ifd_data = &ifbr;
1120
1121         if (ioctl(s, SIOCSDRVSPEC, &ifd) < 0) {
1122                 /*
1123                  * 'errno == EEXIST' means that the tap(4) is already
1124                  * a member of the bridge(4)
1125                  */
1126                 if (errno != EEXIST) {
1127                         warn("ioctl(%s, SIOCSDRVSPEC) failed", ifbridge);
1128                         return -1;
1129                 }
1130         }
1131         return 0;
1132 }
1133
1134 #define TAPDEV_OFLAGS   (O_RDWR | O_NONBLOCK)
1135
1136 /*
1137  * Locate the first unused tap(4) device file if auto mode is requested,
1138  * or open the user supplied device file, and bring up the corresponding
1139  * tap(4) interface.
1140  *
1141  * NOTE: Only tap(4) device file is supported currently
1142  */
1143 static
1144 int
1145 netif_open_tap(const char *netif, int *tap_unit, int s)
1146 {
1147         char tap_dev[MAXPATHLEN];
1148         int tap_fd, failed;
1149         struct stat st;
1150         char *dname;
1151
1152         *tap_unit = -1;
1153
1154         if (strcmp(netif, "auto") == 0) {
1155                 /*
1156                  * Find first unused tap(4) device file
1157                  */
1158                 tap_fd = open("/dev/tap", TAPDEV_OFLAGS);
1159                 if (tap_fd < 0) {
1160                         warnc(errno, "Unable to find a free tap(4)");
1161                         return -1;
1162                 }
1163         } else {
1164                 /*
1165                  * User supplied tap(4) device file or unix socket.
1166                  */
1167                 if (netif[0] == '/')    /* Absolute path */
1168                         strlcpy(tap_dev, netif, sizeof(tap_dev));
1169                 else
1170                         snprintf(tap_dev, sizeof(tap_dev), "/dev/%s", netif);
1171
1172                 tap_fd = open(tap_dev, TAPDEV_OFLAGS);
1173
1174                 /*
1175                  * If we cannot open normally try to connect to it.
1176                  */
1177                 if (tap_fd < 0)
1178                         tap_fd = unix_connect(tap_dev);
1179
1180                 if (tap_fd < 0) {
1181                         warn("Unable to open %s", tap_dev);
1182                         return -1;
1183                 }
1184         }
1185
1186         /*
1187          * Check whether the device file is a tap(4)
1188          */
1189         if (fstat(tap_fd, &st) < 0) {
1190                 failed = 1;
1191         } else if (S_ISCHR(st.st_mode)) {
1192                 dname = fdevname(tap_fd);
1193                 if (dname)
1194                         dname = strstr(dname, "tap");
1195                 if (dname) {
1196                         /*
1197                          * Bring up the corresponding tap(4) interface
1198                          */
1199                         *tap_unit = strtol(dname + 3, NULL, 10);
1200                         printf("TAP UNIT %d\n", *tap_unit);
1201                         if (netif_set_tapflags(*tap_unit, IFF_UP, s) == 0)
1202                                 failed = 0;
1203                         else
1204                                 failed = 1;
1205                 } else {
1206                         failed = 1;
1207                 }
1208         } else if (S_ISSOCK(st.st_mode)) {
1209                 /*
1210                  * Special socket connection (typically to vknet).  We
1211                  * do not have to do anything.
1212                  */
1213                 failed = 0;
1214         } else {
1215                 failed = 1;
1216         }
1217
1218         if (failed) {
1219                 warnx("%s is not a tap(4) device or socket", tap_dev);
1220                 close(tap_fd);
1221                 tap_fd = -1;
1222                 *tap_unit = -1;
1223         }
1224         return tap_fd;
1225 }
1226
1227 static int
1228 unix_connect(const char *path)
1229 {
1230         struct sockaddr_un sunx;
1231         int len;
1232         int net_fd;
1233         int sndbuf = 262144;
1234         struct stat st;
1235
1236         snprintf(sunx.sun_path, sizeof(sunx.sun_path), "%s", path);
1237         len = offsetof(struct sockaddr_un, sun_path[strlen(sunx.sun_path)]);
1238         ++len;  /* include nul */
1239         sunx.sun_family = AF_UNIX;
1240         sunx.sun_len = len;
1241
1242         net_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
1243         if (net_fd < 0)
1244                 return(-1);
1245         if (connect(net_fd, (void *)&sunx, len) < 0) {
1246                 close(net_fd);
1247                 return(-1);
1248         }
1249         setsockopt(net_fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
1250         if (fstat(net_fd, &st) == 0)
1251                 printf("Network socket buffer: %d bytes\n", st.st_blksize);
1252         fcntl(net_fd, F_SETFL, O_NONBLOCK);
1253         return(net_fd);
1254 }
1255
1256 #undef TAPDEV_MAJOR
1257 #undef TAPDEV_MINOR
1258 #undef TAPDEV_OFLAGS
1259
1260 /*
1261  * Following syntax is supported,
1262  * 1) x.x.x.x             tap(4)'s address is x.x.x.x
1263  *
1264  * 2) x.x.x.x/z           tap(4)'s address is x.x.x.x
1265  *                        tap(4)'s netmask len is z
1266  *
1267  * 3) x.x.x.x:y.y.y.y     tap(4)'s address is x.x.x.x
1268  *                        pseudo netif's address is y.y.y.y
1269  *
1270  * 4) x.x.x.x:y.y.y.y/z   tap(4)'s address is x.x.x.x
1271  *                        pseudo netif's address is y.y.y.y
1272  *                        tap(4) and pseudo netif's netmask len are z
1273  *
1274  * 5) bridgeX             tap(4) will be added to bridgeX
1275  *
1276  * 6) bridgeX:y.y.y.y     tap(4) will be added to bridgeX
1277  *                        pseudo netif's address is y.y.y.y
1278  *
1279  * 7) bridgeX:y.y.y.y/z   tap(4) will be added to bridgeX
1280  *                        pseudo netif's address is y.y.y.y
1281  *                        pseudo netif's netmask len is z
1282  */
1283 static
1284 int
1285 netif_init_tap(int tap_unit, in_addr_t *addr, in_addr_t *mask, int s)
1286 {
1287         in_addr_t tap_addr, netmask, netif_addr;
1288         int next_netif_addr;
1289         char *tok, *masklen_str, *ifbridge;
1290
1291         *addr = 0;
1292         *mask = 0;
1293
1294         tok = strtok(NULL, ":/");
1295         if (tok == NULL) {
1296                 /*
1297                  * Nothing special, simply use tap(4) as backend
1298                  */
1299                 return 0;
1300         }
1301
1302         if (inet_pton(AF_INET, tok, &tap_addr) > 0) {
1303                 /*
1304                  * tap(4)'s address is supplied
1305                  */
1306                 ifbridge = NULL;
1307
1308                 /*
1309                  * If there is next token, then it may be pseudo
1310                  * netif's address or netmask len for tap(4)
1311                  */
1312                 next_netif_addr = 0;
1313         } else {
1314                 /*
1315                  * Not tap(4)'s address, assume it as a bridge(4)
1316                  * iface name
1317                  */
1318                 tap_addr = 0;
1319                 ifbridge = tok;
1320
1321                 /*
1322                  * If there is next token, then it must be pseudo
1323                  * netif's address
1324                  */
1325                 next_netif_addr = 1;
1326         }
1327
1328         netmask = netif_addr = 0;
1329
1330         tok = strtok(NULL, ":/");
1331         if (tok == NULL)
1332                 goto back;
1333
1334         if (inet_pton(AF_INET, tok, &netif_addr) <= 0) {
1335                 if (next_netif_addr) {
1336                         warnx("Invalid pseudo netif address: %s", tok);
1337                         return -1;
1338                 }
1339                 netif_addr = 0;
1340
1341                 /*
1342                  * Current token is not address, then it must be netmask len
1343                  */
1344                 masklen_str = tok;
1345         } else {
1346                 /*
1347                  * Current token is pseudo netif address, if there is next token
1348                  * it must be netmask len
1349                  */
1350                 masklen_str = strtok(NULL, "/");
1351         }
1352
1353         /* Calculate netmask */
1354         if (masklen_str != NULL) {
1355                 u_long masklen;
1356
1357                 masklen = strtoul(masklen_str, NULL, 10);
1358                 if (masklen < 32 && masklen > 0) {
1359                         netmask = htonl(~((1LL << (32 - masklen)) - 1)
1360                                         & 0xffffffff);
1361                 } else {
1362                         warnx("Invalid netmask len: %lu", masklen);
1363                         return -1;
1364                 }
1365         }
1366
1367         /* Make sure there is no more token left */
1368         if (strtok(NULL, ":/") != NULL) {
1369                 warnx("Invalid argument to '-I'");
1370                 return -1;
1371         }
1372
1373 back:
1374         if (tap_unit < 0) {
1375                 /* Do nothing */
1376         } else if (ifbridge == NULL) {
1377                 /* Set tap(4) address/netmask */
1378                 if (netif_set_tapaddr(tap_unit, tap_addr, netmask, s) < 0)
1379                         return -1;
1380         } else {
1381                 /* Tie tap(4) to bridge(4) */
1382                 if (netif_add_tap2brg(tap_unit, ifbridge, s) < 0)
1383                         return -1;
1384         }
1385
1386         *addr = netif_addr;
1387         *mask = netmask;
1388         return 0;
1389 }
1390
1391 /*
1392  * NetifInfo[] will be filled for pseudo netif initialization.
1393  * NetifNum will be bumped to reflect the number of valid entries
1394  * in NetifInfo[].
1395  */
1396 static
1397 void
1398 init_netif(char *netifExp[], int netifExpNum)
1399 {
1400         int i, s;
1401         char *tmp;
1402
1403         if (netifExpNum == 0)
1404                 return;
1405
1406         s = socket(AF_INET, SOCK_DGRAM, 0);     /* for ioctl(SIOC) */
1407         if (s < 0)
1408                 return;
1409
1410         for (i = 0; i < netifExpNum; ++i) {
1411                 struct vknetif_info *info;
1412                 in_addr_t netif_addr, netif_mask;
1413                 int tap_fd, tap_unit;
1414                 char *netif;
1415
1416                 /* Extract MAC address if there is one */
1417                 tmp = netifExp[i];
1418                 strsep(&tmp, "=");
1419
1420                 netif = strtok(netifExp[i], ":");
1421                 if (netif == NULL) {
1422                         warnx("Invalid argument to '-I'");
1423                         continue;
1424                 }
1425
1426                 /*
1427                  * Open tap(4) device file and bring up the
1428                  * corresponding interface
1429                  */
1430                 tap_fd = netif_open_tap(netif, &tap_unit, s);
1431                 if (tap_fd < 0)
1432                         continue;
1433
1434                 /*
1435                  * Initialize tap(4) and get address/netmask
1436                  * for pseudo netif
1437                  *
1438                  * NB: Rest part of netifExp[i] is passed
1439                  *     to netif_init_tap() implicitly.
1440                  */
1441                 if (netif_init_tap(tap_unit, &netif_addr, &netif_mask, s) < 0) {
1442                         /*
1443                          * NB: Closing tap(4) device file will bring
1444                          *     down the corresponding interface
1445                          */
1446                         close(tap_fd);
1447                         continue;
1448                 }
1449
1450                 info = &NetifInfo[NetifNum];
1451                 bzero(info, sizeof(*info));
1452                 info->tap_fd = tap_fd;
1453                 info->tap_unit = tap_unit;
1454                 info->netif_addr = netif_addr;
1455                 info->netif_mask = netif_mask;
1456                 /*
1457                  * If tmp isn't NULL it means a MAC could have been
1458                  * specified so attempt to convert it.
1459                  * Setting enaddr to NULL will tell vke_attach() we
1460                  * need a pseudo-random MAC address.
1461                  */
1462                 if (tmp != NULL) {
1463                         if ((info->enaddr = malloc(ETHER_ADDR_LEN)) == NULL)
1464                                 warnx("Couldn't allocate memory for the operation");
1465                         else {
1466                                 if ((kether_aton(tmp, info->enaddr)) == NULL) {
1467                                         free(info->enaddr);
1468                                         info->enaddr = NULL;
1469                                 }
1470                         }
1471                 }
1472
1473                 NetifNum++;
1474                 if (NetifNum >= VKNETIF_MAX)    /* XXX will this happen? */
1475                         break;
1476         }
1477         close(s);
1478 }
1479
1480 /*
1481  * Create the pid file and leave it open and locked while the vkernel is
1482  * running.  This allows a script to use /usr/bin/lockf to probe whether
1483  * a vkernel is still running (so as not to accidently kill an unrelated
1484  * process from a stale pid file).
1485  */
1486 static
1487 void
1488 writepid(void)
1489 {
1490         char buf[32];
1491         int fd;
1492
1493         if (pid_file != NULL) {
1494                 snprintf(buf, sizeof(buf), "%ld\n", (long)getpid());
1495                 fd = open(pid_file, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0666);
1496                 if (fd < 0) {
1497                         if (errno == EWOULDBLOCK) {
1498                                 perror("Failed to lock pidfile, "
1499                                        "vkernel already running");
1500                         } else {
1501                                 perror("Failed to create pidfile");
1502                         }
1503                         exit(EX_SOFTWARE);
1504                 }
1505                 ftruncate(fd, 0);
1506                 write(fd, buf, strlen(buf));
1507                 /* leave the file open to maintain the lock */
1508         }
1509 }
1510
1511 static
1512 void
1513 cleanpid( void )
1514 {
1515         if (pid_file != NULL) {
1516                 if (unlink(pid_file) < 0)
1517                         perror("Warning: couldn't remove pidfile");
1518         }
1519 }
1520
1521 static
1522 void
1523 usage_err(const char *ctl, ...)
1524 {
1525         va_list va;
1526
1527         va_start(va, ctl);
1528         vfprintf(stderr, ctl, va);
1529         va_end(va);
1530         fprintf(stderr, "\n");
1531         exit(EX_USAGE);
1532 }
1533
1534 static
1535 void
1536 usage_help(_Bool help)
1537 {
1538         fprintf(stderr, "Usage: %s [-hsUvd] [-c file] [-e name=value:name=value:...]\n"
1539             "\t[-i file] [-I interface[:address1[:address2][/netmask]]] [-l cpulock]\n"
1540             "\t[-m size] [-n numcpus[:lbits[:cbits]]]\n"
1541             "\t[-p file] [-r file]\n", save_av[0]);
1542
1543         if (help)
1544                 fprintf(stderr, "\nArguments:\n"
1545                     "\t-c\tSpecify a readonly CD-ROM image file to be used by the kernel.\n"
1546                     "\t-e\tSpecify an environment to be used by the kernel.\n"
1547                     "\t-h\tThis list of options.\n"
1548                     "\t-i\tSpecify a memory image file to be used by the virtual kernel.\n"
1549                     "\t-I\tCreate a virtual network device.\n"
1550                     "\t-l\tSpecify which, if any, real CPUs to lock virtual CPUs to.\n"
1551                     "\t-m\tSpecify the amount of memory to be used by the kernel in bytes.\n"
1552                     "\t-n\tSpecify the number of CPUs and the topology you wish to emulate:\n"
1553                     "\t\t\tnumcpus - number of cpus\n"
1554                     "\t\t\tlbits - specify the number of bits within APICID(=CPUID)\n"
1555                     "\t\t\t        needed for representing the logical ID.\n"
1556                     "\t\t\t        Controls the number of threads/core:\n"
1557                     "\t\t\t        (0 bits - 1 thread, 1 bit - 2 threads).\n"
1558                     "\t\t\tcbits - specify the number of bits within APICID(=CPUID)\n"
1559                     "\t\t\t        needed for representing the core ID.\n"
1560                     "\t\t\t        Controls the number of cores/package:\n"
1561                     "\t\t\t        (0 bits - 1 core, 1 bit - 2 cores).\n"
1562                     "\t-p\tSpecify a file in which to store the process ID.\n"
1563                     "\t-r\tSpecify a R/W disk image file, iterates vkd0..n\n"
1564                     "\t-R\tSpecify a COW disk image file, iterates vkd0..n\n"
1565                     "\t-s\tBoot into single-user mode.\n"
1566                     "\t-U\tEnable writing to kernel memory and module loading.\n"
1567                     "\t-v\tTurn on verbose booting.\n");
1568
1569         exit(EX_USAGE);
1570 }
1571
1572 void
1573 cpu_smp_stopped(void)
1574 {
1575 }
1576
1577 void
1578 cpu_reset(void)
1579 {
1580         kprintf("cpu reset, rebooting vkernel\n");
1581         closefrom(3);
1582         cleanpid();
1583         exit(EX_VKERNEL_REBOOT);
1584 }
1585
1586 void
1587 cpu_halt(void)
1588 {
1589         kprintf("cpu halt, exiting vkernel\n");
1590         cleanpid();
1591         exit(EX_OK);
1592 }
1593
1594 void
1595 setrealcpu(void)
1596 {
1597         switch(lwp_cpu_lock) {
1598         case LCL_PER_CPU:
1599                 if (bootverbose)
1600                         kprintf("Locking CPU%d to real cpu %d\n",
1601                                 mycpuid, next_cpu);
1602                 usched_set(getpid(), USCHED_SET_CPU, &next_cpu, sizeof(next_cpu));
1603                 next_cpu++;
1604                 if (next_cpu >= real_ncpus)
1605                         next_cpu = 0;
1606                 break;
1607         case LCL_SINGLE_CPU:
1608                 if (bootverbose)
1609                         kprintf("Locking CPU%d to real cpu %d\n",
1610                                 mycpuid, next_cpu);
1611                 usched_set(getpid(), USCHED_SET_CPU, &next_cpu, sizeof(next_cpu));
1612                 break;
1613         default:
1614                 /* do not map virtual cpus to real cpus */
1615                 break;
1616         }
1617 }
1618
1619 /*
1620  * Allocate and free memory for module loading.  The loaded module
1621  * has to be placed somewhere near the current kernel binary load
1622  * point or the relocations will not work.
1623  *
1624  * I'm not sure why this isn't working.
1625  */
1626 int
1627 vkernel_module_memory_alloc(vm_offset_t *basep, size_t bytes)
1628 {
1629 #if 1
1630         size_t xtra;
1631         xtra = (PAGE_SIZE - (vm_offset_t)sbrk(0)) & PAGE_MASK;
1632         *basep = (vm_offset_t)sbrk(xtra + bytes) + xtra;
1633         bzero((void *)*basep, bytes);
1634 #else
1635         *basep = (vm_offset_t)mmap((void *)0x000000000, bytes,
1636                                    PROT_READ|PROT_WRITE|PROT_EXEC,
1637                                    MAP_ANON|MAP_SHARED, -1, 0);
1638         if ((void *)*basep == MAP_FAILED)
1639                 return ENOMEM;
1640 #endif
1641         return 0;
1642 }
1643
1644 void
1645 vkernel_module_memory_free(vm_offset_t base, size_t bytes)
1646 {
1647 #if 0
1648 #if 0
1649         munmap((void *)base, bytes);
1650 #endif
1651 #endif
1652 }