diff options
Diffstat (limited to 'arch/ppc64/kernel')
-rw-r--r-- | arch/ppc64/kernel/HvLpEvent.c | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/nvram.c | 17 | ||||
-rw-r--r-- | arch/ppc64/kernel/pSeries_hvCall.S | 8 | ||||
-rw-r--r-- | arch/ppc64/kernel/prom.c | 4 | ||||
-rw-r--r-- | arch/ppc64/kernel/prom_init.c | 115 | ||||
-rw-r--r-- | arch/ppc64/kernel/ptrace.c | 5 | ||||
-rw-r--r-- | arch/ppc64/kernel/ptrace32.c | 5 | ||||
-rw-r--r-- | arch/ppc64/kernel/signal32.c | 4 | ||||
-rw-r--r-- | arch/ppc64/kernel/smp.c | 12 | ||||
-rw-r--r-- | arch/ppc64/kernel/time.c | 12 | ||||
-rw-r--r-- | arch/ppc64/kernel/vdso32/Makefile | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/vdso32/note.S | 25 | ||||
-rw-r--r-- | arch/ppc64/kernel/vdso32/vdso32.lds.S | 3 | ||||
-rw-r--r-- | arch/ppc64/kernel/vdso64/Makefile | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/vdso64/note.S | 1 | ||||
-rw-r--r-- | arch/ppc64/kernel/vdso64/vdso64.lds.S | 5 |
16 files changed, 190 insertions, 32 deletions
diff --git a/arch/ppc64/kernel/HvLpEvent.c b/arch/ppc64/kernel/HvLpEvent.c index 9802beefa217..f8f19637f73f 100644 --- a/arch/ppc64/kernel/HvLpEvent.c +++ b/arch/ppc64/kernel/HvLpEvent.c @@ -45,7 +45,7 @@ int HvLpEvent_unregisterHandler( HvLpEvent_Type eventType ) /* We now sleep until all other CPUs have scheduled. This ensures that * the deletion is seen by all other CPUs, and that the deleted handler * isn't still running on another CPU when we return. */ - synchronize_kernel(); + synchronize_rcu(); } } return rc; diff --git a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c index b9069c2d1933..4e71781a4414 100644 --- a/arch/ppc64/kernel/nvram.c +++ b/arch/ppc64/kernel/nvram.c @@ -339,9 +339,9 @@ static int nvram_remove_os_partition(void) static int nvram_create_os_partition(void) { struct list_head * p; - struct nvram_partition * part; - struct nvram_partition * new_part = NULL; - struct nvram_partition * free_part = NULL; + struct nvram_partition *part = NULL; + struct nvram_partition *new_part = NULL; + struct nvram_partition *free_part = NULL; int seq_init[2] = { 0, 0 }; loff_t tmp_index; long size = 0; @@ -364,13 +364,11 @@ static int nvram_create_os_partition(void) free_part = part; } } - if (!size) { + if (!size) return -ENOSPC; - } /* Create our OS partition */ - new_part = (struct nvram_partition *) - kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); + new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); if (!new_part) { printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n"); return -ENOMEM; @@ -379,7 +377,7 @@ static int nvram_create_os_partition(void) new_part->index = free_part->index; new_part->header.signature = NVRAM_SIG_OS; new_part->header.length = size; - sprintf(new_part->header.name, "ppc64,linux"); + strcpy(new_part->header.name, "ppc64,linux"); new_part->header.checksum = nvram_checksum(&new_part->header); rc = nvram_write_header(new_part); @@ -394,7 +392,8 @@ static int nvram_create_os_partition(void) tmp_index = new_part->index + NVRAM_HEADER_LEN; rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index); if (rc <= 0) { - printk(KERN_ERR "nvram_create_os_partition: nvram_write failed (%d)\n", rc); + printk(KERN_ERR "nvram_create_os_partition: nvram_write " + "failed (%d)\n", rc); return rc; } diff --git a/arch/ppc64/kernel/pSeries_hvCall.S b/arch/ppc64/kernel/pSeries_hvCall.S index 0715d3038019..176e8da76466 100644 --- a/arch/ppc64/kernel/pSeries_hvCall.S +++ b/arch/ppc64/kernel/pSeries_hvCall.S @@ -28,6 +28,8 @@ unsigned long *out3); R10 */ _GLOBAL(plpar_hcall) + HMT_MEDIUM + mfcr r0 std r8,STK_PARM(r8)(r1) /* Save out ptrs */ @@ -53,6 +55,8 @@ _GLOBAL(plpar_hcall) /* Simple interface with no output values (other than status) */ _GLOBAL(plpar_hcall_norets) + HMT_MEDIUM + mfcr r0 stw r0,8(r1) @@ -75,6 +79,8 @@ _GLOBAL(plpar_hcall_norets) unsigned long *out1); 120(R1) */ _GLOBAL(plpar_hcall_8arg_2ret) + HMT_MEDIUM + mfcr r0 ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */ stw r0,8(r1) @@ -99,6 +105,8 @@ _GLOBAL(plpar_hcall_8arg_2ret) unsigned long *out4); 112(R1) */ _GLOBAL(plpar_hcall_4out) + HMT_MEDIUM + mfcr r0 stw r0,8(r1) diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 45a4ad08fbc2..fe2946c58314 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -321,6 +321,10 @@ static int __devinit finish_node_interrupts(struct device_node *np, char *name = get_property(ic->parent, "name", NULL); if (name && !strcmp(name, "u3")) np->intrs[intrcount].line += 128; + else if (!(name && !strcmp(name, "mac-io"))) + /* ignore other cascaded controllers, such as + the k2-sata-root */ + break; } np->intrs[intrcount].sense = 1; if (n > 1) diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 8dffa9ae2623..35ec42de962e 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -493,6 +493,113 @@ static void __init early_cmdline_parse(void) } /* + * To tell the firmware what our capabilities are, we have to pass + * it a fake 32-bit ELF header containing a couple of PT_NOTE sections + * that contain structures that contain the actual values. + */ +static struct fake_elf { + Elf32_Ehdr elfhdr; + Elf32_Phdr phdr[2]; + struct chrpnote { + u32 namesz; + u32 descsz; + u32 type; + char name[8]; /* "PowerPC" */ + struct chrpdesc { + u32 real_mode; + u32 real_base; + u32 real_size; + u32 virt_base; + u32 virt_size; + u32 load_base; + } chrpdesc; + } chrpnote; + struct rpanote { + u32 namesz; + u32 descsz; + u32 type; + char name[24]; /* "IBM,RPA-Client-Config" */ + struct rpadesc { + u32 lpar_affinity; + u32 min_rmo_size; + u32 min_rmo_percent; + u32 max_pft_size; + u32 splpar; + u32 min_load; + u32 new_mem_def; + u32 ignore_me; + } rpadesc; + } rpanote; +} fake_elf = { + .elfhdr = { + .e_ident = { 0x7f, 'E', 'L', 'F', + ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, + .e_type = ET_EXEC, /* yeah right */ + .e_machine = EM_PPC, + .e_version = EV_CURRENT, + .e_phoff = offsetof(struct fake_elf, phdr), + .e_phentsize = sizeof(Elf32_Phdr), + .e_phnum = 2 + }, + .phdr = { + [0] = { + .p_type = PT_NOTE, + .p_offset = offsetof(struct fake_elf, chrpnote), + .p_filesz = sizeof(struct chrpnote) + }, [1] = { + .p_type = PT_NOTE, + .p_offset = offsetof(struct fake_elf, rpanote), + .p_filesz = sizeof(struct rpanote) + } + }, + .chrpnote = { + .namesz = sizeof("PowerPC"), + .descsz = sizeof(struct chrpdesc), + .type = 0x1275, + .name = "PowerPC", + .chrpdesc = { + .real_mode = ~0U, /* ~0 means "don't care" */ + .real_base = ~0U, + .real_size = ~0U, + .virt_base = ~0U, + .virt_size = ~0U, + .load_base = ~0U + }, + }, + .rpanote = { + .namesz = sizeof("IBM,RPA-Client-Config"), + .descsz = sizeof(struct rpadesc), + .type = 0x12759999, + .name = "IBM,RPA-Client-Config", + .rpadesc = { + .lpar_affinity = 0, + .min_rmo_size = 64, /* in megabytes */ + .min_rmo_percent = 0, + .max_pft_size = 48, /* 2^48 bytes max PFT size */ + .splpar = 1, + .min_load = ~0U, + .new_mem_def = 0 + } + } +}; + +static void __init prom_send_capabilities(void) +{ + unsigned long offset = reloc_offset(); + ihandle elfloader; + int ret; + + elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); + if (elfloader == 0) { + prom_printf("couldn't open /packages/elf-loader\n"); + return; + } + ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"), + elfloader, ADDR(&fake_elf)); + call_prom("close", 1, 0, elfloader); +} + +/* * Memory allocation strategy... our layout is normally: * * at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd @@ -1448,6 +1555,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, } } +/* + * The Open Firmware 1275 specification states properties must be 31 bytes or + * less, however not all firmwares obey this. Make it 64 bytes to be safe. + */ +#define MAX_PROPERTY_NAME 64 + static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, unsigned long *mem_end) { @@ -1457,7 +1570,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, unsigned long soff; unsigned char *valp; unsigned long offset = reloc_offset(); - char pname[32]; + char pname[MAX_PROPERTY_NAME]; char *path; path = RELOC(prom_scratch); diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c index 3c76333ec3a9..9f8c6087ae56 100644 --- a/arch/ppc64/kernel/ptrace.c +++ b/arch/ppc64/kernel/ptrace.c @@ -28,6 +28,7 @@ #include <linux/security.h> #include <linux/audit.h> #include <linux/seccomp.h> +#include <linux/signal.h> #include <asm/uaccess.h> #include <asm/page.h> @@ -162,7 +163,7 @@ int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -194,7 +195,7 @@ int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: { /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_single_step(child); diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c index ee81b1b776cc..16436426c7e2 100644 --- a/arch/ppc64/kernel/ptrace32.c +++ b/arch/ppc64/kernel/ptrace32.c @@ -26,6 +26,7 @@ #include <linux/ptrace.h> #include <linux/user.h> #include <linux/security.h> +#include <linux/signal.h> #include <asm/uaccess.h> #include <asm/page.h> @@ -293,7 +294,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -325,7 +326,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) case PTRACE_SINGLESTEP: { /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_single_step(child); diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c index b0e167db6af9..3c2fa5c284c0 100644 --- a/arch/ppc64/kernel/signal32.c +++ b/arch/ppc64/kernel/signal32.c @@ -657,7 +657,7 @@ static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, /* Save user registers on the stack */ frame = &rt_sf->uc.uc_mcontext; - if (put_user(regs->gpr[1], (unsigned long __user *)newsp)) + if (put_user(regs->gpr[1], (u32 __user *)newsp)) goto badframe; if (vdso32_rt_sigtramp && current->thread.vdso_base) { @@ -842,7 +842,7 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka, regs->link = (unsigned long) frame->mctx.tramp; } - if (put_user(regs->gpr[1], (unsigned long __user *)newsp)) + if (put_user(regs->gpr[1], (u32 __user *)newsp)) goto badframe; regs->gpr[1] = (unsigned long) newsp; regs->gpr[3] = sig; diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c index 1c92da3e4525..3b906cd94037 100644 --- a/arch/ppc64/kernel/smp.c +++ b/arch/ppc64/kernel/smp.c @@ -125,7 +125,7 @@ void __devinit smp_generic_kick_cpu(int nr) * the processor will continue on to secondary_start */ paca[nr].cpu_start = 1; - mb(); + smp_mb(); } #endif /* CONFIG_PPC_MULTIPLATFORM */ @@ -256,7 +256,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, } call_data = &data; - wmb(); + smp_wmb(); /* Send a message to all other CPUs and wait for them to respond */ smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION); @@ -431,7 +431,7 @@ int generic_cpu_enable(unsigned int cpu) /* get the target out of it's holding state */ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; - wmb(); + smp_wmb(); while (!cpu_online(cpu)) cpu_relax(); @@ -447,7 +447,7 @@ void generic_cpu_die(unsigned int cpu) int i; for (i = 0; i < 100; i++) { - rmb(); + smp_rmb(); if (per_cpu(cpu_state, cpu) == CPU_DEAD) return; msleep(100); @@ -463,7 +463,7 @@ void generic_mach_cpu_die(void) cpu = smp_processor_id(); printk(KERN_DEBUG "CPU%d offline\n", cpu); __get_cpu_var(cpu_state) = CPU_DEAD; - wmb(); + smp_wmb(); while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) cpu_relax(); @@ -515,7 +515,7 @@ int __devinit __cpu_up(unsigned int cpu) * be written out to main store before we release * the processor. */ - mb(); + smp_mb(); /* wake up cpus */ DBG("smp: kicking cpu %d\n", cpu); diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 77ded5a363b6..772a465b49f9 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -221,15 +221,15 @@ static __inline__ void timer_recalc_offset(unsigned long cur_tb) temp_varp->tb_to_xs = do_gtod.varp->tb_to_xs; temp_varp->tb_orig_stamp = new_tb_orig_stamp; temp_varp->stamp_xsec = new_stamp_xsec; - mb(); + smp_mb(); do_gtod.varp = temp_varp; do_gtod.var_idx = temp_idx; ++(systemcfg->tb_update_count); - wmb(); + smp_wmb(); systemcfg->tb_orig_stamp = new_tb_orig_stamp; systemcfg->stamp_xsec = new_stamp_xsec; - wmb(); + smp_wmb(); ++(systemcfg->tb_update_count); } @@ -648,7 +648,7 @@ void ppc_adjtimex(void) temp_varp->tb_to_xs = new_tb_to_xs; temp_varp->stamp_xsec = new_stamp_xsec; temp_varp->tb_orig_stamp = do_gtod.varp->tb_orig_stamp; - mb(); + smp_mb(); do_gtod.varp = temp_varp; do_gtod.var_idx = temp_idx; @@ -662,10 +662,10 @@ void ppc_adjtimex(void) * loops back and reads them again until this criteria is met. */ ++(systemcfg->tb_update_count); - wmb(); + smp_wmb(); systemcfg->tb_to_xs = new_tb_to_xs; systemcfg->stamp_xsec = new_stamp_xsec; - wmb(); + smp_wmb(); ++(systemcfg->tb_update_count); write_sequnlock_irqrestore( &xtime_lock, flags ); diff --git a/arch/ppc64/kernel/vdso32/Makefile b/arch/ppc64/kernel/vdso32/Makefile index ede2f7e477c2..0b1b0df973eb 100644 --- a/arch/ppc64/kernel/vdso32/Makefile +++ b/arch/ppc64/kernel/vdso32/Makefile @@ -1,7 +1,7 @@ # List of files in the vdso, has to be asm only for now -obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o +obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o # Build rules diff --git a/arch/ppc64/kernel/vdso32/note.S b/arch/ppc64/kernel/vdso32/note.S new file mode 100644 index 000000000000..d4b5be4f3d5f --- /dev/null +++ b/arch/ppc64/kernel/vdso32/note.S @@ -0,0 +1,25 @@ +/* + * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. + * Here we can supply some information useful to userland. + */ + +#include <linux/uts.h> +#include <linux/version.h> + +#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type) \ + .section name, flags; \ + .balign 4; \ + .long 1f - 0f; /* name length */ \ + .long 3f - 2f; /* data length */ \ + .long type; /* note type */ \ +0: .asciz vendor; /* vendor name */ \ +1: .balign 4; \ +2: + +#define ASM_ELF_NOTE_END \ +3: .balign 4; /* pad out section */ \ + .previous + + ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0) + .long LINUX_VERSION_CODE + ASM_ELF_NOTE_END diff --git a/arch/ppc64/kernel/vdso32/vdso32.lds.S b/arch/ppc64/kernel/vdso32/vdso32.lds.S index cca27bd03a57..11290c902ba3 100644 --- a/arch/ppc64/kernel/vdso32/vdso32.lds.S +++ b/arch/ppc64/kernel/vdso32/vdso32.lds.S @@ -20,6 +20,8 @@ SECTIONS .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } + .note : { *(.note.*) } :text :note + . = ALIGN (16); .text : { @@ -87,6 +89,7 @@ SECTIONS PHDRS { text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + note PT_NOTE FLAGS(4); /* PF_R */ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ } diff --git a/arch/ppc64/kernel/vdso64/Makefile b/arch/ppc64/kernel/vdso64/Makefile index bd3f70b1a384..ab39988452cc 100644 --- a/arch/ppc64/kernel/vdso64/Makefile +++ b/arch/ppc64/kernel/vdso64/Makefile @@ -1,6 +1,6 @@ # List of files in the vdso, has to be asm only for now -obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o +obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o # Build rules diff --git a/arch/ppc64/kernel/vdso64/note.S b/arch/ppc64/kernel/vdso64/note.S new file mode 100644 index 000000000000..dc2a509f7e8a --- /dev/null +++ b/arch/ppc64/kernel/vdso64/note.S @@ -0,0 +1 @@ +#include "../vdso32/note.S" diff --git a/arch/ppc64/kernel/vdso64/vdso64.lds.S b/arch/ppc64/kernel/vdso64/vdso64.lds.S index 942c815c7bc7..9cb28181da80 100644 --- a/arch/ppc64/kernel/vdso64/vdso64.lds.S +++ b/arch/ppc64/kernel/vdso64/vdso64.lds.S @@ -18,12 +18,14 @@ SECTIONS .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } + .note : { *(.note.*) } :text :note + . = ALIGN (16); .text : { *(.text .stub .text.* .gnu.linkonce.t.*) *(.sfpr .glink) - } + } :text PROVIDE (__etext = .); PROVIDE (_etext = .); PROVIDE (etext = .); @@ -88,6 +90,7 @@ SECTIONS PHDRS { text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + note PT_NOTE FLAGS(4); /* PF_R */ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ } |