diff options
Diffstat (limited to 'arch/alpha/boot/main.c')
-rw-r--r-- | arch/alpha/boot/main.c | 142 |
1 files changed, 45 insertions, 97 deletions
diff --git a/arch/alpha/boot/main.c b/arch/alpha/boot/main.c index c2d4e657e..dd4e47ab5 100644 --- a/arch/alpha/boot/main.c +++ b/arch/alpha/boot/main.c @@ -22,61 +22,27 @@ extern int vsprintf(char *, const char *, va_list); extern unsigned long switch_to_osf_pal(unsigned long nr, struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa, - unsigned long vptb, unsigned long *kstk); - -int printk(const char * fmt, ...) -{ - va_list args; - int i, j, written, remaining, num_nl; - static char buf[1024]; - char * str; - - va_start(args, fmt); - i = vsprintf(buf, fmt, args); - va_end(args); - - /* expand \n into \r\n: */ - - num_nl = 0; - for (j = 0; j < i; ++j) { - if (buf[j] == '\n') - ++num_nl; - } - remaining = i + num_nl; - for (j = i - 1; j >= 0; --j) { - buf[j + num_nl] = buf[j]; - if (buf[j] == '\n') { - --num_nl; - buf[j + num_nl] = '\r'; - } - } - - str = buf; - do { - written = puts(str, remaining); - remaining -= written; - str += written; - } while (remaining > 0); - return i; -} - -#define hwrpb (*INIT_HWRPB) + unsigned long *vptb); +struct hwrpb_struct *hwrpb = INIT_HWRPB; +static struct pcb_struct pcb_va[1]; /* * Find a physical address of a virtual object.. * * This is easy using the virtual page table address. */ -struct pcb_struct * find_pa(unsigned long *vptb, struct pcb_struct * pcb) + +static inline void * +find_pa(unsigned long *vptb, void *ptr) { - unsigned long address = (unsigned long) pcb; + unsigned long address = (unsigned long) ptr; unsigned long result; result = vptb[address >> 13]; result >>= 32; result <<= 13; result |= address & 0x1fff; - return (struct pcb_struct *) result; + return (void *) result; } /* @@ -88,30 +54,19 @@ struct pcb_struct * find_pa(unsigned long *vptb, struct pcb_struct * pcb) * code has the L1 page table identity-map itself in the second PTE * in the L1 page table. Thus the L1-page is virtually addressable * itself (through three levels) at virtual address 0x200802000. - * - * As we don't want it there anyway, we also move the L1 self-map - * up as high as we can, so that the last entry in the L1 page table - * maps the page tables. - * - * As a result, the OSF/1 pal-code will instead use a virtual page table - * map located at 0xffffffe00000000. */ -#define pcb_va ((struct pcb_struct *) 0x20000000) -#define old_vptb (0x0000000200000000UL) -#define new_vptb (0xfffffffe00000000UL) -void pal_init(void) + +#define VPTB ((unsigned long *) 0x200000000) +#define L1 ((unsigned long *) 0x200802000) + +void +pal_init(void) { - unsigned long i, rev, sum; - unsigned long *L1, *l; + unsigned long i, rev; struct percpu_struct * percpu; struct pcb_struct * pcb_pa; - /* Find the level 1 page table and duplicate it in high memory */ - L1 = (unsigned long *) 0x200802000UL; /* (1<<33 | 1<<23 | 1<<13) */ - L1[1023] = L1[1]; - - percpu = (struct percpu_struct *) (hwrpb.processor_offset + (unsigned long) &hwrpb), - + /* Create the dummy PCB. */ pcb_va->ksp = 0; pcb_va->usp = 0; pcb_va->ptbr = L1[1] >> 32; @@ -119,39 +74,32 @@ void pal_init(void) pcb_va->pcc = 0; pcb_va->unique = 0; pcb_va->flags = 1; - pcb_pa = find_pa((unsigned long *) old_vptb, pcb_va); - printk("Switching to OSF PAL-code .. "); + pcb_va->res1 = 0; + pcb_va->res2 = 0; + pcb_pa = find_pa(VPTB, pcb_va); + /* * a0 = 2 (OSF) - * a1 = return address, but we give the asm the virtual addr of the PCB + * a1 = return address, but we give the asm the vaddr of the PCB * a2 = physical addr of PCB * a3 = new virtual page table pointer - * a4 = KSP (but we give it 0, asm sets it) + * a4 = KSP (but the asm sets it) */ - i = switch_to_osf_pal( - 2, - pcb_va, - pcb_pa, - new_vptb, - 0); + srm_printk("Switching to OSF PAL-code .. "); + + i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB); if (i) { - printk("failed, code %ld\n", i); + srm_printk("failed, code %ld\n", i); halt(); } - rev = percpu->pal_revision = percpu->palcode_avail[2]; - hwrpb.vptb = new_vptb; + percpu = (struct percpu_struct *) + (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB); + rev = percpu->pal_revision = percpu->palcode_avail[2]; - /* update checksum: */ - sum = 0; - for (l = (unsigned long *) &hwrpb; l < (unsigned long *) &hwrpb.chksum; ++l) - sum += *l; - hwrpb.chksum = sum; + srm_printk("Ok (rev %lx)\n", rev); - printk("Ok (rev %lx)\n", rev); - /* remove the old virtual page-table mapping */ - L1[1] = 0; - flush_tlb_all(); + tbia(); /* do it directly in case we are SMP */ } static inline long openboot(void) @@ -159,15 +107,15 @@ static inline long openboot(void) char bootdev[256]; long result; - result = dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255); + result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255); if (result < 0) return result; - return dispatch(CCB_OPEN, bootdev, result & 255); + return srm_dispatch(CCB_OPEN, bootdev, result & 255); } static inline long close(long dev) { - return dispatch(CCB_CLOSE, dev); + return srm_dispatch(CCB_CLOSE, dev); } static inline long load(long dev, unsigned long addr, unsigned long count) @@ -176,15 +124,15 @@ static inline long load(long dev, unsigned long addr, unsigned long count) extern char _end; long result, boot_size = &_end - (char *) BOOT_ADDR; - result = dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255); + result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255); if (result < 0) return result; result &= 255; bootfile[result] = '\0'; if (result) - printk("Boot file specification (%s) not implemented\n", + srm_printk("Boot file specification (%s) not implemented\n", bootfile); - return dispatch(CCB_READ, dev, count, addr, boot_size/512 + 1); + return srm_dispatch(CCB_READ, dev, count, addr, boot_size/512 + 1); } /* @@ -208,27 +156,27 @@ void start_kernel(void) int nbytes; char envval[256]; - printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n"); - if (hwrpb.pagesize != 8192) { - printk("Expected 8kB pages, got %ldkB\n", hwrpb.pagesize >> 10); + srm_printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n"); + if (INIT_HWRPB->pagesize != 8192) { + srm_printk("Expected 8kB pages, got %ldkB\n", INIT_HWRPB->pagesize >> 10); return; } pal_init(); dev = openboot(); if (dev < 0) { - printk("Unable to open boot device: %016lx\n", dev); + srm_printk("Unable to open boot device: %016lx\n", dev); return; } dev &= 0xffffffff; - printk("Loading vmlinux ..."); + srm_printk("Loading vmlinux ..."); i = load(dev, START_ADDR, KERNEL_SIZE); close(dev); if (i != KERNEL_SIZE) { - printk("Failed (%lx)\n", i); + srm_printk("Failed (%lx)\n", i); return; } - nbytes = dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS, + nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS, envval, sizeof(envval)); if (nbytes < 0) { nbytes = 0; @@ -236,7 +184,7 @@ void start_kernel(void) envval[nbytes] = '\0'; strcpy((char*)ZERO_PAGE, envval); - printk(" Ok\nNow booting the kernel\n"); + srm_printk(" Ok\nNow booting the kernel\n"); runkernel(); for (i = 0 ; i < 0x100000000 ; i++) /* nothing */; |