|
|
1.1 ! root 1: /* Initialization of the system and the HWRPB. ! 2: ! 3: Copyright (C) 2011 Richard Henderson ! 4: ! 5: This file is part of QEMU PALcode. ! 6: ! 7: This program is free software; you can redistribute it and/or modify ! 8: it under the terms of the GNU General Public License as published by ! 9: the Free Software Foundation; either version 2 of the License or ! 10: (at your option) any later version. ! 11: ! 12: This program is distributed in the hope that it will be useful, ! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text ! 15: of the GNU General Public License for more details. ! 16: ! 17: You should have received a copy of the GNU General Public License ! 18: along with this program; see the file COPYING. If not see ! 19: <http://www.gnu.org/licenses/>. */ ! 20: ! 21: #include <string.h> ! 22: #include <stddef.h> ! 23: #include "hwrpb.h" ! 24: #include "osf.h" ! 25: #include "ioport.h" ! 26: #include "uart.h" ! 27: #include "protos.h" ! 28: #include SYSTEM_H ! 29: ! 30: #define PAGE_SHIFT 13 ! 31: #define PAGE_SIZE (1ul << PAGE_SHIFT) ! 32: #define PAGE_OFFSET 0xfffffc0000000000UL ! 33: ! 34: #define VPTPTR 0xfffffffe00000000UL ! 35: ! 36: #define PA(VA) ((unsigned long)(VA) & 0xfffffffffful) ! 37: #define VA(PA) ((void *)(PA) + PAGE_OFFSET) ! 38: ! 39: #define HZ 1024 ! 40: ! 41: struct hwrpb_combine { ! 42: struct hwrpb_struct hwrpb; ! 43: struct percpu_struct processor; ! 44: struct memdesc_struct md; ! 45: struct memclust_struct mc[2]; ! 46: struct crb_struct crb; ! 47: struct procdesc_struct proc_dispatch; ! 48: struct procdesc_struct proc_fixup; ! 49: }; ! 50: ! 51: extern char stack[PAGE_SIZE] __attribute__((section(".sbss"))); ! 52: extern char _end[] __attribute__((visibility("hidden"), nocommon)); ! 53: ! 54: struct pcb_struct pcb __attribute__((section(".sbss"))); ! 55: ! 56: static unsigned long page_dir[1024] __attribute__((aligned(PAGE_SIZE))); ! 57: ! 58: /* The HWRPB must be aligned because it is exported at INIT_HWRPB. */ ! 59: struct hwrpb_combine hwrpb __attribute__((aligned(PAGE_SIZE))); ! 60: ! 61: void *last_alloc; ! 62: bool have_vga; ! 63: ! 64: static void * ! 65: alloc (unsigned long size, unsigned long align) ! 66: { ! 67: void *p = (void *)(((unsigned long)last_alloc + align - 1) & ~(align - 1)); ! 68: last_alloc = p + size; ! 69: return memset (p, 0, size); ! 70: } ! 71: ! 72: static inline unsigned long ! 73: pt_index(unsigned long addr, int level) ! 74: { ! 75: return (addr >> (PAGE_SHIFT + (10 * level))) & 0x3ff; ! 76: } ! 77: ! 78: static inline unsigned long ! 79: build_pte (void *page) ! 80: { ! 81: unsigned long bits; ! 82: ! 83: bits = PA((unsigned long)page) << (32 - PAGE_SHIFT); ! 84: bits += _PAGE_VALID | _PAGE_KRE | _PAGE_KWE; ! 85: ! 86: return bits; ! 87: } ! 88: ! 89: static inline void * ! 90: pte_page (unsigned long pte) ! 91: { ! 92: return VA(pte >> 32 << PAGE_SHIFT); ! 93: } ! 94: ! 95: static void ! 96: set_pte (unsigned long addr, void *page) ! 97: { ! 98: unsigned long *pt = page_dir; ! 99: unsigned long index; ! 100: ! 101: index = pt_index(addr, 2); ! 102: if (pt[index] != 0) ! 103: pt = pte_page (pt[index]); ! 104: else ! 105: { ! 106: unsigned long *npt = alloc(PAGE_SIZE, PAGE_SIZE); ! 107: pt[index] = build_pte (npt); ! 108: pt = npt; ! 109: } ! 110: ! 111: index = pt_index(addr, 1); ! 112: if (pt[index] != 0) ! 113: pt = pte_page (pt[index]); ! 114: else ! 115: { ! 116: unsigned long *npt = alloc(PAGE_SIZE, PAGE_SIZE); ! 117: pt[index] = build_pte (npt); ! 118: pt = npt; ! 119: } ! 120: ! 121: index = pt_index(addr, 0); ! 122: pt[index] = build_pte (page); ! 123: } ! 124: ! 125: static void ! 126: init_page_table(void) ! 127: { ! 128: /* Install the self-reference for the virtual page table base register. */ ! 129: page_dir[pt_index(VPTPTR, 2)] = build_pte(page_dir); ! 130: ! 131: set_pte ((unsigned long)INIT_HWRPB, &hwrpb); ! 132: ! 133: /* ??? SRM maps some amount of memory at 0x20000000 for use by programs ! 134: started from the console prompt. Including the bootloader. While ! 135: we're emulating MILO, don't bother as we jump straight to the kernel ! 136: loaded into KSEG. */ ! 137: } ! 138: ! 139: static void ! 140: init_hwrpb (unsigned long memsize) ! 141: { ! 142: unsigned long pal_pages; ! 143: unsigned long amask; ! 144: ! 145: hwrpb.hwrpb.phys_addr = PA(&hwrpb); ! 146: ! 147: /* Yes, the 'HWRPB' magic is in big-endian byte ordering. */ ! 148: hwrpb.hwrpb.id = ( (long)'H' << 56 ! 149: | (long)'W' << 48 ! 150: | (long)'R' << 40 ! 151: | (long)'P' << 32 ! 152: | (long)'B' << 24); ! 153: ! 154: hwrpb.hwrpb.size = sizeof(struct hwrpb_struct); ! 155: ! 156: ((int *)hwrpb.hwrpb.ssn)[0] = ( 'Q' << 0 ! 157: | 'E' << 8 ! 158: | 'M' << 16 ! 159: | 'U' << 24); ! 160: ! 161: amask = ~__builtin_alpha_amask(-1); ! 162: switch (__builtin_alpha_implver()) ! 163: { ! 164: case 0: /* EV4 */ ! 165: hwrpb.hwrpb.cpuid = EV4_CPU; ! 166: hwrpb.hwrpb.max_asn = 63; ! 167: break; ! 168: ! 169: case 1: /* EV5 */ ! 170: hwrpb.hwrpb.cpuid ! 171: = ((amask & 0x101) == 0x101 ? PCA56_CPU /* MAX+BWX */ ! 172: : amask & 1 ? EV56_CPU /* BWX */ ! 173: : EV5_CPU); ! 174: hwrpb.hwrpb.max_asn = 127; ! 175: break; ! 176: ! 177: case 2: /* EV6 */ ! 178: hwrpb.hwrpb.cpuid = (amask & 4 ? EV67_CPU : EV6_CPU); /* CIX */ ! 179: hwrpb.hwrpb.max_asn = 255; ! 180: break; ! 181: } ! 182: ! 183: hwrpb.hwrpb.pagesize = PAGE_SIZE; ! 184: hwrpb.hwrpb.pa_bits = 40; ! 185: hwrpb.hwrpb.sys_type = SYS_TYPE; ! 186: hwrpb.hwrpb.sys_variation = SYS_VARIATION; ! 187: hwrpb.hwrpb.sys_revision = SYS_REVISION; ! 188: hwrpb.processor.type = hwrpb.hwrpb.cpuid; ! 189: ! 190: hwrpb.hwrpb.intr_freq = HZ * 4096; ! 191: hwrpb.hwrpb.cycle_freq = 250000000; /* QEMU architects 250MHz. */ ! 192: ! 193: hwrpb.hwrpb.vptb = VPTPTR; ! 194: ! 195: hwrpb.hwrpb.nr_processors = 1; ! 196: hwrpb.hwrpb.processor_size = sizeof(struct percpu_struct); ! 197: hwrpb.hwrpb.processor_offset = offsetof(struct hwrpb_combine, processor); ! 198: ! 199: hwrpb.hwrpb.mddt_offset = offsetof(struct hwrpb_combine, md); ! 200: hwrpb.md.numclusters = 2; ! 201: ! 202: pal_pages = (PA(last_alloc) + PAGE_SIZE - 1) >> PAGE_SHIFT; ! 203: ! 204: hwrpb.mc[0].numpages = pal_pages; ! 205: hwrpb.mc[0].usage = 1; ! 206: hwrpb.mc[1].start_pfn = pal_pages; ! 207: hwrpb.mc[1].numpages = (memsize >> PAGE_SHIFT) - pal_pages; ! 208: ! 209: hwrpb.hwrpb.crb_offset = offsetof(struct hwrpb_combine, crb); ! 210: hwrpb.crb.dispatch_va = &hwrpb.proc_dispatch; ! 211: hwrpb.crb.dispatch_pa = PA(&hwrpb.proc_dispatch); ! 212: hwrpb.crb.fixup_va = &hwrpb.proc_fixup; ! 213: hwrpb.crb.fixup_pa = PA(&hwrpb.proc_fixup); ! 214: hwrpb.crb.map_entries = 1; ! 215: hwrpb.crb.map_pages = 1; ! 216: hwrpb.crb.map[0].va = &hwrpb; ! 217: hwrpb.crb.map[0].pa = PA(&hwrpb); ! 218: hwrpb.crb.map[0].count = 1; ! 219: ! 220: /* See crb.c for how we match the VMS calling conventions to Unix. */ ! 221: hwrpb.proc_dispatch.address = (unsigned long)crb_dispatch; ! 222: hwrpb.proc_fixup.address = (unsigned long)crb_fixup; ! 223: ! 224: hwrpb_update_checksum(&hwrpb.hwrpb); ! 225: } ! 226: ! 227: static void ! 228: init_pcb (void) ! 229: { ! 230: pcb.ksp = (unsigned long)stack + sizeof(stack); ! 231: pcb.ptbr = PA(page_dir) >> PAGE_SHIFT; ! 232: pcb.flags = 1; /* FEN */ ! 233: } ! 234: ! 235: static void ! 236: init_i8259 (void) ! 237: { ! 238: /* ??? MILO initializes the PIC as edge triggered; I do not know how SRM ! 239: initializes them. However, Linux seems to expect that these are level ! 240: triggered. That may be a kernel bug, but level triggers are more ! 241: reliable anyway so lets go with that. */ ! 242: ! 243: /* Initialize the slave PIC. */ ! 244: outb(0x11, PORT_PIC2_CMD); /* ICW1: edge trigger, cascade, ICW4 req */ ! 245: outb(0x08, PORT_PIC2_DATA); /* ICW2: irq offset = 8 */ ! 246: outb(0x02, PORT_PIC2_DATA); /* ICW3: slave ID 2 */ ! 247: outb(0x01, PORT_PIC2_DATA); /* ICW4: not special nested, normal eoi */ ! 248: ! 249: /* Initialize the master PIC. */ ! 250: outb(0x11, PORT_PIC1_CMD); /* ICW1 */ ! 251: outb(0x00, PORT_PIC1_DATA); /* ICW2: irq offset = 0 */ ! 252: outb(0x04, PORT_PIC1_DATA); /* ICW3: slave control INTC2 */ ! 253: outb(0x01, PORT_PIC1_DATA); /* ICW4 */ ! 254: ! 255: /* Initialize level triggers. The CY82C693UB that's on real alpha ! 256: hardware doesn't have this; this is a PIIX extension. However, ! 257: QEMU doesn't implement regular level triggers. */ ! 258: outb(0xff, PORT_PIC2_ELCR); ! 259: outb(0xff, PORT_PIC1_ELCR); ! 260: ! 261: /* Disable all interrupts. */ ! 262: outb(0xff, PORT_PIC2_DATA); ! 263: outb(0xff, PORT_PIC1_DATA); ! 264: ! 265: /* Non-specific EOI, clearing anything the might be pending. */ ! 266: outb(0x20, PORT_PIC2_CMD); ! 267: outb(0x20, PORT_PIC1_CMD); ! 268: } ! 269: ! 270: void ! 271: do_start(unsigned long memsize, void (*kernel_entry)(void), long cpus) ! 272: { ! 273: last_alloc = _end; ! 274: ! 275: init_page_table(); ! 276: init_hwrpb(memsize); ! 277: init_pcb(); ! 278: init_i8259(); ! 279: uart_init(); ! 280: ps2port_setup(); ! 281: pci_setup(); ! 282: vgahw_init(); ! 283: ! 284: { ! 285: register int variant __asm__("$16") = 2; /* OSF/1 PALcode */ ! 286: register void (*pc)(void) __asm__("$17"); ! 287: register unsigned long pa_pcb __asm__("$18"); ! 288: register unsigned long vptptr __asm__("$19"); ! 289: ! 290: pc = (kernel_entry ? kernel_entry : do_console); ! 291: pa_pcb = PA(&pcb); ! 292: vptptr = VPTPTR; ! 293: asm("call_pal 0x0a" : : "r"(variant), "r"(pc), "r"(pa_pcb), "r"(vptptr)); ! 294: } ! 295: __builtin_unreachable (); ! 296: } ! 297: ! 298: void ! 299: do_start_wait(void) ! 300: { ! 301: while (1) ! 302: { ! 303: // WtInt with interrupts off. Rely on the fact that QEMU will ! 304: // un-halt the CPU when an interrupt arrives. ! 305: asm("lda $16,-1\n\tcall_pal 0x3e" : : : "$0", "$16"); ! 306: ! 307: // FIXME do something with the IPI. ! 308: } ! 309: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.