home *** CD-ROM | disk | FTP | other *** search
- /*
- * Mach Operating System
- * Copyright (c) 1992 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
- /*
- * HISTORY
- * $Log: sun_init.c,v $
- * Revision 2.4 92/01/03 20:31:41 dbg
- * Move symbol table and bootstrap image out of BSS. Clear BSS
- * afterwards.
- * [91/08/21 dbg]
- *
- * Revision 2.3 91/06/19 11:59:30 rvb
- * cputypes.h->platforms.h
- * [91/06/12 13:46:53 rvb]
- *
- * Revision 2.2 91/05/18 14:38:20 rpd
- * Added avail_remaining, avail_next, hole_start, hole_end.
- * [91/05/15 rpd]
- *
- * Revision 2.1 89/08/03 16:53:21 rwd
- * Created.
- *
- * Revision 2.4 88/08/24 02:10:59 mwyoung
- * Corrected include file references.
- * [88/08/22 mwyoung]
- *
- *
- * 9-Mar-88 Michael Young (mwyoung) at Carnegie-Mellon University
- * Eliminate use of freemem. Fix copyright notice, include file format.
- *
- * 4-Feb-88 Robert Baron (rvb) at Carnegie-Mellon University
- * Revised for new pmap module:
- * pmap_bootstrap vs {ctx,pmeg}init
- *
- * 04-Oct-87 Jonathan J. Chew (jjc) at Carnegie-Mellon University
- * Added changes for Sun 3/{60,110}.
- *
- * 25-Jun-87 Jonathan J. Chew (jjc) at Carnegie-Mellon University
- * Added code for Sun 3/260 to deal with cache and ecc memory.
- * Don't cache prom monitor.
- *
- * 30-Apr-87 David Golub (dbg) at Carnegie-Mellon University
- * MACH: don't reserve pmeg for U_AREA.
- *
- * 29-Oct-86 David Golub (dbg) at Carnegie-Mellon University
- * Made sure that memory allocated for IOPB isn't part of
- * managed physical memory.
- *
- * 13-Sep-86 Jonathan J. Chew (jjc) at Carnegie-Mellon University
- * Modified to use "esym" as the end of the kernel instead of
- * "end" if the kernel debugger is enabled.
- *
- * 14-Aug-86 Jonathan J. Chew (jjc) at Carnegie-Mellon University
- * Replaced all occurences of "romp" with "sunromp" to avoid
- * name conflict with IBM PC RT "romp".
- * Added code to set aside 1 page of virtual memory per cpu
- * for scratch work.
- *
- * 31-Jul-86 Jonathan J. Chew (jjc) at Carnegie-Mellon University
- * Added code to set aside 2 pages of virtual memory for use
- * by the phys routines.
- *
- * 14-Jun-86 Jonathan J. Chew (jjc) at Carnegie-Mellon University
- * Created from startup routine.
- */
- #include <platforms.h>
- #include <cpus.h>
-
- #include <mach_kdb.h>
-
- #include <mach/boolean.h>
- #include <mach/vm_param.h>
- #include <mach/vm_prot.h>
-
- #include <sys/types.h>
-
- #include <sundev/mbvar.h>
-
- #include <machine/psl.h>
- #include <machine/reg.h>
- #include <machine/clock.h>
- #include <machine/scb.h>
- #include <machine/mmu.h>
- #include <machine/cpu.h>
- #include <machine/eeprom.h>
- #include <machine/interreg.h>
- #include <machine/memerr.h>
- #include <machine/eccreg.h>
-
- #include <sun3/pmap.h>
-
- #ifdef SUN3_260
- #include <sun3/enable.h>
-
- extern struct eccreg *ecc_alive[];
- #endif SUN3_260
-
- extern long getpgmap();
- extern u_char getsgmap(), pmegallocres();
-
- vm_offset_t avail_start; /* PA of first available physical page */
- vm_offset_t avail_end; /* PA of last available physical page */
- vm_size_t mem_size; /* memory size in bytes */
- vm_offset_t virtual_avail; /* VA of 1st available page (after kernel bss)*/
- vm_offset_t virtual_end; /* VA of last available page (end of kernel
- address space) */
- vm_offset_t hole_start, hole_end; /* for pmap_next_page */
- vm_offset_t avail_next; /* for pmap_next_page */
- unsigned int avail_remaining;/* for pmap_free_pages */
-
- vm_offset_t phys_map_vaddr1, phys_map_vaddr2;
-
- int physmem = 0; /* patch to restrict physical memory used */
-
- boolean_t kernprot = TRUE;/* write-protect kernel text */
-
- /*
-
- */
- /*
- * Sun3 initialization code.
- *
- * Running virtual.
- * BSS is still filled with symbol table and bootstrap image.
- */
-
- extern char start[], etext[], edata[], end[];
- extern void v_handler();
-
- #define sun_round_segment(x) (((vm_offset_t)(x)+SGOFSET)&~SGOFSET)
- void
- sun3_init()
- {
- register unsigned int i;
- register vm_offset_t v;
- vm_offset_t kernel_end;
- int mon_mem;
-
-
- initscb(); /* set trap vectors */
- *INTERREG |= IR_ENA_INT; /* make sure interrupts can occur */
-
- /*
- * Reset VM page size to be SUN3 page size.
- */
-
- page_size = NBPG;
- vm_set_page_size();
-
- /*
- * Move symbol table and bootstrap image out of BSS.
- */
-
- kernel_end = move_bootstrap();
-
- /*
- * Clear bss.
- */
- bzero(edata, end - edata);
-
- /*
- * Find end of occupied virtual (and physical)
- * memory. Virtual memory is assumed to be mapped
- * 1-1 to physical memory starting at
- * KERNELBASE::0.
- */
-
- kernel_end = round_page(kernel_end);
- avail_start = kernel_end - KERNELBASE;
-
- /*
- * Add virtual address space for
- * physical memory manipulation.
- */
- virtual_avail = kernel_end;
- phys_map_vaddr1 = virtual_avail;
- virtual_avail += PAGE_SIZE;
- phys_map_vaddr2 = virtual_avail;
- virtual_avail += PAGE_SIZE;
-
- /*
- * Reserve necessary pmegs and set segment mapping.
- */
-
- /*
- * Invalidate to start of kernel memory.
- */
- for (v = 0; v < (vm_offset_t)KERNELBASE; v += NBSG)
- setsgmap(v, (u_char)SEGINV);
-
- /*
- * Reserve kernel pmegs.
- */
- for (; v < sun_round_segment(kernel_end); v += NBSG)
- pmeg_reserve(v);
-
- /*
- * Invalidate to start of monitor.
- */
- for (; v < (vm_offset_t)MONSTART; v += NBSG)
- setsgmap(v, (u_char)SEGINV);
-
- /*
- * Reserve monitor pmegs.
- */
- for (; v < (vm_offset_t)MONEND; v += NBSG) {
-
- register vm_offset_t lv;
-
- if (getsgmap(v) != (u_char)SEGINV) {
-
- for (lv = v; lv < v + NBSG; lv += NBPG) {
- long pg = getpgmap(lv);
-
- if ((pg & PG_V) && (pg & PG_PROT) >= PG_KR)
- break;
- }
- if (lv < v + NBSG) {
- /*
- * The pmeg had a valid page with
- * some access allowed, reserve
- * the pmeg for the monitor.
- */
- pmeg_reserve(v);
- }
- else {
- /*
- * "steal" wasted pmeg back from the monitor
- */
- setsgmap(v, (u_char)SEGINV);
- }
- }
- }
-
- /*
- * Invalidate until last segment.
- */
- for (; v < (vm_offset_t)((NSEGMAP - 1)*NBSG); v += NBSG)
- setsgmap(v, (u_char)SEGINV);
-
- /*
- * Last segment is used for devices and dvma map.
- */
- pmeg_reserve(v);
-
- /*
- * Now go through all the other contexts and set up the
- * segment maps so that all segments are mapped the same.
- * We have to use a PROM routine to do this since we can`t
- * switch to a new (unmapped) context to call setsegmap()!
- */
- for (i = 0; i < NCONTEXT; i++) {
- if (i == KCONTEXT)
- continue;
-
- for (v = 0; v < (vm_offset_t)(NBSG * NSEGMAP); v += NBSG)
- (*sunromp->v_setcxsegmap)(i, v, getsgmap(v));
- }
-
- /*
- * Now all the monitor set up pmegs have been reserved.
- * Normal allocation can proceed.
- * pmap_reserve is now illegal.
- */
- pmap_bootstrap();
-
-
- /*
- * Initialize kernel page table entries.
- * We don`t know the physical addresses,
- * but they are set up, so we just fix
- * the protection.
- */
-
- /* invalid until start except scb page which is kernel writable */
-
- for (v = (vm_offset_t)KERNELBASE; v < (vm_offset_t)start; v += NBPG) {
- long pme;
-
- if (v == (vm_offset_t)&scb)
- pme = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
- else
- pme = 0;
- setpgmap(v, pme);
- }
-
- /* set up kernel text pages */
- pmap_protect(kernel_pmap,
- start,
- trunc_page(etext),
- kernprot ? VM_PROT_READ : VM_PROT_WRITE|VM_PROT_READ);
-
- /* set up kernel data/bss pages to be writeable */
- pmap_protect(kernel_pmap,
- trunc_page(etext),
- round_page(kernel_end),
- VM_PROT_READ|VM_PROT_WRITE);
-
- pme_zero(round_page(kernel_end),
- sun_round_segment(virtual_avail),
- TRUE);
-
- /*
- * Remove user access to monitor-set-up maps.
- */
- pme_protect(MONSTART, MONEND, PG_KW|PG_NC);
-
- /*
- * Invalidate any other pages in last segment besides
- * EEPROM_ADDR, CLKADDR, MEMREG, INTERREG and MONSHORTPAGE.
- * Since MONSHORTPAGE is defined as a 32 bit virtual address
- * (to get short references to work), we must mask to get
- * only the 28 bits we really want to look at.
- */
-
- for (v = (vm_offset_t)(NBSG * (NSEGMAP - 1));
- v < (vm_offset_t)(NBSG * NSEGMAP);
- v += NBPG)
- {
- if (v == ((vm_offset_t)MONSHORTPAGE & 0x0FFFFFFF))
- setpgmap(v, (long)((getpgmap(v) & ~PG_PROT) | PG_KW | PG_NC) );
- /* remove any user access */
- else if (
- v != ((vm_offset_t)MONSHORTPAGE & 0x0FFFFFFF) &&
- v != (vm_offset_t)EEPROM_ADDR &&
- v != (vm_offset_t)CLKADDR &&
- v != (vm_offset_t)MEMREG &&
- v != (vm_offset_t)INTERREG)
- setpgmap(v, (long)0);
- }
-
-
- setcputype(); /* sets cpu and dvmasize variables */
- #ifdef SUN3_260
- if (cpu == CPU_SUN3_260) /* initialize virtual address cache */
- vac_init();
- #endif
-
- /*
- * Make sure the memory error register is
- * set up to generate interrupts on error.
- */
- #if defined(SUN3_160) || defined(SUN3_50) || defined(SUN3_110) || defined(SUN3_60)
- if (cpu == CPU_SUN3_160 || cpu == CPU_SUN3_50)
- MEMREG->mr_per = PER_INTENA | PER_CHECK;
- #endif defined(SUN3_160) || defined(SUN3_50) || defined(SUN3_110) || defined(SUN3_60)
-
- #ifdef SUN3_260
- if (cpu == CPU_SUN3_260) {
- register struct eccreg **ecc_nxt = ecc_alive;
- register struct eccreg *ecc;
-
- /*
- * Go probe for all memory cards and perform initialization.
- * The address of the cards found is stashed in ecc_alive[].
- * We assume that the cards are already enabled and the
- * base addresses have been set correctly by the monitor.
- */
- for (ecc = ECCREG; ecc < &ECCREG[MAX_ECC]; ecc++) {
- if (peekc((char *)ecc) == -1)
- continue;
- MEMREG->mr_dvma = 1; /* clear intr from mem register */
- ecc->syndrome |= SY_CE_MASK; /* clear syndrom fields */
- ecc->eccena |= ENA_SCRUB_MASK;
- ecc->eccena |= ENA_BUSENA_MASK;
- *ecc_nxt++ = ecc;
- }
- *ecc_nxt = (struct eccreg *)0; /* terminate list */
- }
- #endif SUN3_260
-
- /*
- * v_memorysize is the amount of physical memory while
- * v_memoryavail is the amount of usable memory in versions
- * equal or greater to 1. Mon_mem is the difference which
- * is the number of pages hidden by the monitor.
- */
-
- if (sunromp->v_romvec_version >= 1)
- mon_mem = btop(*sunromp->v_memorysize - *sunromp->v_memoryavail);
- else
- mon_mem = 0;
-
- /*
- * If physmem is patched to be non-zero, use it instead of
- * the monitor value unless physmem is larger than the total
- * amount of memory on hand.
- */
- if (physmem == 0 || physmem > btop(*sunromp->v_memorysize))
- physmem = btop(*sunromp->v_memorysize);
- /*
- * Adjust physmem down for the pages stolen by the monitor.
- */
- physmem -= mon_mem;
-
- /*
- * v_vector_cmd is the handler for new monitor vector
- * command in versions equal or greater to 2.
- * We install v_handler() there for Unix.
- */
- if (sunromp->v_romvec_version >= 2)
- *sunromp->v_vector_cmd = v_handler;
-
- #include <bwtwo.h>
- #if NBWTWO > 0
- if (physmem > btop(OBFBADDR + FBSIZE))
- fbobmemavail = 1;
- else
- fbobmemavail = 0;
- #else
- fbobmemavail = 0;
- #endif
-
-
- /* XXX - need to handle message buffer */
-
-
- /*
- * Allocate pmegs for DVMA space with zero pme's
- */
- pme_zero(DVMA, DVMA + NBPG*dvmasize, TRUE);
-
- /*
- * Allocate IOPB memory space just below the message
- * buffer and map it to the first pages of DVMA space.
- */
- physmem -= IOPBMEM;
- pmap_map_page(DVMA, physmem, IOPBMEM*NBPG);
-
- /*
- * Tell the VM system what virtual and physical memory
- * it can use.
- */
- mem_size = (vm_size_t)ptob(physmem); /* Mach version of physmem */
-
- avail_start = (vm_offset_t)round_page(avail_start);
- avail_end = (vm_offset_t)trunc_page(mem_size);
-
- virtual_avail = (vm_offset_t)round_page(virtual_avail);
- virtual_end = (vm_offset_t)round_page(VM_MAX_KERNEL_ADDRESS);
-
- avail_remaining = atop((avail_end - avail_start) -
- (hole_end - hole_start));
- avail_next = avail_start;
-
- if (fbobmemavail) {
- /* leave room for the frame buffer */
-
- hole_start = trunc_page(OBFBADDR);
- hole_end = round_page(OBFBADDR + FBSIZE);
- } else {
- hole_start = 0;
- hole_end = 0;
- }
-
- /*
- * Run the system.
- */
- setup_main();
- /*NOTREACHED*/
- }
-