Merge from vendor branch FILE:
[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.2 2006/12/05 23:14:54 dillon Exp $
35  */
36
37 #include <sys/types.h>
38 #include <sys/systm.h>
39 #include <sys/stat.h>
40 #include <sys/mman.h>
41 #include <vm/vm_page.h>
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <fcntl.h>
47 #include <string.h>
48 #include <err.h>
49 #include <errno.h>
50
51 vm_paddr_t Maxmem;
52 int MemImageFd = -1;
53 int RootImageFd = -1;
54 vm_offset_t KvaBase;
55 vm_offset_t KvaSize;
56
57 static void init_sys_memory(char *imageFile);
58 static void init_kern_memory(void);
59 static void init_rootdevice(char *imageFile);
60 static void usage(const char *ctl);
61
62 /*
63  * Kernel startup for virtual kernels - standard main() 
64  */
65 int
66 main(int ac, char **av)
67 {
68         char *memImageFile = NULL;
69         char *rootImageFile = NULL;
70         char *suffix;
71         int c;
72
73         /*
74          * Process options
75          */
76         while ((c = getopt(ac, av, "vm:")) != -1) {
77                 switch(c) {
78                 case 'v':
79                         bootverbose = 1;
80                         break;
81                 case 'i':
82                         memImageFile = optarg;
83                         break;
84                 case 'r':
85                         rootImageFile = optarg;
86                         break;
87                 case 'm':
88                         Maxmem = strtoull(optarg, &suffix, 0);
89                         if (suffix) {
90                                 switch(*suffix) {
91                                 case 'g':
92                                 case 'G':
93                                         Maxmem <<= 30;
94                                         break;
95                                 case 'm':
96                                 case 'M':
97                                         Maxmem <<= 20;
98                                         break;
99                                 case 'k':
100                                 case 'K':
101                                         Maxmem <<= 10;
102                                         break;
103                                 default:
104                                         Maxmem = 0;
105                                         usage("Bad maxmem option");
106                                         /* NOT REACHED */
107                                         break;
108                                 }
109                         }
110                         break;
111                 }
112         }
113
114         init_sys_memory(memImageFile);
115         init_kern_memory();
116         init_rootdevice(rootImageFile);
117         mi_startup();
118         /* NOT REACHED */
119         exit(1);
120 }
121
122 /*
123  * Initialize system memory.  This is the virtual kernel's 'RAM'.
124  */
125 static
126 void
127 init_sys_memory(char *imageFile)
128 {
129         struct stat st;
130         int fd;
131
132         /*
133          * Figure out the system memory image size.  If an image file was
134          * specified and -m was not specified, use the image file's size.
135          */
136
137         if (imageFile && stat(imageFile, &st) == 0 && Maxmem == 0)
138                 Maxmem = (vm_paddr_t)st.st_size;
139         if ((imageFile == NULL || stat(imageFile, &st) < 0) && Maxmem == 0) {
140                 err(1, "Cannot create new memory file %s unless "
141                        "system memory size is specified with -m",
142                        imageFile);
143                 /* NOT REACHED */
144         }
145
146         /*
147          * Maxmem must be known at this time
148          */
149         if (Maxmem < 32 * 1024 * 1024 || (Maxmem & SEG_MASK)) {
150                 err(1, "Bad maxmem specification: 32MB minimum, "
151                        "multiples of %dMB only",
152                        SEG_SIZE / 1024 / 1024);
153                 /* NOT REACHED */
154         }
155
156         /*
157          * Generate an image file name if necessary, then open/create the
158          * file exclusively locked.  Do not allow multiple virtual kernels
159          * to use the same image file.
160          */
161         if (imageFile == NULL)
162                 asprintf(&imageFile, "/var/vkernel/image.%05d", (int)getpid());
163         fd = open(imageFile, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
164         if (fd < 0 || fstat(fd, &st) < 0) {
165                 err(1, "Unable to open/create %s: %s",
166                       imageFile, strerror(errno));
167                 /* NOT REACHED */
168         }
169
170         /*
171          * Truncate or extend the file as necessary.
172          */
173         if (st.st_size > Maxmem) {
174                 ftruncate(fd, Maxmem);
175         } else if (st.st_size < Maxmem) {
176                 char *zmem;
177                 off_t off = st.st_size & ~SEG_MASK;
178
179                 printf("%s: Reserving blocks for memory image\n", imageFile);
180                 zmem = malloc(SEG_SIZE);
181                 bzero(zmem, SEG_SIZE);
182                 lseek(fd, off, 0);
183                 while (off < Maxmem) {
184                         if (write(fd, zmem, SEG_SIZE) != SEG_SIZE) {
185                                 err(1, "Unable to reserve blocks for memory image");
186                                 /* NOT REACHED */
187                         }
188                         off += SEG_SIZE;
189                 }
190                 if (fsync(fd) < 0)
191                         err(1, "Unable to reserve blocks for memory image");
192                 free(zmem);
193         }
194         MemImageFd = fd;
195 }
196
197 /*
198  * Initialize kernel memory.  This reserves kernel virtual memory by using
199  * MAP_VPAGETABLE
200  */
201 static
202 void
203 init_kern_memory(void)
204 {
205         void *base;
206
207         /*
208          * Memory map our kernel virtual memory space.  Note that the
209          * kernel image itself is not made part of this memory for the
210          * moment.
211          */
212         base = mmap(NULL, KERNEL_KVA_SIZE, PROT_READ|PROT_WRITE,
213                     MAP_FILE|MAP_VPAGETABLE, MemImageFd, 0);
214         if (base == MAP_FAILED) {
215                 err(1, "Unable to mmap() kernel virtual memory!");
216                 /* NOT REACHED */
217         }
218         KvaBase = (vm_offset_t)base;
219         KvaSize = KERNEL_KVA_SIZE;
220
221         /*
222          * Create a top-level page table self-mapping itself.
223          */
224 }
225
226 /*
227  * The root filesystem path for the virtual kernel is optional.  If specified
228  * it points to a filesystem image.
229  */
230 static
231 void
232 init_rootdevice(char *imageFile)
233 {
234 }
235
236 static
237 void
238 usage(const char *ctl)
239 {
240         
241 }
242