Commit 6f2697c7 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Linus Torvalds

[PATCH] ppc64: monster cleanup

This is the third & hopefully final version of the monster cleanup
patch. It does significant cleanups of the early boot code of the
ppc64 kernel, and begins the long process of cleaning up & splitting
properly the platform support.

It completely reworks the interface between the early code that is
run in the firmware context (prom_init) and the rest of the kernel,
in such a way that will make kexec or static device-tree for embedded
people possible. The early init code can eventually be moved to a
separate link entity, it no longer touches any of the kernel globals,
everything is passed via a single blob of data in memory containing
a flattened version of the device-tree and a memory reserve map.

While doing it, I also cut the ties between pSeries and Powermac. Now,
the kernel config provides a choice between legacy iSeries and
"multiplatform". The later is a set of various supported platform,
each of them beeing a boolean switch, currently defined beeing pSeries
and PowerMac. You can enable both or just one of them. CONFIG_PPC_PSERIES
is now specifically set for IBM pSeries support, you can build a PowerMac
kernel without pSeries support if you which.
The main goal here is to simplify addition of new platform types.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7f0424f9
...@@ -58,16 +58,27 @@ menu "Platform support" ...@@ -58,16 +58,27 @@ menu "Platform support"
choice choice
prompt "Platform Type" prompt "Platform Type"
default PPC_PSERIES default PPC_MULTIPLATFORM
config PPC_ISERIES config PPC_ISERIES
bool "iSeries" bool "IBM Legacy iSeries"
config PPC_PSERIES config PPC_MULTIPLATFORM
bool "pSeries / PowerMac G5" bool "Generic"
endchoice endchoice
config PPC_PSERIES
depends on PPC_MULTIPLATFORM
bool " IBM pSeries & new iSeries"
default y
config PPC_PMAC
depends on PPC_MULTIPLATFORM
bool " Apple G5 based machines"
default y
select ADB_PMU
config PPC config PPC
bool bool
default y default y
...@@ -77,7 +88,7 @@ config PPC64 ...@@ -77,7 +88,7 @@ config PPC64
default y default y
config PPC_OF config PPC_OF
depends on PPC_PSERIES depends on PPC_MULTIPLATFORM
bool bool
default y default y
...@@ -85,14 +96,9 @@ config PPC_OF ...@@ -85,14 +96,9 @@ config PPC_OF
# exception vectors for it # exception vectors for it
config ALTIVEC config ALTIVEC
bool "Support for VMX (Altivec) vector unit" bool "Support for VMX (Altivec) vector unit"
depends on PPC_PSERIES depends on PPC_MULTIPLATFORM
default y default y
config PPC_PMAC
depends on PPC_PSERIES
bool "Apple PowerMac G5 support"
select ADB_PMU
config PPC_SPLPAR config PPC_SPLPAR
depends on PPC_PSERIES depends on PPC_PSERIES
bool "Support for shared-processor logical partitions" bool "Support for shared-processor logical partitions"
...@@ -163,7 +169,7 @@ config SMP ...@@ -163,7 +169,7 @@ config SMP
config IRQ_ALL_CPUS config IRQ_ALL_CPUS
bool "Distribute interrupts on all CPUs by default" bool "Distribute interrupts on all CPUs by default"
depends on SMP && PPC_PSERIES depends on SMP && PPC_MULTIPLATFORM
help help
This option gives the kernel permission to distribute IRQs across This option gives the kernel permission to distribute IRQs across
multiple CPUs. Saying N here will route all IRQs to the first multiple CPUs. Saying N here will route all IRQs to the first
......
...@@ -31,6 +31,7 @@ BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional ...@@ -31,6 +31,7 @@ BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional
BOOTLD := $(CROSS32_COMPILE)ld BOOTLD := $(CROSS32_COMPILE)ld
BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
BOOTOBJCOPY := $(CROSS32_COMPILE)objcopy BOOTOBJCOPY := $(CROSS32_COMPILE)objcopy
BOOTSTRIP := $(CROSS32_COMPILE)strip
OBJCOPYFLAGS := contents,alloc,load,readonly,data OBJCOPYFLAGS := contents,alloc,load,readonly,data
src-boot := crt0.S string.S prom.c main.c zlib.c imagesize.c div64.S src-boot := crt0.S string.S prom.c main.c zlib.c imagesize.c div64.S
...@@ -51,36 +52,31 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S ...@@ -51,36 +52,31 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S
#----------------------------------------------------------- #-----------------------------------------------------------
# ELF sections within the zImage bootloader/wrapper # ELF sections within the zImage bootloader/wrapper
#----------------------------------------------------------- #-----------------------------------------------------------
required := vmlinux .config System.map required := vmlinux.strip
initrd := initrd initrd := initrd
obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section))) obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section)))
src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
hostprogs-y := piggy addnote addSystemMap addRamDisk hostprogs-y := piggy addnote addRamDisk
targets += zImage zImage.initrd imagesize.c \ targets += zImage zImage.initrd imagesize.c \
$(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
vmlinux.sm vmlinux.initrd vmlinux.sminitrd vmlinux.initrd
extra-y := sysmap.o initrd.o extra-y := initrd.o
quiet_cmd_sysmap = SYSMAP $@
cmd_sysmap = $(obj)/addSystemMap System.map $< $@
$(obj)/vmlinux.sm: vmlinux $(obj)/addSystemMap System.map FORCE
$(call if_changed,sysmap)
quiet_cmd_ramdisk = RAMDISK $@ quiet_cmd_ramdisk = RAMDISK $@
cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map $< $@ cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz $< $@
$(obj)/vmlinux.initrd: vmlinux $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map FORCE
$(call if_changed,ramdisk)
$(obj)/vmlinux.sminitrd: $(obj)/vmlinux.sm $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE quiet_cmd_stripvm = STRIP $@
$(call if_changed,ramdisk) cmd_stripvm = $(BOOTSTRIP) -s $< -o $@
$(obj)/sysmap.o: System.map $(obj)/piggyback FORCE vmlinux.strip: vmlinux FORCE
$(call if_changed,piggy) $(call if_changed,stripvm)
$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
$(call if_changed,ramdisk)
addsection = $(BOOTOBJCOPY) $(1) \ addsection = $(BOOTOBJCOPY) $(1) \
--add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \ --add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \
...@@ -113,9 +109,9 @@ $(obj)/zImage.initrd: obj-boot += $(call obj-sec, $(required) $(initrd)) ...@@ -113,9 +109,9 @@ $(obj)/zImage.initrd: obj-boot += $(call obj-sec, $(required) $(initrd))
$(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(obj)/addnote FORCE $(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(obj)/addnote FORCE
$(call if_changed,addnote) $(call if_changed,addnote)
$(obj)/imagesize.c: vmlinux $(obj)/imagesize.c: vmlinux.strip
@echo Generating $@ @echo Generating $@
ls -l vmlinux | \ ls -l vmlinux.strip | \
awk '{printf "/* generated -- do not edit! */\n" \ awk '{printf "/* generated -- do not edit! */\n" \
"unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c "unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c
$(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \ $(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
...@@ -123,6 +119,6 @@ $(obj)/imagesize.c: vmlinux ...@@ -123,6 +119,6 @@ $(obj)/imagesize.c: vmlinux
>> $(obj)/imagesize.c >> $(obj)/imagesize.c
install: $(CONFIGURE) $(obj)/$(BOOTIMAGE) install: $(CONFIGURE) $(obj)/$(BOOTIMAGE)
sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(TOPDIR)/System.map" "$(INSTALL_PATH)" sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(INSTALL_PATH)"
clean-files := $(patsubst $(obj)/%,%, $(obj-boot)) clean-files := $(patsubst $(obj)/%,%, $(obj-boot))
#include <stdio.h>
#include <stdlib.h>
#include <byteswap.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
void xlate( char * inb, char * trb, unsigned len )
{
unsigned i;
for ( i=0; i<len; ++i )
{
char c = *inb++;
char c1 = c >> 4;
char c2 = c & 0xf;
if ( c1 > 9 )
c1 = c1 + 'A' - 10;
else
c1 = c1 + '0';
if ( c2 > 9 )
c2 = c2 + 'A' - 10;
else
c2 = c2 + '0';
*trb++ = c1;
*trb++ = c2;
}
*trb = 0;
}
#define ElfHeaderSize (64 * 1024)
#define ElfPages (ElfHeaderSize / 4096)
void get4k( /*istream *inf*/FILE *file, char *buf )
{
unsigned j;
unsigned num = fread(buf, 1, 4096, file);
for ( j=num; j<4096; ++j )
buf[j] = 0;
}
void put4k( /*ostream *outf*/FILE *file, char *buf )
{
fwrite(buf, 1, 4096, file);
}
int main(int argc, char **argv)
{
char inbuf[4096];
FILE *sysmap = NULL;
char* ptr_end = NULL;
FILE *inputVmlinux = NULL;
FILE *outputVmlinux = NULL;
long i = 0;
unsigned long sysmapFileLen = 0;
unsigned long sysmapLen = 0;
unsigned long roundR = 0;
unsigned long kernelLen = 0;
unsigned long actualKernelLen = 0;
unsigned long round = 0;
unsigned long roundedKernelLen = 0;
unsigned long sysmapStartOffs = 0;
unsigned long sysmapPages = 0;
unsigned long roundedKernelPages = 0;
long padPages = 0;
if ( argc < 2 )
{
fprintf(stderr, "Name of System Map file missing.\n");
exit(1);
}
if ( argc < 3 )
{
fprintf(stderr, "Name of vmlinux file missing.\n");
exit(1);
}
if ( argc < 4 )
{
fprintf(stderr, "Name of vmlinux output file missing.\n");
exit(1);
}
sysmap = fopen(argv[1], "r");
if ( ! sysmap )
{
fprintf(stderr, "System Map file \"%s\" failed to open.\n", argv[1]);
exit(1);
}
inputVmlinux = fopen(argv[2], "r");
if ( ! inputVmlinux )
{
fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", argv[2]);
exit(1);
}
outputVmlinux = fopen(argv[3], "w");
if ( ! outputVmlinux )
{
fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", argv[3]);
exit(1);
}
fseek(inputVmlinux, 0, SEEK_END);
kernelLen = ftell(inputVmlinux);
fseek(inputVmlinux, 0, SEEK_SET);
printf("kernel file size = %ld\n", kernelLen);
if ( kernelLen == 0 )
{
fprintf(stderr, "You must have a linux kernel specified as argv[2]\n");
exit(1);
}
actualKernelLen = kernelLen - ElfHeaderSize;
printf("actual kernel length (minus ELF header) = %ld/%lxx \n", actualKernelLen, actualKernelLen);
round = actualKernelLen % 4096;
roundedKernelLen = actualKernelLen;
if ( round )
roundedKernelLen += (4096 - round);
printf("Kernel length rounded up to a 4k multiple = %ld/%lxx \n", roundedKernelLen, roundedKernelLen);
roundedKernelPages = roundedKernelLen / 4096;
printf("Kernel pages to copy = %ld/%lxx\n", roundedKernelPages, roundedKernelPages);
/* Sysmap file */
fseek(sysmap, 0, SEEK_END);
sysmapFileLen = ftell(sysmap);
fseek(sysmap, 0, SEEK_SET);
printf("%s file size = %ld\n", argv[1], sysmapFileLen);
sysmapLen = sysmapFileLen;
roundR = 4096 - (sysmapLen % 4096);
if (roundR)
{
printf("Rounding System Map file up to a multiple of 4096, adding %ld\n", roundR);
sysmapLen += roundR;
}
printf("Rounded System Map size is %ld\n", sysmapLen);
/* Process the Sysmap file to determine the true end of the kernel */
sysmapPages = sysmapLen / 4096;
printf("System map pages to copy = %ld\n", sysmapPages);
/* read the whole file line by line, expect that it doesn't fail */
while ( fgets(inbuf, 4096, sysmap) ) ;
/* search for _end in the last page of the system map */
ptr_end = strstr(inbuf, " _end");
if (!ptr_end)
{
fprintf(stderr, "Unable to find _end in the sysmap file \n");
fprintf(stderr, "inbuf: \n");
fprintf(stderr, "%s \n", inbuf);
exit(1);
}
printf("Found _end in the last page of the sysmap - backing up 10 characters it looks like %s", ptr_end-10);
sysmapStartOffs = (unsigned int)strtol(ptr_end-10, NULL, 16);
/* calc how many pages we need to insert between the vmlinux and the start of the sysmap */
padPages = sysmapStartOffs/4096 - roundedKernelPages;
/* Check and see if the vmlinux is larger than _end in System.map */
if (padPages < 0)
{ /* vmlinux is larger than _end - adjust the offset to start the embedded system map */
sysmapStartOffs = roundedKernelLen;
printf("vmlinux is larger than _end indicates it needs to be - sysmapStartOffs = %lx \n", sysmapStartOffs);
padPages = 0;
printf("will insert %lx pages between the vmlinux and the start of the sysmap \n", padPages);
}
else
{ /* _end is larger than vmlinux - use the sysmapStartOffs we calculated from the system map */
printf("vmlinux is smaller than _end indicates is needed - sysmapStartOffs = %lx \n", sysmapStartOffs);
printf("will insert %lx pages between the vmlinux and the start of the sysmap \n", padPages);
}
/* Copy 64K ELF header */
for (i=0; i<(ElfPages); ++i)
{
get4k( inputVmlinux, inbuf );
put4k( outputVmlinux, inbuf );
}
/* Copy the vmlinux (as full pages). */
fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
for ( i=0; i<roundedKernelPages; ++i )
{
get4k( inputVmlinux, inbuf );
/* Set the offsets (of the start and end) of the embedded sysmap so it is set in the vmlinux.sm */
if ( i == 0 )
{
unsigned long * p;
printf("Storing embedded_sysmap_start at 0x3c\n");
p = (unsigned long *)(inbuf + 0x3c);
#if (BYTE_ORDER == __BIG_ENDIAN)
*p = sysmapStartOffs;
#else
*p = bswap_32(sysmapStartOffs);
#endif
printf("Storing embedded_sysmap_end at 0x44\n");
p = (unsigned long *)(inbuf + 0x44);
#if (BYTE_ORDER == __BIG_ENDIAN)
*p = sysmapStartOffs + sysmapFileLen;
#else
*p = bswap_32(sysmapStartOffs + sysmapFileLen);
#endif
}
put4k( outputVmlinux, inbuf );
}
/* Insert any pad pages between the end of the vmlinux and where the system map needs to be. */
for (i=0; i<padPages; ++i)
{
memset(inbuf, 0, 4096);
put4k(outputVmlinux, inbuf);
}
/* Copy the system map (as full pages). */
fseek(sysmap, 0, SEEK_SET); /* start reading from begining of the system map */
for ( i=0; i<sysmapPages; ++i )
{
get4k( sysmap, inbuf );
put4k( outputVmlinux, inbuf );
}
fclose(sysmap);
fclose(inputVmlinux);
fclose(outputVmlinux);
/* Set permission to executable */
chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
return 0;
}
...@@ -31,13 +31,9 @@ unsigned long strlen(const char *s); ...@@ -31,13 +31,9 @@ unsigned long strlen(const char *s);
void *memmove(void *dest, const void *src, unsigned long n); void *memmove(void *dest, const void *src, unsigned long n);
void *memcpy(void *dest, const void *src, unsigned long n); void *memcpy(void *dest, const void *src, unsigned long n);
static struct bi_record *make_bi_recs(unsigned long);
#define RAM_START 0x00000000
#define RAM_END (64<<20)
/* Value picked to match that used by yaboot */ /* Value picked to match that used by yaboot */
#define PROG_START 0x01400000 #define PROG_START 0x01400000
#define RAM_END (256<<20) // Fixme: use OF */
char *avail_ram; char *avail_ram;
char *begin_avail, *end_avail; char *begin_avail, *end_avail;
...@@ -48,8 +44,6 @@ unsigned int heap_max; ...@@ -48,8 +44,6 @@ unsigned int heap_max;
extern char _start[]; extern char _start[];
extern char _vmlinux_start[]; extern char _vmlinux_start[];
extern char _vmlinux_end[]; extern char _vmlinux_end[];
extern char _sysmap_start[];
extern char _sysmap_end[];
extern char _initrd_start[]; extern char _initrd_start[];
extern char _initrd_end[]; extern char _initrd_end[];
extern unsigned long vmlinux_filesize; extern unsigned long vmlinux_filesize;
...@@ -62,7 +56,6 @@ struct addr_range { ...@@ -62,7 +56,6 @@ struct addr_range {
}; };
struct addr_range vmlinux = {0, 0, 0}; struct addr_range vmlinux = {0, 0, 0};
struct addr_range vmlinuz = {0, 0, 0}; struct addr_range vmlinuz = {0, 0, 0};
struct addr_range sysmap = {0, 0, 0};
struct addr_range initrd = {0, 0, 0}; struct addr_range initrd = {0, 0, 0};
static char scratch[128<<10]; /* 128kB of scratch space for gunzip */ static char scratch[128<<10]; /* 128kB of scratch space for gunzip */
...@@ -70,7 +63,7 @@ static char scratch[128<<10]; /* 128kB of scratch space for gunzip */ ...@@ -70,7 +63,7 @@ static char scratch[128<<10]; /* 128kB of scratch space for gunzip */
typedef void (*kernel_entry_t)( unsigned long, typedef void (*kernel_entry_t)( unsigned long,
unsigned long, unsigned long,
void *, void *,
struct bi_record *); void *);
int (*prom)(void *); int (*prom)(void *);
...@@ -80,12 +73,31 @@ void *stdin; ...@@ -80,12 +73,31 @@ void *stdin;
void *stdout; void *stdout;
void *stderr; void *stderr;
#define DEBUG
void static unsigned long claim_base = PROG_START;
start(unsigned long a1, unsigned long a2, void *promptr)
static unsigned long try_claim(unsigned long size)
{ {
unsigned long i, claim_addr, claim_size; unsigned long addr = 0;
struct bi_record *bi_recs;
for(; claim_base < RAM_END; claim_base += 0x100000) {
#ifdef DEBUG
printf(" trying: 0x%08lx\n\r", claim_base);
#endif
addr = (unsigned long)claim(claim_base, size, 0);
if ((void *)addr != (void *)-1)
break;
}
if (addr == 0)
return 0;
claim_base = PAGE_ALIGN(claim_base + size);
return addr;
}
void start(unsigned long a1, unsigned long a2, void *promptr)
{
unsigned long i;
kernel_entry_t kernel_entry; kernel_entry_t kernel_entry;
Elf64_Ehdr *elf64; Elf64_Ehdr *elf64;
Elf64_Phdr *elf64ph; Elf64_Phdr *elf64ph;
...@@ -102,61 +114,59 @@ start(unsigned long a1, unsigned long a2, void *promptr) ...@@ -102,61 +114,59 @@ start(unsigned long a1, unsigned long a2, void *promptr)
printf("zImage starting: loaded at 0x%x\n\r", (unsigned)_start); printf("zImage starting: loaded at 0x%x\n\r", (unsigned)_start);
#if 0 /*
sysmap.size = (unsigned long)(_sysmap_end - _sysmap_start); * Now we try to claim some memory for the kernel itself
sysmap.memsize = sysmap.size; * our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what
if ( sysmap.size > 0 ) { * our Makefile stuffs in is an image containing all sort of junk including
sysmap.addr = (RAM_END - sysmap.size) & ~0xFFF; * an ELF header. We need to do some calculations here to find the right
claim(sysmap.addr, RAM_END - sysmap.addr, 0); * size... In practice we add 1Mb, that is enough, but we should really
printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r", * consider fixing the Makefile to put a _raw_ kernel in there !
sysmap.addr, (unsigned long)_sysmap_start, sysmap.size); */
memcpy((void *)sysmap.addr, (void *)_sysmap_start, sysmap.size); vmlinux_memsize += 0x100000;
} printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize);
#endif vmlinux.addr = try_claim(vmlinux_memsize);
if (vmlinux.addr == 0) {
initrd.size = (unsigned long)(_initrd_end - _initrd_start); printf("Can't allocate memory for kernel image !\n\r");
initrd.memsize = initrd.size; exit();
if ( initrd.size > 0 ) {
initrd.addr = (RAM_END - initrd.size) & ~0xFFF;
a1 = a2 = 0;
claim(initrd.addr, RAM_END - initrd.addr, 0);
printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
initrd.addr, (unsigned long)_initrd_start, initrd.size);
memcpy((void *)initrd.addr, (void *)_initrd_start, initrd.size);
} }
vmlinuz.addr = (unsigned long)_vmlinux_start; vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
vmlinux.addr = (unsigned long)(void *)-1;
vmlinux.size = PAGE_ALIGN(vmlinux_filesize); vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
vmlinux.memsize = vmlinux_memsize; vmlinux.memsize = vmlinux_memsize;
claim_size = vmlinux.memsize /* PPPBBB: + fudge for bi_recs */; /*
for(claim_addr = PROG_START; * Now we try to claim memory for the initrd (and copy it there)
claim_addr <= PROG_START * 8; */
claim_addr += 0x100000) { initrd.size = (unsigned long)(_initrd_end - _initrd_start);
#ifdef DEBUG initrd.memsize = initrd.size;
printf(" trying: 0x%08lx\n\r", claim_addr); if ( initrd.size > 0 ) {
#endif printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
vmlinux.addr = (unsigned long)claim(claim_addr, claim_size, 0); initrd.addr = try_claim(initrd.size);
if ((void *)vmlinux.addr != (void *)-1) break; if (initrd.addr == 0) {
} printf("Can't allocate memory for initial ramdisk !\n\r");
if ((void *)vmlinux.addr == (void *)-1) {
printf("claim error, can't allocate kernel memory\n\r");
exit(); exit();
} }
a1 = initrd.addr;
a2 = initrd.size;
printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
initrd.addr, (unsigned long)_initrd_start, initrd.size);
memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
printf("initrd head: 0x%lx\n", *((u32 *)initrd.addr));
}
/* PPPBBB: should kernel always be gziped? */ /* Eventually gunzip the kernel */
if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
int len;
avail_ram = scratch; avail_ram = scratch;
begin_avail = avail_high = avail_ram; begin_avail = avail_high = avail_ram;
end_avail = scratch + sizeof(scratch); end_avail = scratch + sizeof(scratch);
printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...",
vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);
len = vmlinuz.size;
gunzip((void *)vmlinux.addr, vmlinux.size, gunzip((void *)vmlinux.addr, vmlinux.size,
(unsigned char *)vmlinuz.addr, (int *)&vmlinuz.size); (unsigned char *)vmlinuz.addr, &len);
printf("done %lu bytes\n\r", vmlinuz.size); printf("done 0x%lx bytes\n\r", len);
printf("%u bytes of heap consumed, max in use %u\n\r", printf("0x%x bytes of heap consumed, max in use 0x%\n\r",
(unsigned)(avail_high - begin_avail), heap_max); (unsigned)(avail_high - begin_avail), heap_max);
} else { } else {
memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size); memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
...@@ -192,7 +202,8 @@ start(unsigned long a1, unsigned long a2, void *promptr) ...@@ -192,7 +202,8 @@ start(unsigned long a1, unsigned long a2, void *promptr)
flush_cache((void *)vmlinux.addr, vmlinux.memsize); flush_cache((void *)vmlinux.addr, vmlinux.memsize);
bi_recs = make_bi_recs(vmlinux.addr + vmlinux.memsize); if (a1)
printf("initrd head: 0x%lx\n\r", *((u32 *)initrd.addr));
kernel_entry = (kernel_entry_t)vmlinux.addr; kernel_entry = (kernel_entry_t)vmlinux.addr;
#ifdef DEBUG #ifdef DEBUG
...@@ -203,65 +214,16 @@ start(unsigned long a1, unsigned long a2, void *promptr) ...@@ -203,65 +214,16 @@ start(unsigned long a1, unsigned long a2, void *promptr)
" prom = 0x%lx,\n\r" " prom = 0x%lx,\n\r"
" bi_recs = 0x%lx,\n\r", " bi_recs = 0x%lx,\n\r",
(unsigned long)kernel_entry, a1, a2, (unsigned long)kernel_entry, a1, a2,
(unsigned long)prom, (unsigned long)bi_recs); (unsigned long)prom, NULL);
#endif #endif
kernel_entry( a1, a2, prom, bi_recs ); kernel_entry( a1, a2, prom, NULL );
printf("Error: Linux kernel returned to zImage bootloader!\n\r"); printf("Error: Linux kernel returned to zImage bootloader!\n\r");
exit(); exit();
} }
static struct bi_record *
make_bi_recs(unsigned long addr)
{
struct bi_record *bi_recs;
struct bi_record *rec;
bi_recs = rec = bi_rec_init(addr);
rec = bi_rec_alloc(rec, 2);
rec->tag = BI_FIRST;
/* rec->data[0] = ...; # Written below before return */
/* rec->data[1] = ...; # Written below before return */
rec = bi_rec_alloc_bytes(rec, strlen("chrpboot")+1);
rec->tag = BI_BOOTLOADER_ID;
sprintf( (char *)rec->data, "chrpboot");
rec = bi_rec_alloc(rec, 2);
rec->tag = BI_MACHTYPE;
rec->data[0] = PLATFORM_PSERIES;
rec->data[1] = 1;
if ( initrd.size > 0 ) {
rec = bi_rec_alloc(rec, 2);
rec->tag = BI_INITRD;
rec->data[0] = initrd.addr;
rec->data[1] = initrd.size;
}
if ( sysmap.size > 0 ) {
rec = bi_rec_alloc(rec, 2);
rec->tag = BI_SYSMAP;
rec->data[0] = (unsigned long)sysmap.addr;
rec->data[1] = (unsigned long)sysmap.size;
}
rec = bi_rec_alloc(rec, 1);
rec->tag = BI_LAST;
rec->data[0] = (bi_rec_field)bi_recs;
/* Save the _end_ address of the bi_rec's in the first bi_rec
* data field for easy access by the kernel.
*/
bi_recs->data[0] = (bi_rec_field)rec;
bi_recs->data[1] = (bi_rec_field)rec + rec->size - (bi_rec_field)bi_recs;
return bi_recs;
}
struct memchunk { struct memchunk {
unsigned int size; unsigned int size;
unsigned int pad; unsigned int pad;
......
...@@ -61,19 +61,9 @@ SECTIONS ...@@ -61,19 +61,9 @@ SECTIONS
. = ALIGN(4096); . = ALIGN(4096);
_vmlinux_start = .; _vmlinux_start = .;
.kernel:vmlinux : { *(.kernel:vmlinux) } .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) }
_vmlinux_end = .; _vmlinux_end = .;
. = ALIGN(4096);
_dotconfig_start = .;
.kernel:.config : { *(.kernel:.config) }
_dotconfig_end = .;
. = ALIGN(4096);
_sysmap_start = .;
.kernel:System.map : { *(.kernel:System.map) }
_sysmap_end = .;
. = ALIGN(4096); . = ALIGN(4096);
_initrd_start = .; _initrd_start = .;
.kernel:initrd : { *(.kernel:initrd) } .kernel:initrd : { *(.kernel:initrd) }
......
This diff is collapsed.
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.9-rc2
# Thu Sep 23 16:45:05 2004
# #
CONFIG_64BIT=y CONFIG_64BIT=y
CONFIG_MMU=y CONFIG_MMU=y
...@@ -20,6 +22,7 @@ CONFIG_CLEAN_COMPILE=y ...@@ -20,6 +22,7 @@ CONFIG_CLEAN_COMPILE=y
# #
# General setup # General setup
# #
CONFIG_LOCALVERSION=""
CONFIG_SWAP=y CONFIG_SWAP=y
CONFIG_SYSVIPC=y CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y CONFIG_POSIX_MQUEUE=y
...@@ -61,12 +64,13 @@ CONFIG_SYSVIPC_COMPAT=y ...@@ -61,12 +64,13 @@ CONFIG_SYSVIPC_COMPAT=y
# Platform support # Platform support
# #
# CONFIG_PPC_ISERIES is not set # CONFIG_PPC_ISERIES is not set
CONFIG_PPC_MULTIPLATFORM=y
CONFIG_PPC_PSERIES=y CONFIG_PPC_PSERIES=y
# CONFIG_PPC_PMAC is not set
CONFIG_PPC=y CONFIG_PPC=y
CONFIG_PPC64=y CONFIG_PPC64=y
CONFIG_PPC_OF=y CONFIG_PPC_OF=y
CONFIG_ALTIVEC=y CONFIG_ALTIVEC=y
# CONFIG_PPC_PMAC is not set
CONFIG_PPC_SPLPAR=y CONFIG_PPC_SPLPAR=y
# CONFIG_BOOTX_TEXT is not set # CONFIG_BOOTX_TEXT is not set
# CONFIG_POWER4_ONLY is not set # CONFIG_POWER4_ONLY is not set
...@@ -189,7 +193,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y ...@@ -189,7 +193,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set # CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_ALI15X3 is not set
CONFIG_BLK_DEV_AMD74XX=y CONFIG_BLK_DEV_AMD74XX=y
...@@ -365,6 +368,8 @@ CONFIG_NETFILTER=y ...@@ -365,6 +368,8 @@ CONFIG_NETFILTER=y
# IP: Netfilter Configuration # IP: Netfilter Configuration
# #
CONFIG_IP_NF_CONNTRACK=m CONFIG_IP_NF_CONNTRACK=m
# CONFIG_IP_NF_CT_ACCT is not set
CONFIG_IP_NF_CT_PROTO_SCTP=m
CONFIG_IP_NF_FTP=m CONFIG_IP_NF_FTP=m
CONFIG_IP_NF_IRC=m CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_TFTP=m
...@@ -389,8 +394,14 @@ CONFIG_IP_NF_MATCH_HELPER=m ...@@ -389,8 +394,14 @@ CONFIG_IP_NF_MATCH_HELPER=m
CONFIG_IP_NF_MATCH_STATE=m CONFIG_IP_NF_MATCH_STATE=m
CONFIG_IP_NF_MATCH_CONNTRACK=m CONFIG_IP_NF_MATCH_CONNTRACK=m
CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_REALM=m
CONFIG_IP_NF_MATCH_SCTP=m
CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_IP_NF_TARGET_TCPMSS=m
CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_MASQUERADE=m
...@@ -409,21 +420,13 @@ CONFIG_IP_NF_TARGET_ECN=m ...@@ -409,21 +420,13 @@ CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_DSCP=m
CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_MARK=m
CONFIG_IP_NF_TARGET_CLASSIFY=m CONFIG_IP_NF_TARGET_CLASSIFY=m
CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_NOTRACK=m
CONFIG_IP_NF_TARGET_TCPMSS=m
CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_IP_NF_COMPAT_IPCHAINS=m CONFIG_IP_NF_COMPAT_IPCHAINS=m
CONFIG_IP_NF_COMPAT_IPFWADM=m CONFIG_IP_NF_COMPAT_IPFWADM=m
CONFIG_IP_NF_TARGET_NOTRACK=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_REALM=m
# CONFIG_IP_NF_CT_ACCT is not set
CONFIG_IP_NF_MATCH_SCTP=m
CONFIG_IP_NF_CT_PROTO_SCTP=m
CONFIG_XFRM=y CONFIG_XFRM=y
CONFIG_XFRM_USER=m CONFIG_XFRM_USER=m
...@@ -604,6 +607,7 @@ CONFIG_SERIO_I8042=y ...@@ -604,6 +607,7 @@ CONFIG_SERIO_I8042=y
# CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PCIPS2 is not set # CONFIG_SERIO_PCIPS2 is not set
# CONFIG_SERIO_RAW is not set
# #
# Input Device Drivers # Input Device Drivers
...@@ -621,6 +625,7 @@ CONFIG_MOUSE_PS2=y ...@@ -621,6 +625,7 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y CONFIG_INPUT_MISC=y
# CONFIG_INPUT_PCSPKR is not set
# CONFIG_INPUT_UINPUT is not set # CONFIG_INPUT_UINPUT is not set
# #
......
...@@ -17,7 +17,7 @@ obj-$(CONFIG_PPC_OF) += of_device.o ...@@ -17,7 +17,7 @@ obj-$(CONFIG_PPC_OF) += of_device.o
pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \ pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \
iSeries_IoMmTable.o iSeries_IoMmTable.o
pci-obj-$(CONFIG_PPC_PSERIES) += pci_dn.o pci_dma_direct.o pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_dma_direct.o
obj-$(CONFIG_PCI) += pci.o pci_iommu.o $(pci-obj-y) obj-$(CONFIG_PCI) += pci.o pci_iommu.o $(pci-obj-y)
...@@ -28,10 +28,11 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \ ...@@ -28,10 +28,11 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
iSeries_iommu.o iSeries_iommu.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o open_pic.o i8259.o prom_init.o prom.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \ eeh.o pSeries_nvram.o rtasd.o ras.o \
open_pic.o xics.o pSeries_htab.o rtas.o \ xics.o rtas.o pSeries_setup.o pSeries_iommu.o
chrp_setup.o i8259.o prom.o pSeries_iommu.o
obj-$(CONFIG_PROC_FS) += proc_ppc64.o obj-$(CONFIG_PROC_FS) += proc_ppc64.o
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <asm/iSeries/ItLpPaca.h> #include <asm/iSeries/ItLpPaca.h>
#include <asm/iSeries/ItLpQueue.h> #include <asm/iSeries/ItLpQueue.h>
#include <asm/iSeries/HvLpEvent.h> #include <asm/iSeries/HvLpEvent.h>
#include <asm/prom.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/cputable.h> #include <asm/cputable.h>
...@@ -108,7 +107,6 @@ int main(void) ...@@ -108,7 +107,6 @@ int main(void)
DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1)); DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1));
DEFINE(LPPACAANYINT, offsetof(struct ItLpPaca, xIntDword.xAnyInt)); DEFINE(LPPACAANYINT, offsetof(struct ItLpPaca, xIntDword.xAnyInt));
DEFINE(LPPACADECRINT, offsetof(struct ItLpPaca, xIntDword.xFields.xDecrInt)); DEFINE(LPPACADECRINT, offsetof(struct ItLpPaca, xIntDword.xFields.xDecrInt));
DEFINE(PROMENTRY, offsetof(struct prom_t, entry));
/* RTAS */ /* RTAS */
DEFINE(RTASBASE, offsetof(struct rtas_t, base)); DEFINE(RTASBASE, offsetof(struct rtas_t, base));
......
This diff is collapsed.
...@@ -746,6 +746,10 @@ _STATIC(rtas_restore_regs) ...@@ -746,6 +746,10 @@ _STATIC(rtas_restore_regs)
mtlr r0 mtlr r0
blr /* return to caller */ blr /* return to caller */
#endif /* CONFIG_PPC_PSERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
_GLOBAL(enter_prom) _GLOBAL(enter_prom)
mflr r0 mflr r0
std r0,16(r1) std r0,16(r1)
...@@ -777,11 +781,8 @@ _GLOBAL(enter_prom) ...@@ -777,11 +781,8 @@ _GLOBAL(enter_prom)
std r11,_MSR(r1) std r11,_MSR(r1)
/* Get the PROM entrypoint */ /* Get the PROM entrypoint */
bl .reloc_offset ld r0,GPR4(r1)
LOADADDR(r12,prom) mtlr r0
sub r12,r12,r3
ld r12,PROMENTRY(r12)
mtlr r12
/* Switch MSR to 32 bits mode /* Switch MSR to 32 bits mode
*/ */
...@@ -834,4 +835,4 @@ _GLOBAL(enter_prom) ...@@ -834,4 +835,4 @@ _GLOBAL(enter_prom)
mtlr r0 mtlr r0
blr blr
#endif /* defined(CONFIG_PPC_PSERIES) */ #endif /* CONFIG_PPC_MULTIPLATFORM */
...@@ -83,13 +83,14 @@ ...@@ -83,13 +83,14 @@
.text .text
.globl _stext .globl _stext
_stext: _stext:
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_MULTIPLATFORM
_STATIC(__start) _GLOBAL(__start)
/* NOP this out unconditionally */ /* NOP this out unconditionally */
BEGIN_FTR_SECTION BEGIN_FTR_SECTION
b .__start_initialization_pSeries b .__start_initialization_multiplatform
END_FTR_SECTION(0, 1) END_FTR_SECTION(0, 1)
#endif #endif /* CONFIG_PPC_MULTIPLATFORM */
/* Catch branch to 0 in real mode */ /* Catch branch to 0 in real mode */
trap trap
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
...@@ -117,7 +118,8 @@ embedded_sysmap_start: ...@@ -117,7 +118,8 @@ embedded_sysmap_start:
.globl embedded_sysmap_end .globl embedded_sysmap_end
embedded_sysmap_end: embedded_sysmap_end:
.llong 0 .llong 0
#else
#else /* CONFIG_PPC_ISERIES */
/* Secondary processors spin on this value until it goes to 1. */ /* Secondary processors spin on this value until it goes to 1. */
.globl __secondary_hold_spinloop .globl __secondary_hold_spinloop
...@@ -1223,12 +1225,10 @@ _GLOBAL(pseries_secondary_smp_init) ...@@ -1223,12 +1225,10 @@ _GLOBAL(pseries_secondary_smp_init)
#endif #endif
b 1b /* Loop until told to go */ b 1b /* Loop until told to go */
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
_GLOBAL(__start_initialization_iSeries) _STATIC(__start_initialization_iSeries)
/* Clear out the BSS */ /* Clear out the BSS */
LOADADDR(r11,__bss_stop) LOADADDR(r11,__bss_stop)
LOADADDR(r8,__bss_start) LOADADDR(r8,__bss_start)
sub r11,r11,r8 /* bss size */ sub r11,r11,r8 /* bss size */
addi r11,r11,7 /* round up to an even double word */ addi r11,r11,7 /* round up to an even double word */
rldicl. r11,r11,61,3 /* shift right by 3 */ rldicl. r11,r11,61,3 /* shift right by 3 */
...@@ -1265,32 +1265,73 @@ _GLOBAL(__start_initialization_iSeries) ...@@ -1265,32 +1265,73 @@ _GLOBAL(__start_initialization_iSeries)
ld r6,PACA(r4) /* Get the base paca pointer */ ld r6,PACA(r4) /* Get the base paca pointer */
ld r4,PACASTABVIRT(r6) ld r4,PACASTABVIRT(r6)
bl .iSeries_fixup_klimit bl .iSeries_early_setup
/* relocation is on at this point */ /* relocation is on at this point */
b .start_here_common b .start_here_common
#endif #endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_MULTIPLATFORM
_STATIC(mmu_off) _STATIC(__mmu_off)
mfmsr r3 mfmsr r3
andi. r0,r3,MSR_IR|MSR_DR andi. r0,r3,MSR_IR|MSR_DR
beqlr beqlr
andc r3,r3,r0 andc r3,r3,r0
mtspr SRR0,r4 mtspr SPRN_SRR0,r4
mtspr SRR1,r3 mtspr SPRN_SRR1,r3
sync sync
rfid rfid
b . /* prevent speculative execution */ b . /* prevent speculative execution */
_GLOBAL(__start_initialization_pSeries)
mr r31,r3 /* save parameters */
/*
* Here is our main kernel entry point. We support currently 2 kind of entries
* depending on the value of r5.
*
* r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content
* in r3...r7
*
* r5 == NULL -> kexec style entry. r3 is a physical pointer to the
* DT block, r4 is a physical pointer to the kernel itself
*
*/
_GLOBAL(__start_initialization_multiplatform)
/*
* Are we booted from a PROM Of-type client-interface ?
*/
cmpldi cr0,r5,0
bne .__boot_from_prom /* yes -> prom */
/* Save parameters */
mr r31,r3
mr r30,r4
/* Make sure we are running in 64 bits mode */
bl .enable_64b_mode
/* Setup some critical 970 SPRs before switching MMU off */
bl .__970_cpu_preinit
/* cpu # */
li r24,0
/* Switch off MMU if not already */
LOADADDR(r4, .__after_prom_start - KERNELBASE)
add r4,r4,r30
bl .__mmu_off
b .__after_prom_start
_STATIC(__boot_from_prom)
/* Save parameters */
mr r31,r3
mr r30,r4 mr r30,r4
mr r29,r5 mr r29,r5
mr r28,r6 mr r28,r6
mr r27,r7 mr r27,r7
/* Make sure we are running in 64 bits mode */
bl .enable_64b_mode bl .enable_64b_mode
/* put a relocation offset into r3 */ /* put a relocation offset into r3 */
...@@ -1303,7 +1344,7 @@ _GLOBAL(__start_initialization_pSeries) ...@@ -1303,7 +1344,7 @@ _GLOBAL(__start_initialization_pSeries)
/* Relocate the TOC from a virt addr to a real addr */ /* Relocate the TOC from a virt addr to a real addr */
sub r2,r2,r3 sub r2,r2,r3
/* Save parameters */ /* Restore parameters */
mr r3,r31 mr r3,r31
mr r4,r30 mr r4,r30
mr r5,r29 mr r5,r29
...@@ -1312,17 +1353,8 @@ _GLOBAL(__start_initialization_pSeries) ...@@ -1312,17 +1353,8 @@ _GLOBAL(__start_initialization_pSeries)
/* Do all of the interaction with OF client interface */ /* Do all of the interaction with OF client interface */
bl .prom_init bl .prom_init
mr r23,r3 /* Save phys address we are running at */ /* We never return */
trap
/* Setup some critical 970 SPRs before switching MMU off */
bl .__970_cpu_preinit
li r24,0 /* cpu # */
/* Switch off MMU if not already */
LOADADDR(r4, .__after_prom_start - KERNELBASE)
add r4,r4,r23
bl .mmu_off
/* /*
* At this point, r3 contains the physical address we are running at, * At this point, r3 contains the physical address we are running at,
...@@ -1348,7 +1380,7 @@ _STATIC(__after_prom_start) ...@@ -1348,7 +1380,7 @@ _STATIC(__after_prom_start)
li r3,0 /* target addr */ li r3,0 /* target addr */
// XXX FIXME: Use phys returned by OF (r23) // XXX FIXME: Use phys returned by OF (r30)
sub r4,r27,r26 /* source addr */ sub r4,r27,r26 /* source addr */
/* current address of _start */ /* current address of _start */
/* i.e. where we are running */ /* i.e. where we are running */
...@@ -1373,8 +1405,9 @@ _STATIC(__after_prom_start) ...@@ -1373,8 +1405,9 @@ _STATIC(__after_prom_start)
ld r5,0(r5) /* get the value of klimit */ ld r5,0(r5) /* get the value of klimit */
sub r5,r5,r27 sub r5,r5,r27
bl .copy_and_flush /* copy the rest */ bl .copy_and_flush /* copy the rest */
b .start_here_pSeries b .start_here_multiplatform
#endif
#endif /* CONFIG_PPC_MULTIPLATFORM */
/* /*
* Copy routine used to copy the kernel to start at physical address 0 * Copy routine used to copy the kernel to start at physical address 0
...@@ -1794,15 +1827,33 @@ _GLOBAL(enable_64b_mode) ...@@ -1794,15 +1827,33 @@ _GLOBAL(enable_64b_mode)
isync isync
blr blr
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_MULTIPLATFORM
/* /*
* This is where the main kernel code starts. * This is where the main kernel code starts.
*/ */
_STATIC(start_here_pSeries) _STATIC(start_here_multiplatform)
/* get a new offset, now that the kernel has moved. */ /* get a new offset, now that the kernel has moved. */
bl .reloc_offset bl .reloc_offset
mr r26,r3 mr r26,r3
/* Clear out the BSS. It may have been done in prom_init,
* already but that's irrelevant since prom_init will soon
* be detached from the kernel completely. Besides, we need
* to clear it now for kexec-style entry.
*/
LOADADDR(r11,__bss_stop)
LOADADDR(r8,__bss_start)
sub r11,r11,r8 /* bss size */
addi r11,r11,7 /* round up to an even double word */
rldicl. r11,r11,61,3 /* shift right by 3 */
beq 4f
addi r8,r8,-8
li r0,0
mtctr r11 /* zero this many doublewords */
3: stdu r0,8(r8)
bdnz 3b
4:
mfmsr r6 mfmsr r6
ori r6,r6,MSR_RI ori r6,r6,MSR_RI
mtmsrd r6 /* RI on */ mtmsrd r6 /* RI on */
...@@ -1875,8 +1926,11 @@ _STATIC(start_here_pSeries) ...@@ -1875,8 +1926,11 @@ _STATIC(start_here_pSeries)
mr r5,r26 mr r5,r26
bl .identify_cpu bl .identify_cpu
/* Get the pointer to the segment table which is used by */ /* Setup a valid physical PACA pointer in SPRG3 for early_setup
/* stab_initialize */ * note that boot_cpuid can always be 0 nowadays since there is
* nowhere it can be initialized differently before we reach this
* code
*/
LOADADDR(r27, boot_cpuid) LOADADDR(r27, boot_cpuid)
sub r27,r27,r26 sub r27,r27,r26
lwz r27,0(r27) lwz r27,0(r27)
...@@ -1885,12 +1939,18 @@ _STATIC(start_here_pSeries) ...@@ -1885,12 +1939,18 @@ _STATIC(start_here_pSeries)
mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r13,r24 /* for this processor. */ add r13,r13,r24 /* for this processor. */
sub r13,r13,r26 /* convert to physical addr */ sub r13,r13,r26 /* convert to physical addr */
mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */ mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */
ld r3,PACASTABREAL(r13)
ori r4,r3,1 /* turn on valid bit */ /* Do very early kernel initializations, including initial hash table,
* stab and slb setup before we turn on relocation. */
/* Restore parameters passed from prom_init/kexec */
mr r3,r31
bl .early_setup
/* set the ASR */ /* set the ASR */
ld r3,PACASTABREAL(r13)
ori r4,r3,1 /* turn on valid bit */
li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */ lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES_LPAR cmpldi r3,PLATFORM_PSERIES_LPAR
...@@ -1909,13 +1969,7 @@ _STATIC(start_here_pSeries) ...@@ -1909,13 +1969,7 @@ _STATIC(start_here_pSeries)
98: /* !(rpa hypervisor) || !(star) */ 98: /* !(rpa hypervisor) || !(star) */
mtasr r4 /* set the stab location */ mtasr r4 /* set the stab location */
99: 99:
mfspr r6,SPRG3 /* Set SDR1 (hash table pointer) */
ld r3,PACASTABREAL(r6) /* restore r3 for stab_initialize */
/* Initialize an initial memory mapping and turn on relocation. */
bl .stab_initialize
bl .htab_initialize
li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */ lwz r3,PLATFORM(r3) /* r3 = platform flags */
/* Test if bit 0 is set (LPAR bit) */ /* Test if bit 0 is set (LPAR bit) */
...@@ -1932,7 +1986,7 @@ _STATIC(start_here_pSeries) ...@@ -1932,7 +1986,7 @@ _STATIC(start_here_pSeries)
mtspr SRR1,r4 mtspr SRR1,r4
rfid rfid
b . /* prevent speculative execution */ b . /* prevent speculative execution */
#endif /* CONFIG_PPC_PSERIES */ #endif /* CONFIG_PPC_MULTIPLATFORM */
/* This is where all platforms converge execution */ /* This is where all platforms converge execution */
_STATIC(start_here_common) _STATIC(start_here_common)
...@@ -1980,13 +2034,6 @@ _STATIC(start_here_common) ...@@ -1980,13 +2034,6 @@ _STATIC(start_here_common)
ld r2,PACATOC(r13) ld r2,PACATOC(r13)
std r1,PACAKSAVE(r13) std r1,PACAKSAVE(r13)
/* Restore the parms passed in from the bootloader. */
mr r3,r31
mr r4,r30
mr r5,r29
mr r6,r28
mr r7,r27
bl .setup_system bl .setup_system
/* Load up the kernel context */ /* Load up the kernel context */
......
...@@ -233,4 +233,6 @@ void hpte_init_iSeries(void) ...@@ -233,4 +233,6 @@ void hpte_init_iSeries(void)
ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
ppc_md.hpte_insert = iSeries_hpte_insert; ppc_md.hpte_insert = iSeries_hpte_insert;
ppc_md.hpte_remove = iSeries_hpte_remove; ppc_md.hpte_remove = iSeries_hpte_remove;
htab_finish_init();
} }
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#undef DEBUG
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/threads.h> #include <linux/threads.h>
...@@ -54,6 +56,14 @@ ...@@ -54,6 +56,14 @@
#include <asm/iSeries/iSeries_proc.h> #include <asm/iSeries/iSeries_proc.h>
#include <asm/iSeries/mf.h> #include <asm/iSeries/mf.h>
extern void hvlog(char *fmt, ...);
#ifdef DEBUG
#define DBG(fmt...) hvlog(fmt)
#else
#define DBG(fmt...)
#endif
/* Function Prototypes */ /* Function Prototypes */
extern void ppcdbg_initialize(void); extern void ppcdbg_initialize(void);
extern void tce_init_iSeries(void); extern void tce_init_iSeries(void);
...@@ -75,8 +85,6 @@ static unsigned long tbFreqMhzHundreths; ...@@ -75,8 +85,6 @@ static unsigned long tbFreqMhzHundreths;
int piranha_simulator; int piranha_simulator;
int boot_cpuid;
extern int rd_size; /* Defined in drivers/block/rd.c */ extern int rd_size; /* Defined in drivers/block/rd.c */
extern unsigned long klimit; extern unsigned long klimit;
extern unsigned long embedded_sysmap_start; extern unsigned long embedded_sysmap_start;
...@@ -275,8 +283,28 @@ unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array, ...@@ -275,8 +283,28 @@ unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
return mem_blocks; return mem_blocks;
} }
void __init iSeries_init_early(void) static void __init iSeries_parse_cmdline(void)
{ {
char *p, *q;
/* copy the command line parameter from the primary VSP */
HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
HvLpDma_Direction_RemoteToLocal);
p = cmd_line;
q = cmd_line + 255;
while(p < q) {
if (!*p || *p == '\n')
break;
++p;
}
*p = 0;
}
/*static*/ void __init iSeries_init_early(void)
{
DBG(" -> iSeries_init_early()\n");
ppcdbg_initialize(); ppcdbg_initialize();
#if defined(CONFIG_BLK_DEV_INITRD) #if defined(CONFIG_BLK_DEV_INITRD)
...@@ -300,25 +328,20 @@ void __init iSeries_init_early(void) ...@@ -300,25 +328,20 @@ void __init iSeries_init_early(void)
iSeries_recal_tb = get_tb(); iSeries_recal_tb = get_tb();
iSeries_recal_titan = HvCallXm_loadTod(); iSeries_recal_titan = HvCallXm_loadTod();
ppc_md.setup_arch = iSeries_setup_arch; /*
ppc_md.get_cpuinfo = iSeries_get_cpuinfo; * Cache sizes must be initialized before hpte_init_iSeries is called
ppc_md.init_IRQ = iSeries_init_IRQ; * as the later need them for flush_icache_range()
ppc_md.get_irq = iSeries_get_irq; */
ppc_md.init = NULL; setup_iSeries_cache_sizes();
ppc_md.pcibios_fixup = iSeries_pci_final_fixup;
ppc_md.restart = iSeries_restart;
ppc_md.power_off = iSeries_power_off;
ppc_md.halt = iSeries_halt;
ppc_md.get_boot_time = iSeries_get_boot_time;
ppc_md.set_rtc_time = iSeries_set_rtc_time;
ppc_md.get_rtc_time = iSeries_get_rtc_time;
ppc_md.calibrate_decr = iSeries_calibrate_decr;
ppc_md.progress = iSeries_progress;
/*
* Initialize the hash table management pointers
*/
hpte_init_iSeries(); hpte_init_iSeries();
/*
* Initialize the DMA/TCE management
*/
tce_init_iSeries(); tce_init_iSeries();
/* /*
...@@ -326,7 +349,7 @@ void __init iSeries_init_early(void) ...@@ -326,7 +349,7 @@ void __init iSeries_init_early(void)
* AS/400 absolute addresses * AS/400 absolute addresses
*/ */
build_iSeries_Memory_Map(); build_iSeries_Memory_Map();
setup_iSeries_cache_sizes();
/* Initialize machine-dependency vectors */ /* Initialize machine-dependency vectors */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
smp_init_iSeries(); smp_init_iSeries();
...@@ -340,24 +363,22 @@ void __init iSeries_init_early(void) ...@@ -340,24 +363,22 @@ void __init iSeries_init_early(void)
mf_init(); mf_init();
mf_initialized = 1; mf_initialized = 1;
mb(); mb();
}
void __init iSeries_parse_cmdline(void) /* If we were passed an initrd, set the ROOT_DEV properly if the values
{ * look sensible. If not, clear initrd reference.
char *p, *q; */
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
initrd_end > initrd_start)
ROOT_DEV = Root_RAM0;
else
initrd_start = initrd_end = 0;
#endif /* CONFIG_BLK_DEV_INITRD */
/* copy the command line parameter from the primary VSP */
HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
HvLpDma_Direction_RemoteToLocal);
p = cmd_line; iSeries_parse_cmdline();
q = cmd_line + 255;
while(p < q) { DBG(" <- iSeries_init_early()\n");
if (!*p || *p == '\n')
break;
++p;
}
*p = 0;
} }
/* /*
...@@ -781,7 +802,7 @@ void __init iSeries_progress(char * st, unsigned short code) ...@@ -781,7 +802,7 @@ void __init iSeries_progress(char * st, unsigned short code)
} }
} }
void iSeries_fixup_klimit(void) static void __init iSeries_fixup_klimit(void)
{ {
/* /*
* Change klimit to take into account any ram disk * Change klimit to take into account any ram disk
...@@ -810,3 +831,27 @@ int __init iSeries_src_init(void) ...@@ -810,3 +831,27 @@ int __init iSeries_src_init(void)
} }
late_initcall(iSeries_src_init); late_initcall(iSeries_src_init);
void __init iSeries_early_setup(void)
{
iSeries_fixup_klimit();
ppc_md.setup_arch = iSeries_setup_arch;
ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
ppc_md.init_IRQ = iSeries_init_IRQ;
ppc_md.get_irq = iSeries_get_irq;
ppc_md.init_early = iSeries_init_early,
ppc_md.pcibios_fixup = iSeries_pci_final_fixup;
ppc_md.restart = iSeries_restart;
ppc_md.power_off = iSeries_power_off;
ppc_md.halt = iSeries_halt;
ppc_md.get_boot_time = iSeries_get_boot_time;
ppc_md.set_rtc_time = iSeries_set_rtc_time;
ppc_md.get_rtc_time = iSeries_get_rtc_time;
ppc_md.calibrate_decr = iSeries_calibrate_decr;
ppc_md.progress = iSeries_progress;
}
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
#ifndef __ISERIES_SETUP_H__ #ifndef __ISERIES_SETUP_H__
#define __ISERIES_SETUP_H__ #define __ISERIES_SETUP_H__
extern void iSeries_init_early(void);
extern void iSeries_init(unsigned long r3, unsigned long ird_start,
unsigned long ird_end, unsigned long cline_start,
unsigned long cline_end);
extern void iSeries_setup_arch(void); extern void iSeries_setup_arch(void);
extern void iSeries_setup_residual(struct seq_file *m, int cpu_id); extern void iSeries_setup_residual(struct seq_file *m, int cpu_id);
extern void iSeries_get_cpuinfo(struct seq_file *m); extern void iSeries_get_cpuinfo(struct seq_file *m);
......
...@@ -30,9 +30,8 @@ ...@@ -30,9 +30,8 @@
#include <asm/time.h> #include <asm/time.h>
#include <asm/iSeries/HvCall.h> #include <asm/iSeries/HvCall.h>
#include <asm/iSeries/ItLpQueue.h> #include <asm/iSeries/ItLpQueue.h>
#include <asm/plpar_wrappers.h>
extern long cede_processor(void);
extern long poll_pending(void);
extern void power4_idle(void); extern void power4_idle(void);
static int (*idle_loop)(void); static int (*idle_loop)(void);
...@@ -153,6 +152,8 @@ static int default_idle(void) ...@@ -153,6 +152,8 @@ static int default_idle(void)
return 0; return 0;
} }
#ifdef CONFIG_PPC_PSERIES
DECLARE_PER_CPU(unsigned long, smt_snooze_delay); DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
int dedicated_idle(void) int dedicated_idle(void)
...@@ -280,9 +281,12 @@ static int shared_idle(void) ...@@ -280,9 +281,12 @@ static int shared_idle(void)
return 0; return 0;
} }
static int powermac_idle(void) #endif /* CONFIG_PPC_PSERIES */
static int native_idle(void)
{ {
while(1) { while(1) {
/* check CPU type here */
if (!need_resched()) if (!need_resched())
power4_idle(); power4_idle();
if (need_resched()) if (need_resched())
...@@ -290,7 +294,8 @@ static int powermac_idle(void) ...@@ -290,7 +294,8 @@ static int powermac_idle(void)
} }
return 0; return 0;
} }
#endif
#endif /* CONFIG_PPC_ISERIES */
int cpu_idle(void) int cpu_idle(void)
{ {
...@@ -332,30 +337,38 @@ __initcall(register_powersave_nap_sysctl); ...@@ -332,30 +337,38 @@ __initcall(register_powersave_nap_sysctl);
int idle_setup(void) int idle_setup(void)
{ {
/*
* Move that junk to each platform specific file, eventually define
* a pSeries_idle for shared processor stuff
*/
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
idle_loop = iSeries_idle; idle_loop = iSeries_idle;
return 1;
#else #else
idle_loop = default_idle;
#endif
#ifdef CONFIG_PPC_PSERIES
if (systemcfg->platform & PLATFORM_PSERIES) { if (systemcfg->platform & PLATFORM_PSERIES) {
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
if (get_paca()->lppaca.xSharedProc) { if (get_paca()->lppaca.xSharedProc) {
printk("idle = shared_idle\n"); printk(KERN_INFO "Using shared processor idle loop\n");
idle_loop = shared_idle; idle_loop = shared_idle;
} else { } else {
printk("idle = dedicated_idle\n"); printk(KERN_INFO "Using dedicated idle loop\n");
idle_loop = dedicated_idle; idle_loop = dedicated_idle;
} }
} else { } else {
printk("idle = default_idle\n"); printk(KERN_INFO "Using default idle loop\n");
idle_loop = default_idle; idle_loop = default_idle;
} }
} else if (systemcfg->platform == PLATFORM_POWERMAC) {
printk("idle = powermac_idle\n");
idle_loop = powermac_idle;
} else {
printk("idle_setup: unknown platform, use default_idle\n");
idle_loop = default_idle;
} }
#endif #endif /* CONFIG_PPC_PSERIES */
#ifdef CONFIG_PPC_PMAC
if (systemcfg->platform == PLATFORM_POWERMAC) {
printk(KERN_INFO "Using native/NAP idle loop\n");
idle_loop = native_idle;
}
#endif /* CONFIG_PPC_PMAC */
return 1; return 1;
} }
...@@ -22,6 +22,43 @@ ...@@ -22,6 +22,43 @@
struct lmb lmb; struct lmb lmb;
#undef DEBUG
void lmb_dump_all(void)
{
#ifdef DEBUG
unsigned long i;
struct lmb *_lmb = &lmb;
udbg_printf("lmb_dump_all:\n");
udbg_printf(" memory.cnt = 0x%lx\n",
_lmb->memory.cnt);
udbg_printf(" memory.size = 0x%lx\n",
_lmb->memory.size);
for (i=0; i < _lmb->memory.cnt ;i++) {
udbg_printf(" memory.region[0x%x].base = 0x%lx\n",
i, _lmb->memory.region[i].base);
udbg_printf(" .physbase = 0x%lx\n",
_lmb->memory.region[i].physbase);
udbg_printf(" .size = 0x%lx\n",
_lmb->memory.region[i].size);
}
udbg_printf("\n reserved.cnt = 0x%lx\n",
_lmb->reserved.cnt);
udbg_printf(" reserved.size = 0x%lx\n",
_lmb->reserved.size);
for (i=0; i < _lmb->reserved.cnt ;i++) {
udbg_printf(" reserved.region[0x%x].base = 0x%lx\n",
i, _lmb->reserved.region[i].base);
udbg_printf(" .physbase = 0x%lx\n",
_lmb->reserved.region[i].physbase);
udbg_printf(" .size = 0x%lx\n",
_lmb->reserved.region[i].size);
}
#endif /* DEBUG */
}
static unsigned long __init static unsigned long __init
lmb_addrs_overlap(unsigned long base1, unsigned long size1, lmb_addrs_overlap(unsigned long base1, unsigned long size1,
unsigned long base2, unsigned long size2) unsigned long base2, unsigned long size2)
...@@ -71,8 +108,7 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2) ...@@ -71,8 +108,7 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
void __init void __init
lmb_init(void) lmb_init(void)
{ {
unsigned long offset = reloc_offset(); struct lmb *_lmb = &lmb;
struct lmb *_lmb = PTRRELOC(&lmb);
/* Create a dummy zero size LMB which will get coalesced away later. /* Create a dummy zero size LMB which will get coalesced away later.
* This simplifies the lmb_add() code below... * This simplifies the lmb_add() code below...
...@@ -94,8 +130,7 @@ lmb_analyze(void) ...@@ -94,8 +130,7 @@ lmb_analyze(void)
unsigned long i; unsigned long i;
unsigned long mem_size = 0; unsigned long mem_size = 0;
unsigned long size_mask = 0; unsigned long size_mask = 0;
unsigned long offset = reloc_offset(); struct lmb *_lmb = &lmb;
struct lmb *_lmb = PTRRELOC(&lmb);
#ifdef CONFIG_MSCHUNKS #ifdef CONFIG_MSCHUNKS
unsigned long physbase = 0; unsigned long physbase = 0;
#endif #endif
...@@ -178,8 +213,7 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size) ...@@ -178,8 +213,7 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
long __init long __init
lmb_add(unsigned long base, unsigned long size) lmb_add(unsigned long base, unsigned long size)
{ {
unsigned long offset = reloc_offset(); struct lmb *_lmb = &lmb;
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb_region *_rgn = &(_lmb->memory); struct lmb_region *_rgn = &(_lmb->memory);
/* On pSeries LPAR systems, the first LMB is our RMO region. */ /* On pSeries LPAR systems, the first LMB is our RMO region. */
...@@ -193,8 +227,7 @@ lmb_add(unsigned long base, unsigned long size) ...@@ -193,8 +227,7 @@ lmb_add(unsigned long base, unsigned long size)
long __init long __init
lmb_reserve(unsigned long base, unsigned long size) lmb_reserve(unsigned long base, unsigned long size)
{ {
unsigned long offset = reloc_offset(); struct lmb *_lmb = &lmb;
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb_region *_rgn = &(_lmb->reserved); struct lmb_region *_rgn = &(_lmb->reserved);
return lmb_add_region(_rgn, base, size); return lmb_add_region(_rgn, base, size);
...@@ -227,8 +260,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) ...@@ -227,8 +260,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
{ {
long i, j; long i, j;
unsigned long base = 0; unsigned long base = 0;
unsigned long offset = reloc_offset(); struct lmb *_lmb = &lmb;
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_mem = &(_lmb->memory);
struct lmb_region *_rsv = &(_lmb->reserved); struct lmb_region *_rsv = &(_lmb->reserved);
...@@ -263,8 +295,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) ...@@ -263,8 +295,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
unsigned long __init unsigned long __init
lmb_phys_mem_size(void) lmb_phys_mem_size(void)
{ {
unsigned long offset = reloc_offset(); struct lmb *_lmb = &lmb;
struct lmb *_lmb = PTRRELOC(&lmb);
#ifdef CONFIG_MSCHUNKS #ifdef CONFIG_MSCHUNKS
return _lmb->memory.size; return _lmb->memory.size;
#else #else
...@@ -282,8 +313,7 @@ lmb_phys_mem_size(void) ...@@ -282,8 +313,7 @@ lmb_phys_mem_size(void)
unsigned long __init unsigned long __init
lmb_end_of_DRAM(void) lmb_end_of_DRAM(void)
{ {
unsigned long offset = reloc_offset(); struct lmb *_lmb = &lmb;
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_mem = &(_lmb->memory);
int idx = _mem->cnt - 1; int idx = _mem->cnt - 1;
...@@ -300,8 +330,7 @@ unsigned long __init ...@@ -300,8 +330,7 @@ unsigned long __init
lmb_abs_to_phys(unsigned long aa) lmb_abs_to_phys(unsigned long aa)
{ {
unsigned long i, pa = aa; unsigned long i, pa = aa;
unsigned long offset = reloc_offset(); struct lmb *_lmb = &lmb;
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_mem = &(_lmb->memory);
for (i=0; i < _mem->cnt; i++) { for (i=0; i < _mem->cnt; i++) {
......
...@@ -127,6 +127,47 @@ _GLOBAL(call_handle_irq_event) ...@@ -127,6 +127,47 @@ _GLOBAL(call_handle_irq_event)
blr blr
#endif /* CONFIG_IRQSTACKS */ #endif /* CONFIG_IRQSTACKS */
/*
* To be called by C code which needs to do some operations with MMU
* disabled. Note that interrupts have to be disabled by the caller
* prior to calling us. The code called _MUST_ be in the RMO of course
* and part of the linear mapping as we don't attempt to translate the
* stack pointer at all. The function is called with the stack switched
* to this CPU emergency stack
*
* prototype is void *call_with_mmu_off(void *func, void *data);
*
* the called function is expected to be of the form
*
* void *called(void *data);
*/
_GLOBAL(call_with_mmu_off)
mflr r0 /* get link, save it on stackframe */
std r0,16(r1)
mr r1,r5 /* save old stack ptr */
ld r1,PACAEMERGSP(r13) /* get emerg. stack */
subi r1,r1,STACK_FRAME_OVERHEAD
std r0,16(r1) /* save link on emerg. stack */
std r5,0(r1) /* save old stack ptr in backchain */
ld r3,0(r3) /* get to real function ptr (assume same TOC) */
bl 2f /* we need LR to return, continue at label 2 */
ld r0,16(r1) /* we return here from the call, get LR and */
ld r1,0(r1) /* .. old stack ptr */
mtspr SPRN_SRR0,r0 /* and get back to virtual mode with these */
mfmsr r4
ori r4,r4,MSR_IR|MSR_DR
mtspr SPRN_SRR1,r4
rfid
2: mtspr SPRN_SRR0,r3 /* coming from above, enter real mode */
mr r3,r4 /* get parameter */
mfmsr r0
ori r0,r0,MSR_IR|MSR_DR
xori r0,r0,MSR_IR|MSR_DR
mtspr SPRN_SRR1,r0
rfid
/* /*
* Flush instruction cache. * Flush instruction cache.
*/ */
...@@ -454,17 +495,6 @@ _GLOBAL(_outsl_ns) ...@@ -454,17 +495,6 @@ _GLOBAL(_outsl_ns)
sync sync
blr blr
_GLOBAL(_get_PVR)
mfspr r3,PVR
blr
_GLOBAL(_get_PIR)
mfspr r3,PIR
blr
_GLOBAL(_get_HID0)
mfspr r3,HID0
blr
_GLOBAL(cvt_fd) _GLOBAL(cvt_fd)
lfd 0,0(r5) /* load up fpscr value */ lfd 0,0(r5) /* load up fpscr value */
...@@ -561,6 +591,69 @@ _GLOBAL(do_cpu_ftr_fixups) ...@@ -561,6 +591,69 @@ _GLOBAL(do_cpu_ftr_fixups)
isync isync
b 1b b 1b
#ifdef CONFIG_PPC_PMAC
/*
* Do an IO access in real mode
*/
_GLOBAL(real_readb)
mfmsr r7
ori r0,r7,MSR_DR
xori r0,r0,MSR_DR
sync
mtmsrd r0
sync
isync
mfspr r6,SPRN_HID4
rldicl r5,r6,32,0
ori r5,r5,0x100
rldicl r5,r5,32,0
sync
mtspr SPRN_HID4,r5
isync
slbia
isync
lbz r3,0(r3)
sync
mtspr SPRN_HID4,r6
isync
slbia
isync
mtmsrd r7
sync
isync
blr
/*
* Do an IO access in real mode
*/
_GLOBAL(real_writeb)
mfmsr r7
ori r0,r7,MSR_DR
xori r0,r0,MSR_DR
sync
mtmsrd r0
sync
isync
mfspr r6,SPRN_HID4
rldicl r5,r6,32,0
ori r5,r5,0x100
rldicl r5,r5,32,0
sync
mtspr SPRN_HID4,r5
isync
slbia
isync
stb r3,0(r4)
sync
mtspr SPRN_HID4,r6
isync
slbia
isync
mtmsrd r7
sync
isync
blr
#endif /* CONFIG_PPC_PMAC */
/* /*
* Create a kernel thread * Create a kernel thread
...@@ -594,7 +687,7 @@ _GLOBAL(kernel_thread) ...@@ -594,7 +687,7 @@ _GLOBAL(kernel_thread)
ld r30,-16(r1) ld r30,-16(r1)
blr blr
#ifdef CONFIG_PPC_ISERIES /* hack hack hack */ #ifndef CONFIG_PPC_PSERIE /* hack hack hack */
#define ppc_rtas sys_ni_syscall #define ppc_rtas sys_ni_syscall
#endif #endif
......
...@@ -603,6 +603,7 @@ void __exit nvram_cleanup(void) ...@@ -603,6 +603,7 @@ void __exit nvram_cleanup(void)
} }
#ifdef CONFIG_PPC_PSERIES
/* nvram_write_error_log /* nvram_write_error_log
* *
...@@ -727,6 +728,7 @@ int nvram_clear_error_log() ...@@ -727,6 +728,7 @@ int nvram_clear_error_log()
return 0; return 0;
} }
#endif /* CONFIG_PPC_PSERIES */
module_init(nvram_init); module_init(nvram_init);
module_exit(nvram_cleanup); module_exit(nvram_cleanup);
......
...@@ -362,7 +362,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack, ...@@ -362,7 +362,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
find_ISUs(); find_ISUs();
/* Initialize timer interrupts */ /* Initialize timer interrupts */
ppc64_boot_msg(0x21, "OpenPic Timer");
for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
/* Disabled, Priority 0 */ /* Disabled, Priority 0 */
openpic_inittimer(i, 0, openpic_vec_timer+i); openpic_inittimer(i, 0, openpic_vec_timer+i);
...@@ -372,7 +371,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack, ...@@ -372,7 +371,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Initialize IPI interrupts */ /* Initialize IPI interrupts */
ppc64_boot_msg(0x22, "OpenPic IPI");
openpic_test_broken_IPI(); openpic_test_broken_IPI();
for (i = 0; i < OPENPIC_NUM_IPI; i++) { for (i = 0; i < OPENPIC_NUM_IPI; i++) {
/* Disabled, Priority 10..13 */ /* Disabled, Priority 10..13 */
...@@ -384,8 +382,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack, ...@@ -384,8 +382,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
#endif #endif
/* Initialize external interrupts */ /* Initialize external interrupts */
ppc64_boot_msg(0x23, "OpenPic Ext");
openpic_set_priority(0xf); openpic_set_priority(0xf);
/* SIOint (8259 cascade) is special */ /* SIOint (8259 cascade) is special */
...@@ -420,7 +416,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack, ...@@ -420,7 +416,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
irq_desc[i].handler = &open_pic; irq_desc[i].handler = &open_pic;
/* Initialize the spurious interrupt */ /* Initialize the spurious interrupt */
ppc64_boot_msg(0x24, "OpenPic Spurious");
openpic_set_spurious(openpic_vec_spurious); openpic_set_spurious(openpic_vec_spurious);
openpic_set_priority(0); openpic_set_priority(0);
......
...@@ -344,5 +344,5 @@ void __init openpic2_init(int offset) ...@@ -344,5 +344,5 @@ void __init openpic2_init(int offset)
openpic2_set_priority(0); openpic2_set_priority(0);
openpic2_disable_8259_pass_through(); openpic2_disable_8259_pass_through();
ppc64_boot_msg(0x25, "OpenPic2 Done"); ppc64_boot_msg(0x25, "OpenPic U3 Done");
} }
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/plpar_wrappers.h>
#include "pci.h" #include "pci.h"
...@@ -88,6 +89,150 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) ...@@ -88,6 +89,150 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
} }
static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
enum dma_data_direction direction)
{
u64 rc;
union tce_entry tce;
tce.te_word = 0;
tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
tce.te_rdwr = 1;
if (direction != DMA_TO_DEVICE)
tce.te_pciwr = 1;
while (npages--) {
rc = plpar_tce_put((u64)tbl->it_index,
(u64)tcenum << 12,
tce.te_word );
if (rc && printk_ratelimit()) {
printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
printk("\ttcenum = 0x%lx\n", (u64)tcenum);
printk("\ttce val = 0x%lx\n", tce.te_word );
show_stack(current, (unsigned long *)__get_SP());
}
tcenum++;
tce.te_rpn++;
}
}
DEFINE_PER_CPU(void *, tce_page) = NULL;
static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
enum dma_data_direction direction)
{
u64 rc;
union tce_entry tce, *tcep;
long l, limit;
if (npages == 1)
return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
direction);
tcep = __get_cpu_var(tce_page);
/* This is safe to do since interrupts are off when we're called
* from iommu_alloc{,_sg}()
*/
if (!tcep) {
tcep = (void *)__get_free_page(GFP_ATOMIC);
/* If allocation fails, fall back to the loop implementation */
if (!tcep)
return tce_build_pSeriesLP(tbl, tcenum, npages,
uaddr, direction);
__get_cpu_var(tce_page) = tcep;
}
tce.te_word = 0;
tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
tce.te_rdwr = 1;
if (direction != DMA_TO_DEVICE)
tce.te_pciwr = 1;
/* We can map max one pageful of TCEs at a time */
do {
/*
* Set up the page with TCE data, looping through and setting
* the values.
*/
limit = min_t(long, npages, PAGE_SIZE/sizeof(union tce_entry));
for (l = 0; l < limit; l++) {
tcep[l] = tce;
tce.te_rpn++;
}
rc = plpar_tce_put_indirect((u64)tbl->it_index,
(u64)tcenum << 12,
(u64)virt_to_abs(tcep),
limit);
npages -= limit;
tcenum += limit;
} while (npages > 0 && !rc);
if (rc && printk_ratelimit()) {
printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
printk("\tnpages = 0x%lx\n", (u64)npages);
printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
show_stack(current, (unsigned long *)__get_SP());
}
}
static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
{
u64 rc;
union tce_entry tce;
tce.te_word = 0;
while (npages--) {
rc = plpar_tce_put((u64)tbl->it_index,
(u64)tcenum << 12,
tce.te_word);
if (rc && printk_ratelimit()) {
printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
printk("\ttcenum = 0x%lx\n", (u64)tcenum);
printk("\ttce val = 0x%lx\n", tce.te_word );
show_stack(current, (unsigned long *)__get_SP());
}
tcenum++;
}
}
static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
{
u64 rc;
union tce_entry tce;
tce.te_word = 0;
rc = plpar_tce_stuff((u64)tbl->it_index,
(u64)tcenum << 12,
tce.te_word,
npages);
if (rc && printk_ratelimit()) {
printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
printk("\trc = %ld\n", rc);
printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
printk("\tnpages = 0x%lx\n", (u64)npages);
printk("\ttce val = 0x%lx\n", tce.te_word );
show_stack(current, (unsigned long *)__get_SP());
}
}
static void iommu_buses_init(void) static void iommu_buses_init(void)
{ {
struct pci_controller *phb, *tmp; struct pci_controller *phb, *tmp;
...@@ -166,24 +311,25 @@ static void iommu_table_setparms(struct pci_controller *phb, ...@@ -166,24 +311,25 @@ static void iommu_table_setparms(struct pci_controller *phb,
struct device_node *dn, struct device_node *dn,
struct iommu_table *tbl) struct iommu_table *tbl)
{ {
phandle node; struct device_node *node;
unsigned long i; unsigned long *basep;
struct of_tce_table *oft; unsigned int *sizep;
node = ((struct device_node *)(phb->arch_data))->node;
oft = NULL; node = (struct device_node *)phb->arch_data;
for (i=0; of_tce_table[i].node; i++) if (get_property(node, "linux,has-tce-table", NULL) == NULL) {
if(of_tce_table[i].node == node) { printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has no tce table !\n",
oft = &of_tce_table[i]; dn->full_name);
break; return;
} }
basep = (unsigned long *)get_property(node, "linux,tce-base", NULL);
if (!oft) sizep = (unsigned int *)get_property(node, "linux,tce-size", NULL);
panic("PCI_DMA: iommu_table_setparms: Can't find phb named '%s' in of_tce_table\n", dn->full_name); if (basep == NULL || sizep == NULL) {
printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has missing tce"
memset((void *)oft->base, 0, oft->size); " entries !\n", dn->full_name);
return;
}
memset((void *)(*basep), 0, *sizep);
tbl->it_busno = phb->bus->number; tbl->it_busno = phb->bus->number;
...@@ -207,7 +353,7 @@ static void iommu_table_setparms(struct pci_controller *phb, ...@@ -207,7 +353,7 @@ static void iommu_table_setparms(struct pci_controller *phb,
if (phb->dma_window_base_cur > (1 << 19)) if (phb->dma_window_base_cur > (1 << 19))
panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
tbl->it_base = oft->base; tbl->it_base = *basep;
tbl->it_index = 0; tbl->it_index = 0;
tbl->it_entrysize = sizeof(union tce_entry); tbl->it_entrysize = sizeof(union tce_entry);
tbl->it_blocksize = 16; tbl->it_blocksize = 16;
...@@ -295,8 +441,16 @@ void iommu_setup_pSeries(void) ...@@ -295,8 +441,16 @@ void iommu_setup_pSeries(void)
/* These are called very early. */ /* These are called very early. */
void tce_init_pSeries(void) void tce_init_pSeries(void)
{ {
if (!(systemcfg->platform & PLATFORM_LPAR)) {
ppc_md.tce_build = tce_build_pSeries; ppc_md.tce_build = tce_build_pSeries;
ppc_md.tce_free = tce_free_pSeries; ppc_md.tce_free = tce_free_pSeries;
} else if (cur_cpu_spec->firmware_features & FW_FEATURE_MULTITCE) {
ppc_md.tce_build = tce_buildmulti_pSeriesLP;
ppc_md.tce_free = tce_freemulti_pSeriesLP;
} else {
ppc_md.tce_build = tce_build_pSeriesLP;
ppc_md.tce_free = tce_free_pSeriesLP;
}
pci_iommu_init(); pci_iommu_init();
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -54,9 +54,9 @@ static inline struct iommu_table *devnode_table(struct pci_dev *dev) ...@@ -54,9 +54,9 @@ static inline struct iommu_table *devnode_table(struct pci_dev *dev)
return ISERIES_DEVNODE(dev)->iommu_table; return ISERIES_DEVNODE(dev)->iommu_table;
#endif /* CONFIG_PPC_ISERIES */ #endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_MULTIPLATFORM
return PCI_GET_DN(dev)->iommu_table; return PCI_GET_DN(dev)->iommu_table;
#endif /* CONFIG_PPC_PSERIES */ #endif /* CONFIG_PPC_MULTIPLATFORM */
} }
......
...@@ -29,4 +29,6 @@ extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, ...@@ -29,4 +29,6 @@ extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
extern void pmac_nvram_init(void); extern void pmac_nvram_init(void);
extern void pmac_iommu_alloc(void);
#endif /* __PMAC_H__ */ #endif /* __PMAC_H__ */
...@@ -44,9 +44,9 @@ ...@@ -44,9 +44,9 @@
#undef DEBUG_FEATURE #undef DEBUG_FEATURE
#ifdef DEBUG_FEATURE #ifdef DEBUG_FEATURE
#define DBG(fmt,...) printk(KERN_DEBUG fmt) #define DBG(fmt...) printk(KERN_DEBUG fmt)
#else #else
#define DBG(fmt,...) #define DBG(fmt...)
#endif #endif
/* /*
......
...@@ -37,13 +37,14 @@ ...@@ -37,13 +37,14 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/lmb.h>
#include "pci.h" #include "pci.h"
...@@ -76,8 +77,8 @@ ...@@ -76,8 +77,8 @@
#define DARTMAP_RPNMASK 0x00ffffff #define DARTMAP_RPNMASK 0x00ffffff
/* Physical base address and size of the DART table */ /* Physical base address and size of the DART table */
unsigned long dart_tablebase; unsigned long dart_tablebase; /* exported to htab_initialize */
unsigned long dart_tablesize; static unsigned long dart_tablesize;
/* Virtual base address of the DART table */ /* Virtual base address of the DART table */
static u32 *dart_vbase; static u32 *dart_vbase;
...@@ -263,7 +264,6 @@ static int dart_init(struct device_node *dart_node) ...@@ -263,7 +264,6 @@ static int dart_init(struct device_node *dart_node)
return 0; return 0;
} }
void iommu_setup_pmac(void) void iommu_setup_pmac(void)
{ {
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
...@@ -300,6 +300,22 @@ void iommu_setup_pmac(void) ...@@ -300,6 +300,22 @@ void iommu_setup_pmac(void)
} }
} }
void __init pmac_iommu_alloc(void)
{
/* Only reserve DART space if machine has more than 2GB of RAM
* or if requested with iommu=on on cmdline.
*/
if (lmb_end_of_DRAM() <= 0x80000000ull &&
get_property(of_chosen, "linux,iommu-force-on", NULL) == NULL)
return;
/* 512 pages (2MB) is max DART tablesize. */
dart_tablesize = 1UL << 21;
/* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
* will blow up an entire large page anyway in the kernel mapping
*/
dart_tablebase = (unsigned long)
abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
printk(KERN_INFO "U3-DART allocated at: %lx\n", dart_tablebase);
}
...@@ -746,6 +746,9 @@ void __init pmac_pci_init(void) ...@@ -746,6 +746,9 @@ void __init pmac_pci_init(void)
* the exception of U3/AGP (hook into pci_set_mwi) * the exception of U3/AGP (hook into pci_set_mwi)
*/ */
pci_cache_line_size = 16; /* 64 bytes */ pci_cache_line_size = 16; /* 64 bytes */
/* Allow all IO */
io_page_mask = -1;
} }
/* /*
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
* bootup setup stuff.. * bootup setup stuff..
*/ */
#undef DEBUG
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -63,7 +65,6 @@ ...@@ -63,7 +65,6 @@
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/bootx.h>
#include <asm/btext.h> #include <asm/btext.h>
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/pmac_feature.h> #include <asm/pmac_feature.h>
...@@ -73,6 +74,13 @@ ...@@ -73,6 +74,13 @@
#include "pmac.h" #include "pmac.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
static int current_root_goodness = -1; static int current_root_goodness = -1;
#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */
...@@ -81,10 +89,6 @@ int sccdbg; ...@@ -81,10 +89,6 @@ int sccdbg;
extern void udbg_init_scc(struct device_node *np); extern void udbg_init_scc(struct device_node *np);
#ifdef CONFIG_BOOTX_TEXT
void pmac_progress(char *s, unsigned short hex);
#endif
void __pmac pmac_show_cpuinfo(struct seq_file *m) void __pmac pmac_show_cpuinfo(struct seq_file *m)
{ {
struct device_node *np; struct device_node *np;
...@@ -134,28 +138,20 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m) ...@@ -134,28 +138,20 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m)
void __init pmac_setup_arch(void) void __init pmac_setup_arch(void)
{ {
struct device_node *cpu; /* init to some ~sane value until calibrate_delay() runs */
int *fp; loops_per_jiffy = 50000000;
unsigned long pvr;
pvr = PVR_VER(mfspr(PVR));
/* Set loops_per_jiffy to a half-way reasonable value,
for use until calibrate_delay gets called. */
cpu = find_type_devices("cpu");
if (cpu != 0) {
fp = (int *) get_property(cpu, "clock-frequency", NULL);
if (fp != 0) {
if (pvr == 4 || pvr >= 8)
/* 604, G3, G4 etc. */
loops_per_jiffy = *fp / HZ;
else
/* 601, 603, etc. */
loops_per_jiffy = *fp / (2*HZ);
} else
loops_per_jiffy = 50000000 / HZ;
}
/* Probe motherboard chipset */
pmac_feature_init();
#if 0
/* Lock-enable the SCC channel used for debug */
if (sccdbg) {
np = of_find_node_by_name(NULL, "escc");
if (np)
pmac_call_feature(PMAC_FTR_SCC_ENABLE, np,
PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
}
#endif
/* We can NAP */ /* We can NAP */
powersave_nap = 1; powersave_nap = 1;
...@@ -183,67 +179,13 @@ void __init pmac_setup_arch(void) ...@@ -183,67 +179,13 @@ void __init pmac_setup_arch(void)
#endif #endif
} }
extern char *bootpath;
extern char *bootdevice;
void *boot_host;
int boot_target;
int boot_part;
extern dev_t boot_dev;
#ifdef CONFIG_SCSI #ifdef CONFIG_SCSI
void __init note_scsi_host(struct device_node *node, void *host) void note_scsi_host(struct device_node *node, void *host)
{ {
int l; /* Obsolete */
char *p;
l = strlen(node->full_name);
if (bootpath != NULL && bootdevice != NULL
&& strncmp(node->full_name, bootdevice, l) == 0
&& (bootdevice[l] == '/' || bootdevice[l] == 0)) {
boot_host = host;
/*
* There's a bug in OF 1.0.5. (Why am I not surprised.)
* If you pass a path like scsi/sd@1:0 to canon, it returns
* something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
* That is, the scsi target number doesn't get preserved.
* So we pick the target number out of bootpath and use that.
*/
p = strstr(bootpath, "/sd@");
if (p != NULL) {
p += 4;
boot_target = simple_strtoul(p, NULL, 10);
p = strchr(p, ':');
if (p != NULL)
boot_part = simple_strtoul(p + 1, NULL, 10);
}
}
} }
#endif #endif
#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
static dev_t __init find_ide_boot(void)
{
char *p;
int n;
dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
if (bootdevice == NULL)
return 0;
p = strrchr(bootdevice, '/');
if (p == NULL)
return 0;
n = p - bootdevice;
return pmac_find_ide_boot(bootdevice, n);
}
#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
void __init find_boot_device(void)
{
#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
boot_dev = find_ide_boot();
#endif
}
static int initializing = 1; static int initializing = 1;
...@@ -258,7 +200,7 @@ late_initcall(pmac_late_init); ...@@ -258,7 +200,7 @@ late_initcall(pmac_late_init);
/* can't be __init - can be called whenever a disk is first accessed */ /* can't be __init - can be called whenever a disk is first accessed */
void __pmac note_bootable_part(dev_t dev, int part, int goodness) void __pmac note_bootable_part(dev_t dev, int part, int goodness)
{ {
static int found_boot = 0; extern dev_t boot_dev;
char *p; char *p;
if (!initializing) if (!initializing)
...@@ -270,10 +212,6 @@ void __pmac note_bootable_part(dev_t dev, int part, int goodness) ...@@ -270,10 +212,6 @@ void __pmac note_bootable_part(dev_t dev, int part, int goodness)
if (p != NULL && (p == saved_command_line || p[-1] == ' ')) if (p != NULL && (p == saved_command_line || p[-1] == ' '))
return; return;
if (!found_boot) {
find_boot_device();
found_boot = 1;
}
if (!boot_dev || dev == boot_dev) { if (!boot_dev || dev == boot_dev) {
ROOT_DEV = dev + part; ROOT_DEV = dev + part;
boot_dev = 0; boot_dev = 0;
...@@ -313,21 +251,73 @@ static void btext_putc(unsigned char c) ...@@ -313,21 +251,73 @@ static void btext_putc(unsigned char c)
} }
#endif /* CONFIG_BOOTX_TEXT */ #endif /* CONFIG_BOOTX_TEXT */
static void __init init_boot_display(void)
{
char *name;
struct device_node *np = NULL;
int rc = -ENODEV;
printk("trying to initialize btext ...\n");
name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
if (name != NULL) {
np = of_find_node_by_path(name);
if (np != NULL) {
if (strcmp(np->type, "display") != 0) {
printk("boot stdout isn't a display !\n");
of_node_put(np);
np = NULL;
}
}
}
if (np)
rc = btext_initialize(np);
if (rc == 0)
return;
for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
if (get_property(np, "linux,opened", NULL)) {
printk("trying %s ...\n", np->full_name);
rc = btext_initialize(np);
printk("result: %d\n", rc);
}
if (rc == 0)
return;
}
}
/* /*
* Early initialization. * Early initialization.
* Relocation is on but do not reference unbolted pages
* Also, device-tree hasn't been "finished", so don't muck with
* it too much
*/ */
void __init pmac_init_early(void) void __init pmac_init_early(void)
{ {
hpte_init_pSeries(); DBG(" -> pmac_init_early\n");
/* Initialize hash table, from now on, we can take hash faults
* and call ioremap
*/
hpte_init_native();
/* Init SCC */
if (strstr(cmd_line, "sccdbg")) {
sccdbg = 1;
udbg_init_scc(NULL);
}
else {
#ifdef CONFIG_BOOTX_TEXT #ifdef CONFIG_BOOTX_TEXT
init_boot_display();
ppc_md.udbg_putc = btext_putc; ppc_md.udbg_putc = btext_putc;
ppc_md.udbg_getc = dummy_getc; ppc_md.udbg_getc = dummy_getc;
ppc_md.udbg_getc_poll = dummy_getc_poll; ppc_md.udbg_getc_poll = dummy_getc_poll;
#endif /* CONFIG_BOOTX_TEXT */ #endif /* CONFIG_BOOTX_TEXT */
}
/* Setup interrupt mapping options */
naca->interrupt_controller = IC_OPEN_PIC;
DBG(" <- pmac_init_early\n");
} }
extern void* OpenPIC_Addr; extern void* OpenPIC_Addr;
...@@ -417,60 +407,19 @@ static int __init pmac_irq_cascade_init(void) ...@@ -417,60 +407,19 @@ static int __init pmac_irq_cascade_init(void)
core_initcall(pmac_irq_cascade_init); core_initcall(pmac_irq_cascade_init);
void __init pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, static void __init pmac_progress(char *s, unsigned short hex)
unsigned long r6, unsigned long r7)
{
/* Probe motherboard chipset */
pmac_feature_init();
/* Init SCC */
if (strstr(cmd_line, "sccdbg")) {
sccdbg = 1;
udbg_init_scc(NULL);
}
/* Fill up the machine description */
ppc_md.setup_arch = pmac_setup_arch;
ppc_md.get_cpuinfo = pmac_show_cpuinfo;
ppc_md.init_IRQ = pmac_init_IRQ;
ppc_md.get_irq = openpic_get_irq;
ppc_md.pcibios_fixup = pmac_pcibios_fixup;
ppc_md.restart = pmac_restart;
ppc_md.power_off = pmac_power_off;
ppc_md.halt = pmac_halt;
ppc_md.get_boot_time = pmac_get_boot_time;
ppc_md.set_rtc_time = pmac_set_rtc_time;
ppc_md.get_rtc_time = pmac_get_rtc_time;
ppc_md.calibrate_decr = pmac_calibrate_decr;
ppc_md.feature_call = pmac_do_feature_call;
#ifdef CONFIG_BOOTX_TEXT
ppc_md.progress = pmac_progress;
#endif /* CONFIG_BOOTX_TEXT */
if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
}
#ifdef CONFIG_BOOTX_TEXT
void __init pmac_progress(char *s, unsigned short hex)
{ {
if (sccdbg) { if (sccdbg) {
udbg_puts(s); udbg_puts(s);
udbg_putc('\n'); udbg_puts("\n");
} }
#ifdef CONFIG_BOOTX_TEXT
else if (boot_text_mapped) { else if (boot_text_mapped) {
btext_drawstring(s); btext_drawstring(s);
btext_drawchar('\n'); btext_drawstring("\n");
} }
}
#endif /* CONFIG_BOOTX_TEXT */ #endif /* CONFIG_BOOTX_TEXT */
}
static int __init pmac_declare_of_platform_devices(void) static int __init pmac_declare_of_platform_devices(void)
{ {
...@@ -489,3 +438,43 @@ static int __init pmac_declare_of_platform_devices(void) ...@@ -489,3 +438,43 @@ static int __init pmac_declare_of_platform_devices(void)
} }
device_initcall(pmac_declare_of_platform_devices); device_initcall(pmac_declare_of_platform_devices);
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
static int __init pmac_probe(int platform)
{
if (platform != PLATFORM_POWERMAC)
return 0;
#ifdef CONFIG_PMAC_DART
/*
* On U3, the DART (iommu) must be allocated now since it
* has an impact on htab_initialize (due to the large page it
* occupies having to be broken up so the DART itself is not
* part of the cacheable linar mapping
*/
pmac_iommu_alloc();
#endif /* CONFIG_PMAC_DART */
return 1;
}
struct machdep_calls __initdata pmac_md = {
.probe = pmac_probe,
.setup_arch = pmac_setup_arch,
.init_early = pmac_init_early,
.get_cpuinfo = pmac_show_cpuinfo,
.init_IRQ = pmac_init_IRQ,
.get_irq = openpic_get_irq,
.pcibios_fixup = pmac_pcibios_fixup,
.restart = pmac_restart,
.power_off = pmac_power_off,
.halt = pmac_halt,
.get_boot_time = pmac_get_boot_time,
.set_rtc_time = pmac_set_rtc_time,
.get_rtc_time = pmac_get_rtc_time,
.calibrate_decr = pmac_calibrate_decr,
.feature_call = pmac_do_feature_call,
.progress = pmac_progress,
};
...@@ -119,7 +119,6 @@ EXPORT_SYMBOL(start_thread); ...@@ -119,7 +119,6 @@ EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(flush_instruction_cache); EXPORT_SYMBOL(flush_instruction_cache);
EXPORT_SYMBOL(_get_PVR);
EXPORT_SYMBOL(giveup_fpu); EXPORT_SYMBOL(giveup_fpu);
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
EXPORT_SYMBOL(giveup_altivec); EXPORT_SYMBOL(giveup_altivec);
......
This diff is collapsed.
This diff is collapsed.
...@@ -42,13 +42,16 @@ char rtas_err_buf[RTAS_ERROR_LOG_MAX]; ...@@ -42,13 +42,16 @@ char rtas_err_buf[RTAS_ERROR_LOG_MAX];
spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED; spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED;
char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned; char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned;
unsigned long rtas_rmo_buf;
void void
call_rtas_display_status(char c) call_rtas_display_status(unsigned char c)
{ {
struct rtas_args *args = &rtas.args; struct rtas_args *args = &rtas.args;
unsigned long s; unsigned long s;
if (!rtas.base)
return;
spin_lock_irqsave(&rtas.lock, s); spin_lock_irqsave(&rtas.lock, s);
args->token = 10; args->token = 10;
...@@ -62,6 +65,31 @@ call_rtas_display_status(char c) ...@@ -62,6 +65,31 @@ call_rtas_display_status(char c)
spin_unlock_irqrestore(&rtas.lock, s); spin_unlock_irqrestore(&rtas.lock, s);
} }
void
call_rtas_display_status_delay(unsigned char c)
{
static int pending_newline = 0; /* did last write end with unprinted newline? */
static int width = 16;
if (c == '\n') {
while (width-- > 0)
call_rtas_display_status(' ');
width = 16;
udelay(500000);
pending_newline = 1;
} else {
if (pending_newline) {
call_rtas_display_status('\r');
call_rtas_display_status('\n');
}
pending_newline = 0;
if (width--) {
call_rtas_display_status(c);
udelay(10000);
}
}
}
int int
rtas_token(const char *service) rtas_token(const char *service)
{ {
...@@ -425,7 +453,6 @@ void rtas_os_term(char *str) ...@@ -425,7 +453,6 @@ void rtas_os_term(char *str)
} while (status == RTAS_BUSY); } while (status == RTAS_BUSY);
} }
unsigned long rtas_rmo_buf = 0;
asmlinkage int ppc_rtas(struct rtas_args __user *uargs) asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
{ {
...@@ -536,6 +563,53 @@ int rtas_get_error_log_max(void) ...@@ -536,6 +563,53 @@ int rtas_get_error_log_max(void)
return rtas_error_log_max; return rtas_error_log_max;
} }
/*
* Call early during boot, before mem init or bootmem, to retreive the RTAS
* informations from the device-tree and allocate the RMO buffer for userland
* accesses.
*/
void __init rtas_initialize(void)
{
/* Get RTAS dev node and fill up our "rtas" structure with infos
* about it.
*/
rtas.dev = of_find_node_by_name(NULL, "rtas");
if (rtas.dev) {
u64 *basep, *entryp;
u32 *sizep;
basep = (u64 *)get_property(of_chosen, "linux,rtas-base", NULL);
sizep = (u32 *)get_property(of_chosen, "linux,rtas-size", NULL);
if (basep != NULL && sizep != NULL) {
rtas.base = *basep;
rtas.size = *sizep;
entryp = (u64 *)get_property(of_chosen, "linux,rtas-entry", NULL);
if (entryp == NULL) /* Ugh */
rtas.entry = rtas.base;
else
rtas.entry = *entryp;
} else
rtas.dev = NULL;
}
/* If RTAS was found, allocate the RMO buffer for it and look for
* the stop-self token if any
*/
if (rtas.dev) {
unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE,
rtas_region);
#ifdef CONFIG_HOTPLUG_CPU
rtas_stop_self_args.token = rtas_token("stop-self");
#endif /* CONFIG_HOTPLUG_CPU */
}
}
EXPORT_SYMBOL(rtas_firmware_flash_list); EXPORT_SYMBOL(rtas_firmware_flash_list);
EXPORT_SYMBOL(rtas_token); EXPORT_SYMBOL(rtas_token);
EXPORT_SYMBOL(rtas_call); EXPORT_SYMBOL(rtas_call);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -8,3 +8,4 @@ obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \ ...@@ -8,3 +8,4 @@ obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \
slb_low.o slb.o stab.o mmap.o slb_low.o slb.o stab.o mmap.o
obj-$(CONFIG_DISCONTIGMEM) += numa.o obj-$(CONFIG_DISCONTIGMEM) += numa.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment