]> git.saurik.com Git - apple/xnu.git/blame_incremental - osfmk/i386/AT386/model_dep.c
xnu-344.34.tar.gz
[apple/xnu.git] / osfmk / i386 / AT386 / model_dep.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
25/*
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989, 1988 Carnegie Mellon University
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
35 *
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50
51/*
52 */
53
54/*
55 * File: model_dep.c
56 * Author: Avadis Tevanian, Jr., Michael Wayne Young
57 *
58 * Copyright (C) 1986, Avadis Tevanian, Jr., Michael Wayne Young
59 *
60 * Basic initialization for I386 - ISA bus machines.
61 */
62
63#include <cpus.h>
64#include <platforms.h>
65#include <mp_v1_1.h>
66#include <mach_kdb.h>
67#include <himem.h>
68#include <fast_idle.h>
69
70#include <mach/i386/vm_param.h>
71
72#include <string.h>
73#include <mach/vm_param.h>
74#include <mach/vm_prot.h>
75#include <mach/machine.h>
76#include <mach/time_value.h>
77#include <kern/etap_macros.h>
78#include <kern/spl.h>
79#include <kern/assert.h>
80#include <kern/debug.h>
81#include <kern/misc_protos.h>
82#include <kern/startup.h>
83#include <kern/clock.h>
84#include <kern/time_out.h>
85#include <kern/xpr.h>
86#include <kern/cpu_data.h>
87#include <vm/vm_page.h>
88#include <vm/pmap.h>
89#include <vm/vm_kern.h>
90#include <i386/fpu.h>
91#include <i386/pmap.h>
92#include <i386/ipl.h>
93#include <i386/pio.h>
94#include <i386/misc_protos.h>
95#include <i386/cpuid.h>
96#include <i386/rtclock_entries.h>
97#include <i386/AT386/mp/mp.h>
98#if MACH_KDB
99#include <ddb/db_aout.h>
100#endif /* MACH_KDB */
101#include <ddb/tr.h>
102#ifdef __MACHO__
103#include <i386/AT386/kernBootStruct.h>
104#include <mach/boot_info.h>
105#include <mach/thread_status.h>
106#endif
107
108#if NCPUS > 1
109#include <i386/mp_desc.h>
110#endif /* NCPUS */
111
112#if MP_V1_1
113#include <i386/AT386/mp/mp_v1_1.h>
114#endif /* MP_V1_1 */
115
116#include <IOKit/IOPlatformExpert.h>
117
118vm_size_t mem_size = 0;
119vm_offset_t first_addr = 0; /* set by start.s - keep out of bss */
120vm_offset_t first_avail = 0;/* first after page tables */
121vm_offset_t last_addr;
122
123vm_offset_t avail_start, avail_end;
124vm_offset_t virtual_avail, virtual_end;
125vm_offset_t hole_start, hole_end;
126vm_offset_t avail_next;
127unsigned int avail_remaining;
128
129/* parameters passed from bootstrap loader */
130int cnvmem = 0; /* must be in .data section */
131int extmem = 0;
132
133/* FIXME!! REMOVE WHEN OSFMK DEVICES ARE COMPLETELY PULLED OUT */
134int dev_name_count = 0;
135int dev_name_list = 0;
136
137#ifndef __MACHO__
138extern char edata, end;
139#endif
140
141extern char version[];
142
143void parse_arguments(void);
144const char *getenv(const char *);
145
146#define BOOT_LINE_LENGTH 160
147char boot_string_store[BOOT_LINE_LENGTH] = {0};
148char *boot_string = (char *)0;
149int boot_string_sz = BOOT_LINE_LENGTH;
150int boottype = 0;
151
152#if __MACHO__
153#include <mach-o/loader.h>
154vm_offset_t edata, etext, end;
155
156extern struct mach_header _mh_execute_header;
157void *sectTEXTB; int sectSizeTEXT;
158void *sectDATAB; int sectSizeDATA;
159void *sectOBJCB; int sectSizeOBJC;
160void *sectLINKB; int sectSizeLINK;
161
162/* Kernel boot information */
163KERNBOOTSTRUCT kernBootStructData;
164KERNBOOTSTRUCT *kernBootStruct;
165#endif
166
167vm_offset_t kern_args_start = 0; /* kernel arguments */
168vm_size_t kern_args_size = 0; /* size of kernel arguments */
169
170#ifdef __MACHO__
171
172unsigned long
173i386_preinit()
174{
175 int i;
176 struct segment_command *sgp;
177 struct section *sp;
178
179 sgp = (struct segment_command *) getsegbyname("__DATA");
180 if (sgp) {
181 sp = (struct section *) firstsect(sgp);
182 if (sp) {
183 do {
184 if (sp->flags & S_ZEROFILL)
185 bzero((char *) sp->addr, sp->size);
186 } while (sp = (struct section *)nextsect(sgp, sp));
187 }
188 }
189
190 bcopy((char *) KERNSTRUCT_ADDR, (char *) &kernBootStructData,
191 sizeof(kernBootStructData));
192
193 kernBootStruct = &kernBootStructData;
194
195 end = round_page( kernBootStruct->kaddr + kernBootStruct->ksize );
196
197 return end;
198}
199#endif
200
201/*
202 * Cpu initialization. Running virtual, but without MACH VM
203 * set up. First C routine called.
204 */
205void
206machine_startup(void)
207{
208
209#ifdef __MACHO__
210 /* Now copy over various bits.. */
211 cnvmem = kernBootStruct->convmem;
212 extmem = kernBootStruct->extmem;
213 kern_args_start = (vm_offset_t) kernBootStruct->bootString;
214 kern_args_size = strlen(kernBootStruct->bootString);
215 boottype = kernBootStruct->rootdev;
216
217 /* Now retrieve addresses for end, edata, and etext
218 * from MACH-O headers.
219 */
220
221 sectTEXTB = (void *) getsegdatafromheader(
222 &_mh_execute_header, "__TEXT", &sectSizeTEXT);
223 sectDATAB = (void *) getsegdatafromheader(
224 &_mh_execute_header, "__DATA", &sectSizeDATA);
225 sectOBJCB = (void *) getsegdatafromheader(
226 &_mh_execute_header, "__OBJC", &sectSizeOBJC);
227 sectLINKB = (void *) getsegdatafromheader(
228 &_mh_execute_header, "__LINKEDIT", &sectSizeLINK);
229
230 etext = (vm_offset_t) sectTEXTB + sectSizeTEXT;
231 edata = (vm_offset_t) sectDATAB + sectSizeDATA;
232#endif
233
234 printf_init(); /* Init this in case we need debugger */
235 panic_init(); /* Init this in case we need debugger */
236
237 PE_init_platform(FALSE, kernBootStruct);
238 PE_init_kprintf(FALSE);
239 PE_init_printf(FALSE);
240
241 /*
242 * Parse startup arguments
243 */
244 parse_arguments();
245
246 /*
247 * Set up initial thread so current_thread() works early on
248 */
249 pageout_thread.top_act = &pageout_act;
250 pageout_act.thread = &pageout_thread;
251 thread_machine_set_current(&pageout_thread);
252
253 /*
254 * Do basic VM initialization
255 */
256 i386_init();
257
258 PE_init_platform(TRUE, kernBootStruct);
259 PE_init_kprintf(TRUE);
260 PE_init_printf(TRUE);
261
262#if MACH_KDB
263 /*
264 * Initialize the kernel debugger.
265 */
266 ddb_init();
267
268 /*
269 * Cause a breakpoint trap to the debugger before proceeding
270 * any further if the proper option bit was specified in
271 * the boot flags.
272 */
273
274 if (halt_in_debugger) {
275 printf("inline call to debugger(machine_startup)\n");
276 Debugger("inline call");
277 }
278#endif /* MACH_KDB */
279
280 TR_INIT();
281
282 printf(version);
283
284 machine_slot[0].is_cpu = TRUE;
285 machine_slot[0].running = TRUE;
286#ifdef MACH_BSD
287 /* FIXME */
288 machine_slot[0].cpu_type = CPU_TYPE_I386;
289 machine_slot[0].cpu_subtype = CPU_SUBTYPE_PENTPRO;
290#else
291 machine_slot[0].cpu_type = cpuid_cputype(0);
292 machine_slot[0].cpu_subtype = CPU_SUBTYPE_AT386;
293#endif
294
295 /*
296 * Start the system.
297 */
298#if NCPUS > 1
299 mp_desc_init(0);
300#endif /* NCPUS */
301
302 setup_main();
303}
304
305
306vm_offset_t env_start = 0; /* environment */
307vm_size_t env_size = 0; /* size of environment */
308
309/*
310 * Parse command line arguments.
311 */
312void
313parse_arguments(void)
314{
315 unsigned int boot_arg;
316
317 if (PE_parse_boot_arg("maxmem", &boot_arg))
318 {
319 mem_size = boot_arg * (1024 * 1024);
320 }
321
322 if (PE_parse_boot_arg("debug", &boot_arg))
323 {
324 if (boot_arg & DB_HALT) halt_in_debugger = 1;
325 if (boot_arg & DB_PRT) disableDebugOuput = FALSE;
326 }
327}
328
329const char *
330getenv(const char *name)
331{
332 int len = strlen(name);
333 const char *p = (const char *)env_start;
334 const char *endp = p + env_size;
335
336 while (p < endp) {
337 if (len >= endp - p)
338 break;
339 if (strncmp(name, p, len) == 0 && *(p + len) == '=')
340 return p + len + 1;
341 while (*p++)
342 ;
343 }
344 return NULL;
345}
346
347extern void
348calibrate_delay(void);
349
350/*
351 * Find devices. The system is alive.
352 */
353void
354machine_init(void)
355{
356 int unit;
357 const char *p;
358 int n;
359
360 /*
361 * Adjust delay count before entering drivers
362 */
363
364 calibrate_delay();
365
366 /*
367 * Display CPU identification
368 */
369 cpuid_cpu_display("CPU identification", 0);
370 cpuid_cache_display("CPU configuration", 0);
371
372#if MP_V1_1
373 mp_v1_1_init();
374#endif /* MP_V1_1 */
375
376 /*
377 * Set up to use floating point.
378 */
379 init_fpu();
380
381#if 0
382#if NPCI > 0
383 dma_zones_init();
384#endif /* NPCI > 0 */
385#endif
386
387 /*
388 * Configure clock devices.
389 */
390 clock_config();
391}
392
393/*
394 * Halt a cpu.
395 */
396void
397halt_cpu(void)
398{
399 halt_all_cpus(FALSE);
400}
401
402int reset_mem_on_reboot = 1;
403
404/*
405 * Halt the system or reboot.
406 */
407void
408halt_all_cpus(boolean_t reboot)
409{
410 if (reboot)
411 {
412 /*
413 * Tell the BIOS not to clear and test memory.
414 */
415 if (!reset_mem_on_reboot)
416 *(unsigned short *)phystokv(0x472) = 0x1234;
417
418 printf("MACH Reboot\n");
419 PEHaltRestart( kPERestartCPU );
420 }
421 else
422 {
423 printf("CPU halted\n");
424 PEHaltRestart( kPEHaltCPU );
425 }
426 while(1);
427}
428
429/*
430 * Basic VM initialization.
431 */
432
433void
434i386_init(void)
435{
436 int i,j; /* Standard index vars. */
437 vm_size_t bios_hole_size;
438
439#ifndef __MACHO__
440 /*
441 * Zero the BSS.
442 */
443
444 bzero((char *)&edata,(unsigned)(&end - &edata));
445#endif
446
447 boot_string = &boot_string_store[0];
448
449 /*
450 * Initialize the pic prior to any possible call to an spl.
451 */
452
453 set_cpu_model();
454 vm_set_page_size();
455
456 /*
457 * Initialize the Event Trace Analysis Package
458 * Static Phase: 1 of 2
459 */
460 etap_init_phase1();
461
462 /*
463 * Compute the memory size.
464 */
465
466#if 1
467 /* FIXME
468 * fdisk needs to change to use a sysctl instead of
469 * opening /dev/kmem and reading out the kernboot structure
470 */
471
472 first_addr = (char *)(KERNSTRUCT_ADDR) + sizeof(KERNBOOTSTRUCT);
473#else
474#if NCPUS > 1
475 first_addr = 0x1000;
476#else
477 /* First two pages are used to boot the other cpus. */
478 /* TODO - reclaim pages after all cpus have booted */
479
480 first_addr = 0x3000;
481#endif
482#endif
483
484 /* BIOS leaves data in low memory */
485 last_addr = 1024*1024 + extmem*1024;
486
487 /* extended memory starts at 1MB */
488
489 bios_hole_size = 1024*1024 - trunc_page((vm_offset_t)(1024 * cnvmem));
490
491 /*
492 * Initialize for pmap_free_pages and pmap_next_page.
493 * These guys should be page-aligned.
494 */
495
496 hole_start = trunc_page((vm_offset_t)(1024 * cnvmem));
497 hole_end = round_page((vm_offset_t)first_avail);
498
499 /*
500 * compute mem_size
501 */
502
503 if (mem_size != 0) {
504 if (mem_size < (last_addr) - bios_hole_size)
505 last_addr = mem_size + bios_hole_size;
506 }
507
508 first_addr = round_page(first_addr);
509 last_addr = trunc_page(last_addr);
510 mem_size = last_addr - bios_hole_size;
511
512 avail_start = first_addr;
513 avail_end = last_addr;
514 avail_next = avail_start;
515
516 /*
517 * Initialize kernel physical map, mapping the
518 * region from loadpt to avail_start.
519 * Kernel virtual address starts at VM_KERNEL_MIN_ADDRESS.
520 */
521
522
523#if NCPUS > 1 && AT386
524 /*
525 * Must Allocate interrupt stacks before kdb is called and also
526 * before vm is initialized. Must find out number of cpus first.
527 */
528 /*
529 * Get number of cpus to boot, passed as an optional argument
530 * boot: mach [-sah#] # from 0 to 9 is the number of cpus to boot
531 */
532 if (wncpu == -1) {
533 /*
534 * "-1" check above is to allow for old boot loader to pass
535 * wncpu through boothowto. New boot loader uses environment.
536 */
537 const char *cpus;
538 if ((cpus = getenv("cpus")) != NULL) {
539 /* only a single digit for now */
540 if ((*cpus > '0') && (*cpus <= '9'))
541 wncpu = *cpus - '0';
542 } else
543 wncpu = NCPUS;
544 }
545 mp_probe_cpus();
546 interrupt_stack_alloc();
547
548#endif /* NCPUS > 1 && AT386 */
549
550 pmap_bootstrap(0);
551
552 avail_remaining = atop((avail_end - avail_start) -
553 (hole_end - hole_start));
554}
555
556unsigned int
557pmap_free_pages(void)
558{
559 return avail_remaining;
560}
561
562boolean_t
563pmap_next_page(
564 vm_offset_t *addrp)
565{
566 if (avail_next == avail_end)
567 return FALSE;
568
569 /* skip the hole */
570
571 if (avail_next == hole_start)
572 avail_next = hole_end;
573
574 *addrp = avail_next;
575 avail_next += PAGE_SIZE;
576 avail_remaining--;
577
578 return TRUE;
579}
580
581boolean_t
582pmap_valid_page(
583 vm_offset_t x)
584{
585 return ((avail_start <= x) && (x < avail_end));
586}
587
588/*XXX*/
589void fc_get(mach_timespec_t *ts);
590#include <kern/clock.h>
591#include <i386/rtclock_entries.h>
592extern kern_return_t sysclk_gettime(
593 mach_timespec_t *cur_time);
594void fc_get(mach_timespec_t *ts) {
595 (void )sysclk_gettime(ts);
596}
597
598void
599Debugger(
600 const char *message)
601{
602 printf("Debugger called: <%s>\n", message);
603
604 __asm__("int3");
605}
606
607void
608display_syscall(int syscall)
609{
610 printf("System call happened %d\n", syscall);
611}
612
613#if XPR_DEBUG && (NCPUS == 1 || MP_V1_1)
614
615extern kern_return_t sysclk_gettime_interrupts_disabled(
616 mach_timespec_t *cur_time);
617
618int xpr_time(void)
619{
620 mach_timespec_t time;
621
622 sysclk_gettime_interrupts_disabled(&time);
623 return(time.tv_sec*1000000 + time.tv_nsec/1000);
624}
625#endif /* XPR_DEBUG && (NCPUS == 1 || MP_V1_1) */
626
627enable_bluebox()
628{
629}
630disable_bluebox()
631{
632}
633
634char *
635machine_boot_info(char *buf, vm_size_t size)
636{
637 *buf ='\0';
638 return buf;
639}
640