diff options
Diffstat (limited to 'arch/powerpc/kernel')
41 files changed, 3104 insertions, 1494 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 9ed551b6c17..6e03b595b6c 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -17,11 +17,11 @@ obj-y += vdso32/ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ signal_64.o ptrace32.o systbl.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_ALTIVEC) += vecemu.o vector.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 obj-$(CONFIG_PROC_FS) += $(procfs-y) rtaspci-$(CONFIG_PPC64) := rtas_pci.o @@ -30,12 +30,10 @@ obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_IBMVIO) += vio.o +obj-$(CONFIG_IBMEBUS) += ibmebus.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 +obj-$(CONFIG_CRASH_DUMP) += crash_dump.o ifeq ($(CONFIG_PPC_MERGE),y) @@ -48,25 +46,25 @@ extra-$(CONFIG_8xx) := head_8xx.o extra-y += vmlinux.lds 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_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_BOOTX_TEXT) += btext.o obj-$(CONFIG_6xx) += idle_6xx.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_KPROBES) += kprobes.o - +obj-$(CONFIG_SERIAL_8250) += legacy_serial.o udbg_16550.o module-$(CONFIG_PPC64) += module_64.o obj-$(CONFIG_MODULES) += $(module-y) pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ pci_direct_iommu.o iomap.o obj-$(CONFIG_PCI) += $(pci64-y) - -kexec64-$(CONFIG_PPC64) += machine_kexec_64.o -obj-$(CONFIG_KEXEC) += $(kexec64-y) +kexec-$(CONFIG_PPC64) := machine_kexec_64.o +kexec-$(CONFIG_PPC32) := machine_kexec_32.o +obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y) ifeq ($(CONFIG_PPC_ISERIES),y) $(obj)/head_64.o: $(obj)/lparmap.s diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 91538d2445b..56399c5c931 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -92,9 +92,9 @@ int main(void) DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); - DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); -#ifdef CONFIG_PPC32 + DEFINE(TI_SIGFRAME, offsetof(struct thread_info, nvgprs_frame)); DEFINE(TI_TASK, offsetof(struct thread_info, task)); +#ifdef CONFIG_PPC32 DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); #endif /* CONFIG_PPC32 */ @@ -131,11 +131,9 @@ int main(void) DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); #endif /* CONFIG_HUGETLB_PAGE */ - DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); 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(PACALPPACA, offsetof(struct paca_struct, lppaca)); DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index bdfba92b2b3..6223d39177c 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -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_8(unsigned char *bits, unsigned int *base, int rb); -static int g_loc_X; -static int g_loc_Y; -static int g_max_loc_X; -static int g_max_loc_Y; +#define __force_data __attribute__((__section__(".data"))) -static int dispDeviceRowBytes; -static int dispDeviceDepth; -static int dispDeviceRect[4]; -static unsigned char *dispDeviceBase, *logicalDisplayBase; +static int g_loc_X __force_data; +static int g_loc_Y __force_data; +static int g_max_loc_X __force_data; +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}; @@ -47,7 +50,7 @@ unsigned long disp_BAT[2] __initdata = {0, 0}; static unsigned char vga_font[cmapsz]; -int boot_text_mapped; +int boot_text_mapped __force_data = 0; int force_printk_to_btext = 0; #ifdef CONFIG_PPC32 @@ -57,7 +60,7 @@ int force_printk_to_btext = 0; * * The display is mapped to virtual address 0xD0000000, rather * 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 * setup done by MMU_Init() is applied. * @@ -66,10 +69,9 @@ int force_printk_to_btext = 0; * is really badly aligned, but I didn't encounter this case * yet. */ -void __init -btext_prepare_BAT(void) +void __init btext_prepare_BAT(void) { - unsigned long vaddr = KERNELBASE + 0x10000000; + unsigned long vaddr = PAGE_OFFSET + 0x10000000; unsigned long addr; unsigned long lowbits; @@ -95,12 +97,13 @@ btext_prepare_BAT(void) } #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 -btext_setup_display(int width, int height, int depth, int pitch, - unsigned long address) +void __init btext_setup_display(int width, int height, int depth, int pitch, + unsigned long address) { g_loc_X = 0; g_loc_Y = 0; @@ -116,6 +119,11 @@ btext_setup_display(int width, int height, int depth, int pitch, boot_text_mapped = 1; } +void __init btext_unmap(void) +{ + boot_text_mapped = 0; +} + /* Here's a small text engine to use during early boot * or for debugging purposes * @@ -127,7 +135,7 @@ btext_setup_display(int width, int height, int depth, int pitch, * changes. */ -void map_boot_text(void) +static void map_boot_text(void) { unsigned long base, offset, size; unsigned char *vbase; @@ -175,8 +183,9 @@ int btext_initialize(struct device_node *np) if (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) return -EINVAL; @@ -184,7 +193,6 @@ int btext_initialize(struct device_node *np) g_loc_Y = 0; g_max_loc_X = width / 8; g_max_loc_Y = height / 16; - logicalDisplayBase = (unsigned char *)address; dispDeviceBase = (unsigned char *)address; dispDeviceRowBytes = pitch; dispDeviceDepth = depth; @@ -197,14 +205,12 @@ int btext_initialize(struct device_node *np) return 0; } -void __init init_boot_display(void) +int __init btext_find_display(int allow_nonstdout) { char *name; struct device_node *np = NULL; int rc = -ENODEV; - printk("trying to initialize btext ...\n"); - name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); if (name != NULL) { np = of_find_node_by_path(name); @@ -218,8 +224,8 @@ void __init init_boot_display(void) } if (np) rc = btext_initialize(np); - if (rc == 0) - return; + if (rc == 0 || !allow_nonstdout) + return rc; for (np = NULL; (np = of_find_node_by_type(np, "display"));) { if (get_property(np, "linux,opened", NULL)) { @@ -228,8 +234,9 @@ void __init init_boot_display(void) printk("result: %d\n", rc); } if (rc == 0) - return; + break; } + return rc; } /* Calc the base address of a given point (x,y) */ @@ -277,44 +284,83 @@ EXPORT_SYMBOL(btext_update_display); 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]) * - (dispDeviceDepth >> 3)) >> 3; + (dispDeviceDepth >> 3)) >> 2; int i,j; for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) { - unsigned long *ptr = base; + unsigned int *ptr = base; for(j=width; j; --j) *(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 static void scrollscreen(void) { - unsigned long *src = (unsigned long *)calc_base(0,16); - unsigned long *dst = (unsigned long *)calc_base(0,0); + unsigned int *src = (unsigned int *)calc_base(0,16); + unsigned int *dst = (unsigned int *)calc_base(0,0); unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * - (dispDeviceDepth >> 3)) >> 3; + (dispDeviceDepth >> 3)) >> 2; int i,j; for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) { - unsigned long *src_ptr = src; - unsigned long *dst_ptr = dst; + unsigned int *src_ptr = src; + unsigned int *dst_ptr = dst; for(j=width; j; --j) *(dst_ptr++) = *(src_ptr++); - src += (dispDeviceRowBytes >> 3); - dst += (dispDeviceRowBytes >> 3); + src += (dispDeviceRowBytes >> 2); + dst += (dispDeviceRowBytes >> 2); } for (i=0; i<16; i++) { - unsigned long *dst_ptr = dst; + unsigned int *dst_ptr = dst; for(j=width; j; --j) *(dst_ptr++) = 0; - dst += (dispDeviceRowBytes >> 3); + dst += (dispDeviceRowBytes >> 2); } } #endif /* ndef NO_SCROLL */ @@ -377,6 +423,14 @@ void btext_drawstring(const char *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) { char *hex_table = "0123456789abcdef"; diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 1d85cedbbb7..43c74a6b07b 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -78,10 +78,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power3", - .oprofile_model = &op_model_rs64, -#endif + .oprofile_type = RS64, }, { /* Power3+ */ .pvr_mask = 0xffff0000, @@ -93,10 +91,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power3", - .oprofile_model = &op_model_rs64, -#endif + .oprofile_type = RS64, }, { /* Northstar */ .pvr_mask = 0xffff0000, @@ -108,10 +104,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/rs64", - .oprofile_model = &op_model_rs64, -#endif + .oprofile_type = RS64, }, { /* Pulsar */ .pvr_mask = 0xffff0000, @@ -123,10 +117,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/rs64", - .oprofile_model = &op_model_rs64, -#endif + .oprofile_type = RS64, }, { /* I-star */ .pvr_mask = 0xffff0000, @@ -138,10 +130,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/rs64", - .oprofile_model = &op_model_rs64, -#endif + .oprofile_type = RS64, }, { /* S-star */ .pvr_mask = 0xffff0000, @@ -153,10 +143,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/rs64", - .oprofile_model = &op_model_rs64, -#endif + .oprofile_type = RS64, }, { /* Power4 */ .pvr_mask = 0xffff0000, @@ -168,10 +156,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power4", - .oprofile_model = &op_model_rs64, -#endif + .oprofile_type = POWER4, }, { /* Power4+ */ .pvr_mask = 0xffff0000, @@ -183,10 +169,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power4", - .oprofile_model = &op_model_power4, -#endif + .oprofile_type = POWER4, }, { /* PPC970 */ .pvr_mask = 0xffff0000, @@ -199,10 +183,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/970", - .oprofile_model = &op_model_power4, -#endif + .oprofile_type = POWER4, }, #endif /* CONFIG_PPC64 */ #if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) @@ -221,10 +203,8 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/970", - .oprofile_model = &op_model_power4, -#endif + .oprofile_type = POWER4, }, #endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ #ifdef CONFIG_PPC64 @@ -238,10 +218,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .cpu_setup = __setup_cpu_ppc970, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/970", - .oprofile_model = &op_model_power4, -#endif + .oprofile_type = POWER4, }, { /* Power5 GR */ .pvr_mask = 0xffff0000, @@ -253,27 +231,23 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, -#ifdef CONFIG_OPROFILE .oprofile_cpu_type = "ppc64/power5", - .oprofile_model = &op_model_power4, -#endif + .oprofile_type = POWER4, }, { /* Power5 GS */ .pvr_mask = 0xffff0000, .pvr_value = 0x003b0000, - .cpu_name = "POWER5 (gs)", + .cpu_name = "POWER5+ (gs)", .cpu_features = CPU_FTRS_POWER5, .cpu_user_features = COMMON_USER_POWER5_PLUS, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, -#ifdef CONFIG_OPROFILE - .oprofile_cpu_type = "ppc64/power5", - .oprofile_model = &op_model_power4, -#endif + .oprofile_cpu_type = "ppc64/power5+", + .oprofile_type = POWER4, }, - { /* BE DD1.x */ + { /* Cell Broadband Engine */ .pvr_mask = 0xffff0000, .pvr_value = 0x00700000, .cpu_name = "Cell Broadband Engine", @@ -545,7 +519,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, - .cpu_setup = __setup_cpu_745x + .cpu_setup = __setup_cpu_745x, + .oprofile_cpu_type = "ppc/7450", + .oprofile_type = G4, }, { /* 7450 2.1 */ .pvr_mask = 0xffffffff, @@ -556,7 +532,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .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 */ .pvr_mask = 0xffff0000, @@ -567,7 +545,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .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 */ .pvr_mask = 0xffffff00, @@ -578,7 +558,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .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 */ .pvr_mask = 0xffffffff, @@ -589,7 +571,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, - .cpu_setup = __setup_cpu_745x + .cpu_setup = __setup_cpu_745x, + .oprofile_cpu_type = "ppc/7450", + .oprofile_type = G4, }, { /* 7455 others */ .pvr_mask = 0xffff0000, @@ -600,7 +584,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .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 */ .pvr_mask = 0xffffffff, @@ -611,7 +597,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .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 */ .pvr_mask = 0xffffffff, @@ -622,7 +610,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .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 */ .pvr_mask = 0xffff0000, @@ -633,7 +623,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, - .cpu_setup = __setup_cpu_745x + .cpu_setup = __setup_cpu_745x, + .oprofile_cpu_type = "ppc/7450", + .oprofile_type = G4, }, { /* 7447A */ .pvr_mask = 0xffff0000, @@ -644,7 +636,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, - .cpu_setup = __setup_cpu_745x + .cpu_setup = __setup_cpu_745x, + .oprofile_cpu_type = "ppc/7450", + .oprofile_type = G4, }, { /* 7448 */ .pvr_mask = 0xffff0000, @@ -655,7 +649,9 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .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) */ .pvr_mask = 0x7fff0000, @@ -979,6 +975,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, + .oprofile_cpu_type = "ppc/e500", + .oprofile_type = BOOKE, }, { /* e500v2 */ .pvr_mask = 0xffff0000, @@ -992,6 +990,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, + .oprofile_cpu_type = "ppc/e500", + .oprofile_type = BOOKE, }, #endif #if !CLASSIC_PPC diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c new file mode 100644 index 00000000000..4681155121e --- /dev/null +++ b/arch/powerpc/kernel/crash.c @@ -0,0 +1,264 @@ +/* + * 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, ¬e, 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, ¬e, 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" |