diff options
author | Robert Drehmel <robert@FreeBSD.org> | 2001-10-15 14:35:39 +0000 |
---|---|---|
committer | Robert Drehmel <robert@FreeBSD.org> | 2001-10-15 14:35:39 +0000 |
commit | 2727d8ffc8496a812dfb0e6574cec86fb6838de8 (patch) | |
tree | 6d7365c5ca56ef7446ac5b19d9c13cc25bcb4eda /sys/boot | |
parent | f048d52363e424542ec55dc13b78be85bf55a041 (diff) | |
download | src-2727d8ffc8496a812dfb0e6574cec86fb6838de8.tar.gz src-2727d8ffc8496a812dfb0e6574cec86fb6838de8.zip |
Add the FreeBSD/sparc64 boot loader source files.
Notes
Notes:
svn path=/head/; revision=84996
Diffstat (limited to 'sys/boot')
-rw-r--r-- | sys/boot/sparc64/loader/locore.S | 169 | ||||
-rw-r--r-- | sys/boot/sparc64/loader/locore.s | 169 | ||||
-rw-r--r-- | sys/boot/sparc64/loader/main.c | 320 |
3 files changed, 658 insertions, 0 deletions
diff --git a/sys/boot/sparc64/loader/locore.S b/sys/boot/sparc64/loader/locore.S new file mode 100644 index 000000000000..3a4eda216eeb --- /dev/null +++ b/sys/boot/sparc64/loader/locore.S @@ -0,0 +1,169 @@ +/* + * Initial implementation: + * Copyright (c) 2001 Robert Drehmel + * All rights reserved. + * + * As long as the above copyright statement and this notice remain + * unchanged, you can do what ever you want with this file. + * + * $FreeBSD$ + */ +#include <machine/asi.h> +#include <machine/pstate.h> +#include <machine/param.h> + +#define BIAS 2047 +#define CC64FSZ 192 +#define TLB_TAG_ACCESS 0x30 + + .text + .globl _start +_start: + setx ofw_entry, %l7, %l0 + stx %o4, [%l0] + + /* limit interrupts */ + wrpr %g0, 13, %pil + + /* + * PSTATE: privileged, interrupts enabled, floating point + * unit enabled + */ + wrpr %g0, PSTATE_PRIV|PSTATE_IE|PSTATE_PEF, %pstate + wr %o0, 0x4, %fprs + + setx stack, %l7, %sp + call main + nop + +/* + * %o0 kernel entry (VA) + * %o1 bootinfo structure pointer (VA) + * + * XXX Does the FreeBSD kernel expect the bootinfo pointer + * in %o0 or in %o1? + */ +.globl jmpkern +jmpkern: + setx ofw_entry, %l7, %o2 + jmp %o0 + ldx [%o2], %o2 + +/* + * %o0 input VA constant + * %o1 current iTLB offset + * %o2 current iTLB TTE tag + */ +.globl itlb_va_to_pa +itlb_va_to_pa: + clr %o1 +0: ldxa [%o1] ASI_ITLB_TAG_READ_REG, %o2 + cmp %o2, %o0 + bne,a %xcc, 1f + nop + /* return PA of matching entry */ + ldxa [%o1] ASI_ITLB_DATA_ACCESS_REG, %o0 + sllx %o0, 23, %o0 + srlx %o0, PAGE_SHIFT+23, %o0 + sllx %o0, PAGE_SHIFT, %o0 + retl + mov %o0, %o1 +1: cmp %o1, 63<<3 + blu %xcc, 0b + add %o1, 8, %o1 + clr %o0 + retl + not %o0 + +.globl dtlb_va_to_pa +dtlb_va_to_pa: + clr %o1 +0: ldxa [%o1] ASI_DTLB_TAG_READ_REG, %o2 + cmp %o2, %o0 + bne,a %xcc, 1f + nop + /* return PA of matching entry */ + ldxa [%o1] ASI_DTLB_DATA_ACCESS_REG, %o0 + sllx %o0, 23, %o0 + srlx %o0, PAGE_SHIFT+23, %o0 + sllx %o0, PAGE_SHIFT, %o0 + retl + mov %o0, %o1 +1: cmp %o1, 63<<3 + blu %xcc, 0b + add %o1, 8, %o1 + clr %o0 + retl + not %o0 + +/* + * %o0 = slot number + * %o1 = pa + * %o2 = va + * %o3 = flags + */ +.globl itlb_enter +itlb_enter: + sllx %o0, 3, %o0 + or %o1, %o3, %o1 + mov TLB_TAG_ACCESS, %o3 + stxa %o2, [%o3] ASI_IMMU + membar #Sync + stxa %o1, [%o0] ASI_ITLB_DATA_ACCESS_REG + retl + nop + +.globl dtlb_enter +dtlb_enter: + sllx %o0, 3, %o0 + or %o1, %o3, %o1 + mov TLB_TAG_ACCESS, %o3 + stxa %o2, [%o3] ASI_DMMU + membar #Sync + stxa %o1, [%o0] ASI_DTLB_DATA_ACCESS_REG + retl + nop + +.globl ofw_gate +ofw_gate: + save %sp, -CC64FSZ, %sp + setx ofw_entry, %i3, %i4 + ldx [%i4], %i4 + + mov %g1, %l1 + mov %g2, %l2 + mov %g3, %l3 + mov %g4, %l4 + mov %g5, %l5 + mov %g6, %l6 + mov %g7, %l7 + + rdpr %pstate, %i3 + wrpr %g0, PSTATE_PRIV, %pstate + + jmpl %i4, %o7 + mov %i0, %o0 + mov %o0, %i0 + + wrpr %i3, 0, %pstate + + mov %l1, %g1 + mov %l2, %g2 + mov %l3, %g3 + mov %l4, %g4 + mov %l5, %g5 + mov %l6, %g6 + mov %l7, %g7 + + ret + restore + + .data + .align 8 +ofw_entry: .xword 0 + + .align 32 + .space 0x4000 + .set stack, _stack-BIAS +_stack: + .space 0x10000 diff --git a/sys/boot/sparc64/loader/locore.s b/sys/boot/sparc64/loader/locore.s new file mode 100644 index 000000000000..3a4eda216eeb --- /dev/null +++ b/sys/boot/sparc64/loader/locore.s @@ -0,0 +1,169 @@ +/* + * Initial implementation: + * Copyright (c) 2001 Robert Drehmel + * All rights reserved. + * + * As long as the above copyright statement and this notice remain + * unchanged, you can do what ever you want with this file. + * + * $FreeBSD$ + */ +#include <machine/asi.h> +#include <machine/pstate.h> +#include <machine/param.h> + +#define BIAS 2047 +#define CC64FSZ 192 +#define TLB_TAG_ACCESS 0x30 + + .text + .globl _start +_start: + setx ofw_entry, %l7, %l0 + stx %o4, [%l0] + + /* limit interrupts */ + wrpr %g0, 13, %pil + + /* + * PSTATE: privileged, interrupts enabled, floating point + * unit enabled + */ + wrpr %g0, PSTATE_PRIV|PSTATE_IE|PSTATE_PEF, %pstate + wr %o0, 0x4, %fprs + + setx stack, %l7, %sp + call main + nop + +/* + * %o0 kernel entry (VA) + * %o1 bootinfo structure pointer (VA) + * + * XXX Does the FreeBSD kernel expect the bootinfo pointer + * in %o0 or in %o1? + */ +.globl jmpkern +jmpkern: + setx ofw_entry, %l7, %o2 + jmp %o0 + ldx [%o2], %o2 + +/* + * %o0 input VA constant + * %o1 current iTLB offset + * %o2 current iTLB TTE tag + */ +.globl itlb_va_to_pa +itlb_va_to_pa: + clr %o1 +0: ldxa [%o1] ASI_ITLB_TAG_READ_REG, %o2 + cmp %o2, %o0 + bne,a %xcc, 1f + nop + /* return PA of matching entry */ + ldxa [%o1] ASI_ITLB_DATA_ACCESS_REG, %o0 + sllx %o0, 23, %o0 + srlx %o0, PAGE_SHIFT+23, %o0 + sllx %o0, PAGE_SHIFT, %o0 + retl + mov %o0, %o1 +1: cmp %o1, 63<<3 + blu %xcc, 0b + add %o1, 8, %o1 + clr %o0 + retl + not %o0 + +.globl dtlb_va_to_pa +dtlb_va_to_pa: + clr %o1 +0: ldxa [%o1] ASI_DTLB_TAG_READ_REG, %o2 + cmp %o2, %o0 + bne,a %xcc, 1f + nop + /* return PA of matching entry */ + ldxa [%o1] ASI_DTLB_DATA_ACCESS_REG, %o0 + sllx %o0, 23, %o0 + srlx %o0, PAGE_SHIFT+23, %o0 + sllx %o0, PAGE_SHIFT, %o0 + retl + mov %o0, %o1 +1: cmp %o1, 63<<3 + blu %xcc, 0b + add %o1, 8, %o1 + clr %o0 + retl + not %o0 + +/* + * %o0 = slot number + * %o1 = pa + * %o2 = va + * %o3 = flags + */ +.globl itlb_enter +itlb_enter: + sllx %o0, 3, %o0 + or %o1, %o3, %o1 + mov TLB_TAG_ACCESS, %o3 + stxa %o2, [%o3] ASI_IMMU + membar #Sync + stxa %o1, [%o0] ASI_ITLB_DATA_ACCESS_REG + retl + nop + +.globl dtlb_enter +dtlb_enter: + sllx %o0, 3, %o0 + or %o1, %o3, %o1 + mov TLB_TAG_ACCESS, %o3 + stxa %o2, [%o3] ASI_DMMU + membar #Sync + stxa %o1, [%o0] ASI_DTLB_DATA_ACCESS_REG + retl + nop + +.globl ofw_gate +ofw_gate: + save %sp, -CC64FSZ, %sp + setx ofw_entry, %i3, %i4 + ldx [%i4], %i4 + + mov %g1, %l1 + mov %g2, %l2 + mov %g3, %l3 + mov %g4, %l4 + mov %g5, %l5 + mov %g6, %l6 + mov %g7, %l7 + + rdpr %pstate, %i3 + wrpr %g0, PSTATE_PRIV, %pstate + + jmpl %i4, %o7 + mov %i0, %o0 + mov %o0, %i0 + + wrpr %i3, 0, %pstate + + mov %l1, %g1 + mov %l2, %g2 + mov %l3, %g3 + mov %l4, %g4 + mov %l5, %g5 + mov %l6, %g6 + mov %l7, %g7 + + ret + restore + + .data + .align 8 +ofw_entry: .xword 0 + + .align 32 + .space 0x4000 + .set stack, _stack-BIAS +_stack: + .space 0x10000 diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c new file mode 100644 index 000000000000..b00209d2dd9a --- /dev/null +++ b/sys/boot/sparc64/loader/main.c @@ -0,0 +1,320 @@ +/* + * Initial implementation: + * Copyright (c) 2001 Robert Drehmel + * All rights reserved. + * + * As long as the above copyright statement and this notice remain + * unchanged, you can do what ever you want with this file. + * + * $FreeBSD$ + */ +/* + * FreeBSD/sparc64 kernel loader - machine dependent part + * + * - implements copyin and readin functions that map kernel + * pages on demand. The machine independent code does not + * know the size of the kernel early enough to pre-enter + * TTEs and install just one 4MB mapping seemed to limiting + * to me. + */ +#include <stand.h> +#include <sys/exec.h> +#include <sys/param.h> +#include <sys/linker.h> + +#include <machine/asi.h> +#include <machine/bootinfo.h> +#include <machine/elf.h> +#include <machine/tte.h> + +#include "bootstrap.h" +#include "libofw.h" + +enum { + HEAPVA = 0x800000, + HEAPSZ = 0x1000000, + LOADSZ = 0x1000000 /* for kernel and modules */ +}; + +struct memory_slice { + vm_offset_t pstart; + vm_offset_t size; +}; + +extern int ofw_gate(void *); +extern void itlb_enter(int, vm_offset_t, vm_offset_t, unsigned long); +extern void dtlb_enter(int, vm_offset_t, vm_offset_t, unsigned long); +extern vm_offset_t itlb_va_to_pa(vm_offset_t); +extern vm_offset_t dtlb_va_to_pa(vm_offset_t); +extern void jmpkern(vm_offset_t, struct bootinfo *); +static int elf_exec(struct preloaded_file *); +static int sparc64_autoload(void); +static int mmu_mapin(vm_offset_t, vm_size_t); + +char __progname[] = "FreeBSD/sparc64 loader"; + +vm_offset_t kernelpa; /* Begin of kernel and mod memory. */ +vm_offset_t curkpg; /* (PA) used for on-demand map-in. */ +vm_offset_t curkva = 0; +vm_offset_t heapva; +int tlbslot = 60; /* Insert first entry at this TLB slot. */ +phandle_t pmemh; /* OFW memory handle */ + +struct memory_slice memslices[18]; +struct ofw_devdesc bootdev; + +/* + * Machine dependent structures that the machine independent + * loader part uses. + */ +struct devsw *devsw[] = { + &ofwdisk, + 0 +}; +struct arch_switch archsw; + +struct file_format sparc64_elf = { + elf_loadfile, + elf_exec +}; +struct file_format *file_formats[] = { + &sparc64_elf, + 0 +}; +struct fs_ops *file_system[] = { + &ufs_fsops, + 0 +}; + +extern struct console ofwconsole; +struct console *consoles[] = { + &ofwconsole, + 0 +}; + +/* + * archsw functions + */ +static int +sparc64_autoload(void) +{ + printf("nothing to autoload yet.\n"); + return 0; +} + +static ssize_t +sparc64_readin(const int fd, vm_offset_t va, const size_t len) +{ + mmu_mapin(va, len); + return read(fd, (void *)va, len); +} + +static ssize_t +sparc64_copyin(const void *src, vm_offset_t dest, size_t len) +{ + mmu_mapin(dest, len); + memcpy((void *)dest, src, len); + return len; +} + +/* + * other MD functions + */ +static int +elf_exec(struct preloaded_file *fp) +{ + struct file_metadata *fmp; + struct bootinfo bi, *bip; + Elf_Ehdr *Ehdr; + vm_offset_t entry; + + if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == 0) { + return EFTYPE; + } + Ehdr = (Elf_Ehdr *)&fmp->md_data; + entry = Ehdr->e_entry; + + /* align the bootinfo structure on an eight byte boundary */ + bip = (struct bootinfo *)(curkva + 8 & 0x7); + + bi.bi_version = BOOTINFO_VERSION; + bi.bi_kpa = kernelpa; + bi.bi_end = (vm_offset_t)(bip + 1); + bi.bi_metadata = 0; + sparc64_copyin(&bi, bip, sizeof(struct bootinfo)); + + printf("jumping to kernel entry at 0x%lx.\n", entry); +#if 0 + pmap_print_tlb('i'); + pmap_print_tlb('d'); +#endif + jmpkern(entry, bip); + return 1; +} + +static int +mmu_mapin(vm_offset_t va, vm_size_t len) +{ + printf("mmu_mapin(): access to 0x%lx-0x%lx requested\n", va, va + len); + + if (va + len > curkva) + curkva = va + len; + + len += va & 0x3fffff; + va &= ~0x3fffff; + while (len) { + if (dtlb_va_to_pa(va) == (vm_offset_t)-1 || + itlb_va_to_pa(va) == (vm_offset_t)-1) { + printf("mmu_mapin(): map pa 0x%lx as va 0x%lx.\n", + curkpg, va); + dtlb_enter(tlbslot, curkpg, va, + TD_V | TD_4M | TD_L | TD_CP | TD_CV | TD_P | TD_W); + itlb_enter(tlbslot, curkpg, va, + TD_V | TD_4M | TD_L | TD_CP | TD_CV | TD_P | TD_W); + tlbslot--; + curkpg += 0x400000; + } + len -= len > 0x400000 ? 0x400000 : len; + va += 0x400000; + } + return 0; +} + +static vm_offset_t +init_heap(void) +{ + if ((pmemh = OF_finddevice("/memory")) == (phandle_t)-1) + OF_exit(); + if (OF_getprop(pmemh, "reg", memslices, sizeof(memslices)) <= 0) + OF_exit(); + + /* Reserve 16 MB continuous for kernel and modules. */ + kernelpa = (vm_offset_t)OF_alloc_phys(LOADSZ, 0x400000); + curkpg = kernelpa; + /* There is no need for continuous physical heap memory. */ + heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32); + return heapva; +} + +int main(int (*openfirm)(void *)) +{ + char bootpath[64]; + struct devsw **dp; + phandle_t chosenh; + + /* + * Tell the OpenFirmware functions where they find the ofw gate. + */ + OF_init(&ofw_gate); + + archsw.arch_getdev = ofw_getdev; + archsw.arch_copyin = sparc64_copyin; + archsw.arch_copyout = ofw_copyout; + archsw.arch_readin = sparc64_readin; + archsw.arch_autoload = sparc64_autoload; + + init_heap(); + setheap((void *)heapva, (void *)(heapva + HEAPSZ)); + + /* + * Probe for a console. + */ + cons_probe(); + + bcache_init(32, 512); + + /* + * Initialize devices. + */ + for (dp = devsw; *dp != 0; dp++) { + if ((*dp)->dv_init != 0) + (*dp)->dv_init(); + } + + /* + * Set up the current device. + */ + chosenh = OF_finddevice("/chosen"); + OF_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); + + bootdev.d_type = ofw_devicetype(bootpath); + switch (bootdev.d_type) { + case DEVT_DISK: + bootdev.d_dev = &ofwdisk; + strncpy(bootdev.d_kind.ofwdisk.path, bootpath, 64); + ofw_parseofwdev(&bootdev, bootpath); + break; + case DEVT_NET: + //bootdev.d_dev = &netdev; + strncpy(bootdev.d_kind.netif.path, bootpath, 64); + bootdev.d_kind.netif.unit = 0; + break; + } + + env_setenv("currdev", EV_VOLATILE, ofw_fmtdev(&bootdev), + ofw_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, ofw_fmtdev(&bootdev), + env_noset, env_nounset); + + printf("%s\n", __progname); + printf("bootpath=\"%s\"\n", bootpath); + printf("loaddev=%s\n", getenv("loaddev")); + printf("kernelpa=0x%x\n", curkpg); + + /* Give control to the machine independent loader code. */ + interact(); + return 1; +} + +typedef u_int64_t tte_t; + +const char *page_sizes[] = { + " 8k", " 64k", "512k", " 4m" +}; + +static void +pmap_print_tte(tte_t tag, tte_t tte) +{ + printf("%s %s ", + page_sizes[(tte & TD_SIZE_MASK) >> TD_SIZE_SHIFT], + tag & TD_G ? "G" : " "); + printf(tte & TD_W ? "W " : " "); + printf(tte & TD_P ? "\e[33mP\e[0m " : " "); + printf(tte & TD_E ? "E " : " "); + printf(tte & TD_CV ? "CV " : " "); + printf(tte & TD_CP ? "CP " : " "); + printf(tte & TD_L ? "\e[32mL\e[0m " : " "); + printf(tte & TD_IE ? "IE " : " "); + printf(tte & TD_NFO ? "NFO " : " "); + printf("tag=0x%lx pa=0x%lx va=0x%lx ctx=%d\n", tag, TD_PA(tte), + TT_VA(tag), TT_CTX(tag)); +} +void +pmap_print_tlb(char which) +{ + int i; + tte_t tte, tag; + + for (i = 0; i < 64*8; i += 8) { + if (which == 'i') { + __asm__ __volatile__("ldxa [%1] %2, %0\n" : + "=r" (tag) : "r" (i), + "i" (ASI_ITLB_TAG_READ_REG)); + __asm__ __volatile__("ldxa [%1] %2, %0\n" : + "=r" (tte) : "r" (i), + "i" (ASI_ITLB_DATA_ACCESS_REG)); + } + else { + __asm__ __volatile__("ldxa [%1] %2, %0\n" : + "=r" (tag) : "r" (i), + "i" (ASI_DTLB_TAG_READ_REG)); + __asm__ __volatile__("ldxa [%1] %2, %0\n" : + "=r" (tte) : "r" (i), + "i" (ASI_DTLB_DATA_ACCESS_REG)); + } + if (!(tte & TD_V)) + continue; + printf("%cTLB-%2u: ", which, i>>3); + pmap_print_tte(tag, tte); + } +} |