diff options
Diffstat (limited to 'qemu/roms/qemu-palcode/init.c')
-rw-r--r-- | qemu/roms/qemu-palcode/init.c | 310 |
1 files changed, 0 insertions, 310 deletions
diff --git a/qemu/roms/qemu-palcode/init.c b/qemu/roms/qemu-palcode/init.c deleted file mode 100644 index 324bc911a..000000000 --- a/qemu/roms/qemu-palcode/init.c +++ /dev/null @@ -1,310 +0,0 @@ -/* Initialization of the system and the HWRPB. - - Copyright (C) 2011 Richard Henderson - - This file is part of QEMU PALcode. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text - of the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not see - <http://www.gnu.org/licenses/>. */ - -#include <string.h> -#include <stddef.h> -#include "hwrpb.h" -#include "osf.h" -#include "ioport.h" -#include "uart.h" -#include "protos.h" -#include SYSTEM_H - -#define PAGE_SHIFT 13 -#define PAGE_SIZE (1ul << PAGE_SHIFT) -#define PAGE_OFFSET 0xfffffc0000000000UL - -#define VPTPTR 0xfffffffe00000000UL - -#define PA(VA) ((unsigned long)(VA) & 0xfffffffffful) -#define VA(PA) ((void *)(PA) + PAGE_OFFSET) - -#define HZ 1024 - -struct hwrpb_combine { - struct hwrpb_struct hwrpb; - struct percpu_struct processor; - struct memdesc_struct md; - struct memclust_struct mc[2]; - struct crb_struct crb; - struct procdesc_struct proc_dispatch; - struct procdesc_struct proc_fixup; -}; - -extern char stack[PAGE_SIZE] __attribute__((section(".sbss"))); -extern char _end[] __attribute__((visibility("hidden"), nocommon)); - -struct pcb_struct pcb __attribute__((section(".sbss"))); - -static unsigned long page_dir[1024] - __attribute__((aligned(PAGE_SIZE), section(".bss.page_dir"))); - -/* The HWRPB must be aligned because it is exported at INIT_HWRPB. */ -struct hwrpb_combine hwrpb __attribute__((aligned(PAGE_SIZE))); - -void *last_alloc; -bool have_vga; - -static void * -alloc (unsigned long size, unsigned long align) -{ - void *p = (void *)(((unsigned long)last_alloc + align - 1) & ~(align - 1)); - last_alloc = p + size; - return memset (p, 0, size); -} - -static inline unsigned long -pt_index(unsigned long addr, int level) -{ - return (addr >> (PAGE_SHIFT + (10 * level))) & 0x3ff; -} - -static inline unsigned long -build_pte (void *page) -{ - unsigned long bits; - - bits = PA((unsigned long)page) << (32 - PAGE_SHIFT); - bits += _PAGE_VALID | _PAGE_KRE | _PAGE_KWE; - - return bits; -} - -static inline void * -pte_page (unsigned long pte) -{ - return VA(pte >> 32 << PAGE_SHIFT); -} - -static void -set_pte (unsigned long addr, void *page) -{ - unsigned long *pt = page_dir; - unsigned long index; - - index = pt_index(addr, 2); - if (pt[index] != 0) - pt = pte_page (pt[index]); - else - { - unsigned long *npt = alloc(PAGE_SIZE, PAGE_SIZE); - pt[index] = build_pte (npt); - pt = npt; - } - - index = pt_index(addr, 1); - if (pt[index] != 0) - pt = pte_page (pt[index]); - else - { - unsigned long *npt = alloc(PAGE_SIZE, PAGE_SIZE); - pt[index] = build_pte (npt); - pt = npt; - } - - index = pt_index(addr, 0); - pt[index] = build_pte (page); -} - -static void -init_page_table(void) -{ - /* Install the self-reference for the virtual page table base register. */ - page_dir[pt_index(VPTPTR, 2)] = build_pte(page_dir); - - set_pte ((unsigned long)INIT_HWRPB, &hwrpb); - - /* ??? SRM maps some amount of memory at 0x20000000 for use by programs - started from the console prompt. Including the bootloader. While - we're emulating MILO, don't bother as we jump straight to the kernel - loaded into KSEG. */ -} - -static void -init_hwrpb (unsigned long memsize) -{ - unsigned long pal_pages; - unsigned long amask; - - hwrpb.hwrpb.phys_addr = PA(&hwrpb); - - /* Yes, the 'HWRPB' magic is in big-endian byte ordering. */ - hwrpb.hwrpb.id = ( (long)'H' << 56 - | (long)'W' << 48 - | (long)'R' << 40 - | (long)'P' << 32 - | (long)'B' << 24); - - hwrpb.hwrpb.size = sizeof(struct hwrpb_struct); - - ((int *)hwrpb.hwrpb.ssn)[0] = ( 'Q' << 0 - | 'E' << 8 - | 'M' << 16 - | 'U' << 24); - - amask = ~__builtin_alpha_amask(-1); - switch (__builtin_alpha_implver()) - { - case 0: /* EV4 */ - hwrpb.hwrpb.cpuid = EV4_CPU; - hwrpb.hwrpb.max_asn = 63; - break; - - case 1: /* EV5 */ - hwrpb.hwrpb.cpuid - = ((amask & 0x101) == 0x101 ? PCA56_CPU /* MAX+BWX */ - : amask & 1 ? EV56_CPU /* BWX */ - : EV5_CPU); - hwrpb.hwrpb.max_asn = 127; - break; - - case 2: /* EV6 */ - hwrpb.hwrpb.cpuid = (amask & 4 ? EV67_CPU : EV6_CPU); /* CIX */ - hwrpb.hwrpb.max_asn = 255; - break; - } - - hwrpb.hwrpb.pagesize = PAGE_SIZE; - hwrpb.hwrpb.pa_bits = 40; - hwrpb.hwrpb.sys_type = SYS_TYPE; - hwrpb.hwrpb.sys_variation = SYS_VARIATION; - hwrpb.hwrpb.sys_revision = SYS_REVISION; - hwrpb.processor.type = hwrpb.hwrpb.cpuid; - - hwrpb.hwrpb.intr_freq = HZ * 4096; - hwrpb.hwrpb.cycle_freq = 250000000; /* QEMU architects 250MHz. */ - - hwrpb.hwrpb.vptb = VPTPTR; - - hwrpb.hwrpb.nr_processors = 1; - hwrpb.hwrpb.processor_size = sizeof(struct percpu_struct); - hwrpb.hwrpb.processor_offset = offsetof(struct hwrpb_combine, processor); - - hwrpb.hwrpb.mddt_offset = offsetof(struct hwrpb_combine, md); - hwrpb.md.numclusters = 2; - - pal_pages = (PA(last_alloc) + PAGE_SIZE - 1) >> PAGE_SHIFT; - - hwrpb.mc[0].numpages = pal_pages; - hwrpb.mc[0].usage = 1; - hwrpb.mc[1].start_pfn = pal_pages; - hwrpb.mc[1].numpages = (memsize >> PAGE_SHIFT) - pal_pages; - - hwrpb.hwrpb.crb_offset = offsetof(struct hwrpb_combine, crb); - hwrpb.crb.dispatch_va = &hwrpb.proc_dispatch; - hwrpb.crb.dispatch_pa = PA(&hwrpb.proc_dispatch); - hwrpb.crb.fixup_va = &hwrpb.proc_fixup; - hwrpb.crb.fixup_pa = PA(&hwrpb.proc_fixup); - hwrpb.crb.map_entries = 1; - hwrpb.crb.map_pages = 1; - hwrpb.crb.map[0].va = &hwrpb; - hwrpb.crb.map[0].pa = PA(&hwrpb); - hwrpb.crb.map[0].count = 1; - - /* See crb.c for how we match the VMS calling conventions to Unix. */ - hwrpb.proc_dispatch.address = (unsigned long)crb_dispatch; - hwrpb.proc_fixup.address = (unsigned long)crb_fixup; - - hwrpb_update_checksum(&hwrpb.hwrpb); -} - -static void -init_pcb (void) -{ - pcb.ksp = (unsigned long)stack + sizeof(stack); - pcb.ptbr = PA(page_dir) >> PAGE_SHIFT; - pcb.flags = 1; /* FEN */ -} - -static void -init_i8259 (void) -{ - /* ??? MILO initializes the PIC as edge triggered; I do not know how SRM - initializes them. However, Linux seems to expect that these are level - triggered. That may be a kernel bug, but level triggers are more - reliable anyway so lets go with that. */ - - /* Initialize the slave PIC. */ - outb(0x11, PORT_PIC2_CMD); /* ICW1: edge trigger, cascade, ICW4 req */ - outb(0x08, PORT_PIC2_DATA); /* ICW2: irq offset = 8 */ - outb(0x02, PORT_PIC2_DATA); /* ICW3: slave ID 2 */ - outb(0x01, PORT_PIC2_DATA); /* ICW4: not special nested, normal eoi */ - - /* Initialize the master PIC. */ - outb(0x11, PORT_PIC1_CMD); /* ICW1 */ - outb(0x00, PORT_PIC1_DATA); /* ICW2: irq offset = 0 */ - outb(0x04, PORT_PIC1_DATA); /* ICW3: slave control INTC2 */ - outb(0x01, PORT_PIC1_DATA); /* ICW4 */ - - /* Initialize level triggers. The CY82C693UB that's on real alpha - hardware doesn't have this; this is a PIIX extension. However, - QEMU doesn't implement regular level triggers. */ - outb(0xff, PORT_PIC2_ELCR); - outb(0xff, PORT_PIC1_ELCR); - - /* Disable all interrupts. */ - outb(0xff, PORT_PIC2_DATA); - outb(0xff, PORT_PIC1_DATA); - - /* Non-specific EOI, clearing anything the might be pending. */ - outb(0x20, PORT_PIC2_CMD); - outb(0x20, PORT_PIC1_CMD); -} - -void -do_start(unsigned long memsize, void (*kernel_entry)(void), long cpus) -{ - last_alloc = _end; - - init_page_table(); - init_hwrpb(memsize); - init_pcb(); - init_i8259(); - uart_init(); - ps2port_setup(); - pci_setup(); - vgahw_init(); - - { - register int variant __asm__("$16") = 2; /* OSF/1 PALcode */ - register void (*pc)(void) __asm__("$17"); - register unsigned long pa_pcb __asm__("$18"); - register unsigned long vptptr __asm__("$19"); - - pc = (kernel_entry ? kernel_entry : do_console); - pa_pcb = PA(&pcb); - vptptr = VPTPTR; - asm("call_pal 0x0a" : : "r"(variant), "r"(pc), "r"(pa_pcb), "r"(vptptr)); - } - __builtin_unreachable (); -} - -void -do_start_wait(void) -{ - while (1) - { - // WtInt with interrupts off. Rely on the fact that QEMU will - // un-halt the CPU when an interrupt arrives. - asm("lda $16,-1\n\tcall_pal 0x3e" : : : "$0", "$16"); - - // FIXME do something with the IPI. - } -} |