mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
initial sparc64 version
git-svn-id: svn://coreboot.org/openbios/openbios-devel@58 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
@@ -6,4 +6,5 @@
|
||||
<include href="ia64/build.xml"/>
|
||||
<include href="unix/build.xml"/>
|
||||
<include href="sparc32/build.xml"/>
|
||||
<include href="sparc64/build.xml"/>
|
||||
</build>
|
||||
|
||||
145
arch/sparc64/asi.h
Normal file
145
arch/sparc64/asi.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/* $Id: asi.h,v 1.5 2001/03/29 11:47:47 davem Exp $ */
|
||||
#ifndef _SPARC64_ASI_H
|
||||
#define _SPARC64_ASI_H
|
||||
|
||||
/* asi.h: Address Space Identifier values for the V9.
|
||||
*
|
||||
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
|
||||
/* V9 Architecture mandary ASIs. */
|
||||
#define ASI_N 0x04 /* Nucleus */
|
||||
#define ASI_NL 0x0c /* Nucleus, little endian */
|
||||
#define ASI_AIUP 0x10 /* Primary, user */
|
||||
#define ASI_AIUS 0x11 /* Secondary, user */
|
||||
#define ASI_AIUPL 0x18 /* Primary, user, little endian */
|
||||
#define ASI_AIUSL 0x19 /* Secondary, user, little endian */
|
||||
#define ASI_P 0x80 /* Primary, implicit */
|
||||
#define ASI_S 0x81 /* Secondary, implicit */
|
||||
#define ASI_PNF 0x82 /* Primary, no fault */
|
||||
#define ASI_SNF 0x83 /* Secondary, no fault */
|
||||
#define ASI_PL 0x88 /* Primary, implicit, l-endian */
|
||||
#define ASI_SL 0x89 /* Secondary, implicit, l-endian */
|
||||
#define ASI_PNFL 0x8a /* Primary, no fault, l-endian */
|
||||
#define ASI_SNFL 0x8b /* Secondary, no fault, l-endian */
|
||||
|
||||
/* SpitFire and later extended ASIs. The "(III)" marker designates
|
||||
* UltraSparc-III and later specific ASIs. The "(CMT)" marker designates
|
||||
* Chip Multi Threading specific ASIs.
|
||||
*/
|
||||
#define ASI_PHYS_USE_EC 0x14 /* PADDR, E-cachable */
|
||||
#define ASI_PHYS_BYPASS_EC_E 0x15 /* PADDR, E-bit */
|
||||
#define ASI_PHYS_USE_EC_L 0x1c /* PADDR, E-cachable, little endian*/
|
||||
#define ASI_PHYS_BYPASS_EC_E_L 0x1d /* PADDR, E-bit, little endian */
|
||||
#define ASI_NUCLEUS_QUAD_LDD 0x24 /* Cachable, qword load */
|
||||
#define ASI_NUCLEUS_QUAD_LDD_L 0x2c /* Cachable, qword load, l-endian */
|
||||
#define ASI_PCACHE_DATA_STATUS 0x30 /* (III) PCache data stat RAM diag */
|
||||
#define ASI_PCACHE_DATA 0x31 /* (III) PCache data RAM diag */
|
||||
#define ASI_PCACHE_TAG 0x32 /* (III) PCache tag RAM diag */
|
||||
#define ASI_PCACHE_SNOOP_TAG 0x33 /* (III) PCache snoop tag RAM diag */
|
||||
#define ASI_QUAD_LDD_PHYS 0x34 /* (III+) PADDR, qword load */
|
||||
#define ASI_WCACHE_VALID_BITS 0x38 /* (III) WCache Valid Bits diag */
|
||||
#define ASI_WCACHE_DATA 0x39 /* (III) WCache data RAM diag */
|
||||
#define ASI_WCACHE_TAG 0x3a /* (III) WCache tag RAM diag */
|
||||
#define ASI_WCACHE_SNOOP_TAG 0x3b /* (III) WCache snoop tag RAM diag */
|
||||
#define ASI_QUAD_LDD_PHYS_L 0x3c /* (III+) PADDR, qw-load, l-endian */
|
||||
#define ASI_SRAM_FAST_INIT 0x40 /* (III+) Fast SRAM init */
|
||||
#define ASI_CORE_AVAILABLE 0x41 /* (CMT) LP Available */
|
||||
#define ASI_CORE_ENABLE_STAT 0x41 /* (CMT) LP Enable Status */
|
||||
#define ASI_CORE_ENABLE 0x41 /* (CMT) LP Enable RW */
|
||||
#define ASI_XIR_STEERING 0x41 /* (CMT) XIR Steering RW */
|
||||
#define ASI_CORE_RUNNING_RW 0x41 /* (CMT) LP Running RW */
|
||||
#define ASI_CORE_RUNNING_W1S 0x41 /* (CMT) LP Running Write-One Set */
|
||||
#define ASI_CORE_RUNNING_W1C 0x41 /* (CMT) LP Running Write-One Clr */
|
||||
#define ASI_CORE_RUNNING_STAT 0x41 /* (CMT) LP Running Status */
|
||||
#define ASI_CMT_ERROR_STEERING 0x41 /* (CMT) Error Steering RW */
|
||||
#define ASI_DCACHE_INVALIDATE 0x42 /* (III) DCache Invalidate diag */
|
||||
#define ASI_DCACHE_UTAG 0x43 /* (III) DCache uTag diag */
|
||||
#define ASI_DCACHE_SNOOP_TAG 0x44 /* (III) DCache snoop tag RAM diag */
|
||||
#define ASI_LSU_CONTROL 0x45 /* Load-store control unit */
|
||||
#define ASI_DCU_CONTROL_REG 0x45 /* (III) DCache Unit Control reg */
|
||||
#define ASI_DCACHE_DATA 0x46 /* DCache data-ram diag access */
|
||||
#define ASI_DCACHE_TAG 0x47 /* Dcache tag/valid ram diag access*/
|
||||
#define ASI_INTR_DISPATCH_STAT 0x48 /* IRQ vector dispatch status */
|
||||
#define ASI_INTR_RECEIVE 0x49 /* IRQ vector receive status */
|
||||
#define ASI_UPA_CONFIG 0x4a /* UPA config space */
|
||||
#define ASI_JBUS_CONFIG 0x4a /* (IIIi) JBUS Config Register */
|
||||
#define ASI_SAFARI_CONFIG 0x4a /* (III) Safari Config Register */
|
||||
#define ASI_SAFARI_ADDRESS 0x4a /* (III) Safari Address Register */
|
||||
#define ASI_ESTATE_ERROR_EN 0x4b /* E-cache error enable space */
|
||||
#define ASI_AFSR 0x4c /* Async fault status register */
|
||||
#define ASI_AFAR 0x4d /* Async fault address register */
|
||||
#define ASI_EC_TAG_DATA 0x4e /* E-cache tag/valid ram diag acc */
|
||||
#define ASI_IMMU 0x50 /* Insn-MMU main register space */
|
||||
#define ASI_IMMU_TSB_8KB_PTR 0x51 /* Insn-MMU 8KB TSB pointer reg */
|
||||
#define ASI_IMMU_TSB_64KB_PTR 0x52 /* Insn-MMU 64KB TSB pointer reg */
|
||||
#define ASI_ITLB_DATA_IN 0x54 /* Insn-MMU TLB data in reg */
|
||||
#define ASI_ITLB_DATA_ACCESS 0x55 /* Insn-MMU TLB data access reg */
|
||||
#define ASI_ITLB_TAG_READ 0x56 /* Insn-MMU TLB tag read reg */
|
||||
#define ASI_IMMU_DEMAP 0x57 /* Insn-MMU TLB demap */
|
||||
#define ASI_DMMU 0x58 /* Data-MMU main register space */
|
||||
#define ASI_DMMU_TSB_8KB_PTR 0x59 /* Data-MMU 8KB TSB pointer reg */
|
||||
#define ASI_DMMU_TSB_64KB_PTR 0x5a /* Data-MMU 16KB TSB pointer reg */
|
||||
#define ASI_DMMU_TSB_DIRECT_PTR 0x5b /* Data-MMU TSB direct pointer reg */
|
||||
#define ASI_DTLB_DATA_IN 0x5c /* Data-MMU TLB data in reg */
|
||||
#define ASI_DTLB_DATA_ACCESS 0x5d /* Data-MMU TLB data access reg */
|
||||
#define ASI_DTLB_TAG_READ 0x5e /* Data-MMU TLB tag read reg */
|
||||
#define ASI_DMMU_DEMAP 0x5f /* Data-MMU TLB demap */
|
||||
#define ASI_IIU_INST_TRAP 0x60 /* (III) Instruction Breakpoint */
|
||||
#define ASI_INTR_ID 0x63 /* (CMT) Interrupt ID register */
|
||||
#define ASI_CORE_ID 0x63 /* (CMT) LP ID register */
|
||||
#define ASI_CESR_ID 0x63 /* (CMT) CESR ID register */
|
||||
#define ASI_IC_INSTR 0x66 /* Insn cache instrucion ram diag */
|
||||
#define ASI_IC_TAG 0x67 /* Insn cache tag/valid ram diag */
|
||||
#define ASI_IC_STAG 0x68 /* (III) Insn cache snoop tag ram */
|
||||
#define ASI_IC_PRE_DECODE 0x6e /* Insn cache pre-decode ram diag */
|
||||
#define ASI_IC_NEXT_FIELD 0x6f /* Insn cache next-field ram diag */
|
||||
#define ASI_BRPRED_ARRAY 0x6f /* (III) Branch Prediction RAM diag*/
|
||||
#define ASI_BLK_AIUP 0x70 /* Primary, user, block load/store */
|
||||
#define ASI_BLK_AIUS 0x71 /* Secondary, user, block ld/st */
|
||||
#define ASI_MCU_CTRL_REG 0x72 /* (III) Memory controller regs */
|
||||
#define ASI_EC_DATA 0x74 /* (III) E-cache data staging reg */
|
||||
#define ASI_EC_CTRL 0x75 /* (III) E-cache control reg */
|
||||
#define ASI_EC_W 0x76 /* E-cache diag write access */
|
||||
#define ASI_UDB_ERROR_W 0x77 /* External UDB error regs W */
|
||||
#define ASI_UDB_CONTROL_W 0x77 /* External UDB control regs W */
|
||||
#define ASI_INTR_W 0x77 /* IRQ vector dispatch write */
|
||||
#define ASI_INTR_DATAN_W 0x77 /* (III) Out irq vector data reg N */
|
||||
#define ASI_INTR_DISPATCH_W 0x77 /* (III) Interrupt vector dispatch */
|
||||
#define ASI_BLK_AIUPL 0x78 /* Primary, user, little, blk ld/st*/
|
||||
#define ASI_BLK_AIUSL 0x79 /* Secondary, user, little, blk ld/st*/
|
||||
#define ASI_EC_R 0x7e /* E-cache diag read access */
|
||||
#define ASI_UDBH_ERROR_R 0x7f /* External UDB error regs rd hi */
|
||||
#define ASI_UDBL_ERROR_R 0x7f /* External UDB error regs rd low */
|
||||
#define ASI_UDBH_CONTROL_R 0x7f /* External UDB control regs rd hi */
|
||||
#define ASI_UDBL_CONTROL_R 0x7f /* External UDB control regs rd low*/
|
||||
#define ASI_INTR_R 0x7f /* IRQ vector dispatch read */
|
||||
#define ASI_INTR_DATAN_R 0x7f /* (III) In irq vector data reg N */
|
||||
#define ASI_PST8_P 0xc0 /* Primary, 8 8-bit, partial */
|
||||
#define ASI_PST8_S 0xc1 /* Secondary, 8 8-bit, partial */
|
||||
#define ASI_PST16_P 0xc2 /* Primary, 4 16-bit, partial */
|
||||
#define ASI_PST16_S 0xc3 /* Secondary, 4 16-bit, partial */
|
||||
#define ASI_PST32_P 0xc4 /* Primary, 2 32-bit, partial */
|
||||
#define ASI_PST32_S 0xc5 /* Secondary, 2 32-bit, partial */
|
||||
#define ASI_PST8_PL 0xc8 /* Primary, 8 8-bit, partial, L */
|
||||
#define ASI_PST8_SL 0xc9 /* Secondary, 8 8-bit, partial, L */
|
||||
#define ASI_PST16_PL 0xca /* Primary, 4 16-bit, partial, L */
|
||||
#define ASI_PST16_SL 0xcb /* Secondary, 4 16-bit, partial, L */
|
||||
#define ASI_PST32_PL 0xcc /* Primary, 2 32-bit, partial, L */
|
||||
#define ASI_PST32_SL 0xcd /* Secondary, 2 32-bit, partial, L */
|
||||
#define ASI_FL8_P 0xd0 /* Primary, 1 8-bit, fpu ld/st */
|
||||
#define ASI_FL8_S 0xd1 /* Secondary, 1 8-bit, fpu ld/st */
|
||||
#define ASI_FL16_P 0xd2 /* Primary, 1 16-bit, fpu ld/st */
|
||||
#define ASI_FL16_S 0xd3 /* Secondary, 1 16-bit, fpu ld/st */
|
||||
#define ASI_FL8_PL 0xd8 /* Primary, 1 8-bit, fpu ld/st, L */
|
||||
#define ASI_FL8_SL 0xd9 /* Secondary, 1 8-bit, fpu ld/st, L*/
|
||||
#define ASI_FL16_PL 0xda /* Primary, 1 16-bit, fpu ld/st, L */
|
||||
#define ASI_FL16_SL 0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/
|
||||
#define ASI_BLK_COMMIT_P 0xe0 /* Primary, blk store commit */
|
||||
#define ASI_BLK_COMMIT_S 0xe1 /* Secondary, blk store commit */
|
||||
#define ASI_BLK_P 0xf0 /* Primary, blk ld/st */
|
||||
#define ASI_BLK_S 0xf1 /* Secondary, blk ld/st */
|
||||
#define ASI_BLK_PL 0xf8 /* Primary, blk ld/st, little */
|
||||
#define ASI_BLK_SL 0xf9 /* Secondary, blk ld/st, little */
|
||||
|
||||
#endif /* _SPARC64_ASI_H */
|
||||
82
arch/sparc64/boot.c
Normal file
82
arch/sparc64/boot.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
#undef BOOTSTRAP
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/bindings.h"
|
||||
#include "openbios/elfload.h"
|
||||
#include "openbios/nvram.h"
|
||||
#include "libc/diskio.h"
|
||||
#include "sys_info.h"
|
||||
|
||||
int elf_load(struct sys_info *, const char *filename, const char *cmdline);
|
||||
int aout_load(struct sys_info *, const char *filename, const char *cmdline);
|
||||
int linux_load(struct sys_info *, const char *filename, const char *cmdline);
|
||||
|
||||
void boot(void);
|
||||
|
||||
struct sys_info sys_info;
|
||||
uint32_t kernel_image;
|
||||
uint32_t kernel_size;
|
||||
uint32_t cmdline;
|
||||
uint32_t cmdline_size;
|
||||
char boot_device;
|
||||
|
||||
void boot(void)
|
||||
{
|
||||
char *path=pop_fstr_copy(), *param;
|
||||
char altpath[256];
|
||||
|
||||
if (kernel_size) {
|
||||
int (*entry)(const void *romvec, int p2, int p3, int p4, int p5);
|
||||
|
||||
printk("[sparc64] Kernel already loaded\n");
|
||||
entry = (void *) kernel_image;
|
||||
entry(0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if(!path) {
|
||||
switch(boot_device) {
|
||||
case 'a':
|
||||
path = "/obio/SUNW,fdtwo";
|
||||
break;
|
||||
case 'c':
|
||||
path = "disk";
|
||||
break;
|
||||
default:
|
||||
case 'd':
|
||||
path = "cdrom";
|
||||
break;
|
||||
case 'n':
|
||||
path = "net";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
param = strchr(path, ' ');
|
||||
if(param) {
|
||||
*param = '\0';
|
||||
param++;
|
||||
} else if (cmdline_size) {
|
||||
param = (char *)cmdline;
|
||||
}
|
||||
|
||||
printk("[sparc64] Booting file '%s' ", path);
|
||||
if(param)
|
||||
printk("with parameters '%s'\n", param);
|
||||
else
|
||||
printk("without parameters.\n");
|
||||
|
||||
|
||||
if (elf_load(&sys_info, path, param) == LOADER_NOT_SUPPORT)
|
||||
if (linux_load(&sys_info, path, param) == LOADER_NOT_SUPPORT) {
|
||||
|
||||
sprintf(altpath, "%s:d", path);
|
||||
|
||||
if (elf_load(&sys_info, altpath, param) == LOADER_NOT_SUPPORT)
|
||||
if (linux_load(&sys_info, altpath, param) == LOADER_NOT_SUPPORT)
|
||||
printk("Unsupported image format\n");
|
||||
}
|
||||
|
||||
free(path);
|
||||
}
|
||||
14
arch/sparc64/boot.h
Normal file
14
arch/sparc64/boot.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/* tag: openbios loader prototypes for sparc64
|
||||
*
|
||||
* Copyright (C) 2004 Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
int forth_load(struct sys_info *info, const char *filename, const char *cmdline);
|
||||
int elf_load(struct sys_info *info, const char *filename, const char *cmdline);
|
||||
int linux_load(struct sys_info *info, const char *file, const char *cmdline);
|
||||
|
||||
unsigned int start_elf(unsigned long entry_point, unsigned long param);
|
||||
|
||||
108
arch/sparc64/build.xml
Normal file
108
arch/sparc64/build.xml
Normal file
@@ -0,0 +1,108 @@
|
||||
<build condition="SPARC64">
|
||||
|
||||
<dictionary name="openbios-sparc64" init="openbios">
|
||||
<object source="tree.fs" target="forth"/>
|
||||
<object source="init.fs" target="forth"/>
|
||||
</dictionary>
|
||||
|
||||
<library name="sparc64" type="static" target="target">
|
||||
<object source="openbios.c"/>
|
||||
<object source="console.c"/>
|
||||
<object source="lib.c"/>
|
||||
<object source="boot.c"/>
|
||||
<object source="context.c"/>
|
||||
<object source="switch.S"/>
|
||||
<object source="linux_load.c"/>
|
||||
<object source="sys_info.c"/>
|
||||
<object source="elfload.c"/>
|
||||
<object source="forthload.c"/>
|
||||
<object source="loadfs.c"/>
|
||||
</library>
|
||||
|
||||
<executable name="target/arch/sparc64/entry.o" target="target">
|
||||
<rule><![CDATA[
|
||||
$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ arch/sparc64/entry.S
|
||||
]]></rule>
|
||||
</executable>
|
||||
<executable name="target/arch/sparc64/vectors.o" target="target">
|
||||
<rule><![CDATA[
|
||||
$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ arch/sparc64/vectors.S
|
||||
]]></rule>
|
||||
</executable>
|
||||
|
||||
<executable name="openbios.multiboot" target="target" condition="IMAGE_ELF_MULTIBOOT">
|
||||
<rule>
|
||||
$(LD) -T arch/sparc64/ldscript -o $@.nostrip $^
|
||||
$(NM) $@.nostrip | sort > $(ODIR)/openbios-multiboot.syms
|
||||
cp $@.nostrip $@
|
||||
$(STRIP) $@
|
||||
</rule>
|
||||
<object source="multiboot.c"/>
|
||||
<external-object source="target/arch/sparc64/vectors.o"/>
|
||||
<external-object source="target/arch/sparc64/entry.o"/>
|
||||
<external-object source="libsparc64.a"/>
|
||||
<external-object source="libbootstrap.a"/>
|
||||
<external-object source="libmodules.a"/>
|
||||
<external-object source="libdrivers.a"/>
|
||||
<external-object source="liblibc.a"/>
|
||||
<external-object source="libfs.a"/>
|
||||
</executable>
|
||||
|
||||
<executable name="openbios-plain.elf" target="target" condition="IMAGE_ELF">
|
||||
<rule>
|
||||
$(LD) -T arch/sparc64/ldscript -o $@.nostrip $^
|
||||
$(NM) $@.nostrip | sort > $(ODIR)/openbios-plain.syms
|
||||
cp $@.nostrip $@
|
||||
$(STRIP) $@
|
||||
</rule>
|
||||
<object source="plainboot.c"/>
|
||||
<external-object source="target/arch/sparc64/vectors.o"/>
|
||||
<external-object source="target/arch/sparc64/entry.o"/>
|
||||
<external-object source="libsparc64.a"/>
|
||||
<external-object source="libbootstrap.a"/>
|
||||
<external-object source="libmodules.a"/>
|
||||
<external-object source="libdrivers.a"/>
|
||||
<external-object source="liblibc.a"/>
|
||||
<external-object source="libfs.a"/>
|
||||
</executable>
|
||||
|
||||
<!-- HACK ALERT -->
|
||||
|
||||
<executable name="target/include/static-dict.h" target="target" condition="IMAGE_ELF_EMBEDDED">
|
||||
<rule><![CDATA[
|
||||
@echo "static const char forth_dictionary[] = {" > $@
|
||||
@cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
|
||||
| sed 's/0x ,//g' >> $@
|
||||
@echo "};" >> $@
|
||||
]]></rule>
|
||||
<external-object source="openbios-sparc64.dict"/>
|
||||
</executable>
|
||||
|
||||
<executable name="target/arch/sparc64/builtin.o" target="target" condition="IMAGE_ELF_EMBEDDED">
|
||||
<rule><![CDATA[
|
||||
$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ arch/sparc64/builtin.c
|
||||
]]></rule>
|
||||
<external-object source="target/include/static-dict.h"/>
|
||||
</executable>
|
||||
|
||||
<!-- END OF HACK ALERT -->
|
||||
|
||||
<executable name="openbios-builtin.elf" target="target" condition="IMAGE_ELF_EMBEDDED">
|
||||
<rule>
|
||||
$(LD) -T arch/sparc64/ldscript -o $@.nostrip $^
|
||||
$(NM) $@.nostrip | sort > $(ODIR)/openbios-builtin.syms
|
||||
cp $@.nostrip $@
|
||||
$(STRIP) $@
|
||||
</rule>
|
||||
<external-object source="target/arch/sparc64/vectors.o"/>
|
||||
<external-object source="target/arch/sparc64/entry.o"/>
|
||||
<external-object source="target/arch/sparc64/builtin.o"/>
|
||||
<external-object source="libsparc64.a"/>
|
||||
<external-object source="libbootstrap.a"/>
|
||||
<external-object source="libmodules.a"/>
|
||||
<external-object source="libdrivers.a"/>
|
||||
<external-object source="liblibc.a"/>
|
||||
<external-object source="libfs.a"/>
|
||||
</executable>
|
||||
|
||||
</build>
|
||||
26
arch/sparc64/builtin.c
Normal file
26
arch/sparc64/builtin.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/* tag: openbios forth starter for builtin dictionary for sparc64
|
||||
*
|
||||
* Copyright (C) 2003 Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include <asm/types.h>
|
||||
#include "sys_info.h"
|
||||
|
||||
/*
|
||||
* wrap an array around the hex'ed dictionary file
|
||||
*/
|
||||
|
||||
#include "static-dict.h"
|
||||
|
||||
void collect_multiboot_info(struct sys_info *info);
|
||||
void collect_multiboot_info(struct sys_info *info)
|
||||
{
|
||||
info->dict_start=(unsigned long *)forth_dictionary;
|
||||
info->dict_end=(unsigned long *)((ucell)forth_dictionary +
|
||||
sizeof(forth_dictionary));
|
||||
}
|
||||
|
||||
406
arch/sparc64/console.c
Normal file
406
arch/sparc64/console.c
Normal file
@@ -0,0 +1,406 @@
|
||||
/*
|
||||
* Copyright (C) 2003, 2004 Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/kernel.h"
|
||||
#include "openbios.h"
|
||||
|
||||
#ifdef CONFIG_DEBUG_CONSOLE
|
||||
|
||||
/* ******************************************************************
|
||||
* serial console functions
|
||||
* ****************************************************************** */
|
||||
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
|
||||
|
||||
#define RBR(x) x==2?0x2f8:0x3f8
|
||||
#define THR(x) x==2?0x2f8:0x3f8
|
||||
#define IER(x) x==2?0x2f9:0x3f9
|
||||
#define IIR(x) x==2?0x2fa:0x3fa
|
||||
#define LCR(x) x==2?0x2fb:0x3fb
|
||||
#define MCR(x) x==2?0x2fc:0x3fc
|
||||
#define LSR(x) x==2?0x2fd:0x3fd
|
||||
#define MSR(x) x==2?0x2fe:0x3fe
|
||||
#define SCR(x) x==2?0x2ff:0x3ff
|
||||
#define DLL(x) x==2?0x2f8:0x3f8
|
||||
#define DLM(x) x==2?0x2f9:0x3f9
|
||||
|
||||
static int uart_charav(int port)
|
||||
{
|
||||
return ((inb(LSR(port)) & 1) != 0);
|
||||
}
|
||||
|
||||
static char uart_getchar(int port)
|
||||
{
|
||||
while (!uart_charav(port));
|
||||
return ((char) inb(RBR(port)) & 0177);
|
||||
}
|
||||
|
||||
static void uart_putchar(int port, unsigned char c)
|
||||
{
|
||||
if (c == '\n')
|
||||
uart_putchar(port, '\r');
|
||||
while (!(inb(LSR(port)) & 0x20));
|
||||
outb(c, THR(port));
|
||||
}
|
||||
|
||||
static void uart_init_line(int port, unsigned long baud)
|
||||
{
|
||||
int i, baudconst;
|
||||
|
||||
switch (baud) {
|
||||
case 115200:
|
||||
baudconst = 1;
|
||||
break;
|
||||
case 57600:
|
||||
baudconst = 2;
|
||||
break;
|
||||
case 38400:
|
||||
baudconst = 3;
|
||||
break;
|
||||
case 19200:
|
||||
baudconst = 6;
|
||||
break;
|
||||
case 9600:
|
||||
default:
|
||||
baudconst = 12;
|
||||
break;
|
||||
}
|
||||
|
||||
outb(0x87, LCR(port));
|
||||
outb(0x00, DLM(port));
|
||||
outb(baudconst, DLL(port));
|
||||
outb(0x07, LCR(port));
|
||||
outb(0x0f, MCR(port));
|
||||
|
||||
for (i = 10; i > 0; i--) {
|
||||
if (inb(LSR(port)) == (unsigned int) 0)
|
||||
break;
|
||||
inb(RBR(port));
|
||||
}
|
||||
}
|
||||
|
||||
static void serial_cls(void);
|
||||
static void serial_putchar(int c);
|
||||
|
||||
int uart_init(int port, unsigned long speed)
|
||||
{
|
||||
uart_init_line(port, speed);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void serial_putchar(int c)
|
||||
{
|
||||
uart_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff));
|
||||
}
|
||||
|
||||
static void serial_cls(void)
|
||||
{
|
||||
serial_putchar(27);
|
||||
serial_putchar('[');
|
||||
serial_putchar('H');
|
||||
serial_putchar(27);
|
||||
serial_putchar('[');
|
||||
serial_putchar('J');
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ******************************************************************
|
||||
* simple polling video/keyboard console functions
|
||||
* ****************************************************************** */
|
||||
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_VGA
|
||||
|
||||
/* raw vga text mode */
|
||||
#define COLUMNS 80 /* The number of columns. */
|
||||
#define LINES 25 /* The number of lines. */
|
||||
#define ATTRIBUTE 7 /* The attribute of an character. */
|
||||
|
||||
#define APB_MEM_BASE 0x1ff00000000ULL
|
||||
#define VGA_BASE (APB_MEM_BASE + 0x4b8000ULL) /* The video memory address. */
|
||||
|
||||
/* VGA Index and Data Registers */
|
||||
#define VGA_REG_INDEX 0x03D4 /* VGA index register */
|
||||
#define VGA_REG_DATA 0x03D5 /* VGA data register */
|
||||
|
||||
#define VGA_IDX_CURMSL 0x09 /* cursor maximum scan line */
|
||||
#define VGA_IDX_CURSTART 0x0A /* cursor start */
|
||||
#define VGA_IDX_CUREND 0x0B /* cursor end */
|
||||
#define VGA_IDX_CURLO 0x0F /* cursor position (low 8 bits) */
|
||||
#define VGA_IDX_CURHI 0x0E /* cursor position (high 8 bits) */
|
||||
|
||||
/* Save the X and Y position. */
|
||||
static int xpos, ypos;
|
||||
/* Point to the video memory. */
|
||||
static volatile unsigned char *video = (unsigned char *) VGA_BASE;
|
||||
|
||||
static void video_initcursor(void)
|
||||
{
|
||||
u8 val;
|
||||
outb(VGA_IDX_CURMSL, VGA_REG_INDEX);
|
||||
val = inb(VGA_REG_DATA) & 0x1f; /* maximum scan line -1 */
|
||||
|
||||
outb(VGA_IDX_CURSTART, VGA_REG_INDEX);
|
||||
outb(0, VGA_REG_DATA);
|
||||
|
||||
outb(VGA_IDX_CUREND, VGA_REG_INDEX);
|
||||
outb(val, VGA_REG_DATA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void video_poscursor(unsigned int x, unsigned int y)
|
||||
{
|
||||
unsigned short pos;
|
||||
|
||||
/* Calculate new cursor position as a function of x and y */
|
||||
pos = (y * COLUMNS) + x;
|
||||
|
||||
/* Output the new position to VGA card */
|
||||
outb(VGA_IDX_CURLO, VGA_REG_INDEX); /* output low 8 bits */
|
||||
outb((u8) (pos), VGA_REG_DATA);
|
||||
outb(VGA_IDX_CURHI, VGA_REG_INDEX); /* output high 8 bits */
|
||||
outb((u8) (pos >> 8), VGA_REG_DATA);
|
||||
|
||||
};
|
||||
|
||||
|
||||
static void video_newline(void)
|
||||
{
|
||||
xpos = 0;
|
||||
|
||||
if (ypos < LINES - 1) {
|
||||
ypos++;
|
||||
} else {
|
||||
int i;
|
||||
memmove((void *) video, (void *) (video + 2 * COLUMNS),
|
||||
(LINES - 1) * COLUMNS * 2);
|
||||
|
||||
for (i = ((LINES - 1) * 2 * COLUMNS);
|
||||
i < 2 * COLUMNS * LINES;) {
|
||||
video[i++] = 0;
|
||||
video[i++] = ATTRIBUTE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Put the character C on the screen. */
|
||||
static void video_putchar(int c)
|
||||
{
|
||||
int p=1;
|
||||
|
||||
if (c == '\n' || c == '\r') {
|
||||
video_newline();
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == '\b') {
|
||||
if (xpos) xpos--;
|
||||
c=' ';
|
||||
p=0;
|
||||
}
|
||||
|
||||
|
||||
if (xpos >= COLUMNS)
|
||||
video_newline();
|
||||
|
||||
*(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
|
||||
*(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
|
||||
|
||||
if (p)
|
||||
xpos++;
|
||||
|
||||
video_poscursor(xpos, ypos);
|
||||
}
|
||||
|
||||
static void video_cls(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * COLUMNS * LINES;) {
|
||||
video[i++] = 0;
|
||||
video[i++] = ATTRIBUTE;
|
||||
}
|
||||
|
||||
|
||||
xpos = 0;
|
||||
ypos = 0;
|
||||
|
||||
video_initcursor();
|
||||
video_poscursor(xpos, ypos);
|
||||
}
|
||||
|
||||
void video_init(void)
|
||||
{
|
||||
video=(unsigned char *)VGA_BASE;
|
||||
}
|
||||
|
||||
/*
|
||||
* keyboard driver
|
||||
*/
|
||||
|
||||
static const char normal[] = {
|
||||
0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
|
||||
'=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
|
||||
'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j',
|
||||
'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b',
|
||||
'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f
|
||||
};
|
||||
|
||||
static const char shifted[] = {
|
||||
0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
|
||||
'+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
|
||||
'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J',
|
||||
'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B',
|
||||
'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8',
|
||||
'9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f
|
||||
};
|
||||
|
||||
static int key_ext;
|
||||
static int key_lshift = 0, key_rshift = 0, key_caps = 0;
|
||||
|
||||
static char last_key;
|
||||
|
||||
static void keyboard_cmd(unsigned char cmd, unsigned char val)
|
||||
{
|
||||
outb(cmd, 0x60);
|
||||
/* wait until keyboard controller accepts cmds: */
|
||||
while (inb(0x64) & 2);
|
||||
outb(val, 0x60);
|
||||
while (inb(0x64) & 2);
|
||||
}
|
||||
|
||||
static char keyboard_poll(void)
|
||||
{
|
||||
unsigned int c;
|
||||
if (inb(0x64) & 1) {
|
||||
c = inb(0x60);
|
||||
switch (c) {
|
||||
case 0xe0:
|
||||
key_ext = 1;
|
||||
return 0;
|
||||
case 0x2a:
|
||||
key_lshift = 1;
|
||||
return 0;
|
||||
case 0x36:
|
||||
key_rshift = 1;
|
||||
return 0;
|
||||
case 0xaa:
|
||||
key_lshift = 0;
|
||||
return 0;
|
||||
case 0xb6:
|
||||
key_rshift = 0;
|
||||
return 0;
|
||||
case 0x3a:
|
||||
if (key_caps) {
|
||||
key_caps = 0;
|
||||
keyboard_cmd(0xed, 0);
|
||||
} else {
|
||||
key_caps = 1;
|
||||
keyboard_cmd(0xed, 4); /* set caps led */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (key_ext) {
|
||||
// void printk(const char *format, ...);
|
||||
printk("extended keycode: %x\n", c);
|
||||
|
||||
key_ext = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (c & 0x80) /* unhandled key release */
|
||||
return 0;
|
||||
|
||||
if (key_lshift || key_rshift)
|
||||
return key_caps ? normal[c] : shifted[c];
|
||||
else
|
||||
return key_caps ? shifted[c] : normal[c];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int keyboard_dataready(void)
|
||||
{
|
||||
if (last_key)
|
||||
return 1;
|
||||
|
||||
last_key = keyboard_poll();
|
||||
|
||||
return (last_key != 0);
|
||||
}
|
||||
|
||||
static unsigned char keyboard_readdata(void)
|
||||
{
|
||||
char tmp;
|
||||
while (!keyboard_dataready());
|
||||
tmp = last_key;
|
||||
last_key = 0;
|
||||
return tmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* ******************************************************************
|
||||
* common functions, implementing simple concurrent console
|
||||
* ****************************************************************** */
|
||||
|
||||
int putchar(int c)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
|
||||
serial_putchar(c);
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_VGA
|
||||
video_putchar(c);
|
||||
#endif
|
||||
return c;
|
||||
}
|
||||
|
||||
int availchar(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
|
||||
if (uart_charav(CONFIG_SERIAL_PORT))
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_VGA
|
||||
if (keyboard_dataready())
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getchar(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
|
||||
if (uart_charav(CONFIG_SERIAL_PORT))
|
||||
return (uart_getchar(CONFIG_SERIAL_PORT));
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_VGA
|
||||
if (keyboard_dataready())
|
||||
return (keyboard_readdata());
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cls(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
|
||||
serial_cls();
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_VGA
|
||||
video_cls();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif // CONFIG_DEBUG_CONSOLE
|
||||
19
arch/sparc64/const.h
Normal file
19
arch/sparc64/const.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* const.h: Macros for dealing with constants. */
|
||||
|
||||
#ifndef _SPARC64_CONST_H
|
||||
#define _SPARC64_CONST_H
|
||||
|
||||
/* Some constant macros are used in both assembler and
|
||||
* C code. Therefore we cannot annotate them always with
|
||||
* 'UL' and other type specificers unilaterally. We
|
||||
* use the following macros to deal with this.
|
||||
*/
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#define _AC(X,Y) X
|
||||
#else
|
||||
#define _AC(X,Y) (X##Y)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* !(_SPARC64_CONST_H) */
|
||||
109
arch/sparc64/context.c
Normal file
109
arch/sparc64/context.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* context switching
|
||||
* 2003-10 by SONE Takeshi
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/kernel.h"
|
||||
#include "context.h"
|
||||
|
||||
#define MAIN_STACK_SIZE 16384
|
||||
#define IMAGE_STACK_SIZE 4096
|
||||
|
||||
#define debug printk
|
||||
|
||||
static void start_main(void); /* forward decl. */
|
||||
void __exit_context(void); /* assembly routine */
|
||||
|
||||
/*
|
||||
* Main context structure
|
||||
* It is placed at the bottom of our stack, and loaded by assembly routine
|
||||
* to start us up.
|
||||
*/
|
||||
struct context main_ctx = {
|
||||
.regs[REG_SP] = (uint64_t) &_estack - 96,
|
||||
.pc = (uint64_t) start_main,
|
||||
.npc = (uint64_t) start_main + 4,
|
||||
.return_addr = (uint64_t) __exit_context,
|
||||
};
|
||||
|
||||
/* This is used by assembly routine to load/store the context which
|
||||
* it is to switch/switched. */
|
||||
struct context *__context = &main_ctx;
|
||||
|
||||
/* Stack for loaded ELF image */
|
||||
static uint8_t image_stack[IMAGE_STACK_SIZE];
|
||||
|
||||
/* Pointer to startup context (physical address) */
|
||||
unsigned long __boot_ctx;
|
||||
|
||||
/*
|
||||
* Main starter
|
||||
* This is the C function that runs first.
|
||||
*/
|
||||
static void start_main(void)
|
||||
{
|
||||
int retval;
|
||||
extern int openbios(void);
|
||||
|
||||
/* Save startup context, so we can refer to it later.
|
||||
* We have to keep it in physical address since we will relocate. */
|
||||
__boot_ctx = virt_to_phys(__context);
|
||||
|
||||
/* Start the real fun */
|
||||
retval = openbios();
|
||||
|
||||
/* Pass return value to startup context. Bootloader may see it. */
|
||||
//boot_ctx->eax = retval;
|
||||
|
||||
/* Returning from here should jump to __exit_context */
|
||||
__context = boot_ctx;
|
||||
}
|
||||
|
||||
/* Setup a new context using the given stack.
|
||||
*/
|
||||
struct context *
|
||||
init_context(uint8_t *stack, uint64_t stack_size, int num_params)
|
||||
{
|
||||
struct context *ctx;
|
||||
|
||||
ctx = (struct context *)
|
||||
(stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t)));
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
/* Fill in reasonable default for flat memory model */
|
||||
ctx->regs[REG_SP] = virt_to_phys(SP_LOC(ctx));
|
||||
ctx->return_addr = virt_to_phys(__exit_context);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/* Switch to another context. */
|
||||
struct context *switch_to(struct context *ctx)
|
||||
{
|
||||
struct context *save, *ret;
|
||||
|
||||
debug("switching to new context:\n");
|
||||
save = __context;
|
||||
__context = ctx;
|
||||
//asm ("pushl %cs; call __switch_context");
|
||||
ret = __context;
|
||||
__context = save;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Start ELF Boot image */
|
||||
uint64_t start_elf(uint64_t entry_point, uint64_t param)
|
||||
{
|
||||
struct context *ctx;
|
||||
|
||||
ctx = init_context(image_stack, sizeof image_stack, 1);
|
||||
ctx->pc = entry_point;
|
||||
ctx->param[0] = param;
|
||||
//ctx->eax = 0xe1fb007;
|
||||
//ctx->ebx = param;
|
||||
|
||||
ctx = switch_to(ctx);
|
||||
//return ctx->eax;
|
||||
return 0;
|
||||
}
|
||||
31
arch/sparc64/context.h
Normal file
31
arch/sparc64/context.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef SPARC64_CONTEXT_H
|
||||
#define SPARC64_CONTEXT_H
|
||||
|
||||
struct context {
|
||||
/* General registers */
|
||||
uint64_t regs[32];
|
||||
uint64_t pc;
|
||||
uint64_t npc;
|
||||
#define REG_O0 8
|
||||
#define REG_SP 14
|
||||
#define SP_LOC(ctx) (&(ctx)->regs[REG_SP])
|
||||
/* Flags */
|
||||
/* Optional stack contents */
|
||||
uint64_t return_addr;
|
||||
uint64_t param[0];
|
||||
};
|
||||
|
||||
/* Create a new context in the given stack */
|
||||
struct context *
|
||||
init_context(uint8_t *stack, uint64_t stack_size, int num_param);
|
||||
|
||||
/* Switch context */
|
||||
struct context *switch_to(struct context *);
|
||||
|
||||
/* Holds physical address of boot context */
|
||||
extern unsigned long __boot_ctx;
|
||||
|
||||
/* This can always be safely used to refer to the boot context */
|
||||
#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx))
|
||||
|
||||
#endif /* SPARC64_CONTEXT_H */
|
||||
416
arch/sparc64/elfload.c
Normal file
416
arch/sparc64/elfload.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/* ELF Boot loader
|
||||
* As we have seek, this implementation can be straightforward.
|
||||
* 2003-07 by SONE Takeshi
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/kernel.h"
|
||||
#include "openbios/elf.h"
|
||||
#include "asm/elf.h"
|
||||
#include "elf_boot.h"
|
||||
#include "sys_info.h"
|
||||
#include "ipchecksum.h"
|
||||
#include "loadfs.h"
|
||||
#define printf printk
|
||||
#define debug printk
|
||||
|
||||
extern unsigned int start_elf(unsigned long entry_point, unsigned long param);
|
||||
#define addr_fixup(addr) ((addr) & 0x00ffffff)
|
||||
|
||||
static char *image_name, *image_version;
|
||||
const char *program_name, *program_version;
|
||||
|
||||
static void *calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
size_t alloc_size = nmemb * size;
|
||||
void *mem;
|
||||
|
||||
if (alloc_size < nmemb || alloc_size < size) {
|
||||
printf("calloc overflow: %u, %u\n", nmemb, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mem = malloc(alloc_size);
|
||||
memset(mem, 0, alloc_size);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
static int check_mem_ranges(struct sys_info *info,
|
||||
Elf_phdr *phdr, int phnum)
|
||||
{
|
||||
int i, j;
|
||||
unsigned long start, end;
|
||||
unsigned long prog_start, prog_end;
|
||||
struct memrange *mem;
|
||||
|
||||
prog_start = virt_to_phys(&_start);
|
||||
prog_end = virt_to_phys(&_end);
|
||||
|
||||
for (i = 0; i < phnum; i++) {
|
||||
if (phdr[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
start = addr_fixup(phdr[i].p_paddr);
|
||||
end = start + phdr[i].p_memsz;
|
||||
if (start < prog_start && end > prog_start)
|
||||
goto conflict;
|
||||
if (start < prog_end && end > prog_end)
|
||||
goto conflict;
|
||||
mem=info->memrange;
|
||||
for (j = 0; j < info->n_memranges; j++) {
|
||||
if (mem[j].base <= start && mem[j].base + mem[j].size >= end)
|
||||
break;
|
||||
}
|
||||
if (j >= info->n_memranges)
|
||||
goto badseg;
|
||||
}
|
||||
return 1;
|
||||
|
||||
conflict:
|
||||
printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end);
|
||||
|
||||
badseg:
|
||||
printf("Segment %d [%#lx-%#lx] doesn't fit into memory\n", i, start, end-1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long process_image_notes(Elf_phdr *phdr, int phnum,
|
||||
unsigned short *sum_ptr,
|
||||
unsigned int offset)
|
||||
{
|
||||
int i;
|
||||
char *buf = NULL;
|
||||
int retval = 0;
|
||||
unsigned long addr, end;
|
||||
Elf_Nhdr *nhdr;
|
||||
const char *name;
|
||||
void *desc;
|
||||
|
||||
for (i = 0; i < phnum; i++) {
|
||||
if (phdr[i].p_type != PT_NOTE)
|
||||
continue;
|
||||
buf = malloc(phdr[i].p_filesz);
|
||||
file_seek(offset + phdr[i].p_offset);
|
||||
if (lfile_read(buf, phdr[i].p_filesz) != phdr[i].p_filesz) {
|
||||
printf("Can't read note segment\n");
|
||||
goto out;
|
||||
}
|
||||
addr = (unsigned long) buf;
|
||||
end = addr + phdr[i].p_filesz;
|
||||
while (addr < end) {
|
||||
nhdr = (Elf_Nhdr *) addr;
|
||||
addr += sizeof(Elf_Nhdr);
|
||||
name = (const char *) addr;
|
||||
addr += (nhdr->n_namesz+3) & ~3;
|
||||
desc = (void *) addr;
|
||||
addr += (nhdr->n_descsz+3) & ~3;
|
||||
|
||||
if (nhdr->n_namesz==sizeof(ELF_NOTE_BOOT)
|
||||
&& memcmp(name, ELF_NOTE_BOOT, sizeof(ELF_NOTE_BOOT))==0) {
|
||||
if (nhdr->n_type == EIN_PROGRAM_NAME) {
|
||||
image_name = calloc(1, nhdr->n_descsz + 1);
|
||||
memcpy(image_name, desc, nhdr->n_descsz);
|
||||
}
|
||||
if (nhdr->n_type == EIN_PROGRAM_VERSION) {
|
||||
image_version = calloc(1, nhdr->n_descsz + 1);
|
||||
memcpy(image_version, desc, nhdr->n_descsz);
|
||||
}
|
||||
if (nhdr->n_type == EIN_PROGRAM_CHECKSUM) {
|
||||
*sum_ptr = *(unsigned short *) desc;
|
||||
debug("Image checksum: %#04x\n", *sum_ptr);
|
||||
/* Where in the file */
|
||||
retval = phdr[i].p_offset
|
||||
+ (unsigned long) desc - (unsigned long) buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
file_close();
|
||||
if (buf)
|
||||
free(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int load_segments(Elf_phdr *phdr, int phnum,
|
||||
unsigned long checksum_offset,
|
||||
unsigned int offset)
|
||||
{
|
||||
unsigned long bytes;
|
||||
//unsigned int start_time, time;
|
||||
int i;
|
||||
|
||||
bytes = 0;
|
||||
// start_time = currticks();
|
||||
for (i = 0; i < phnum; i++) {
|
||||
if (phdr[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
debug("segment %d addr:%#lx file:%#lx mem:%#lx ",
|
||||
i, addr_fixup(phdr[i].p_paddr), phdr[i].p_filesz, phdr[i].p_memsz);
|
||||
file_seek(offset + phdr[i].p_offset);
|
||||
debug("loading... ");
|
||||
if (lfile_read(phys_to_virt(addr_fixup(phdr[i].p_paddr)), phdr[i].p_filesz)
|
||||
!= phdr[i].p_filesz) {
|
||||
printf("Can't read program segment %d\n", i);
|
||||
return 0;
|
||||
}
|
||||
bytes += phdr[i].p_filesz;
|
||||
debug("clearing... ");
|
||||
memset(phys_to_virt(addr_fixup(phdr[i].p_paddr) + phdr[i].p_filesz), 0,
|
||||
phdr[i].p_memsz - phdr[i].p_filesz);
|
||||
if (phdr[i].p_offset <= checksum_offset
|
||||
&& phdr[i].p_offset + phdr[i].p_filesz >= checksum_offset+2) {
|
||||
debug("clearing checksum... ");
|
||||
memset(phys_to_virt(addr_fixup(phdr[i].p_paddr) + checksum_offset
|
||||
- phdr[i].p_offset), 0, 2);
|
||||
}
|
||||
debug("ok\n");
|
||||
|
||||
}
|
||||
// time = currticks() - start_time;
|
||||
//debug("Loaded %lu bytes in %ums (%luKB/s)\n", bytes, time,
|
||||
// time? bytes/time : 0);
|
||||
debug("Loaded %lu bytes \n", bytes);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int verify_image(Elf_ehdr *ehdr, Elf_phdr *phdr, int phnum,
|
||||
unsigned short image_sum)
|
||||
{
|
||||
unsigned short sum, part_sum;
|
||||
unsigned long offset;
|
||||
int i;
|
||||
|
||||
sum = 0;
|
||||
offset = 0;
|
||||
|
||||
part_sum = ipchksum(ehdr, sizeof *ehdr);
|
||||
sum = add_ipchksums(offset, sum, part_sum);
|
||||
offset += sizeof *ehdr;
|
||||
|
||||
part_sum = ipchksum(phdr, phnum * sizeof(*phdr));
|
||||
sum = add_ipchksums(offset, sum, part_sum);
|
||||
offset += phnum * sizeof(*phdr);
|
||||
|
||||
for (i = 0; i < phnum; i++) {
|
||||
if (phdr[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
part_sum = ipchksum(phys_to_virt(addr_fixup(phdr[i].p_paddr)), phdr[i].p_memsz);
|
||||
sum = add_ipchksums(offset, sum, part_sum);
|
||||
offset += phdr[i].p_memsz;
|
||||
}
|
||||
|
||||
if (sum != image_sum) {
|
||||
printf("Verify FAILED (image:%#04x vs computed:%#04x)\n",
|
||||
image_sum, sum);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline unsigned padded(unsigned s)
|
||||
{
|
||||
return (s + 3) & ~3;
|
||||
}
|
||||
|
||||
static Elf_Bhdr *add_boot_note(Elf_Bhdr *bhdr, const char *name,
|
||||
unsigned type, const char *desc, unsigned descsz)
|
||||
{
|
||||
Elf_Nhdr nhdr;
|
||||
unsigned ent_size, new_size, pad;
|
||||
char *addr;
|
||||
|
||||
if (!bhdr)
|
||||
return NULL;
|
||||
|
||||
nhdr.n_namesz = name? strlen(name)+1 : 0;
|
||||
nhdr.n_descsz = descsz;
|
||||
nhdr.n_type = type;
|
||||
ent_size = sizeof(nhdr) + padded(nhdr.n_namesz) + padded(nhdr.n_descsz);
|
||||
if (bhdr->b_size + ent_size > 0xffff) {
|
||||
printf("Boot notes too big\n");
|
||||
free(bhdr);
|
||||
return NULL;
|
||||
}
|
||||
if (bhdr->b_size + ent_size > bhdr->b_checksum) {
|
||||
do {
|
||||
new_size = bhdr->b_checksum * 2;
|
||||
} while (new_size < bhdr->b_size + ent_size);
|
||||
if (new_size > 0xffff)
|
||||
new_size = 0xffff;
|
||||
debug("expanding boot note size to %u\n", new_size);
|
||||
#ifdef HAVE_REALLOC
|
||||
bhdr = realloc(bhdr, new_size);
|
||||
bhdr->b_checksum = new_size;
|
||||
#else
|
||||
printf("Boot notes too big\n");
|
||||
free(bhdr);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
addr = (char *) bhdr;
|
||||
addr += bhdr->b_size;
|
||||
memcpy(addr, &nhdr, sizeof(nhdr));
|
||||
addr += sizeof(nhdr);
|
||||
|
||||
memcpy(addr, name, nhdr.n_namesz);
|
||||
addr += nhdr.n_namesz;
|
||||
pad = padded(nhdr.n_namesz) - nhdr.n_namesz;
|
||||
memset(addr, 0, pad);
|
||||
addr += pad;
|
||||
|
||||
memcpy(addr, desc, nhdr.n_descsz);
|
||||
addr += nhdr.n_descsz;
|
||||
pad = padded(nhdr.n_descsz) - nhdr.n_descsz;
|
||||
memset(addr, 0, pad);
|
||||
addr += pad;
|
||||
|
||||
bhdr->b_size += ent_size;
|
||||
bhdr->b_records++;
|
||||
return bhdr;
|
||||
}
|
||||
|
||||
static inline Elf_Bhdr *add_note_string(Elf_Bhdr *bhdr, const char *name,
|
||||
unsigned type, const char *desc)
|
||||
{
|
||||
return add_boot_note(bhdr, name, type, desc, strlen(desc) + 1);
|
||||
}
|
||||
|
||||
static Elf_Bhdr *build_boot_notes(struct sys_info *info, const char *cmdline)
|
||||
{
|
||||
Elf_Bhdr *bhdr;
|
||||
|
||||
bhdr = malloc(256);
|
||||
bhdr->b_signature = ELF_BHDR_MAGIC;
|
||||
bhdr->b_size = sizeof *bhdr;
|
||||
bhdr->b_checksum = 256; /* XXX cache the current buffer size here */
|
||||
bhdr->b_records = 0;
|
||||
|
||||
if (info->firmware)
|
||||
bhdr = add_note_string(bhdr, NULL, EBN_FIRMWARE_TYPE, info->firmware);
|
||||
bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_NAME, program_name);
|
||||
bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_VERSION, program_version);
|
||||
if (cmdline)
|
||||
bhdr = add_note_string(bhdr, NULL, EBN_COMMAND_LINE, cmdline);
|
||||
if (!bhdr)
|
||||
return bhdr;
|
||||
bhdr->b_checksum = 0;
|
||||
bhdr->b_checksum = ipchksum(bhdr, bhdr->b_size);
|
||||
return bhdr;
|
||||
}
|
||||
|
||||
int elf_load(struct sys_info *info, const char *filename, const char *cmdline)
|
||||
{
|
||||
Elf_ehdr ehdr;
|
||||
Elf_phdr *phdr = NULL;
|
||||
unsigned long phdr_size;
|
||||
unsigned long checksum_offset;
|
||||
unsigned short checksum;
|
||||
Elf_Bhdr *boot_notes = NULL;
|
||||
int retval = -1;
|
||||
int image_retval;
|
||||
unsigned int offset;
|
||||
|
||||
image_name = image_version = 0;
|
||||
|
||||
if (!file_open(filename))
|
||||
goto out;
|
||||
|
||||
for (offset = 0; offset < 16 * 512; offset += 512) {
|
||||
if (lfile_read(&ehdr, sizeof ehdr) != sizeof ehdr) {
|
||||
debug("Can't read ELF header\n");
|
||||
retval = LOADER_NOT_SUPPORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ehdr.e_ident[EI_MAG0] == ELFMAG0)
|
||||
break;
|
||||
|
||||
file_seek(offset);
|
||||
}
|
||||
|
||||
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|
||||
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|
||||
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|
||||
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
|
||||
|| ehdr.e_ident[EI_CLASS] != ARCH_ELF_CLASS
|
||||
|| ehdr.e_ident[EI_DATA] != ARCH_ELF_DATA
|
||||
|| ehdr.e_ident[EI_VERSION] != EV_CURRENT
|
||||
|| ehdr.e_type != ET_EXEC
|
||||
|| !ARCH_ELF_MACHINE_OK(ehdr.e_machine)
|
||||
|| ehdr.e_version != EV_CURRENT
|
||||
|| ehdr.e_phentsize != sizeof(Elf_phdr)) {
|
||||
debug("Not a bootable ELF image\n");
|
||||
retval = LOADER_NOT_SUPPORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
phdr_size = ehdr.e_phnum * sizeof *phdr;
|
||||
phdr = malloc(phdr_size);
|
||||
file_seek(offset + ehdr.e_phoff);
|
||||
if (lfile_read(phdr, phdr_size) != phdr_size) {
|
||||
printf("Can't read program header\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!check_mem_ranges(info, phdr, ehdr.e_phnum))
|
||||
goto out;
|
||||
|
||||
checksum_offset = process_image_notes(phdr, ehdr.e_phnum, &checksum, offset);
|
||||
|
||||
printf("Loading %s", image_name ? image_name : "image");
|
||||
if (image_version)
|
||||
printf(" version %s", image_version);
|
||||
printf("...\n");
|
||||
|
||||
if (!load_segments(phdr, ehdr.e_phnum, checksum_offset, offset))
|
||||
goto out;
|
||||
|
||||
if (checksum_offset) {
|
||||
if (!verify_image(&ehdr, phdr, ehdr.e_phnum, checksum))
|
||||
goto out;
|
||||
}
|
||||
|
||||
boot_notes = build_boot_notes(info, cmdline);
|
||||
|
||||
//debug("current time: %lu\n", currticks());
|
||||
|
||||
debug("entry point is %#lx\n", addr_fixup(ehdr.e_entry));
|
||||
printf("Jumping to entry point...\n");
|
||||
|
||||
#if 0
|
||||
{
|
||||
extern unsigned int qemu_mem_size;
|
||||
extern char boot_device;
|
||||
void *init_openprom(unsigned long memsize, const char *cmdline, char boot_device);
|
||||
|
||||
int (*entry)(const void *romvec, int p2, int p3, int p4, int p5);
|
||||
const void *romvec;
|
||||
|
||||
romvec = init_openprom(qemu_mem_size, cmdline, boot_device);
|
||||
entry = (void *) addr_fixup(ehdr.e_entry);
|
||||
image_retval = entry(romvec, 0, 0, 0, 0);
|
||||
}
|
||||
#else
|
||||
image_retval = start_elf(addr_fixup(ehdr.e_entry), virt_to_phys(boot_notes));
|
||||
#endif
|
||||
|
||||
// console_init(); FIXME
|
||||
printf("Image returned with return value %#x\n", image_retval);
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
file_close();
|
||||
if (phdr)
|
||||
free(phdr);
|
||||
if (boot_notes)
|
||||
free(boot_notes);
|
||||
if (image_name)
|
||||
free(image_name);
|
||||
if (image_version)
|
||||
free(image_version);
|
||||
return retval;
|
||||
}
|
||||
250
arch/sparc64/entry.S
Normal file
250
arch/sparc64/entry.S
Normal file
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
** Standalone startup code for Linux PROM emulator.
|
||||
** Copyright 1999 Pete A. Zaitcev
|
||||
** This code is licensed under GNU General Public License.
|
||||
**/
|
||||
/*
|
||||
* $Id: head.S,v 1.12 2002/07/23 05:47:09 zaitcev Exp $
|
||||
*/
|
||||
|
||||
#define __ASSEMBLY__
|
||||
#include "asi.h"
|
||||
#include "pstate.h"
|
||||
#include "lsu.h"
|
||||
|
||||
.globl entry, _entry
|
||||
|
||||
.section ".text", "ax"
|
||||
.align 8
|
||||
.register %g2, #scratch
|
||||
.register %g3, #scratch
|
||||
.register %g6, #scratch
|
||||
.register %g7, #scratch
|
||||
|
||||
/*
|
||||
* Entry point
|
||||
* We start execution from here.
|
||||
*/
|
||||
_entry:
|
||||
entry:
|
||||
! Set up CPU state
|
||||
wrpr %g0, PSTATE_PRIV, %pstate
|
||||
wr %g0, 0, %fprs
|
||||
wrpr %g0, 0x0, %tl
|
||||
|
||||
! Extract NWINDOWS from %ver
|
||||
rdpr %ver, %g1
|
||||
and %g1, 0xf, %g1
|
||||
wrpr %g1, 0, %cleanwin
|
||||
wrpr %g1, 0, %cansave
|
||||
wrpr %g0, 0, %canrestore
|
||||
wrpr %g0, 0, %otherwin
|
||||
wrpr %g0, 0, %wstate
|
||||
|
||||
! Disable I/D MMUs and caches
|
||||
stxa %g0, [%g0] ASI_LSU_CONTROL
|
||||
|
||||
! Get memory size from NVRAM
|
||||
setx 0x1fe02000074, %g2, %g5
|
||||
mov 0x30, %g2
|
||||
stba %g2, [%g5] ASI_PHYS_BYPASS_EC_E
|
||||
add %g5, 1, %g1
|
||||
stba %g0, [%g1] ASI_PHYS_BYPASS_EC_E
|
||||
add %g1, 2, %g1
|
||||
lduba [%g1] ASI_PHYS_BYPASS_EC_E, %g4
|
||||
|
||||
sll %g4, 8, %g4
|
||||
inc %g2
|
||||
stba %g2, [%g5] ASI_PHYS_BYPASS_EC_E
|
||||
lduba [%g1] ASI_PHYS_BYPASS_EC_E, %g3
|
||||
or %g3, %g4, %g4
|
||||
|
||||
sll %g4, 8, %g4
|
||||
inc %g2
|
||||
stba %g2, [%g5] ASI_PHYS_BYPASS_EC_E
|
||||
lduba [%g1] ASI_PHYS_BYPASS_EC_E, %g3
|
||||
or %g3, %g4, %g4
|
||||
|
||||
sll %g4, 8, %g4
|
||||
inc %g2
|
||||
stba %g2, [%g5] ASI_PHYS_BYPASS_EC_E
|
||||
lduba [%g1] ASI_PHYS_BYPASS_EC_E, %g3
|
||||
or %g3, %g4, %g1
|
||||
! %g1 contains end of memory
|
||||
|
||||
|
||||
setx _end, %g7, %g3
|
||||
set 0xffff, %g2
|
||||
add %g3, %g2, %g3
|
||||
andn %g3, %g2, %g3
|
||||
setx _data, %g7, %g2
|
||||
sub %g3, %g2, %g2
|
||||
sub %g1, %g2, %g2 ! %g2 = start of private memory
|
||||
mov %g2, %l0
|
||||
|
||||
! setup .data & .bss
|
||||
setx _data, %g7, %g4
|
||||
sub %g3, %g4, %g5
|
||||
srlx %g5, 16, %g6 ! %g6 = # of 64k .bss pages
|
||||
set 0xa0000000, %g3
|
||||
sllx %g3, 32, %g3
|
||||
or %g3, 0x76, %g3
|
||||
! valid, 64k, locked, cacheable(I/E/C), priv, writable
|
||||
set 48, %g7
|
||||
1: stxa %g4, [%g7] ASI_DMMU ! vaddr = _data + N * 0x10000, ctx=0
|
||||
or %g2, %g3, %g5
|
||||
! paddr = start_mem + N * 0x10000
|
||||
stxa %g5, [%g0] ASI_DTLB_DATA_IN
|
||||
set 0x10000, %g5
|
||||
add %g2, %g5, %g2
|
||||
add %g4, %g5, %g4
|
||||
deccc %g6
|
||||
bne 1b
|
||||
nop
|
||||
|
||||
! setup .rodata
|
||||
setx _data, %g7, %g5
|
||||
setx _rodata, %g7, %g4
|
||||
sub %g5, %g4, %g5
|
||||
srlx %g5, 16, %g6 ! %g6 = # of 64k .rodata pages
|
||||
set 48, %g7
|
||||
set 0x10000, %g5
|
||||
1: stxa %g4, [%g7] ASI_DMMU ! vaddr = _rodata, ctx=0
|
||||
set 0xa0000000, %g3
|
||||
sllx %g3, 32, %g3
|
||||
or %g3, 0x74, %g3
|
||||
or %g4, %g3, %g3
|
||||
! valid, 64k, locked, cacheable(I/E/C), priv
|
||||
! paddr = _rodata + N * 0x10000
|
||||
stxa %g3, [%g0] ASI_DTLB_DATA_IN
|
||||
add %g4, %g5, %g4
|
||||
deccc %g6
|
||||
bne 1b
|
||||
nop
|
||||
|
||||
! setup VGA buffer
|
||||
setx 0x1ff004a0000, %g7, %g4
|
||||
mov 2, %g6
|
||||
set 48, %g7
|
||||
set 0x10000, %g5
|
||||
1: stxa %g4, [%g7] ASI_DMMU ! vaddr = 0x1ff004a0000, ctx=0
|
||||
set 0xa0000000, %g3
|
||||
sllx %g3, 32, %g3
|
||||
or %g3, 0x76, %g3
|
||||
or %g4, %g3, %g3
|
||||
! valid, 64k, locked, cacheable(I/E/C), priv, writable
|
||||
! paddr = 0x1ff004a0000
|
||||
stxa %g3, [%g0] ASI_DTLB_DATA_IN
|
||||
add %g4, %g5, %g4
|
||||
deccc %g6
|
||||
bne 1b
|
||||
nop
|
||||
|
||||
#if 0
|
||||
! setup 0-4M
|
||||
set 48, %g7
|
||||
stxa %g0, [%g7] ASI_DMMU ! vaddr = 0, ctx=0
|
||||
set 0xe0000000, %g3
|
||||
sllx %g3, 32, %g3
|
||||
or %g3, 0x36, %g3
|
||||
! valid, 4M, cacheable(I/E/C), priv, writable
|
||||
! paddr = 0
|
||||
stxa %g3, [%g0] ASI_DTLB_DATA_IN
|
||||
#endif
|
||||
|
||||
membar #Sync
|
||||
|
||||
setx _start, %g7, %g4
|
||||
setx _rodata, %g7, %g5
|
||||
sub %g5, %g4, %g5
|
||||
srlx %g5, 16, %g6 ! %g6 = # of 64k .text pages
|
||||
set 48, %g7
|
||||
1: stxa %g4, [%g7] ASI_IMMU ! vaddr = _start, ctx=0
|
||||
set 0xa0000000, %g3
|
||||
sllx %g3, 32, %g3
|
||||
or %g3, 0x74, %g3
|
||||
or %g4, %g3, %g3
|
||||
! valid, 64k, locked, cacheable(I/E/C), priv
|
||||
! paddr = _start + N * 0x10000
|
||||
stxa %g3, [%g0] ASI_ITLB_DATA_IN
|
||||
set 0x10000, %g5
|
||||
add %g4, %g5, %g4
|
||||
deccc %g6
|
||||
bne 1b
|
||||
nop
|
||||
|
||||
#if 0
|
||||
! setup 0-4M
|
||||
stxa %g0, [%g7] ASI_IMMU ! vaddr = 0, ctx=0
|
||||
set 0xe0000000, %g3
|
||||
sllx %g3, 32, %g3
|
||||
or %g3, 0x34, %g3
|
||||
! valid, 4M, cacheable(I/E/C), priv
|
||||
! paddr = 0
|
||||
stxa %g3, [%g0] ASI_ITLB_DATA_IN
|
||||
#endif
|
||||
|
||||
flush %g4
|
||||
|
||||
mov %g1, %g3
|
||||
|
||||
set 8, %g2
|
||||
sta %g0, [%g2] ASI_DMMU ! set primary ctx=0
|
||||
|
||||
! Enable I/D MMUs and caches
|
||||
set LSU_CONTROL_DM|LSU_CONTROL_IM|LSU_CONTROL_DC|LSU_CONTROL_IC, %g2
|
||||
stxa %g2, [%g0] ASI_LSU_CONTROL
|
||||
|
||||
/* Copy the DATA section from ROM. */
|
||||
setx _data - 8, %o7, %o0 ! First address of DATA
|
||||
setx _bss, %o7, %o1 ! Last address of DATA
|
||||
ba 2f
|
||||
nop
|
||||
1:
|
||||
ldxa [%o0] ASI_PHYS_BYPASS_EC_E, %g1
|
||||
stx %g1, [%o0]
|
||||
2:
|
||||
subcc %o0, %o1, %g0
|
||||
bl 1b
|
||||
add %o0, 0x8, %o0
|
||||
|
||||
/* Zero out our BSS section. */
|
||||
setx _bss - 8, %o7, %o0 ! First address of BSS
|
||||
setx _end, %o7, %o1 ! Last address of BSS
|
||||
ba 2f
|
||||
nop
|
||||
1:
|
||||
stx %g0, [%o0]
|
||||
2:
|
||||
subcc %o0, %o1, %g0
|
||||
bl 1b
|
||||
add %o0, 0x8, %o0
|
||||
|
||||
setx trap_table, %g2, %g1
|
||||
wrpr %g1, %tba
|
||||
|
||||
setx qemu_mem_size, %g7, %g1
|
||||
stx %g3, [%g1]
|
||||
|
||||
setx _data, %g7, %g1 ! Store va->pa conversion factor
|
||||
sub %g1, %l0, %g2
|
||||
setx va_shift, %g7, %g1
|
||||
stx %g2, [%g1]
|
||||
|
||||
/* Finally, turn on traps so that we can call c-code. */
|
||||
wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
|
||||
|
||||
/* Switch to our main context.
|
||||
* Main context is statically defined in C.
|
||||
*/
|
||||
|
||||
call __switch_context_nosave
|
||||
nop
|
||||
|
||||
/* We get here when the main context switches back to
|
||||
* the boot context.
|
||||
* Return to previous bootloader.
|
||||
*/
|
||||
ret
|
||||
nop
|
||||
|
||||
62
arch/sparc64/forthload.c
Normal file
62
arch/sparc64/forthload.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/* tag: forth source loader
|
||||
*
|
||||
* Copyright (C) 2004 Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/kernel.h"
|
||||
#include "openbios/bindings.h"
|
||||
#include "sys_info.h"
|
||||
#include "loadfs.h"
|
||||
#include "boot.h"
|
||||
#define printk printk
|
||||
#define debug printk
|
||||
|
||||
static char *forthtext=NULL;
|
||||
int forth_load(struct sys_info *info, const char *filename, const char *cmdline)
|
||||
{
|
||||
char magic[2];
|
||||
unsigned long forthsize;
|
||||
int retval = -1;
|
||||
|
||||
if (!file_open(filename))
|
||||
goto out;
|
||||
|
||||
if (lfile_read(magic, 2) != 2) {
|
||||
debug("Can't read magic header\n");
|
||||
retval = LOADER_NOT_SUPPORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (magic[0] != '\\' || magic[1] != ' ') {
|
||||
debug("No forth source image\n");
|
||||
retval = LOADER_NOT_SUPPORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
forthsize = file_size();
|
||||
|
||||
forthtext = malloc(forthsize+1);
|
||||
file_seek(0);
|
||||
|
||||
printk("Loading forth source ...");
|
||||
if ((unsigned long)lfile_read(forthtext, forthsize) != forthsize) {
|
||||
printk("Can't read forth text\n");
|
||||
goto out;
|
||||
}
|
||||
forthtext[forthsize]=0;
|
||||
printk("ok\n");
|
||||
|
||||
PUSH ( (ucell)forthtext );
|
||||
PUSH ( (ucell)forthsize );
|
||||
fword("eval2");
|
||||
retval=0;
|
||||
|
||||
out:
|
||||
//if (forthtext)
|
||||
// free(forthtext);
|
||||
return retval;
|
||||
}
|
||||
58
arch/sparc64/init.fs
Normal file
58
arch/sparc64/init.fs
Normal file
@@ -0,0 +1,58 @@
|
||||
:noname
|
||||
." Type 'help' for detailed information" cr
|
||||
\ ." boot secondary slave cdrom: " cr
|
||||
\ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr
|
||||
; DIAG-initializer
|
||||
|
||||
: make-openable ( path )
|
||||
find-dev if
|
||||
begin ?dup while
|
||||
\ install trivial open and close methods
|
||||
dup active-package! is-open
|
||||
parent
|
||||
repeat
|
||||
then
|
||||
;
|
||||
|
||||
: preopen ( chosen-str node-path )
|
||||
2dup make-openable
|
||||
|
||||
" /chosen" find-device
|
||||
open-dev ?dup if
|
||||
encode-int 2swap property
|
||||
else
|
||||
2drop
|
||||
then
|
||||
;
|
||||
|
||||
:noname
|
||||
set-defaults
|
||||
; SYSTEM-initializer
|
||||
|
||||
\ preopen device nodes (and store the ihandles under /chosen)
|
||||
:noname
|
||||
" memory" " /memory" preopen
|
||||
" mmu" " /cpus/@0" preopen
|
||||
" stdout" " /builtin/console" preopen
|
||||
" stdin" " /builtin/console" preopen
|
||||
|
||||
; SYSTEM-initializer
|
||||
|
||||
\ use the tty interface if available
|
||||
:noname
|
||||
" /builtin/console" find-dev if drop
|
||||
" /builtin/console" " input-device" $setenv
|
||||
" /builtin/console" " output-device" $setenv
|
||||
then
|
||||
; SYSTEM-initializer
|
||||
|
||||
:noname
|
||||
" keyboard" input
|
||||
; CONSOLE-IN-initializer
|
||||
|
||||
device-end
|
||||
|
||||
: rmap@ ( virt -- rmentry )
|
||||
drop 0
|
||||
;
|
||||
|
||||
83
arch/sparc64/ldscript
Normal file
83
arch/sparc64/ldscript
Normal file
@@ -0,0 +1,83 @@
|
||||
OUTPUT_FORMAT(elf64-sparc)
|
||||
OUTPUT_ARCH(sparc:v9)
|
||||
|
||||
/* Qemu ELF loader can't handle very complex files, so we put ELFBoot
|
||||
info to rodata and put initctx to data.*/
|
||||
|
||||
ENTRY(trap_table)
|
||||
|
||||
/* Initial load address
|
||||
*/
|
||||
BASE_ADDR = 0x000001fff0000000;
|
||||
|
||||
/* 16KB heap and stack */
|
||||
HEAP_SIZE = 16384;
|
||||
STACK_SIZE = 16384;
|
||||
VMEM_SIZE = 128 * 1024;
|
||||
IOMEM_SIZE = 256 * 1024 + 768 * 1024;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BASE_ADDR;
|
||||
|
||||
/* Start of the program.
|
||||
* Now the version string is in the note, we must include it
|
||||
* in the program. Otherwise we lose the string after relocation. */
|
||||
_start = .;
|
||||
|
||||
/* Normal sections */
|
||||
.text ALIGN(65536): {
|
||||
*(.text.vectors)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
}
|
||||
.rodata ALIGN(65536): {
|
||||
_rodata = .;
|
||||
sound_drivers_start = .;
|
||||
*(.rodata.sound_drivers)
|
||||
sound_drivers_end = .;
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.note.ELFBoot)
|
||||
}
|
||||
.data ALIGN(65536): {
|
||||
_data = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
}
|
||||
|
||||
.bss ALIGN(4096): {
|
||||
_bss = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
|
||||
/* Put heap and stack here, so they are included in PT_LOAD segment
|
||||
* and the bootloader is aware of it. */
|
||||
|
||||
. = ALIGN(16);
|
||||
_heap = .;
|
||||
. += HEAP_SIZE;
|
||||
. = ALIGN(16);
|
||||
_eheap = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
_vmem = .;
|
||||
. += VMEM_SIZE;
|
||||
_evmem = .;
|
||||
|
||||
_stack = .;
|
||||
. += STACK_SIZE;
|
||||
. = ALIGN(16);
|
||||
_estack = .;
|
||||
}
|
||||
|
||||
. = ALIGN(4096);
|
||||
_end = .;
|
||||
_iomem = _end + IOMEM_SIZE;
|
||||
|
||||
/* We discard .note sections other than .note.ELFBoot,
|
||||
* because some versions of GCC generates useless ones. */
|
||||
|
||||
/DISCARD/ : { *(.comment*) *(.note.*) }
|
||||
}
|
||||
59
arch/sparc64/lib.c
Normal file
59
arch/sparc64/lib.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/* lib.c
|
||||
* tag: simple function library
|
||||
*
|
||||
* Copyright (C) 2003 Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "asm/types.h"
|
||||
#include <stdarg.h>
|
||||
#include "libc/stdlib.h"
|
||||
#include "libc/vsprintf.h"
|
||||
#include "openbios/kernel.h"
|
||||
|
||||
/* Format a string and print it on the screen, just like the libc
|
||||
* function printf.
|
||||
*/
|
||||
int printk( const char *fmt, ... )
|
||||
{
|
||||
char *p, buf[512]; /* XXX: no buffer overflow protection... */
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i=vsprintf(buf,fmt,args);
|
||||
va_end(args);
|
||||
|
||||
for( p=buf; *p; p++ )
|
||||
putchar(*p);
|
||||
return i;
|
||||
}
|
||||
|
||||
#define MEMSIZE 128*1024
|
||||
static char memory[MEMSIZE];
|
||||
static void *memptr=memory;
|
||||
static int memsize=MEMSIZE;
|
||||
|
||||
|
||||
void *malloc(int size)
|
||||
{
|
||||
void *ret=(void *)0;
|
||||
if(memsize>=size) {
|
||||
memsize-=size;
|
||||
ret=memptr;
|
||||
memptr+=size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void free(void *ptr)
|
||||
{
|
||||
/* Nothing yet */
|
||||
}
|
||||
|
||||
unsigned long map_page(unsigned long va, unsigned long epa, int type)
|
||||
{
|
||||
}
|
||||
623
arch/sparc64/linux_load.c
Normal file
623
arch/sparc64/linux_load.c
Normal file
@@ -0,0 +1,623 @@
|
||||
/*
|
||||
* Linux/i386 loader
|
||||
* Supports bzImage, zImage and Image format.
|
||||
*
|
||||
* Based on work by Steve Gehlbach.
|
||||
* Portions are taken from mkelfImage.
|
||||
*
|
||||
* 2003-09 by SONE Takeshi
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/kernel.h"
|
||||
#include "openbios/bindings.h"
|
||||
#include "sys_info.h"
|
||||
#include "context.h"
|
||||
#include "loadfs.h"
|
||||
|
||||
#define printf printk
|
||||
#define debug printk
|
||||
#define strtoull_with_suffix strtol
|
||||
|
||||
#define LINUX_PARAM_LOC 0x90000
|
||||
#define COMMAND_LINE_LOC 0x91000
|
||||
#define GDT_LOC 0x92000
|
||||
#define STACK_LOC 0x93000
|
||||
|
||||
#define E820MAX 32 /* number of entries in E820MAP */
|
||||
struct e820entry {
|
||||
unsigned long long addr; /* start of memory segment */
|
||||
unsigned long long size; /* size of memory segment */
|
||||
unsigned long type; /* type of memory segment */
|
||||
#define E820_RAM 1
|
||||
#define E820_RESERVED 2
|
||||
#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
|
||||
#define E820_NVS 4
|
||||
};
|
||||
|
||||
/* The header of Linux/i386 kernel */
|
||||
struct linux_header {
|
||||
uint8_t reserved1[0x1f1]; /* 0x000 */
|
||||
uint8_t setup_sects; /* 0x1f1 */
|
||||
uint16_t root_flags; /* 0x1f2 */
|
||||
uint8_t reserved2[6]; /* 0x1f4 */
|
||||
uint16_t vid_mode; /* 0x1fa */
|
||||
uint16_t root_dev; /* 0x1fc */
|
||||
uint16_t boot_sector_magic; /* 0x1fe */
|
||||
/* 2.00+ */
|
||||
uint8_t reserved3[2]; /* 0x200 */
|
||||
uint8_t header_magic[4]; /* 0x202 */
|
||||
uint16_t protocol_version; /* 0x206 */
|
||||
uint32_t realmode_swtch; /* 0x208 */
|
||||
uint16_t start_sys; /* 0x20c */
|
||||
uint16_t kver_addr; /* 0x20e */
|
||||
uint8_t type_of_loader; /* 0x210 */
|
||||
uint8_t loadflags; /* 0x211 */
|
||||
uint16_t setup_move_size; /* 0x212 */
|
||||
uint32_t code32_start; /* 0x214 */
|
||||
uint32_t ramdisk_image; /* 0x218 */
|
||||
uint32_t ramdisk_size; /* 0x21c */
|
||||
uint8_t reserved4[4]; /* 0x220 */
|
||||
/* 2.01+ */
|
||||
uint16_t heap_end_ptr; /* 0x224 */
|
||||
uint8_t reserved5[2]; /* 0x226 */
|
||||
/* 2.02+ */
|
||||
uint32_t cmd_line_ptr; /* 0x228 */
|
||||
/* 2.03+ */
|
||||
uint32_t initrd_addr_max; /* 0x22c */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* Paramters passed to 32-bit part of Linux
|
||||
* This is another view of the structure above.. */
|
||||
struct linux_params {
|
||||
uint8_t orig_x; /* 0x00 */
|
||||
uint8_t orig_y; /* 0x01 */
|
||||
uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */
|
||||
uint16_t orig_video_page; /* 0x04 */
|
||||
uint8_t orig_video_mode; /* 0x06 */
|
||||
uint8_t orig_video_cols; /* 0x07 */
|
||||
uint16_t unused2; /* 0x08 */
|
||||
uint16_t orig_video_ega_bx; /* 0x0a */
|
||||
uint16_t unused3; /* 0x0c */
|
||||
uint8_t orig_video_lines; /* 0x0e */
|
||||
uint8_t orig_video_isVGA; /* 0x0f */
|
||||
uint16_t orig_video_points; /* 0x10 */
|
||||
|
||||
/* VESA graphic mode -- linear frame buffer */
|
||||
uint16_t lfb_width; /* 0x12 */
|
||||
uint16_t lfb_height; /* 0x14 */
|
||||
uint16_t lfb_depth; /* 0x16 */
|
||||
uint32_t lfb_base; /* 0x18 */
|
||||
uint32_t lfb_size; /* 0x1c */
|
||||
uint16_t cl_magic; /* 0x20 */
|
||||
#define CL_MAGIC_VALUE 0xA33F
|
||||
uint16_t cl_offset; /* 0x22 */
|
||||
uint16_t lfb_linelength; /* 0x24 */
|
||||
uint8_t red_size; /* 0x26 */
|
||||
uint8_t red_pos; /* 0x27 */
|
||||
uint8_t green_size; /* 0x28 */
|
||||
uint8_t green_pos; /* 0x29 */
|
||||
uint8_t blue_size; /* 0x2a */
|
||||
uint8_t blue_pos; /* 0x2b */
|
||||
uint8_t rsvd_size; /* 0x2c */
|
||||
uint8_t rsvd_pos; /* 0x2d */
|
||||
uint16_t vesapm_seg; /* 0x2e */
|
||||
uint16_t vesapm_off; /* 0x30 */
|
||||
uint16_t pages; /* 0x32 */
|
||||
uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */
|
||||
|
||||
//struct apm_bios_info apm_bios_info; /* 0x40 */
|
||||
uint8_t apm_bios_info[0x40];
|
||||
//struct drive_info_struct drive_info; /* 0x80 */
|
||||
uint8_t drive_info[0x20];
|
||||
//struct sys_desc_table sys_desc_table; /* 0xa0 */
|
||||
uint8_t sys_desc_table[0x140];
|
||||
uint32_t alt_mem_k; /* 0x1e0 */
|
||||
uint8_t reserved5[4]; /* 0x1e4 */
|
||||
uint8_t e820_map_nr; /* 0x1e8 */
|
||||
uint8_t reserved6[9]; /* 0x1e9 */
|
||||
uint16_t mount_root_rdonly; /* 0x1f2 */
|
||||
uint8_t reserved7[4]; /* 0x1f4 */
|
||||
uint16_t ramdisk_flags; /* 0x1f8 */
|
||||
#define RAMDISK_IMAGE_START_MASK 0x07FF
|
||||
#define RAMDISK_PROMPT_FLAG 0x8000
|
||||
#define RAMDISK_LOAD_FLAG 0x4000
|
||||
uint8_t reserved8[2]; /* 0x1fa */
|
||||
uint16_t orig_root_dev; /* 0x1fc */
|
||||
uint8_t reserved9[1]; /* 0x1fe */
|
||||
uint8_t aux_device_info; /* 0x1ff */
|
||||
uint8_t reserved10[2]; /* 0x200 */
|
||||
uint8_t param_block_signature[4]; /* 0x202 */
|
||||
uint16_t param_block_version; /* 0x206 */
|
||||
uint8_t reserved11[8]; /* 0x208 */
|
||||
uint8_t loader_type; /* 0x210 */
|
||||
#define LOADER_TYPE_LOADLIN 1
|
||||
#define LOADER_TYPE_BOOTSECT_LOADER 2
|
||||
#define LOADER_TYPE_SYSLINUX 3
|
||||
#define LOADER_TYPE_ETHERBOOT 4
|
||||
#define LOADER_TYPE_KERNEL 5
|
||||
uint8_t loader_flags; /* 0x211 */
|
||||
uint8_t reserved12[2]; /* 0x212 */
|
||||
uint32_t kernel_start; /* 0x214 */
|
||||
uint32_t initrd_start; /* 0x218 */
|
||||
uint32_t initrd_size; /* 0x21c */
|
||||
uint8_t reserved12_5[8]; /* 0x220 */
|
||||
uint32_t cmd_line_ptr; /* 0x228 */
|
||||
uint8_t reserved13[164]; /* 0x22c */
|
||||
struct e820entry e820_map[E820MAX]; /* 0x2d0 */
|
||||
uint8_t reserved16[688]; /* 0x550 */
|
||||
#define COMMAND_LINE_SIZE 256
|
||||
/* Command line is copied here by 32-bit i386/kernel/head.S.
|
||||
* So I will follow the boot protocol, rather than putting it
|
||||
* directly here. --ts1 */
|
||||
uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */
|
||||
uint8_t reserved17[1792]; /* 0x900 - 0x1000 */
|
||||
};
|
||||
|
||||
uint64_t forced_memsize;
|
||||
|
||||
/* Load the first part the file and check if it's Linux */
|
||||
static uint32_t load_linux_header(struct linux_header *hdr)
|
||||
{
|
||||
int load_high;
|
||||
uint32_t kern_addr;
|
||||
|
||||
if (lfile_read(hdr, sizeof *hdr) != sizeof *hdr) {
|
||||
debug("Can't read Linux header\n");
|
||||
return 0;
|
||||
}
|
||||
if (hdr->boot_sector_magic != 0xaa55) {
|
||||
debug("Not a Linux kernel image\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Linux is found. Print some information */
|
||||
if (memcmp(hdr->header_magic, "HdrS", 4) != 0) {
|
||||
/* This may be floppy disk image or something.
|
||||
* Perform a simple (incomplete) sanity check. */
|
||||
if (hdr->setup_sects >= 16
|
||||
|| file_size() - (hdr->setup_sects<<9) >= 512<<10) {
|
||||
debug("This looks like a bootdisk image but not like Linux...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Possible very old Linux");
|
||||
/* This kernel does not even have a protocol version.
|
||||
* Force the value. */
|
||||
hdr->protocol_version = 0; /* pre-2.00 */
|
||||
} else
|
||||
printf("Found Linux");
|
||||
if (hdr->protocol_version >= 0x200 && hdr->kver_addr) {
|
||||
char kver[256];
|
||||
file_seek(hdr->kver_addr + 0x200);
|
||||
if (lfile_read(kver, sizeof kver) != 0) {
|
||||
kver[255] = 0;
|
||||
printf(" version %s", kver);
|
||||
}
|
||||
}
|
||||
debug(" (protocol %#x)", hdr->protocol_version);
|
||||
load_high = 0;
|
||||
if (hdr->protocol_version >= 0x200) {
|
||||
debug(" (loadflags %#x)", hdr->loadflags);
|
||||
load_high = hdr->loadflags & 1;
|
||||
}
|
||||
if (load_high) {
|
||||
printf(" bzImage");
|
||||
kern_addr = 0x100000;
|
||||
} else {
|
||||
printf(" zImage or Image");
|
||||
kern_addr = 0x1000;
|
||||
}
|
||||
printf(".\n");
|
||||
|
||||
return kern_addr;
|
||||
}
|
||||
|
||||
/* Set up parameters for 32-bit kernel */
|
||||
static void
|
||||
init_linux_params(struct linux_params *params, struct linux_header *hdr)
|
||||
{
|
||||
debug("Setting up paramters at %#lx\n", virt_to_phys(params));
|
||||
memset(params, 0, sizeof *params);
|
||||
|
||||
/* Copy some useful values from header */
|
||||
params->mount_root_rdonly = hdr->root_flags;
|
||||
params->orig_root_dev = hdr->root_dev;
|
||||
|
||||
/* Video parameters.
|
||||
* This assumes we have VGA in standard 80x25 text mode,
|
||||
* just like our vga.c does.
|
||||
* Cursor position is filled later to allow some more printf's. */
|
||||
params->orig_video_mode = 3;
|
||||
params->orig_video_cols = 80;
|
||||
params->orig_video_lines = 25;
|
||||
params->orig_video_isVGA = 1;
|
||||
params->orig_video_points = 16;
|
||||
|
||||
params->loader_type = 0xff; /* Unregistered Linux loader */
|
||||
}
|
||||
|
||||
/* Memory map */
|
||||
static void
|
||||
set_memory_size(struct linux_params *params, struct sys_info *info)
|
||||
{
|
||||
int i;
|
||||
uint64_t end;
|
||||
uint32_t ramtop = 0;
|
||||
struct e820entry *linux_map;
|
||||
struct memrange *filo_map;
|
||||
|
||||
linux_map = params->e820_map;
|
||||
filo_map = info->memrange;
|
||||
for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) {
|
||||
if (i < E820MAX) {
|
||||
/* Convert to BIOS e820 style */
|
||||
linux_map->addr = filo_map->base;
|
||||
linux_map->size = filo_map->size;
|
||||
linux_map->type = E820_RAM;
|
||||
debug("%016Lx - %016Lx\n", linux_map->addr,
|
||||
linux_map->addr + linux_map->size);
|
||||
params->e820_map_nr = i+1;
|
||||
}
|
||||
|
||||
/* Find out top of RAM. XXX This ignores hole above 1MB */
|
||||
end = filo_map->base + filo_map->size;
|
||||
if (end < (1ULL << 32)) { /* don't count memory above 4GB */
|
||||
if (end > ramtop)
|
||||
ramtop = (uint32_t) end;
|
||||
}
|
||||
}
|
||||
debug("ramtop=%#x\n", ramtop);
|
||||
/* Size of memory above 1MB in KB */
|
||||
params->alt_mem_k = (ramtop - (1<<20)) >> 10;
|
||||
/* old style, 64MB max */
|
||||
if (ramtop >= (64<<20))
|
||||
params->ext_mem_k = (63<<10);
|
||||
else
|
||||
params->ext_mem_k = params->alt_mem_k;
|
||||
debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse command line
|
||||
* Some parameters, like initrd=<file>, are not passed to kernel,
|
||||
* we are responsible to process them.
|
||||
* Parameters for kernel are copied to kern_cmdline. Returns name of initrd.
|
||||
*/
|
||||
static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline)
|
||||
{
|
||||
const char *start, *sep, *end, *val;
|
||||
char name[64];
|
||||
unsigned long len;
|
||||
int k_len;
|
||||
int to_kern;
|
||||
char *initrd = 0;
|
||||
int toolong = 0;
|
||||
|
||||
forced_memsize = 0;
|
||||
|
||||
if (!orig_cmdline) {
|
||||
*kern_cmdline = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
k_len = 0;
|
||||
debug("original command line: \"%s\"\n", orig_cmdline);
|
||||
debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline));
|
||||
|
||||
start = orig_cmdline;
|
||||
while (*start == ' ')
|
||||
start++;
|
||||
while (*start) {
|
||||
end = strchr(start, ' ');
|
||||
if (!end)
|
||||
end = start + strlen(start);
|
||||
sep = strchr(start, '=');
|
||||
if (!sep || sep > end)
|
||||
sep = end;
|
||||
len = sep - start;
|
||||
if (len >= sizeof(name))
|
||||
len = sizeof(name) - 1;
|
||||
memcpy(name, start, len);
|
||||
name[len] = 0;
|
||||
|
||||
if (*sep == '=') {
|
||||
val = sep + 1;
|
||||
len = end - val;
|
||||
} else {
|
||||
val = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/* Only initrd= and mem= are handled here. vga= is not,
|
||||
* which I believe is a paramter to the realmode part of Linux,
|
||||
* which we don't execute. */
|
||||
if (strcmp(name, "initrd") == 0) {
|
||||
if (!val)
|
||||
printf("Missing filename to initrd parameter\n");
|
||||
else {
|
||||
initrd = malloc(len + 1);
|
||||
memcpy(initrd, val, len);
|
||||
initrd[len] = 0;
|
||||
debug("initrd=%s\n", initrd);
|
||||
}
|
||||
/* Don't pass this to kernel */
|
||||
to_kern = 0;
|
||||
} else if (strcmp(name, "mem") == 0) {
|
||||
if (!val)
|
||||
printf("Missing value for mem parameter\n");
|
||||
else {
|
||||
forced_memsize = strtoull_with_suffix(val, (char**)&val, 0);
|
||||
if (forced_memsize == 0)
|
||||
printf("Invalid mem option, ignored\n");
|
||||
if (val != end) {
|
||||
printf("Garbage after mem=<size>, ignored\n");
|
||||
forced_memsize = 0;
|
||||
}
|
||||
debug("mem=%Lu\n", forced_memsize);
|
||||
}
|
||||
/* mem= is for both loader and kernel */
|
||||
to_kern = 1;
|
||||
} else
|
||||
to_kern = 1;
|
||||
|
||||
if (to_kern) {
|
||||
/* Copy to kernel command line buffer */
|
||||
if (k_len != 0)
|
||||
kern_cmdline[k_len++] = ' '; /* put separator */
|
||||
len = end - start;
|
||||
if (k_len + len >= COMMAND_LINE_SIZE) {
|
||||
len = COMMAND_LINE_SIZE - k_len - 1;
|
||||
if (!toolong) {
|
||||
printf("Kernel command line is too long; truncated to "
|
||||
"%d bytes\n", COMMAND_LINE_SIZE-1);
|
||||
toolong = 1;
|
||||
}
|
||||
}
|
||||
memcpy(kern_cmdline + k_len, start, len);
|
||||
k_len += len;
|
||||
}
|
||||
|
||||
start = end;
|
||||
while (*start == ' ')
|
||||
start++;
|
||||
}
|
||||
kern_cmdline[k_len] = 0;
|
||||
debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline);
|
||||
|
||||
return initrd;
|
||||
}
|
||||
|
||||
/* Set command line location */
|
||||
static void set_command_line_loc(struct linux_params *params,
|
||||
struct linux_header *hdr)
|
||||
{
|
||||
if (hdr->protocol_version >= 0x202) {
|
||||
/* new style */
|
||||
params->cmd_line_ptr = COMMAND_LINE_LOC;
|
||||
} else {
|
||||
/* old style */
|
||||
params->cl_magic = CL_MAGIC_VALUE;
|
||||
params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load 32-bit part of kernel */
|
||||
static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr)
|
||||
{
|
||||
uint32_t kern_offset, kern_size;
|
||||
|
||||
if (hdr->setup_sects == 0)
|
||||
hdr->setup_sects = 4;
|
||||
kern_offset = (hdr->setup_sects + 1) * 512;
|
||||
file_seek(kern_offset);
|
||||
kern_size = file_size() - kern_offset;
|
||||
debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size);
|
||||
|
||||
#if 0
|
||||
if (using_devsize) {
|
||||
printf("Attempt to load up to end of device as kernel; "
|
||||
"specify the image size\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("Loading kernel... ");
|
||||
if (lfile_read(phys_to_virt(kern_addr), kern_size) != kern_size) {
|
||||
printf("Can't read kernel\n");
|
||||
return 0;
|
||||
}
|
||||
printf("ok\n");
|
||||
|
||||
return kern_size;
|
||||
}
|
||||
|
||||
static int load_initrd(struct linux_header *hdr, struct sys_info *info,
|
||||
uint32_t kern_end, struct linux_params *params, const char *initrd_file)
|
||||
{
|
||||
uint32_t max;
|
||||
uint32_t start, end, size;
|
||||
uint64_t forced;
|
||||
|
||||
if (!file_open(initrd_file)) {
|
||||
printf("Can't open initrd: %s\n", initrd_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (using_devsize) {
|
||||
printf("Attempt to load up to end of device as initrd; "
|
||||
"specify the image size\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
size = file_size();
|
||||
|
||||
|
||||
/* Find out the kernel's restriction on how high the initrd can be
|
||||
* placed */
|
||||
if (hdr->protocol_version >= 0x203)
|
||||
max = hdr->initrd_addr_max;
|
||||
else
|
||||
max = 0x38000000; /* Hardcoded value for older kernels */
|
||||
|
||||
/* FILO itself is at the top of RAM. (relocated)
|
||||
* So, try putting initrd just below us. */
|
||||
end = virt_to_phys(_start);
|
||||
if (end > max)
|
||||
end = max;
|
||||
|
||||
/* If "mem=" option is given, we have to put the initrd within
|
||||
* the specified range. */
|
||||
if (forced_memsize) {
|
||||
forced = forced_memsize;
|
||||
if (forced > max)
|
||||
forced = max;
|
||||
/* If the "mem=" is lower, it's easy */
|
||||
if (forced <= end)
|
||||
end = forced;
|
||||
else {
|
||||
/* Otherwise, see if we can put it above us */
|
||||
if (virt_to_phys(_end) + size <= forced)
|
||||
end = forced; /* Ok */
|
||||
}
|
||||
}
|
||||
|
||||
start = end - size;
|
||||
start &= ~0xfff; /* page align */
|
||||
end = start + size;
|
||||
|
||||
debug("start=%#x end=%#x\n", start, end);
|
||||
|
||||
if (start < kern_end) {
|
||||
printf("Initrd is too big to fit in memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Loading initrd... ");
|
||||
if (lfile_read(phys_to_virt(start), size) != size) {
|
||||
printf("Can't read initrd\n");
|
||||
return -1;
|
||||
}
|
||||
printf("ok\n");
|
||||
|
||||
params->initrd_start = start;
|
||||
params->initrd_size = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hardware_setup(void)
|
||||
{
|
||||
/* Disable nmi */
|
||||
outb(0x80, 0x70);
|
||||
|
||||
/* Make sure any coprocessor is properly reset.. */
|
||||
outb(0, 0xf0);
|
||||
outb(0, 0xf1);
|
||||
|
||||
/* we're getting screwed again and again by this problem of the 8259.
|
||||
* so we're going to leave this lying around for inclusion into
|
||||
* crt0.S on an as-needed basis.
|
||||
*
|
||||
* well, that went ok, I hope. Now we have to reprogram the interrupts :-(
|
||||
* we put them right after the intel-reserved hardware interrupts, at
|
||||
* int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
|
||||
* messed this up with the original PC, and they haven't been able to
|
||||
* rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
|
||||
* which is used for the internal hardware interrupts as well. We just
|
||||
* have to reprogram the 8259's, and it isn't fun.
|
||||
*/
|
||||
|
||||
outb(0x11, 0x20); /* initialization sequence to 8259A-1 */
|
||||
outb(0x11, 0xA0); /* and to 8259A-2 */
|
||||
|
||||
outb(0x20, 0x21); /* start of hardware int's (0x20) */
|
||||
outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */
|
||||
|
||||
outb(0x04, 0x21); /* 8259-1 is master */
|
||||
outb(0x02, 0xA1); /* 8259-2 is slave */
|
||||
|
||||
outb(0x01, 0x21); /* 8086 mode for both */
|
||||
outb(0x01, 0xA1);
|
||||
|
||||
outb(0xFF, 0xA1); /* mask off all interrupts for now */
|
||||
outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */
|
||||
}
|
||||
|
||||
/* Start Linux */
|
||||
static int start_linux(uint32_t kern_addr, struct linux_params *params)
|
||||
{
|
||||
struct context *ctx;
|
||||
//extern int cursor_x, cursor_y;
|
||||
|
||||
ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
|
||||
|
||||
/* Entry point */
|
||||
ctx->pc = kern_addr;
|
||||
ctx->npc = kern_addr + 4;
|
||||
|
||||
debug("pc=%#x\n", kern_addr);
|
||||
printf("Jumping to entry point...\n");
|
||||
|
||||
#ifdef VGA_CONSOLE
|
||||
/* Update VGA cursor position.
|
||||
* This must be here because the printf changes the value! */
|
||||
params->orig_x = cursor_x;
|
||||
params->orig_y = cursor_y;
|
||||
#endif
|
||||
|
||||
/* Go... */
|
||||
ctx = switch_to(ctx);
|
||||
|
||||
/* It's impossible but... */
|
||||
printf("Returned with o0=%#x\n", ctx->regs[REG_O0]);
|
||||
|
||||
return ctx->regs[REG_O0];
|
||||
}
|
||||
|
||||
int linux_load(struct sys_info *info, const char *file, const char *cmdline)
|
||||
{
|
||||
struct linux_header hdr;
|
||||
struct linux_params *params;
|
||||
uint32_t kern_addr, kern_size;
|
||||
char *initrd_file = 0;
|
||||
|
||||
if (!file_open(file))
|
||||
return -1;
|
||||
|
||||
kern_addr = load_linux_header(&hdr);
|
||||
if (kern_addr == 0) {
|
||||
file_close();
|
||||
return LOADER_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
params = phys_to_virt(LINUX_PARAM_LOC);
|
||||
init_linux_params(params, &hdr);
|
||||
set_memory_size(params, info);
|
||||
initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC));
|
||||
set_command_line_loc(params, &hdr);
|
||||
|
||||
kern_size = load_linux_kernel(&hdr, kern_addr);
|
||||
if (kern_size == 0) {
|
||||
if (initrd_file)
|
||||
free(initrd_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (initrd_file) {
|
||||
if (load_initrd(&hdr, info, kern_addr+kern_size, params, initrd_file)
|
||||
!= 0) {
|
||||
free(initrd_file);
|
||||
return -1;
|
||||
}
|
||||
free(initrd_file);
|
||||
}
|
||||
|
||||
hardware_setup();
|
||||
|
||||
start_linux(kern_addr, params);
|
||||
return 0;
|
||||
}
|
||||
64
arch/sparc64/loadfs.c
Normal file
64
arch/sparc64/loadfs.c
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/kernel.h"
|
||||
#include "libc/diskio.h"
|
||||
#include "loadfs.h"
|
||||
|
||||
static int load_fd=-1;
|
||||
|
||||
int file_open(const char *filename)
|
||||
{
|
||||
load_fd=open_io(filename);
|
||||
if(load_fd >= 0)
|
||||
seek_io(load_fd, 0);
|
||||
return load_fd>-1;
|
||||
}
|
||||
|
||||
void file_close(void)
|
||||
{
|
||||
if(load_fd==-1)
|
||||
return;
|
||||
|
||||
close_io(load_fd);
|
||||
load_fd=-1;
|
||||
}
|
||||
|
||||
int lfile_read(void *buf, unsigned long len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (load_fd >= 0)
|
||||
ret=read_io(load_fd, buf, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int file_seek(unsigned long offset)
|
||||
{
|
||||
if (load_fd >= 0)
|
||||
return seek_io(load_fd, offset);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned long file_size(void)
|
||||
{
|
||||
llong fpos, fsize;
|
||||
|
||||
if (load_fd < 0)
|
||||
return 0;
|
||||
|
||||
/* save current position */
|
||||
fpos=tell(load_fd);
|
||||
|
||||
/* go to end of file and get position */
|
||||
seek_io(load_fd, -1);
|
||||
fsize=tell(load_fd);
|
||||
|
||||
/* go back to old position */
|
||||
seek_io(load_fd, 0);
|
||||
seek_io(load_fd, fpos);
|
||||
|
||||
return fsize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
7
arch/sparc64/loadfs.h
Normal file
7
arch/sparc64/loadfs.h
Normal file
@@ -0,0 +1,7 @@
|
||||
int file_open(const char *filename);
|
||||
int lfile_read(void *buf, unsigned long len);
|
||||
int file_seek(unsigned long offset);
|
||||
unsigned long file_size(void);
|
||||
|
||||
|
||||
|
||||
20
arch/sparc64/lsu.h
Normal file
20
arch/sparc64/lsu.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* $Id: lsu.h,v 1.2 1997/04/04 00:50:22 davem Exp $ */
|
||||
#ifndef _SPARC64_LSU_H
|
||||
#define _SPARC64_LSU_H
|
||||
|
||||
#include "const.h"
|
||||
|
||||
/* LSU Control Register */
|
||||
#define LSU_CONTROL_PM _AC(0x000001fe00000000,UL) /* Phys-watchpoint byte mask*/
|
||||
#define LSU_CONTROL_VM _AC(0x00000001fe000000,UL) /* Virt-watchpoint byte mask*/
|
||||
#define LSU_CONTROL_PR _AC(0x0000000001000000,UL) /* Phys-rd watchpoint enable*/
|
||||
#define LSU_CONTROL_PW _AC(0x0000000000800000,UL) /* Phys-wr watchpoint enable*/
|
||||
#define LSU_CONTROL_VR _AC(0x0000000000400000,UL) /* Virt-rd watchpoint enable*/
|
||||
#define LSU_CONTROL_VW _AC(0x0000000000200000,UL) /* Virt-wr watchpoint enable*/
|
||||
#define LSU_CONTROL_FM _AC(0x00000000000ffff0,UL) /* Parity mask enables. */
|
||||
#define LSU_CONTROL_DM _AC(0x0000000000000008,UL) /* Data MMU enable. */
|
||||
#define LSU_CONTROL_IM _AC(0x0000000000000004,UL) /* Instruction MMU enable. */
|
||||
#define LSU_CONTROL_DC _AC(0x0000000000000002,UL) /* Data cache enable. */
|
||||
#define LSU_CONTROL_IC _AC(0x0000000000000001,UL) /* Instruction cache enable.*/
|
||||
|
||||
#endif /* !(_SPARC64_LSU_H) */
|
||||
125
arch/sparc64/multiboot.c
Normal file
125
arch/sparc64/multiboot.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/* Support for Multiboot */
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "asm/io.h"
|
||||
#include "sys_info.h"
|
||||
#include "multiboot.h"
|
||||
|
||||
#define printf printk
|
||||
#ifdef CONFIG_DEBUG_BOOT
|
||||
#define debug printk
|
||||
#else
|
||||
#define debug(x...)
|
||||
#endif
|
||||
|
||||
struct mbheader {
|
||||
unsigned int magic, flags, checksum;
|
||||
};
|
||||
const struct mbheader multiboot_header
|
||||
__attribute__((section (".hdr"))) =
|
||||
{
|
||||
MULTIBOOT_HEADER_MAGIC,
|
||||
MULTIBOOT_HEADER_FLAGS,
|
||||
-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
||||
};
|
||||
|
||||
/* Multiboot information structure, provided by loader to us */
|
||||
|
||||
struct multiboot_mmap {
|
||||
unsigned entry_size;
|
||||
unsigned base_lo, base_hi;
|
||||
unsigned size_lo, size_hi;
|
||||
unsigned type;
|
||||
};
|
||||
|
||||
#define MULTIBOOT_MEM_VALID 0x01
|
||||
#define MULTIBOOT_BOOT_DEV_VALID 0x02
|
||||
#define MULTIBOOT_CMDLINE_VALID 0x04
|
||||
#define MULTIBOOT_MODS_VALID 0x08
|
||||
#define MULTIBOOT_AOUT_SYMS_VALID 0x10
|
||||
#define MULTIBOOT_ELF_SYMS_VALID 0x20
|
||||
#define MULTIBOOT_MMAP_VALID 0x40
|
||||
|
||||
void collect_multiboot_info(struct sys_info *info);
|
||||
void collect_multiboot_info(struct sys_info *info)
|
||||
{
|
||||
struct multiboot_info *mbinfo;
|
||||
struct multiboot_mmap *mbmem;
|
||||
unsigned mbcount, mbaddr;
|
||||
unsigned int i;
|
||||
struct memrange *mmap;
|
||||
int mmap_count;
|
||||
module_t *mod;
|
||||
|
||||
if (info->boot_type != 0x2BADB002)
|
||||
return;
|
||||
|
||||
debug("Using Multiboot information at %#lx\n", info->boot_data);
|
||||
|
||||
mbinfo = phys_to_virt(info->boot_data);
|
||||
|
||||
if (mbinfo->mods_count != 1) {
|
||||
printf("Multiboot: no dictionary\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mod = (module_t *) mbinfo->mods_addr;
|
||||
info->dict_start=(unsigned long *)mod->mod_start;
|
||||
info->dict_end=(unsigned long *)mod->mod_end;
|
||||
|
||||
if (mbinfo->flags & MULTIBOOT_MMAP_VALID) {
|
||||
/* convert mmap records */
|
||||
mbmem = phys_to_virt(mbinfo->mmap_addr);
|
||||
mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4);
|
||||
mmap = malloc(mbcount * sizeof(struct memrange));
|
||||
mmap_count = 0;
|
||||
mbaddr = mbinfo->mmap_addr;
|
||||
for (i = 0; i < mbcount; i++) {
|
||||
mbmem = phys_to_virt(mbaddr);
|
||||
debug("%08x%08x %08x%08x (%d)\n",
|
||||
mbmem->base_hi,
|
||||
mbmem->base_lo,
|
||||
mbmem->size_hi,
|
||||
mbmem->size_lo,
|
||||
mbmem->type);
|
||||
if (mbmem->type == 1) { /* Only normal RAM */
|
||||
mmap[mmap_count].base = mbmem->base_lo
|
||||
+ (((unsigned long long) mbmem->base_hi) << 32);
|
||||
mmap[mmap_count].size = mbmem->size_lo
|
||||
+ (((unsigned long long) mbmem->size_hi) << 32);
|
||||
mmap_count++;
|
||||
}
|
||||
mbaddr += mbmem->entry_size + 4;
|
||||
if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length)
|
||||
break;
|
||||
}
|
||||
/* simple sanity check - there should be at least 2 RAM segments
|
||||
* (base 640k and extended) */
|
||||
if (mmap_count >= 2)
|
||||
goto got_it;
|
||||
|
||||
printf("Multiboot mmap is broken\n");
|
||||
free(mmap);
|
||||
/* fall back to mem_lower/mem_upper */
|
||||
}
|
||||
|
||||
if (mbinfo->flags & MULTIBOOT_MEM_VALID) {
|
||||
/* use mem_lower and mem_upper */
|
||||
mmap_count = 2;
|
||||
mmap = malloc(2 * sizeof(*mmap));
|
||||
mmap[0].base = 0;
|
||||
mmap[0].size = mbinfo->mem_lower << 10;
|
||||
mmap[1].base = 1 << 20; /* 1MB */
|
||||
mmap[1].size = mbinfo->mem_upper << 10;
|
||||
goto got_it;
|
||||
}
|
||||
|
||||
printf("Can't get memory information from Multiboot\n");
|
||||
return;
|
||||
|
||||
got_it:
|
||||
info->memrange = mmap;
|
||||
info->n_memranges = mmap_count;
|
||||
|
||||
return;
|
||||
}
|
||||
96
arch/sparc64/multiboot.h
Normal file
96
arch/sparc64/multiboot.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* multiboot.h
|
||||
* tag: header for multiboot
|
||||
*
|
||||
* Copyright (C) 2003-2004 Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
/* magic number for multiboot header */
|
||||
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
|
||||
|
||||
/* flags for multiboot header */
|
||||
#define MULTIBOOT_HEADER_FLAGS 0x00010003
|
||||
|
||||
/* magic number passed by multiboot-compliant boot loader. */
|
||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
|
||||
|
||||
/* The size of our stack (8KB). */
|
||||
#define STACK_SIZE 0x2000
|
||||
|
||||
/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
|
||||
#ifdef HAVE_ASM_USCORE
|
||||
# define EXT_C(sym) _ ## sym
|
||||
#else
|
||||
# define EXT_C(sym) sym
|
||||
#endif
|
||||
|
||||
#ifndef ASM
|
||||
/* We don't want these declarations in boot.S */
|
||||
|
||||
/* multiboot header */
|
||||
typedef struct multiboot_header {
|
||||
unsigned long magic;
|
||||
unsigned long flags;
|
||||
unsigned long checksum;
|
||||
unsigned long header_addr;
|
||||
unsigned long load_addr;
|
||||
unsigned long load_end_addr;
|
||||
unsigned long bss_end_addr;
|
||||
unsigned long entry_addr;
|
||||
} multiboot_header_t;
|
||||
|
||||
/* symbol table for a.out */
|
||||
typedef struct aout_symbol_table {
|
||||
unsigned long tabsize;
|
||||
unsigned long strsize;
|
||||
unsigned long addr;
|
||||
unsigned long reserved;
|
||||
} aout_symbol_table_t;
|
||||
|
||||
/* section header table for ELF */
|
||||
typedef struct elf_section_header_table {
|
||||
unsigned long num;
|
||||
unsigned long size;
|
||||
unsigned long addr;
|
||||
unsigned long shndx;
|
||||
} elf_section_header_table_t;
|
||||
|
||||
/* multiboot information */
|
||||
typedef struct multiboot_info {
|
||||
unsigned long flags;
|
||||
unsigned long mem_lower;
|
||||
unsigned long mem_upper;
|
||||
unsigned long boot_device;
|
||||
unsigned long cmdline;
|
||||
unsigned long mods_count;
|
||||
unsigned long mods_addr;
|
||||
union {
|
||||
aout_symbol_table_t aout_sym;
|
||||
elf_section_header_table_t elf_sec;
|
||||
} u;
|
||||
unsigned long mmap_length;
|
||||
unsigned long mmap_addr;
|
||||
} multiboot_info_t;
|
||||
|
||||
/* module structure */
|
||||
typedef struct module {
|
||||
unsigned long mod_start;
|
||||
unsigned long mod_end;
|
||||
unsigned long string;
|
||||
unsigned long reserved;
|
||||
} module_t;
|
||||
|
||||
/* memory map. Be careful that the offset 0 is base_addr_low
|
||||
but no size. */
|
||||
typedef struct memory_map {
|
||||
unsigned long size;
|
||||
unsigned long base_addr_low;
|
||||
unsigned long base_addr_high;
|
||||
unsigned long length_low;
|
||||
unsigned long length_high;
|
||||
unsigned long type;
|
||||
} memory_map_t;
|
||||
|
||||
#endif /* ! ASM */
|
||||
115
arch/sparc64/openbios.c
Normal file
115
arch/sparc64/openbios.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/* tag: openbios forth environment, executable code
|
||||
*
|
||||
* Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/bindings.h"
|
||||
#include "openbios/drivers.h"
|
||||
#include "asm/types.h"
|
||||
#include "dict.h"
|
||||
#include "openbios/kernel.h"
|
||||
#include "openbios/stack.h"
|
||||
#include "sys_info.h"
|
||||
#include "openbios.h"
|
||||
|
||||
void boot(void);
|
||||
|
||||
static unsigned char intdict[256 * 1024];
|
||||
|
||||
// XXX
|
||||
void arch_nvram_put()
|
||||
{
|
||||
}
|
||||
|
||||
void arch_nvram_get()
|
||||
{
|
||||
}
|
||||
|
||||
int arch_nvram_size;
|
||||
|
||||
static void init_memory(void)
|
||||
{
|
||||
|
||||
/* push start and end of available memory to the stack
|
||||
* so that the forth word QUIT can initialize memory
|
||||
* management. For now we use hardcoded memory between
|
||||
* 0x10000 and 0x9ffff (576k). If we need more memory
|
||||
* than that we have serious bloat.
|
||||
*/
|
||||
|
||||
PUSH((unsigned int)&_heap);
|
||||
PUSH((unsigned int)&_eheap);
|
||||
}
|
||||
|
||||
static void
|
||||
arch_init( void )
|
||||
{
|
||||
void setup_timers(void);
|
||||
|
||||
modules_init();
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
|
||||
init_video();
|
||||
#endif
|
||||
|
||||
nvram_init();
|
||||
device_end();
|
||||
|
||||
bind_func("platform-boot", boot );
|
||||
}
|
||||
|
||||
int openbios(void)
|
||||
{
|
||||
extern struct sys_info sys_info;
|
||||
|
||||
#ifdef CONFIG_DEBUG_CONSOLE
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
|
||||
uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED);
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUG_CONSOLE_VGA
|
||||
video_init();
|
||||
#endif
|
||||
/* Clear the screen. */
|
||||
cls();
|
||||
printk("OpenBIOS for Sparc64\n");
|
||||
#endif
|
||||
|
||||
collect_sys_info(&sys_info);
|
||||
|
||||
dict=intdict;
|
||||
load_dictionary((char *)sys_info.dict_start,
|
||||
(unsigned long)sys_info.dict_end
|
||||
- (unsigned long)sys_info.dict_start);
|
||||
|
||||
#ifdef CONFIG_DEBUG_BOOT
|
||||
printk("forth started.\n");
|
||||
printk("initializing memory...");
|
||||
#endif
|
||||
|
||||
init_memory();
|
||||
|
||||
#ifdef CONFIG_DEBUG_BOOT
|
||||
printk("done\n");
|
||||
#endif
|
||||
|
||||
PUSH_xt( bind_noname_func(arch_init) );
|
||||
fword("PREPOST-initializer");
|
||||
|
||||
PC = (ucell)findword("initialize-of");
|
||||
|
||||
if (!PC) {
|
||||
printk("panic: no dictionary entry point.\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef CONFIG_DEBUG_DICTIONARY
|
||||
printk("done (%d bytes).\n", dicthead);
|
||||
printk("Jumping to dictionary...\n");
|
||||
#endif
|
||||
|
||||
enterforth((xt_t)PC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
29
arch/sparc64/openbios.h
Normal file
29
arch/sparc64/openbios.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Creation Date: <2004/01/15 16:14:05 samuel>
|
||||
* Time-stamp: <2004/01/15 16:14:05 samuel>
|
||||
*
|
||||
* <openbios.h>
|
||||
*
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _H_OPENBIOS
|
||||
#define _H_OPENBIOS
|
||||
|
||||
int openbios(void);
|
||||
|
||||
/* console.c */
|
||||
extern void cls(void);
|
||||
#ifdef CONFIG_DEBUG_CONSOLE
|
||||
extern int uart_init(int port, unsigned long speed);
|
||||
extern void video_init(void);
|
||||
#endif
|
||||
|
||||
#endif /* _H_OPENBIOS */
|
||||
281
arch/sparc64/openprom.h
Normal file
281
arch/sparc64/openprom.h
Normal file
@@ -0,0 +1,281 @@
|
||||
/* $Id: openprom.h,v 1.9 2001/03/16 10:22:02 davem Exp $ */
|
||||
#ifndef __SPARC64_OPENPROM_H
|
||||
#define __SPARC64_OPENPROM_H
|
||||
|
||||
/* openprom.h: Prom structures and defines for access to the OPENBOOT
|
||||
* prom routines and data areas.
|
||||
*
|
||||
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
/* V0 prom device operations. */
|
||||
struct linux_dev_v0_funcs {
|
||||
int (*v0_devopen)(char *device_str);
|
||||
int (*v0_devclose)(int dev_desc);
|
||||
int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
|
||||
int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
|
||||
int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
|
||||
int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
|
||||
int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
|
||||
int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
|
||||
int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
|
||||
};
|
||||
|
||||
/* V2 and later prom device operations. */
|
||||
struct linux_dev_v2_funcs {
|
||||
int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
|
||||
char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
|
||||
void (*v2_dumb_mem_free)(char *va, unsigned sz);
|
||||
|
||||
/* To map devices into virtual I/O space. */
|
||||
char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
|
||||
void (*v2_dumb_munmap)(char *virta, unsigned size);
|
||||
|
||||
int (*v2_dev_open)(char *devpath);
|
||||
void (*v2_dev_close)(int d);
|
||||
int (*v2_dev_read)(int d, char *buf, int nbytes);
|
||||
int (*v2_dev_write)(int d, char *buf, int nbytes);
|
||||
int (*v2_dev_seek)(int d, int hi, int lo);
|
||||
|
||||
/* Never issued (multistage load support) */
|
||||
void (*v2_wheee2)(void);
|
||||
void (*v2_wheee3)(void);
|
||||
};
|
||||
|
||||
struct linux_mlist_v0 {
|
||||
struct linux_mlist_v0 *theres_more;
|
||||
unsigned start_adr;
|
||||
unsigned num_bytes;
|
||||
};
|
||||
|
||||
struct linux_mem_v0 {
|
||||
struct linux_mlist_v0 **v0_totphys;
|
||||
struct linux_mlist_v0 **v0_prommap;
|
||||
struct linux_mlist_v0 **v0_available; /* What we can use */
|
||||
};
|
||||
|
||||
/* Arguments sent to the kernel from the boot prompt. */
|
||||
struct linux_arguments_v0 {
|
||||
char *argv[8];
|
||||
char args[100];
|
||||
char boot_dev[2];
|
||||
int boot_dev_ctrl;
|
||||
int boot_dev_unit;
|
||||
int dev_partition;
|
||||
char *kernel_file_name;
|
||||
void *aieee1; /* XXX */
|
||||
};
|
||||
|
||||
/* V2 and up boot things. */
|
||||
struct linux_bootargs_v2 {
|
||||
char **bootpath;
|
||||
char **bootargs;
|
||||
int *fd_stdin;
|
||||
int *fd_stdout;
|
||||
};
|
||||
|
||||
/* The top level PROM vector. */
|
||||
struct linux_romvec {
|
||||
/* Version numbers. */
|
||||
unsigned int pv_magic_cookie;
|
||||
unsigned int pv_romvers;
|
||||
unsigned int pv_plugin_revision;
|
||||
unsigned int pv_printrev;
|
||||
|
||||
/* Version 0 memory descriptors. */
|
||||
struct linux_mem_v0 pv_v0mem;
|
||||
|
||||
/* Node operations. */
|
||||
struct linux_nodeops *pv_nodeops;
|
||||
|
||||
char **pv_bootstr;
|
||||
struct linux_dev_v0_funcs pv_v0devops;
|
||||
|
||||
char *pv_stdin;
|
||||
char *pv_stdout;
|
||||
#define PROMDEV_KBD 0 /* input from keyboard */
|
||||
#define PROMDEV_SCREEN 0 /* output to screen */
|
||||
#define PROMDEV_TTYA 1 /* in/out to ttya */
|
||||
#define PROMDEV_TTYB 2 /* in/out to ttyb */
|
||||
|
||||
/* Blocking getchar/putchar. NOT REENTRANT! (grr) */
|
||||
int (*pv_getchar)(void);
|
||||
void (*pv_putchar)(int ch);
|
||||
|
||||
/* Non-blocking variants. */
|
||||
int (*pv_nbgetchar)(void);
|
||||
int (*pv_nbputchar)(int ch);
|
||||
|
||||
void (*pv_putstr)(char *str, int len);
|
||||
|
||||
/* Miscellany. */
|
||||
void (*pv_reboot)(char *bootstr);
|
||||
void (*pv_printf)(__const__ char *fmt, ...);
|
||||
void (*pv_abort)(void);
|
||||
__volatile__ int *pv_ticks;
|
||||
void (*pv_halt)(void);
|
||||
void (**pv_synchook)(void);
|
||||
|
||||
/* Evaluate a forth string, not different proto for V0 and V2->up. */
|
||||
union {
|
||||
void (*v0_eval)(int len, char *str);
|
||||
void (*v2_eval)(char *str);
|
||||
} pv_fortheval;
|
||||
|
||||
struct linux_arguments_v0 **pv_v0bootargs;
|
||||
|
||||
/* Get ether address. */
|
||||
unsigned int (*pv_enaddr)(int d, char *enaddr);
|
||||
|
||||
struct linux_bootargs_v2 pv_v2bootargs;
|
||||
struct linux_dev_v2_funcs pv_v2devops;
|
||||
|
||||
int filler[15];
|
||||
|
||||
/* This one is sun4c/sun4 only. */
|
||||
void (*pv_setctxt)(int ctxt, char *va, int pmeg);
|
||||
|
||||
/* Prom version 3 Multiprocessor routines. This stuff is crazy.
|
||||
* No joke. Calling these when there is only one cpu probably
|
||||
* crashes the machine, have to test this. :-)
|
||||
*/
|
||||
|
||||
/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
|
||||
* 'thiscontext' executing at address 'prog_counter'
|
||||
*/
|
||||
int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
|
||||
int thiscontext, char *prog_counter);
|
||||
|
||||
/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
|
||||
* until a resume cpu call is made.
|
||||
*/
|
||||
int (*v3_cpustop)(unsigned int whichcpu);
|
||||
|
||||
/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
|
||||
* resume cpu call is made.
|
||||
*/
|
||||
int (*v3_cpuidle)(unsigned int whichcpu);
|
||||
|
||||
/* v3_cpuresume() will resume processor 'whichcpu' executing
|
||||
* starting with whatever 'pc' and 'npc' were left at the
|
||||
* last 'idle' or 'stop' call.
|
||||
*/
|
||||
int (*v3_cpuresume)(unsigned int whichcpu);
|
||||
};
|
||||
|
||||
/* Routines for traversing the prom device tree. */
|
||||
struct linux_nodeops {
|
||||
int (*no_nextnode)(int node);
|
||||
int (*no_child)(int node);
|
||||
int (*no_proplen)(int node, char *name);
|
||||
int (*no_getprop)(int node, char *name, char *val);
|
||||
int (*no_setprop)(int node, char *name, char *val, int len);
|
||||
char * (*no_nextprop)(int node, char *name);
|
||||
};
|
||||
|
||||
/* More fun PROM structures for device probing. */
|
||||
#define PROMREG_MAX 16
|
||||
#define PROMVADDR_MAX 16
|
||||
#define PROMINTR_MAX 15
|
||||
|
||||
struct linux_prom_registers {
|
||||
unsigned which_io; /* hi part of physical address */
|
||||
unsigned phys_addr; /* The physical address of this register */
|
||||
int reg_size; /* How many bytes does this register take up? */
|
||||
};
|
||||
|
||||
struct linux_prom64_registers {
|
||||
long phys_addr;
|
||||
long reg_size;
|
||||
};
|
||||
|
||||
struct linux_prom_irqs {
|
||||
int pri; /* IRQ priority */
|
||||
int vector; /* This is foobar, what does it do? */
|
||||
};
|
||||
|
||||
/* Element of the "ranges" vector */
|
||||
struct linux_prom_ranges {
|
||||
unsigned int ot_child_space;
|
||||
unsigned int ot_child_base; /* Bus feels this */
|
||||
unsigned int ot_parent_space;
|
||||
unsigned int ot_parent_base; /* CPU looks from here */
|
||||
unsigned int or_size;
|
||||
};
|
||||
|
||||
struct linux_prom64_ranges {
|
||||
unsigned long ot_child_base; /* Bus feels this */
|
||||
unsigned long ot_parent_base; /* CPU looks from here */
|
||||
unsigned long or_size;
|
||||
};
|
||||
|
||||
/* Ranges and reg properties are a bit different for PCI. */
|
||||
struct linux_prom_pci_registers {
|
||||
unsigned int phys_hi;
|
||||
unsigned int phys_mid;
|
||||
unsigned int phys_lo;
|
||||
|
||||
unsigned int size_hi;
|
||||
unsigned int size_lo;
|
||||
};
|
||||
|
||||
struct linux_prom_pci_ranges {
|
||||
unsigned int child_phys_hi; /* Only certain bits are encoded here. */
|
||||
unsigned int child_phys_mid;
|
||||
unsigned int child_phys_lo;
|
||||
|
||||
unsigned int parent_phys_hi;
|
||||
unsigned int parent_phys_lo;
|
||||
|
||||
unsigned int size_hi;
|
||||
unsigned int size_lo;
|
||||
};
|
||||
|
||||
struct linux_prom_pci_intmap {
|
||||
unsigned int phys_hi;
|
||||
unsigned int phys_mid;
|
||||
unsigned int phys_lo;
|
||||
|
||||
unsigned int interrupt;
|
||||
|
||||
int cnode;
|
||||
unsigned int cinterrupt;
|
||||
};
|
||||
|
||||
struct linux_prom_pci_intmask {
|
||||
unsigned int phys_hi;
|
||||
unsigned int phys_mid;
|
||||
unsigned int phys_lo;
|
||||
unsigned int interrupt;
|
||||
};
|
||||
|
||||
struct linux_prom_ebus_ranges {
|
||||
unsigned int child_phys_hi;
|
||||
unsigned int child_phys_lo;
|
||||
|
||||
unsigned int parent_phys_hi;
|
||||
unsigned int parent_phys_mid;
|
||||
unsigned int parent_phys_lo;
|
||||
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct linux_prom_ebus_intmap {
|
||||
unsigned int phys_hi;
|
||||
unsigned int phys_lo;
|
||||
|
||||
unsigned int interrupt;
|
||||
|
||||
int cnode;
|
||||
unsigned int cinterrupt;
|
||||
};
|
||||
|
||||
struct linux_prom_ebus_intmask {
|
||||
unsigned int phys_hi;
|
||||
unsigned int phys_lo;
|
||||
unsigned int interrupt;
|
||||
};
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
#endif /* !(__SPARC64_OPENPROM_H) */
|
||||
22
arch/sparc64/plainboot.c
Normal file
22
arch/sparc64/plainboot.c
Normal file
@@ -0,0 +1,22 @@
|
||||
/* tag: openbios fixed address forth starter
|
||||
*
|
||||
* Copyright (C) 2003 Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
#include "openbios/config.h"
|
||||
#include "sys_info.h"
|
||||
#include "multiboot.h"
|
||||
|
||||
#define FIXED_DICTSTART 0xfffe0000
|
||||
#define FIXED_DICTEND 0xfffeffff
|
||||
|
||||
void collect_multiboot_info(struct sys_info *info);
|
||||
void collect_multiboot_info(struct sys_info *info)
|
||||
{
|
||||
info->dict_start=(unsigned long *)FIXED_DICTSTART;
|
||||
info->dict_end=(unsigned long *)FIXED_DICTEND;
|
||||
}
|
||||
|
||||
90
arch/sparc64/pstate.h
Normal file
90
arch/sparc64/pstate.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* $Id: pstate.h,v 1.6 1997/06/25 07:39:45 jj Exp $ */
|
||||
#ifndef _SPARC64_PSTATE_H
|
||||
#define _SPARC64_PSTATE_H
|
||||
|
||||
#include "const.h"
|
||||
|
||||
/* The V9 PSTATE Register (with SpitFire extensions).
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* | Resv | IG | MG | CLE | TLE | MM | RED | PEF | AM | PRIV | IE | AG |
|
||||
* -----------------------------------------------------------------------
|
||||
* 63 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
*/
|
||||
#define PSTATE_IG _AC(0x0000000000000800,UL) /* Interrupt Globals. */
|
||||
#define PSTATE_MG _AC(0x0000000000000400,UL) /* MMU Globals. */
|
||||
#define PSTATE_CLE _AC(0x0000000000000200,UL) /* Current Little Endian.*/
|
||||
#define PSTATE_TLE _AC(0x0000000000000100,UL) /* Trap Little Endian. */
|
||||
#define PSTATE_MM _AC(0x00000000000000c0,UL) /* Memory Model. */
|
||||
#define PSTATE_TSO _AC(0x0000000000000000,UL) /* MM: TotalStoreOrder */
|
||||
#define PSTATE_PSO _AC(0x0000000000000040,UL) /* MM: PartialStoreOrder */
|
||||
#define PSTATE_RMO _AC(0x0000000000000080,UL) /* MM: RelaxedMemoryOrder*/
|
||||
#define PSTATE_RED _AC(0x0000000000000020,UL) /* Reset Error Debug. */
|
||||
#define PSTATE_PEF _AC(0x0000000000000010,UL) /* Floating Point Enable.*/
|
||||
#define PSTATE_AM _AC(0x0000000000000008,UL) /* Address Mask. */
|
||||
#define PSTATE_PRIV _AC(0x0000000000000004,UL) /* Privilege. */
|
||||
#define PSTATE_IE _AC(0x0000000000000002,UL) /* Interrupt Enable. */
|
||||
#define PSTATE_AG _AC(0x0000000000000001,UL) /* Alternate Globals. */
|
||||
|
||||
/* The V9 TSTATE Register (with SpitFire and Linux extensions).
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
* | Resv | CCR | ASI | %pil | PSTATE | Resv | CWP |
|
||||
* ---------------------------------------------------------------
|
||||
* 63 40 39 32 31 24 23 20 19 8 7 5 4 0
|
||||
*/
|
||||
#define TSTATE_CCR _AC(0x000000ff00000000,UL) /* Condition Codes. */
|
||||
#define TSTATE_XCC _AC(0x000000f000000000,UL) /* Condition Codes. */
|
||||
#define TSTATE_XNEG _AC(0x0000008000000000,UL) /* %xcc Negative. */
|
||||
#define TSTATE_XZERO _AC(0x0000004000000000,UL) /* %xcc Zero. */
|
||||
#define TSTATE_XOVFL _AC(0x0000002000000000,UL) /* %xcc Overflow. */
|
||||
#define TSTATE_XCARRY _AC(0x0000001000000000,UL) /* %xcc Carry. */
|
||||
#define TSTATE_ICC _AC(0x0000000f00000000,UL) /* Condition Codes. */
|
||||
#define TSTATE_INEG _AC(0x0000000800000000,UL) /* %icc Negative. */
|
||||
#define TSTATE_IZERO _AC(0x0000000400000000,UL) /* %icc Zero. */
|
||||
#define TSTATE_IOVFL _AC(0x0000000200000000,UL) /* %icc Overflow. */
|
||||
#define TSTATE_ICARRY _AC(0x0000000100000000,UL) /* %icc Carry. */
|
||||
#define TSTATE_ASI _AC(0x00000000ff000000,UL) /* AddrSpace ID. */
|
||||
#define TSTATE_PIL _AC(0x0000000000f00000,UL) /* %pil (Linux traps)*/
|
||||
#define TSTATE_PSTATE _AC(0x00000000000fff00,UL) /* PSTATE. */
|
||||
#define TSTATE_IG _AC(0x0000000000080000,UL) /* Interrupt Globals.*/
|
||||
#define TSTATE_MG _AC(0x0000000000040000,UL) /* MMU Globals. */
|
||||
#define TSTATE_CLE _AC(0x0000000000020000,UL) /* CurrLittleEndian. */
|
||||
#define TSTATE_TLE _AC(0x0000000000010000,UL) /* TrapLittleEndian. */
|
||||
#define TSTATE_MM _AC(0x000000000000c000,UL) /* Memory Model. */
|
||||
#define TSTATE_TSO _AC(0x0000000000000000,UL) /* MM: TSO */
|
||||
#define TSTATE_PSO _AC(0x0000000000004000,UL) /* MM: PSO */
|
||||
#define TSTATE_RMO _AC(0x0000000000008000,UL) /* MM: RMO */
|
||||
#define TSTATE_RED _AC(0x0000000000002000,UL) /* Reset Error Debug.*/
|
||||
#define TSTATE_PEF _AC(0x0000000000001000,UL) /* FPU Enable. */
|
||||
#define TSTATE_AM _AC(0x0000000000000800,UL) /* Address Mask. */
|
||||
#define TSTATE_PRIV _AC(0x0000000000000400,UL) /* Privilege. */
|
||||
#define TSTATE_IE _AC(0x0000000000000200,UL) /* Interrupt Enable. */
|
||||
#define TSTATE_AG _AC(0x0000000000000100,UL) /* Alternate Globals.*/
|
||||
#define TSTATE_CWP _AC(0x000000000000001f,UL) /* Curr Win-Pointer. */
|
||||
|
||||
/* Floating-Point Registers State Register.
|
||||
*
|
||||
* --------------------------------
|
||||
* | Resv | FEF | DU | DL |
|
||||
* --------------------------------
|
||||
* 63 3 2 1 0
|
||||
*/
|
||||
#define FPRS_FEF _AC(0x0000000000000004,UL) /* FPU Enable. */
|
||||
#define FPRS_DU _AC(0x0000000000000002,UL) /* Dirty Upper. */
|
||||
#define FPRS_DL _AC(0x0000000000000001,UL) /* Dirty Lower. */
|
||||
|
||||
/* Version Register.
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
* | MANUF | IMPL | MASK | Resv | MAXTL | Resv | MAXWIN |
|
||||
* ------------------------------------------------------
|
||||
* 63 48 47 32 31 24 23 16 15 8 7 5 4 0
|
||||
*/
|
||||
#define VERS_MANUF _AC(0xffff000000000000,UL) /* Manufacturer. */
|
||||
#define VERS_IMPL _AC(0x0000ffff00000000,UL) /* Implementation. */
|
||||
#define VERS_MASK _AC(0x00000000ff000000,UL) /* Mask Set Revision.*/
|
||||
#define VERS_MAXTL _AC(0x000000000000ff00,UL) /* Max Trap Level. */
|
||||
#define VERS_MAXWIN _AC(0x000000000000001f,UL) /* Max RegWindow Idx.*/
|
||||
|
||||
#endif /* !(_SPARC64_PSTATE_H) */
|
||||
502
arch/sparc64/spitfire.h
Normal file
502
arch/sparc64/spitfire.h
Normal file
@@ -0,0 +1,502 @@
|
||||
/* $Id: spitfire.h,v 1.18 2001/11/29 16:42:10 kanoj Exp $
|
||||
* spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
|
||||
*
|
||||
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
|
||||
#ifndef _SPARC64_SPITFIRE_H
|
||||
#define _SPARC64_SPITFIRE_H
|
||||
|
||||
#include <asm/asi.h>
|
||||
|
||||
/* The following register addresses are accessible via ASI_DMMU
|
||||
* and ASI_IMMU, that is there is a distinct and unique copy of
|
||||
* each these registers for each TLB.
|
||||
*/
|
||||
#define TSB_TAG_TARGET 0x0000000000000000 /* All chips */
|
||||
#define TLB_SFSR 0x0000000000000018 /* All chips */
|
||||
#define TSB_REG 0x0000000000000028 /* All chips */
|
||||
#define TLB_TAG_ACCESS 0x0000000000000030 /* All chips */
|
||||
#define VIRT_WATCHPOINT 0x0000000000000038 /* All chips */
|
||||
#define PHYS_WATCHPOINT 0x0000000000000040 /* All chips */
|
||||
#define TSB_EXTENSION_P 0x0000000000000048 /* Ultra-III and later */
|
||||
#define TSB_EXTENSION_S 0x0000000000000050 /* Ultra-III and later, D-TLB only */
|
||||
#define TSB_EXTENSION_N 0x0000000000000058 /* Ultra-III and later */
|
||||
#define TLB_TAG_ACCESS_EXT 0x0000000000000060 /* Ultra-III+ and later */
|
||||
|
||||
/* These registers only exist as one entity, and are accessed
|
||||
* via ASI_DMMU only.
|
||||
*/
|
||||
#define PRIMARY_CONTEXT 0x0000000000000008
|
||||
#define SECONDARY_CONTEXT 0x0000000000000010
|
||||
#define DMMU_SFAR 0x0000000000000020
|
||||
#define VIRT_WATCHPOINT 0x0000000000000038
|
||||
#define PHYS_WATCHPOINT 0x0000000000000040
|
||||
|
||||
#define SPITFIRE_HIGHEST_LOCKED_TLBENT (64 - 1)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
enum ultra_tlb_layout {
|
||||
spitfire = 0,
|
||||
cheetah = 1,
|
||||
cheetah_plus = 2,
|
||||
};
|
||||
|
||||
extern enum ultra_tlb_layout tlb_type;
|
||||
|
||||
#define CHEETAH_HIGHEST_LOCKED_TLBENT (16 - 1)
|
||||
|
||||
#define L1DCACHE_SIZE 0x4000
|
||||
|
||||
#define sparc64_highest_locked_tlbent() \
|
||||
(tlb_type == spitfire ? \
|
||||
SPITFIRE_HIGHEST_LOCKED_TLBENT : \
|
||||
CHEETAH_HIGHEST_LOCKED_TLBENT)
|
||||
|
||||
static __inline__ unsigned long spitfire_get_isfsr(void)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (ret)
|
||||
: "r" (TLB_SFSR), "i" (ASI_IMMU));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long spitfire_get_dsfsr(void)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (ret)
|
||||
: "r" (TLB_SFSR), "i" (ASI_DMMU));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long spitfire_get_sfar(void)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (ret)
|
||||
: "r" (DMMU_SFAR), "i" (ASI_DMMU));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_put_isfsr(unsigned long sfsr)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* no outputs */
|
||||
: "r" (sfsr), "r" (TLB_SFSR), "i" (ASI_IMMU));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_put_dsfsr(unsigned long sfsr)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* no outputs */
|
||||
: "r" (sfsr), "r" (TLB_SFSR), "i" (ASI_DMMU));
|
||||
}
|
||||
|
||||
static __inline__ unsigned long spitfire_get_primary_context(void)
|
||||
{
|
||||
unsigned long ctx;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (ctx)
|
||||
: "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_set_primary_context(unsigned long ctx)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (ctx & 0x3ff),
|
||||
"r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
|
||||
__asm__ __volatile__ ("membar #Sync" : : : "memory");
|
||||
}
|
||||
|
||||
static __inline__ unsigned long spitfire_get_secondary_context(void)
|
||||
{
|
||||
unsigned long ctx;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (ctx)
|
||||
: "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_set_secondary_context(unsigned long ctx)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (ctx & 0x3ff),
|
||||
"r" (SECONDARY_CONTEXT), "i" (ASI_DMMU));
|
||||
__asm__ __volatile__ ("membar #Sync" : : : "memory");
|
||||
}
|
||||
|
||||
/* The data cache is write through, so this just invalidates the
|
||||
* specified line.
|
||||
*/
|
||||
static __inline__ void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG));
|
||||
__asm__ __volatile__ ("membar #Sync" : : : "memory");
|
||||
}
|
||||
|
||||
/* The instruction cache lines are flushed with this, but note that
|
||||
* this does not flush the pipeline. It is possible for a line to
|
||||
* get flushed but stale instructions to still be in the pipeline,
|
||||
* a flush instruction (to any address) is sufficient to handle
|
||||
* this issue after the line is invalidated.
|
||||
*/
|
||||
static __inline__ void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (tag), "r" (addr), "i" (ASI_IC_TAG));
|
||||
}
|
||||
|
||||
static __inline__ unsigned long spitfire_get_dtlb_data(int entry)
|
||||
{
|
||||
unsigned long data;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (data)
|
||||
: "r" (entry << 3), "i" (ASI_DTLB_DATA_ACCESS));
|
||||
|
||||
/* Clear TTE diag bits. */
|
||||
data &= ~0x0003fe0000000000UL;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long spitfire_get_dtlb_tag(int entry)
|
||||
{
|
||||
unsigned long tag;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (tag)
|
||||
: "r" (entry << 3), "i" (ASI_DTLB_TAG_READ));
|
||||
return tag;
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_put_dtlb_data(int entry, unsigned long data)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (data), "r" (entry << 3),
|
||||
"i" (ASI_DTLB_DATA_ACCESS));
|
||||
}
|
||||
|
||||
static __inline__ unsigned long spitfire_get_itlb_data(int entry)
|
||||
{
|
||||
unsigned long data;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (data)
|
||||
: "r" (entry << 3), "i" (ASI_ITLB_DATA_ACCESS));
|
||||
|
||||
/* Clear TTE diag bits. */
|
||||
data &= ~0x0003fe0000000000UL;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long spitfire_get_itlb_tag(int entry)
|
||||
{
|
||||
unsigned long tag;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (tag)
|
||||
: "r" (entry << 3), "i" (ASI_ITLB_TAG_READ));
|
||||
return tag;
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_put_itlb_data(int entry, unsigned long data)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (data), "r" (entry << 3),
|
||||
"i" (ASI_ITLB_DATA_ACCESS));
|
||||
}
|
||||
|
||||
/* Spitfire hardware assisted TLB flushes. */
|
||||
|
||||
/* Context level flushes. */
|
||||
static __inline__ void spitfire_flush_dtlb_primary_context(void)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (0x40), "i" (ASI_DMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_itlb_primary_context(void)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (0x40), "i" (ASI_IMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_dtlb_secondary_context(void)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (0x50), "i" (ASI_DMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_itlb_secondary_context(void)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (0x50), "i" (ASI_IMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_dtlb_nucleus_context(void)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (0x60), "i" (ASI_DMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_itlb_nucleus_context(void)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (0x60), "i" (ASI_IMMU_DEMAP));
|
||||
}
|
||||
|
||||
/* Page level flushes. */
|
||||
static __inline__ void spitfire_flush_dtlb_primary_page(unsigned long page)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (page), "i" (ASI_DMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_itlb_primary_page(unsigned long page)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (page), "i" (ASI_IMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_dtlb_secondary_page(unsigned long page)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (page | 0x10), "i" (ASI_DMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_itlb_secondary_page(unsigned long page)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (page | 0x10), "i" (ASI_IMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_dtlb_nucleus_page(unsigned long page)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (page | 0x20), "i" (ASI_DMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void spitfire_flush_itlb_nucleus_page(unsigned long page)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (page | 0x20), "i" (ASI_IMMU_DEMAP));
|
||||
}
|
||||
|
||||
/* Cheetah has "all non-locked" tlb flushes. */
|
||||
static __inline__ void cheetah_flush_dtlb_all(void)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (0x80), "i" (ASI_DMMU_DEMAP));
|
||||
}
|
||||
|
||||
static __inline__ void cheetah_flush_itlb_all(void)
|
||||
{
|
||||
__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (0x80), "i" (ASI_IMMU_DEMAP));
|
||||
}
|
||||
|
||||
/* Cheetah has a 4-tlb layout so direct access is a bit different.
|
||||
* The first two TLBs are fully assosciative, hold 16 entries, and are
|
||||
* used only for locked and >8K sized translations. One exists for
|
||||
* data accesses and one for instruction accesses.
|
||||
*
|
||||
* The third TLB is for data accesses to 8K non-locked translations, is
|
||||
* 2 way assosciative, and holds 512 entries. The fourth TLB is for
|
||||
* instruction accesses to 8K non-locked translations, is 2 way
|
||||
* assosciative, and holds 128 entries.
|
||||
*
|
||||
* Cheetah has some bug where bogus data can be returned from
|
||||
* ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes
|
||||
* the problem for me. -DaveM
|
||||
*/
|
||||
static __inline__ unsigned long cheetah_get_ldtlb_data(int entry)
|
||||
{
|
||||
unsigned long data;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
|
||||
"ldxa [%1] %2, %0"
|
||||
: "=r" (data)
|
||||
: "r" ((0 << 16) | (entry << 3)),
|
||||
"i" (ASI_DTLB_DATA_ACCESS));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long cheetah_get_litlb_data(int entry)
|
||||
{
|
||||
unsigned long data;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
|
||||
"ldxa [%1] %2, %0"
|
||||
: "=r" (data)
|
||||
: "r" ((0 << 16) | (entry << 3)),
|
||||
"i" (ASI_ITLB_DATA_ACCESS));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long cheetah_get_ldtlb_tag(int entry)
|
||||
{
|
||||
unsigned long tag;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (tag)
|
||||
: "r" ((0 << 16) | (entry << 3)),
|
||||
"i" (ASI_DTLB_TAG_READ));
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long cheetah_get_litlb_tag(int entry)
|
||||
{
|
||||
unsigned long tag;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (tag)
|
||||
: "r" ((0 << 16) | (entry << 3)),
|
||||
"i" (ASI_ITLB_TAG_READ));
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
static __inline__ void cheetah_put_ldtlb_data(int entry, unsigned long data)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (data),
|
||||
"r" ((0 << 16) | (entry << 3)),
|
||||
"i" (ASI_DTLB_DATA_ACCESS));
|
||||
}
|
||||
|
||||
static __inline__ void cheetah_put_litlb_data(int entry, unsigned long data)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (data),
|
||||
"r" ((0 << 16) | (entry << 3)),
|
||||
"i" (ASI_ITLB_DATA_ACCESS));
|
||||
}
|
||||
|
||||
static __inline__ unsigned long cheetah_get_dtlb_data(int entry, int tlb)
|
||||
{
|
||||
unsigned long data;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
|
||||
"ldxa [%1] %2, %0"
|
||||
: "=r" (data)
|
||||
: "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
|
||||
{
|
||||
unsigned long tag;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (tag)
|
||||
: "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ));
|
||||
return tag;
|
||||
}
|
||||
|
||||
static __inline__ void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (data),
|
||||
"r" ((tlb << 16) | (entry << 3)),
|
||||
"i" (ASI_DTLB_DATA_ACCESS));
|
||||
}
|
||||
|
||||
static __inline__ unsigned long cheetah_get_itlb_data(int entry)
|
||||
{
|
||||
unsigned long data;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
|
||||
"ldxa [%1] %2, %0"
|
||||
: "=r" (data)
|
||||
: "r" ((2 << 16) | (entry << 3)),
|
||||
"i" (ASI_ITLB_DATA_ACCESS));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long cheetah_get_itlb_tag(int entry)
|
||||
{
|
||||
unsigned long tag;
|
||||
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0"
|
||||
: "=r" (tag)
|
||||
: "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_TAG_READ));
|
||||
return tag;
|
||||
}
|
||||
|
||||
static __inline__ void cheetah_put_itlb_data(int entry, unsigned long data)
|
||||
{
|
||||
__asm__ __volatile__("stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* No outputs */
|
||||
: "r" (data), "r" ((2 << 16) | (entry << 3)),
|
||||
"i" (ASI_ITLB_DATA_ACCESS));
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
#endif /* !(_SPARC64_SPITFIRE_H) */
|
||||
118
arch/sparc64/switch.S
Normal file
118
arch/sparc64/switch.S
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "pstate.h"
|
||||
#include "asi.h"
|
||||
#define ASI_BP ASI_M_BYPASS
|
||||
#define REGWIN_SZ 0x40
|
||||
|
||||
.globl __switch_context, __switch_context_nosave, __exit_context, halt
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.register %g2, #scratch
|
||||
.register %g3, #scratch
|
||||
.register %g6, #scratch
|
||||
.register %g7, #scratch
|
||||
|
||||
/*
|
||||
* Switch execution context
|
||||
* This saves registers in the stack, then
|
||||
* switches the stack, and restores everything from the new stack.
|
||||
* This function takes no argument. New stack pointer is
|
||||
* taken from global variable __context, and old stack pointer
|
||||
* is also saved to __context. This way we can just jump to
|
||||
* this routine to get back to the original context.
|
||||
*/
|
||||
|
||||
/* XXX: totally bogus for sparc, need to save and restore all windows */
|
||||
__switch_context:
|
||||
/* Save everything in current stack */
|
||||
setx __context, %g2, %g1
|
||||
stx %g3, [%g1 + 24]
|
||||
stx %g4, [%g1 + 32]
|
||||
stx %g5, [%g1 + 40]
|
||||
stx %g6, [%g1 + 48]
|
||||
stx %g7, [%g1 + 56]
|
||||
|
||||
stx %o0, [%g1 + 64]
|
||||
stx %o1, [%g1 + 72]
|
||||
stx %o2, [%g1 + 80]
|
||||
stx %o3, [%g1 + 88]
|
||||
stx %o4, [%g1 + 96]
|
||||
stx %o5, [%g1 + 104]
|
||||
stx %o6, [%g1 + 112]
|
||||
stx %o7, [%g1 + 120]
|
||||
|
||||
stx %l0, [%g1 + 128]
|
||||
stx %l1, [%g1 + 136]
|
||||
stx %l2, [%g1 + 144]
|
||||
stx %l3, [%g1 + 152]
|
||||
stx %l4, [%g1 + 160]
|
||||
stx %l5, [%g1 + 168]
|
||||
stx %l6, [%g1 + 176]
|
||||
stx %l7, [%g1 + 184]
|
||||
|
||||
stx %i0, [%g1 + 192]
|
||||
stx %i1, [%g1 + 200]
|
||||
stx %i2, [%g1 + 208]
|
||||
stx %i3, [%g1 + 216]
|
||||
stx %i4, [%g1 + 224]
|
||||
stx %i5, [%g1 + 232]
|
||||
stx %i6, [%g1 + 240]
|
||||
stx %i7, [%g1 + 248]
|
||||
|
||||
__switch_context_nosave:
|
||||
/* Interrupts are not allowed... */
|
||||
|
||||
/* Load all registers
|
||||
*/
|
||||
setx __context, %g2, %g1
|
||||
ldx [%g1], %g1
|
||||
ldx [%g1 + 16], %g2
|
||||
ldx [%g1 + 24], %g3
|
||||
ldx [%g1 + 32], %g4
|
||||
ldx [%g1 + 40], %g5
|
||||
ldx [%g1 + 48], %g6
|
||||
ldx [%g1 + 56], %g7
|
||||
|
||||
ldx [%g1 + 64], %o0
|
||||
ldx [%g1 + 72], %o1
|
||||
ldx [%g1 + 80], %o2
|
||||
ldx [%g1 + 88], %o3
|
||||
ldx [%g1 + 96], %o4
|
||||
ldx [%g1 + 104], %o5
|
||||
ldx [%g1 + 112], %o6
|
||||
ldx [%g1 + 120], %o7
|
||||
|
||||
ldx [%g1 + 128], %l0
|
||||
ldx [%g1 + 136], %l1
|
||||
ldx [%g1 + 144], %l2
|
||||
ldx [%g1 + 152], %l3
|
||||
ldx [%g1 + 160], %l4
|
||||
ldx [%g1 + 168], %l5
|
||||
ldx [%g1 + 176], %l6
|
||||
ldx [%g1 + 184], %l7
|
||||
|
||||
ldx [%g1 + 192], %i0
|
||||
ldx [%g1 + 200], %i1
|
||||
ldx [%g1 + 208], %i2
|
||||
ldx [%g1 + 216], %i3
|
||||
ldx [%g1 + 224], %i4
|
||||
ldx [%g1 + 232], %i5
|
||||
ldx [%g1 + 240], %i6
|
||||
ldx [%g1 + 248], %i7
|
||||
|
||||
ldx [%g1 + 256], %g1
|
||||
/* Finally, load new %pc */
|
||||
jmp %g1
|
||||
clr %g1
|
||||
|
||||
__exit_context:
|
||||
/* Get back to the original context */
|
||||
call __switch_context
|
||||
nop
|
||||
|
||||
/* We get here if the other context attempt to switch to this
|
||||
* dead context. This should not happen. */
|
||||
|
||||
halt:
|
||||
b halt
|
||||
nop
|
||||
59
arch/sparc64/sys_info.c
Normal file
59
arch/sparc64/sys_info.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "openbios/config.h"
|
||||
#include "openbios/kernel.h"
|
||||
#include "elf_boot.h"
|
||||
#include "sys_info.h"
|
||||
#include "context.h"
|
||||
|
||||
#define printf printk
|
||||
#ifdef CONFIG_DEBUG_BOOT
|
||||
#define debug printk
|
||||
#else
|
||||
#define debug(x...)
|
||||
#endif
|
||||
|
||||
unsigned long qemu_mem_size;
|
||||
unsigned long va_shift;
|
||||
|
||||
void collect_multiboot_info(struct sys_info *);
|
||||
|
||||
void collect_sys_info(struct sys_info *info)
|
||||
{
|
||||
int i;
|
||||
unsigned long long total = 0;
|
||||
struct memrange *mmap;
|
||||
extern struct elf_image_note elf_image_notes;
|
||||
|
||||
/* Pick up paramters given by bootloader to us */
|
||||
//info->boot_type = boot_ctx->eax;
|
||||
//info->boot_data = boot_ctx->ebx;
|
||||
info->boot_arg = boot_ctx->param[0];
|
||||
//debug("boot eax = %#lx\n", info->boot_type);
|
||||
//debug("boot ebx = %#lx\n", info->boot_data);
|
||||
info->boot_type = ELF_BHDR_MAGIC;
|
||||
info->boot_data = virt_to_phys(&elf_image_notes);
|
||||
debug("boot arg = %#lx\n", info->boot_arg);
|
||||
|
||||
collect_elfboot_info(info);
|
||||
#ifdef CONFIG_LINUXBIOS
|
||||
collect_linuxbios_info(info);
|
||||
#endif
|
||||
#ifdef CONFIG_IMAGE_ELF_MULTIBOOT
|
||||
collect_multiboot_info(info);
|
||||
#endif
|
||||
|
||||
if (!info->memrange) {
|
||||
info->n_memranges = 1;
|
||||
info->memrange = malloc(1 * sizeof(struct memrange));
|
||||
info->memrange[0].base = 0;
|
||||
info->memrange[0].size = qemu_mem_size;
|
||||
}
|
||||
|
||||
debug("\n");
|
||||
mmap=info->memrange;
|
||||
for (i = 0; i < info->n_memranges; i++) {
|
||||
debug("%08lx-", (long)mmap[i].base);
|
||||
debug("%08lx\n", (long)mmap[i].base + (long)mmap[i].size);
|
||||
total += mmap[i].size;
|
||||
}
|
||||
debug("RAM %ld MB\n", (long)total >> 20);
|
||||
}
|
||||
29
arch/sparc64/tree.fs
Normal file
29
arch/sparc64/tree.fs
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
" /" find-device
|
||||
2 encode-int " #address-cells" property
|
||||
1 encode-int " #size-cells" property
|
||||
|
||||
: encode-unit encode-unit-sbus ;
|
||||
: decode-unit decode-unit-sbus ;
|
||||
|
||||
new-device
|
||||
" memory" device-name
|
||||
external
|
||||
: open true ;
|
||||
: close ;
|
||||
\ claim ( phys size align -- base )
|
||||
\ release ( phys size -- )
|
||||
finish-device
|
||||
|
||||
new-device
|
||||
" virtual-memory" device-name
|
||||
external
|
||||
: open true ;
|
||||
: close ;
|
||||
\ claim ( phys size align -- base )
|
||||
\ release ( phys size -- )
|
||||
finish-device
|
||||
|
||||
" /options" find-device
|
||||
" disk" encode-string " boot-from" property
|
||||
|
||||
407
arch/sparc64/ttable.h
Normal file
407
arch/sparc64/ttable.h
Normal file
@@ -0,0 +1,407 @@
|
||||
/* $Id: ttable.h,v 1.18 2002/02/09 19:49:32 davem Exp $ */
|
||||
#ifndef _SPARC64_TTABLE_H
|
||||
#define _SPARC64_TTABLE_H
|
||||
|
||||
//#include <linux/config.h>
|
||||
//#include <asm/utrap.h>
|
||||
|
||||
//#ifdef __ASSEMBLY__
|
||||
//#include <asm/thread_info.h>
|
||||
//#endif
|
||||
|
||||
//#define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop;
|
||||
|
||||
/* We need a "cleaned" instruction... */
|
||||
#define CLEAN_WINDOW \
|
||||
rdpr %cleanwin, %l0; add %l0, 1, %l0; \
|
||||
wrpr %l0, 0x0, %cleanwin; \
|
||||
clr %o0; clr %o1; clr %o2; clr %o3; \
|
||||
clr %o4; clr %o5; clr %o6; clr %o7; \
|
||||
clr %l0; clr %l1; clr %l2; clr %l3; \
|
||||
clr %l4; clr %l5; clr %l6; clr %l7; \
|
||||
retry; \
|
||||
nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
|
||||
|
||||
#define TRAP(routine) \
|
||||
sethi %hi(109f), %g7; \
|
||||
ba,pt %xcc, etrap; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
call routine; \
|
||||
add %sp, PTREGS_OFF, %o0; \
|
||||
ba,pt %xcc, rtrap; \
|
||||
clr %l6; \
|
||||
nop;
|
||||
|
||||
#define TRAP_7INSNS(routine) \
|
||||
sethi %hi(109f), %g7; \
|
||||
ba,pt %xcc, etrap; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
call routine; \
|
||||
add %sp, PTREGS_OFF, %o0; \
|
||||
ba,pt %xcc, rtrap; \
|
||||
clr %l6;
|
||||
|
||||
#define TRAP_SAVEFPU(routine) \
|
||||
sethi %hi(109f), %g7; \
|
||||
ba,pt %xcc, do_fptrap; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
call routine; \
|
||||
add %sp, PTREGS_OFF, %o0; \
|
||||
ba,pt %xcc, rtrap; \
|
||||
clr %l6; \
|
||||
nop;
|
||||
|
||||
#define TRAP_NOSAVE(routine) \
|
||||
ba,pt %xcc, routine; \
|
||||
nop; \
|
||||
nop; nop; nop; nop; nop; nop;
|
||||
|
||||
#define TRAP_NOSAVE_7INSNS(routine) \
|
||||
ba,pt %xcc, routine; \
|
||||
nop; \
|
||||
nop; nop; nop; nop; nop;
|
||||
|
||||
#define TRAPTL1(routine) \
|
||||
sethi %hi(109f), %g7; \
|
||||
ba,pt %xcc, etraptl1; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
call routine; \
|
||||
add %sp, PTREGS_OFF, %o0; \
|
||||
ba,pt %xcc, rtrap; \
|
||||
clr %l6; \
|
||||
nop;
|
||||
|
||||
#define TRAP_ARG(routine, arg) \
|
||||
sethi %hi(109f), %g7; \
|
||||
ba,pt %xcc, etrap; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
add %sp, PTREGS_OFF, %o0; \
|
||||
call routine; \
|
||||
mov arg, %o1; \
|
||||
ba,pt %xcc, rtrap; \
|
||||
clr %l6;
|
||||
|
||||
#define TRAPTL1_ARG(routine, arg) \
|
||||
sethi %hi(109f), %g7; \
|
||||
ba,pt %xcc, etraptl1; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
add %sp, PTREGS_OFF, %o0; \
|
||||
call routine; \
|
||||
mov arg, %o1; \
|
||||
ba,pt %xcc, rtrap; \
|
||||
clr %l6;
|
||||
|
||||
#define SYSCALL_TRAP(routine, systbl) \
|
||||
sethi %hi(109f), %g7; \
|
||||
ba,pt %xcc, scetrap; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
sethi %hi(systbl), %l7; \
|
||||
ba,pt %xcc, routine; \
|
||||
or %l7, %lo(systbl), %l7; \
|
||||
nop; nop;
|
||||
|
||||
#define INDIRECT_SOLARIS_SYSCALL(num) \
|
||||
sethi %hi(109f), %g7; \
|
||||
ba,pt %xcc, etrap; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
ba,pt %xcc, tl0_solaris + 0xc; \
|
||||
mov num, %g1; \
|
||||
nop;nop;nop;
|
||||
|
||||
#define TRAP_UTRAP(handler,lvl) \
|
||||
ldx [%g6 + TI_UTRAPS], %g1; \
|
||||
sethi %hi(109f), %g7; \
|
||||
brz,pn %g1, utrap; \
|
||||
or %g7, %lo(109f), %g7; \
|
||||
ba,pt %xcc, utrap; \
|
||||
109: ldx [%g1 + handler*8], %g1; \
|
||||
ba,pt %xcc, utrap_ill; \
|
||||
mov lvl, %o1;
|
||||
|
||||
#ifdef CONFIG_SUNOS_EMUL
|
||||
#define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sunos_sys_table)
|
||||
#else
|
||||
#define SUNOS_SYSCALL_TRAP TRAP(sunos_syscall)
|
||||
#endif
|
||||
#ifdef CONFIG_COMPAT
|
||||
#define LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sys_call_table32)
|
||||
#else
|
||||
#define LINUX_32BIT_SYSCALL_TRAP BTRAP(0x110)
|
||||
#endif
|
||||
#define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64)
|
||||
#define GETCC_TRAP TRAP(getcc)
|
||||
#define SETCC_TRAP TRAP(setcc)
|
||||
#ifdef CONFIG_SOLARIS_EMUL
|
||||
#define SOLARIS_SYSCALL_TRAP TRAP(solaris_sparc_syscall)
|
||||
#else
|
||||
#define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall)
|
||||
#endif
|
||||
/* FIXME: Write these actually */
|
||||
#define NETBSD_SYSCALL_TRAP TRAP(netbsd_syscall)
|
||||
#define BREAKPOINT_TRAP TRAP(breakpoint_trap)
|
||||
|
||||
#define TRAP_IRQ(routine, level) \
|
||||
rdpr %pil, %g2; \
|
||||
wrpr %g0, 15, %pil; \
|
||||
b,pt %xcc, etrap_irq; \
|
||||
rd %pc, %g7; \
|
||||
mov level, %o0; \
|
||||
call routine; \
|
||||
add %sp, PTREGS_OFF, %o1; \
|
||||
ba,a,pt %xcc, rtrap_irq;
|
||||
|
||||
#define TICK_SMP_IRQ \
|
||||
rdpr %pil, %g2; \
|
||||
wrpr %g0, 15, %pil; \
|
||||
sethi %hi(109f), %g7; \
|
||||
b,pt %xcc, etrap_irq; \
|
||||
109: or %g7, %lo(109b), %g7; \
|
||||
call smp_percpu_timer_interrupt; \
|
||||
add %sp, PTREGS_OFF, %o0; \
|
||||
ba,a,pt %xcc, rtrap_irq;
|
||||
|
||||
#define TRAP_IVEC TRAP_NOSAVE(do_ivec)
|
||||
|
||||
#define BTRAP(lvl) TRAP_ARG(bad_trap, lvl)
|
||||
|
||||
#define BTRAPTL1(lvl) TRAPTL1_ARG(bad_trap_tl1, lvl)
|
||||
|
||||
#define FLUSH_WINDOW_TRAP \
|
||||
ba,pt %xcc, etrap; \
|
||||
rd %pc, %g7; \
|
||||
flushw; \
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1; \
|
||||
add %l1, 4, %l2; \
|
||||
stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]; \
|
||||
ba,pt %xcc, rtrap_clr_l6; \
|
||||
stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
#define KPROBES_TRAP(lvl) TRAP_IRQ(kprobe_trap, lvl)
|
||||
#else
|
||||
#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
|
||||
#endif
|
||||
|
||||
/* Before touching these macros, you owe it to yourself to go and
|
||||
* see how arch/sparc64/kernel/winfixup.S works... -DaveM
|
||||
*
|
||||
* For the user cases we used to use the %asi register, but
|
||||
* it turns out that the "wr xxx, %asi" costs ~5 cycles, so
|
||||
* now we use immediate ASI loads and stores instead. Kudos
|
||||
* to Greg Onufer for pointing out this performance anomaly.
|
||||
*
|
||||
* Further note that we cannot use the g2, g4, g5, and g7 alternate
|
||||
* globals in the spill routines, check out the save instruction in
|
||||
* arch/sparc64/kernel/etrap.S to see what I mean about g2, and
|
||||
* g4/g5 are the globals which are preserved by etrap processing
|
||||
* for the caller of it. The g7 register is the return pc for
|
||||
* etrap. Finally, g6 is the current thread register so we cannot
|
||||
* us it in the spill handlers either. Most of these rules do not
|
||||
* apply to fill processing, only g6 is not usable.
|
||||
*/
|
||||
|
||||
/* Normal kernel spill */
|
||||
#define SPILL_0_NORMAL \
|
||||
stx %l0, [%sp + STACK_BIAS + 0x00]; \
|
||||
stx %l1, [%sp + STACK_BIAS + 0x08]; \
|
||||
stx %l2, [%sp + STACK_BIAS + 0x10]; \
|
||||
stx %l3, [%sp + STACK_BIAS + 0x18]; \
|
||||
stx %l4, [%sp + STACK_BIAS + 0x20]; \
|
||||
stx %l5, [%sp + STACK_BIAS + 0x28]; \
|
||||
stx %l6, [%sp + STACK_BIAS + 0x30]; \
|
||||
stx %l7, [%sp + STACK_BIAS + 0x38]; \
|
||||
stx %i0, [%sp + STACK_BIAS + 0x40]; \
|
||||
stx %i1, [%sp + STACK_BIAS + 0x48]; \
|
||||
stx %i2, [%sp + STACK_BIAS + 0x50]; \
|
||||
stx %i3, [%sp + STACK_BIAS + 0x58]; \
|
||||
stx %i4, [%sp + STACK_BIAS + 0x60]; \
|
||||
stx %i5, [%sp + STACK_BIAS + 0x68]; \
|
||||
stx %i6, [%sp + STACK_BIAS + 0x70]; \
|
||||
stx %i7, [%sp + STACK_BIAS + 0x78]; \
|
||||
saved; retry; nop; nop; nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop; nop; nop; nop; nop;
|
||||
|
||||
/* Normal 64bit spill */
|
||||
#define SPILL_1_GENERIC(ASI) \
|
||||
add %sp, STACK_BIAS + 0x00, %g1; \
|
||||
stxa %l0, [%g1 + %g0] ASI; \
|
||||
mov 0x08, %g3; \
|
||||
stxa %l1, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x10, %g1; \
|
||||
stxa %l2, [%g1 + %g0] ASI; \
|
||||
stxa %l3, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x10, %g1; \
|
||||
stxa %l4, [%g1 + %g0] ASI; \
|
||||
stxa %l5, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x10, %g1; \
|
||||
stxa %l6, [%g1 + %g0] ASI; \
|
||||
stxa %l7, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x10, %g1; \
|
||||
stxa %i0, [%g1 + %g0] ASI; \
|
||||
stxa %i1, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x10, %g1; \
|
||||
stxa %i2, [%g1 + %g0] ASI; \
|
||||
stxa %i3, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x10, %g1; \
|
||||
stxa %i4, [%g1 + %g0] ASI; \
|
||||
stxa %i5, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x10, %g1; \
|
||||
stxa %i6, [%g1 + %g0] ASI; \
|
||||
stxa %i7, [%g1 + %g3] ASI; \
|
||||
saved; \
|
||||
retry; nop; nop; \
|
||||
b,a,pt %xcc, spill_fixup_dax; \
|
||||
b,a,pt %xcc, spill_fixup_mna; \
|
||||
b,a,pt %xcc, spill_fixup;
|
||||
|
||||
/* Normal 32bit spill */
|
||||
#define SPILL_2_GENERIC(ASI) \
|
||||
srl %sp, 0, %sp; \
|
||||
stwa %l0, [%sp + %g0] ASI; \
|
||||
mov 0x04, %g3; \
|
||||
stwa %l1, [%sp + %g3] ASI; \
|
||||
add %sp, 0x08, %g1; \
|
||||
stwa %l2, [%g1 + %g0] ASI; \
|
||||
stwa %l3, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x08, %g1; \
|
||||
stwa %l4, [%g1 + %g0] ASI; \
|
||||
stwa %l5, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x08, %g1; \
|
||||
stwa %l6, [%g1 + %g0] ASI; \
|
||||
stwa %l7, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x08, %g1; \
|
||||
stwa %i0, [%g1 + %g0] ASI; \
|
||||
stwa %i1, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x08, %g1; \
|
||||
stwa %i2, [%g1 + %g0] ASI; \
|
||||
stwa %i3, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x08, %g1; \
|
||||
stwa %i4, [%g1 + %g0] ASI; \
|
||||
stwa %i5, [%g1 + %g3] ASI; \
|
||||
add %g1, 0x08, %g1; \
|
||||
stwa %i6, [%g1 + %g0] ASI; \
|
||||
stwa %i7, [%g1 + %g3] ASI; \
|
||||
saved; \
|
||||
retry; nop; nop; \
|
||||
b,a,pt %xcc, spill_fixup_dax; \
|
||||
b,a,pt %xcc, spill_fixup_mna; \
|
||||
b,a,pt %xcc, spill_fixup;
|
||||
|
||||
#define SPILL_1_NORMAL SPILL_1_GENERIC(ASI_AIUP)
|
||||
#define SPILL_2_NORMAL SPILL_2_GENERIC(ASI_AIUP)
|
||||
#define SPILL_3_NORMAL SPILL_0_NORMAL
|
||||
#define SPILL_4_NORMAL SPILL_0_NORMAL
|
||||
#define SPILL_5_NORMAL SPILL_0_NORMAL
|
||||
#define SPILL_6_NORMAL SPILL_0_NORMAL
|
||||
#define SPILL_7_NORMAL SPILL_0_NORMAL
|
||||
|
||||
#define SPILL_0_OTHER SPILL_0_NORMAL
|
||||
#define SPILL_1_OTHER SPILL_1_GENERIC(ASI_AIUS)
|
||||
#define SPILL_2_OTHER SPILL_2_GENERIC(ASI_AIUS)
|
||||
#define SPILL_3_OTHER SPILL_3_NORMAL
|
||||
#define SPILL_4_OTHER SPILL_4_NORMAL
|
||||
#define SPILL_5_OTHER SPILL_5_NORMAL
|
||||
#define SPILL_6_OTHER SPILL_6_NORMAL
|
||||
#define SPILL_7_OTHER SPILL_7_NORMAL
|
||||
|
||||
/* Normal kernel fill */
|
||||
#define FILL_0_NORMAL \
|
||||
ldx [%sp + STACK_BIAS + 0x00], %l0; \
|
||||
ldx [%sp + STACK_BIAS + 0x08], %l1; \
|
||||
ldx [%sp + STACK_BIAS + 0x10], %l2; \
|
||||
ldx [%sp + STACK_BIAS + 0x18], %l3; \
|
||||
ldx [%sp + STACK_BIAS + 0x20], %l4; \
|
||||
ldx [%sp + STACK_BIAS + 0x28], %l5; \
|
||||
ldx [%sp + STACK_BIAS + 0x30], %l6; \
|
||||
ldx [%sp + STACK_BIAS + 0x38], %l7; \
|
||||
ldx [%sp + STACK_BIAS + 0x40], %i0; \
|
||||
ldx [%sp + STACK_BIAS + 0x48], %i1; \
|
||||
ldx [%sp + STACK_BIAS + 0x50], %i2; \
|
||||
ldx [%sp + STACK_BIAS + 0x58], %i3; \
|
||||
ldx [%sp + STACK_BIAS + 0x60], %i4; \
|
||||
ldx [%sp + STACK_BIAS + 0x68], %i5; \
|
||||
ldx [%sp + STACK_BIAS + 0x70], %i6; \
|
||||
ldx [%sp + STACK_BIAS + 0x78], %i7; \
|
||||
restored; retry; nop; nop; nop; nop; nop; nop; \
|
||||
nop; nop; nop; nop; nop; nop; nop; nop;
|
||||
|
||||
/* Normal 64bit fill */
|
||||
#define FILL_1_GENERIC(ASI) \
|
||||
add %sp, STACK_BIAS + 0x00, %g1; \
|
||||
ldxa [%g1 + %g0] ASI, %l0; \
|
||||
mov 0x08, %g2; \
|
||||
mov 0x10, %g3; \
|
||||
ldxa [%g1 + %g2] ASI, %l1; \
|
||||
mov 0x18, %g5; \
|
||||
ldxa [%g1 + %g3] ASI, %l2; \
|
||||
ldxa [%g1 + %g5] ASI, %l3; \
|
||||
add %g1, 0x20, %g1; \
|
||||
ldxa [%g1 + %g0] ASI, %l4; \
|
||||
ldxa [%g1 + %g2] ASI, %l5; \
|
||||
ldxa [%g1 + %g3] ASI, %l6; \
|
||||
ldxa [%g1 + %g5] ASI, %l7; \
|
||||
add %g1, 0x20, %g1; \
|
||||
ldxa [%g1 + %g0] ASI, %i0; \
|
||||
ldxa [%g1 + %g2] ASI, %i1; \
|
||||
ldxa [%g1 + %g3] ASI, %i2; \
|
||||
ldxa [%g1 + %g5] ASI, %i3; \
|
||||
add %g1, 0x20, %g1; \
|
||||
ldxa [%g1 + %g0] ASI, %i4; \
|
||||
ldxa [%g1 + %g2] ASI, %i5; \
|
||||
ldxa [%g1 + %g3] ASI, %i6; \
|
||||
ldxa [%g1 + %g5] ASI, %i7; \
|
||||
restored; \
|
||||
retry; nop; nop; nop; nop; \
|
||||
b,a,pt %xcc, fill_fixup_dax; \
|
||||
b,a,pt %xcc, fill_fixup_mna; \
|
||||
b,a,pt %xcc, fill_fixup;
|
||||
|
||||
/* Normal 32bit fill */
|
||||
#define FILL_2_GENERIC(ASI) \
|
||||
srl %sp, 0, %sp; \
|
||||
lduwa [%sp + %g0] ASI, %l0; \
|
||||
mov 0x04, %g2; \
|
||||
mov 0x08, %g3; \
|
||||
lduwa [%sp + %g2] ASI, %l1; \
|
||||
mov 0x0c, %g5; \
|
||||
lduwa [%sp + %g3] ASI, %l2; \
|
||||
lduwa [%sp + %g5] ASI, %l3; \
|
||||
add %sp, 0x10, %g1; \
|
||||
lduwa [%g1 + %g0] ASI, %l4; \
|
||||
lduwa [%g1 + %g2] ASI, %l5; \
|
||||
lduwa [%g1 + %g3] ASI, %l6; \
|
||||
lduwa [%g1 + %g5] ASI, %l7; \
|
||||
add %g1, 0x10, %g1; \
|
||||
lduwa [%g1 + %g0] ASI, %i0; \
|
||||
lduwa [%g1 + %g2] ASI, %i1; \
|
||||
lduwa [%g1 + %g3] ASI, %i2; \
|
||||
lduwa [%g1 + %g5] ASI, %i3; \
|
||||
add %g1, 0x10, %g1; \
|
||||
lduwa [%g1 + %g0] ASI, %i4; \
|
||||
lduwa [%g1 + %g2] ASI, %i5; \
|
||||
lduwa [%g1 + %g3] ASI, %i6; \
|
||||
lduwa [%g1 + %g5] ASI, %i7; \
|
||||
restored; \
|
||||
retry; nop; nop; nop; nop; \
|
||||
b,a,pt %xcc, fill_fixup_dax; \
|
||||
b,a,pt %xcc, fill_fixup_mna; \
|
||||
b,a,pt %xcc, fill_fixup;
|
||||
|
||||
#define FILL_1_NORMAL FILL_1_GENERIC(ASI_AIUP)
|
||||
#define FILL_2_NORMAL FILL_2_GENERIC(ASI_AIUP)
|
||||
#define FILL_3_NORMAL FILL_0_NORMAL
|
||||
#define FILL_4_NORMAL FILL_0_NORMAL
|
||||
#define FILL_5_NORMAL FILL_0_NORMAL
|
||||
#define FILL_6_NORMAL FILL_0_NORMAL
|
||||
#define FILL_7_NORMAL FILL_0_NORMAL
|
||||
|
||||
#define FILL_0_OTHER FILL_0_NORMAL
|
||||
#define FILL_1_OTHER FILL_1_GENERIC(ASI_AIUS)
|
||||
#define FILL_2_OTHER FILL_2_GENERIC(ASI_AIUS)
|
||||
#define FILL_3_OTHER FILL_3_NORMAL
|
||||
#define FILL_4_OTHER FILL_4_NORMAL
|
||||
#define FILL_5_OTHER FILL_5_NORMAL
|
||||
#define FILL_6_OTHER FILL_6_NORMAL
|
||||
#define FILL_7_OTHER FILL_7_NORMAL
|
||||
|
||||
#endif /* !(_SPARC64_TTABLE_H) */
|
||||
322
arch/sparc64/vectors.S
Normal file
322
arch/sparc64/vectors.S
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* <vectors.S>
|
||||
*
|
||||
* Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions.
|
||||
*
|
||||
* Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License V2
|
||||
* as published by the Free Software Foundation
|
||||
*/
|
||||
|
||||
#define __ASSEMBLY__
|
||||
#include "pstate.h"
|
||||
#include "asi.h"
|
||||
#include "ttable.h"
|
||||
#define ASI_BP ASI_PHYS_BYPASS_EC_E
|
||||
#define SER_ADDR 0x1fe020003f8
|
||||
|
||||
.section ".text.vectors", "ax"
|
||||
.align 16384
|
||||
/* Sparc64 trap table */
|
||||
.globl trap_table, __divide_error
|
||||
.register %g2, #scratch
|
||||
.register %g3, #scratch
|
||||
.register %g6, #scratch
|
||||
.register %g7, #scratch
|
||||
trap_table:
|
||||
#undef TRAP_IRQ
|
||||
#define TRAP_IRQ(routine, level) \
|
||||
ba routine; nop; nop; nop; nop; nop; nop; nop;
|
||||
#undef BTRAP
|
||||
#define BTRAP(lvl) \
|
||||
ba bug; mov lvl, %g1; nop; nop; nop; nop; nop; nop;
|
||||
#undef BTRAPTL1
|
||||
#define BTRAPTL1(lvl) BTRAP(lvl)
|
||||
#define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7)
|
||||
|
||||
#define STACK_BIAS 2047
|
||||
.globl sparc64_ttable_tl0, sparc64_ttable_tl1
|
||||
sparc64_ttable_tl0:
|
||||
ba entry; nop; nop; nop; nop; nop; nop; nop;
|
||||
BTRAP(0x01) BTRAP(0x02) BTRAP(0x03) BTRAP(0x04) BTRAP(0x05) BTRAP(0x06) BTRAP(0x07)
|
||||
BTRAPS(0x08)
|
||||
BTRAPS(0x10) BTRAPS(0x18)
|
||||
BTRAP(0x20) BTRAP(0x21) BTRAP(0x22) BTRAP(0x23)
|
||||
CLEAN_WINDOW ! 24-27
|
||||
BTRAPS(0x28)
|
||||
BTRAPS(0x30) BTRAPS(0x38)
|
||||
#if 0
|
||||
BTRAP(0x40) BTRAP(0x41) BTRAP(0x42) BTRAP(0x43)
|
||||
tl0_irq4: TRAP_IRQ(handler_irq, 4)
|
||||
tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6)
|
||||
tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8)
|
||||
tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10)
|
||||
tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12)
|
||||
tl0_irq13: TRAP_IRQ(handler_irq, 13)
|
||||
tl0_irq14: TRAP_IRQ(handler_irq, 14)
|
||||
tl0_irq15: TRAP_IRQ(handler_irq, 15)
|
||||
#else
|
||||
BTRAPS(0x40) BTRAPS(0x48)
|
||||
#endif
|
||||
BTRAPS(0x50) BTRAPS(0x58)
|
||||
BTRAPS(0x60) BTRAPS(0x68)
|
||||
BTRAPS(0x70) BTRAPS(0x78)
|
||||
tl0_s0n: SPILL_0_NORMAL
|
||||
tl0_s1n: SPILL_1_NORMAL
|
||||
tl0_s2n: SPILL_2_NORMAL
|
||||
tl0_s3n: SPILL_3_NORMAL
|
||||
tl0_s4n: SPILL_4_NORMAL
|
||||
tl0_s5n: SPILL_5_NORMAL
|
||||
tl0_s6n: SPILL_6_NORMAL
|
||||
tl0_s7n: SPILL_7_NORMAL
|
||||
tl0_s0o: SPILL_0_OTHER
|
||||
tl0_s1o: SPILL_1_OTHER
|
||||
tl0_s2o: SPILL_2_OTHER
|
||||
tl0_s3o: SPILL_3_OTHER
|
||||
tl0_s4o: SPILL_4_OTHER
|
||||
tl0_s5o: SPILL_5_OTHER
|
||||
tl0_s6o: SPILL_6_OTHER
|
||||
tl0_s7o: SPILL_7_OTHER
|
||||
tl0_f0n: FILL_0_NORMAL
|
||||
tl0_f1n: FILL_1_NORMAL
|
||||
tl0_f2n: FILL_2_NORMAL
|
||||
tl0_f3n: FILL_3_NORMAL
|
||||
tl0_f4n: FILL_4_NORMAL
|
||||
tl0_f5n: FILL_5_NORMAL
|
||||
tl0_f6n: FILL_6_NORMAL
|
||||
tl0_f7n: FILL_7_NORMAL
|
||||
tl0_f0o: FILL_0_OTHER
|
||||
tl0_f1o: FILL_1_OTHER
|
||||
tl0_f2o: FILL_2_OTHER
|
||||
tl0_f3o: FILL_3_OTHER
|
||||
tl0_f4o: FILL_4_OTHER
|
||||
tl0_f5o: FILL_5_OTHER
|
||||
tl0_f6o: FILL_6_OTHER
|
||||
tl0_f7o: FILL_7_OTHER
|
||||
tl0_resv100: BTRAPS(0x100) BTRAPS(0x108)
|
||||
tl0_resv110: BTRAPS(0x110) BTRAPS(0x118)
|
||||
tl0_resv120: BTRAPS(0x120) BTRAPS(0x128)
|
||||
tl0_resv130: BTRAPS(0x130) BTRAPS(0x138)
|
||||
tl0_resv140: BTRAPS(0x140) BTRAPS(0x148)
|
||||
tl0_resv150: BTRAPS(0x150) BTRAPS(0x158)
|
||||
tl0_resv160: BTRAPS(0x160) BTRAPS(0x168)
|
||||
tl0_resv170: BTRAPS(0x170) BTRAPS(0x178)
|
||||
tl0_resv180: BTRAPS(0x180) BTRAPS(0x188)
|
||||
tl0_resv190: BTRAPS(0x190) BTRAPS(0x198)
|
||||
tl0_resv1a0: BTRAPS(0x1a0) BTRAPS(0x1a8)
|
||||
tl0_resv1b0: BTRAPS(0x1b0) BTRAPS(0x1b8)
|
||||
tl0_resv1c0: BTRAPS(0x1c0) BTRAPS(0x1c8)
|
||||
tl0_resv1d0: BTRAPS(0x1d0) BTRAPS(0x1d8)
|
||||
tl0_resv1e0: BTRAPS(0x1e0) BTRAPS(0x1e8)
|
||||
tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8)
|
||||
|
||||
#undef BTRAPS
|
||||
#define BTRAPS(x) BTRAPTL1(x) BTRAPTL1(x+1) BTRAPTL1(x+2) BTRAPTL1(x+3) BTRAPTL1(x+4) BTRAPTL1(x+5) BTRAPTL1(x+6) BTRAPTL1(x+7)
|
||||
|
||||
sparc64_ttable_tl1:
|
||||
BTRAPS(0x00) BTRAPS(0x08)
|
||||
BTRAPS(0x10) BTRAPS(0x18)
|
||||
BTRAPTL1(0x20) BTRAPTL1(0x21) BTRAPTL1(0x22) BTRAPTL1(0x23)
|
||||
CLEAN_WINDOW ! 24-27
|
||||
BTRAPS(0x28)
|
||||
BTRAPS(0x30) BTRAPS(0x38)
|
||||
#if 0
|
||||
BTRAPTL1(0x40) BTRAPTL1(0x41) BTRAPTL1(0x42) BTRAPTL1(0x43)
|
||||
tl1_irq4: TRAP_IRQ(handler_irq, 4)
|
||||
tl1_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6)
|
||||
tl1_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8)
|
||||
tl1_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10)
|
||||
tl1_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12)
|
||||
tl1_irq13: TRAP_IRQ(handler_irq, 13)
|
||||
tl1_irq14: TRAP_IRQ(handler_irq, 14)
|
||||
tl1_irq15: TRAP_IRQ(handler_irq, 15)
|
||||
#else
|
||||
BTRAPS(0x40) BTRAPS(0x48)
|
||||
#endif
|
||||
BTRAPS(0x50) BTRAPS(0x58)
|
||||
BTRAPS(0x60) BTRAPS(0x68)
|
||||
BTRAPS(0x70) BTRAPS(0x78)
|
||||
tl1_s0n: SPILL_0_NORMAL
|
||||
tl1_s1n: SPILL_1_NORMAL
|
||||
tl1_s2n: SPILL_2_NORMAL
|
||||
tl1_s3n: SPILL_3_NORMAL
|
||||
tl1_s4n: SPILL_4_NORMAL
|
||||
tl1_s5n: SPILL_5_NORMAL
|
||||
tl1_s6n: SPILL_6_NORMAL
|
||||
tl1_s7n: SPILL_7_NORMAL
|
||||
tl1_s0o: SPILL_0_OTHER
|
||||
tl1_s1o: SPILL_1_OTHER
|
||||
tl1_s2o: SPILL_2_OTHER
|
||||
tl1_s3o: SPILL_3_OTHER
|
||||
tl1_s4o: SPILL_4_OTHER
|
||||
tl1_s5o: SPILL_5_OTHER
|
||||
tl1_s6o: SPILL_6_OTHER
|
||||
tl1_s7o: SPILL_7_OTHER
|
||||
tl1_f0n: FILL_0_NORMAL
|
||||
tl1_f1n: FILL_1_NORMAL
|
||||
tl1_f2n: FILL_2_NORMAL
|
||||
tl1_f3n: FILL_3_NORMAL
|
||||
tl1_f4n: FILL_4_NORMAL
|
||||
tl1_f5n: FILL_5_NORMAL
|
||||
tl1_f6n: FILL_6_NORMAL
|
||||
tl1_f7n: FILL_7_NORMAL
|
||||
tl1_f0o: FILL_0_OTHER
|
||||
tl1_f1o: FILL_1_OTHER
|
||||
tl1_f2o: FILL_2_OTHER
|
||||
tl1_f3o: FILL_3_OTHER
|
||||
tl1_f4o: FILL_4_OTHER
|
||||
tl1_f5o: FILL_5_OTHER
|
||||
tl1_f6o: FILL_6_OTHER
|
||||
tl1_f7o: FILL_7_OTHER
|
||||
tl1_resv100: BTRAPS(0x100) BTRAPS(0x108)
|
||||
tl1_resv110: BTRAPS(0x110) BTRAPS(0x118)
|
||||
tl1_resv120: BTRAPS(0x120) BTRAPS(0x128)
|
||||
tl1_resv130: BTRAPS(0x130) BTRAPS(0x138)
|
||||
tl1_resv140: BTRAPS(0x140) BTRAPS(0x148)
|
||||
tl1_resv150: BTRAPS(0x150) BTRAPS(0x158)
|
||||
tl1_resv160: BTRAPS(0x160) BTRAPS(0x168)
|
||||
tl1_resv170: BTRAPS(0x170) BTRAPS(0x178)
|
||||
tl1_resv180: BTRAPS(0x180) BTRAPS(0x188)
|
||||
tl1_resv190: BTRAPS(0x190) BTRAPS(0x198)
|
||||
tl1_resv1a0: BTRAPS(0x1a0) BTRAPS(0x1a8)
|
||||
tl1_resv1b0: BTRAPS(0x1b0) BTRAPS(0x1b8)
|
||||
tl1_resv1c0: BTRAPS(0x1c0) BTRAPS(0x1c8)
|
||||
tl1_resv1d0: BTRAPS(0x1d0) BTRAPS(0x1d8)
|
||||
tl1_resv1e0: BTRAPS(0x1e0) BTRAPS(0x1e8)
|
||||
tl1_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8)
|
||||
|
||||
spill_fixup:
|
||||
spill_fixup_dax:
|
||||
spill_fixup_mna:
|
||||
fill_fixup:
|
||||
fill_fixup_dax:
|
||||
fill_fixup_mna:
|
||||
__divide_error:
|
||||
bug:
|
||||
/* Dump the exception and its context */
|
||||
! Set up CPU state
|
||||
wrpr %g0, PSTATE_PRIV, %pstate
|
||||
wr %g0, 0, %fprs
|
||||
wrpr %g0, 0x0, %tl
|
||||
|
||||
! Disable I/D MMUs and caches
|
||||
stxa %g0, [%g0] ASI_LSU_CONTROL
|
||||
|
||||
! Extract NWINDOWS from %ver
|
||||
rdpr %ver, %g2
|
||||
and %g2, 0xf, %g2
|
||||
wrpr %g2, 0, %cleanwin
|
||||
wrpr %g2, 0, %cansave
|
||||
wrpr %g0, 0, %canrestore
|
||||
wrpr %g0, 0, %otherwin
|
||||
wrpr %g0, 0, %wstate
|
||||
|
||||
call dump_exception
|
||||
nop
|
||||
_forever:
|
||||
/* Loop forever */
|
||||
b _forever ;
|
||||
nop
|
||||
outstr:
|
||||
/* void outstr (unsigned long port, const unsigned char *str);
|
||||
* Writes a string on an IO port.
|
||||
*/
|
||||
1: ldub [%o1], %o3
|
||||
cmp %o3, 0
|
||||
be 2f
|
||||
nop
|
||||
stba %o3, [%o0] ASI_BP
|
||||
b 1b
|
||||
inc %o1
|
||||
2: retl
|
||||
nop
|
||||
|
||||
outdigit:
|
||||
/* void outdigit (unsigned long port, uint8_t digit);
|
||||
* Dumps a single digit on serial port.
|
||||
*/
|
||||
add %o1, '0', %o1
|
||||
retl
|
||||
stba %o1, [%o0] ASI_BP
|
||||
|
||||
outhex:
|
||||
/* void outhex (unsigned long port, uint64_t value);
|
||||
* Dumps a 64 bits hex number on serial port
|
||||
*/
|
||||
mov %o1, %o2
|
||||
set 60, %o3
|
||||
srlx %o2, %o3, %o1
|
||||
1: and %o1, 0xf, %o1
|
||||
cmp %o1, 9
|
||||
bgt 2f
|
||||
nop
|
||||
b 3f
|
||||
add %o1, '0', %o1
|
||||
2: add %o1, 'a' - 10, %o1
|
||||
3: stba %o1, [%o0] ASI_BP
|
||||
subcc %o3, 4, %o3
|
||||
bge 1b
|
||||
srlx %o2, %o3, %o1
|
||||
retl
|
||||
nop
|
||||
|
||||
/* void dump_exception ();
|
||||
*
|
||||
* Dump a message when catching an exception
|
||||
*/
|
||||
dump_exception:
|
||||
setx SER_ADDR, %o3, %o0
|
||||
setx (_BUG_message_0), %o3, %o1
|
||||
call outstr
|
||||
nop
|
||||
|
||||
call outhex
|
||||
mov %g1, %o1
|
||||
|
||||
setx (_BUG_message_1), %o3, %o1
|
||||
call outstr
|
||||
nop
|
||||
|
||||
call outhex
|
||||
rdpr %tpc, %o1
|
||||
|
||||
setx (_BUG_message_2), %o3, %o1
|
||||
call outstr
|
||||
nop
|
||||
|
||||
call outhex
|
||||
rdpr %tnpc, %o1
|
||||
|
||||
setx (_BUG_message_3), %o3, %o1
|
||||
call outstr
|
||||
nop
|
||||
|
||||
retl
|
||||
nop
|
||||
|
||||
//#include "winfixup.S"
|
||||
|
||||
.section .rodata
|
||||
_BUG_message_0:
|
||||
.string "Unhandled Exception 0x"
|
||||
_BUG_message_1:
|
||||
.string "\nPC = 0x"
|
||||
_BUG_message_2:
|
||||
.string " NPC = 0x"
|
||||
_BUG_message_3:
|
||||
.string "\nStopping execution\n"
|
||||
240
arch/sparc64/winfixup.S
Normal file
240
arch/sparc64/winfixup.S
Normal file
@@ -0,0 +1,240 @@
|
||||
/* $Id: winfixup.S,v 1.30 2002/02/09 19:49:30 davem Exp $
|
||||
*
|
||||
* winfixup.S: Handle cases where user stack pointer is found to be bogus.
|
||||
*
|
||||
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
|
||||
#include "asi.h"
|
||||
#include "spitfire.h"
|
||||
#if 0
|
||||
#include <asm/head.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/thread_info.h>
|
||||
#else
|
||||
#define FAULT_CODE_WRITE 0x01 /* Write access, implies D-TLB */
|
||||
#define FAULT_CODE_DTLB 0x02 /* Miss happened in D-TLB */
|
||||
#define FAULT_CODE_ITLB 0x04 /* Miss happened in I-TLB */
|
||||
#define FAULT_CODE_WINFIXUP 0x08 /* Miss happened during spill/fill */
|
||||
#define FAULT_CODE_BLKCOMMIT 0x10 /* Use blk-commit ASI in copy_page */
|
||||
#endif
|
||||
.text
|
||||
.align 32
|
||||
|
||||
/* Here are the rules, pay attention.
|
||||
*
|
||||
* The kernel is disallowed from touching user space while
|
||||
* the trap level is greater than zero, except for from within
|
||||
* the window spill/fill handlers. This must be followed
|
||||
* so that we can easily detect the case where we tried to
|
||||
* spill/fill with a bogus (or unmapped) user stack pointer.
|
||||
*
|
||||
* These are layed out in a special way for cache reasons,
|
||||
* don't touch...
|
||||
*/
|
||||
.globl fill_fixup, spill_fixup
|
||||
fill_fixup:
|
||||
rdpr %tstate, %g1
|
||||
or %g4, FAULT_CODE_WINFIXUP, %g4
|
||||
and %g1, TSTATE_CWP, %g1
|
||||
|
||||
/* This is the extremely complex case, but it does happen from
|
||||
* time to time if things are just right. Essentially the restore
|
||||
* done in rtrap right before going back to user mode, with tl=1
|
||||
* and that levels trap stack registers all setup, took a fill trap,
|
||||
* the user stack was not mapped in the tlb, and tlb miss occurred,
|
||||
* the pte found was not valid, and a simple ref bit watch update
|
||||
* could not satisfy the miss, so we got here.
|
||||
*
|
||||
* We must carefully unwind the state so we get back to tl=0, preserve
|
||||
* all the register values we were going to give to the user. Luckily
|
||||
* most things are where they need to be, we also have the address
|
||||
* which triggered the fault handy as well.
|
||||
*
|
||||
* Also note that we must preserve %l5 and %l6. If the user was
|
||||
* returning from a system call, we must make it look this way
|
||||
* after we process the fill fault on the users stack.
|
||||
*
|
||||
* First, get into the window where the original restore was executed.
|
||||
*/
|
||||
|
||||
rdpr %wstate, %g2 ! Grab user mode wstate.
|
||||
wrpr %g1, %cwp ! Get into the right window.
|
||||
sll %g2, 3, %g2 ! NORMAL-->OTHER
|
||||
|
||||
wrpr %g0, 0x0, %canrestore ! Standard etrap stuff.
|
||||
wrpr %g2, 0x0, %wstate ! This must be consistent.
|
||||
wrpr %g0, 0x0, %otherwin ! We know this.
|
||||
mov PRIMARY_CONTEXT, %g1 ! Change contexts...
|
||||
stxa %g0, [%g1] ASI_DMMU ! Back into the nucleus.
|
||||
flush %g6 ! Flush instruction buffers
|
||||
rdpr %pstate, %l1 ! Prepare to change globals.
|
||||
mov %g6, %o7 ! Get current.
|
||||
|
||||
andn %l1, PSTATE_MM, %l1 ! We want to be in RMO
|
||||
stb %g4, [%g6 + TI_FAULT_CODE]
|
||||
stx %g5, [%g6 + TI_FAULT_ADDR]
|
||||
wrpr %g0, 0x0, %tl ! Out of trap levels.
|
||||
wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
|
||||
mov %o7, %g6
|
||||
ldx [%g6 + TI_TASK], %g4
|
||||
|
||||
/* This is the same as below, except we handle this a bit special
|
||||
* since we must preserve %l5 and %l6, see comment above.
|
||||
*/
|
||||
call do_sparc64_fault
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop ! yes, nop is correct
|
||||
|
||||
/* Be very careful about usage of the alternate globals here.
|
||||
* You cannot touch %g4/%g5 as that has the fault information
|
||||
* should this be from usermode. Also be careful for the case
|
||||
* where we get here from the save instruction in etrap.S when
|
||||
* coming from either user or kernel (does not matter which, it
|
||||
* is the same problem in both cases). Essentially this means
|
||||
* do not touch %g7 or %g2 so we handle the two cases fine.
|
||||
*/
|
||||
spill_fixup:
|
||||
ldx [%g6 + TI_FLAGS], %g1
|
||||
andcc %g1, _TIF_32BIT, %g0
|
||||
ldub [%g6 + TI_WSAVED], %g1
|
||||
|
||||
sll %g1, 3, %g3
|
||||
add %g6, %g3, %g3
|
||||
stx %sp, [%g3 + TI_RWIN_SPTRS]
|
||||
sll %g1, 7, %g3
|
||||
bne,pt %xcc, 1f
|
||||
add %g6, %g3, %g3
|
||||
stx %l0, [%g3 + TI_REG_WINDOW + 0x00]
|
||||
stx %l1, [%g3 + TI_REG_WINDOW + 0x08]
|
||||
|
||||
stx %l2, [%g3 + TI_REG_WINDOW + 0x10]
|
||||
stx %l3, [%g3 + TI_REG_WINDOW + 0x18]
|
||||
stx %l4, [%g3 + TI_REG_WINDOW + 0x20]
|
||||
stx %l5, [%g3 + TI_REG_WINDOW + 0x28]
|
||||
stx %l6, [%g3 + TI_REG_WINDOW + 0x30]
|
||||
stx %l7, [%g3 + TI_REG_WINDOW + 0x38]
|
||||
stx %i0, [%g3 + TI_REG_WINDOW + 0x40]
|
||||
stx %i1, [%g3 + TI_REG_WINDOW + 0x48]
|
||||
|
||||
stx %i2, [%g3 + TI_REG_WINDOW + 0x50]
|
||||
stx %i3, [%g3 + TI_REG_WINDOW + 0x58]
|
||||
stx %i4, [%g3 + TI_REG_WINDOW + 0x60]
|
||||
stx %i5, [%g3 + TI_REG_WINDOW + 0x68]
|
||||
stx %i6, [%g3 + TI_REG_WINDOW + 0x70]
|
||||
b,pt %xcc, 2f
|
||||
stx %i7, [%g3 + TI_REG_WINDOW + 0x78]
|
||||
1: stw %l0, [%g3 + TI_REG_WINDOW + 0x00]
|
||||
|
||||
stw %l1, [%g3 + TI_REG_WINDOW + 0x04]
|
||||
stw %l2, [%g3 + TI_REG_WINDOW + 0x08]
|
||||
stw %l3, [%g3 + TI_REG_WINDOW + 0x0c]
|
||||
stw %l4, [%g3 + TI_REG_WINDOW + 0x10]
|
||||
stw %l5, [%g3 + TI_REG_WINDOW + 0x14]
|
||||
stw %l6, [%g3 + TI_REG_WINDOW + 0x18]
|
||||
stw %l7, [%g3 + TI_REG_WINDOW + 0x1c]
|
||||
stw %i0, [%g3 + TI_REG_WINDOW + 0x20]
|
||||
|
||||
stw %i1, [%g3 + TI_REG_WINDOW + 0x24]
|
||||
stw %i2, [%g3 + TI_REG_WINDOW + 0x28]
|
||||
stw %i3, [%g3 + TI_REG_WINDOW + 0x2c]
|
||||
stw %i4, [%g3 + TI_REG_WINDOW + 0x30]
|
||||
stw %i5, [%g3 + TI_REG_WINDOW + 0x34]
|
||||
stw %i6, [%g3 + TI_REG_WINDOW + 0x38]
|
||||
stw %i7, [%g3 + TI_REG_WINDOW + 0x3c]
|
||||
2: add %g1, 1, %g1
|
||||
|
||||
stb %g1, [%g6 + TI_WSAVED]
|
||||
rdpr %tstate, %g1
|
||||
saved
|
||||
and %g1, TSTATE_CWP, %g1
|
||||
mov FAULT_CODE_WRITE | FAULT_CODE_DTLB | FAULT_CODE_WINFIXUP, %g4
|
||||
retry
|
||||
|
||||
.globl winfix_mna, fill_fixup_mna, spill_fixup_mna
|
||||
winfix_mna:
|
||||
andn %g3, 0x7f, %g3
|
||||
add %g3, 0x78, %g3
|
||||
wrpr %g3, %tnpc
|
||||
done
|
||||
fill_fixup_mna:
|
||||
rdpr %tstate, %g1
|
||||
and %g1, TSTATE_CWP, %g1
|
||||
|
||||
/* Please, see fill_fixup commentary about why we must preserve
|
||||
* %l5 and %l6 to preserve absolute correct semantics.
|
||||
*/
|
||||
rdpr %wstate, %g2 ! Grab user mode wstate.
|
||||
wrpr %g1, %cwp ! Get into the right window.
|
||||
sll %g2, 3, %g2 ! NORMAL-->OTHER
|
||||
wrpr %g0, 0x0, %canrestore ! Standard etrap stuff.
|
||||
|
||||
wrpr %g2, 0x0, %wstate ! This must be consistent.
|
||||
wrpr %g0, 0x0, %otherwin ! We know this.
|
||||
mov PRIMARY_CONTEXT, %g1 ! Change contexts...
|
||||
stxa %g0, [%g1] ASI_DMMU ! Back into the nucleus.
|
||||
flush %g6 ! Flush instruction buffers
|
||||
rdpr %pstate, %l1 ! Prepare to change globals.
|
||||
mov %g4, %o2 ! Setup args for
|
||||
mov %g5, %o1 ! final call to mem_address_unaligned.
|
||||
andn %l1, PSTATE_MM, %l1 ! We want to be in RMO
|
||||
|
||||
mov %g6, %o7 ! Stash away current.
|
||||
wrpr %g0, 0x0, %tl ! Out of trap levels.
|
||||
wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
|
||||
mov %o7, %g6 ! Get current back.
|
||||
ldx [%g6 + TI_TASK], %g4 ! Finish it.
|
||||
call mem_address_unaligned
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
|
||||
b,pt %xcc, rtrap
|
||||
nop ! yes, the nop is correct
|
||||
spill_fixup_mna:
|
||||
ldx [%g6 + TI_FLAGS], %g1
|
||||
andcc %g1, _TIF_32BIT, %g0
|
||||
ldub [%g6 + TI_WSAVED], %g1
|
||||
sll %g1, 3, %g3
|
||||
add %g6, %g3, %g3
|
||||
stx %sp, [%g3 + TI_RWIN_SPTRS]
|
||||
|
||||
sll %g1, 7, %g3
|
||||
bne,pt %xcc, 1f
|
||||
add %g6, %g3, %g3
|
||||
stx %l0, [%g3 + TI_REG_WINDOW + 0x00]
|
||||
stx %l1, [%g3 + TI_REG_WINDOW + 0x08]
|
||||
stx %l2, [%g3 + TI_REG_WINDOW + 0x10]
|
||||
stx %l3, [%g3 + TI_REG_WINDOW + 0x18]
|
||||
stx %l4, [%g3 + TI_REG_WINDOW + 0x20]
|
||||
|
||||
stx %l5, [%g3 + TI_REG_WINDOW + 0x28]
|
||||
stx %l6, [%g3 + TI_REG_WINDOW + 0x30]
|
||||
stx %l7, [%g3 + TI_REG_WINDOW + 0x38]
|
||||
stx %i0, [%g3 + TI_REG_WINDOW + 0x40]
|
||||
stx %i1, [%g3 + TI_REG_WINDOW + 0x48]
|
||||
stx %i2, [%g3 + TI_REG_WINDOW + 0x50]
|
||||
stx %i3, [%g3 + TI_REG_WINDOW + 0x58]
|
||||
stx %i4, [%g3 + TI_REG_WINDOW + 0x60]
|
||||
|
||||
stx %i5, [%g3 + TI_REG_WINDOW + 0x68]
|
||||
stx %i6, [%g3 + TI_REG_WINDOW + 0x70]
|
||||
stx %i7, [%g3 + TI_REG_WINDOW + 0x78]
|
||||
b,pt %xcc, 2f
|
||||
add %g1, 1, %g1
|
||||
1: std %l0, [%g3 + TI_REG_WINDOW + 0x00]
|
||||
std %l2, [%g3 + TI_REG_WINDOW + 0x08]
|
||||
std %l4, [%g3 + TI_REG_WINDOW + 0x10]
|
||||
|
||||
std %l6, [%g3 + TI_REG_WINDOW + 0x18]
|
||||
std %i0, [%g3 + TI_REG_WINDOW + 0x20]
|
||||
std %i2, [%g3 + TI_REG_WINDOW + 0x28]
|
||||
std %i4, [%g3 + TI_REG_WINDOW + 0x30]
|
||||
std %i6, [%g3 + TI_REG_WINDOW + 0x38]
|
||||
add %g1, 1, %g1
|
||||
2: stb %g1, [%g6 + TI_WSAVED]
|
||||
|
||||
saved
|
||||
retry
|
||||
|
||||
76
config/examples/cross-sparc64_config.xml
Normal file
76
config/examples/cross-sparc64_config.xml
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0"?>
|
||||
<config>
|
||||
|
||||
<!-- generic -->
|
||||
<option name="CONFIG_SPARC" type="boolean" value="true"/>
|
||||
<option name="CONFIG_SPARC64" type="boolean" value="true"/>
|
||||
<option name="CONFIG_BIG_ENDIAN" type="boolean" value="true"/>
|
||||
|
||||
<!-- kernel binaries (SPARC64) -->
|
||||
<option name="CONFIG_IMAGE_ELF" type="boolean" value="true"/>
|
||||
<option name="CONFIG_IMAGE_ELF_EMBEDDED" type="boolean" value="true"/>
|
||||
<option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/>
|
||||
|
||||
<!-- Build hosted UNIX Binary -->
|
||||
<option name="CONFIG_HOST_UNIX" type="boolean" value="false"/>
|
||||
<option name="CONFIG_UNIX_QT" type="boolean" value="false"/>
|
||||
<option name="CONFIG_PLUGINS" type="boolean" value="false"/>
|
||||
|
||||
<!-- Kernel Debugging -->
|
||||
<option name="CONFIG_DEBUG" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_BOOT" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_SUN_PARTS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_SERIAL_PORT" type="integer" value="0"/>
|
||||
<option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/>
|
||||
<option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/>
|
||||
|
||||
|
||||
<!-- Module Configuration -->
|
||||
<option name="CONFIG_CMDLINE" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBLOCKER" type="boolean" value="true"/>
|
||||
|
||||
|
||||
<!-- Filesystem Configuration -->
|
||||
<option name="CONFIG_DISK_LABEL" type="boolean" value="true"/>
|
||||
<option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/>
|
||||
<option name="CONFIG_PC_PARTS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_SUN_PARTS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_HFS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_HFSP" type="boolean" value="true"/>
|
||||
<option name="CONFIG_GRUBFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_FAT" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_JFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_MINIX" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_REISERFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_XFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_UFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_ISO9660" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_FFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_VSTAFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_FSYS_AFFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_FS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_EXT2FS" type="boolean" value="false"/>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<option name="CONFIG_LINUXBIOS" type="boolean" value="false"/>
|
||||
|
||||
<!-- Drivers -->
|
||||
<option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_PCI" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/>
|
||||
<option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="4"/>
|
||||
<option name="CONFIG_DEBUG_IDE" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="true"/>
|
||||
|
||||
</config>
|
||||
|
||||
82
config/examples/cross-sparc64_rules.xml
Normal file
82
config/examples/cross-sparc64_rules.xml
Normal file
@@ -0,0 +1,82 @@
|
||||
<rules>
|
||||
|
||||
<pre><![CDATA[
|
||||
#
|
||||
# Autogenerated OpenBIOS Makefile
|
||||
# (C) 2004-2006 by the OpenBIOS team
|
||||
#
|
||||
|
||||
ARCH := sparc64
|
||||
ODIR := obj-$(ARCH)
|
||||
HOSTCC := gcc
|
||||
CROSSCFLAGS := -DNATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH -DSWAP_ENDIANNESS
|
||||
HOSTCFLAGS := -O2 -g -Wall -W -DFCOMPILER -DBOOTSTRAP $(CROSSCFLAGS)
|
||||
HOSTINCLUDES := -Iinclude -Ikernel/include -I$(ODIR)/target/include
|
||||
|
||||
CC := sparc-linux-gcc
|
||||
AS := sparc-linux-as
|
||||
AR := sparc-linux-ar
|
||||
LD := sparc-linux-ld
|
||||
NM := sparc-linux-nm
|
||||
STRIP := sparc-linux-strip
|
||||
RANLIB := sparc-linux-ranlib
|
||||
CFLAGS := -Os -Wall -W -DNATIVE_BITWIDTH_EQUALS_HOST_BITWIDTH -USWAP_ENDIANNESS -fno-builtin -g
|
||||
CFLAGS+= -Wa,-xarch=v9 -Wa,-64 -m64 -mcpu=ultrasparc -mcmodel=medany
|
||||
CFLAGS+= -Wredundant-decls -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-declarations
|
||||
CFLAGS+= -Wundef -Wendif-labels -Wstrict-aliasing
|
||||
INCLUDES := -Iinclude -Ikernel/include -I$(ODIR)/target/include
|
||||
AS_FLAGS := -Wa,-xarch=v9 -Wa,-64 -g
|
||||
|
||||
#
|
||||
# pre rules
|
||||
#
|
||||
|
||||
all: versions dictionaries host-libraries target-libraries host-executables target-executables
|
||||
|
||||
VERSION := "1.0RC1"
|
||||
|
||||
versions: $(ODIR)/target/include/openbios-version.h $(ODIR)/forth/version.fs
|
||||
|
||||
$(ODIR)/forth/version.fs:
|
||||
@DATE="$(shell echo `date +'%b %e %Y %H:%M'`)" ; \
|
||||
( echo ": builddate \" $$DATE\" ; " ; \
|
||||
echo ": version \" $(VERSION)\" ; " ; ) \
|
||||
> $(dir $@)/version.fs
|
||||
|
||||
$(ODIR)/target/include/openbios-version.h:
|
||||
@DATE="$(shell echo `date +'%b %e %Y %H:%M'`)" ; \
|
||||
( echo "#define OPENBIOS_BUILD_DATE \"$$DATE\"" ; \
|
||||
echo "#define OPENBIOS_VERSION_STR \"$(VERSION)\"" ; \
|
||||
echo "#define OPENBIOS_RELEASE \"$(VERSION)\"" ; ) \
|
||||
> $(dir $@)/openbios-version.h
|
||||
]]></pre>
|
||||
|
||||
<!-- host compiler build rules -->
|
||||
|
||||
<rule target="host" entity="executable">
|
||||
$(HOSTCC) $(HOSTCFLAGS) -o $@ $^
|
||||
</rule>
|
||||
|
||||
<rule target="host" entity="object">
|
||||
$(HOSTCC) $(HOSTCFLAGS) $(HOSTINCLUDES) -c -o $@ $^
|
||||
</rule>
|
||||
|
||||
<rule target="host" entity="library">
|
||||
$(AR) cru $@ $^; $(RANLIB) $@
|
||||
</rule>
|
||||
|
||||
<!-- target/cross compiler build rules -->
|
||||
|
||||
<rule target="target" entity="executable">
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
</rule>
|
||||
|
||||
<rule target="target" entity="object">
|
||||
$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $^
|
||||
</rule>
|
||||
|
||||
<rule target="target" entity="library">
|
||||
$(AR) cru $@ $^; $(RANLIB) $@
|
||||
</rule>
|
||||
|
||||
</rules>
|
||||
76
config/examples/sparc64_config.xml
Normal file
76
config/examples/sparc64_config.xml
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0"?>
|
||||
<config>
|
||||
|
||||
<!-- generic -->
|
||||
<option name="CONFIG_SPARC" type="boolean" value="true"/>
|
||||
<option name="CONFIG_SPARC64" type="boolean" value="true"/>
|
||||
<option name="CONFIG_BIG_ENDIAN" type="boolean" value="true"/>
|
||||
|
||||
<!-- kernel binaries (SPARC64) -->
|
||||
<option name="CONFIG_IMAGE_ELF" type="boolean" value="true"/>
|
||||
<option name="CONFIG_IMAGE_ELF_EMBEDDED" type="boolean" value="true"/>
|
||||
<option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/>
|
||||
|
||||
<!-- Build hosted UNIX Binary -->
|
||||
<option name="CONFIG_HOST_UNIX" type="boolean" value="true"/>
|
||||
<option name="CONFIG_UNIX_QT" type="boolean" value="false"/>
|
||||
<option name="CONFIG_PLUGINS" type="boolean" value="false"/>
|
||||
|
||||
<!-- Kernel Debugging -->
|
||||
<option name="CONFIG_DEBUG" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_BOOT" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_SUN_PARTS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_SERIAL_PORT" type="integer" value="0"/>
|
||||
<option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/>
|
||||
<option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/>
|
||||
|
||||
|
||||
<!-- Module Configuration -->
|
||||
<option name="CONFIG_CMDLINE" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBLOCKER" type="boolean" value="true"/>
|
||||
|
||||
|
||||
<!-- Filesystem Configuration -->
|
||||
<option name="CONFIG_DISK_LABEL" type="boolean" value="true"/>
|
||||
<option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/>
|
||||
<option name="CONFIG_PC_PARTS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_SUN_PARTS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_HFS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_HFSP" type="boolean" value="true"/>
|
||||
<option name="CONFIG_GRUBFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_FAT" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_JFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_MINIX" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_REISERFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_XFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_UFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_ISO9660" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_FFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_VSTAFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_FSYS_AFFS" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_FS" type="boolean" value="false"/>
|
||||
<option name="CONFIG_DEBUG_EXT2FS" type="boolean" value="false"/>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<option name="CONFIG_LINUXBIOS" type="boolean" value="false"/>
|
||||
|
||||
<!-- Drivers -->
|
||||
<option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DEBUG_PCI" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/>
|
||||
<option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="4"/>
|
||||
<option name="CONFIG_DEBUG_IDE" type="boolean" value="true"/>
|
||||
<option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="true"/>
|
||||
|
||||
</config>
|
||||
|
||||
88
config/examples/sparc64_rules.xml
Normal file
88
config/examples/sparc64_rules.xml
Normal file
@@ -0,0 +1,88 @@
|
||||
<rules>
|
||||
|
||||
<pre><![CDATA[
|
||||
#
|
||||
# Autogenerated OpenBIOS Makefile
|
||||
# (C) 2004-2006 by the OpenBIOS team
|
||||
#
|
||||
|
||||
ARCH := sparc64
|
||||
ODIR := obj-$(ARCH)
|
||||
HOSTCC := gcc
|
||||
CROSSCFLAGS := -DNATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH -USWAP_ENDIANNESS
|
||||
HOSTCFLAGS := -O2 -g -Wall -W -DFCOMPILER -DBOOTSTRAP $(CROSSCFLAGS)
|
||||
HOSTINCLUDES := -Iinclude -Ikernel/include -I$(ODIR)/target/include
|
||||
|
||||
CC := gcc
|
||||
AS := as
|
||||
AR := ar
|
||||
LD := ld
|
||||
NM := nm
|
||||
STRIP := strip
|
||||
RANLIB := ranlib
|
||||
INSTALL := install
|
||||
|
||||
ifeq ($(shell uname), Linux)
|
||||
LIBDL_LDFLAGS=-ldl
|
||||
endif
|
||||
|
||||
CFLAGS := -Os -Wall -W -DNATIVE_BITWIDTH_EQUALS_HOST_BITWIDTH -USWAP_ENDIANNESS -fno-builtin -g
|
||||
CFLAGS+= -Wa,-xarch=v9 -Wa,-64 -m64 -mcpu=ultrasparc -mcmodel=medany
|
||||
CFLAGS+= -Wredundant-decls -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-declarations
|
||||
CFLAGS+= -Wundef -Wendif-labels -Wstrict-aliasing
|
||||
INCLUDES := -Iinclude -Ikernel/include -I$(ODIR)/target/include
|
||||
AS_FLAGS := -Wa,-xarch=v9 -Wa,-64 -g
|
||||
|
||||
#
|
||||
# pre rules
|
||||
#
|
||||
|
||||
all: versions dictionaries host-libraries target-libraries host-executables target-executables
|
||||
|
||||
VERSION := "1.0RC1"
|
||||
|
||||
versions: $(ODIR)/target/include/openbios-version.h $(ODIR)/forth/version.fs
|
||||
|
||||
$(ODIR)/forth/version.fs:
|
||||
@DATE="$(shell echo `date +'%b %e %Y %H:%M'`)" ; \
|
||||
( echo ": builddate \" $$DATE\" ; " ; \
|
||||
echo ": version \" $(VERSION)\" ; " ; ) \
|
||||
> $(dir $@)/version.fs
|
||||
|
||||
$(ODIR)/target/include/openbios-version.h:
|
||||
@DATE="$(shell echo `date +'%b %e %Y %H:%M'`)" ; \
|
||||
( echo "#define OPENBIOS_BUILD_DATE \"$$DATE\"" ; \
|
||||
echo "#define OPENBIOS_VERSION_STR \"$(VERSION)\"" ; \
|
||||
echo "#define OPENBIOS_RELEASE \"$(VERSION)\"" ; ) \
|
||||
> $(dir $@)/openbios-version.h
|
||||
]]></pre>
|
||||
|
||||
<!-- host compiler build rules -->
|
||||
|
||||
<rule target="host" entity="executable">
|
||||
$(HOSTCC) $(HOSTCFLAGS) -o $@ $^
|
||||
</rule>
|
||||
|
||||
<rule target="host" entity="object">
|
||||
$(HOSTCC) $(HOSTCFLAGS) $(HOSTINCLUDES) -c -o $@ $^
|
||||
</rule>
|
||||
|
||||
<rule target="host" entity="library">
|
||||
$(AR) cru $@ $^; $(RANLIB) $@
|
||||
</rule>
|
||||
|
||||
<!-- target/cross compiler build rules -->
|
||||
|
||||
<rule target="target" entity="executable">
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
</rule>
|
||||
|
||||
<rule target="target" entity="object">
|
||||
$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $^
|
||||
</rule>
|
||||
|
||||
<rule target="target" entity="library">
|
||||
$(AR) cru $@ $^; $(RANLIB) $@
|
||||
</rule>
|
||||
|
||||
</rules>
|
||||
5
include/sparc64/elf.h
Normal file
5
include/sparc64/elf.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#define ARCH_ELF_CLASS ELFCLASS64
|
||||
#define ARCH_ELF_DATA ELFDATA2MSB
|
||||
#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_SPARCV9)
|
||||
typedef Elf64_Ehdr Elf_ehdr;
|
||||
typedef Elf64_Phdr Elf_phdr;
|
||||
203
include/sparc64/io.h
Normal file
203
include/sparc64/io.h
Normal file
@@ -0,0 +1,203 @@
|
||||
#ifndef _ASM_IO_H
|
||||
#define _ASM_IO_H
|
||||
|
||||
#include "asm/types.h"
|
||||
|
||||
extern unsigned long va_shift; // Set in entry.S
|
||||
extern char _start, _data, _heap, _eheap, _stack, _estack, _end,
|
||||
_vmem, _evmem,_iomem; // Defined in ldscript
|
||||
|
||||
static inline unsigned long
|
||||
va2pa(unsigned long va)
|
||||
{
|
||||
if ((va >= (unsigned long)&_data) &&
|
||||
(va < (unsigned long)&_end))
|
||||
return va - va_shift;
|
||||
else
|
||||
return va;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
pa2va(unsigned long pa)
|
||||
{
|
||||
if ((pa + va_shift >= (unsigned long)&_data) &&
|
||||
(pa + va_shift< (unsigned long)&_end))
|
||||
return pa + va_shift;
|
||||
else
|
||||
return pa;
|
||||
}
|
||||
|
||||
// XXX check use and merge
|
||||
#define phys_to_virt(phys) ((void *) ((unsigned long) (phys)))
|
||||
#define virt_to_phys(virt) ((unsigned long) (virt))
|
||||
|
||||
#ifndef BOOTSTRAP
|
||||
|
||||
#ifndef _IO_BASE
|
||||
#define _IO_BASE 0x1fe02000000ULL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The insw/outsw/insl/outsl macros don't do byte-swapping.
|
||||
* They are only used in practice for transferring buffers which
|
||||
* are arrays of bytes, and byte-swapping is not appropriate in
|
||||
* that case. - paulus
|
||||
*/
|
||||
#define insw(port, buf, ns) _insw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns))
|
||||
#define outsw(port, buf, ns) _outsw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns))
|
||||
|
||||
#define inb(port) in_8((uint8_t *)((port)+_IO_BASE))
|
||||
#define outb(val, port) out_8((uint8_t *)((port)+_IO_BASE), (val))
|
||||
#define inw(port) in_le16((uint16_t *)((port)+_IO_BASE))
|
||||
#define outw(val, port) out_le16((uint16_t *)((port)+_IO_BASE), (val))
|
||||
#define inl(port) in_le32((uint32_t *)((port)+_IO_BASE))
|
||||
#define outl(val, port) out_le32((uint32_t *)((port)+_IO_BASE), (val))
|
||||
|
||||
/*
|
||||
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
|
||||
*/
|
||||
static inline int in_8(volatile unsigned char *addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__asm__ __volatile__("lduba [%1] 0x15, %0\n\t"
|
||||
:"=r"(ret):"r"(addr):"memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void out_8(volatile unsigned char *addr, int val)
|
||||
{
|
||||
__asm__ __volatile__("stba %0, [%1] 0x15\n\t"
|
||||
: : "r"(val), "r"(addr):"memory");
|
||||
}
|
||||
|
||||
static inline int in_le16(volatile unsigned short *addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// XXX
|
||||
__asm__ __volatile__("lduha [%1] 0x15, %0\n\t"
|
||||
:"=r"(ret):"r"(addr):"memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int in_be16(volatile unsigned short *addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__asm__ __volatile__("lduha [%1] 0x15, %0\n\t"
|
||||
:"=r"(ret):"r"(addr):"memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void out_le16(volatile unsigned short *addr, int val)
|
||||
{
|
||||
// XXX
|
||||
__asm__ __volatile__("stha %0, [%1] 0x15\n\t"
|
||||
: : "r"(val), "r"(addr):"memory");
|
||||
}
|
||||
|
||||
static inline void out_be16(volatile unsigned short *addr, int val)
|
||||
{
|
||||
__asm__ __volatile__("stha %0, [%1] 0x15\n\t"
|
||||
: : "r"(val), "r"(addr):"memory");
|
||||
}
|
||||
|
||||
static inline unsigned in_le32(volatile unsigned *addr)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
// XXX
|
||||
__asm__ __volatile__("lduwa [%1] 0x15, %0\n\t"
|
||||
:"=r"(ret):"r"(addr):"memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned in_be32(volatile unsigned *addr)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
__asm__ __volatile__("lduwa [%1] 0x15, %0\n\t"
|
||||
:"=r"(ret):"r"(addr):"memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void out_le32(volatile unsigned *addr, int val)
|
||||
{
|
||||
// XXX
|
||||
__asm__ __volatile__("stwa %0, [%1] 0x15\n\t"
|
||||
: : "r"(val), "r"(addr):"memory");
|
||||
}
|
||||
|
||||
static inline void out_be32(volatile unsigned *addr, int val)
|
||||
{
|
||||
__asm__ __volatile__("stwa %0, [%1] 0x15\n\t"
|
||||
: : "r"(val), "r"(addr):"memory");
|
||||
}
|
||||
|
||||
static inline void _insw_ns(volatile uint16_t * port, void *buf, int ns)
|
||||
{
|
||||
uint16_t *b = (uint16_t *) buf;
|
||||
|
||||
while (ns > 0) {
|
||||
*b++ = in_le16(port);
|
||||
ns--;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _outsw_ns(volatile uint16_t * port, const void *buf,
|
||||
int ns)
|
||||
{
|
||||
uint16_t *b = (uint16_t *) buf;
|
||||
|
||||
while (ns > 0) {
|
||||
out_le16(port, *b++);
|
||||
ns--;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _insw(volatile uint16_t * port, void *buf, int ns)
|
||||
{
|
||||
uint16_t *b = (uint16_t *) buf;
|
||||
|
||||
while (ns > 0) {
|
||||
*b++ = in_be16(port);
|
||||
ns--;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _outsw(volatile uint16_t * port, const void *buf,
|
||||
int ns)
|
||||
{
|
||||
uint16_t *b = (uint16_t *) buf;
|
||||
|
||||
while (ns > 0) {
|
||||
out_be16(port, *b++);
|
||||
ns--;
|
||||
}
|
||||
}
|
||||
#else /* BOOTSTRAP */
|
||||
#ifdef FCOMPILER
|
||||
#define inb(reg) ((u8)0xff)
|
||||
#define inw(reg) ((u16)0xffff)
|
||||
#define inl(reg) ((u32)0xffffffff)
|
||||
#define outb(reg, val) do{} while(0)
|
||||
#define outw(reg, val) do{} while(0)
|
||||
#define outl(reg, val) do{} while(0)
|
||||
#else
|
||||
extern u8 inb(u32 reg);
|
||||
extern u16 inw(u32 reg);
|
||||
extern u32 inl(u32 reg);
|
||||
extern void insw(u32 reg, void *addr, unsigned long count);
|
||||
extern void outb(u32 reg, u8 val);
|
||||
extern void outw(u32 reg, u16 val);
|
||||
extern void outl(u32 reg, u32 val);
|
||||
extern void outsw(u32 reg, const void *addr, unsigned long count);
|
||||
#endif
|
||||
#endif
|
||||
#endif /* _ASM_IO_H */
|
||||
39
include/sparc64/types.h
Normal file
39
include/sparc64/types.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* tag: data types for forth engine
|
||||
*
|
||||
* Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer
|
||||
*
|
||||
* See the file "COPYING" for further information about
|
||||
* the copyright and warranty status of this work.
|
||||
*/
|
||||
|
||||
#ifndef __TYPES_H
|
||||
#define __TYPES_H
|
||||
|
||||
#include "mconfig.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* cell based types */
|
||||
typedef int64_t cell;
|
||||
typedef uint64_t ucell;
|
||||
typedef long long dcell;
|
||||
typedef unsigned long long ducell;
|
||||
|
||||
#define bitspercell (sizeof(cell)<<3)
|
||||
#define bitsperdcell (sizeof(dcell)<<3)
|
||||
|
||||
#define BITS 64
|
||||
|
||||
/* size named types */
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long u64;
|
||||
|
||||
typedef signed char s8;
|
||||
typedef short s16;
|
||||
typedef int s32;
|
||||
typedef long s64;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user