diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 17 | ||||
-rw-r--r-- | hwrpb.h | 220 | ||||
-rw-r--r-- | init.c | 206 | ||||
-rw-r--r-- | memset.c | 73 | ||||
-rw-r--r-- | palcode.ld | 48 |
6 files changed, 562 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5761abc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.o @@ -1,6 +1,17 @@ CC = /home/rth/work/gcc/run-axp/bin/alphaev6-linux-gcc +LD = /home/rth/work/gcc/run-axp/bin/alphaev6-linux-ld +CFLAGS = -O2 -g -msmall-text -msmall-data -fvisibility=hidden -all: pal.o +OBJS = pal.o init.o memset.o -pal.o: pal.S - $(CC) -c -Wa,-m21264 -g -o $@ $< +all: palcode + +palcode: palcode.ld $(OBJS) + $(LD) -relax -o $@ -T palcode.ld -Map palcode.map $(OBJS) + +clean: + rm -f *.o + rm -f palcode palcode.map + +pal.o: pal.S osf.h + $(CC) $(CFLAGS) -c -Wa,-m21264 -Wa,--noexecstack -o $@ $< @@ -0,0 +1,220 @@ +#ifndef __ALPHA_HWRPB_H +#define __ALPHA_HWRPB_H + +#define INIT_HWRPB ((struct hwrpb_struct *) 0x10000000) + +/* + * DEC processor types for Alpha systems. Found in HWRPB. + * These values are architected. + */ + +#define EV3_CPU 1 /* EV3 */ +#define EV4_CPU 2 /* EV4 (21064) */ +#define LCA4_CPU 4 /* LCA4 (21066/21068) */ +#define EV5_CPU 5 /* EV5 (21164) */ +#define EV45_CPU 6 /* EV4.5 (21064/xxx) */ +#define EV56_CPU 7 /* EV5.6 (21164) */ +#define EV6_CPU 8 /* EV6 (21264) */ +#define PCA56_CPU 9 /* PCA56 (21164PC) */ +#define PCA57_CPU 10 /* PCA57 (notyet) */ +#define EV67_CPU 11 /* EV67 (21264A) */ +#define EV68CB_CPU 12 /* EV68CB (21264C) */ +#define EV68AL_CPU 13 /* EV68AL (21264B) */ +#define EV68CX_CPU 14 /* EV68CX (21264D) */ +#define EV7_CPU 15 /* EV7 (21364) */ +#define EV79_CPU 16 /* EV79 (21364??) */ +#define EV69_CPU 17 /* EV69 (21264/EV69A) */ + +/* + * DEC system types for Alpha systems. Found in HWRPB. + * These values are architected. + */ + +#define ST_ADU 1 /* Alpha ADU systype */ +#define ST_DEC_4000 2 /* Cobra systype */ +#define ST_DEC_7000 3 /* Ruby systype */ +#define ST_DEC_3000_500 4 /* Flamingo systype */ +#define ST_DEC_2000_300 6 /* Jensen systype */ +#define ST_DEC_3000_300 7 /* Pelican systype */ +#define ST_DEC_2100_A500 9 /* Sable systype */ +#define ST_DEC_AXPVME_64 10 /* AXPvme system type */ +#define ST_DEC_AXPPCI_33 11 /* NoName system type */ +#define ST_DEC_TLASER 12 /* Turbolaser systype */ +#define ST_DEC_2100_A50 13 /* Avanti systype */ +#define ST_DEC_MUSTANG 14 /* Mustang systype */ +#define ST_DEC_ALCOR 15 /* Alcor (EV5) systype */ +#define ST_DEC_1000 17 /* Mikasa systype */ +#define ST_DEC_EB64 18 /* EB64 systype */ +#define ST_DEC_EB66 19 /* EB66 systype */ +#define ST_DEC_EB64P 20 /* EB64+ systype */ +#define ST_DEC_BURNS 21 /* laptop systype */ +#define ST_DEC_RAWHIDE 22 /* Rawhide systype */ +#define ST_DEC_K2 23 /* K2 systype */ +#define ST_DEC_LYNX 24 /* Lynx systype */ +#define ST_DEC_XL 25 /* Alpha XL systype */ +#define ST_DEC_EB164 26 /* EB164 systype */ +#define ST_DEC_NORITAKE 27 /* Noritake systype */ +#define ST_DEC_CORTEX 28 /* Cortex systype */ +#define ST_DEC_MIATA 30 /* Miata systype */ +#define ST_DEC_XXM 31 /* XXM systype */ +#define ST_DEC_TAKARA 32 /* Takara systype */ +#define ST_DEC_YUKON 33 /* Yukon systype */ +#define ST_DEC_TSUNAMI 34 /* Tsunami systype */ +#define ST_DEC_WILDFIRE 35 /* Wildfire systype */ +#define ST_DEC_CUSCO 36 /* CUSCO systype */ +#define ST_DEC_EIGER 37 /* Eiger systype */ +#define ST_DEC_TITAN 38 /* Titan systype */ +#define ST_DEC_MARVEL 39 /* Marvel systype */ + +/* UNOFFICIAL!!! */ +#define ST_UNOFFICIAL_BIAS 100 +#define ST_DTI_RUFFIAN 101 /* RUFFIAN systype */ + +/* Alpha Processor, Inc. systems */ +#define ST_API_BIAS 200 +#define ST_API_NAUTILUS 201 /* UP1000 systype */ + +struct pcb_struct { + unsigned long ksp; + unsigned long usp; + unsigned long ptbr; + unsigned int pcc; + unsigned int asn; + unsigned long unique; + unsigned long flags; + unsigned long res1, res2; +}; + +struct percpu_struct { + unsigned long hwpcb[16]; + unsigned long flags; + unsigned long pal_mem_size; + unsigned long pal_scratch_size; + unsigned long pal_mem_pa; + unsigned long pal_scratch_pa; + unsigned long pal_revision; + unsigned long type; + unsigned long variation; + unsigned long revision; + unsigned long serial_no[2]; + unsigned long logout_area_pa; + unsigned long logout_area_len; + unsigned long halt_PCBB; + unsigned long halt_PC; + unsigned long halt_PS; + unsigned long halt_arg; + unsigned long halt_ra; + unsigned long halt_pv; + unsigned long halt_reason; + unsigned long res; + unsigned long ipc_buffer[21]; + unsigned long palcode_avail[16]; + unsigned long compatibility; + unsigned long console_data_log_pa; + unsigned long console_data_log_length; + unsigned long bcache_info; +}; + +struct procdesc_struct { + unsigned long weird_vms_stuff; + unsigned long address; +}; + +struct vf_map_struct { + unsigned long va; + unsigned long pa; + unsigned long count; +}; + +struct crb_struct { + struct procdesc_struct * dispatch_va; + struct procdesc_struct * dispatch_pa; + struct procdesc_struct * fixup_va; + struct procdesc_struct * fixup_pa; + /* virtual->physical map */ + unsigned long map_entries; + unsigned long map_pages; + struct vf_map_struct map[1]; +}; + +struct memclust_struct { + unsigned long start_pfn; + unsigned long numpages; + unsigned long numtested; + unsigned long bitmap_va; + unsigned long bitmap_pa; + unsigned long bitmap_chksum; + unsigned long usage; +}; + +struct memdesc_struct { + unsigned long chksum; + unsigned long optional_pa; + unsigned long numclusters; + struct memclust_struct cluster[0]; +}; + +struct dsr_struct { + long smm; /* SMM nubber used by LMF */ + unsigned long lurt_off; /* offset to LURT table */ + unsigned long sysname_off; /* offset to sysname char count */ +}; + +struct hwrpb_struct { + unsigned long phys_addr; /* check: physical address of the hwrpb */ + unsigned long id; /* check: "HWRPB\0\0\0" */ + unsigned long revision; + unsigned long size; /* size of hwrpb */ + unsigned long cpuid; + unsigned long pagesize; /* 8192, I hope */ + unsigned long pa_bits; /* number of physical address bits */ + unsigned long max_asn; + unsigned char ssn[16]; /* system serial number: big bother is watching */ + unsigned long sys_type; + unsigned long sys_variation; + unsigned long sys_revision; + unsigned long intr_freq; /* interval clock frequency * 4096 */ + unsigned long cycle_freq; /* cycle counter frequency */ + unsigned long vptb; /* Virtual Page Table Base address */ + unsigned long res1; + unsigned long tbhb_offset; /* Translation Buffer Hint Block */ + unsigned long nr_processors; + unsigned long processor_size; + unsigned long processor_offset; + unsigned long ctb_nr; + unsigned long ctb_size; /* console terminal block size */ + unsigned long ctbt_offset; /* console terminal block table offset */ + unsigned long crb_offset; /* console callback routine block */ + unsigned long mddt_offset; /* memory data descriptor table */ + unsigned long cdb_offset; /* configuration data block (or NULL) */ + unsigned long frut_offset; /* FRU table (or NULL) */ + void (*save_terminal)(unsigned long); + unsigned long save_terminal_data; + void (*restore_terminal)(unsigned long); + unsigned long restore_terminal_data; + void (*CPU_restart)(unsigned long); + unsigned long CPU_restart_data; + unsigned long res2; + unsigned long res3; + unsigned long chksum; + unsigned long rxrdy; + unsigned long txrdy; + unsigned long dsr_offset; /* "Dynamic System Recognition Data Block Table" */ +}; + +#ifdef __KERNEL__ + +extern struct hwrpb_struct *hwrpb; + +static inline void +hwrpb_update_checksum(struct hwrpb_struct *h) +{ + unsigned long sum = 0, *l; + for (l = (unsigned long *) h; l < (unsigned long *) &h->chksum; ++l) + sum += *l; + h->chksum = sum; +} + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_HWRPB_H */ @@ -0,0 +1,206 @@ +#include <string.h> +#include <stddef.h> +#include "hwrpb.h" +#include "osf.h" + +#define PAGE_SHIFT 13 +#define PAGE_SIZE (1ul << PAGE_SHIFT) +#define PAGE_OFFSET 0xfffffc0000000000UL + +#define HZ 1024 + +struct pcb_struct pal_pcb __attribute__((section(".sbss"))); + +unsigned long page_dir[1024] __attribute__((aligned(PAGE_SIZE))); +unsigned long page_L1[1024] __attribute__((aligned(PAGE_SIZE))); +unsigned long page_L2[1024][1024] __attribute__((aligned(PAGE_SIZE))); + +struct hwrpb_combine { + struct hwrpb_struct hwrpb; + struct percpu_struct processor; + struct memdesc_struct md; + struct memclust_struct mc[2]; +} hwrpb __attribute__((section(".data.hwrpb"))) = { + /* This is HWRPB\0\0\0. */ + .hwrpb.id = 0x4857525042000000, + + .hwrpb.size = sizeof(struct hwrpb_struct), + .hwrpb.pagesize = PAGE_SIZE, + .hwrpb.ssn = "QEMU", + + /* ??? This should match TARGET_PHYS_ADDR_SPACE_BITS from qemu. */ + .hwrpb.pa_bits = 44, + + /* ??? Should we be truethful and say 1 asn, or simply pretend we + have ASNs but ignore them? */ + .hwrpb.max_asn = 127, + + /* For now, hard-code emulation of sx164. */ + .hwrpb.cpuid = PCA56_CPU, + .processor.type = PCA56_CPU, + .hwrpb.sys_type = ST_DEC_EB164, + .hwrpb.sys_variation = 15 << 10, + .hwrpb.sys_revision = 0, + + .hwrpb.intr_freq = HZ * 4096, + + /* ??? What the hell should we put here. Measure like the kernel will? */ + .hwrpb.cycle_freq = 400000000, + + .hwrpb.vptb = 0x200000000UL, + .hwrpb.nr_processors = 1, + .hwrpb.processor_size = sizeof(struct percpu_struct), + .hwrpb.processor_offset = offsetof(struct hwrpb_combine, processor), + + .hwrpb.mddt_offset = offsetof(struct hwrpb_combine, md), + .md.numclusters = 2, + .mc[0].usage = 2 +}; + +static unsigned long +init_cpuid (void) +{ + unsigned long implver, amask; + + __asm ("implver %0" : "=r"(implver)); + __asm ("amask %1,%0" : "=r"(amask) : "r"(-1)); + amask = ~amask; + + switch (implver) + { + case 0: /* EV4 */ + return EV4_CPU; + + case 1: /* EV5 */ + if ((amask & 0x101) == 0x101) /* MAX + BWX */ + return PCA56_CPU; + if (amask & 1) /* BWX */ + return EV56_CPU; + return EV5_CPU; + + case 2: /* EV6 */ + if (amask & 4) /* CIX */ + return EV67_CPU; + return EV6_CPU; + } + return 0; +} + +static void +hwrpb_update_checksum (void) +{ + unsigned long sum = 0, *l; + for (l = (unsigned long *) &hwrpb.hwrpb; l < &hwrpb.hwrpb.chksum; ++l) + sum += *l; + hwrpb.hwrpb.chksum = sum; +} + +static void +init_hwrpb (unsigned long memsize) +{ + unsigned long end, pal_pages; + + hwrpb.hwrpb.phys_addr = (unsigned int)(unsigned long)&hwrpb; + + /* ??? For some reason GCC wants to use a LITERAL relocation for + _end instead of gp-relative relocations. */ + __asm ("ldah %0,_end($gp) !gprelhigh\n\tlda %0,_end(%0) !gprellow" + : "=r"(end)); + + pal_pages = ((unsigned int)end + PAGE_SIZE - 1) >> PAGE_SHIFT; + + hwrpb.mc[0].numpages = pal_pages; + hwrpb.mc[1].start_pfn = pal_pages; + hwrpb.mc[1].numpages = (memsize >> PAGE_SHIFT) - pal_pages; + + hwrpb_update_checksum (); +} + +static void +init_pcb (void) +{ + pal_pcb.ptbr = (unsigned int)(unsigned long)page_dir; + pal_pcb.flags = 1; +} + +static inline unsigned long +build_pte (void *page) +{ + unsigned long bits; + + bits = ((unsigned long)page - PAGE_OFFSET) << (32 - PAGE_SHIFT); + bits |= _PAGE_VALID; + + return bits; +} + +static inline void * +pte_page (unsigned long pte) +{ + return (void *)((pte >> 32 << PAGE_SHIFT) + PAGE_OFFSET); +} + +static void +set_pte (unsigned long addr, void *page) +{ + unsigned long *pt = page_dir; + unsigned long index; + + index = (addr >> (PAGE_SHIFT+20)) % 1024; + if (pt[index] != 0) + pt = pte_page (pt[index]); + else + __builtin_trap(); + + index = (addr >> (PAGE_SHIFT+10)) % 1024; + if (pt[index] != 0) + pt = pte_page (pt[index]); + else + __builtin_trap(); + + index = (addr >> PAGE_SHIFT) % 1024; + pt[index] = build_pte (page); +} + +static void +init_page_table (unsigned long memsize, unsigned long pal_pages) +{ + unsigned long i, addr, max_addr, page; + + page_dir[0] = build_pte (page_L1); + + for (i = 0; i < 1024; ++i) + page_L1[i] = build_pte (page_L2[i]); + + set_pte ((unsigned long)INIT_HWRPB, &hwrpb); + + addr = 0x20000000ul; + max_addr = 1ul << (PAGE_SHIFT + 20); + page = pal_pages << PAGE_SHIFT; + + while (addr < max_addr && page < memsize) + { + set_pte (addr, (void *)(PAGE_OFFSET + page)); + addr += PAGE_SIZE; + page += PAGE_SIZE; + } + + /* SRM places the self-map for the VPTBR in the second entry. */ + page_dir[1] = build_pte (page_dir); + + /* Write the SRM vptptr. */ + { + register unsigned long a0 __asm__("$16") = max_addr; + __asm ("call_pal 0x2d" : : "r"(a0)); + } +} + +void +do_start(unsigned long memsize) +{ + init_hwrpb (memsize); + init_pcb (); + init_page_table (memsize, hwrpb.mc[0].numpages); + + while (1) ; +} diff --git a/memset.c b/memset.c new file mode 100644 index 0000000..5f93dc3 --- /dev/null +++ b/memset.c @@ -0,0 +1,73 @@ +void *memset(void *optr, int ival, unsigned long size) +{ + unsigned long val = ival; + void *ptr = optr; + + if (__builtin_expect (size == 0, 0)) + return; + + if (__builtin_expect (val != 0, 0)) + { + val = val & 0xff; + val |= val << 8; + val |= val << 16; + val |= val << 32; + } + + if (__builtin_expect ((unsigned long)ptr & 1, 0)) + { + *(char *)ptr = val; + ptr += 1; + size -= 1; + } + + if (__builtin_expect ((unsigned long)ptr & 2, 0)) + { + if (size < 2) + goto tail_1; + *(short *)ptr = val; + ptr += 2; + size -= 2; + } + + if (__builtin_expect ((unsigned long)ptr & 4, 0)) + { + if (size < 4) + goto tail_3; + *(int *)ptr = val; + ptr += 4; + size -= 4; + } + + while (size >= 8) + { + *(long *)ptr = val; + ptr += 8; + size -= 8; + } + + if (size >= 4) + { + *(int *)ptr = val; + ptr += 4; + size -= 4; + } + + tail_3: + if (size >= 2) + { + *(short *)ptr = val; + ptr += 2; + size -= 2; + } + + tail_1: + if (size > 0) + { + *(char *)ptr = val; + ptr += 1; + size -= 1; + } + + return optr; +} diff --git a/palcode.ld b/palcode.ld new file mode 100644 index 0000000..a1304b5 --- /dev/null +++ b/palcode.ld @@ -0,0 +1,48 @@ +OUTPUT_FORMAT("elf64-alpha") +ENTRY(__start) + +SECTIONS +{ + . = 0xfffffc0000000000; + .text : { *(.text*) } + .rodata : { *(.rodata) } + .data ALIGN(8192) : { *(.data.hwrpb) *(.data*) } + .got : { *(.got.plt) *(.got) } + .sdata : { *(.sdata*) } + .sbss : { *(.sbss) *(.scommon) } + .bss : { *(.bss) *(COMMON) } + PROVIDE (_end = .); + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } + /DISCARD/ : { *(.eh_frame) } +} |