Commit 6150c325 authored by Linus Torvalds's avatar Linus Torvalds
parents 44637a12 be42d5fa
This diff is collapsed.
...@@ -8,12 +8,18 @@ please mail me. ...@@ -8,12 +8,18 @@ please mail me.
cpu_features.txt cpu_features.txt
- info on how we support a variety of CPUs with minimal compile-time - info on how we support a variety of CPUs with minimal compile-time
options. options.
eeh-pci-error-recovery.txt
- info on PCI Bus EEH Error Recovery
hvcs.txt
- IBM "Hypervisor Virtual Console Server" Installation Guide
mpc52xx.txt
- Linux 2.6.x on MPC52xx family
ppc_htab.txt ppc_htab.txt
- info about the Linux/PPC /proc/ppc_htab entry - info about the Linux/PPC /proc/ppc_htab entry
smp.txt
- use and state info about Linux/PPC on MP machines
SBC8260_memory_mapping.txt SBC8260_memory_mapping.txt
- EST SBC8260 board info - EST SBC8260 board info
smp.txt
- use and state info about Linux/PPC on MP machines
sound.txt sound.txt
- info on sound support under Linux/PPC - info on sound support under Linux/PPC
zImage_layout.txt zImage_layout.txt
......
...@@ -47,7 +47,7 @@ config PPC ...@@ -47,7 +47,7 @@ config PPC
config EARLY_PRINTK config EARLY_PRINTK
bool bool
default y if PPC64 default y
config COMPAT config COMPAT
bool bool
...@@ -297,6 +297,7 @@ config PPC_PMAC64 ...@@ -297,6 +297,7 @@ config PPC_PMAC64
bool bool
depends on PPC_PMAC && POWER4 depends on PPC_PMAC && POWER4
select U3_DART select U3_DART
select MPIC_BROKEN_U3
select GENERIC_TBSYNC select GENERIC_TBSYNC
default y default y
...@@ -325,9 +326,7 @@ config PPC_CELL ...@@ -325,9 +326,7 @@ config PPC_CELL
select MMIO_NVRAM select MMIO_NVRAM
config PPC_OF config PPC_OF
bool def_bool y
depends on PPC_MULTIPLATFORM # for now
default y
config XICS config XICS
depends on PPC_PSERIES depends on PPC_PSERIES
...@@ -376,11 +375,28 @@ config CELL_IIC ...@@ -376,11 +375,28 @@ config CELL_IIC
bool bool
default y default y
config CRASH_DUMP
bool "kernel crash dumps (EXPERIMENTAL)"
depends on PPC_MULTIPLATFORM
depends on EXPERIMENTAL
help
Build a kernel suitable for use as a kdump capture kernel.
The kernel will be linked at a different address than normal, and
so can only be used for Kdump.
Don't change this unless you know what you are doing.
config IBMVIO config IBMVIO
depends on PPC_PSERIES || PPC_ISERIES depends on PPC_PSERIES || PPC_ISERIES
bool bool
default y default y
config IBMEBUS
depends on PPC_PSERIES
bool "Support for GX bus based adapters"
help
Bus device driver for GX bus based adapters.
config PPC_MPC106 config PPC_MPC106
bool bool
default n default n
...@@ -472,6 +488,7 @@ source arch/powerpc/platforms/embedded6xx/Kconfig ...@@ -472,6 +488,7 @@ source arch/powerpc/platforms/embedded6xx/Kconfig
source arch/powerpc/platforms/4xx/Kconfig source arch/powerpc/platforms/4xx/Kconfig
source arch/powerpc/platforms/85xx/Kconfig source arch/powerpc/platforms/85xx/Kconfig
source arch/powerpc/platforms/8xx/Kconfig source arch/powerpc/platforms/8xx/Kconfig
source arch/powerpc/platforms/cell/Kconfig
menu "Kernel options" menu "Kernel options"
...@@ -575,11 +592,12 @@ config ARCH_SELECT_MEMORY_MODEL ...@@ -575,11 +592,12 @@ config ARCH_SELECT_MEMORY_MODEL
depends on PPC64 depends on PPC64
config ARCH_FLATMEM_ENABLE config ARCH_FLATMEM_ENABLE
def_bool y def_bool y
depends on PPC64 && !NUMA depends on (PPC64 && !NUMA) || PPC32
config ARCH_SPARSEMEM_ENABLE config ARCH_SPARSEMEM_ENABLE
def_bool y def_bool y
depends on PPC64
config ARCH_SPARSEMEM_DEFAULT config ARCH_SPARSEMEM_DEFAULT
def_bool y def_bool y
......
...@@ -151,7 +151,7 @@ CPPFLAGS_vmlinux.lds := -Upowerpc ...@@ -151,7 +151,7 @@ CPPFLAGS_vmlinux.lds := -Upowerpc
# All the instructions talk about "make bzImage". # All the instructions talk about "make bzImage".
bzImage: zImage bzImage: zImage
BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage
.PHONY: $(BOOT_TARGETS) .PHONY: $(BOOT_TARGETS)
......
...@@ -143,6 +143,36 @@ $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote ...@@ -143,6 +143,36 @@ $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote
@cp -f $< $@ @cp -f $< $@
$(call if_changed,addnote) $(call if_changed,addnote)
#-----------------------------------------------------------
# build u-boot images
#-----------------------------------------------------------
quiet_cmd_mygzip = GZIP $@
cmd_mygzip = gzip -f -9 < $< > $@.$$$$ && mv $@.$$$$ $@
quiet_cmd_objbin = OBJCOPY $@
cmd_objbin = $(OBJCOPY) -O binary $< $@
quiet_cmd_uimage = UIMAGE $@
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A ppc -O linux -T kernel \
-C gzip -a 00000000 -e 00000000 -n 'Linux-$(KERNELRELEASE)' \
-d $< $@
MKIMAGE := $(srctree)/scripts/mkuboot.sh
targets += uImage
extra-y += vmlinux.bin vmlinux.gz
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objbin)
$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
$(call if_changed,mygzip)
$(obj)/uImage: $(obj)/vmlinux.gz
$(Q)rm -f $@
$(call cmd,uimage)
@echo -n ' Image: $@ '
@if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
install: $(CONFIGURE) $(BOOTIMAGE) install: $(CONFIGURE) $(BOOTIMAGE)
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)" sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"
......
This diff is collapsed.
...@@ -17,11 +17,11 @@ obj-y += vdso32/ ...@@ -17,11 +17,11 @@ obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o systbl.o \ signal_64.o ptrace32.o systbl.o \
paca.o ioctl32.o cpu_setup_power4.o \ paca.o ioctl32.o cpu_setup_power4.o \
firmware.o sysfs.o udbg.o idle_64.o firmware.o sysfs.o idle_64.o
obj-$(CONFIG_PPC64) += vdso64/ obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
obj-$(CONFIG_POWER4) += idle_power4.o obj-$(CONFIG_POWER4) += idle_power4.o
obj-$(CONFIG_PPC_OF) += of_device.o obj-$(CONFIG_PPC_OF) += of_device.o prom_parse.o
procfs-$(CONFIG_PPC64) := proc_ppc64.o procfs-$(CONFIG_PPC64) := proc_ppc64.o
obj-$(CONFIG_PROC_FS) += $(procfs-y) obj-$(CONFIG_PROC_FS) += $(procfs-y)
rtaspci-$(CONFIG_PPC64) := rtas_pci.o rtaspci-$(CONFIG_PPC64) := rtas_pci.o
...@@ -30,12 +30,10 @@ obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o ...@@ -30,12 +30,10 @@ obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_LPARCFG) += lparcfg.o
obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_IBMVIO) += vio.o
obj-$(CONFIG_IBMEBUS) += ibmebus.o
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o
obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o
udbgscc-$(CONFIG_PPC64) := udbg_scc.o
obj-$(CONFIG_PPC_PMAC) += $(udbgscc-y)
obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
ifeq ($(CONFIG_PPC_MERGE),y) ifeq ($(CONFIG_PPC_MERGE),y)
...@@ -48,25 +46,25 @@ extra-$(CONFIG_8xx) := head_8xx.o ...@@ -48,25 +46,25 @@ extra-$(CONFIG_8xx) := head_8xx.o
extra-y += vmlinux.lds extra-y += vmlinux.lds
obj-y += process.o init_task.o time.o \ obj-y += process.o init_task.o time.o \
prom.o traps.o setup-common.o prom.o traps.o setup-common.o udbg.o
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o
obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
obj-$(CONFIG_PPC_OF) += prom_init.o obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
obj-$(CONFIG_MODULES) += ppc_ksyms.o obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_6xx) += idle_6xx.o obj-$(CONFIG_6xx) += idle_6xx.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_SERIAL_8250) += legacy_serial.o udbg_16550.o
module-$(CONFIG_PPC64) += module_64.o module-$(CONFIG_PPC64) += module_64.o
obj-$(CONFIG_MODULES) += $(module-y) obj-$(CONFIG_MODULES) += $(module-y)
pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \
pci_direct_iommu.o iomap.o pci_direct_iommu.o iomap.o
obj-$(CONFIG_PCI) += $(pci64-y) obj-$(CONFIG_PCI) += $(pci64-y)
kexec-$(CONFIG_PPC64) := machine_kexec_64.o
kexec64-$(CONFIG_PPC64) += machine_kexec_64.o kexec-$(CONFIG_PPC32) := machine_kexec_32.o
obj-$(CONFIG_KEXEC) += $(kexec64-y) obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y)
ifeq ($(CONFIG_PPC_ISERIES),y) ifeq ($(CONFIG_PPC_ISERIES),y)
$(obj)/head_64.o: $(obj)/lparmap.s $(obj)/head_64.o: $(obj)/lparmap.s
......
...@@ -92,9 +92,9 @@ int main(void) ...@@ -92,9 +92,9 @@ int main(void)
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); DEFINE(TI_SIGFRAME, offsetof(struct thread_info, nvgprs_frame));
#ifdef CONFIG_PPC32
DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_TASK, offsetof(struct thread_info, task));
#ifdef CONFIG_PPC32
DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
#endif /* CONFIG_PPC32 */ #endif /* CONFIG_PPC32 */
...@@ -131,11 +131,9 @@ int main(void) ...@@ -131,11 +131,9 @@ int main(void)
DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
#endif /* CONFIG_HUGETLB_PAGE */ #endif /* CONFIG_HUGETLB_PAGE */
DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr));
DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi));
DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca));
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
......
...@@ -31,15 +31,18 @@ static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb); ...@@ -31,15 +31,18 @@ static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb);
static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb); static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb);
static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb); static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb);
static int g_loc_X; #define __force_data __attribute__((__section__(".data")))
static int g_loc_Y;
static int g_max_loc_X;
static int g_max_loc_Y;
static int dispDeviceRowBytes; static int g_loc_X __force_data;
static int dispDeviceDepth; static int g_loc_Y __force_data;
static int dispDeviceRect[4]; static int g_max_loc_X __force_data;
static unsigned char *dispDeviceBase, *logicalDisplayBase; static int g_max_loc_Y __force_data;
static int dispDeviceRowBytes __force_data;
static int dispDeviceDepth __force_data;
static int dispDeviceRect[4] __force_data;
static unsigned char *dispDeviceBase __force_data;
static unsigned char *logicalDisplayBase __force_data;
unsigned long disp_BAT[2] __initdata = {0, 0}; unsigned long disp_BAT[2] __initdata = {0, 0};
...@@ -47,7 +50,7 @@ unsigned long disp_BAT[2] __initdata = {0, 0}; ...@@ -47,7 +50,7 @@ unsigned long disp_BAT[2] __initdata = {0, 0};
static unsigned char vga_font[cmapsz]; static unsigned char vga_font[cmapsz];
int boot_text_mapped; int boot_text_mapped __force_data = 0;
int force_printk_to_btext = 0; int force_printk_to_btext = 0;
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC32
...@@ -57,7 +60,7 @@ int force_printk_to_btext = 0; ...@@ -57,7 +60,7 @@ int force_printk_to_btext = 0;
* *
* The display is mapped to virtual address 0xD0000000, rather * The display is mapped to virtual address 0xD0000000, rather
* than 1:1, because some some CHRP machines put the frame buffer * than 1:1, because some some CHRP machines put the frame buffer
* in the region starting at 0xC0000000 (KERNELBASE). * in the region starting at 0xC0000000 (PAGE_OFFSET).
* This mapping is temporary and will disappear as soon as the * This mapping is temporary and will disappear as soon as the
* setup done by MMU_Init() is applied. * setup done by MMU_Init() is applied.
* *
...@@ -66,10 +69,9 @@ int force_printk_to_btext = 0; ...@@ -66,10 +69,9 @@ int force_printk_to_btext = 0;
* is really badly aligned, but I didn't encounter this case * is really badly aligned, but I didn't encounter this case
* yet. * yet.
*/ */
void __init void __init btext_prepare_BAT(void)
btext_prepare_BAT(void)
{ {
unsigned long vaddr = KERNELBASE + 0x10000000; unsigned long vaddr = PAGE_OFFSET + 0x10000000;
unsigned long addr; unsigned long addr;
unsigned long lowbits; unsigned long lowbits;
...@@ -95,12 +97,13 @@ btext_prepare_BAT(void) ...@@ -95,12 +97,13 @@ btext_prepare_BAT(void)
} }
#endif #endif
/* This function will enable the early boot text when doing OF booting. This
* way, xmon output should work too /* This function can be used to enable the early boot text when doing
* OF booting or within bootx init. It must be followed by a btext_unmap()
* call before the logical address becomes unuseable
*/ */
void __init void __init btext_setup_display(int width, int height, int depth, int pitch,
btext_setup_display(int width, int height, int depth, int pitch, unsigned long address)
unsigned long address)
{ {
g_loc_X = 0; g_loc_X = 0;
g_loc_Y = 0; g_loc_Y = 0;
...@@ -116,6 +119,11 @@ btext_setup_display(int width, int height, int depth, int pitch, ...@@ -116,6 +119,11 @@ btext_setup_display(int width, int height, int depth, int pitch,
boot_text_mapped = 1; boot_text_mapped = 1;
} }
void __init btext_unmap(void)
{
boot_text_mapped = 0;
}
/* Here's a small text engine to use during early boot /* Here's a small text engine to use during early boot
* or for debugging purposes * or for debugging purposes
* *
...@@ -127,7 +135,7 @@ btext_setup_display(int width, int height, int depth, int pitch, ...@@ -127,7 +135,7 @@ btext_setup_display(int width, int height, int depth, int pitch,
* changes. * changes.
*/ */
void map_boot_text(void) static void map_boot_text(void)
{ {
unsigned long base, offset, size; unsigned long base, offset, size;
unsigned char *vbase; unsigned char *vbase;
...@@ -175,8 +183,9 @@ int btext_initialize(struct device_node *np) ...@@ -175,8 +183,9 @@ int btext_initialize(struct device_node *np)
if (prop) if (prop)
address = *prop; address = *prop;
/* FIXME: Add support for PCI reg properties */ /* FIXME: Add support for PCI reg properties. Right now, only
* reliable on macs
*/
if (address == 0) if (address == 0)
return -EINVAL; return -EINVAL;
...@@ -184,7 +193,6 @@ int btext_initialize(struct device_node *np) ...@@ -184,7 +193,6 @@ int btext_initialize(struct device_node *np)
g_loc_Y = 0; g_loc_Y = 0;
g_max_loc_X = width / 8; g_max_loc_X = width / 8;
g_max_loc_Y = height / 16; g_max_loc_Y = height / 16;
logicalDisplayBase = (unsigned char *)address;
dispDeviceBase = (unsigned char *)address; dispDeviceBase = (unsigned char *)address;
dispDeviceRowBytes = pitch; dispDeviceRowBytes = pitch;
dispDeviceDepth = depth; dispDeviceDepth = depth;
...@@ -197,14 +205,12 @@ int btext_initialize(struct device_node *np) ...@@ -197,14 +205,12 @@ int btext_initialize(struct device_node *np)
return 0; return 0;
} }
void __init init_boot_display(void) int __init btext_find_display(int allow_nonstdout)
{ {
char *name; char *name;
struct device_node *np = NULL; struct device_node *np = NULL;
int rc = -ENODEV; int rc = -ENODEV;
printk("trying to initialize btext ...\n");
name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
if (name != NULL) { if (name != NULL) {
np = of_find_node_by_path(name); np = of_find_node_by_path(name);
...@@ -218,8 +224,8 @@ void __init init_boot_display(void) ...@@ -218,8 +224,8 @@ void __init init_boot_display(void)
} }
if (np) if (np)
rc = btext_initialize(np); rc = btext_initialize(np);
if (rc == 0) if (rc == 0 || !allow_nonstdout)
return; return rc;
for (np = NULL; (np = of_find_node_by_type(np, "display"));) { for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
if (get_property(np, "linux,opened", NULL)) { if (get_property(np, "linux,opened", NULL)) {
...@@ -228,8 +234,9 @@ void __init init_boot_display(void) ...@@ -228,8 +234,9 @@ void __init init_boot_display(void)
printk("result: %d\n", rc); printk("result: %d\n", rc);
} }
if (rc == 0) if (rc == 0)
return; break;
} }
return rc;
} }
/* Calc the base address of a given point (x,y) */ /* Calc the base address of a given point (x,y) */
...@@ -277,44 +284,83 @@ EXPORT_SYMBOL(btext_update_display); ...@@ -277,44 +284,83 @@ EXPORT_SYMBOL(btext_update_display);
void btext_clearscreen(void) void btext_clearscreen(void)
{ {
unsigned long *base = (unsigned long *)calc_base(0, 0); unsigned int *base = (unsigned int *)calc_base(0, 0);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 3; (dispDeviceDepth >> 3)) >> 2;
int i,j; int i,j;
for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
{ {
unsigned long *ptr = base; unsigned int *ptr = base;
for(j=width; j; --j) for(j=width; j; --j)
*(ptr++) = 0; *(ptr++) = 0;
base += (dispDeviceRowBytes >> 3); base += (dispDeviceRowBytes >> 2);
} }
} }
void btext_flushscreen(void)
{
unsigned int *base = (unsigned int *)calc_base(0, 0);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 2;
int i,j;
for (i=0; i < (dispDeviceRect[3] - dispDeviceRect[1]); i++)
{
unsigned int *ptr = base;
for(j = width; j > 0; j -= 8) {
__asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
ptr += 8;
}
base += (dispDeviceRowBytes >> 2);
}
__asm__ __volatile__ ("sync" ::: "memory");
}
void btext_flushline(void)
{
unsigned int *base = (unsigned int *)calc_base(0, g_loc_Y << 4);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 2;
int i,j;
for (i=0; i < 16; i++)
{
unsigned int *ptr = base;
for(j = width; j > 0; j -= 8) {
__asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
ptr += 8;
}
base += (dispDeviceRowBytes >> 2);
}
__asm__ __volatile__ ("sync" ::: "memory");
}
#ifndef NO_SCROLL #ifndef NO_SCROLL
static void scrollscreen(void) static void scrollscreen(void)
{ {
unsigned long *src = (unsigned long *)calc_base(0,16); unsigned int *src = (unsigned int *)calc_base(0,16);
unsigned long *dst = (unsigned long *)calc_base(0,0); unsigned int *dst = (unsigned int *)calc_base(0,0);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 3; (dispDeviceDepth >> 3)) >> 2;
int i,j; int i,j;
for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
{ {
unsigned long *src_ptr = src; unsigned int *src_ptr = src;
unsigned long *dst_ptr = dst; unsigned int *dst_ptr = dst;
for(j=width; j; --j) for(j=width; j; --j)
*(dst_ptr++) = *(src_ptr++); *(dst_ptr++) = *(src_ptr++);
src += (dispDeviceRowBytes >> 3); src += (dispDeviceRowBytes >> 2);
dst += (dispDeviceRowBytes >> 3); dst += (dispDeviceRowBytes >> 2);
} }
for (i=0; i<16; i++) for (i=0; i<16; i++)
{ {
unsigned long *dst_ptr = dst; unsigned int *dst_ptr = dst;
for(j=width; j; --j) for(j=width; j; --j)
*(dst_ptr++) = 0; *(dst_ptr++) = 0;
dst += (dispDeviceRowBytes >> 3); dst += (dispDeviceRowBytes >> 2);
} }
} }
#endif /* ndef NO_SCROLL */ #endif /* ndef NO_SCROLL */
...@@ -377,6 +423,14 @@ void btext_drawstring(const char *c) ...@@ -377,6 +423,14 @@ void btext_drawstring(const char *c)
btext_drawchar(*c++); btext_drawchar(*c++);
} }
void btext_drawtext(const char *c, unsigned int len)
{
if (!boot_text_mapped)
return;
while (len--)
btext_drawchar(*c++);
}
void btext_drawhex(unsigned long v) void btext_drawhex(unsigned long v)
{ {
char *hex_table = "0123456789abcdef"; char *hex_table = "0123456789abcdef";
......
...@@ -78,10 +78,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -78,10 +78,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3, .cpu_setup = __setup_cpu_power3,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power3", .oprofile_cpu_type = "ppc64/power3",
.oprofile_model = &op_model_rs64, .oprofile_type = RS64,
#endif
}, },
{ /* Power3+ */ { /* Power3+ */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -93,10 +91,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -93,10 +91,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3, .cpu_setup = __setup_cpu_power3,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power3", .oprofile_cpu_type = "ppc64/power3",
.oprofile_model = &op_model_rs64, .oprofile_type = RS64,
#endif
}, },
{ /* Northstar */ { /* Northstar */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -108,10 +104,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -108,10 +104,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3, .cpu_setup = __setup_cpu_power3,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/rs64", .oprofile_cpu_type = "ppc64/rs64",
.oprofile_model = &op_model_rs64, .oprofile_type = RS64,
#endif
}, },
{ /* Pulsar */ { /* Pulsar */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -123,10 +117,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -123,10 +117,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3, .cpu_setup = __setup_cpu_power3,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/rs64", .oprofile_cpu_type = "ppc64/rs64",
.oprofile_model = &op_model_rs64, .oprofile_type = RS64,
#endif
}, },
{ /* I-star */ { /* I-star */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -138,10 +130,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -138,10 +130,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3, .cpu_setup = __setup_cpu_power3,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/rs64", .oprofile_cpu_type = "ppc64/rs64",
.oprofile_model = &op_model_rs64, .oprofile_type = RS64,
#endif
}, },
{ /* S-star */ { /* S-star */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -153,10 +143,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -153,10 +143,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_power3, .cpu_setup = __setup_cpu_power3,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/rs64", .oprofile_cpu_type = "ppc64/rs64",
.oprofile_model = &op_model_rs64, .oprofile_type = RS64,
#endif
}, },
{ /* Power4 */ { /* Power4 */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -168,10 +156,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -168,10 +156,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_power4, .cpu_setup = __setup_cpu_power4,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power4", .oprofile_cpu_type = "ppc64/power4",
.oprofile_model = &op_model_rs64, .oprofile_type = POWER4,
#endif
}, },
{ /* Power4+ */ { /* Power4+ */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -183,10 +169,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -183,10 +169,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_power4, .cpu_setup = __setup_cpu_power4,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power4", .oprofile_cpu_type = "ppc64/power4",
.oprofile_model = &op_model_power4, .oprofile_type = POWER4,
#endif
}, },
{ /* PPC970 */ { /* PPC970 */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -199,10 +183,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -199,10 +183,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_ppc970, .cpu_setup = __setup_cpu_ppc970,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/970", .oprofile_cpu_type = "ppc64/970",
.oprofile_model = &op_model_power4, .oprofile_type = POWER4,
#endif
}, },
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64 */
#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) #if defined(CONFIG_PPC64) || defined(CONFIG_POWER4)
...@@ -221,10 +203,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -221,10 +203,8 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 8, .num_pmcs = 8,
.cpu_setup = __setup_cpu_ppc970, .cpu_setup = __setup_cpu_ppc970,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/970", .oprofile_cpu_type = "ppc64/970",
.oprofile_model = &op_model_power4, .oprofile_type = POWER4,
#endif
}, },
#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ #endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
...@@ -238,10 +218,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -238,10 +218,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
.cpu_setup = __setup_cpu_ppc970, .cpu_setup = __setup_cpu_ppc970,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/970", .oprofile_cpu_type = "ppc64/970",
.oprofile_model = &op_model_power4, .oprofile_type = POWER4,
#endif
}, },
{ /* Power5 GR */ { /* Power5 GR */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -253,27 +231,23 @@ struct cpu_spec cpu_specs[] = { ...@@ -253,27 +231,23 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_power4, .cpu_setup = __setup_cpu_power4,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power5", .oprofile_cpu_type = "ppc64/power5",
.oprofile_model = &op_model_power4, .oprofile_type = POWER4,
#endif
}, },
{ /* Power5 GS */ { /* Power5 GS */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
.pvr_value = 0x003b0000, .pvr_value = 0x003b0000,
.cpu_name = "POWER5 (gs)", .cpu_name = "POWER5+ (gs)",
.cpu_features = CPU_FTRS_POWER5, .cpu_features = CPU_FTRS_POWER5,
.cpu_user_features = COMMON_USER_POWER5_PLUS, .cpu_user_features = COMMON_USER_POWER5_PLUS,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_power4, .cpu_setup = __setup_cpu_power4,
#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power5+",
.oprofile_cpu_type = "ppc64/power5", .oprofile_type = POWER4,
.oprofile_model = &op_model_power4,
#endif
}, },
{ /* BE DD1.x */ { /* Cell Broadband Engine */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
.pvr_value = 0x00700000, .pvr_value = 0x00700000,
.cpu_name = "Cell Broadband Engine", .cpu_name = "Cell Broadband Engine",
...@@ -545,7 +519,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -545,7 +519,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7450 2.1 */ { /* 7450 2.1 */
.pvr_mask = 0xffffffff, .pvr_mask = 0xffffffff,
...@@ -556,7 +532,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -556,7 +532,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7450 2.3 and newer */ { /* 7450 2.3 and newer */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -567,7 +545,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -567,7 +545,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7455 rev 1.x */ { /* 7455 rev 1.x */
.pvr_mask = 0xffffff00, .pvr_mask = 0xffffff00,
...@@ -578,7 +558,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -578,7 +558,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7455 rev 2.0 */ { /* 7455 rev 2.0 */
.pvr_mask = 0xffffffff, .pvr_mask = 0xffffffff,
...@@ -589,7 +571,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -589,7 +571,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7455 others */ { /* 7455 others */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -600,7 +584,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -600,7 +584,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7447/7457 Rev 1.0 */ { /* 7447/7457 Rev 1.0 */
.pvr_mask = 0xffffffff, .pvr_mask = 0xffffffff,
...@@ -611,7 +597,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -611,7 +597,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7447/7457 Rev 1.1 */ { /* 7447/7457 Rev 1.1 */
.pvr_mask = 0xffffffff, .pvr_mask = 0xffffffff,
...@@ -622,7 +610,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -622,7 +610,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7447/7457 Rev 1.2 and later */ { /* 7447/7457 Rev 1.2 and later */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -633,7 +623,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -633,7 +623,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7447A */ { /* 7447A */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -644,7 +636,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -644,7 +636,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 7448 */ { /* 7448 */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -655,7 +649,9 @@ struct cpu_spec cpu_specs[] = { ...@@ -655,7 +649,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 6, .num_pmcs = 6,
.cpu_setup = __setup_cpu_745x .cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = G4,
}, },
{ /* 82xx (8240, 8245, 8260 are all 603e cores) */ { /* 82xx (8240, 8245, 8260 are all 603e cores) */
.pvr_mask = 0x7fff0000, .pvr_mask = 0x7fff0000,
...@@ -979,6 +975,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -979,6 +975,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 4, .num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
.oprofile_type = BOOKE,
}, },
{ /* e500v2 */ { /* e500v2 */
.pvr_mask = 0xffff0000, .pvr_mask = 0xffff0000,
...@@ -992,6 +990,8 @@ struct cpu_spec cpu_specs[] = { ...@@ -992,6 +990,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 4, .num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
.oprofile_type = BOOKE,
}, },
#endif #endif
#if !CLASSIC_PPC #if !CLASSIC_PPC
......
/*
* Architecture specific (PPC64) functions for kexec based crash dumps.
*
* Copyright (C) 2005, IBM Corp.
*
* Created by: Haren Myneni
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/reboot.h>
#include <linux/kexec.h>
#include <linux/bootmem.h>
#include <linux/crash_dump.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/init.h>
#include <linux/types.h>
#include <asm/processor.h>
#include <asm/machdep.h>
#include <asm/kdump.h>
#include <asm/lmb.h>
#include <asm/firmware.h>
#ifdef DEBUG
#include <asm/udbg.h>
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
/* This keeps a track of which one is crashing cpu. */
int crashing_cpu = -1;
static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
size_t data_len)
{
struct elf_note note;
note.n_namesz = strlen(name) + 1;
note.n_descsz = data_len;
note.n_type = type;
memcpy(buf, &note, sizeof(note));
buf += (sizeof(note) +3)/4;
memcpy(buf, name, note.n_namesz);
buf += (note.n_namesz + 3)/4;
memcpy(buf, data, note.n_descsz);
buf += (note.n_descsz + 3)/4;
return buf;
}
static void final_note(u32 *buf)
{
struct elf_note note;
note.n_namesz = 0;
note.n_descsz = 0;
note.n_type = 0;
memcpy(buf, &note, sizeof(note));
}
static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
{
struct elf_prstatus prstatus;
u32 *buf;
if ((cpu < 0) || (cpu >= NR_CPUS))
return;
/* Using ELF notes here is opportunistic.
* I need a well defined structure format
* for the data I pass, and I need tags
* on the data to indicate what information I have
* squirrelled away. ELF notes happen to provide
* all of that that no need to invent something new.
*/
buf = &crash_notes[cpu][0];
memset(&prstatus, 0, sizeof(prstatus));
prstatus.pr_pid = current->pid;
elf_core_copy_regs(&prstatus.pr_reg, regs);
buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
sizeof(prstatus));
final_note(buf);
}
/* FIXME Merge this with xmon_save_regs ?? */
static inline void crash_get_current_regs(struct pt_regs *regs)
{
unsigned long tmp1, tmp2;
__asm__ __volatile__ (
"std 0,0(%2)\n"
"std 1,8(%2)\n"
"std 2,16(%2)\n"
"std 3,24(%2)\n"
"std 4,32(%2)\n"
"std 5,40(%2)\n"
"std 6,48(%2)\n"
"std 7,56(%2)\n"
"std 8,64(%2)\n"
"std 9,72(%2)\n"
"std 10,80(%2)\n"
"std 11,88(%2)\n"
"std 12,96(%2)\n"
"std 13,104(%2)\n"
"std 14,112(%2)\n"
"std 15,120(%2)\n"
"std 16,128(%2)\n"
"std 17,136(%2)\n"
"std 18,144(%2)\n"
"std 19,152(%2)\n"
"std 20,160(%2)\n"
"std 21,168(%2)\n"
"std 22,176(%2)\n"
"std 23,184(%2)\n"
"std 24,192(%2)\n"
"std 25,200(%2)\n"
"std 26,208(%2)\n"
"std 27,216(%2)\n"
"std 28,224(%2)\n"
"std 29,232(%2)\n"
"std 30,240(%2)\n"
"std 31,248(%2)\n"
"mfmsr %0\n"
"std %0, 264(%2)\n"
"mfctr %0\n"
"std %0, 280(%2)\n"
"mflr %0\n"
"std %0, 288(%2)\n"
"bl 1f\n"
"1: mflr %1\n"
"std %1, 256(%2)\n"
"mtlr %0\n"
"mfxer %0\n"
"std %0, 296(%2)\n"
: "=&r" (tmp1), "=&r" (tmp2)
: "b" (regs));
}
/* We may have saved_regs from where the error came from
* or it is NULL if via a direct panic().
*/
static void crash_save_self(struct pt_regs *saved_regs)
{
struct pt_regs regs;
int cpu;
cpu = smp_processor_id();
if (saved_regs)
memcpy(&regs, saved_regs, sizeof(regs));
else
crash_get_current_regs(&regs);
crash_save_this_cpu(&regs, cpu);
}
#ifdef CONFIG_SMP
static atomic_t waiting_for_crash_ipi;
void crash_ipi_callback(struct pt_regs *regs)
{
int cpu = smp_processor_id();
if (cpu == crashing_cpu)
return;
if (!cpu_online(cpu))
return;
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 1);
local_irq_disable();
crash_save_this_cpu(regs, cpu);
atomic_dec(&waiting_for_crash_ipi);
kexec_smp_wait();
/* NOTREACHED */
}
static void crash_kexec_prepare_cpus(void)
{
unsigned int msecs;
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
crash_send_ipi(crash_ipi_callback);
smp_wmb();
/*
* FIXME: Until we will have the way to stop other CPUSs reliabally,
* the crash CPU will send an IPI and wait for other CPUs to
* respond. If not, proceed the kexec boot even though we failed to
* capture other CPU states.
*/
msecs = 1000000;
while ((atomic_read(&waiting_for_crash_ipi) > 0) && (--msecs > 0)) {
barrier();
mdelay(1);
}
/* Would it be better to replace the trap vector here? */
/*
* FIXME: In case if we do not get all CPUs, one possibility: ask the
* user to do soft reset such that we get all.
* IPI handler is already set by the panic cpu initially. Therefore,
* all cpus could invoke this handler from die() and the panic CPU
* will call machine_kexec() directly from this handler to do
* kexec boot.
*/
if (atomic_read(&waiting_for_crash_ipi))
printk(KERN_ALERT "done waiting: %d cpus not responding\n",
atomic_read(&waiting_for_crash_ipi));
/* Leave the IPI callback set */
}
#else
static void crash_kexec_prepare_cpus(void)
{
/*
* move the secondarys to us so that we can copy
* the new kernel 0-0x100 safely
*
* do this if kexec in setup.c ?
*/
smp_release_cpus();
}
#endif
void default_machine_crash_shutdown(struct pt_regs *regs)
{
/*
* This function is only called after the system
* has paniced or is otherwise in a critical state.
* The minimum amount of code to allow a kexec'd kernel
* to run successfully needs to happen here.
*
* In practice this means stopping other cpus in
* an SMP system.
* The kernel is broken so disable interrupts.
*/
local_irq_disable();
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 0);
/*
* Make a note of crashing cpu. Will be used in machine_kexec
* such that another IPI will not be sent.
*/
crashing_cpu = smp_processor_id();
crash_kexec_prepare_cpus();
crash_save_self(regs);
}
/*
* Routines for doing kexec-based kdump.
*
* Copyright (C) 2005, IBM Corp.
*
* Created by: Michael Ellerman
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
#undef DEBUG
#include <linux/crash_dump.h>
#include <linux/bootmem.h>
#include <asm/kdump.h>
#include <asm/lmb.h>
#include <asm/firmware.h>
#include <asm/uaccess.h>
#ifdef DEBUG
#include <asm/udbg.h>
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
static void __init create_trampoline(unsigned long addr)
{
/* The maximum range of a single instruction branch, is the current
* instruction's address + (32 MB - 4) bytes. For the trampoline we
* need to branch to current address + 32 MB. So we insert a nop at
* the trampoline address, then the next instruction (+ 4 bytes)
* does a branch to (32 MB - 4). The net effect is that when we
* branch to "addr" we jump to ("addr" + 32 MB). Although it requires
* two instructions it doesn't require any registers.
*/
create_instruction(addr, 0x60000000); /* nop */
create_branch(addr + 4, addr + PHYSICAL_START, 0);
}
void __init kdump_setup(void)
{
unsigned long i;
DBG(" -> kdump_setup()\n");
for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
create_trampoline(i);
}
create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
DBG(" <- kdump_setup()\n");
}
static int __init parse_elfcorehdr(char *p)
{
if (p)
elfcorehdr_addr = memparse(p, &p);
return 0;
}
__setup("elfcorehdr=", parse_elfcorehdr);
static int __init parse_savemaxmem(char *p)
{
if (p)
saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
return 0;
}
__setup("savemaxmem=", parse_savemaxmem);
/*
* copy_oldmem_page - copy one page from "oldmem"
* @pfn: page frame number to be copied
* @buf: target memory address for the copy; this can be in kernel address
* space or user address space (see @userbuf)
* @csize: number of bytes to copy
* @offset: offset in bytes into the page (based on pfn) to begin the copy
* @userbuf: if set, @buf is in user address space, use copy_to_user(),
* otherwise @buf is in kernel address space, use memcpy().
*
* Copy a page from "oldmem". For this page, there is no pte mapped
* in the current kernel. We stitch up a pte, similar to kmap_atomic.
*/
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
size_t csize, unsigned long offset, int userbuf)
{
void *vaddr;
if (!csize)
return 0;
vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0);
if (userbuf) {
if (copy_to_user((char __user *)buf, (vaddr + offset), csize)) {
iounmap(vaddr);
return -EFAULT;
}
} else
memcpy(buf, (vaddr + offset), csize);
iounmap(vaddr);
return csize;
}
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
/* Include the busses we support */ /* Include the busses we support */
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/vio.h> #include <asm/vio.h>
#include <asm/ibmebus.h>
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
#include <asm/bug.h> #include <asm/bug.h>
...@@ -22,6 +23,10 @@ static struct dma_mapping_ops *get_dma_ops(struct device *dev) ...@@ -22,6 +23,10 @@ static struct dma_mapping_ops *get_dma_ops(struct device *dev)
#ifdef CONFIG_IBMVIO #ifdef CONFIG_IBMVIO
if (dev->bus == &vio_bus_type) if (dev->bus == &vio_bus_type)
return &vio_dma_ops; return &vio_dma_ops;
#endif
#ifdef CONFIG_IBMEBUS
if (dev->bus == &ibmebus_bus_type)
return &ibmebus_dma_ops;
#endif #endif
return NULL; return NULL;
} }
...@@ -47,6 +52,10 @@ int dma_set_mask(struct device *dev, u64 dma_mask) ...@@ -47,6 +52,10 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
if (dev->bus == &vio_bus_type) if (dev->bus == &vio_bus_type)
return -EIO; return -EIO;
#endif /* CONFIG_IBMVIO */ #endif /* CONFIG_IBMVIO */
#ifdef CONFIG_IBMEBUS
if (dev->bus == &ibmebus_bus_type)
return -EIO;
#endif
BUG(); BUG();
return 0; return 0;
} }
......
...@@ -200,8 +200,6 @@ _GLOBAL(DoSyscall) ...@@ -200,8 +200,6 @@ _GLOBAL(DoSyscall)
bl do_show_syscall bl do_show_syscall
#endif /* SHOW_SYSCALLS */ #endif /* SHOW_SYSCALLS */
rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
li r11,0
stb r11,TI_SC_NOERR(r10)
lwz r11,TI_FLAGS(r10) lwz r11,TI_FLAGS(r10)
andi. r11,r11,_TIF_SYSCALL_T_OR_A andi. r11,r11,_TIF_SYSCALL_T_OR_A
bne- syscall_dotrace bne- syscall_dotrace
...@@ -222,25 +220,21 @@ ret_from_syscall: ...@@ -222,25 +220,21 @@ ret_from_syscall:
bl do_show_syscall_exit bl do_show_syscall_exit
#endif #endif
mr r6,r3 mr r6,r3
li r11,-_LAST_ERRNO
cmplw 0,r3,r11
rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
blt+ 30f
lbz r11,TI_SC_NOERR(r12)
cmpwi r11,0
bne 30f
neg r3,r3
lwz r10,_CCR(r1) /* Set SO bit in CR */
oris r10,r10,0x1000
stw r10,_CCR(r1)
/* disable interrupts so current_thread_info()->flags can't change */ /* disable interrupts so current_thread_info()->flags can't change */
30: LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
SYNC SYNC
MTMSRD(r10) MTMSRD(r10)
lwz r9,TI_FLAGS(r12) lwz r9,TI_FLAGS(r12)
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED) li r8,-_LAST_ERRNO
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
bne- syscall_exit_work bne- syscall_exit_work
cmplw 0,r3,r8
blt+ syscall_exit_cont
lwz r11,_CCR(r1) /* Load CR */
neg r3,r3
oris r11,r11,0x1000 /* Set SO bit in CR */
stw r11,_CCR(r1)
syscall_exit_cont: syscall_exit_cont:
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
/* If the process has its own DBCR0 value, load it up. The single /* If the process has its own DBCR0 value, load it up. The single
...@@ -292,46 +286,113 @@ syscall_dotrace: ...@@ -292,46 +286,113 @@ syscall_dotrace:
b syscall_dotrace_cont b syscall_dotrace_cont
syscall_exit_work: syscall_exit_work:
stw r6,RESULT(r1) /* Save result */ andi. r0,r9,_TIF_RESTOREALL
bne- 2f
cmplw 0,r3,r8
blt+ 1f
andi. r0,r9,_TIF_NOERROR
bne- 1f
lwz r11,_CCR(r1) /* Load CR */
neg r3,r3
oris r11,r11,0x1000 /* Set SO bit in CR */
stw r11,_CCR(r1)
1: stw r6,RESULT(r1) /* Save result */
stw r3,GPR3(r1) /* Update return value */ stw r3,GPR3(r1) /* Update return value */
andi. r0,r9,_TIF_SYSCALL_T_OR_A 2: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
beq 5f beq 4f
ori r10,r10,MSR_EE
SYNC /* Clear per-syscall TIF flags if any are set, but _leave_
MTMSRD(r10) /* re-enable interrupts */ _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that
yet. */
li r11,_TIF_PERSYSCALL_MASK
addi r12,r12,TI_FLAGS
3: lwarx r8,0,r12
andc r8,r8,r11
#ifdef CONFIG_IBM405_ERR77
dcbt 0,r12
#endif
stwcx. r8,0,r12
bne- 3b
subi r12,r12,TI_FLAGS
4: /* Anything which requires enabling interrupts? */
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS)
beq 7f
/* Save NVGPRS if they're not saved already */
lwz r4,_TRAP(r1) lwz r4,_TRAP(r1)
andi. r4,r4,1 andi. r4,r4,1
beq 4f beq 5f
SAVE_NVGPRS(r1) SAVE_NVGPRS(r1)
li r4,0xc00 li r4,0xc00
stw r4,_TRAP(r1) stw r4,_TRAP(r1)
4:
/* Re-enable interrupts */
5: ori r10,r10,MSR_EE
SYNC
MTMSRD(r10)
andi. r0,r9,_TIF_SAVE_NVGPRS
bne save_user_nvgprs
save_user_nvgprs_cont:
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
beq 7f
addi r3,r1,STACK_FRAME_OVERHEAD addi r3,r1,STACK_FRAME_OVERHEAD
bl do_syscall_trace_leave bl do_syscall_trace_leave
REST_NVGPRS(r1) REST_NVGPRS(r1)
2:
lwz r3,GPR3(r1) 6: lwz r3,GPR3(r1)
LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
SYNC SYNC
MTMSRD(r10) /* disable interrupts again */ MTMSRD(r10) /* disable interrupts again */
rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
lwz r9,TI_FLAGS(r12) lwz r9,TI_FLAGS(r12)
5: 7:
andi. r0,r9,_TIF_NEED_RESCHED andi. r0,r9,_TIF_NEED_RESCHED
bne 1f bne 8f
lwz r5,_MSR(r1) lwz r5,_MSR(r1)
andi. r5,r5,MSR_PR andi. r5,r5,MSR_PR
beq syscall_exit_cont beq ret_from_except
andi. r0,r9,_TIF_SIGPENDING andi. r0,r9,_TIF_SIGPENDING
beq syscall_exit_cont beq ret_from_except
b do_user_signal b do_user_signal
1: 8:
ori r10,r10,MSR_EE ori r10,r10,MSR_EE
SYNC SYNC
MTMSRD(r10) /* re-enable interrupts */ MTMSRD(r10) /* re-enable interrupts */
bl schedule bl schedule
b 2b b 6b
save_user_nvgprs:
lwz r8,TI_SIGFRAME(r12)
.macro savewords start, end
1: stw \start,4*(\start)(r8)
.section __ex_table,"a"
.align 2
.long 1b,save_user_nvgprs_fault
.previous
.if \end - \start
savewords "(\start+1)",\end
.endif
.endm
savewords 14,31
b save_user_nvgprs_cont
save_user_nvgprs_fault:
li r3,11 /* SIGSEGV */
lwz r4,TI_TASK(r12)
bl force_sigsegv
rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
lwz r9,TI_FLAGS(r12)
b save_user_nvgprs_cont
#ifdef SHOW_SYSCALLS #ifdef SHOW_SYSCALLS
do_show_syscall: do_show_syscall:
#ifdef SHOW_SYSCALLS_TASK #ifdef SHOW_SYSCALLS_TASK
...@@ -401,28 +462,10 @@ show_syscalls_task: ...@@ -401,28 +462,10 @@ show_syscalls_task:
#endif /* SHOW_SYSCALLS */ #endif /* SHOW_SYSCALLS */
/* /*
* The sigsuspend and rt_sigsuspend system calls can call do_signal * The fork/clone functions need to copy the full register set into
* and thus put the process into the stopped state where we might * the child process. Therefore we need to save all the nonvolatile
* want to examine its user state with ptrace. Therefore we need * registers (r13 - r31) before calling the C code.
* to save all the nonvolatile registers (r13 - r31) before calling
* the C code.
*/ */
.globl ppc_sigsuspend
ppc_sigsuspend:
SAVE_NVGPRS(r1)
lwz r0,_TRAP(r1)
rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
stw r0,_TRAP(r1) /* register set saved */
b sys_sigsuspend
.globl ppc_rt_sigsuspend
ppc_rt_sigsuspend:
SAVE_NVGPRS(r1)
lwz r0,_TRAP(r1)
rlwinm r0,r0,0,0,30
stw r0,_TRAP(r1)
b sys_rt_sigsuspend
.globl ppc_fork .globl ppc_fork
ppc_fork: ppc_fork:
SAVE_NVGPRS(r1) SAVE_NVGPRS(r1)
...@@ -447,14 +490,6 @@ ppc_clone: ...@@ -447,14 +490,6 @@ ppc_clone:
stw r0,_TRAP(r1) /* register set saved */ stw r0,_TRAP(r1) /* register set saved */
b sys_clone b sys_clone
.globl ppc_swapcontext
ppc_swapcontext:
SAVE_NVGPRS(r1)
lwz r0,_TRAP(r1)
rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
stw r0,_TRAP(r1) /* register set saved */
b sys_swapcontext
/* /*
* Top-level page fault handling. * Top-level page fault handling.
* This is in assembler because if do_page_fault tells us that * This is in assembler because if do_page_fault tells us that
...@@ -626,16 +661,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) ...@@ -626,16 +661,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
.long ret_from_except .long ret_from_except
#endif #endif
.globl sigreturn_exit
sigreturn_exit:
subi r1,r3,STACK_FRAME_OVERHEAD
rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
lwz r9,TI_FLAGS(r12)
andi. r0,r9,_TIF_SYSCALL_T_OR_A
beq+ ret_from_except_full
bl do_syscall_trace_leave
/* fall through */
.globl ret_from_except_full .globl ret_from_except_full
ret_from_except_full: ret_from_except_full:
REST_NVGPRS(r1) REST_NVGPRS(r1)
...@@ -658,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */ ...@@ -658,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
/* Check current_thread_info()->flags */ /* Check current_thread_info()->flags */
rlwinm r9,r1,0,0,(31-THREAD_SHIFT) rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
lwz r9,TI_FLAGS(r9) lwz r9,TI_FLAGS(r9)
andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED) andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
bne do_work bne do_work
restore_user: restore_user:
......
...@@ -113,9 +113,7 @@ system_call_common: ...@@ -113,9 +113,7 @@ system_call_common:
addi r9,r1,STACK_FRAME_OVERHEAD addi r9,r1,STACK_FRAME_OVERHEAD
#endif #endif
clrrdi r11,r1,THREAD_SHIFT clrrdi r11,r1,THREAD_SHIFT
li r12,0
ld r10,TI_FLAGS(r11) ld r10,TI_FLAGS(r11)
stb r12,TI_SC_NOERR(r11)
andi. r11,r10,_TIF_SYSCALL_T_OR_A andi. r11,r10,_TIF_SYSCALL_T_OR_A
bne- syscall_dotrace bne- syscall_dotrace
syscall_dotrace_cont: syscall_dotrace_cont:
...@@ -144,24 +142,12 @@ system_call: /* label this so stack traces look sane */ ...@@ -144,24 +142,12 @@ system_call: /* label this so stack traces look sane */
bctrl /* Call handler */ bctrl /* Call handler */
syscall_exit: syscall_exit:
std r3,RESULT(r1)
#ifdef SHOW_SYSCALLS #ifdef SHOW_SYSCALLS
std r3,GPR3(r1)
bl .do_show_syscall_exit bl .do_show_syscall_exit
ld r3,GPR3(r1) ld r3,RESULT(r1)
#endif #endif
std r3,RESULT(r1)
ld r5,_CCR(r1)
li r10,-_LAST_ERRNO
cmpld r3,r10
clrrdi r12,r1,THREAD_SHIFT clrrdi r12,r1,THREAD_SHIFT
bge- syscall_error
syscall_error_cont:
/* check for syscall tracing or audit */
ld r9,TI_FLAGS(r12)
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
bne- syscall_exit_trace
syscall_exit_trace_cont:
/* disable interrupts so current_thread_info()->flags can't change, /* disable interrupts so current_thread_info()->flags can't change,
and so that we don't get interrupted after loading SRR0/1. */ and so that we don't get interrupted after loading SRR0/1. */
...@@ -173,8 +159,13 @@ syscall_exit_trace_cont: ...@@ -173,8 +159,13 @@ syscall_exit_trace_cont:
rotldi r10,r10,16 rotldi r10,r10,16
mtmsrd r10,1 mtmsrd r10,1
ld r9,TI_FLAGS(r12) ld r9,TI_FLAGS(r12)
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED) li r11,-_LAST_ERRNO
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR)
bne- syscall_exit_work bne- syscall_exit_work
cmpld r3,r11
ld r5,_CCR(r1)
bge- syscall_error
syscall_error_cont:
ld r7,_NIP(r1) ld r7,_NIP(r1)
stdcx. r0,0,r1 /* to clear the reservation */ stdcx. r0,0,r1 /* to clear the reservation */
andi. r6,r8,MSR_PR andi. r6,r8,MSR_PR
...@@ -193,21 +184,12 @@ syscall_exit_trace_cont: ...@@ -193,21 +184,12 @@ syscall_exit_trace_cont:
rfid rfid
b . /* prevent speculative execution */ b . /* prevent speculative execution */
syscall_enosys: syscall_error:
li r3,-ENOSYS
std r3,RESULT(r1)
clrrdi r12,r1,THREAD_SHIFT
ld r5,_CCR(r1)
syscall_error:
lbz r11,TI_SC_NOERR(r12)
cmpwi 0,r11,0
bne- syscall_error_cont
neg r3,r3
oris r5,r5,0x1000 /* Set SO bit in CR */ oris r5,r5,0x1000 /* Set SO bit in CR */
neg r3,r3
std r5,_CCR(r1) std r5,_CCR(r1)
b syscall_error_cont b syscall_error_cont
/* Traced system call support */ /* Traced system call support */
syscall_dotrace: syscall_dotrace:
bl .save_nvgprs bl .save_nvgprs
...@@ -225,21 +207,69 @@ syscall_dotrace: ...@@ -225,21 +207,69 @@ syscall_dotrace:
ld r10,TI_FLAGS(r10) ld r10,TI_FLAGS(r10)
b syscall_dotrace_cont b syscall_dotrace_cont
syscall_exit_trace: syscall_enosys:
std r3,GPR3(r1) li r3,-ENOSYS
bl .save_nvgprs b syscall_exit
syscall_exit_work:
/* If TIF_RESTOREALL is set, don't scribble on either r3 or ccr.
If TIF_NOERROR is set, just save r3 as it is. */
andi. r0,r9,_TIF_RESTOREALL
bne- 2f
cmpld r3,r11 /* r10 is -LAST_ERRNO */
blt+ 1f
andi. r0,r9,_TIF_NOERROR
bne- 1f
ld r5,_CCR(r1)
neg r3,r3
oris r5,r5,0x1000 /* Set SO bit in CR */
std r5,_CCR(r1)
1: std r3,GPR3(r1)
2: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
beq 4f
/* Clear per-syscall TIF flags if any are set, but _leave_
_TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that
yet. */
li r11,_TIF_PERSYSCALL_MASK
addi r12,r12,TI_FLAGS
3: ldarx r10,0,r12
andc r10,r10,r11
stdcx. r10,0,r12
bne- 3b
subi r12,r12,TI_FLAGS
4: bl .save_nvgprs
/* Anything else left to do? */
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS)
beq .ret_from_except_lite
/* Re-enable interrupts */
mfmsr r10
ori r10,r10,MSR_EE
mtmsrd r10,1
andi. r0,r9,_TIF_SAVE_NVGPRS
bne save_user_nvgprs
/* If tracing, re-enable interrupts and do it */
save_user_nvgprs_cont:
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
beq 5f
addi r3,r1,STACK_FRAME_OVERHEAD addi r3,r1,STACK_FRAME_OVERHEAD
bl .do_syscall_trace_leave bl .do_syscall_trace_leave
REST_NVGPRS(r1) REST_NVGPRS(r1)
ld r3,GPR3(r1)
ld r5,_CCR(r1)
clrrdi r12,r1,THREAD_SHIFT clrrdi r12,r1,THREAD_SHIFT
b syscall_exit_trace_cont
/* Stuff to do on exit from a system call. */ /* Disable interrupts again and handle other work if any */
syscall_exit_work: 5: mfmsr r10
std r3,GPR3(r1) rldicl r10,r10,48,1
std r5,_CCR(r1) rotldi r10,r10,16
mtmsrd r10,1
b .ret_from_except_lite b .ret_from_except_lite
/* Save non-volatile GPRs, if not already saved. */ /* Save non-volatile GPRs, if not already saved. */
...@@ -252,6 +282,52 @@ _GLOBAL(save_nvgprs) ...@@ -252,6 +282,52 @@ _GLOBAL(save_nvgprs)
std r0,_TRAP(r1) std r0,_TRAP(r1)
blr blr
save_user_nvgprs:
ld r10,TI_SIGFRAME(r12)
andi. r0,r9,_TIF_32BIT
beq- save_user_nvgprs_64
/* 32-bit save to userspace */
.macro savewords start, end
1: stw \start,4*(\start)(r10)
.section __ex_table,"a"
.align 3
.llong 1b,save_user_nvgprs_fault
.previous
.if \end - \start
savewords "(\start+1)",\end
.endif
.endm
savewords 14,31
b save_user_nvgprs_cont
save_user_nvgprs_64:
/* 64-bit save to userspace */
.macro savelongs start, end
1: std \start,8*(\start)(r10)
.section __ex_table,"a"
.align 3
.llong 1b,save_user_nvgprs_fault
.previous
.if \end - \start
savelongs "(\start+1)",\end
.endif
.endm
savelongs 14,31
b save_user_nvgprs_cont
save_user_nvgprs_fault:
li r3,11 /* SIGSEGV */
ld r4,TI_TASK(r12)
bl .force_sigsegv
clrrdi r12,r1,THREAD_SHIFT
ld r9,TI_FLAGS(r12)
b save_user_nvgprs_cont
/* /*
* The sigsuspend and rt_sigsuspend system calls can call do_signal * The sigsuspend and rt_sigsuspend system calls can call do_signal
* and thus put the process into the stopped state where we might * and thus put the process into the stopped state where we might
...@@ -260,35 +336,6 @@ _GLOBAL(save_nvgprs) ...@@ -260,35 +336,6 @@ _GLOBAL(save_nvgprs)
* the C code. Similarly, fork, vfork and clone need the full * the C code. Similarly, fork, vfork and clone need the full
* register state on the stack so that it can be copied to the child. * register state on the stack so that it can be copied to the child.
*/ */
_GLOBAL(ppc32_sigsuspend)
bl .save_nvgprs
bl .compat_sys_sigsuspend
b 70f
_GLOBAL(ppc64_rt_sigsuspend)
bl .save_nvgprs
bl .sys_rt_sigsuspend
b 70f
_GLOBAL(ppc32_rt_sigsuspend)
bl .save_nvgprs
bl .compat_sys_rt_sigsuspend
70: cmpdi 0,r3,0
/* If it returned an error, we need to return via syscall_exit to set
the SO bit in cr0 and potentially stop for ptrace. */
bne syscall_exit
/* If sigsuspend() returns zero, we are going into a signal handler. We
may need to call audit_syscall_exit() to mark the exit from sigsuspend() */
#ifdef CONFIG_AUDITSYSCALL
ld r3,PACACURRENT(r13)
ld r4,AUDITCONTEXT(r3)
cmpdi 0,r4,0
beq .ret_from_except /* No audit_context: Leave immediately. */
li r4, 2 /* AUDITSC_FAILURE */
li r5,-4 /* It's always -EINTR */
bl .audit_syscall_exit
#endif
b .ret_from_except
_GLOBAL(ppc_fork) _GLOBAL(ppc_fork)
bl .save_nvgprs bl .save_nvgprs
...@@ -305,37 +352,6 @@ _GLOBAL(ppc_clone) ...@@ -305,37 +352,6 @@ _GLOBAL(ppc_clone)
bl .sys_clone bl .sys_clone
b syscall_exit b syscall_exit
_GLOBAL(ppc32_swapcontext)
bl .save_nvgprs
bl .compat_sys_swapcontext
b 80f
_GLOBAL(ppc64_swapcontext)
bl .save_nvgprs
bl .sys_swapcontext
b 80f
_GLOBAL(ppc32_sigreturn)
bl .compat_sys_sigreturn
b 80f
_GLOBAL(ppc32_rt_sigreturn)
bl .compat_sys_rt_sigreturn
b 80f
_GLOBAL(ppc64_rt_sigreturn)
bl .sys_rt_sigreturn
80: cmpdi 0,r3,0
blt syscall_exit
clrrdi r4,r1,THREAD_SHIFT
ld r4,TI_FLAGS(r4)
andi. r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
beq+ 81f
addi r3,r1,STACK_FRAME_OVERHEAD
bl .do_syscall_trace_leave
81: b .ret_from_except
_GLOBAL(ret_from_fork) _GLOBAL(ret_from_fork)
bl .schedule_tail bl .schedule_tail
REST_NVGPRS(r1) REST_NVGPRS(r1)
...@@ -674,7 +690,7 @@ _GLOBAL(enter_rtas) ...@@ -674,7 +690,7 @@ _GLOBAL(enter_rtas)
/* Setup our real return addr */ /* Setup our real return addr */
SET_REG_TO_LABEL(r4,.rtas_return_loc) SET_REG_TO_LABEL(r4,.rtas_return_loc)
SET_REG_TO_CONST(r9,KERNELBASE) SET_REG_TO_CONST(r9,PAGE_OFFSET)
sub r4,r4,r9 sub r4,r4,r9
mtlr r4 mtlr r4
...@@ -702,7 +718,7 @@ _GLOBAL(enter_rtas) ...@@ -702,7 +718,7 @@ _GLOBAL(enter_rtas)
_STATIC(rtas_return_loc) _STATIC(rtas_return_loc)
/* relocation is off at this point */ /* relocation is off at this point */
mfspr r4,SPRN_SPRG3 /* Get PACA */ mfspr r4,SPRN_SPRG3 /* Get PACA */
SET_REG_TO_CONST(r5, KERNELBASE) SET_REG_TO_CONST(r5, PAGE_OFFSET)
sub r4,r4,r5 /* RELOC the PACA base pointer */ sub r4,r4,r5 /* RELOC the PACA base pointer */
mfmsr r6 mfmsr r6
......
...@@ -120,10 +120,25 @@ __start: ...@@ -120,10 +120,25 @@ __start:
* because OF may have I/O devices mapped into that area * because OF may have I/O devices mapped into that area
* (particularly on CHRP). * (particularly on CHRP).
*/ */
#ifdef CONFIG_PPC_MULTIPLATFORM
cmpwi 0,r5,0 cmpwi 0,r5,0
beq 1f beq 1f
bl prom_init bl prom_init
trap trap
#endif
/*
* Check for BootX signature when supporting PowerMac and branch to
* appropriate trampoline if it's present
*/
#ifdef CONFIG_PPC_PMAC
1: lis r31,0x426f
ori r31,r31,0x6f58
cmpw 0,r3,r31
bne 1f
bl bootx_init
trap
#endif /* CONFIG_PPC_PMAC */
1: mr r31,r3 /* save parameters */ 1: mr r31,r3 /* save parameters */
mr r30,r4 mr r30,r4
...@@ -153,6 +168,9 @@ __after_mmu_off: ...@@ -153,6 +168,9 @@ __after_mmu_off:
bl flush_tlbs bl flush_tlbs
bl initial_bats bl initial_bats
#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
bl setup_disp_bat
#endif
/* /*
* Call setup_cpu for CPU 0 and initialize 6xx Idle * Call setup_cpu for CPU 0 and initialize 6xx Idle
...@@ -450,16 +468,11 @@ SystemCall: ...@@ -450,16 +468,11 @@ SystemCall:
* by executing an altivec instruction. * by executing an altivec instruction.
*/ */
. = 0xf00 . = 0xf00
b Trap_0f b PerformanceMonitor
. = 0xf20 . = 0xf20
b AltiVecUnavailable b AltiVecUnavailable
Trap_0f:
EXCEPTION_PROLOG
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_EE(0xf00, unknown_exception)
/* /*
* Handle TLB miss for instruction on 603/603e. * Handle TLB miss for instruction on 603/603e.
* Note: we get an alternate set of r0 - r3 to use automatically. * Note: we get an alternate set of r0 - r3 to use automatically.
...@@ -703,6 +716,11 @@ AltiVecUnavailable: ...@@ -703,6 +716,11 @@ AltiVecUnavailable:
#endif /* CONFIG_ALTIVEC */ #endif /* CONFIG_ALTIVEC */
EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception) EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
PerformanceMonitor:
EXCEPTION_PROLOG
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_STD(0xf00, performance_monitor_exception)
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
/* Note that the AltiVec support is closely modeled after the FP /* Note that the AltiVec support is closely modeled after the FP
* support. Changes to one are likely to be applicable to the * support. Changes to one are likely to be applicable to the
...@@ -1306,6 +1324,32 @@ initial_bats: ...@@ -1306,6 +1324,32 @@ initial_bats:
blr blr
#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
setup_disp_bat:
/*
* setup the display bat prepared for us in prom.c
*/
mflr r8
bl reloc_offset
mtlr r8
addis r8,r3,disp_BAT@ha
addi r8,r8,disp_BAT@l
cmpwi cr0,r8,0
beqlr
lwz r11,0(r8)
lwz r8,4(r8)
mfspr r9,SPRN_PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpwi 0,r9,1
beq 1f
mtspr SPRN_DBAT3L,r8
mtspr SPRN_DBAT3U,r11
blr
1: mtspr SPRN_IBAT3L,r8
mtspr SPRN_IBAT3U,r11
blr
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
#ifdef CONFIG_8260 #ifdef CONFIG_8260
/* Jump into the system reset for the rom. /* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address. * We first disable the MMU, and then jump to the ROM reset address.
......
...@@ -154,11 +154,15 @@ _GLOBAL(__secondary_hold) ...@@ -154,11 +154,15 @@ _GLOBAL(__secondary_hold)
bne 100b bne 100b
#ifdef CONFIG_HMT #ifdef CONFIG_HMT
b .hmt_init LOADADDR(r4, .hmt_init)
mtctr r4
bctr
#else #else
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
LOADADDR(r4, .pSeries_secondary_smp_init)
mtctr r4
mr r3,r24 mr r3,r24
b .pSeries_secondary_smp_init bctr
#else #else
BUG_OPCODE BUG_OPCODE
#endif #endif
...@@ -200,6 +204,20 @@ exception_marker: ...@@ -200,6 +204,20 @@ exception_marker:
#define EX_R3 64 #define EX_R3 64
#define EX_LR 72 #define EX_LR 72
/*
* We're short on space and time in the exception prolog, so we can't use
* the normal LOADADDR macro. Normally we just need the low halfword of the
* address, but for Kdump we need the whole low word.
*/
#ifdef CONFIG_CRASH_DUMP
#define LOAD_HANDLER(reg, label) \
oris reg,reg,(label)@h; /* virt addr of handler ... */ \
ori reg,reg,(label)@l; /* .. and the rest */
#else
#define LOAD_HANDLER(reg, label) \
ori reg,reg,(label)@l; /* virt addr of handler ... */
#endif
#define EXCEPTION_PROLOG_PSERIES(area, label) \ #define EXCEPTION_PROLOG_PSERIES(area, label) \
mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
std r9,area+EX_R9(r13); /* save r9 - r12 */ \ std r9,area+EX_R9(r13); /* save r9 - r12 */ \
...@@ -212,7 +230,7 @@ exception_marker: ...@@ -212,7 +230,7 @@ exception_marker:
clrrdi r12,r13,32; /* get high part of &label */ \ clrrdi r12,r13,32; /* get high part of &label */ \
mfmsr r10; \ mfmsr r10; \
mfspr r11,SPRN_SRR0; /* save SRR0 */ \ mfspr r11,SPRN_SRR0; /* save SRR0 */ \
ori r12,r12,(label)@l; /* virt addr of handler */ \ LOAD_HANDLER(r12,label) \
ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
mtspr SPRN_SRR0,r12; \ mtspr SPRN_SRR0,r12; \
mfspr r12,SPRN_SRR1; /* and SRR1 */ \ mfspr r12,SPRN_SRR1; /* and SRR1 */ \
...@@ -553,6 +571,7 @@ slb_miss_user_pseries: ...@@ -553,6 +571,7 @@ slb_miss_user_pseries:
* Vectors for the FWNMI option. Share common code. * Vectors for the FWNMI option. Share common code.
*/ */
.globl system_reset_fwnmi .globl system_reset_fwnmi
.align 7
system_reset_fwnmi: system_reset_fwnmi:
HMT_MEDIUM HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */ mtspr SPRN_SPRG1,r13 /* save r13 */
...@@ -560,6 +579,7 @@ system_reset_fwnmi: ...@@ -560,6 +579,7 @@ system_reset_fwnmi:
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
.globl machine_check_fwnmi .globl machine_check_fwnmi
.align 7
machine_check_fwnmi: machine_check_fwnmi:
HMT_MEDIUM HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */ mtspr SPRN_SPRG1,r13 /* save r13 */
...@@ -726,7 +746,8 @@ iSeries_secondary_smp_loop: ...@@ -726,7 +746,8 @@ iSeries_secondary_smp_loop:
decrementer_iSeries_masked: decrementer_iSeries_masked:
li r11,1 li r11,1
stb r11,PACALPPACA+LPPACADECRINT(r13) stb r11,PACALPPACA+LPPACADECRINT(r13)
lwz r12,PACADEFAULTDECR(r13) LOADBASE(r12,tb_ticks_per_jiffy)
lwz r12,OFF(tb_ticks_per_jiffy)(r12)
mtspr SPRN_DEC,r12 mtspr SPRN_DEC,r12
/* fall through */ /* fall through */
...@@ -1345,7 +1366,7 @@ _GLOBAL(do_stab_bolted) ...@@ -1345,7 +1366,7 @@ _GLOBAL(do_stab_bolted)
* fixed address (the linker can't compute (u64)&initial_stab >> * fixed address (the linker can't compute (u64)&initial_stab >>
* PAGE_SHIFT). * PAGE_SHIFT).
*/ */
. = STAB0_PHYS_ADDR /* 0x6000 */ . = STAB0_OFFSET /* 0x6000 */
.globl initial_stab .globl initial_stab
initial_stab: initial_stab:
.space 4096 .space 4096
...@@ -1485,11 +1506,13 @@ _STATIC(__mmu_off) ...@@ -1485,11 +1506,13 @@ _STATIC(__mmu_off)
* *
*/ */
_GLOBAL(__start_initialization_multiplatform) _GLOBAL(__start_initialization_multiplatform)
#ifdef CONFIG_PPC_MULTIPLATFORM
/* /*
* Are we booted from a PROM Of-type client-interface ? * Are we booted from a PROM Of-type client-interface ?
*/ */
cmpldi cr0,r5,0 cmpldi cr0,r5,0
bne .__boot_from_prom /* yes -> prom */ bne .__boot_from_prom /* yes -> prom */
#endif
/* Save parameters */ /* Save parameters */
mr r31,r3 mr r31,r3
...@@ -1510,6 +1533,7 @@ _GLOBAL(__start_initialization_multiplatform) ...@@ -1510,6 +1533,7 @@ _GLOBAL(__start_initialization_multiplatform)
bl .__mmu_off bl .__mmu_off
b .__after_prom_start b .__after_prom_start
#ifdef CONFIG_PPC_MULTIPLATFORM
_STATIC(__boot_from_prom) _STATIC(__boot_from_prom)
/* Save parameters */ /* Save parameters */
mr r31,r3 mr r31,r3
...@@ -1542,6 +1566,7 @@ _STATIC(__boot_from_prom) ...@@ -1542,6 +1566,7 @@ _STATIC(__boot_from_prom)
bl .prom_init bl .prom_init
/* We never return */ /* We never return */
trap trap
#endif
/* /*
* At this point, r3 contains the physical address we are running at, * At this point, r3 contains the physical address we are running at,
...@@ -1550,7 +1575,7 @@ _STATIC(__boot_from_prom) ...@@ -1550,7 +1575,7 @@ _STATIC(__boot_from_prom)
_STATIC(__after_prom_start) _STATIC(__after_prom_start)
/* /*
* We need to run with __start at physical address 0. * We need to run with __start at physical address PHYSICAL_START.
* This will leave some code in the first 256B of * This will leave some code in the first 256B of
* real memory, which are reserved for software use. * real memory, which are reserved for software use.
* The remainder of the first page is loaded with the fixed * The remainder of the first page is loaded with the fixed
...@@ -1565,7 +1590,7 @@ _STATIC(__after_prom_start) ...@@ -1565,7 +1590,7 @@ _STATIC(__after_prom_start)
mr r26,r3 mr r26,r3
SET_REG_TO_CONST(r27,KERNELBASE) SET_REG_TO_CONST(r27,KERNELBASE)
li r3,0 /* target addr */ LOADADDR(r3, PHYSICAL_START) /* target addr */
// XXX FIXME: Use phys returned by OF (r30) // XXX FIXME: Use phys returned by OF (r30)
add r4,r27,r26 /* source addr */ add r4,r27,r26 /* source addr */
...@@ -1846,7 +1871,7 @@ _STATIC(start_here_multiplatform) ...@@ -1846,7 +1871,7 @@ _STATIC(start_here_multiplatform)
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. */
add r13,r13,r26 /* convert to physical addr */ add r13,r13,r26 /* convert to physical addr */
mtspr SPRN_SPRG3,r13 /* PPPBBB: Temp... -Peter */ mtspr SPRN_SPRG3,r13
/* Do very early kernel initializations, including initial hash table, /* Do very early kernel initializations, including initial hash table,
* stab and slb setup before we turn on relocation. */ * stab and slb setup before we turn on relocation. */
......
/*
* IBM PowerPC IBM eBus Infrastructure Support.
*
* Copyright (c) 2005 IBM Corporation
* Heiko J Schick <schickhj@de.ibm.com>
*
* All rights reserved.
*
* This source code is distributed under a dual license of GPL v2.0 and OpenIB
* BSD.
*
* OpenIB BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/init.h>
#include <linux/console.h>
#include <linux/kobject.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <asm/ibmebus.h>
#include <asm/abs_addr.h>
static struct ibmebus_dev ibmebus_bus_device = { /* fake "parent" device */
.name = ibmebus_bus_device.ofdev.dev.bus_id,
.ofdev.dev.bus_id = "ibmebus",
.ofdev.dev.bus = &ibmebus_bus_type,
};
static void *ibmebus_alloc_coherent(struct device *dev,
size_t size,
dma_addr_t *dma_handle,
gfp_t flag)
{
void *mem;
mem = kmalloc(size, flag);
*dma_handle = (dma_addr_t)mem;
return mem;
}
static void ibmebus_free_coherent(struct device *dev,
size_t size, void *vaddr,
dma_addr_t dma_handle)
{
kfree(vaddr);
}
static dma_addr_t ibmebus_map_single(struct device *dev,
void *ptr,
size_t size,
enum dma_data_direction direction)
{
return (dma_addr_t)(ptr);
}
static void ibmebus_unmap_single(struct device *dev,
dma_addr_t dma_addr,
size_t size,
enum dma_data_direction direction)
{
return;
}
static int ibmebus_map_sg(struct device *dev,
struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
int i;
for (i = 0; i < nents; i++) {
sg[i].dma_address = (dma_addr_t)page_address(sg[i].page)
+ sg[i].offset;
sg[i].dma_length = sg[i].length;
}
return nents;
}
static void ibmebus_unmap_sg(struct device *dev,
struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
return;
}
static int ibmebus_dma_supported(struct device *dev, u64 mask)
{
return 1;
}
struct dma_mapping_ops ibmebus_dma_ops = {
.alloc_coherent = ibmebus_alloc_coherent,
.free_coherent = ibmebus_free_coherent,
.map_single = ibmebus_map_single,
.unmap_single = ibmebus_unmap_single,
.map_sg = ibmebus_map_sg,
.unmap_sg = ibmebus_unmap_sg,
.dma_supported = ibmebus_dma_supported,
};
static int ibmebus_bus_probe(struct device *dev)
{
struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
const struct of_device_id *id;
int error = -ENODEV;
if (!ibmebusdrv->probe)
return error;
id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
if (id) {
error = ibmebusdrv->probe(ibmebusdev, id);
}
return error;
}
static int ibmebus_bus_remove(struct device *dev)
{
struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
if (ibmebusdrv->remove) {
return ibmebusdrv->remove(ibmebusdev);
}
return 0;
}
static void __devinit ibmebus_dev_release(struct device *dev)
{
of_node_put(to_ibmebus_dev(dev)->ofdev.node);
kfree(to_ibmebus_dev(dev));
}
static ssize_t ibmebusdev_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", to_ibmebus_dev(dev)->name);
}
static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name,
NULL);
static struct ibmebus_dev* __devinit ibmebus_register_device_common(
struct ibmebus_dev *dev, char *name)
{
int err = 0;
dev->name = name;
dev->ofdev.dev.parent = &ibmebus_bus_device.ofdev.dev;
dev->ofdev.dev.bus = &ibmebus_bus_type;
dev->ofdev.dev.release = ibmebus_dev_release;
/* An ibmebusdev is based on a of_device. We have to change the
* bus type to use our own DMA mapping operations.
*/
if ((err = of_device_register(&dev->ofdev)) != 0) {
printk(KERN_ERR "%s: failed to register device (%d).\n",
__FUNCTION__, err);
return NULL;
}
device_create_file(&dev->ofdev.dev, &dev_attr_name);
return dev;
}
static struct ibmebus_dev* __devinit ibmebus_register_device_node(
struct device_node *dn)
{
struct ibmebus_dev *dev;
char *loc_code;
int length;
loc_code = (char *)get_property(dn, "ibm,loc-code", NULL);
if (!loc_code) {
printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n",
__FUNCTION__, dn->name ? dn->name : "<unknown>");
return NULL;
}
if (strlen(loc_code) == 0) {
printk(KERN_WARNING "%s: 'ibm,loc-code' is invalid\n",
__FUNCTION__);
return NULL;
}
dev = kmalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
if (!dev) {
return NULL;
}
memset(dev, 0, sizeof(struct ibmebus_dev));
dev->ofdev.node = of_node_get(dn);
length = strlen(loc_code);
memcpy(dev->ofdev.dev.bus_id, loc_code
+ (length - min(length, BUS_ID_SIZE - 1)),
min(length, BUS_ID_SIZE - 1));
/* Register with generic device framework. */
if (ibmebus_register_device_common(dev, dn->name) == NULL) {
kfree(dev);
return NULL;
}
return dev;
}
static void ibmebus_probe_of_nodes(char* name)
{
struct device_node *dn = NULL;
while ((dn = of_find_node_by_name(dn, name))) {
if (ibmebus_register_device_node(dn) == NULL) {
of_node_put(dn);
return;
}
}
of_node_put(dn);
return;
}
static void ibmebus_add_devices_by_id(struct of_device_id *idt)
{
while (strlen(idt->name) > 0) {
ibmebus_probe_of_nodes(idt->name);
idt++;
}
return;
}
static int ibmebus_match_helper(struct device *dev, void *data)
{
if (strcmp((char*)data, to_ibmebus_dev(dev)->name) == 0)
return 1;
return 0;
}
static int ibmebus_unregister_device(struct device *dev)
{
device_remove_file(dev, &dev_attr_name);
of_device_unregister(to_of_device(dev));
return 0;
}
static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
{
struct device *dev;
while (strlen(idt->name) > 0) {
while ((dev = bus_find_device(&ibmebus_bus_type, NULL,
(void*)idt->name,
ibmebus_match_helper))) {
ibmebus_unregister_device(dev);
}
idt++;
}
return;
}
int ibmebus_register_driver(struct ibmebus_driver *drv)
{
int err = 0;
drv->driver.name = drv->name;
drv->driver.bus = &ibmebus_bus_type;
drv->driver.probe = ibmebus_bus_probe;
drv->driver.remove = ibmebus_bus_remove;
if ((err = driver_register(&drv->driver) != 0))
return err;
ibmebus_add_devices_by_id(drv->id_table);
return 0;
}
EXPORT_SYMBOL(ibmebus_register_driver);
void ibmebus_unregister_driver(struct ibmebus_driver *drv)
{
driver_unregister(&drv->driver);
ibmebus_remove_devices_by_id(drv->id_table);
}
EXPORT_SYMBOL(ibmebus_unregister_driver);
int ibmebus_request_irq(struct ibmebus_dev *dev,
u32 ist,
irqreturn_t (*handler)(int, void*, struct pt_regs *),
unsigned long irq_flags, const char * devname,
void *dev_id)
{
unsigned int irq = virt_irq_create_mapping(ist);
if (irq == NO_IRQ)
return -EINVAL;
irq = irq_offset_up(irq);
return request_irq(irq, handler,
irq_flags, devname, dev_id);
}
EXPORT_SYMBOL(ibmebus_request_irq);
void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
{
unsigned int irq = virt_irq_create_mapping(ist);
irq = irq_offset_up(irq);
free_irq(irq, dev_id);
return;
}
EXPORT_SYMBOL(ibmebus_free_irq);
static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
{
const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv);
const struct of_device_id *ids = ebus_drv->id_table;
const struct of_device_id *found_id;
if (!ids)
return 0;
found_id = of_match_device(ids, &ebus_dev->ofdev);
if (found_id)
return 1;
return 0;
}
struct bus_type ibmebus_bus_type = {
.name = "ibmebus",
.match = ibmebus_bus_match,
};
EXPORT_SYMBOL(ibmebus_bus_type);
static int __init ibmebus_bus_init(void)
{
int err;
printk(KERN_INFO "IBM eBus Device Driver\n");
err = bus_register(&ibmebus_bus_type);
if (err) {
printk(KERN_ERR ":%s: failed to register IBM eBus.\n",
__FUNCTION__);
return err;
}
err = device_register(&ibmebus_bus_device.ofdev.dev);
if (err) {
printk(KERN_WARNING "%s: device_register returned %i\n",
__FUNCTION__, err);
bus_unregister(&ibmebus_bus_type);
return err;
}
return 0;
}
__initcall(ibmebus_bus_init);
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
* to reduce code space and undefined function references. * to reduce code space and undefined function references.
*/ */
#include <linux/errno.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
...@@ -44,18 +43,12 @@ ...@@ -44,18 +43,12 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/proc_fs.h>
#include <linux/random.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#ifdef CONFIG_PPC64
#include <linux/kallsyms.h>
#endif
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -66,8 +59,7 @@ ...@@ -66,8 +59,7 @@
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC_ISERIES
#include <asm/iseries/it_lp_queue.h>
#include <asm/paca.h> #include <asm/paca.h>
#endif #endif
...@@ -78,10 +70,6 @@ EXPORT_SYMBOL(__irq_offset_value); ...@@ -78,10 +70,6 @@ EXPORT_SYMBOL(__irq_offset_value);
static int ppc_spurious_interrupts; static int ppc_spurious_interrupts;
#if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP)
extern void iSeries_smp_message_recv(struct pt_regs *);
#endif
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC32
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) #define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
...@@ -195,49 +183,6 @@ void fixup_irqs(cpumask_t map) ...@@ -195,49 +183,6 @@ void fixup_irqs(cpumask_t map)
} }
#endif #endif
#ifdef CONFIG_PPC_ISERIES
void do_IRQ(struct pt_regs *regs)
{
struct paca_struct *lpaca;
irq_enter();
#ifdef CONFIG_DEBUG_STACKOVERFLOW
/* Debugging check for stack overflow: is there less than 2KB free? */
{
long sp;
sp = __get_SP() & (THREAD_SIZE-1);
if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
printk("do_IRQ: stack overflow: %ld\n",
sp - sizeof(struct thread_info));
dump_stack();
}
}
#endif
lpaca = get_paca();
#ifdef CONFIG_SMP
if (lpaca->lppaca.int_dword.fields.ipi_cnt) {
lpaca->lppaca.int_dword.fields.ipi_cnt = 0;
iSeries_smp_message_recv(regs);
}
#endif /* CONFIG_SMP */
if (hvlpevent_is_pending())
process_hvlpevents(regs);
irq_exit();
if (lpaca->lppaca.int_dword.fields.decr_int) {
lpaca->lppaca.int_dword.fields.decr_int = 0;
/* Signal a fake decrementer interrupt */
timer_interrupt(regs);
}
}
#else /* CONFIG_PPC_ISERIES */
void do_IRQ(struct pt_regs *regs) void do_IRQ(struct pt_regs *regs)
{ {
int irq; int irq;
...@@ -286,16 +231,24 @@ void do_IRQ(struct pt_regs *regs) ...@@ -286,16 +231,24 @@ void do_IRQ(struct pt_regs *regs)
} else } else
#endif #endif
__do_IRQ(irq, regs); __do_IRQ(irq, regs);
} else } else if (irq != -2)
#ifdef CONFIG_PPC32 /* That's not SMP safe ... but who cares ? */
if (irq != -2) ppc_spurious_interrupts++;
#endif
/* That's not SMP safe ... but who cares ? */
ppc_spurious_interrupts++;
irq_exit(); irq_exit();
}
#endif /* CONFIG_PPC_ISERIES */ #ifdef CONFIG_PPC_ISERIES
{
struct paca_struct *lpaca = get_paca();
if (lpaca->lppaca.int_dword.fields.decr_int) {
lpaca->lppaca.int_dword.fields.decr_int = 0;
/* Signal a fake decrementer interrupt */
timer_interrupt(regs);
}
}
#endif
}
void __init init_IRQ(void) void __init init_IRQ(void)
{ {
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/page.h> #include <asm/pgtable.h>
#include <asm/iseries/lpar_map.h> #include <asm/iseries/lpar_map.h>
const struct LparMap __attribute__((__section__(".text"))) xLparMap = { const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
...@@ -16,16 +16,16 @@ const struct LparMap __attribute__((__section__(".text"))) xLparMap = { ...@@ -16,16 +16,16 @@ const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
.xSegmentTableOffs = STAB0_PAGE, .xSegmentTableOffs = STAB0_PAGE,
.xEsids = { .xEsids = {
{ .xKernelEsid = GET_ESID(KERNELBASE), { .xKernelEsid = GET_ESID(PAGE_OFFSET),
.xKernelVsid = KERNEL_VSID(KERNELBASE), }, .xKernelVsid = KERNEL_VSID(PAGE_OFFSET), },
{ .xKernelEsid = GET_ESID(VMALLOCBASE), { .xKernelEsid = GET_ESID(VMALLOC_START),
.xKernelVsid = KERNEL_VSID(VMALLOCBASE), }, .xKernelVsid = KERNEL_VSID(VMALLOC_START), },
}, },
.xRanges = { .xRanges = {
{ .xPages = HvPagesToMap, { .xPages = HvPagesToMap,
.xOffset = 0, .xOffset = 0,
.xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - HW_PAGE_SHIFT), .xVPN = KERNEL_VSID(PAGE_OFFSET) << (SID_SHIFT - HW_PAGE_SHIFT),
}, },
}, },
}; };
/*
* Code to handle transition of Linux booting another kernel.
*
* Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
* GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
* Copyright (C) 2005 IBM Corporation.
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
#include <linux/kexec.h>
#include <linux/reboot.h>
#include <linux/threads.h>
#include <asm/machdep.h>
/*
* Provide a dummy crash_notes definition until crash dump is implemented.
* This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
*/
note_buf_t crash_notes[NR_CPUS];
void machine_crash_shutdown(struct pt_regs *regs)
{
if (ppc_md.machine_crash_shutdown)
ppc_md.machine_crash_shutdown(regs);
}
/*
* Do what every setup is needed on image and the
* reboot code buffer to allow us to avoid allocations
* later.
*/
int machine_kexec_prepare(struct kimage *image)
{
if (ppc_md.machine_kexec_prepare)
return ppc_md.machine_kexec_prepare(image);
/*
* Fail if platform doesn't provide its own machine_kexec_prepare
* implementation.
*/
return -ENOSYS;
}
void machine_kexec_cleanup(struct kimage *image)
{
if (ppc_md.machine_kexec_cleanup)
ppc_md.machine_kexec_cleanup(image);
}
/*
* Do not allocate memory (or fail in any way) in machine_kexec().
* We are past the point of no return, committed to rebooting now.
*/
NORET_TYPE void machine_kexec(struct kimage *image)
{
if (ppc_md.machine_kexec)
ppc_md.machine_kexec(image);
else {
/*
* Fall back to normal restart if platform doesn't provide
* its own kexec function, and user insist to kexec...
*/
machine_restart(NULL);
}
for(;;);
}
/*
* PPC32 code to handle Linux booting another kernel.
*
* Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
* GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
* Copyright (C) 2005 IBM Corporation.
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
#include <linux/kexec.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <asm/cacheflush.h>
#include <asm/hw_irq.h>
#include <asm/io.h>
typedef NORET_TYPE void (*relocate_new_kernel_t)(
unsigned long indirection_page,
unsigned long reboot_code_buffer,
unsigned long start_address) ATTRIB_NORET;
/*
* This is a generic machine_kexec function suitable at least for
* non-OpenFirmware embedded platforms.
* It merely copies the image relocation code to the control page and
* jumps to it.
* A platform specific function may just call this one.
*/
void default_machine_kexec(struct kimage *image)
{
const extern unsigned char relocate_new_kernel[];
const extern unsigned int relocate_new_kernel_size;
unsigned long page_list;
unsigned long reboot_code_buffer, reboot_code_buffer_phys;
relocate_new_kernel_t rnk;
/* Interrupts aren't acceptable while we reboot */
local_irq_disable();
page_list = image->head;
/* we need both effective and real address here */
reboot_code_buffer =
(unsigned long)page_address(image->control_code_page);
reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
/* copy our kernel relocation code to the control code page */
memcpy((void *)reboot_code_buffer, relocate_new_kernel,
relocate_new_kernel_size);
flush_icache_range(reboot_code_buffer,
reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
printk(KERN_INFO "Bye!\n");
/* now call it */
rnk = (relocate_new_kernel_t) reboot_code_buffer;
(*rnk)(page_list, reboot_code_buffer_phys, image->start);
}
int default_machine_kexec_prepare(struct kimage *image)
{
return 0;
}
/* /*
* machine_kexec.c - handle transition of Linux booting another kernel * PPC64 code to handle Linux booting another kernel.
* *
* Copyright (C) 2004-2005, IBM Corp. * Copyright (C) 2004-2005, IBM Corp.
* *
...@@ -28,21 +28,7 @@ ...@@ -28,21 +28,7 @@
#define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */ #define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */
/* Have this around till we move it into crash specific file */ int default_machine_kexec_prepare(struct kimage *image)
note_buf_t crash_notes[NR_CPUS];
/* Dummy for now. Not sure if we need to have a crash shutdown in here
* and if what it will achieve. Letting it be now to compile the code
* in generic kexec environment
*/
void machine_crash_shutdown(struct pt_regs *regs)
{
/* do nothing right now */
/* smp_relase_cpus() if we want smp on panic kernel */
/* cpu_irq_down to isolate us until we are ready */
}
int machine_kexec_prepare(struct kimage *image)
{ {
int i; int i;
unsigned long begin, end; /* limits of segment */ unsigned long begin, end; /* limits of segment */
...@@ -111,11 +97,6 @@ int machine_kexec_prepare(struct kimage *image) ...@@ -111,11 +97,6 @@ int machine_kexec_prepare(struct kimage *image)
return 0; return 0;
} }
void machine_kexec_cleanup(struct kimage *image)
{
/* we do nothing in prepare that needs to be undone */
}
#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE) #define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE)
static void copy_segments(unsigned long ind) static void copy_segments(unsigned long ind)
...@@ -172,9 +153,8 @@ void kexec_copy_flush(struct kimage *image) ...@@ -172,9 +153,8 @@ void kexec_copy_flush(struct kimage *image)
* including ones that were in place on the original copy * including ones that were in place on the original copy
*/ */
for (i = 0; i < nr_segments; i++) for (i = 0; i < nr_segments; i++)
flush_icache_range(ranges[i].mem + KERNELBASE, flush_icache_range((unsigned long)__va(ranges[i].mem),
ranges[i].mem + KERNELBASE + (unsigned long)__va(ranges[i].mem + ranges[i].memsz));
ranges[i].memsz);
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -283,13 +263,20 @@ extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start, ...@@ -283,13 +263,20 @@ extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start,
void (*clear_all)(void)) ATTRIB_NORET; void (*clear_all)(void)) ATTRIB_NORET;
/* too late to fail here */ /* too late to fail here */
void machine_kexec(struct kimage *image) void default_machine_kexec(struct kimage *image)
{ {
/* prepare control code if any */ /* prepare control code if any */
/* shutdown other cpus into our wait loop and quiesce interrupts */ /*
kexec_prepare_cpus(); * If the kexec boot is the normal one, need to shutdown other cpus
* into our wait loop and quiesce interrupts.
* Otherwise, in the case of crashed mode (crashing_cpu >= 0),
* stopping other CPUs and collecting their pt_regs is done before
* using debugger IPI.
*/
if (crashing_cpu == -1)
kexec_prepare_cpus();
/* switch to a staticly allocated stack. Based on irq stack code. /* switch to a staticly allocated stack. Based on irq stack code.
* XXX: the task struct will likely be invalid once we do the copy! * XXX: the task struct will likely be invalid once we do the copy!
......
This diff is collapsed.
This diff is collapsed.
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/lppaca.h> #include <asm/lppaca.h>
#include <asm/iseries/it_lp_queue.h> #include <asm/iseries/it_lp_queue.h>
#include <asm/iseries/it_lp_reg_save.h>
#include <asm/paca.h> #include <asm/paca.h>
...@@ -26,8 +27,7 @@ extern unsigned long __toc_start; ...@@ -26,8 +27,7 @@ extern unsigned long __toc_start;
/* The Paca is an array with one entry per processor. Each contains an /* The Paca is an array with one entry per processor. Each contains an
* lppaca, which contains the information shared between the * lppaca, which contains the information shared between the
* hypervisor and Linux. Each also contains an ItLpRegSave area which * hypervisor and Linux.
* is used by the hypervisor to save registers.
* On systems with hardware multi-threading, there are two threads * On systems with hardware multi-threading, there are two threads
* per processor. The Paca array must contain an entry for each thread. * per processor. The Paca array must contain an entry for each thread.
* The VPD Areas will give a max logical processors = 2 * max physical * The VPD Areas will give a max logical processors = 2 * max physical
...@@ -37,7 +37,6 @@ extern unsigned long __toc_start; ...@@ -37,7 +37,6 @@ extern unsigned long __toc_start;
#define PACA_INIT_COMMON(number, start, asrr, asrv) \ #define PACA_INIT_COMMON(number, start, asrr, asrv) \
.lock_token = 0x8000, \ .lock_token = 0x8000, \
.paca_index = (number), /* Paca Index */ \ .paca_index = (number), /* Paca Index */ \
.default_decr = 0x00ff0000, /* Initial Decr */ \
.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
.stab_real = (asrr), /* Real pointer to segment table */ \ .stab_real = (asrr), /* Real pointer to segment table */ \
.stab_addr = (asrv), /* Virt pointer to segment table */ \ .stab_addr = (asrv), /* Virt pointer to segment table */ \
...@@ -57,11 +56,7 @@ extern unsigned long __toc_start; ...@@ -57,11 +56,7 @@ extern unsigned long __toc_start;
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
#define PACA_INIT_ISERIES(number) \ #define PACA_INIT_ISERIES(number) \
.lppaca_ptr = &paca[number].lppaca, \ .lppaca_ptr = &paca[number].lppaca, \
.reg_save_ptr = &paca[number].reg_save, \ .reg_save_ptr = &iseries_reg_save[number],
.reg_save = { \
.xDesc = 0xd397d9e2, /* "LpRS" */ \
.xSize = sizeof(struct ItLpRegSave) \
}
#define PACA_INIT(number) \ #define PACA_INIT(number) \
{ \ { \
......
This diff is collapsed.
...@@ -43,8 +43,13 @@ static void dummy_perf(struct pt_regs *regs) ...@@ -43,8 +43,13 @@ static void dummy_perf(struct pt_regs *regs)
mtspr(SPRN_MMCR0, mmcr0); mtspr(SPRN_MMCR0, mmcr0);
} }
#else #else
/* Ensure exceptions are disabled */
static void dummy_perf(struct pt_regs *regs) static void dummy_perf(struct pt_regs *regs)
{ {
unsigned int mmcr0 = mfspr(SPRN_MMCR0);
mmcr0 &= ~(MMCR0_PMXE);
mtspr(SPRN_MMCR0, mmcr0);
} }
#endif #endif
......
...@@ -76,11 +76,6 @@ EXPORT_SYMBOL(single_step_exception); ...@@ -76,11 +76,6 @@ EXPORT_SYMBOL(single_step_exception);
EXPORT_SYMBOL(sys_sigreturn); EXPORT_SYMBOL(sys_sigreturn);
#endif #endif
#if defined(CONFIG_PPC_PREP)
EXPORT_SYMBOL(_prep_type);
EXPORT_SYMBOL(ucSystemType);
#endif
EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy); EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcat); EXPORT_SYMBOL(strcat);
......
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.
...@@ -699,10 +699,6 @@ void __init time_init(void) ...@@ -699,10 +699,6 @@ void __init time_init(void)
div128_by_32(1024*1024, 0, tb_ticks_per_sec, &res); div128_by_32(1024*1024, 0, tb_ticks_per_sec, &res);
tb_to_xs = res.result_low; tb_to_xs = res.result_low;
#ifdef CONFIG_PPC64
get_paca()->default_decr = tb_ticks_per_jiffy;
#endif
/* /*
* Compute scale factor for sched_clock. * Compute scale factor for sched_clock.
* The calibrate_decr() function has set tb_ticks_per_sec, * The calibrate_decr() function has set tb_ticks_per_sec,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -107,6 +107,7 @@ static int im_region_status(unsigned long v_addr, unsigned long size, ...@@ -107,6 +107,7 @@ static int im_region_status(unsigned long v_addr, unsigned long size,
if (v_addr < (unsigned long) tmp->addr + tmp->size) if (v_addr < (unsigned long) tmp->addr + tmp->size)
break; break;
*vm = NULL;
if (tmp) { if (tmp) {
if (im_region_overlaps(v_addr, size, tmp)) if (im_region_overlaps(v_addr, size, tmp))
return IM_REGION_OVERLAP; return IM_REGION_OVERLAP;
...@@ -127,7 +128,6 @@ static int im_region_status(unsigned long v_addr, unsigned long size, ...@@ -127,7 +128,6 @@ static int im_region_status(unsigned long v_addr, unsigned long size,
} }
} }
*vm = NULL;
return IM_REGION_UNUSED; return IM_REGION_UNUSED;
} }
......
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.
...@@ -9,3 +9,4 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ ...@@ -9,3 +9,4 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
oprofile-y := $(DRIVER_OBJS) common.o oprofile-y := $(DRIVER_OBJS) common.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
oprofile-$(CONFIG_PPC32) += op_model_7450.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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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