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"
choice
prompt "Platform Type"
default PPC_PSERIES
default PPC_MULTIPLATFORM
config PPC_ISERIES
bool "iSeries"
bool "IBM Legacy iSeries"
config PPC_PSERIES
bool "pSeries / PowerMac G5"
config PPC_MULTIPLATFORM
bool "Generic"
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
bool
default y
......@@ -77,7 +88,7 @@ config PPC64
default y
config PPC_OF
depends on PPC_PSERIES
depends on PPC_MULTIPLATFORM
bool
default y
......@@ -85,14 +96,9 @@ config PPC_OF
# exception vectors for it
config ALTIVEC
bool "Support for VMX (Altivec) vector unit"
depends on PPC_PSERIES
depends on PPC_MULTIPLATFORM
default y
config PPC_PMAC
depends on PPC_PSERIES
bool "Apple PowerMac G5 support"
select ADB_PMU
config PPC_SPLPAR
depends on PPC_PSERIES
bool "Support for shared-processor logical partitions"
......@@ -163,7 +169,7 @@ config SMP
config IRQ_ALL_CPUS
bool "Distribute interrupts on all CPUs by default"
depends on SMP && PPC_PSERIES
depends on SMP && PPC_MULTIPLATFORM
help
This option gives the kernel permission to distribute IRQs across
multiple CPUs. Saying N here will route all IRQs to the first
......
......@@ -31,6 +31,7 @@ BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional
BOOTLD := $(CROSS32_COMPILE)ld
BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
BOOTOBJCOPY := $(CROSS32_COMPILE)objcopy
BOOTSTRIP := $(CROSS32_COMPILE)strip
OBJCOPYFLAGS := contents,alloc,load,readonly,data
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
#-----------------------------------------------------------
# ELF sections within the zImage bootloader/wrapper
#-----------------------------------------------------------
required := vmlinux .config System.map
required := vmlinux.strip
initrd := initrd
obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section)))
src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(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 \
$(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
vmlinux.sm vmlinux.initrd vmlinux.sminitrd
extra-y := sysmap.o 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)
vmlinux.initrd
extra-y := initrd.o
quiet_cmd_ramdisk = RAMDISK $@
cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map $< $@
$(obj)/vmlinux.initrd: vmlinux $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map FORCE
$(call if_changed,ramdisk)
cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz $< $@
$(obj)/vmlinux.sminitrd: $(obj)/vmlinux.sm $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
$(call if_changed,ramdisk)
quiet_cmd_stripvm = STRIP $@
cmd_stripvm = $(BOOTSTRIP) -s $< -o $@
$(obj)/sysmap.o: System.map $(obj)/piggyback FORCE
$(call if_changed,piggy)
vmlinux.strip: vmlinux FORCE
$(call if_changed,stripvm)
$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
$(call if_changed,ramdisk)
addsection = $(BOOTOBJCOPY) $(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))
$(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(obj)/addnote FORCE
$(call if_changed,addnote)
$(obj)/imagesize.c: vmlinux
$(obj)/imagesize.c: vmlinux.strip
@echo Generating $@
ls -l vmlinux | \
ls -l vmlinux.strip | \
awk '{printf "/* generated -- do not edit! */\n" \
"unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c
$(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
......@@ -123,6 +119,6 @@ $(obj)/imagesize.c: vmlinux
>> $(obj)/imagesize.c
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))
#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);
void *memmove(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 */
#define PROG_START 0x01400000
#define RAM_END (256<<20) // Fixme: use OF */
char *avail_ram;
char *begin_avail, *end_avail;
......@@ -48,8 +44,6 @@ unsigned int heap_max;
extern char _start[];
extern char _vmlinux_start[];
extern char _vmlinux_end[];
extern char _sysmap_start[];
extern char _sysmap_end[];
extern char _initrd_start[];
extern char _initrd_end[];
extern unsigned long vmlinux_filesize;
......@@ -62,7 +56,6 @@ struct addr_range {
};
struct addr_range vmlinux = {0, 0, 0};
struct addr_range vmlinuz = {0, 0, 0};
struct addr_range sysmap = {0, 0, 0};
struct addr_range initrd = {0, 0, 0};
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,
unsigned long,
void *,
struct bi_record *);
void *);
int (*prom)(void *);
......@@ -80,12 +73,31 @@ void *stdin;
void *stdout;
void *stderr;
#define DEBUG
static unsigned long claim_base = PROG_START;
static unsigned long try_claim(unsigned long size)
{
unsigned long addr = 0;
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)
void start(unsigned long a1, unsigned long a2, void *promptr)
{
unsigned long i, claim_addr, claim_size;
struct bi_record *bi_recs;
unsigned long i;
kernel_entry_t kernel_entry;
Elf64_Ehdr *elf64;
Elf64_Phdr *elf64ph;
......@@ -102,61 +114,59 @@ start(unsigned long a1, unsigned long a2, void *promptr)
printf("zImage starting: loaded at 0x%x\n\r", (unsigned)_start);
#if 0
sysmap.size = (unsigned long)(_sysmap_end - _sysmap_start);
sysmap.memsize = sysmap.size;
if ( sysmap.size > 0 ) {
sysmap.addr = (RAM_END - sysmap.size) & ~0xFFF;
claim(sysmap.addr, RAM_END - sysmap.addr, 0);
printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
sysmap.addr, (unsigned long)_sysmap_start, sysmap.size);
memcpy((void *)sysmap.addr, (void *)_sysmap_start, sysmap.size);
/*
* Now we try to claim some memory for the kernel itself
* our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what
* our Makefile stuffs in is an image containing all sort of junk including
* an ELF header. We need to do some calculations here to find the right
* size... In practice we add 1Mb, that is enough, but we should really
* consider fixing the Makefile to put a _raw_ kernel in there !
*/
vmlinux_memsize += 0x100000;
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize);
vmlinux.addr = try_claim(vmlinux_memsize);
if (vmlinux.addr == 0) {
printf("Can't allocate memory for kernel image !\n\r");
exit();
}
#endif
vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
vmlinux.memsize = vmlinux_memsize;
/*
* Now we try to claim memory for the initrd (and copy it there)
*/
initrd.size = (unsigned long)(_initrd_end - _initrd_start);
initrd.memsize = initrd.size;
if ( initrd.size > 0 ) {
initrd.addr = (RAM_END - initrd.size) & ~0xFFF;
a1 = a2 = 0;
claim(initrd.addr, RAM_END - initrd.addr, 0);
printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
initrd.addr = try_claim(initrd.size);
if (initrd.addr == 0) {
printf("Can't allocate memory for initial ramdisk !\n\r");
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);
memcpy((void *)initrd.addr, (void *)_initrd_start, initrd.size);
}
vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
vmlinux.addr = (unsigned long)(void *)-1;
vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
vmlinux.memsize = vmlinux_memsize;
claim_size = vmlinux.memsize /* PPPBBB: + fudge for bi_recs */;
for(claim_addr = PROG_START;
claim_addr <= PROG_START * 8;
claim_addr += 0x100000) {
#ifdef DEBUG
printf(" trying: 0x%08lx\n\r", claim_addr);
#endif
vmlinux.addr = (unsigned long)claim(claim_addr, claim_size, 0);
if ((void *)vmlinux.addr != (void *)-1) break;
}
if ((void *)vmlinux.addr == (void *)-1) {
printf("claim error, can't allocate kernel memory\n\r");
exit();
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) {
int len;
avail_ram = scratch;
begin_avail = avail_high = avail_ram;
end_avail = scratch + sizeof(scratch);
printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...",
vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);
len = vmlinuz.size;
gunzip((void *)vmlinux.addr, vmlinux.size,
(unsigned char *)vmlinuz.addr, (int *)&vmlinuz.size);
printf("done %lu bytes\n\r", vmlinuz.size);
printf("%u bytes of heap consumed, max in use %u\n\r",
(unsigned char *)vmlinuz.addr, &len);
printf("done 0x%lx bytes\n\r", len);
printf("0x%x bytes of heap consumed, max in use 0x%\n\r",
(unsigned)(avail_high - begin_avail), heap_max);
} else {
memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
......@@ -192,7 +202,8 @@ start(unsigned long a1, unsigned long a2, void *promptr)
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;
#ifdef DEBUG
......@@ -203,65 +214,16 @@ start(unsigned long a1, unsigned long a2, void *promptr)
" prom = 0x%lx,\n\r"
" bi_recs = 0x%lx,\n\r",
(unsigned long)kernel_entry, a1, a2,
(unsigned long)prom, (unsigned long)bi_recs);
(unsigned long)prom, NULL);
#endif
kernel_entry( a1, a2, prom, bi_recs );
kernel_entry( a1, a2, prom, NULL );
printf("Error: Linux kernel returned to zImage bootloader!\n\r");
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 {
unsigned int size;
unsigned int pad;
......
......@@ -61,19 +61,9 @@ SECTIONS
. = ALIGN(4096);
_vmlinux_start = .;
.kernel:vmlinux : { *(.kernel:vmlinux) }
.kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) }
_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);
_initrd_start = .;
.kernel:initrd : { *(.kernel:initrd) }
......
This diff is collapsed.
#
# 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_MMU=y
......@@ -20,6 +22,7 @@ CONFIG_CLEAN_COMPILE=y
#
# General setup
#
CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
......@@ -61,12 +64,13 @@ CONFIG_SYSVIPC_COMPAT=y
# Platform support
#
# CONFIG_PPC_ISERIES is not set
CONFIG_PPC_MULTIPLATFORM=y
CONFIG_PPC_PSERIES=y
# CONFIG_PPC_PMAC is not set
CONFIG_PPC=y
CONFIG_PPC64=y
CONFIG_PPC_OF=y
CONFIG_ALTIVEC=y
# CONFIG_PPC_PMAC is not set
CONFIG_PPC_SPLPAR=y
# CONFIG_BOOTX_TEXT is not set
# CONFIG_POWER4_ONLY is not set
......@@ -189,7 +193,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
CONFIG_BLK_DEV_AMD74XX=y
......@@ -365,6 +368,8 @@ CONFIG_NETFILTER=y
# IP: Netfilter Configuration
#
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_IRC=m
CONFIG_IP_NF_TFTP=m
......@@ -389,8 +394,14 @@ CONFIG_IP_NF_MATCH_HELPER=m
CONFIG_IP_NF_MATCH_STATE=m
CONFIG_IP_NF_MATCH_CONNTRACK=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_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_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
......@@ -409,21 +420,13 @@ CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_DSCP=m
CONFIG_IP_NF_TARGET_MARK=m
CONFIG_IP_NF_TARGET_CLASSIFY=m
CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_IP_NF_TARGET_TCPMSS=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_TARGET_NOTRACK=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_IP_NF_COMPAT_IPCHAINS=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_USER=m
......@@ -604,6 +607,7 @@ CONFIG_SERIO_I8042=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PCIPS2 is not set
# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
......@@ -621,6 +625,7 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_PCSPKR is not set
# CONFIG_INPUT_UINPUT is not set
#
......
......@@ -17,7 +17,7 @@ obj-$(CONFIG_PPC_OF) += of_device.o
pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.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)
......@@ -28,10 +28,11 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.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 \
eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \
open_pic.o xics.o pSeries_htab.o rtas.o \
chrp_setup.o i8259.o prom.o pSeries_iommu.o
eeh.o pSeries_nvram.o rtasd.o ras.o \
xics.o rtas.o pSeries_setup.o pSeries_iommu.o
obj-$(CONFIG_PROC_FS) += proc_ppc64.o
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
......
......@@ -33,7 +33,6 @@
#include <asm/iSeries/ItLpPaca.h>
#include <asm/iSeries/ItLpQueue.h>
#include <asm/iSeries/HvLpEvent.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/cputable.h>
......@@ -108,7 +107,6 @@ int main(void)
DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1));
DEFINE(LPPACAANYINT, offsetof(struct ItLpPaca, xIntDword.xAnyInt));
DEFINE(LPPACADECRINT, offsetof(struct ItLpPaca, xIntDword.xFields.xDecrInt));
DEFINE(PROMENTRY, offsetof(struct prom_t, entry));
/* RTAS */
DEFINE(RTASBASE, offsetof(struct rtas_t, base));
......
This diff is collapsed.
......@@ -746,6 +746,10 @@ _STATIC(rtas_restore_regs)
mtlr r0
blr /* return to caller */
#endif /* CONFIG_PPC_PSERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
_GLOBAL(enter_prom)
mflr r0
std r0,16(r1)
......@@ -777,11 +781,8 @@ _GLOBAL(enter_prom)
std r11,_MSR(r1)
/* Get the PROM entrypoint */
bl .reloc_offset
LOADADDR(r12,prom)
sub r12,r12,r3
ld r12,PROMENTRY(r12)
mtlr r12
ld r0,GPR4(r1)
mtlr r0
/* Switch MSR to 32 bits mode
*/
......@@ -834,4 +835,4 @@ _GLOBAL(enter_prom)
mtlr r0
blr
#endif /* defined(CONFIG_PPC_PSERIES) */
#endif /* CONFIG_PPC_MULTIPLATFORM */
......@@ -83,13 +83,14 @@
.text
.globl _stext
_stext:
#ifdef CONFIG_PPC_PSERIES
_STATIC(__start)
#ifdef CONFIG_PPC_MULTIPLATFORM
_GLOBAL(__start)
/* NOP this out unconditionally */
BEGIN_FTR_SECTION
b .__start_initialization_pSeries
b .__start_initialization_multiplatform
END_FTR_SECTION(0, 1)
#endif
#endif /* CONFIG_PPC_MULTIPLATFORM */
/* Catch branch to 0 in real mode */
trap
#ifdef CONFIG_PPC_ISERIES
......@@ -117,7 +118,8 @@ embedded_sysmap_start:
.globl embedded_sysmap_end
embedded_sysmap_end:
.llong 0
#else
#else /* CONFIG_PPC_ISERIES */
/* Secondary processors spin on this value until it goes to 1. */
.globl __secondary_hold_spinloop
......@@ -1223,12 +1225,10 @@ _GLOBAL(pseries_secondary_smp_init)
#endif
b 1b /* Loop until told to go */
#ifdef CONFIG_PPC_ISERIES
_GLOBAL(__start_initialization_iSeries)
_STATIC(__start_initialization_iSeries)
/* Clear out the BSS */
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 */
......@@ -1265,32 +1265,73 @@ _GLOBAL(__start_initialization_iSeries)
ld r6,PACA(r4) /* Get the base paca pointer */
ld r4,PACASTABVIRT(r6)
bl .iSeries_fixup_klimit
bl .iSeries_early_setup
/* relocation is on at this point */
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
andi. r0,r3,MSR_IR|MSR_DR
beqlr
andc r3,r3,r0
mtspr SRR0,r4
mtspr SRR1,r3
mtspr SPRN_SRR0,r4
mtspr SPRN_SRR1,r3
sync
rfid
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 r29,r5
mr r28,r6
mr r27,r7
/* Make sure we are running in 64 bits mode */
bl .enable_64b_mode
/* put a relocation offset into r3 */
......@@ -1303,7 +1344,7 @@ _GLOBAL(__start_initialization_pSeries)
/* Relocate the TOC from a virt addr to a real addr */
sub r2,r2,r3
/* Save parameters */
/* Restore parameters */
mr r3,r31
mr r4,r30
mr r5,r29
......@@ -1312,17 +1353,8 @@ _GLOBAL(__start_initialization_pSeries)
/* Do all of the interaction with OF client interface */
bl .prom_init
mr r23,r3 /* Save phys address we are running at */
/* 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
/* We never return */
trap
/*
* At this point, r3 contains the physical address we are running at,
......@@ -1348,7 +1380,7 @@ _STATIC(__after_prom_start)
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 */
/* current address of _start */
/* i.e. where we are running */
......@@ -1373,8 +1405,9 @@ _STATIC(__after_prom_start)
ld r5,0(r5) /* get the value of klimit */
sub r5,r5,r27
bl .copy_and_flush /* copy the rest */
b .start_here_pSeries
#endif
b .start_here_multiplatform
#endif /* CONFIG_PPC_MULTIPLATFORM */
/*
* Copy routine used to copy the kernel to start at physical address 0
......@@ -1794,15 +1827,33 @@ _GLOBAL(enable_64b_mode)
isync
blr
#ifdef CONFIG_PPC_PSERIES
#ifdef CONFIG_PPC_MULTIPLATFORM
/*
* 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. */
bl .reloc_offset
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
ori r6,r6,MSR_RI
mtmsrd r6 /* RI on */
......@@ -1875,8 +1926,11 @@ _STATIC(start_here_pSeries)
mr r5,r26
bl .identify_cpu
/* Get the pointer to the segment table which is used by */
/* stab_initialize */
/* Setup a valid physical PACA pointer in SPRG3 for early_setup
* 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)
sub r27,r27,r26
lwz r27,0(r27)
......@@ -1885,12 +1939,18 @@ _STATIC(start_here_pSeries)
mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r13,r24 /* for this processor. */
sub r13,r13,r26 /* convert to physical addr */
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 */
ld r3,PACASTABREAL(r13)
ori r4,r3,1 /* turn on valid bit */
li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES_LPAR
......@@ -1909,13 +1969,7 @@ _STATIC(start_here_pSeries)
98: /* !(rpa hypervisor) || !(star) */
mtasr r4 /* set the stab location */
99:
mfspr r6,SPRG3
ld r3,PACASTABREAL(r6) /* restore r3 for stab_initialize */
/* Initialize an initial memory mapping and turn on relocation. */
bl .stab_initialize
bl .htab_initialize
/* Set SDR1 (hash table pointer) */
li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */
/* Test if bit 0 is set (LPAR bit) */
......@@ -1932,7 +1986,7 @@ _STATIC(start_here_pSeries)
mtspr SRR1,r4
rfid
b . /* prevent speculative execution */
#endif /* CONFIG_PPC_PSERIES */
#endif /* CONFIG_PPC_MULTIPLATFORM */
/* This is where all platforms converge execution */
_STATIC(start_here_common)
......@@ -1980,13 +2034,6 @@ _STATIC(start_here_common)
ld r2,PACATOC(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
/* Load up the kernel context */
......
......@@ -233,4 +233,6 @@ void hpte_init_iSeries(void)
ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
ppc_md.hpte_insert = iSeries_hpte_insert;
ppc_md.hpte_remove = iSeries_hpte_remove;
htab_finish_init();
}
......@@ -16,6 +16,8 @@
* 2 of the License, or (at your option) any later version.
*/
#undef DEBUG
#include <linux/config.h>
#include <linux/init.h>
#include <linux/threads.h>
......@@ -54,6 +56,14 @@
#include <asm/iSeries/iSeries_proc.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 */
extern void ppcdbg_initialize(void);
extern void tce_init_iSeries(void);
......@@ -75,8 +85,6 @@ static unsigned long tbFreqMhzHundreths;
int piranha_simulator;
int boot_cpuid;
extern int rd_size; /* Defined in drivers/block/rd.c */
extern unsigned long klimit;
extern unsigned long embedded_sysmap_start;
......@@ -275,8 +283,28 @@ unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
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();
#if defined(CONFIG_BLK_DEV_INITRD)
......@@ -300,25 +328,20 @@ void __init iSeries_init_early(void)
iSeries_recal_tb = get_tb();
iSeries_recal_titan = HvCallXm_loadTod();
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 = NULL;
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;
/*
* Cache sizes must be initialized before hpte_init_iSeries is called
* as the later need them for flush_icache_range()
*/
setup_iSeries_cache_sizes();
/*
* Initialize the hash table management pointers
*/
hpte_init_iSeries();
/*
* Initialize the DMA/TCE management
*/
tce_init_iSeries();
/*
......@@ -326,7 +349,7 @@ void __init iSeries_init_early(void)
* AS/400 absolute addresses
*/
build_iSeries_Memory_Map();
setup_iSeries_cache_sizes();
/* Initialize machine-dependency vectors */
#ifdef CONFIG_SMP
smp_init_iSeries();
......@@ -340,24 +363,22 @@ void __init iSeries_init_early(void)
mf_init();
mf_initialized = 1;
mb();
}
void __init iSeries_parse_cmdline(void)
{
char *p, *q;
/* If we were passed an initrd, set the ROOT_DEV properly if the values
* look sensible. If not, clear initrd reference.
*/
#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;
q = cmd_line + 255;
while(p < q) {
if (!*p || *p == '\n')
break;
++p;
}
*p = 0;
iSeries_parse_cmdline();
DBG(" <- iSeries_init_early()\n");
}
/*
......@@ -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
......@@ -810,3 +831,27 @@ int __init iSeries_src_init(void)
}
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 @@
#ifndef __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_residual(struct seq_file *m, int cpu_id);
extern void iSeries_get_cpuinfo(struct seq_file *m);
......
......@@ -30,9 +30,8 @@
#include <asm/time.h>
#include <asm/iSeries/HvCall.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);
static int (*idle_loop)(void);
......@@ -153,6 +152,8 @@ static int default_idle(void)
return 0;
}
#ifdef CONFIG_PPC_PSERIES
DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
int dedicated_idle(void)
......@@ -280,9 +281,12 @@ static int shared_idle(void)
return 0;
}
static int powermac_idle(void)
#endif /* CONFIG_PPC_PSERIES */
static int native_idle(void)
{
while(1) {
/* check CPU type here */
if (!need_resched())
power4_idle();
if (need_resched())
......@@ -290,7 +294,8 @@ static int powermac_idle(void)
}
return 0;
}
#endif
#endif /* CONFIG_PPC_ISERIES */
int cpu_idle(void)
{
......@@ -332,30 +337,38 @@ __initcall(register_powersave_nap_sysctl);
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
idle_loop = iSeries_idle;
return 1;
#else
idle_loop = default_idle;
#endif
#ifdef CONFIG_PPC_PSERIES
if (systemcfg->platform & PLATFORM_PSERIES) {
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
if (get_paca()->lppaca.xSharedProc) {
printk("idle = shared_idle\n");
printk(KERN_INFO "Using shared processor idle loop\n");
idle_loop = shared_idle;
} else {
printk("idle = dedicated_idle\n");
printk(KERN_INFO "Using dedicated idle loop\n");
idle_loop = dedicated_idle;
}
} else {
printk("idle = default_idle\n");
printk(KERN_INFO "Using default idle loop\n");
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;
}
......@@ -22,6 +22,43 @@
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
lmb_addrs_overlap(unsigned long base1, unsigned long size1,
unsigned long base2, unsigned long size2)
......@@ -71,8 +108,7 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
void __init
lmb_init(void)
{
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb *_lmb = &lmb;
/* Create a dummy zero size LMB which will get coalesced away later.
* This simplifies the lmb_add() code below...
......@@ -94,8 +130,7 @@ lmb_analyze(void)
unsigned long i;
unsigned long mem_size = 0;
unsigned long size_mask = 0;
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb *_lmb = &lmb;
#ifdef CONFIG_MSCHUNKS
unsigned long physbase = 0;
#endif
......@@ -178,8 +213,7 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
long __init
lmb_add(unsigned long base, unsigned long size)
{
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb *_lmb = &lmb;
struct lmb_region *_rgn = &(_lmb->memory);
/* On pSeries LPAR systems, the first LMB is our RMO region. */
......@@ -193,8 +227,7 @@ lmb_add(unsigned long base, unsigned long size)
long __init
lmb_reserve(unsigned long base, unsigned long size)
{
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb *_lmb = &lmb;
struct lmb_region *_rgn = &(_lmb->reserved);
return lmb_add_region(_rgn, base, size);
......@@ -227,8 +260,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
{
long i, j;
unsigned long base = 0;
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb *_lmb = &lmb;
struct lmb_region *_mem = &(_lmb->memory);
struct lmb_region *_rsv = &(_lmb->reserved);
......@@ -263,8 +295,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
unsigned long __init
lmb_phys_mem_size(void)
{
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb *_lmb = &lmb;
#ifdef CONFIG_MSCHUNKS
return _lmb->memory.size;
#else
......@@ -282,8 +313,7 @@ lmb_phys_mem_size(void)
unsigned long __init
lmb_end_of_DRAM(void)
{
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb *_lmb = &lmb;
struct lmb_region *_mem = &(_lmb->memory);
int idx = _mem->cnt - 1;
......@@ -300,8 +330,7 @@ unsigned long __init
lmb_abs_to_phys(unsigned long aa)
{
unsigned long i, pa = aa;
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb *_lmb = &lmb;
struct lmb_region *_mem = &(_lmb->memory);
for (i=0; i < _mem->cnt; i++) {
......
......@@ -127,6 +127,47 @@ _GLOBAL(call_handle_irq_event)
blr
#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.
*/
......@@ -454,17 +495,6 @@ _GLOBAL(_outsl_ns)
sync
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)
lfd 0,0(r5) /* load up fpscr value */
......@@ -561,6 +591,69 @@ _GLOBAL(do_cpu_ftr_fixups)
isync
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
......@@ -594,7 +687,7 @@ _GLOBAL(kernel_thread)
ld r30,-16(r1)
blr
#ifdef CONFIG_PPC_ISERIES /* hack hack hack */
#ifndef CONFIG_PPC_PSERIE /* hack hack hack */
#define ppc_rtas sys_ni_syscall
#endif
......
......@@ -603,6 +603,7 @@ void __exit nvram_cleanup(void)
}
#ifdef CONFIG_PPC_PSERIES
/* nvram_write_error_log
*
......@@ -727,6 +728,7 @@ int nvram_clear_error_log()
return 0;
}
#endif /* CONFIG_PPC_PSERIES */
module_init(nvram_init);
module_exit(nvram_cleanup);
......
......@@ -362,7 +362,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
find_ISUs();
/* Initialize timer interrupts */
ppc64_boot_msg(0x21, "OpenPic Timer");
for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
/* Disabled, Priority 0 */
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,
#ifdef CONFIG_SMP
/* Initialize IPI interrupts */
ppc64_boot_msg(0x22, "OpenPic IPI");
openpic_test_broken_IPI();
for (i = 0; i < OPENPIC_NUM_IPI; i++) {
/* Disabled, Priority 10..13 */
......@@ -384,8 +382,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
#endif
/* Initialize external interrupts */
ppc64_boot_msg(0x23, "OpenPic Ext");
openpic_set_priority(0xf);
/* SIOint (8259 cascade) is special */
......@@ -420,7 +416,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
irq_desc[i].handler = &open_pic;
/* Initialize the spurious interrupt */
ppc64_boot_msg(0x24, "OpenPic Spurious");
openpic_set_spurious(openpic_vec_spurious);
openpic_set_priority(0);
......
......@@ -344,5 +344,5 @@ void __init openpic2_init(int offset)
openpic2_set_priority(0);
openpic2_disable_8259_pass_through();
ppc64_boot_msg(0x25, "OpenPic2 Done");
ppc64_boot_msg(0x25, "OpenPic U3 Done");
}
......@@ -42,6 +42,7 @@
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#include <asm/abs_addr.h>
#include <asm/plpar_wrappers.h>
#include "pci.h"
......@@ -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)
{
struct pci_controller *phb, *tmp;
......@@ -166,24 +311,25 @@ static void iommu_table_setparms(struct pci_controller *phb,
struct device_node *dn,
struct iommu_table *tbl)
{
phandle node;
unsigned long i;
struct of_tce_table *oft;
node = ((struct device_node *)(phb->arch_data))->node;
struct device_node *node;
unsigned long *basep;
unsigned int *sizep;
oft = NULL;
node = (struct device_node *)phb->arch_data;
for (i=0; of_tce_table[i].node; i++)
if(of_tce_table[i].node == node) {
oft = &of_tce_table[i];
break;
}
if (!oft)
panic("PCI_DMA: iommu_table_setparms: Can't find phb named '%s' in of_tce_table\n", dn->full_name);
memset((void *)oft->base, 0, oft->size);
if (get_property(node, "linux,has-tce-table", NULL) == NULL) {
printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has no tce table !\n",
dn->full_name);
return;
}
basep = (unsigned long *)get_property(node, "linux,tce-base", NULL);
sizep = (unsigned int *)get_property(node, "linux,tce-size", NULL);
if (basep == NULL || sizep == NULL) {
printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has missing tce"
" entries !\n", dn->full_name);
return;
}
memset((void *)(*basep), 0, *sizep);
tbl->it_busno = phb->bus->number;
......@@ -207,7 +353,7 @@ static void iommu_table_setparms(struct pci_controller *phb,
if (phb->dma_window_base_cur > (1 << 19))
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_entrysize = sizeof(union tce_entry);
tbl->it_blocksize = 16;
......@@ -295,8 +441,16 @@ void iommu_setup_pSeries(void)
/* These are called very early. */
void tce_init_pSeries(void)
{
ppc_md.tce_build = tce_build_pSeries;
ppc_md.tce_free = tce_free_pSeries;
if (!(systemcfg->platform & PLATFORM_LPAR)) {
ppc_md.tce_build = tce_build_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();
}
......
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)
return ISERIES_DEVNODE(dev)->iommu_table;
#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_PSERIES
#ifdef CONFIG_PPC_MULTIPLATFORM
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,
extern void pmac_nvram_init(void);
extern void pmac_iommu_alloc(void);
#endif /* __PMAC_H__ */
......@@ -44,9 +44,9 @@
#undef DEBUG_FEATURE
#ifdef DEBUG_FEATURE
#define DBG(fmt,...) printk(KERN_DEBUG fmt)
#define DBG(fmt...) printk(KERN_DEBUG fmt)
#else
#define DBG(fmt,...)
#define DBG(fmt...)
#endif
/*
......
......@@ -37,13 +37,14 @@
#include <linux/vmalloc.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/ppcdebug.h>
#include <asm/iommu.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#include <asm/abs_addr.h>
#include <asm/cacheflush.h>
#include <asm/lmb.h>
#include "pci.h"
......@@ -76,8 +77,8 @@
#define DARTMAP_RPNMASK 0x00ffffff
/* Physical base address and size of the DART table */
unsigned long dart_tablebase;
unsigned long dart_tablesize;
unsigned long dart_tablebase; /* exported to htab_initialize */
static unsigned long dart_tablesize;
/* Virtual base address of the DART table */
static u32 *dart_vbase;
......@@ -263,7 +264,6 @@ static int dart_init(struct device_node *dart_node)
return 0;
}
void iommu_setup_pmac(void)
{
struct pci_dev *dev = NULL;
......@@ -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)
* the exception of U3/AGP (hook into pci_set_mwi)
*/
pci_cache_line_size = 16; /* 64 bytes */
/* Allow all IO */
io_page_mask = -1;
}
/*
......
......@@ -23,6 +23,8 @@
* bootup setup stuff..
*/
#undef DEBUG
#include <linux/config.h>
#include <linux/init.h>
#include <linux/errno.h>
......@@ -63,7 +65,6 @@
#include <asm/iommu.h>
#include <asm/machdep.h>
#include <asm/dma.h>
#include <asm/bootx.h>
#include <asm/btext.h>
#include <asm/cputable.h>
#include <asm/pmac_feature.h>
......@@ -73,6 +74,13 @@
#include "pmac.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
static int current_root_goodness = -1;
#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */
......@@ -81,10 +89,6 @@ int sccdbg;
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)
{
struct device_node *np;
......@@ -134,28 +138,20 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m)
void __init pmac_setup_arch(void)
{
struct device_node *cpu;
int *fp;
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;
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000;
/* 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 */
powersave_nap = 1;
......@@ -183,67 +179,13 @@ void __init pmac_setup_arch(void)
#endif
}
extern char *bootpath;
extern char *bootdevice;
void *boot_host;
int boot_target;
int boot_part;
extern dev_t boot_dev;
#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;
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);
}
}
/* Obsolete */
}
#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;
......@@ -258,7 +200,7 @@ late_initcall(pmac_late_init);
/* 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)
{
static int found_boot = 0;
extern dev_t boot_dev;
char *p;
if (!initializing)
......@@ -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] == ' '))
return;
if (!found_boot) {
find_boot_device();
found_boot = 1;
}
if (!boot_dev || dev == boot_dev) {
ROOT_DEV = dev + part;
boot_dev = 0;
......@@ -313,21 +251,73 @@ static void btext_putc(unsigned char c)
}
#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.
* 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)
{
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
ppc_md.udbg_putc = btext_putc;
ppc_md.udbg_getc = dummy_getc;
ppc_md.udbg_getc_poll = dummy_getc_poll;
init_boot_display();
ppc_md.udbg_putc = btext_putc;
ppc_md.udbg_getc = dummy_getc;
ppc_md.udbg_getc_poll = dummy_getc_poll;
#endif /* CONFIG_BOOTX_TEXT */
}
/* Setup interrupt mapping options */
naca->interrupt_controller = IC_OPEN_PIC;
DBG(" <- pmac_init_early\n");
}
extern void* OpenPIC_Addr;
......@@ -417,60 +407,19 @@ static int __init pmac_irq_cascade_init(void)
core_initcall(pmac_irq_cascade_init);
void __init pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
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)
static void __init pmac_progress(char *s, unsigned short hex)
{
if (sccdbg) {
udbg_puts(s);
udbg_putc('\n');
udbg_puts("\n");
}
#ifdef CONFIG_BOOTX_TEXT
else if (boot_text_mapped) {
btext_drawstring(s);
btext_drawchar('\n');
btext_drawstring("\n");
}
}
#endif /* CONFIG_BOOTX_TEXT */
}
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);
/*
* 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);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(flush_instruction_cache);
EXPORT_SYMBOL(_get_PVR);
EXPORT_SYMBOL(giveup_fpu);
#ifdef CONFIG_ALTIVEC
EXPORT_SYMBOL(giveup_altivec);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -84,7 +84,7 @@ static unsigned long first_settimeofday = 1;
#define XSEC_PER_SEC (1024*1024)
unsigned long tb_ticks_per_jiffy;
unsigned long tb_ticks_per_usec;
unsigned long tb_ticks_per_usec = 100; /* sane default */
unsigned long tb_ticks_per_sec;
unsigned long next_xtime_sync_tb;
unsigned long xtime_sync_interval;
......
This diff is collapsed.
......@@ -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
obj-$(CONFIG_DISCONTIGMEM) += numa.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.o
This diff is collapsed.
......@@ -133,7 +133,7 @@ int __init oprofile_arch_init(struct oprofile_operations **ops)
{
unsigned int pvr;
pvr = _get_PVR();
pvr = mfspr(SPRN_PVR);
switch (PVR_VER(pvr)) {
case PV_630:
......
......@@ -252,30 +252,28 @@ extern inline void sync(void)
static inline void disable_surveillance(void)
{
#ifndef CONFIG_PPC_ISERIES
#ifdef CONFIG_PPC_PSERIES
/* Since this can't be a module, args should end up below 4GB. */
static struct rtas_args args;
if (systemcfg->platform & PLATFORM_PSERIES) {
/*
* At this point we have got all the cpus we can into
* xmon, so there is hopefully no other cpu calling RTAS
* at the moment, even though we don't take rtas.lock.
* If we did try to take rtas.lock there would be a
* real possibility of deadlock.
*/
args.token = rtas_token("set-indicator");
if (args.token == RTAS_UNKNOWN_SERVICE)
return;
args.nargs = 3;
args.nret = 1;
args.rets = &args.args[3];
args.args[0] = SURVEILLANCE_TOKEN;
args.args[1] = 0;
args.args[2] = 0;
enter_rtas(__pa(&args));
}
#endif
/*
* At this point we have got all the cpus we can into
* xmon, so there is hopefully no other cpu calling RTAS
* at the moment, even though we don't take rtas.lock.
* If we did try to take rtas.lock there would be a
* real possibility of deadlock.
*/
args.token = rtas_token("set-indicator");
if (args.token == RTAS_UNKNOWN_SERVICE)
return;
args.nargs = 3;
args.nret = 1;
args.rets = &args.args[3];
args.args[0] = SURVEILLANCE_TOKEN;
args.args[1] = 0;
args.args[2] = 0;
enter_rtas(__pa(&args));
#endif /* CONFIG_PPC_PSERIES */
}
#ifdef CONFIG_SMP
......
This diff is collapsed.
This diff is collapsed.
......@@ -7,23 +7,20 @@
#define __PPC_BTEXT_H
#ifdef __KERNEL__
#include <asm/bootx.h>
extern void btext_clearscreen(void);
extern void btext_flushscreen(void);
extern boot_infos_t disp_bi;
extern int boot_text_mapped;
void btext_setup_display(int width, int height, int depth, int pitch,
unsigned long address);
void map_boot_text(void);
void btext_update_display(unsigned long phys, int width, int height,
int depth, int pitch);
extern int btext_initialize(struct device_node *np);
extern void map_boot_text(void);
extern void btext_update_display(unsigned long phys, int width, int height,
int depth, int pitch);
void btext_drawchar(char c);
void btext_drawstring(const char *str);
void btext_drawhex(unsigned long v);
extern void btext_drawchar(char c);
extern void btext_drawstring(const char *str);
extern void btext_drawhex(unsigned long v);
#endif /* __KERNEL__ */
#endif /* __PPC_BTEXT_H */
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