Merge from vendor branch OPENSSL:
[dragonfly.git] / sys / platform / vkernel / 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  * $DragonFly: src/sys/platform/vkernel/platform/init.c,v 1.56 2008/05/27 07:48:00 dillon Exp $
35  */
36
37 #include <sys/types.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/stat.h>
41 #include <sys/mman.h>
42 #include <sys/cons.h>
43 #include <sys/random.h>
44 #include <sys/vkernel.h>
45 #include <sys/tls.h>
46 #include <sys/reboot.h>
47 #include <sys/proc.h>
48 #include <sys/msgbuf.h>
49 #include <sys/vmspace.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 #include <sys/sysctl.h>
53 #include <sys/un.h>
54 #include <vm/vm_page.h>
55
56 #include <machine/cpu.h>
57 #include <machine/globaldata.h>
58 #include <machine/tls.h>
59 #include <machine/md_var.h>
60 #include <machine/vmparam.h>
61 #include <cpu/specialreg.h>
62
63 #include <net/if.h>
64 #include <net/if_arp.h>
65 #include <net/ethernet.h>
66 #include <net/bridge/if_bridgevar.h>
67 #include <netinet/in.h>
68 #include <arpa/inet.h>
69
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <stdarg.h>
73 #include <unistd.h>
74 #include <fcntl.h>
75 #include <string.h>
76 #include <err.h>
77 #include <errno.h>
78 #include <assert.h>
79
80 vm_paddr_t phys_avail[16];
81 vm_paddr_t Maxmem;
82 vm_paddr_t Maxmem_bytes;
83 int MemImageFd = -1;
84 struct vkdisk_info DiskInfo[VKDISK_MAX];
85 int DiskNum;
86 struct vknetif_info NetifInfo[VKNETIF_MAX];
87 int NetifNum;
88 char *pid_file;
89 vm_offset_t KvaStart;
90 vm_offset_t KvaEnd;
91 vm_offset_t KvaSize;
92 vm_offset_t virtual_start;
93 vm_offset_t virtual_end;
94 vm_offset_t kernel_vm_end;
95 vm_offset_t crashdumpmap;
96 vm_offset_t clean_sva;
97 vm_offset_t clean_eva;
98 struct msgbuf *msgbufp;
99 caddr_t ptvmmap;
100 vpte_t  *KernelPTD;
101 vpte_t  *KernelPTA;     /* Warning: Offset for direct VA translation */
102 u_int cpu_feature;      /* XXX */
103 int tsc_present;
104 int64_t tsc_frequency;
105 int optcpus;            /* number of cpus - see mp_start() */
106 int lwp_cpu_lock;       /* if/how to lock virtual CPUs to real CPUs */
107 int real_ncpus;         /* number of real CPUs */
108 int next_cpu;           /* next real CPU to lock a virtual CPU to */
109
110 struct privatespace *CPU_prvspace;
111
112 static struct trapframe proc0_tf;
113 static void *proc0paddr;
114
115 static void init_sys_memory(char *imageFile);
116 static void init_kern_memory(void);
117 static void init_globaldata(void);
118 static void init_vkernel(void);
119 static void init_disk(char *diskExp[], int diskFileNum, enum vkdisk_type type); 
120 static void init_netif(char *netifExp[], int netifFileNum);
121 static void writepid( void );
122 static void cleanpid( void );
123 static int unix_connect(const char *path);
124 static void usage(const char *ctl, ...);
125
126 static int save_ac;
127 static char **save_av;
128
129 /*
130  * Kernel startup for virtual kernels - standard main() 
131  */
132 int
133 main(int ac, char **av)
134 {
135         char *memImageFile = NULL;
136         char *netifFile[VKNETIF_MAX];
137         char *diskFile[VKDISK_MAX];
138         char *cdFile[VKDISK_MAX];
139         char *suffix;
140         char *endp;
141         int netifFileNum = 0;
142         int diskFileNum = 0;
143         int cdFileNum = 0;
144         int bootOnDisk = -1;    /* set below to vcd (0) or vkd (1) */
145         int c;
146         int i;
147         int n;
148         int real_vkernel_enable;
149         int supports_sse;
150         size_t vsize;
151         
152         save_ac = ac;
153         save_av = av;
154
155         /*
156          * Process options
157          */
158         kernel_mem_readonly = 1;
159 #ifdef SMP
160         optcpus = 2;
161 #endif
162         lwp_cpu_lock = LCL_NONE;
163
164         real_vkernel_enable = 0;
165         vsize = sizeof(real_vkernel_enable);
166         sysctlbyname("vm.vkernel_enable", &real_vkernel_enable, &vsize, NULL,0);
167         
168         if (real_vkernel_enable == 0) {
169                 errx(1, "vm.vkernel_enable is 0, must be set "
170                         "to 1 to execute a vkernel!");
171         }
172
173         real_ncpus = 1;
174         vsize = sizeof(real_ncpus);
175         sysctlbyname("hw.ncpu", &real_ncpus, &vsize, NULL, 0);
176
177         while ((c = getopt(ac, av, "c:svl:m:n:r:e:i:p:I:U")) != -1) {
178                 switch(c) {
179                 case 'e':
180                         /*
181                          * name=value:name=value:name=value...
182                          */
183                         n = strlen(optarg);
184                         kern_envp = malloc(n + 2);
185                         for (i = 0; i < n; ++i) {
186                                 if (optarg[i] == ':')
187                                         kern_envp[i] = 0;
188                                 else
189                                         kern_envp[i] = optarg[i];
190                         }
191                         kern_envp[i++] = 0;
192                         kern_envp[i++] = 0;
193                         break;
194                 case 's':
195                         boothowto |= RB_SINGLE;
196                         break;
197                 case 'v':
198                         bootverbose = 1;
199                         break;
200                 case 'i':
201                         memImageFile = optarg;
202                         break;
203                 case 'I':
204                         if (netifFileNum < VKNETIF_MAX)
205                                 netifFile[netifFileNum++] = strdup(optarg);
206                         break;
207                 case 'r':
208                         if (bootOnDisk < 0)
209                                 bootOnDisk = 1;
210                         if (diskFileNum + cdFileNum < VKDISK_MAX)
211                                 diskFile[diskFileNum++] = strdup(optarg);
212                         break;
213                 case 'c':
214                         if (bootOnDisk < 0)
215                                 bootOnDisk = 0;
216                         if (diskFileNum + cdFileNum < VKDISK_MAX)
217                                 cdFile[cdFileNum++] = strdup(optarg);
218                         break;
219                 case 'm':
220                         Maxmem_bytes = strtoull(optarg, &suffix, 0);
221                         if (suffix) {
222                                 switch(*suffix) {
223                                 case 'g':
224                                 case 'G':
225                                         Maxmem_bytes <<= 30;
226                                         break;
227                                 case 'm':
228                                 case 'M':
229                                         Maxmem_bytes <<= 20;
230                                         break;
231                                 case 'k':
232                                 case 'K':
233                                         Maxmem_bytes <<= 10;
234                                         break;
235                                 default:
236                                         Maxmem_bytes = 0;
237                                         usage("Bad maxmem option");
238                                         /* NOT REACHED */
239                                         break;
240                                 }
241                         }
242                         break;
243                 case 'l':
244                         next_cpu = -1;
245                         if (strncmp("map", optarg, 3) == 0) {
246                                 lwp_cpu_lock = LCL_PER_CPU;
247                                 if (optarg[3] == ',') {
248                                         next_cpu = strtol(optarg+4, &endp, 0);
249                                         if (*endp != '\0')
250                                                 usage("Bad target CPU number at '%s'", endp);
251                                 } else {
252                                         next_cpu = 0;
253                                 }
254                                 if (next_cpu < 0 || next_cpu > real_ncpus - 1)
255                                         usage("Bad target CPU, valid range is 0-%d", real_ncpus - 1);
256                         } else if (strncmp("any", optarg, 3) == 0) {
257                                 lwp_cpu_lock = LCL_NONE;
258                         } else {
259                                 lwp_cpu_lock = LCL_SINGLE_CPU;
260                                 next_cpu = strtol(optarg, &endp, 0);
261                                 if (*endp != '\0')
262                                         usage("Bad target CPU number at '%s'", endp);
263                                 if (next_cpu < 0 || next_cpu > real_ncpus - 1)
264                                         usage("Bad target CPU, valid range is 0-%d", real_ncpus - 1);
265                         }
266                         break;
267                 case 'n':
268                         /*
269                          * This value is set up by mp_start(), don't just
270                          * set ncpus here.
271                          */
272 #ifdef SMP
273                         optcpus = strtol(optarg, NULL, 0);
274                         if (optcpus < 1 || optcpus > MAXCPU)
275                                 usage("Bad ncpus, valid range is 1-%d", MAXCPU);
276 #else
277                         if (strtol(optarg, NULL, 0) != 1) {
278                                 usage("You built a UP vkernel, only 1 cpu!");
279                         }
280 #endif
281                         
282                         break;
283                 case 'p':
284                         pid_file = optarg;      
285                         break;
286                 case 'U':
287                         kernel_mem_readonly = 0;
288                         break;
289                 }
290         }
291
292         writepid();
293         cpu_disable_intr();
294         init_sys_memory(memImageFile);
295         init_kern_memory();
296         init_globaldata();
297         init_vkernel();
298         setrealcpu();
299         init_kqueue();
300
301         /*
302          * Check TSC
303          */
304         vsize = sizeof(tsc_present);
305         sysctlbyname("hw.tsc_present", &tsc_present, &vsize, NULL, 0);
306         vsize = sizeof(tsc_frequency);
307         sysctlbyname("hw.tsc_frequency", &tsc_frequency, &vsize, NULL, 0);
308         if (tsc_present)
309                 cpu_feature |= CPUID_TSC;
310
311         /*
312          * Check SSE
313          */
314         vsize = sizeof(supports_sse);
315         supports_sse = 0;
316         sysctlbyname("hw.instruction_sse", &supports_sse, &vsize, NULL, 0);
317         init_fpu(supports_sse);
318         if (supports_sse)
319                 cpu_feature |= CPUID_SSE | CPUID_FXSR;
320
321         /*
322          * We boot from the first installed disk.
323          */
324         if (bootOnDisk == 1) {
325                 init_disk(diskFile, diskFileNum, VKD_DISK);
326                 init_disk(cdFile, cdFileNum, VKD_CD);
327         } else {
328                 init_disk(cdFile, cdFileNum, VKD_CD);
329                 init_disk(diskFile, diskFileNum, VKD_DISK);
330         }
331         init_netif(netifFile, netifFileNum);
332         init_exceptions();
333         mi_startup();
334         /* NOT REACHED */
335         exit(1);
336 }
337
338 /*
339  * Initialize system memory.  This is the virtual kernel's 'RAM'.
340  */
341 static
342 void
343 init_sys_memory(char *imageFile)
344 {
345         struct stat st;
346         int i;
347         int fd;
348
349         /*
350          * Figure out the system memory image size.  If an image file was
351          * specified and -m was not specified, use the image file's size.
352          */
353
354         if (imageFile && stat(imageFile, &st) == 0 && Maxmem_bytes == 0)
355                 Maxmem_bytes = (vm_paddr_t)st.st_size;
356         if ((imageFile == NULL || stat(imageFile, &st) < 0) && 
357             Maxmem_bytes == 0) {
358                 err(1, "Cannot create new memory file %s unless "
359                        "system memory size is specified with -m",
360                        imageFile);
361                 /* NOT REACHED */
362         }
363
364         /*
365          * Maxmem must be known at this time
366          */
367         if (Maxmem_bytes < 32 * 1024 * 1024 || (Maxmem_bytes & SEG_MASK)) {
368                 err(1, "Bad maxmem specification: 32MB minimum, "
369                        "multiples of %dMB only",
370                        SEG_SIZE / 1024 / 1024);
371                 /* NOT REACHED */
372         }
373
374         /*
375          * Generate an image file name if necessary, then open/create the
376          * file exclusively locked.  Do not allow multiple virtual kernels
377          * to use the same image file.
378          */
379         if (imageFile == NULL) {
380                 for (i = 0; i < 1000000; ++i) {
381                         asprintf(&imageFile, "/var/vkernel/memimg.%06d", i);
382                         fd = open(imageFile, 
383                                   O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
384                         if (fd < 0 && errno == EWOULDBLOCK) {
385                                 free(imageFile);
386                                 continue;
387                         }
388                         break;
389                 }
390         } else {
391                 fd = open(imageFile, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
392         }
393         printf("Using memory file: %s\n", imageFile);
394         if (fd < 0 || fstat(fd, &st) < 0) {
395                 err(1, "Unable to open/create %s", imageFile);
396                 /* NOT REACHED */
397         }
398
399         /*
400          * Truncate or extend the file as necessary.
401          */
402         if (st.st_size > Maxmem_bytes) {
403                 ftruncate(fd, Maxmem_bytes);
404         } else if (st.st_size < Maxmem_bytes) {
405                 char *zmem;
406                 off_t off = st.st_size & ~SEG_MASK;
407
408                 kprintf("%s: Reserving blocks for memory image\n", imageFile);
409                 zmem = malloc(SEG_SIZE);
410                 bzero(zmem, SEG_SIZE);
411                 lseek(fd, off, SEEK_SET);
412                 while (off < Maxmem_bytes) {
413                         if (write(fd, zmem, SEG_SIZE) != SEG_SIZE) {
414                                 err(1, "Unable to reserve blocks for memory image");
415                                 /* NOT REACHED */
416                         }
417                         off += SEG_SIZE;
418                 }
419                 if (fsync(fd) < 0)
420                         err(1, "Unable to reserve blocks for memory image");
421                 free(zmem);
422         }
423         MemImageFd = fd;
424         Maxmem = Maxmem_bytes >> PAGE_SHIFT;
425 }
426
427 /*
428  * Initialize kernel memory.  This reserves kernel virtual memory by using
429  * MAP_VPAGETABLE
430  */
431
432 static
433 void
434 init_kern_memory(void)
435 {
436         void *base;
437         void *try;
438         char *zero;
439         char dummy;
440         char *topofstack = &dummy;
441         vpte_t pte;
442         int i;
443
444         /*
445          * Memory map our kernel virtual memory space.  Note that the
446          * kernel image itself is not made part of this memory for the
447          * moment.
448          *
449          * The memory map must be segment-aligned so we can properly
450          * offset KernelPTD.
451          *
452          * If the system kernel has a different MAXDSIZ, it might not
453          * be possible to map kernel memory in its prefered location.
454          * Try a number of different locations.
455          */
456         try = (void *)0x40000000;
457         base = NULL;
458         while ((char *)try + KERNEL_KVA_SIZE < topofstack) {
459                 base = mmap(try, KERNEL_KVA_SIZE, PROT_READ|PROT_WRITE,
460                             MAP_FILE|MAP_SHARED|MAP_VPAGETABLE,
461                             MemImageFd, 0);
462                 if (base == try)
463                         break;
464                 if (base != MAP_FAILED)
465                         munmap(base, KERNEL_KVA_SIZE);
466                 try = (char *)try + 0x10000000;
467         }
468         if (base != try) {
469                 err(1, "Unable to mmap() kernel virtual memory!");
470                 /* NOT REACHED */
471         }
472         madvise(base, KERNEL_KVA_SIZE, MADV_NOSYNC);
473         KvaStart = (vm_offset_t)base;
474         KvaSize = KERNEL_KVA_SIZE;
475         KvaEnd = KvaStart + KvaSize;
476         printf("KVM mapped at %p-%p\n", (void *)KvaStart, (void *)KvaEnd);
477
478         /*
479          * Create a top-level page table self-mapping itself. 
480          *
481          * Initialize the page directory at physical page index 0 to point
482          * to an array of page table pages starting at physical page index 1
483          */
484         lseek(MemImageFd, 0L, 0);
485         for (i = 0; i < KERNEL_KVA_SIZE / SEG_SIZE; ++i) {
486                 pte = ((i + 1) * PAGE_SIZE) | VPTE_V | VPTE_R | VPTE_W;
487                 write(MemImageFd, &pte, sizeof(pte));
488         }
489
490         /*
491          * Initialize the PTEs in the page table pages required to map the
492          * page table itself.  This includes mapping the page directory page
493          * at the base so we go one more loop then normal.
494          */
495         lseek(MemImageFd, PAGE_SIZE, 0);
496         for (i = 0; i <= KERNEL_KVA_SIZE / SEG_SIZE * sizeof(vpte_t); ++i) {
497                 pte = (i * PAGE_SIZE) | VPTE_V | VPTE_R | VPTE_W;
498                 write(MemImageFd, &pte, sizeof(pte));
499         }
500
501         /*
502          * Initialize remaining PTEs to 0.  We may be reusing a memory image
503          * file.  This is approximately a megabyte.
504          */
505         i = (KERNEL_KVA_SIZE / PAGE_SIZE - i) * sizeof(pte);
506         zero = malloc(PAGE_SIZE);
507         bzero(zero, PAGE_SIZE);
508         while (i) {
509                 write(MemImageFd, zero, (i > PAGE_SIZE) ? PAGE_SIZE : i);
510                 i = i - ((i > PAGE_SIZE) ? PAGE_SIZE : i);
511         }
512         free(zero);
513
514         /*
515          * Enable the page table and calculate pointers to our self-map
516          * for easy kernel page table manipulation.
517          *
518          * KernelPTA must be offset so we can do direct VA translations
519          */
520         mcontrol(base, KERNEL_KVA_SIZE, MADV_SETMAP,
521                  0 | VPTE_R | VPTE_W | VPTE_V);
522         KernelPTD = (vpte_t *)base;                       /* pg directory */
523         KernelPTA = (vpte_t *)((char *)base + PAGE_SIZE); /* pg table pages */
524         KernelPTA -= KvaStart >> PAGE_SHIFT;
525
526         /*
527          * phys_avail[] represents unallocated physical memory.  MI code
528          * will use phys_avail[] to create the vm_page array.
529          */
530         phys_avail[0] = PAGE_SIZE +
531                         KERNEL_KVA_SIZE / PAGE_SIZE * sizeof(vpte_t);
532         phys_avail[0] = (phys_avail[0] + PAGE_MASK) & ~(vm_paddr_t)PAGE_MASK;
533         phys_avail[1] = Maxmem_bytes;
534
535         /*
536          * (virtual_start, virtual_end) represent unallocated kernel virtual
537          * memory.  MI code will create kernel_map using these parameters.
538          */
539         virtual_start = KvaStart + PAGE_SIZE +
540                         KERNEL_KVA_SIZE / PAGE_SIZE * sizeof(vpte_t);
541         virtual_start = (virtual_start + PAGE_MASK) & ~(vm_offset_t)PAGE_MASK;
542         virtual_end = KvaStart + KERNEL_KVA_SIZE;
543
544         /*
545          * kernel_vm_end could be set to virtual_end but we want some 
546          * indication of how much of the kernel_map we've used, so
547          * set it low and let pmap_growkernel increase it even though we
548          * don't need to create any new page table pages.
549          */
550         kernel_vm_end = virtual_start;
551
552         /*
553          * Allocate space for process 0's UAREA.
554          */
555         proc0paddr = (void *)virtual_start;
556         for (i = 0; i < UPAGES; ++i) {
557                 pmap_kenter_quick(virtual_start, phys_avail[0]);
558                 virtual_start += PAGE_SIZE;
559                 phys_avail[0] += PAGE_SIZE;
560         }
561
562         /*
563          * crashdumpmap
564          */
565         crashdumpmap = virtual_start;
566         virtual_start += MAXDUMPPGS * PAGE_SIZE;
567
568         /*
569          * msgbufp maps the system message buffer
570          */
571         assert((MSGBUF_SIZE & PAGE_MASK) == 0);
572         msgbufp = (void *)virtual_start;
573         for (i = 0; i < (MSGBUF_SIZE >> PAGE_SHIFT); ++i) {
574                 pmap_kenter_quick(virtual_start, phys_avail[0]);
575                 virtual_start += PAGE_SIZE;
576                 phys_avail[0] += PAGE_SIZE;
577         }
578         msgbufinit(msgbufp, MSGBUF_SIZE);
579
580         /*
581          * used by kern_memio for /dev/mem access
582          */
583         ptvmmap = (caddr_t)virtual_start;
584         virtual_start += PAGE_SIZE;
585
586         /*
587          * Bootstrap the kernel_pmap
588          */
589         pmap_bootstrap();
590 }
591
592 /*
593  * Map the per-cpu globaldata for cpu #0.  Allocate the space using
594  * virtual_start and phys_avail[0]
595  */
596 static
597 void
598 init_globaldata(void)
599 {
600         int i;
601         vm_paddr_t pa;
602         vm_offset_t va;
603
604         /*
605          * Reserve enough KVA to cover possible cpus.  This is a considerable
606          * amount of KVA since the privatespace structure includes two 
607          * whole page table mappings.
608          */
609         virtual_start = (virtual_start + SEG_MASK) & ~(vm_offset_t)SEG_MASK;
610         CPU_prvspace = (void *)virtual_start;
611         virtual_start += sizeof(struct privatespace) * SMP_MAXCPU;
612
613         /*
614          * Allocate enough physical memory to cover the mdglobaldata
615          * portion of the space and the idle stack and map the pages
616          * into KVA.  For cpu #0 only.
617          */
618         for (i = 0; i < sizeof(struct mdglobaldata); i += PAGE_SIZE) {
619                 pa = phys_avail[0];
620                 va = (vm_offset_t)&CPU_prvspace[0].mdglobaldata + i;
621                 pmap_kenter_quick(va, pa);
622                 phys_avail[0] += PAGE_SIZE;
623         }
624         for (i = 0; i < sizeof(CPU_prvspace[0].idlestack); i += PAGE_SIZE) {
625                 pa = phys_avail[0];
626                 va = (vm_offset_t)&CPU_prvspace[0].idlestack + i;
627                 pmap_kenter_quick(va, pa);
628                 phys_avail[0] += PAGE_SIZE;
629         }
630
631         /*
632          * Setup the %fs for cpu #0.  The mycpu macro works after this
633          * point.  Note that %gs is used by pthreads.
634          */
635         tls_set_fs(&CPU_prvspace[0], sizeof(struct privatespace));
636 }
637
638 /*
639  * Initialize very low level systems including thread0, proc0, etc.
640  */
641 static
642 void
643 init_vkernel(void)
644 {
645         struct mdglobaldata *gd;
646
647         gd = &CPU_prvspace[0].mdglobaldata;
648         bzero(gd, sizeof(*gd));
649
650         gd->mi.gd_curthread = &thread0;
651         thread0.td_gd = &gd->mi;
652         ncpus = 1;
653         ncpus2 = 1;     /* rounded down power of 2 */
654         ncpus_fit = 1;  /* rounded up power of 2 */
655         /* ncpus2_mask and ncpus_fit_mask are 0 */
656         init_param1();
657         gd->mi.gd_prvspace = &CPU_prvspace[0];
658         mi_gdinit(&gd->mi, 0);
659         cpu_gdinit(gd, 0);
660         mi_proc0init(&gd->mi, proc0paddr);
661         lwp0.lwp_md.md_regs = &proc0_tf;
662
663         /*init_locks();*/
664         cninit();
665         rand_initialize();
666 #if 0   /* #ifdef DDB */
667         kdb_init();
668         if (boothowto & RB_KDB)
669                 Debugger("Boot flags requested debugger");
670 #endif
671         identcpu();
672 #if 0
673         initializecpu();        /* Initialize CPU registers */
674 #endif
675         init_param2((phys_avail[1] - phys_avail[0]) / PAGE_SIZE);
676
677 #if 0
678         /*
679          * Map the message buffer
680          */
681         for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
682                 pmap_kenter((vm_offset_t)msgbufp + off, avail_end + off);
683         msgbufinit(msgbufp, MSGBUF_SIZE);
684 #endif
685 #if 0
686         thread0.td_pcb_cr3 ... MMU
687         lwp0.lwp_md.md_regs = &proc0_tf;
688 #endif
689 }
690
691 /*
692  * Filesystem image paths for the virtual kernel are optional.  
693  * If specified they each should point to a disk image, 
694  * the first of which will become the root disk.
695  *
696  * The virtual kernel caches data from our 'disk' just like a normal kernel,
697  * so we do not really want the real kernel to cache the data too.  Use
698  * O_DIRECT to remove the duplication.
699  */
700 static
701 void
702 init_disk(char *diskExp[], int diskFileNum, enum vkdisk_type type)
703 {
704         int i;  
705
706         if (diskFileNum == 0)
707                 return;
708
709         for(i=0; i < diskFileNum; i++){
710                 char *fname;
711                 fname = diskExp[i];
712
713                 if (fname == NULL) {
714                         warnx("Invalid argument to '-r'");
715                         continue;
716                 }
717
718                 if (DiskNum < VKDISK_MAX) {
719                         struct stat st; 
720                         struct vkdisk_info* info = NULL;
721                         int fd;
722                         size_t l = 0;
723
724                         if (type == VKD_DISK)
725                             fd = open(fname, O_RDWR|O_DIRECT|O_EXLOCK|O_NONBLOCK, 0644);
726                         else
727                             fd = open(fname, O_RDONLY|O_DIRECT, 0644);
728                         if (fd < 0 || fstat(fd, &st) < 0) {
729                                 if (errno == EAGAIN)
730                                         fprintf(stderr, "You may already have a vkernel using this disk image!\n");
731                                 err(1, "Unable to open/create %s", fname);
732                                 /* NOT REACHED */
733                         }
734                         /* get rid of O_NONBLOCK, keep O_DIRECT */
735                         if (type == VKD_DISK)
736                                 fcntl(fd, F_SETFL, O_DIRECT);
737
738                         info = &DiskInfo[DiskNum];
739                         l = strlen(fname);
740
741                         info->unit = i;
742                         info->fd = fd;
743                         info->type = type;
744                         memcpy(info->fname, fname, l);
745
746                         if (DiskNum == 0) {
747                                 if (type == VKD_CD)
748                                     rootdevnames[0] = "cd9660:vcd0a";
749                                 else if (type == VKD_DISK)
750                                     rootdevnames[0] = "ufs:vkd0s0a";
751                         }
752
753                         DiskNum++;
754                 } else {
755                         warnx("vkd%d (%s) > VKDISK_MAX", DiskNum, fname);
756                         continue;
757                 }
758         }
759 }
760
761 static
762 int
763 netif_set_tapflags(int tap_unit, int f, int s)
764 {
765         struct ifreq ifr;
766         int flags;
767
768         bzero(&ifr, sizeof(ifr));
769
770         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tap%d", tap_unit);
771         if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
772                 warn("tap%d: ioctl(SIOCGIFFLAGS) failed", tap_unit);
773                 return -1;
774         }
775
776         /*
777          * Adjust if_flags
778          *
779          * If the flags are already set/cleared, then we return
780          * immediately to avoid extra syscalls
781          */
782         flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
783         if (f < 0) {
784                 /* Turn off flags */
785                 f = -f;
786                 if ((flags & f) == 0)
787                         return 0;
788                 flags &= ~f;
789         } else {
790                 /* Turn on flags */
791                 if (flags & f)
792                         return 0;
793                 flags |= f;
794         }
795
796         /*
797          * Fix up ifreq.ifr_name, since it may be trashed
798          * in previous ioctl(SIOCGIFFLAGS)
799          */
800         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tap%d", tap_unit);
801
802         ifr.ifr_flags = flags & 0xffff;
803         ifr.ifr_flagshigh = flags >> 16;
804         if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
805                 warn("tap%d: ioctl(SIOCSIFFLAGS) failed", tap_unit);
806                 return -1;
807         }
808         return 0;
809 }
810
811 static
812 int
813 netif_set_tapaddr(int tap_unit, in_addr_t addr, in_addr_t mask, int s)
814 {
815         struct ifaliasreq ifra;
816         struct sockaddr_in *in;
817
818         bzero(&ifra, sizeof(ifra));
819         snprintf(ifra.ifra_name, sizeof(ifra.ifra_name), "tap%d", tap_unit);
820
821         /* Setup address */
822         in = (struct sockaddr_in *)&ifra.ifra_addr;
823         in->sin_family = AF_INET;
824         in->sin_len = sizeof(*in);
825         in->sin_addr.s_addr = addr;
826
827         if (mask != 0) {
828                 /* Setup netmask */
829                 in = (struct sockaddr_in *)&ifra.ifra_mask;
830                 in->sin_len = sizeof(*in);
831                 in->sin_addr.s_addr = mask;
832         }
833
834         if (ioctl(s, SIOCAIFADDR, &ifra) < 0) {
835                 warn("tap%d: ioctl(SIOCAIFADDR) failed", tap_unit);
836                 return -1;
837         }
838         return 0;
839 }
840
841 static
842 int
843 netif_add_tap2brg(int tap_unit, const char *ifbridge, int s)
844 {
845         struct ifbreq ifbr;
846         struct ifdrv ifd;
847
848         bzero(&ifbr, sizeof(ifbr));
849         snprintf(ifbr.ifbr_ifsname, sizeof(ifbr.ifbr_ifsname),
850                  "tap%d", tap_unit);
851
852         bzero(&ifd, sizeof(ifd));
853         strlcpy(ifd.ifd_name, ifbridge, sizeof(ifd.ifd_name));
854         ifd.ifd_cmd = BRDGADD;
855         ifd.ifd_len = sizeof(ifbr);
856         ifd.ifd_data = &ifbr;
857
858         if (ioctl(s, SIOCSDRVSPEC, &ifd) < 0) {
859                 /*
860                  * 'errno == EEXIST' means that the tap(4) is already
861                  * a member of the bridge(4)
862                  */
863                 if (errno != EEXIST) {
864                         warn("ioctl(%s, SIOCSDRVSPEC) failed", ifbridge);
865                         return -1;
866                 }
867         }
868         return 0;
869 }
870
871 #define TAPDEV_OFLAGS   (O_RDWR | O_NONBLOCK)
872
873 /* XXX major()/minor() can't be used in vkernel */
874 #define TAPDEV_MAJOR(x) ((int)(((u_int)(x) >> 8) & 0xff))
875 #define TAPDEV_MINOR(x) ((int)((x) & 0xffff00ff))
876
877 #ifndef TAP_CDEV_MAJOR
878 #define TAP_CDEV_MAJOR  149
879 #endif
880
881 /*
882  * Locate the first unused tap(4) device file if auto mode is requested,
883  * or open the user supplied device file, and bring up the corresponding
884  * tap(4) interface.
885  *
886  * NOTE: Only tap(4) device file is supported currently
887  */
888 static
889 int
890 netif_open_tap(const char *netif, int *tap_unit, int s)
891 {
892         char tap_dev[MAXPATHLEN];
893         int tap_fd, failed;
894         struct stat st;
895
896         *tap_unit = -1;
897
898         if (strcmp(netif, "auto") == 0) {
899                 int i;
900                 int lasterr = 0;
901
902                 /*
903                  * Find first unused tap(4) device file
904                  */
905                 for (i = 0; ; ++i) {
906                         snprintf(tap_dev, sizeof(tap_dev), "/dev/tap%d", i);
907                         tap_fd = open(tap_dev, TAPDEV_OFLAGS);
908                         if (tap_fd >= 0 || errno == ENOENT)
909                                 break;
910                         lasterr = errno;
911                 }
912                 if (tap_fd < 0) {
913                         warnc(lasterr, "Unable to find a free tap(4)");
914                         return -1;
915                 }
916         } else {
917                 /*
918                  * User supplied tap(4) device file or unix socket.
919                  */
920                 if (netif[0] == '/')    /* Absolute path */
921                         strlcpy(tap_dev, netif, sizeof(tap_dev));
922                 else
923                         snprintf(tap_dev, sizeof(tap_dev), "/dev/%s", netif);
924
925                 tap_fd = open(tap_dev, TAPDEV_OFLAGS);
926
927                 /*
928                  * If we cannot open normally try to connect to it.
929                  */
930                 if (tap_fd < 0)
931                         tap_fd = unix_connect(tap_dev);
932
933                 if (tap_fd < 0) {
934                         warn("Unable to open %s", tap_dev);
935                         return -1;
936                 }
937         }
938
939         /*
940          * Check whether the device file is a tap(4)
941          */
942         failed = 1;
943         if (fstat(tap_fd, &st) == 0 && S_ISCHR(st.st_mode) &&
944             TAPDEV_MAJOR(st.st_rdev) == TAP_CDEV_MAJOR) {
945                 *tap_unit = TAPDEV_MINOR(st.st_rdev);
946
947                 /*
948                  * Bring up the corresponding tap(4) interface
949                  */
950                 if (netif_set_tapflags(*tap_unit, IFF_UP, s) == 0)
951                         failed = 0;
952         } else if (S_ISSOCK(st.st_mode)) {
953                 /*
954                  * Special socket connection (typically to vknet).  We
955                  * do not have to do anything.
956                  */
957                 failed = 0;
958         } else {
959                 warnx("%s is not a tap(4) device", tap_dev);
960         }
961
962         if (failed) {
963                 close(tap_fd);
964                 tap_fd = -1;
965                 *tap_unit = -1;
966         }
967         return tap_fd;
968 }
969
970 static int
971 unix_connect(const char *path)
972 {
973         struct sockaddr_un sunx;
974         int len;
975         int net_fd;
976         int sndbuf = 262144;
977         struct stat st;
978
979         snprintf(sunx.sun_path, sizeof(sunx.sun_path), "%s", path);
980         len = offsetof(struct sockaddr_un, sun_path[strlen(sunx.sun_path)]);
981         ++len;  /* include nul */
982         sunx.sun_family = AF_UNIX;
983         sunx.sun_len = len;
984
985         net_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
986         if (net_fd < 0)
987                 return(-1);
988         if (connect(net_fd, (void *)&sunx, len) < 0) {
989                 close(net_fd);
990                 return(-1);
991         }
992         setsockopt(net_fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
993         if (fstat(net_fd, &st) == 0)
994                 printf("Network socket buffer: %d bytes\n", st.st_blksize);
995         fcntl(net_fd, F_SETFL, O_NONBLOCK);
996         return(net_fd);
997 }
998
999 #undef TAPDEV_MAJOR
1000 #undef TAPDEV_MINOR
1001 #undef TAPDEV_OFLAGS
1002
1003 /*
1004  * Following syntax is supported,
1005  * 1) x.x.x.x             tap(4)'s address is x.x.x.x
1006  *
1007  * 2) x.x.x.x/z           tap(4)'s address is x.x.x.x
1008  *                        tap(4)'s netmask len is z
1009  *
1010  * 3) x.x.x.x:y.y.y.y     tap(4)'s address is x.x.x.x
1011  *                        pseudo netif's address is y.y.y.y
1012  *
1013  * 4) x.x.x.x:y.y.y.y/z   tap(4)'s address is x.x.x.x
1014  *                        pseudo netif's address is y.y.y.y
1015  *                        tap(4) and pseudo netif's netmask len are z
1016  *
1017  * 5) bridgeX             tap(4) will be added to bridgeX
1018  *
1019  * 6) bridgeX:y.y.y.y     tap(4) will be added to bridgeX
1020  *                        pseudo netif's address is y.y.y.y
1021  *
1022  * 7) bridgeX:y.y.y.y/z   tap(4) will be added to bridgeX
1023  *                        pseudo netif's address is y.y.y.y
1024  *                        pseudo netif's netmask len is z
1025  */
1026 static
1027 int
1028 netif_init_tap(int tap_unit, in_addr_t *addr, in_addr_t *mask, int s)
1029 {
1030         in_addr_t tap_addr, netmask, netif_addr;
1031         int next_netif_addr;
1032         char *tok, *masklen_str, *ifbridge;
1033
1034         *addr = 0;
1035         *mask = 0;
1036
1037         tok = strtok(NULL, ":/");
1038         if (tok == NULL) {
1039                 /*
1040                  * Nothing special, simply use tap(4) as backend
1041                  */
1042                 return 0;
1043         }
1044
1045         if (inet_pton(AF_INET, tok, &tap_addr) > 0) {
1046                 /*
1047                  * tap(4)'s address is supplied
1048                  */
1049                 ifbridge = NULL;
1050
1051                 /*
1052                  * If there is next token, then it may be pseudo
1053                  * netif's address or netmask len for tap(4)
1054                  */
1055                 next_netif_addr = 0;
1056         } else {
1057                 /*
1058                  * Not tap(4)'s address, assume it as a bridge(4)
1059                  * iface name
1060                  */
1061                 tap_addr = 0;
1062                 ifbridge = tok;
1063
1064                 /*
1065                  * If there is next token, then it must be pseudo
1066                  * netif's address
1067                  */
1068                 next_netif_addr = 1;
1069         }
1070
1071         netmask = netif_addr = 0;
1072
1073         tok = strtok(NULL, ":/");
1074         if (tok == NULL)
1075                 goto back;
1076
1077         if (inet_pton(AF_INET, tok, &netif_addr) <= 0) {
1078                 if (next_netif_addr) {
1079                         warnx("Invalid pseudo netif address: %s", tok);
1080                         return -1;
1081                 }
1082                 netif_addr = 0;
1083
1084                 /*
1085                  * Current token is not address, then it must be netmask len
1086                  */
1087                 masklen_str = tok;
1088         } else {
1089                 /*
1090                  * Current token is pseudo netif address, if there is next token
1091                  * it must be netmask len
1092                  */
1093                 masklen_str = strtok(NULL, "/");
1094         }
1095
1096         /* Calculate netmask */
1097         if (masklen_str != NULL) {
1098                 u_long masklen;
1099
1100                 masklen = strtoul(masklen_str, NULL, 10);
1101                 if (masklen < 32 && masklen > 0) {
1102                         netmask = htonl(~((1LL << (32 - masklen)) - 1)
1103                                         & 0xffffffff);
1104                 } else {
1105                         warnx("Invalid netmask len: %lu", masklen);
1106                         return -1;
1107                 }
1108         }
1109
1110         /* Make sure there is no more token left */
1111         if (strtok(NULL, ":/") != NULL) {
1112                 warnx("Invalid argument to '-I'");
1113                 return -1;
1114         }
1115
1116 back:
1117         if (tap_unit < 0) {
1118                 /* Do nothing */
1119         } else if (ifbridge == NULL) {
1120                 /* Set tap(4) address/netmask */
1121                 if (netif_set_tapaddr(tap_unit, tap_addr, netmask, s) < 0)
1122                         return -1;
1123         } else {
1124                 /* Tie tap(4) to bridge(4) */
1125                 if (netif_add_tap2brg(tap_unit, ifbridge, s) < 0)
1126                         return -1;
1127         }
1128
1129         *addr = netif_addr;
1130         *mask = netmask;
1131         return 0;
1132 }
1133
1134 /*
1135  * NetifInfo[] will be filled for pseudo netif initialization.
1136  * NetifNum will be bumped to reflect the number of valid entries
1137  * in NetifInfo[].
1138  */
1139 static
1140 void
1141 init_netif(char *netifExp[], int netifExpNum)
1142 {
1143         int i, s;
1144
1145         if (netifExpNum == 0)
1146                 return;
1147
1148         s = socket(AF_INET, SOCK_DGRAM, 0);     /* for ioctl(SIOC) */
1149         if (s < 0)
1150                 return;
1151
1152         for (i = 0; i < netifExpNum; ++i) {
1153                 struct vknetif_info *info;
1154                 in_addr_t netif_addr, netif_mask;
1155                 int tap_fd, tap_unit;
1156                 char *netif;
1157
1158                 netif = strtok(netifExp[i], ":");
1159                 if (netif == NULL) {
1160                         warnx("Invalid argument to '-I'");
1161                         continue;
1162                 }
1163
1164                 /*
1165                  * Open tap(4) device file and bring up the
1166                  * corresponding interface
1167                  */
1168                 tap_fd = netif_open_tap(netif, &tap_unit, s);
1169                 if (tap_fd < 0)
1170                         continue;
1171
1172                 /*
1173                  * Initialize tap(4) and get address/netmask
1174                  * for pseudo netif
1175                  *
1176                  * NB: Rest part of netifExp[i] is passed
1177                  *     to netif_init_tap() implicitly.
1178                  */
1179                 if (netif_init_tap(tap_unit, &netif_addr, &netif_mask, s) < 0) {
1180                         /*
1181                          * NB: Closing tap(4) device file will bring
1182                          *     down the corresponding interface
1183                          */
1184                         close(tap_fd);
1185                         continue;
1186                 }
1187
1188                 info = &NetifInfo[NetifNum];
1189                 info->tap_fd = tap_fd;
1190                 info->tap_unit = tap_unit;
1191                 info->netif_addr = netif_addr;
1192                 info->netif_mask = netif_mask;
1193
1194                 NetifNum++;
1195                 if (NetifNum >= VKNETIF_MAX)    /* XXX will this happen? */
1196                         break;
1197         }
1198         close(s);
1199 }
1200
1201 static
1202 void
1203 writepid( void )
1204 {
1205         pid_t self;
1206         FILE *fp;
1207
1208         if (pid_file != NULL) {
1209                 self = getpid();
1210                 fp = fopen(pid_file, "w");
1211
1212                 if (fp != NULL) {
1213                         fprintf(fp, "%ld\n", (long)self);
1214                         fclose(fp);
1215                 }
1216                 else {
1217                         perror("Warning: couldn't open pidfile");
1218                 }
1219         }
1220 }
1221
1222 static
1223 void
1224 cleanpid( void ) 
1225 {
1226         if (pid_file != NULL) {
1227                 if ( unlink(pid_file) != 0 )
1228                         perror("Warning: couldn't remove pidfile");
1229         }
1230 }
1231
1232 static
1233 void
1234 usage(const char *ctl, ...)
1235 {
1236         va_list va;
1237
1238         va_start(va, ctl);
1239         vfprintf(stderr, ctl, va);
1240         va_end(va);
1241         fprintf(stderr, "\n");
1242         exit(1);
1243 }
1244
1245 void
1246 cpu_reset(void)
1247 {
1248         kprintf("cpu reset, rebooting vkernel\n");
1249         closefrom(3);
1250         cleanpid();
1251         execv(save_av[0], save_av);
1252 }
1253
1254 void
1255 cpu_halt(void)
1256 {
1257         kprintf("cpu halt, exiting vkernel\n");
1258         cleanpid();
1259         exit(0);
1260 }
1261
1262 void
1263 setrealcpu(void)
1264 {
1265         switch(lwp_cpu_lock) {
1266         case LCL_PER_CPU:
1267                 if (bootverbose)
1268                         kprintf("Locking CPU%d to real cpu %d\n",
1269                                 mycpuid, next_cpu);
1270                 usched_set(getpid(), USCHED_SET_CPU, &next_cpu, sizeof(next_cpu));
1271                 next_cpu++;
1272                 if (next_cpu >= real_ncpus)
1273                         next_cpu = 0;
1274                 break;
1275         case LCL_SINGLE_CPU:
1276                 if (bootverbose)
1277                         kprintf("Locking CPU%d to real cpu %d\n",
1278                                 mycpuid, next_cpu);
1279                 usched_set(getpid(), USCHED_SET_CPU, &next_cpu, sizeof(next_cpu));
1280                 break;
1281         default:
1282                 /* do not map virtual cpus to real cpus */
1283                 break;
1284         }
1285 }
1286