|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1995-1994 The University of Utah and ! 3: * the Computer Systems Laboratory at the University of Utah (CSL). ! 4: * All rights reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software is hereby ! 7: * granted provided that (1) source code retains these copyright, permission, ! 8: * and disclaimer notices, and (2) redistributions including binaries ! 9: * reproduce the notices in supporting documentation, and (3) all advertising ! 10: * materials mentioning features or use of this software display the following ! 11: * acknowledgement: ``This product includes software developed by the ! 12: * Computer Systems Laboratory at the University of Utah.'' ! 13: * ! 14: * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS ! 15: * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF ! 16: * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 17: * ! 18: * CSL requests users of this software to return to [email protected] any ! 19: * improvements that they make and grant CSL redistribution rights. ! 20: * ! 21: * Author: Bryan Ford, University of Utah CSL ! 22: */ ! 23: /* ! 24: This file rovides a default implementation ! 25: of real/pmode switching code. ! 26: Assumes that, as far as it's concerned, ! 27: low linear address always map to physical addresses. ! 28: (The low linear mappings can be changed, ! 29: but must be changed back before switching back to real mode.) ! 30: ! 31: Provides: ! 32: i16_raw_switch_to_pmode() ! 33: i16_raw_switch_to_real_mode() ! 34: ! 35: i16_raw_start() ! 36: Called in real mode. ! 37: Initializes the pmode switching system, ! 38: switches to pmode for the first time, ! 39: and calls the 32-bit function raw_start(). ! 40: ! 41: Depends on: ! 42: ! 43: paging.h: ! 44: raw_paging_enable() ! 45: raw_paging_disable() ! 46: raw_paging_init() ! 47: ! 48: a20.h: ! 49: i16_enable_a20() ! 50: i16_disable_a20() ! 51: ! 52: real.h: ! 53: real_cs ! 54: */ ! 55: ! 56: #include <mach/boolean.h> ! 57: #include <mach/machine/code16.h> ! 58: #include <mach/machine/vm_param.h> ! 59: #include <mach/machine/proc_reg.h> ! 60: #include <mach/machine/pio.h> ! 61: #include <mach/machine/seg.h> ! 62: #include <mach/machine/eflags.h> ! 63: #include <mach/machine/pmode.h> ! 64: ! 65: #include "config.h" ! 66: #include "cpu.h" ! 67: #include "i16.h" ! 68: #include "vm_param.h" ! 69: #include "pic.h" ! 70: #include "debug.h" ! 71: #include "i16_a20.h" ! 72: #include "i16_switch.h" ! 73: ! 74: int irq_master_base, irq_slave_base; ! 75: ! 76: /* Set to true when everything is initialized properly. */ ! 77: static boolean_t inited; ! 78: ! 79: /* Saved value of eflags register for real mode. */ ! 80: static unsigned real_eflags; ! 81: ! 82: ! 83: ! 84: #ifdef ENABLE_PAGING ! 85: #define RAW_PAGING_ENABLE() raw_paging_enable() ! 86: #define RAW_PAGING_DISABLE() raw_paging_disable() ! 87: #define RAW_PAGING_INIT() raw_paging_init() ! 88: #else ! 89: #define RAW_PAGING_ENABLE() ((void)0) ! 90: #define RAW_PAGING_DISABLE() ((void)0) ! 91: #define RAW_PAGING_INIT() ((void)0) ! 92: #endif ! 93: ! 94: ! 95: CODE16 ! 96: ! 97: void i16_raw_switch_to_pmode() ! 98: { ! 99: /* No interrupts from now on please. */ ! 100: i16_cli(); ! 101: ! 102: /* Save the eflags register for switching back later. */ ! 103: real_eflags = get_eflags(); ! 104: ! 105: /* Enable the A20 address line. */ ! 106: i16_enable_a20(); ! 107: ! 108: /* Load the GDT. ! 109: Note that we have to do this each time we enter pmode, ! 110: not just the first, ! 111: because other real-mode programs may have switched to pmode ! 112: and back again in the meantime, trashing the GDT pointer. */ ! 113: { ! 114: struct pseudo_descriptor pdesc; ! 115: ! 116: pdesc.limit = sizeof(cpu[0].tables.gdt)-1; ! 117: pdesc.linear_base = boot_image_pa ! 118: + (vm_offset_t)&cpu[0].tables.gdt; ! 119: i16_set_gdt(&pdesc); ! 120: } ! 121: ! 122: /* Switch into protected mode. */ ! 123: i16_enter_pmode(KERNEL_16_CS); ! 124: ! 125: /* Reload all the segment registers from the new GDT. */ ! 126: set_ds(KERNEL_DS); ! 127: set_es(KERNEL_DS); ! 128: set_fs(0); ! 129: set_gs(0); ! 130: set_ss(KERNEL_DS); ! 131: ! 132: i16_do_32bit( ! 133: ! 134: if (inited) ! 135: { ! 136: /* Turn paging on if necessary. */ ! 137: RAW_PAGING_ENABLE(); ! 138: ! 139: /* Load the CPU tables into the processor. */ ! 140: cpu_tables_load(&cpu[0]); ! 141: ! 142: /* Program the PIC so the interrupt vectors won't ! 143: conflict with the processor exception vectors. */ ! 144: pic_init(PICM_VECTBASE, PICS_VECTBASE); ! 145: } ! 146: ! 147: /* Make sure our flags register is appropriate. */ ! 148: set_eflags((get_eflags() ! 149: & ~(EFL_IF | EFL_DF | EFL_NT)) ! 150: | EFL_IOPL_USER); ! 151: ); ! 152: } ! 153: ! 154: void i16_raw_switch_to_real_mode() ! 155: { ! 156: /* Make sure interrupts are disabled. */ ! 157: cli(); ! 158: ! 159: /* Avoid sending DOS bogus coprocessor exceptions. ! 160: XXX should we save/restore all of CR0? */ ! 161: i16_clts(); ! 162: ! 163: i16_do_32bit( ! 164: /* Turn paging off if necessary. */ ! 165: RAW_PAGING_DISABLE(); ! 166: ! 167: /* Reprogram the PIC back to the settings DOS expects. */ ! 168: pic_init(0x08, 0x70); ! 169: ); ! 170: ! 171: /* Make sure all the segment registers are 16-bit. ! 172: The code segment definitely is already, ! 173: because we're running 16-bit code. */ ! 174: set_ds(KERNEL_16_DS); ! 175: set_es(KERNEL_16_DS); ! 176: set_fs(KERNEL_16_DS); ! 177: set_gs(KERNEL_16_DS); ! 178: set_ss(KERNEL_16_DS); ! 179: ! 180: /* Switch back to real mode. */ ! 181: i16_leave_pmode(real_cs); ! 182: ! 183: /* Load the real-mode segment registers. */ ! 184: set_ds(real_cs); ! 185: set_es(real_cs); ! 186: set_fs(real_cs); ! 187: set_gs(real_cs); ! 188: set_ss(real_cs); ! 189: ! 190: /* Load the real-mode IDT. */ ! 191: { ! 192: struct pseudo_descriptor pdesc; ! 193: ! 194: pdesc.limit = 0xffff; ! 195: pdesc.linear_base = 0; ! 196: i16_set_idt(&pdesc); ! 197: } ! 198: ! 199: /* Disable the A20 address line. */ ! 200: i16_disable_a20(); ! 201: ! 202: /* Restore the eflags register to its original real-mode state. ! 203: Note that this will leave interrupts disabled ! 204: since it was saved after the cli() above. */ ! 205: set_eflags(real_eflags); ! 206: } ! 207: ! 208: void i16_raw_start() ! 209: { ! 210: /* Make sure we're not already in protected mode. */ ! 211: if (i16_get_msw() & CR0_PE) ! 212: i16_die("The processor is in an unknown " ! 213: "protected mode environment."); ! 214: ! 215: do_debug(i16_puts("Real mode detected")); ! 216: ! 217: /* Minimally initialize the GDT. */ ! 218: i16_gdt_init_temp(); ! 219: ! 220: /* Switch to protected mode for the first time. ! 221: This won't load all the processor tables and everything yet, ! 222: since they're not fully initialized. */ ! 223: i16_raw_switch_to_pmode(); ! 224: ! 225: /* We can now hop in and out of 32-bit mode at will. */ ! 226: i16_do_32bit( ! 227: ! 228: /* Now that we can access all physical memory, ! 229: collect the memory regions we discovered while in 16-bit mode ! 230: and add them to our free memory list. ! 231: We can't do this before now because the free list nodes ! 232: are stored in the free memory itself, ! 233: which is probably out of reach of our 16-bit segments. */ ! 234: phys_mem_collect(); ! 235: ! 236: /* Initialize paging if necessary. ! 237: Do it before initializing the other processor tables ! 238: because they might have to be located ! 239: somewhere in high linear memory. */ ! 240: RAW_PAGING_INIT(); ! 241: ! 242: /* Initialize the processor tables. */ ! 243: cpu_init(&cpu[0]); ! 244: ! 245: /* Initialize the hardware interrupt vectors in the IDT. */ ! 246: irq_master_base = PICM_VECTBASE; ! 247: irq_slave_base = PICS_VECTBASE; ! 248: idt_irq_init(); ! 249: ! 250: inited = TRUE; ! 251: ! 252: /* Switch to real mode and back again once more, ! 253: to make sure everything's loaded properly. */ ! 254: do_16bit( ! 255: i16_raw_switch_to_real_mode(); ! 256: i16_raw_switch_to_pmode(); ! 257: ); ! 258: ! 259: raw_start(); ! 260: ); ! 261: } ! 262: ! 263: void (*i16_switch_to_real_mode)() = i16_raw_switch_to_real_mode; ! 264: void (*i16_switch_to_pmode)() = i16_raw_switch_to_pmode; ! 265:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.