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