|
|
1.1 ! root 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 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 [email protected] ! 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: #include <cpus.h> ! 55: ! 56: #if NCPUS > 1 ! 57: ! 58: #include <kern/cpu_number.h> ! 59: #include <kern/cpu_data.h> ! 60: #include <mach/machine.h> ! 61: #include <vm/vm_kern.h> ! 62: ! 63: #include <i386/mp_desc.h> ! 64: #include <i386/lock.h> ! 65: #include <i386/misc_protos.h> ! 66: ! 67: #include <kern/misc_protos.h> ! 68: ! 69: #include <mach_kdb.h> ! 70: ! 71: /* ! 72: * The i386 needs an interrupt stack to keep the PCB stack from being ! 73: * overrun by interrupts. All interrupt stacks MUST lie at lower addresses ! 74: * than any thread`s kernel stack. ! 75: */ ! 76: ! 77: /* ! 78: * Addresses of bottom and top of interrupt stacks. ! 79: */ ! 80: vm_offset_t interrupt_stack[NCPUS]; ! 81: vm_offset_t int_stack_top[NCPUS]; ! 82: ! 83: /* ! 84: * Barrier address. ! 85: */ ! 86: vm_offset_t int_stack_high; ! 87: ! 88: /* ! 89: * First cpu`s interrupt stack. ! 90: */ ! 91: extern char intstack[]; /* bottom */ ! 92: extern char eintstack[]; /* top */ ! 93: ! 94: /* ! 95: * We allocate interrupt stacks from physical memory. ! 96: */ ! 97: extern ! 98: vm_offset_t avail_start; ! 99: ! 100: /* ! 101: * Multiprocessor i386/i486 systems use a separate copy of the ! 102: * GDT, IDT, LDT, and kernel TSS per processor. The first three ! 103: * are separate to avoid lock contention: the i386 uses locked ! 104: * memory cycles to access the descriptor tables. The TSS is ! 105: * separate since each processor needs its own kernel stack, ! 106: * and since using a TSS marks it busy. ! 107: */ ! 108: ! 109: /* ! 110: * Allocated descriptor tables. ! 111: */ ! 112: struct mp_desc_table *mp_desc_table[NCPUS] = { 0 }; ! 113: ! 114: /* ! 115: * Pointer to TSS for access in load_context. ! 116: */ ! 117: struct i386_tss *mp_ktss[NCPUS] = { 0 }; ! 118: ! 119: #if MACH_KDB ! 120: /* ! 121: * Pointer to TSS for debugger use. ! 122: */ ! 123: struct i386_tss *mp_dbtss[NCPUS] = { 0 }; ! 124: #endif /* MACH_KDB */ ! 125: ! 126: /* ! 127: * Pointer to GDT to reset the KTSS busy bit. ! 128: */ ! 129: struct fake_descriptor *mp_gdt[NCPUS] = { 0 }; ! 130: struct fake_descriptor *mp_idt[NCPUS] = { 0 }; ! 131: ! 132: /* ! 133: * Allocate and initialize the per-processor descriptor tables. ! 134: */ ! 135: ! 136: struct fake_descriptor ldt_desc_pattern = { ! 137: (unsigned int) 0, ! 138: LDTSZ * sizeof(struct fake_descriptor) - 1, ! 139: 0, ! 140: ACC_P|ACC_PL_K|ACC_LDT ! 141: }; ! 142: struct fake_descriptor tss_desc_pattern = { ! 143: (unsigned int) 0, ! 144: sizeof(struct i386_tss), ! 145: 0, ! 146: ACC_P|ACC_PL_K|ACC_TSS ! 147: }; ! 148: ! 149: struct fake_descriptor cpudata_desc_pattern = { ! 150: (unsigned int) 0, ! 151: sizeof(cpu_data_t)-1, ! 152: SZ_32, ! 153: ACC_P|ACC_PL_K|ACC_DATA_W ! 154: }; ! 155: ! 156: struct mp_desc_table * ! 157: mp_desc_init( ! 158: int mycpu) ! 159: { ! 160: register struct mp_desc_table *mpt; ! 161: ! 162: if (mycpu == master_cpu) { ! 163: /* ! 164: * Master CPU uses the tables built at boot time. ! 165: * Just set the TSS and GDT pointers. ! 166: */ ! 167: mp_ktss[mycpu] = &ktss; ! 168: #if MACH_KDB ! 169: mp_dbtss[mycpu] = &dbtss; ! 170: #endif /* MACH_KDB */ ! 171: mp_gdt[mycpu] = gdt; ! 172: mp_idt[mycpu] = idt; ! 173: return 0; ! 174: } ! 175: else { ! 176: mpt = mp_desc_table[mycpu]; ! 177: mp_ktss[mycpu] = &mpt->ktss; ! 178: mp_gdt[mycpu] = mpt->gdt; ! 179: mp_idt[mycpu] = mpt->idt; ! 180: ! 181: /* ! 182: * Copy the tables ! 183: */ ! 184: bcopy((char *)idt, ! 185: (char *)mpt->idt, ! 186: sizeof(idt)); ! 187: bcopy((char *)gdt, ! 188: (char *)mpt->gdt, ! 189: sizeof(gdt)); ! 190: bcopy((char *)ldt, ! 191: (char *)mpt->ldt, ! 192: sizeof(ldt)); ! 193: bzero((char *)&mpt->ktss, ! 194: sizeof(struct i386_tss)); ! 195: bzero((char *)&cpu_data[mycpu], ! 196: sizeof(cpu_data_t)); ! 197: #if MACH_KDB ! 198: mp_dbtss[mycpu] = &mpt->dbtss; ! 199: bcopy((char *)&dbtss, ! 200: (char *)&mpt->dbtss, ! 201: sizeof(struct i386_tss)); ! 202: #endif /* MACH_KDB */ ! 203: ! 204: /* ! 205: * Fix up the entries in the GDT to point to ! 206: * this LDT and this TSS. ! 207: */ ! 208: mpt->gdt[sel_idx(KERNEL_LDT)] = ldt_desc_pattern; ! 209: mpt->gdt[sel_idx(KERNEL_LDT)].offset = ! 210: LINEAR_KERNEL_ADDRESS + (unsigned int) mpt->ldt; ! 211: fix_desc(&mpt->gdt[sel_idx(KERNEL_LDT)], 1); ! 212: ! 213: mpt->gdt[sel_idx(KERNEL_TSS)] = tss_desc_pattern; ! 214: mpt->gdt[sel_idx(KERNEL_TSS)].offset = ! 215: LINEAR_KERNEL_ADDRESS + (unsigned int) &mpt->ktss; ! 216: fix_desc(&mpt->gdt[sel_idx(KERNEL_TSS)], 1); ! 217: ! 218: mpt->gdt[sel_idx(CPU_DATA)] = cpudata_desc_pattern; ! 219: mpt->gdt[sel_idx(CPU_DATA)].offset = ! 220: LINEAR_KERNEL_ADDRESS + (unsigned int) &cpu_data[mycpu]; ! 221: fix_desc(&mpt->gdt[sel_idx(CPU_DATA)], 1); ! 222: ! 223: #if MACH_KDB ! 224: mpt->gdt[sel_idx(DEBUG_TSS)] = tss_desc_pattern; ! 225: mpt->gdt[sel_idx(DEBUG_TSS)].offset = ! 226: LINEAR_KERNEL_ADDRESS + (unsigned int) &mpt->dbtss; ! 227: fix_desc(&mpt->gdt[sel_idx(DEBUG_TSS)], 1); ! 228: ! 229: mpt->dbtss.esp0 = (int)(db_task_stack_store + ! 230: (INTSTACK_SIZE * (mycpu + 1)) - sizeof (natural_t)); ! 231: mpt->dbtss.esp = mpt->dbtss.esp0; ! 232: mpt->dbtss.eip = (int)&db_task_start; ! 233: #endif /* MACH_KDB */ ! 234: ! 235: mpt->ktss.ss0 = KERNEL_DS; ! 236: mpt->ktss.io_bit_map_offset = 0x0FFF; /* no IO bitmap */ ! 237: ! 238: return mpt; ! 239: } ! 240: } ! 241: ! 242: /* ! 243: * Called after all CPUs have been found, but before the VM system ! 244: * is running. The machine array must show which CPUs exist. ! 245: */ ! 246: void ! 247: interrupt_stack_alloc(void) ! 248: { ! 249: register int i; ! 250: int cpu_count; ! 251: vm_offset_t stack_start; ! 252: struct mp_desc_table *mpt; ! 253: ! 254: /* ! 255: * Count the number of CPUs. ! 256: */ ! 257: cpu_count = 0; ! 258: for (i = 0; i < NCPUS; i++) ! 259: if (machine_slot[i].is_cpu) ! 260: cpu_count++; ! 261: ! 262: /* ! 263: * Allocate an interrupt stack for each CPU except for ! 264: * the master CPU (which uses the bootstrap stack) ! 265: */ ! 266: stack_start = phystokv(avail_start); ! 267: avail_start = round_page(avail_start + INTSTACK_SIZE*(cpu_count-1)); ! 268: bzero((char *)stack_start, INTSTACK_SIZE*(cpu_count-1)); ! 269: ! 270: /* ! 271: * Set up pointers to the top of the interrupt stack. ! 272: */ ! 273: for (i = 0; i < NCPUS; i++) { ! 274: if (i == master_cpu) { ! 275: interrupt_stack[i] = (vm_offset_t) intstack; ! 276: int_stack_top[i] = (vm_offset_t) eintstack; ! 277: } ! 278: else if (machine_slot[i].is_cpu) { ! 279: interrupt_stack[i] = stack_start; ! 280: int_stack_top[i] = stack_start + INTSTACK_SIZE; ! 281: ! 282: stack_start += INTSTACK_SIZE; ! 283: } ! 284: } ! 285: ! 286: /* ! 287: * Allocate descriptor tables for each CPU except for ! 288: * the master CPU (which already has them initialized) ! 289: */ ! 290: ! 291: mpt = (struct mp_desc_table *) phystokv(avail_start); ! 292: avail_start = round_page((vm_offset_t)avail_start + ! 293: sizeof(struct mp_desc_table)*(cpu_count-1)); ! 294: for (i = 0; i < NCPUS; i++) ! 295: if (i != master_cpu) ! 296: mp_desc_table[i] = mpt++; ! 297: ! 298: ! 299: /* ! 300: * Set up the barrier address. All thread stacks MUST ! 301: * be above this address. ! 302: */ ! 303: /* ! 304: * intstack is at higher addess than stack_start for AT mps ! 305: * so int_stack_high must point at eintstack. ! 306: * XXX ! 307: * But what happens if a kernel stack gets allocated below ! 308: * 1 Meg ? Probably never happens, there is only 640 K available ! 309: * There. ! 310: */ ! 311: int_stack_high = (vm_offset_t) eintstack; ! 312: } ! 313: ! 314: #endif /* NCPUS > 1 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.