summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2011-04-06 16:02:23 -0700
committerRichard Henderson <rth@twiddle.net>2011-04-10 10:25:15 -0700
commit0ea286dc681fe3690fc4bb8007144190e03b8d51 (patch)
tree8f6462f8d6e270a7766e05392b7bee05caf0c28b
parente00c70db6ec09b5015ba5602a781d282134d3fcd (diff)
downloadqemu-palcode-0ea286dc681fe3690fc4bb8007144190e03b8d51.zip
qemu-palcode-0ea286dc681fe3690fc4bb8007144190e03b8d51.tar.gz
qemu-palcode-0ea286dc681fe3690fc4bb8007144190e03b8d51.tar.bz2
TEMP: finished through init_page_tables
-rw-r--r--.gitignore1
-rw-r--r--Makefile17
-rw-r--r--hwrpb.h220
-rw-r--r--init.c206
-rw-r--r--memset.c73
-rw-r--r--palcode.ld48
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
diff --git a/Makefile b/Makefile
index 7c2ac35..462046a 100644
--- a/Makefile
+++ b/Makefile
@@ -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 $@ $<
diff --git a/hwrpb.h b/hwrpb.h
new file mode 100644
index 0000000..8e8f871
--- /dev/null
+++ b/hwrpb.h
@@ -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 */
diff --git a/init.c b/init.c
new file mode 100644
index 0000000..70b6297
--- /dev/null
+++ b/init.c
@@ -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) }
+}