changeset 3415: | 4477c30eec57 |
parent: | 69064e032a3e |
child: | 9ebd6b091242 |
author: | cinap_lenrek@felloff.net |
date: | Tue, 04 Mar 2014 22:37:15 +0100 |
permissions: | -rw-r--r-- |
description: | pc64: fix segattach the comment about Physseg.size being in pages is wrong, change type to uintptr and correct the comment. change the length parameter of segattach() and isoverlap() to uintptr as well. segments can grow over 4GB in pc64 now and globalsegattach() in devsegment calculates len argument of isoverlap() by s->top - s->bot. note that the syscall still takes 32bit ulong argument for the length! check for integer overflow in segattach(), make sure segment goes not beyond USTKTOP. change PTEMAPMEM constant to uvlong as it is used to calculate SEGMAXSIZE. |
cinap_lenrek@2323 | 1 | #include "u.h" |
cinap_lenrek@2323 | 2 | #include "tos.h" |
cinap_lenrek@2323 | 3 | #include "../port/lib.h" |
cinap_lenrek@2323 | 4 | #include "mem.h" |
cinap_lenrek@2323 | 5 | #include "dat.h" |
cinap_lenrek@2323 | 6 | #include "fns.h" |
cinap_lenrek@2323 | 7 | |
cinap_lenrek@2323 | 8 | #include "init.h" |
cinap_lenrek@2323 | 9 | #include <pool.h> |
cinap_lenrek@2323 | 10 | |
cinap_lenrek@2323 | 11 | #include "reboot.h" |
cinap_lenrek@2323 | 12 | |
cinap_lenrek@2323 | 13 | /* Firmware compatibility */ |
cinap_lenrek@2323 | 14 | #define Minfirmrev 326770 |
cinap_lenrek@2323 | 15 | #define Minfirmdate "22 Jul 2012" |
cinap_lenrek@2323 | 16 | |
cinap_lenrek@2323 | 17 | /* |
cinap_lenrek@2323 | 18 | * Where configuration info is left for the loaded programme. |
cinap_lenrek@2323 | 19 | */ |
cinap_lenrek@2323 | 20 | #define BOOTARGS ((char*)CONFADDR) |
cinap_lenrek@2323 | 21 | #define BOOTARGSLEN (MACHADDR-CONFADDR) |
cinap_lenrek@2323 | 22 | #define MAXCONF 64 |
cinap_lenrek@2323 | 23 | #define MAXCONFLINE 160 |
cinap_lenrek@2323 | 24 | |
cinap_lenrek@2323 | 25 | uintptr kseg0 = KZERO; |
cinap_lenrek@2323 | 26 | Mach* machaddr[MAXMACH]; |
cinap_lenrek@2323 | 27 | Conf conf; |
cinap_lenrek@2323 | 28 | ulong memsize = 128*1024*1024; |
cinap_lenrek@2323 | 29 | |
cinap_lenrek@2323 | 30 | /* |
cinap_lenrek@2323 | 31 | * Option arguments from the command line. |
cinap_lenrek@2323 | 32 | * oargv[0] is the boot file. |
cinap_lenrek@2323 | 33 | */ |
cinap_lenrek@2323 | 34 | static int oargc; |
cinap_lenrek@2323 | 35 | static char* oargv[20]; |
cinap_lenrek@2323 | 36 | static char oargb[128]; |
cinap_lenrek@2323 | 37 | static int oargblen; |
cinap_lenrek@2323 | 38 | |
cinap_lenrek@2323 | 39 | static uintptr sp; /* XXX - must go - user stack of init proc */ |
cinap_lenrek@2323 | 40 | |
cinap_lenrek@2323 | 41 | /* store plan9.ini contents here at least until we stash them in #ec */ |
cinap_lenrek@2323 | 42 | static char confname[MAXCONF][KNAMELEN]; |
cinap_lenrek@2323 | 43 | static char confval[MAXCONF][MAXCONFLINE]; |
cinap_lenrek@2323 | 44 | static int nconf; |
cinap_lenrek@2323 | 45 | |
cinap_lenrek@2323 | 46 | typedef struct Atag Atag; |
cinap_lenrek@2323 | 47 | struct Atag { |
cinap_lenrek@2323 | 48 | u32int size; /* size of atag in words, including this header */ |
cinap_lenrek@2323 | 49 | u32int tag; /* atag type */ |
cinap_lenrek@2323 | 50 | union { |
cinap_lenrek@2323 | 51 | u32int data[1]; /* actually [size-2] */ |
cinap_lenrek@2323 | 52 | /* AtagMem */ |
cinap_lenrek@2323 | 53 | struct { |
cinap_lenrek@2323 | 54 | u32int size; |
cinap_lenrek@2323 | 55 | u32int base; |
cinap_lenrek@2323 | 56 | } mem; |
cinap_lenrek@2323 | 57 | /* AtagCmdLine */ |
cinap_lenrek@2323 | 58 | char cmdline[1]; /* actually [4*(size-2)] */ |
cinap_lenrek@2323 | 59 | }; |
cinap_lenrek@2323 | 60 | }; |
cinap_lenrek@2323 | 61 | |
cinap_lenrek@2323 | 62 | enum { |
cinap_lenrek@2323 | 63 | AtagNone = 0x00000000, |
cinap_lenrek@2323 | 64 | AtagCore = 0x54410001, |
cinap_lenrek@2323 | 65 | AtagMem = 0x54410002, |
cinap_lenrek@2323 | 66 | AtagCmdline = 0x54410009, |
cinap_lenrek@2323 | 67 | }; |
cinap_lenrek@2323 | 68 | |
cinap_lenrek@2323 | 69 | static int |
cinap_lenrek@2323 | 70 | findconf(char *name) |
cinap_lenrek@2323 | 71 | { |
cinap_lenrek@2323 | 72 | int i; |
cinap_lenrek@2323 | 73 | |
cinap_lenrek@2323 | 74 | for(i = 0; i < nconf; i++) |
cinap_lenrek@2323 | 75 | if(cistrcmp(confname[i], name) == 0) |
cinap_lenrek@2323 | 76 | return i; |
cinap_lenrek@2323 | 77 | return -1; |
cinap_lenrek@2323 | 78 | } |
cinap_lenrek@2323 | 79 | |
cinap_lenrek@2323 | 80 | char* |
cinap_lenrek@2323 | 81 | getconf(char *name) |
cinap_lenrek@2323 | 82 | { |
cinap_lenrek@2323 | 83 | int i; |
cinap_lenrek@2323 | 84 | |
cinap_lenrek@2323 | 85 | i = findconf(name); |
cinap_lenrek@2323 | 86 | if(i >= 0) |
cinap_lenrek@2323 | 87 | return confval[i]; |
cinap_lenrek@2323 | 88 | return nil; |
cinap_lenrek@2323 | 89 | } |
cinap_lenrek@2323 | 90 | |
cinap_lenrek@2323 | 91 | void |
cinap_lenrek@2323 | 92 | addconf(char *name, char *val) |
cinap_lenrek@2323 | 93 | { |
cinap_lenrek@2323 | 94 | int i; |
cinap_lenrek@2323 | 95 | |
cinap_lenrek@2323 | 96 | i = findconf(name); |
cinap_lenrek@2323 | 97 | if(i < 0){ |
cinap_lenrek@2323 | 98 | if(val == nil || nconf >= MAXCONF) |
cinap_lenrek@2323 | 99 | return; |
cinap_lenrek@2323 | 100 | i = nconf++; |
cinap_lenrek@2323 | 101 | strecpy(confname[i], confname[i]+sizeof(confname[i]), name); |
cinap_lenrek@2323 | 102 | } |
cinap_lenrek@2323 | 103 | strecpy(confval[i], confval[i]+sizeof(confval[i]), val); |
cinap_lenrek@2323 | 104 | } |
cinap_lenrek@2323 | 105 | |
cinap_lenrek@2323 | 106 | static void |
cinap_lenrek@2323 | 107 | writeconf(void) |
cinap_lenrek@2323 | 108 | { |
cinap_lenrek@2323 | 109 | char *p, *q; |
cinap_lenrek@2323 | 110 | int n; |
cinap_lenrek@2323 | 111 | |
cinap_lenrek@2323 | 112 | p = getconfenv(); |
cinap_lenrek@2323 | 113 | |
cinap_lenrek@2323 | 114 | if(waserror()) { |
cinap_lenrek@2323 | 115 | free(p); |
cinap_lenrek@2323 | 116 | nexterror(); |
cinap_lenrek@2323 | 117 | } |
cinap_lenrek@2323 | 118 | |
cinap_lenrek@2323 | 119 | /* convert to name=value\n format */ |
cinap_lenrek@2323 | 120 | for(q=p; *q; q++) { |
cinap_lenrek@2323 | 121 | q += strlen(q); |
cinap_lenrek@2323 | 122 | *q = '='; |
cinap_lenrek@2323 | 123 | q += strlen(q); |
cinap_lenrek@2323 | 124 | *q = '\n'; |
cinap_lenrek@2323 | 125 | } |
cinap_lenrek@2323 | 126 | n = q - p + 1; |
cinap_lenrek@2323 | 127 | if(n >= BOOTARGSLEN) |
cinap_lenrek@2323 | 128 | error("kernel configuration too large"); |
cinap_lenrek@2323 | 129 | memmove(BOOTARGS, p, n); |
cinap_lenrek@2323 | 130 | memset(BOOTARGS + n, '\n', BOOTARGSLEN - n); |
cinap_lenrek@2323 | 131 | poperror(); |
cinap_lenrek@2323 | 132 | free(p); |
cinap_lenrek@2323 | 133 | } |
cinap_lenrek@2323 | 134 | |
cinap_lenrek@2323 | 135 | static void |
cinap_lenrek@2323 | 136 | plan9iniinit(char *s, int cmdline) |
cinap_lenrek@2323 | 137 | { |
cinap_lenrek@2323 | 138 | char *toks[MAXCONF]; |
cinap_lenrek@2323 | 139 | int i, c, n; |
cinap_lenrek@2323 | 140 | char *v; |
cinap_lenrek@2323 | 141 | |
cinap_lenrek@2323 | 142 | if((c = *s) < ' ' || c >= 0x80) |
cinap_lenrek@2323 | 143 | return; |
cinap_lenrek@2323 | 144 | if(cmdline) |
cinap_lenrek@2323 | 145 | n = tokenize(s, toks, MAXCONF); |
cinap_lenrek@2323 | 146 | else |
cinap_lenrek@2323 | 147 | n = getfields(s, toks, MAXCONF, 1, "\n"); |
cinap_lenrek@2323 | 148 | for(i = 0; i < n; i++){ |
cinap_lenrek@2323 | 149 | if(toks[i][0] == '#') |
cinap_lenrek@2323 | 150 | continue; |
cinap_lenrek@2323 | 151 | v = strchr(toks[i], '='); |
cinap_lenrek@2323 | 152 | if(v == nil) |
cinap_lenrek@2323 | 153 | continue; |
cinap_lenrek@2323 | 154 | *v++ = '\0'; |
cinap_lenrek@2323 | 155 | addconf(toks[i], v); |
cinap_lenrek@2323 | 156 | } |
cinap_lenrek@2323 | 157 | } |
cinap_lenrek@2323 | 158 | |
cinap_lenrek@2323 | 159 | static void |
cinap_lenrek@2323 | 160 | ataginit(Atag *a) |
cinap_lenrek@2323 | 161 | { |
cinap_lenrek@2323 | 162 | int n; |
cinap_lenrek@2323 | 163 | |
cinap_lenrek@2323 | 164 | if(a->tag != AtagCore){ |
cinap_lenrek@2323 | 165 | plan9iniinit((char*)a, 0); |
cinap_lenrek@2323 | 166 | return; |
cinap_lenrek@2323 | 167 | } |
cinap_lenrek@2323 | 168 | while(a->tag != AtagNone){ |
cinap_lenrek@2323 | 169 | switch(a->tag){ |
cinap_lenrek@2323 | 170 | case AtagMem: |
cinap_lenrek@2323 | 171 | /* use only first bank */ |
cinap_lenrek@2323 | 172 | if(conf.mem[0].limit == 0 && a->mem.size != 0){ |
cinap_lenrek@2323 | 173 | memsize = a->mem.size; |
cinap_lenrek@2323 | 174 | conf.mem[0].base = a->mem.base; |
cinap_lenrek@2323 | 175 | conf.mem[0].limit = a->mem.base + memsize; |
cinap_lenrek@2323 | 176 | } |
cinap_lenrek@2323 | 177 | break; |
cinap_lenrek@2323 | 178 | case AtagCmdline: |
cinap_lenrek@2323 | 179 | n = (a->size * sizeof(u32int)) - offsetof(Atag, cmdline[0]); |
cinap_lenrek@2323 | 180 | if(a->cmdline + n < BOOTARGS + BOOTARGSLEN) |
cinap_lenrek@2323 | 181 | a->cmdline[n] = 0; |
cinap_lenrek@2323 | 182 | else |
cinap_lenrek@2323 | 183 | BOOTARGS[BOOTARGSLEN-1] = 0; |
cinap_lenrek@2323 | 184 | plan9iniinit(a->cmdline, 1); |
cinap_lenrek@2323 | 185 | break; |
cinap_lenrek@2323 | 186 | } |
cinap_lenrek@2323 | 187 | a = (Atag*)((u32int*)a + a->size); |
cinap_lenrek@2323 | 188 | } |
cinap_lenrek@2323 | 189 | } |
cinap_lenrek@2323 | 190 | |
cinap_lenrek@2323 | 191 | void |
cinap_lenrek@2323 | 192 | machinit(void) |
cinap_lenrek@2323 | 193 | { |
cinap_lenrek@2323 | 194 | m->machno = 0; |
cinap_lenrek@2323 | 195 | machaddr[m->machno] = m; |
cinap_lenrek@2323 | 196 | |
cinap_lenrek@2323 | 197 | m->ticks = 1; |
cinap_lenrek@2323 | 198 | m->perf.period = 1; |
cinap_lenrek@2323 | 199 | |
cinap_lenrek@2323 | 200 | conf.nmach = 1; |
cinap_lenrek@2323 | 201 | |
cinap_lenrek@2323 | 202 | active.machs = 1; |
cinap_lenrek@2323 | 203 | active.exiting = 0; |
cinap_lenrek@2323 | 204 | |
cinap_lenrek@2323 | 205 | up = nil; |
cinap_lenrek@2323 | 206 | } |
cinap_lenrek@2323 | 207 | |
cinap_lenrek@2323 | 208 | static void |
cinap_lenrek@2323 | 209 | optionsinit(char* s) |
cinap_lenrek@2323 | 210 | { |
cinap_lenrek@2323 | 211 | strecpy(oargb, oargb+sizeof(oargb), s); |
cinap_lenrek@2323 | 212 | |
cinap_lenrek@2323 | 213 | oargblen = strlen(oargb); |
cinap_lenrek@2323 | 214 | oargc = tokenize(oargb, oargv, nelem(oargv)-1); |
cinap_lenrek@2323 | 215 | oargv[oargc] = nil; |
cinap_lenrek@2323 | 216 | } |
cinap_lenrek@2323 | 217 | |
cinap_lenrek@2323 | 218 | void |
mveety@3216 | 219 | gpiomeminit(void) |
mveety@3216 | 220 | { |
mveety@3216 | 221 | Physseg seg; |
mveety@3216 | 222 | memset(&seg, 0, sizeof seg); |
mveety@3216 | 223 | seg.attr = SG_PHYSICAL; |
mveety@3216 | 224 | seg.name = "gpio"; |
mveety@3216 | 225 | seg.pa = (VIRTIO+0x200000); |
cinap_lenrek@3415 | 226 | seg.size = BY2PG; |
mveety@3216 | 227 | addphysseg(&seg); |
mveety@3216 | 228 | } |
mveety@3216 | 229 | |
mveety@3216 | 230 | |
mveety@3216 | 231 | void |
cinap_lenrek@2323 | 232 | main(void) |
cinap_lenrek@2323 | 233 | { |
cinap_lenrek@2323 | 234 | extern char edata[], end[]; |
cinap_lenrek@2323 | 235 | uint rev; |
cinap_lenrek@2323 | 236 | |
cinap_lenrek@2323 | 237 | okay(1); |
cinap_lenrek@2323 | 238 | m = (Mach*)MACHADDR; |
cinap_lenrek@2323 | 239 | memset(edata, 0, end - edata); /* clear bss */ |
cinap_lenrek@2323 | 240 | machinit(); |
cinap_lenrek@2323 | 241 | mmuinit1(); |
cinap_lenrek@2323 | 242 | |
cinap_lenrek@2323 | 243 | optionsinit("/boot/boot boot"); |
cinap_lenrek@2323 | 244 | quotefmtinstall(); |
cinap_lenrek@2323 | 245 | |
cinap_lenrek@2323 | 246 | ataginit((Atag*)BOOTARGS); |
cinap_lenrek@2323 | 247 | confinit(); /* figures out amount of memory */ |
cinap_lenrek@2323 | 248 | xinit(); |
cinap_lenrek@2323 | 249 | uartconsinit(); |
cinap_lenrek@2323 | 250 | screeninit(); |
cinap_lenrek@2323 | 251 | |
cinap_lenrek@2323 | 252 | print("\nPlan 9 from Bell Labs\n"); |
cinap_lenrek@2323 | 253 | rev = getfirmware(); |
cinap_lenrek@2323 | 254 | print("firmware: rev %d\n", rev); |
cinap_lenrek@2323 | 255 | if(rev < Minfirmrev){ |
cinap_lenrek@2323 | 256 | print("Sorry, firmware (start.elf) must be at least rev %d (%s)\n", |
cinap_lenrek@2323 | 257 | Minfirmrev, Minfirmdate); |
cinap_lenrek@2323 | 258 | for(;;) |
cinap_lenrek@2323 | 259 | ; |
cinap_lenrek@2323 | 260 | } |
cinap_lenrek@2323 | 261 | trapinit(); |
cinap_lenrek@2323 | 262 | clockinit(); |
cinap_lenrek@2323 | 263 | printinit(); |
cinap_lenrek@2323 | 264 | timersinit(); |
cinap_lenrek@2323 | 265 | cpuidprint(); |
cinap_lenrek@2323 | 266 | archreset(); |
cinap_lenrek@2323 | 267 | |
cinap_lenrek@2323 | 268 | procinit0(); |
cinap_lenrek@2323 | 269 | initseg(); |
cinap_lenrek@2323 | 270 | links(); |
cinap_lenrek@2323 | 271 | chandevreset(); /* most devices are discovered here */ |
cinap_lenrek@2323 | 272 | pageinit(); |
cinap_lenrek@2323 | 273 | swapinit(); |
cinap_lenrek@2323 | 274 | userinit(); |
mveety@3216 | 275 | gpiomeminit(); |
cinap_lenrek@2323 | 276 | schedinit(); |
cinap_lenrek@2323 | 277 | assert(0); /* shouldn't have returned */ |
cinap_lenrek@2323 | 278 | } |
cinap_lenrek@2323 | 279 | |
cinap_lenrek@2323 | 280 | /* |
cinap_lenrek@2323 | 281 | * starting place for first process |
cinap_lenrek@2323 | 282 | */ |
cinap_lenrek@2323 | 283 | void |
cinap_lenrek@2323 | 284 | init0(void) |
cinap_lenrek@2323 | 285 | { |
cinap_lenrek@2323 | 286 | int i; |
cinap_lenrek@2323 | 287 | char buf[2*KNAMELEN]; |
cinap_lenrek@2323 | 288 | |
cinap_lenrek@2323 | 289 | up->nerrlab = 0; |
cinap_lenrek@2323 | 290 | coherence(); |
cinap_lenrek@2323 | 291 | spllo(); |
cinap_lenrek@2323 | 292 | |
cinap_lenrek@2323 | 293 | /* |
cinap_lenrek@2323 | 294 | * These are o.k. because rootinit is null. |
cinap_lenrek@2323 | 295 | * Then early kproc's will have a root and dot. |
cinap_lenrek@2323 | 296 | */ |
cinap_lenrek@2323 | 297 | up->slash = namec("#/", Atodir, 0, 0); |
cinap_lenrek@2323 | 298 | pathclose(up->slash->path); |
cinap_lenrek@2323 | 299 | up->slash->path = newpath("/"); |
cinap_lenrek@2323 | 300 | up->dot = cclone(up->slash); |
cinap_lenrek@2323 | 301 | |
cinap_lenrek@2323 | 302 | chandevinit(); |
cinap_lenrek@2323 | 303 | |
cinap_lenrek@2323 | 304 | if(!waserror()){ |
cinap_lenrek@2323 | 305 | snprint(buf, sizeof(buf), "%s %s", "ARM", conffile); |
cinap_lenrek@2323 | 306 | ksetenv("terminal", buf, 0); |
cinap_lenrek@2323 | 307 | ksetenv("cputype", "arm", 0); |
cinap_lenrek@2323 | 308 | if(cpuserver) |
cinap_lenrek@2323 | 309 | ksetenv("service", "cpu", 0); |
cinap_lenrek@2323 | 310 | else |
cinap_lenrek@2323 | 311 | ksetenv("service", "terminal", 0); |
cinap_lenrek@2323 | 312 | snprint(buf, sizeof(buf), "-a %s", getethermac()); |
cinap_lenrek@2323 | 313 | ksetenv("etherargs", buf, 0); |
cinap_lenrek@2323 | 314 | |
cinap_lenrek@2323 | 315 | /* convert plan9.ini variables to #e and #ec */ |
cinap_lenrek@2323 | 316 | for(i = 0; i < nconf; i++) { |
cinap_lenrek@2323 | 317 | ksetenv(confname[i], confval[i], 0); |
cinap_lenrek@2323 | 318 | ksetenv(confname[i], confval[i], 1); |
cinap_lenrek@2323 | 319 | } |
cinap_lenrek@2323 | 320 | poperror(); |
cinap_lenrek@2323 | 321 | } |
cinap_lenrek@2323 | 322 | kproc("alarm", alarmkproc, 0); |
cinap_lenrek@2323 | 323 | touser(sp); |
cinap_lenrek@2323 | 324 | assert(0); /* shouldn't have returned */ |
cinap_lenrek@2323 | 325 | } |
cinap_lenrek@2323 | 326 | |
cinap_lenrek@2323 | 327 | static void |
cinap_lenrek@2323 | 328 | bootargs(uintptr base) |
cinap_lenrek@2323 | 329 | { |
cinap_lenrek@2323 | 330 | int i; |
cinap_lenrek@2323 | 331 | ulong ssize; |
cinap_lenrek@2323 | 332 | char **av, *p; |
cinap_lenrek@2323 | 333 | |
cinap_lenrek@2323 | 334 | /* |
cinap_lenrek@2323 | 335 | * Push the boot args onto the stack. |
cinap_lenrek@2323 | 336 | * The initial value of the user stack must be such |
cinap_lenrek@2323 | 337 | * that the total used is larger than the maximum size |
cinap_lenrek@2323 | 338 | * of the argument list checked in syscall. |
cinap_lenrek@2323 | 339 | */ |
cinap_lenrek@2323 | 340 | i = oargblen+1; |
cinap_lenrek@2323 | 341 | p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(Tos) - i)); |
cinap_lenrek@2323 | 342 | memmove(p, oargb, i); |
cinap_lenrek@2323 | 343 | |
cinap_lenrek@2323 | 344 | /* |
cinap_lenrek@2323 | 345 | * Now push the argv pointers. |
cinap_lenrek@2323 | 346 | * The code jumped to by touser in lproc.s expects arguments |
cinap_lenrek@2323 | 347 | * main(char* argv0, ...) |
cinap_lenrek@2323 | 348 | * and calls |
cinap_lenrek@2323 | 349 | * startboot("/boot/boot", &argv0) |
cinap_lenrek@2323 | 350 | * not the usual (int argc, char* argv[]) |
cinap_lenrek@2323 | 351 | */ |
cinap_lenrek@2323 | 352 | av = (char**)(p - (oargc+1)*sizeof(char*)); |
cinap_lenrek@2323 | 353 | ssize = base + BY2PG - PTR2UINT(av); |
cinap_lenrek@2323 | 354 | for(i = 0; i < oargc; i++) |
cinap_lenrek@2323 | 355 | *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG); |
cinap_lenrek@2323 | 356 | *av = nil; |
cinap_lenrek@2323 | 357 | sp = USTKTOP - ssize; |
cinap_lenrek@2323 | 358 | } |
cinap_lenrek@2323 | 359 | |
cinap_lenrek@2323 | 360 | /* |
cinap_lenrek@2323 | 361 | * create the first process |
cinap_lenrek@2323 | 362 | */ |
cinap_lenrek@2323 | 363 | void |
cinap_lenrek@2323 | 364 | userinit(void) |
cinap_lenrek@2323 | 365 | { |
cinap_lenrek@2323 | 366 | Proc *p; |
cinap_lenrek@2323 | 367 | Segment *s; |
cinap_lenrek@2323 | 368 | KMap *k; |
cinap_lenrek@2323 | 369 | Page *pg; |
cinap_lenrek@2323 | 370 | |
cinap_lenrek@2323 | 371 | /* no processes yet */ |
cinap_lenrek@2323 | 372 | up = nil; |
cinap_lenrek@2323 | 373 | |
cinap_lenrek@2323 | 374 | p = newproc(); |
cinap_lenrek@2323 | 375 | p->pgrp = newpgrp(); |
cinap_lenrek@2323 | 376 | p->egrp = smalloc(sizeof(Egrp)); |
cinap_lenrek@2323 | 377 | p->egrp->ref = 1; |
cinap_lenrek@2323 | 378 | p->fgrp = dupfgrp(nil); |
cinap_lenrek@2323 | 379 | p->rgrp = newrgrp(); |
cinap_lenrek@2323 | 380 | p->procmode = 0640; |
cinap_lenrek@2323 | 381 | |
cinap_lenrek@2323 | 382 | kstrdup(&eve, ""); |
cinap_lenrek@2323 | 383 | kstrdup(&p->text, "*init*"); |
cinap_lenrek@2323 | 384 | kstrdup(&p->user, eve); |
cinap_lenrek@2323 | 385 | |
cinap_lenrek@2323 | 386 | /* |
cinap_lenrek@2323 | 387 | * Kernel Stack |
cinap_lenrek@2323 | 388 | */ |
cinap_lenrek@2323 | 389 | p->sched.pc = PTR2UINT(init0); |
cinap_lenrek@2323 | 390 | p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr)); |
cinap_lenrek@2323 | 391 | p->sched.sp = STACKALIGN(p->sched.sp); |
cinap_lenrek@2323 | 392 | |
cinap_lenrek@2323 | 393 | /* |
cinap_lenrek@2323 | 394 | * User Stack |
cinap_lenrek@2323 | 395 | * |
cinap_lenrek@2323 | 396 | * Technically, newpage can't be called here because it |
cinap_lenrek@2323 | 397 | * should only be called when in a user context as it may |
cinap_lenrek@2323 | 398 | * try to sleep if there are no pages available, but that |
cinap_lenrek@2323 | 399 | * shouldn't be the case here. |
cinap_lenrek@2323 | 400 | */ |
cinap_lenrek@2323 | 401 | s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG); |
cinap_lenrek@2323 | 402 | s->flushme++; |
cinap_lenrek@2323 | 403 | p->seg[SSEG] = s; |
cinap_lenrek@2323 | 404 | pg = newpage(1, 0, USTKTOP-BY2PG); |
cinap_lenrek@2323 | 405 | segpage(s, pg); |
cinap_lenrek@2323 | 406 | k = kmap(pg); |
cinap_lenrek@2323 | 407 | bootargs(VA(k)); |
cinap_lenrek@2323 | 408 | kunmap(k); |
cinap_lenrek@2323 | 409 | |
cinap_lenrek@2323 | 410 | /* |
cinap_lenrek@2323 | 411 | * Text |
cinap_lenrek@2323 | 412 | */ |
cinap_lenrek@2323 | 413 | s = newseg(SG_TEXT, UTZERO, 1); |
cinap_lenrek@2323 | 414 | p->seg[TSEG] = s; |
cinap_lenrek@2323 | 415 | pg = newpage(1, 0, UTZERO); |
cinap_lenrek@2323 | 416 | memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl)); |
cinap_lenrek@2323 | 417 | segpage(s, pg); |
cinap_lenrek@2323 | 418 | k = kmap(s->map[0]->pages[0]); |
cinap_lenrek@2323 | 419 | memmove(UINT2PTR(VA(k)), initcode, sizeof initcode); |
cinap_lenrek@2323 | 420 | kunmap(k); |
cinap_lenrek@2323 | 421 | |
cinap_lenrek@2323 | 422 | ready(p); |
cinap_lenrek@2323 | 423 | } |
cinap_lenrek@2323 | 424 | |
cinap_lenrek@2323 | 425 | void |
cinap_lenrek@2323 | 426 | confinit(void) |
cinap_lenrek@2323 | 427 | { |
stanley@3401 | 428 | int i, userpcnt; |
cinap_lenrek@2323 | 429 | ulong kpages; |
cinap_lenrek@2323 | 430 | uintptr pa; |
cinap_lenrek@2323 | 431 | char *p; |
cinap_lenrek@2323 | 432 | |
stanley@3401 | 433 | if(p = getconf("*kernelpercent")) |
stanley@3401 | 434 | userpcnt = 100 - strtol(p, 0, 0); |
stanley@3401 | 435 | else |
stanley@3401 | 436 | userpcnt = 0; |
stanley@3401 | 437 | |
cinap_lenrek@2323 | 438 | if(0 && (p = getconf("service")) != nil){ |
cinap_lenrek@2323 | 439 | if(strcmp(p, "cpu") == 0) |
cinap_lenrek@2323 | 440 | cpuserver = 1; |
cinap_lenrek@2323 | 441 | else if(strcmp(p,"terminal") == 0) |
cinap_lenrek@2323 | 442 | cpuserver = 0; |
cinap_lenrek@2323 | 443 | } |
cinap_lenrek@2323 | 444 | if((p = getconf("*maxmem")) != nil){ |
cinap_lenrek@2323 | 445 | memsize = strtoul(p, 0, 0) - PHYSDRAM; |
cinap_lenrek@2323 | 446 | if (memsize < 16*MB) /* sanity */ |
cinap_lenrek@2323 | 447 | memsize = 16*MB; |
cinap_lenrek@2323 | 448 | } |
cinap_lenrek@2323 | 449 | |
cinap_lenrek@2323 | 450 | getramsize(&conf.mem[0]); |
cinap_lenrek@2323 | 451 | if(conf.mem[0].limit == 0){ |
cinap_lenrek@2323 | 452 | conf.mem[0].base = PHYSDRAM; |
cinap_lenrek@2323 | 453 | conf.mem[0].limit = PHYSDRAM + memsize; |
cinap_lenrek@2323 | 454 | }else if(p != nil) |
cinap_lenrek@2323 | 455 | conf.mem[0].limit = conf.mem[0].base + memsize; |
cinap_lenrek@2323 | 456 | |
cinap_lenrek@2323 | 457 | conf.npage = 0; |
cinap_lenrek@2323 | 458 | pa = PADDR(PGROUND(PTR2UINT(end))); |
cinap_lenrek@2323 | 459 | |
cinap_lenrek@2323 | 460 | /* |
cinap_lenrek@2323 | 461 | * we assume that the kernel is at the beginning of one of the |
cinap_lenrek@2323 | 462 | * contiguous chunks of memory and fits therein. |
cinap_lenrek@2323 | 463 | */ |
cinap_lenrek@2323 | 464 | for(i=0; i<nelem(conf.mem); i++){ |
cinap_lenrek@2323 | 465 | /* take kernel out of allocatable space */ |
cinap_lenrek@2323 | 466 | if(pa > conf.mem[i].base && pa < conf.mem[i].limit) |
cinap_lenrek@2323 | 467 | conf.mem[i].base = pa; |
cinap_lenrek@2323 | 468 | |
cinap_lenrek@2323 | 469 | conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG; |
cinap_lenrek@2323 | 470 | conf.npage += conf.mem[i].npage; |
cinap_lenrek@2323 | 471 | } |
cinap_lenrek@2323 | 472 | |
stanley@3401 | 473 | if(userpcnt < 10) |
stanley@3401 | 474 | userpcnt = 60 + cpuserver*10; |
stanley@3401 | 475 | kpages = conf.npage - (conf.npage*userpcnt)/100; |
stanley@3401 | 476 | |
stanley@3401 | 477 | /* |
stanley@3401 | 478 | * can't go past the end of virtual memory |
stanley@3401 | 479 | * (ulong)-KZERO is 2^32 - KZERO |
stanley@3401 | 480 | */ |
stanley@3401 | 481 | if(kpages > ((ulong)-KZERO)/BY2PG) |
stanley@3401 | 482 | kpages = ((ulong)-KZERO)/BY2PG; |
stanley@3401 | 483 | |
stanley@3401 | 484 | conf.upages = conf.npage - kpages; |
stanley@3401 | 485 | conf.ialloc = (kpages/2)*BY2PG; |
cinap_lenrek@2323 | 486 | |
cinap_lenrek@2323 | 487 | /* only one processor */ |
cinap_lenrek@2323 | 488 | conf.nmach = 1; |
cinap_lenrek@2323 | 489 | |
cinap_lenrek@2323 | 490 | /* set up other configuration parameters */ |
cinap_lenrek@2323 | 491 | conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5; |
cinap_lenrek@2323 | 492 | if(cpuserver) |
cinap_lenrek@2323 | 493 | conf.nproc *= 3; |
cinap_lenrek@2323 | 494 | if(conf.nproc > 2000) |
cinap_lenrek@2323 | 495 | conf.nproc = 2000; |
cinap_lenrek@2323 | 496 | conf.nswap = conf.npage*3; |
cinap_lenrek@2323 | 497 | conf.nswppo = 4096; |
cinap_lenrek@2323 | 498 | conf.nimage = 200; |
cinap_lenrek@2323 | 499 | |
cinap_lenrek@2323 | 500 | conf.copymode = 0; /* copy on write */ |
cinap_lenrek@2323 | 501 | |
cinap_lenrek@2323 | 502 | /* |
cinap_lenrek@2323 | 503 | * Guess how much is taken by the large permanent |
cinap_lenrek@2323 | 504 | * datastructures. Mntcache and Mntrpc are not accounted for |
cinap_lenrek@2323 | 505 | * (probably ~300KB). |
cinap_lenrek@2323 | 506 | */ |
cinap_lenrek@2323 | 507 | kpages = conf.npage - conf.upages; |
cinap_lenrek@2323 | 508 | kpages *= BY2PG; |
cinap_lenrek@2323 | 509 | kpages -= conf.upages*sizeof(Page) |
cinap_lenrek@2323 | 510 | + conf.nproc*sizeof(Proc) |
cinap_lenrek@2323 | 511 | + conf.nimage*sizeof(Image) |
cinap_lenrek@2323 | 512 | + conf.nswap |
stanley@3401 | 513 | + conf.nswppo*sizeof(Page*); |
cinap_lenrek@2323 | 514 | mainmem->maxsize = kpages; |
cinap_lenrek@2323 | 515 | if(!cpuserver) |
cinap_lenrek@2323 | 516 | /* |
cinap_lenrek@2323 | 517 | * give terminals lots of image memory, too; the dynamic |
cinap_lenrek@2323 | 518 | * allocation will balance the load properly, hopefully. |
cinap_lenrek@2323 | 519 | * be careful with 32-bit overflow. |
cinap_lenrek@2323 | 520 | */ |
cinap_lenrek@2323 | 521 | imagmem->maxsize = kpages; |
cinap_lenrek@2323 | 522 | |
cinap_lenrek@2323 | 523 | } |
cinap_lenrek@2323 | 524 | |
cinap_lenrek@2323 | 525 | static void |
cinap_lenrek@2323 | 526 | shutdown(int ispanic) |
cinap_lenrek@2323 | 527 | { |
cinap_lenrek@2323 | 528 | int ms, once; |
cinap_lenrek@2323 | 529 | |
cinap_lenrek@2323 | 530 | lock(&active); |
cinap_lenrek@2323 | 531 | if(ispanic) |
cinap_lenrek@2323 | 532 | active.ispanic = ispanic; |
cinap_lenrek@2323 | 533 | else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0) |
cinap_lenrek@2323 | 534 | active.ispanic = 0; |
cinap_lenrek@2323 | 535 | once = active.machs & (1<<m->machno); |
cinap_lenrek@2323 | 536 | active.machs &= ~(1<<m->machno); |
cinap_lenrek@2323 | 537 | active.exiting = 1; |
cinap_lenrek@2323 | 538 | unlock(&active); |
cinap_lenrek@2323 | 539 | |
cinap_lenrek@2323 | 540 | if(once) |
cinap_lenrek@2323 | 541 | iprint("cpu%d: exiting\n", m->machno); |
cinap_lenrek@2323 | 542 | spllo(); |
cinap_lenrek@2323 | 543 | for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){ |
cinap_lenrek@2323 | 544 | delay(TK2MS(2)); |
cinap_lenrek@2323 | 545 | if(active.machs == 0 && consactive() == 0) |
cinap_lenrek@2323 | 546 | break; |
cinap_lenrek@2323 | 547 | } |
cinap_lenrek@2323 | 548 | delay(1000); |
cinap_lenrek@2323 | 549 | } |
cinap_lenrek@2323 | 550 | |
cinap_lenrek@2323 | 551 | /* |
cinap_lenrek@2323 | 552 | * exit kernel either on a panic or user request |
cinap_lenrek@2323 | 553 | */ |
cinap_lenrek@2323 | 554 | void |
cinap_lenrek@2323 | 555 | exit(int code) |
cinap_lenrek@2323 | 556 | { |
cinap_lenrek@2323 | 557 | shutdown(code); |
cinap_lenrek@2323 | 558 | splfhi(); |
cinap_lenrek@2323 | 559 | archreboot(); |
cinap_lenrek@2323 | 560 | } |
cinap_lenrek@2323 | 561 | |
cinap_lenrek@2323 | 562 | /* |
cinap_lenrek@2323 | 563 | * stub for ../omap/devether.c |
cinap_lenrek@2323 | 564 | */ |
cinap_lenrek@2323 | 565 | int |
cinap_lenrek@2323 | 566 | isaconfig(char *class, int ctlrno, ISAConf *isa) |
cinap_lenrek@2323 | 567 | { |
cinap_lenrek@2323 | 568 | USED(ctlrno); |
cinap_lenrek@2323 | 569 | USED(isa); |
cinap_lenrek@2323 | 570 | return strcmp(class, "ether") == 0; |
cinap_lenrek@2323 | 571 | } |
cinap_lenrek@2323 | 572 | |
cinap_lenrek@2323 | 573 | /* |
cinap_lenrek@2323 | 574 | * the new kernel is already loaded at address `code' |
cinap_lenrek@2323 | 575 | * of size `size' and entry point `entry'. |
cinap_lenrek@2323 | 576 | */ |
cinap_lenrek@2323 | 577 | void |
cinap_lenrek@2323 | 578 | reboot(void *entry, void *code, ulong size) |
cinap_lenrek@2323 | 579 | { |
cinap_lenrek@2323 | 580 | void (*f)(ulong, ulong, ulong); |
cinap_lenrek@2323 | 581 | |
cinap_lenrek@2323 | 582 | print("starting reboot..."); |
cinap_lenrek@2323 | 583 | writeconf(); |
cinap_lenrek@2323 | 584 | shutdown(0); |
cinap_lenrek@2323 | 585 | |
cinap_lenrek@2323 | 586 | /* |
cinap_lenrek@2323 | 587 | * should be the only processor running now |
cinap_lenrek@2323 | 588 | */ |
cinap_lenrek@2323 | 589 | |
cinap_lenrek@2323 | 590 | print("reboot entry %#lux code %#lux size %ld\n", |
cinap_lenrek@2323 | 591 | PADDR(entry), PADDR(code), size); |
cinap_lenrek@2323 | 592 | delay(100); |
cinap_lenrek@2323 | 593 | |
cinap_lenrek@2323 | 594 | /* turn off buffered serial console */ |
cinap_lenrek@2323 | 595 | serialoq = nil; |
cinap_lenrek@2323 | 596 | kprintoq = nil; |
cinap_lenrek@2323 | 597 | screenputs = nil; |
cinap_lenrek@2323 | 598 | |
cinap_lenrek@2323 | 599 | /* shutdown devices */ |
cinap_lenrek@2323 | 600 | chandevshutdown(); |
cinap_lenrek@2323 | 601 | |
cinap_lenrek@2323 | 602 | /* stop the clock (and watchdog if any) */ |
cinap_lenrek@2323 | 603 | clockshutdown(); |
cinap_lenrek@2323 | 604 | |
cinap_lenrek@2323 | 605 | splfhi(); |
cinap_lenrek@2323 | 606 | intrsoff(); |
cinap_lenrek@2323 | 607 | |
cinap_lenrek@2323 | 608 | /* setup reboot trampoline function */ |
cinap_lenrek@2323 | 609 | f = (void*)REBOOTADDR; |
cinap_lenrek@2323 | 610 | memmove(f, rebootcode, sizeof(rebootcode)); |
cinap_lenrek@2323 | 611 | cacheuwbinv(); |
cinap_lenrek@2323 | 612 | |
cinap_lenrek@2323 | 613 | /* off we go - never to return */ |
cinap_lenrek@2323 | 614 | (*f)(PADDR(entry), PADDR(code), size); |
cinap_lenrek@2323 | 615 | |
cinap_lenrek@2323 | 616 | iprint("loaded kernel returned!\n"); |
cinap_lenrek@2323 | 617 | delay(1000); |
cinap_lenrek@2323 | 618 | archreboot(); |
cinap_lenrek@2323 | 619 | } |
cinap_lenrek@2323 | 620 | |
cinap_lenrek@2323 | 621 | int |
cinap_lenrek@2323 | 622 | cmpswap(long *addr, long old, long new) |
cinap_lenrek@2323 | 623 | { |
cinap_lenrek@2323 | 624 | return cas32(addr, old, new); |
cinap_lenrek@2323 | 625 | } |