diff options
Diffstat (limited to 'arch/powerpc/kernel')
| -rw-r--r-- | arch/powerpc/kernel/crash_dump.c | 5 | ||||
| -rw-r--r-- | arch/powerpc/kernel/entry_64.S | 4 | ||||
| -rw-r--r-- | arch/powerpc/kernel/fadump.c | 5 | ||||
| -rw-r--r-- | arch/powerpc/kernel/idle.c | 87 | ||||
| -rw-r--r-- | arch/powerpc/kernel/kvm.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/kernel/lparcfg.c | 11 | ||||
| -rw-r--r-- | arch/powerpc/kernel/nvram_64.c | 3 | ||||
| -rw-r--r-- | arch/powerpc/kernel/proc_powerpc.c | 21 | ||||
| -rw-r--r-- | arch/powerpc/kernel/process.c | 16 | ||||
| -rw-r--r-- | arch/powerpc/kernel/rtas_flash.c | 450 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal_32.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal_64.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/smp.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/sys_ppc32.c | 109 | ||||
| -rw-r--r-- | arch/powerpc/kernel/tm.S | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/udbg.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/uprobes.c | 29 | 
17 files changed, 284 insertions, 477 deletions
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index b3ba5163eae..9ec3fe174cb 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -150,10 +150,7 @@ void crash_free_reserved_phys_range(unsigned long begin, unsigned long end)  		if (addr <= rtas_end && ((addr + PAGE_SIZE) > rtas_start))  			continue; -		ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT)); -		init_page_count(pfn_to_page(addr >> PAGE_SHIFT)); -		free_page((unsigned long)__va(addr)); -		totalram_pages++; +		free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT));  	}  }  #endif diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 256c5bf0adb..04d69c4a5ac 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -304,7 +304,7 @@ syscall_exit_work:  	subi	r12,r12,TI_FLAGS  4:	/* Anything else left to do? */ -	SET_DEFAULT_THREAD_PPR(r3, r9)		/* Set thread.ppr = 3 */ +	SET_DEFAULT_THREAD_PPR(r3, r10)		/* Set thread.ppr = 3 */  	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)  	beq	.ret_from_except_lite @@ -657,7 +657,7 @@ resume_kernel:  	/* Clear _TIF_EMULATE_STACK_STORE flag */  	lis	r11,_TIF_EMULATE_STACK_STORE@h  	addi	r5,r9,TI_FLAGS -	ldarx	r4,0,r5 +0:	ldarx	r4,0,r5  	andc	r4,r4,r11  	stdcx.	r4,0,r5  	bne-	0b diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 06c8202a69c..2230fd0ca3e 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -1045,10 +1045,7 @@ static void fadump_release_memory(unsigned long begin, unsigned long end)  		if (addr <= ra_end && ((addr + PAGE_SIZE) > ra_start))  			continue; -		ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT)); -		init_page_count(pfn_to_page(addr >> PAGE_SHIFT)); -		free_page((unsigned long)__va(addr)); -		totalram_pages++; +		free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT));  	}  } diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index ea78761aa16..939ea7ef0dc 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -33,11 +33,6 @@  #include <asm/runlatch.h>  #include <asm/smp.h> -#ifdef CONFIG_HOTPLUG_CPU -#define cpu_should_die()	cpu_is_offline(smp_processor_id()) -#else -#define cpu_should_die()	0 -#endif  unsigned long cpuidle_disable = IDLE_NO_OVERRIDE;  EXPORT_SYMBOL(cpuidle_disable); @@ -50,64 +45,38 @@ static int __init powersave_off(char *arg)  }  __setup("powersave=off", powersave_off); -/* - * The body of the idle task. - */ -void cpu_idle(void) +#ifdef CONFIG_HOTPLUG_CPU +void arch_cpu_idle_dead(void)  { -	set_thread_flag(TIF_POLLING_NRFLAG); -	while (1) { -		tick_nohz_idle_enter(); -		rcu_idle_enter(); - -		while (!need_resched() && !cpu_should_die()) { -			ppc64_runlatch_off(); - -			if (ppc_md.power_save) { -				clear_thread_flag(TIF_POLLING_NRFLAG); -				/* -				 * smp_mb is so clearing of TIF_POLLING_NRFLAG -				 * is ordered w.r.t. need_resched() test. -				 */ -				smp_mb(); -				local_irq_disable(); - -				/* Don't trace irqs off for idle */ -				stop_critical_timings(); - -				/* check again after disabling irqs */ -				if (!need_resched() && !cpu_should_die()) -					ppc_md.power_save(); - -				start_critical_timings(); - -				/* Some power_save functions return with -				 * interrupts enabled, some don't. -				 */ -				if (irqs_disabled()) -					local_irq_enable(); -				set_thread_flag(TIF_POLLING_NRFLAG); +	sched_preempt_enable_no_resched(); +	cpu_die(); +} +#endif -			} else { -				/* -				 * Go into low thread priority and possibly -				 * low power mode. -				 */ -				HMT_low(); -				HMT_very_low(); -			} -		} +void arch_cpu_idle(void) +{ +	ppc64_runlatch_off(); -		HMT_medium(); -		ppc64_runlatch_on(); -		rcu_idle_exit(); -		tick_nohz_idle_exit(); -		if (cpu_should_die()) { -			sched_preempt_enable_no_resched(); -			cpu_die(); -		} -		schedule_preempt_disabled(); +	if (ppc_md.power_save) { +		ppc_md.power_save(); +		/* +		 * Some power_save functions return with +		 * interrupts enabled, some don't. +		 */ +		if (irqs_disabled()) +			local_irq_enable(); +	} else { +		local_irq_enable(); +		/* +		 * Go into low thread priority and possibly +		 * low power mode. +		 */ +		HMT_low(); +		HMT_very_low();  	} + +	HMT_medium(); +	ppc64_runlatch_on();  }  int powersave_nap; diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c index a61b133c4f9..6782221d49b 100644 --- a/arch/powerpc/kernel/kvm.c +++ b/arch/powerpc/kernel/kvm.c @@ -756,12 +756,7 @@ static __init void kvm_free_tmp(void)  	end = (ulong)&kvm_tmp[ARRAY_SIZE(kvm_tmp)] & PAGE_MASK;  	/* Free the tmp space we don't need */ -	for (; start < end; start += PAGE_SIZE) { -		ClearPageReserved(virt_to_page(start)); -		init_page_count(virt_to_page(start)); -		free_page(start); -		totalram_pages++; -	} +	free_reserved_area(start, end, 0, NULL);  }  static int __init kvm_guest_init(void) diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index f5725bce9ed..801a757c363 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -41,8 +41,6 @@  /* #define LPARCFG_DEBUG */ -static struct proc_dir_entry *proc_ppc64_lparcfg; -  /*   * Track sum of all purrs across all processors. This is used to further   * calculate usage values by different applications @@ -688,27 +686,22 @@ static const struct file_operations lparcfg_fops = {  static int __init lparcfg_init(void)  { -	struct proc_dir_entry *ent;  	umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;  	/* Allow writing if we have FW_FEATURE_SPLPAR */  	if (firmware_has_feature(FW_FEATURE_SPLPAR))  		mode |= S_IWUSR; -	ent = proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops); -	if (!ent) { +	if (!proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops)) {  		printk(KERN_ERR "Failed to create powerpc/lparcfg\n");  		return -EIO;  	} - -	proc_ppc64_lparcfg = ent;  	return 0;  }  static void __exit lparcfg_cleanup(void)  { -	if (proc_ppc64_lparcfg) -		remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent); +	remove_proc_subtree("powerpc/lparcfg", NULL);  }  module_init(lparcfg_init); diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index bec1e930ed7..48fbc2b97e9 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -511,8 +511,7 @@ int __init nvram_scan_partitions(void)  			       "detected: 0-length partition\n");  			goto out;  		} -		tmp_part = (struct nvram_partition *) -			kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); +		tmp_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);  		err = -ENOMEM;  		if (!tmp_part) {  			printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n"); diff --git a/arch/powerpc/kernel/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c index f19d0bdc324..feb8580fdc8 100644 --- a/arch/powerpc/kernel/proc_powerpc.c +++ b/arch/powerpc/kernel/proc_powerpc.c @@ -32,8 +32,6 @@  static loff_t page_map_seek( struct file *file, loff_t off, int whence)  {  	loff_t new; -	struct proc_dir_entry *dp = PDE(file_inode(file)); -  	switch(whence) {  	case 0:  		new = off; @@ -42,12 +40,12 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence)  		new = file->f_pos + off;  		break;  	case 2: -		new = dp->size + off; +		new = PAGE_SIZE + off;  		break;  	default:  		return -EINVAL;  	} -	if ( new < 0 || new > dp->size ) +	if ( new < 0 || new > PAGE_SIZE )  		return -EINVAL;  	return (file->f_pos = new);  } @@ -55,19 +53,18 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence)  static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,  			      loff_t *ppos)  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); -	return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size); +	return simple_read_from_buffer(buf, nbytes, ppos, +			PDE_DATA(file_inode(file)), PAGE_SIZE);  }  static int page_map_mmap( struct file *file, struct vm_area_struct *vma )  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); - -	if ((vma->vm_end - vma->vm_start) > dp->size) +	if ((vma->vm_end - vma->vm_start) > PAGE_SIZE)  		return -EINVAL; -	remap_pfn_range(vma, vma->vm_start, __pa(dp->data) >> PAGE_SHIFT, -						dp->size, vma->vm_page_prot); +	remap_pfn_range(vma, vma->vm_start, +			__pa(PDE_DATA(file_inode(file))) >> PAGE_SHIFT, +			PAGE_SIZE, vma->vm_page_prot);  	return 0;  } @@ -86,7 +83,7 @@ static int __init proc_ppc64_init(void)  			       &page_map_fops, vdso_data);  	if (!pde)  		return 1; -	pde->size = PAGE_SIZE; +	proc_set_size(pde, PAGE_SIZE);  	return 0;  } diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 59dd545fdde..13a8d9d0b5c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -555,10 +555,12 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new)  		new->thread.regs->msr |=  			(MSR_FP | new->thread.fpexc_mode);  	} +#ifdef CONFIG_ALTIVEC  	if (msr & MSR_VEC) {  		do_load_up_transact_altivec(&new->thread);  		new->thread.regs->msr |= MSR_VEC;  	} +#endif  	/* We may as well turn on VSX too since all the state is restored now */  	if (msr & MSR_VSX)  		new->thread.regs->msr |= MSR_VSX; @@ -829,6 +831,8 @@ void show_regs(struct pt_regs * regs)  {  	int i, trap; +	show_regs_print_info(KERN_DEFAULT); +  	printk("NIP: "REG" LR: "REG" CTR: "REG"\n",  	       regs->nip, regs->link, regs->ctr);  	printk("REGS: %p TRAP: %04lx   %s  (%s)\n", @@ -848,12 +852,6 @@ void show_regs(struct pt_regs * regs)  #else  		printk("DAR: "REG", DSISR: %08lx\n", regs->dar, regs->dsisr);  #endif -	printk("TASK = %p[%d] '%s' THREAD: %p", -	       current, task_pid_nr(current), current->comm, task_thread_info(current)); - -#ifdef CONFIG_SMP -	printk(" CPU: %d", raw_smp_processor_id()); -#endif /* CONFIG_SMP */  	for (i = 0;  i < 32;  i++) {  		if ((i % REGS_PER_LINE) == 0) @@ -1360,12 +1358,6 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)  	} while (count++ < kstack_depth_to_print);  } -void dump_stack(void) -{ -	show_stack(current, NULL); -} -EXPORT_SYMBOL(dump_stack); -  #ifdef CONFIG_PPC64  /* Called with hard IRQs off */  void __ppc64_runlatch_on(void) diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index c642f013298..5b770262c67 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -102,9 +102,10 @@ static struct kmem_cache *flash_block_cache = NULL;  #define FLASH_BLOCK_LIST_VERSION (1UL) -/* Local copy of the flash block list. - * We only allow one open of the flash proc file and create this - * list as we go.  The rtas_firmware_flash_list varable will be +/* + * Local copy of the flash block list. + * + * The rtas_firmware_flash_list varable will be   * set once the data is fully read.   *   * For convenience as we build the list we use virtual addrs, @@ -125,23 +126,23 @@ struct rtas_update_flash_t  struct rtas_manage_flash_t  {  	int status;			/* Returned status */ -	unsigned int op;		/* Reject or commit image */  };  /* Status int must be first member of struct */  struct rtas_validate_flash_t  {  	int status;		 	/* Returned status */	 -	char buf[VALIDATE_BUF_SIZE]; 	/* Candidate image buffer */ +	char *buf;			/* Candidate image buffer */  	unsigned int buf_size;		/* Size of image buf */  	unsigned int update_results;	/* Update results token */  }; -static DEFINE_SPINLOCK(flash_file_open_lock); -static struct proc_dir_entry *firmware_flash_pde; -static struct proc_dir_entry *firmware_update_pde; -static struct proc_dir_entry *validate_pde; -static struct proc_dir_entry *manage_pde; +static struct rtas_update_flash_t rtas_update_flash_data; +static struct rtas_manage_flash_t rtas_manage_flash_data; +static struct rtas_validate_flash_t rtas_validate_flash_data; +static DEFINE_MUTEX(rtas_update_flash_mutex); +static DEFINE_MUTEX(rtas_manage_flash_mutex); +static DEFINE_MUTEX(rtas_validate_flash_mutex);  /* Do simple sanity checks on the flash image. */  static int flash_list_valid(struct flash_block_list *flist) @@ -191,10 +192,10 @@ static void free_flash_list(struct flash_block_list *f)  static int rtas_flash_release(struct inode *inode, struct file *file)  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); -	struct rtas_update_flash_t *uf; -	 -	uf = (struct rtas_update_flash_t *) dp->data; +	struct rtas_update_flash_t *const uf = &rtas_update_flash_data; + +	mutex_lock(&rtas_update_flash_mutex); +  	if (uf->flist) {      		/* File was opened in write mode for a new flash attempt */  		/* Clear saved list */ @@ -214,13 +215,14 @@ static int rtas_flash_release(struct inode *inode, struct file *file)  		uf->flist = NULL;  	} -	atomic_dec(&dp->count); +	mutex_unlock(&rtas_update_flash_mutex);  	return 0;  } -static void get_flash_status_msg(int status, char *buf) +static size_t get_flash_status_msg(int status, char *buf)  { -	char *msg; +	const char *msg; +	size_t len;  	switch (status) {  	case FLASH_AUTH: @@ -242,34 +244,51 @@ static void get_flash_status_msg(int status, char *buf)  		msg = "ready: firmware image ready for flash on reboot\n";  		break;  	default: -		sprintf(buf, "error: unexpected status value %d\n", status); -		return; +		return sprintf(buf, "error: unexpected status value %d\n", +			       status);  	} -	strcpy(buf, msg);	 +	len = strlen(msg); +	memcpy(buf, msg, len + 1); +	return len;  }  /* Reading the proc file will show status (not the firmware contents) */ -static ssize_t rtas_flash_read(struct file *file, char __user *buf, -			       size_t count, loff_t *ppos) +static ssize_t rtas_flash_read_msg(struct file *file, char __user *buf, +				   size_t count, loff_t *ppos)  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); -	struct rtas_update_flash_t *uf; +	struct rtas_update_flash_t *const uf = &rtas_update_flash_data;  	char msg[RTAS_MSG_MAXLEN]; +	size_t len; +	int status; -	uf = dp->data; +	mutex_lock(&rtas_update_flash_mutex); +	status = uf->status; +	mutex_unlock(&rtas_update_flash_mutex); -	if (!strcmp(dp->name, FIRMWARE_FLASH_NAME)) { -		get_flash_status_msg(uf->status, msg); -	} else {	   /* FIRMWARE_UPDATE_NAME */ -		sprintf(msg, "%d\n", uf->status); -	} +	/* Read as text message */ +	len = get_flash_status_msg(status, msg); +	return simple_read_from_buffer(buf, count, ppos, msg, len); +} + +static ssize_t rtas_flash_read_num(struct file *file, char __user *buf, +				   size_t count, loff_t *ppos) +{ +	struct rtas_update_flash_t *const uf = &rtas_update_flash_data; +	char msg[RTAS_MSG_MAXLEN]; +	int status; + +	mutex_lock(&rtas_update_flash_mutex); +	status = uf->status; +	mutex_unlock(&rtas_update_flash_mutex); +	/* Read as number */ +	sprintf(msg, "%d\n", status);  	return simple_read_from_buffer(buf, count, ppos, msg, strlen(msg));  }  /* constructor for flash_block_cache */ -void rtas_block_ctor(void *ptr) +static void rtas_block_ctor(void *ptr)  {  	memset(ptr, 0, RTAS_BLK_SIZE);  } @@ -282,16 +301,15 @@ void rtas_block_ctor(void *ptr)  static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,  				size_t count, loff_t *off)  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); -	struct rtas_update_flash_t *uf; +	struct rtas_update_flash_t *const uf = &rtas_update_flash_data;  	char *p; -	int next_free; +	int next_free, rc;  	struct flash_block_list *fl; -	uf = (struct rtas_update_flash_t *) dp->data; +	mutex_lock(&rtas_update_flash_mutex);  	if (uf->status == FLASH_AUTH || count == 0) -		return count;	/* discard data */ +		goto out;	/* discard data */  	/* In the case that the image is not ready for flashing, the memory  	 * allocated for the block list will be freed upon the release of the  @@ -300,7 +318,7 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,  	if (uf->flist == NULL) {  		uf->flist = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);  		if (!uf->flist) -			return -ENOMEM; +			goto nomem;  	}  	fl = uf->flist; @@ -311,7 +329,7 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,  		/* Need to allocate another block_list */  		fl->next = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);  		if (!fl->next) -			return -ENOMEM; +			goto nomem;  		fl = fl->next;  		next_free = 0;  	} @@ -320,52 +338,37 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,  		count = RTAS_BLK_SIZE;  	p = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);  	if (!p) -		return -ENOMEM; +		goto nomem;  	if(copy_from_user(p, buffer, count)) {  		kmem_cache_free(flash_block_cache, p); -		return -EFAULT; +		rc = -EFAULT; +		goto error;  	}  	fl->blocks[next_free].data = p;  	fl->blocks[next_free].length = count;  	fl->num_blocks++; - +out: +	mutex_unlock(&rtas_update_flash_mutex);  	return count; -} - -static int rtas_excl_open(struct inode *inode, struct file *file) -{ -	struct proc_dir_entry *dp = PDE(inode); - -	/* Enforce exclusive open with use count of PDE */ -	spin_lock(&flash_file_open_lock); -	if (atomic_read(&dp->count) > 2) { -		spin_unlock(&flash_file_open_lock); -		return -EBUSY; -	} - -	atomic_inc(&dp->count); -	spin_unlock(&flash_file_open_lock); -	 -	return 0; -} -static int rtas_excl_release(struct inode *inode, struct file *file) -{ -	struct proc_dir_entry *dp = PDE(inode); - -	atomic_dec(&dp->count); - -	return 0; +nomem: +	rc = -ENOMEM; +error: +	mutex_unlock(&rtas_update_flash_mutex); +	return rc;  } -static void manage_flash(struct rtas_manage_flash_t *args_buf) +/* + * Flash management routines. + */ +static void manage_flash(struct rtas_manage_flash_t *args_buf, unsigned int op)  {  	s32 rc;  	do { -		rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1,  -			       1, NULL, args_buf->op); +		rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 1, +			       NULL, op);  	} while (rtas_busy_delay(rc));  	args_buf->status = rc; @@ -374,55 +377,62 @@ static void manage_flash(struct rtas_manage_flash_t *args_buf)  static ssize_t manage_flash_read(struct file *file, char __user *buf,  			       size_t count, loff_t *ppos)  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); -	struct rtas_manage_flash_t *args_buf; +	struct rtas_manage_flash_t *const args_buf = &rtas_manage_flash_data;  	char msg[RTAS_MSG_MAXLEN]; -	int msglen; - -	args_buf = dp->data; -	if (args_buf == NULL) -		return 0; +	int msglen, status; -	msglen = sprintf(msg, "%d\n", args_buf->status); +	mutex_lock(&rtas_manage_flash_mutex); +	status = args_buf->status; +	mutex_unlock(&rtas_manage_flash_mutex); +	msglen = sprintf(msg, "%d\n", status);  	return simple_read_from_buffer(buf, count, ppos, msg, msglen);  }  static ssize_t manage_flash_write(struct file *file, const char __user *buf,  				size_t count, loff_t *off)  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); -	struct rtas_manage_flash_t *args_buf; -	const char reject_str[] = "0"; -	const char commit_str[] = "1"; +	struct rtas_manage_flash_t *const args_buf = &rtas_manage_flash_data; +	static const char reject_str[] = "0"; +	static const char commit_str[] = "1";  	char stkbuf[10]; -	int op; +	int op, rc; + +	mutex_lock(&rtas_manage_flash_mutex); -	args_buf = (struct rtas_manage_flash_t *) dp->data;  	if ((args_buf->status == MANAGE_AUTH) || (count == 0)) -		return count; +		goto out;  	op = -1;  	if (buf) {  		if (count > 9) count = 9; -		if (copy_from_user (stkbuf, buf, count)) { -			return -EFAULT; -		} +		rc = -EFAULT; +		if (copy_from_user (stkbuf, buf, count)) +			goto error;  		if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0)   			op = RTAS_REJECT_TMP_IMG;  		else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0)   			op = RTAS_COMMIT_TMP_IMG;  	} -	if (op == -1)   /* buf is empty, or contains invalid string */ -		return -EINVAL; - -	args_buf->op = op; -	manage_flash(args_buf); +	if (op == -1) {   /* buf is empty, or contains invalid string */ +		rc = -EINVAL; +		goto error; +	} +	manage_flash(args_buf, op); +out: +	mutex_unlock(&rtas_manage_flash_mutex);  	return count; + +error: +	mutex_unlock(&rtas_manage_flash_mutex); +	return rc;  } +/* + * Validation routines. + */  static void validate_flash(struct rtas_validate_flash_t *args_buf)  {  	int token = rtas_token("ibm,validate-flash-image"); @@ -462,14 +472,14 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf,  static ssize_t validate_flash_read(struct file *file, char __user *buf,  			       size_t count, loff_t *ppos)  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); -	struct rtas_validate_flash_t *args_buf; +	struct rtas_validate_flash_t *const args_buf = +		&rtas_validate_flash_data;  	char msg[RTAS_MSG_MAXLEN];  	int msglen; -	args_buf = dp->data; - +	mutex_lock(&rtas_validate_flash_mutex);  	msglen = get_validate_flash_msg(args_buf, msg); +	mutex_unlock(&rtas_validate_flash_mutex);  	return simple_read_from_buffer(buf, count, ppos, msg, msglen);  } @@ -477,24 +487,18 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf,  static ssize_t validate_flash_write(struct file *file, const char __user *buf,  				    size_t count, loff_t *off)  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); -	struct rtas_validate_flash_t *args_buf; +	struct rtas_validate_flash_t *const args_buf = +		&rtas_validate_flash_data;  	int rc; -	args_buf = (struct rtas_validate_flash_t *) dp->data; - -	if (dp->data == NULL) { -		dp->data = kmalloc(sizeof(struct rtas_validate_flash_t),  -				GFP_KERNEL); -		if (dp->data == NULL)  -			return -ENOMEM; -	} +	mutex_lock(&rtas_validate_flash_mutex);  	/* We are only interested in the first 4K of the  	 * candidate image */  	if ((*off >= VALIDATE_BUF_SIZE) ||   		(args_buf->status == VALIDATE_AUTH)) {  		*off += count; +		mutex_unlock(&rtas_validate_flash_mutex);  		return count;  	} @@ -517,31 +521,29 @@ static ssize_t validate_flash_write(struct file *file, const char __user *buf,  	*off += count;  	rc = count;  done: -	if (rc < 0) { -		kfree(dp->data); -		dp->data = NULL; -	} +	mutex_unlock(&rtas_validate_flash_mutex);  	return rc;  }  static int validate_flash_release(struct inode *inode, struct file *file)  { -	struct proc_dir_entry *dp = PDE(file_inode(file)); -	struct rtas_validate_flash_t *args_buf; +	struct rtas_validate_flash_t *const args_buf = +		&rtas_validate_flash_data; -	args_buf = (struct rtas_validate_flash_t *) dp->data; +	mutex_lock(&rtas_validate_flash_mutex);  	if (args_buf->status == VALIDATE_READY) {  		args_buf->buf_size = VALIDATE_BUF_SIZE;  		validate_flash(args_buf);  	} -	/* The matching atomic_inc was in rtas_excl_open() */ -	atomic_dec(&dp->count); - +	mutex_unlock(&rtas_validate_flash_mutex);  	return 0;  } +/* + * On-reboot flash update applicator. + */  static void rtas_flash_firmware(int reboot_type)  {  	unsigned long image_size; @@ -634,75 +636,57 @@ static void rtas_flash_firmware(int reboot_type)  	spin_unlock(&rtas_data_buf_lock);  } -static void remove_flash_pde(struct proc_dir_entry *dp) -{ -	if (dp) { -		kfree(dp->data); -		remove_proc_entry(dp->name, dp->parent); -	} -} - -static int initialize_flash_pde_data(const char *rtas_call_name, -				     size_t buf_size, -				     struct proc_dir_entry *dp) -{ +/* + * Manifest of proc files to create + */ +struct rtas_flash_file { +	const char *filename; +	const char *rtas_call_name;  	int *status; -	int token; - -	dp->data = kzalloc(buf_size, GFP_KERNEL); -	if (dp->data == NULL) -		return -ENOMEM; - -	/* -	 * This code assumes that the status int is the first member of the -	 * struct  -	 */ -	status = (int *) dp->data; -	token = rtas_token(rtas_call_name); -	if (token == RTAS_UNKNOWN_SERVICE) -		*status = FLASH_AUTH; -	else -		*status = FLASH_NO_OP; - -	return 0; -} - -static struct proc_dir_entry *create_flash_pde(const char *filename, -					       const struct file_operations *fops) -{ -	return proc_create(filename, S_IRUSR | S_IWUSR, NULL, fops); -} - -static const struct file_operations rtas_flash_operations = { -	.owner		= THIS_MODULE, -	.read		= rtas_flash_read, -	.write		= rtas_flash_write, -	.open		= rtas_excl_open, -	.release	= rtas_flash_release, -	.llseek		= default_llseek, +	const struct file_operations fops;  }; -static const struct file_operations manage_flash_operations = { -	.owner		= THIS_MODULE, -	.read		= manage_flash_read, -	.write		= manage_flash_write, -	.open		= rtas_excl_open, -	.release	= rtas_excl_release, -	.llseek		= default_llseek, -}; - -static const struct file_operations validate_flash_operations = { -	.owner		= THIS_MODULE, -	.read		= validate_flash_read, -	.write		= validate_flash_write, -	.open		= rtas_excl_open, -	.release	= validate_flash_release, -	.llseek		= default_llseek, +static const struct rtas_flash_file rtas_flash_files[] = { +	{ +		.filename	= "powerpc/rtas/" FIRMWARE_FLASH_NAME, +		.rtas_call_name	= "ibm,update-flash-64-and-reboot", +		.status		= &rtas_update_flash_data.status, +		.fops.read	= rtas_flash_read_msg, +		.fops.write	= rtas_flash_write, +		.fops.release	= rtas_flash_release, +		.fops.llseek	= default_llseek, +	}, +	{ +		.filename	= "powerpc/rtas/" FIRMWARE_UPDATE_NAME, +		.rtas_call_name	= "ibm,update-flash-64-and-reboot", +		.status		= &rtas_update_flash_data.status, +		.fops.read	= rtas_flash_read_num, +		.fops.write	= rtas_flash_write, +		.fops.release	= rtas_flash_release, +		.fops.llseek	= default_llseek, +	}, +	{ +		.filename	= "powerpc/rtas/" VALIDATE_FLASH_NAME, +		.rtas_call_name	= "ibm,validate-flash-image", +		.status		= &rtas_validate_flash_data.status, +		.fops.read	= validate_flash_read, +		.fops.write	= validate_flash_write, +		.fops.release	= validate_flash_release, +		.fops.llseek	= default_llseek, +	}, +	{ +		.filename	= "powerpc/rtas/" MANAGE_FLASH_NAME, +		.rtas_call_name	= "ibm,manage-flash-image", +		.status		= &rtas_manage_flash_data.status, +		.fops.read	= manage_flash_read, +		.fops.write	= manage_flash_write, +		.fops.llseek	= default_llseek, +	}  };  static int __init rtas_flash_init(void)  { -	int rc; +	int i;  	if (rtas_token("ibm,update-flash-64-and-reboot") ==  		       RTAS_UNKNOWN_SERVICE) { @@ -710,93 +694,65 @@ static int __init rtas_flash_init(void)  		return 1;  	} -	firmware_flash_pde = create_flash_pde("powerpc/rtas/" -					      FIRMWARE_FLASH_NAME, -					      &rtas_flash_operations); -	if (firmware_flash_pde == NULL) { -		rc = -ENOMEM; -		goto cleanup; -	} - -	rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", -			 	       sizeof(struct rtas_update_flash_t),  -				       firmware_flash_pde); -	if (rc != 0) -		goto cleanup; +	rtas_validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL); +	if (!rtas_validate_flash_data.buf) +		return -ENOMEM; -	firmware_update_pde = create_flash_pde("powerpc/rtas/" -					       FIRMWARE_UPDATE_NAME, -					       &rtas_flash_operations); -	if (firmware_update_pde == NULL) { -		rc = -ENOMEM; -		goto cleanup; +	flash_block_cache = kmem_cache_create("rtas_flash_cache", +					      RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0, +					      rtas_block_ctor); +	if (!flash_block_cache) { +		printk(KERN_ERR "%s: failed to create block cache\n", +				__func__); +		goto enomem_buf;  	} -	rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", -			 	       sizeof(struct rtas_update_flash_t),  -				       firmware_update_pde); -	if (rc != 0) -		goto cleanup; +	for (i = 0; i < ARRAY_SIZE(rtas_flash_files); i++) { +		const struct rtas_flash_file *f = &rtas_flash_files[i]; +		int token; -	validate_pde = create_flash_pde("powerpc/rtas/" VALIDATE_FLASH_NAME, -			      		&validate_flash_operations); -	if (validate_pde == NULL) { -		rc = -ENOMEM; -		goto cleanup; -	} - -	rc = initialize_flash_pde_data("ibm,validate-flash-image", -		                       sizeof(struct rtas_validate_flash_t),  -				       validate_pde); -	if (rc != 0) -		goto cleanup; +		if (!proc_create(f->filename, S_IRUSR | S_IWUSR, NULL, &f->fops)) +			goto enomem; -	manage_pde = create_flash_pde("powerpc/rtas/" MANAGE_FLASH_NAME, -				      &manage_flash_operations); -	if (manage_pde == NULL) { -		rc = -ENOMEM; -		goto cleanup; +		/* +		 * This code assumes that the status int is the first member of the +		 * struct +		 */ +		token = rtas_token(f->rtas_call_name); +		if (token == RTAS_UNKNOWN_SERVICE) +			*f->status = FLASH_AUTH; +		else +			*f->status = FLASH_NO_OP;  	} -	rc = initialize_flash_pde_data("ibm,manage-flash-image", -			               sizeof(struct rtas_manage_flash_t), -				       manage_pde); -	if (rc != 0) -		goto cleanup; -  	rtas_flash_term_hook = rtas_flash_firmware; - -	flash_block_cache = kmem_cache_create("rtas_flash_cache", -				RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0, -				rtas_block_ctor); -	if (!flash_block_cache) { -		printk(KERN_ERR "%s: failed to create block cache\n", -				__func__); -		rc = -ENOMEM; -		goto cleanup; -	}  	return 0; -cleanup: -	remove_flash_pde(firmware_flash_pde); -	remove_flash_pde(firmware_update_pde); -	remove_flash_pde(validate_pde); -	remove_flash_pde(manage_pde); +enomem: +	while (--i >= 0) { +		const struct rtas_flash_file *f = &rtas_flash_files[i]; +		remove_proc_entry(f->filename, NULL); +	} -	return rc; +	kmem_cache_destroy(flash_block_cache); +enomem_buf: +	kfree(rtas_validate_flash_data.buf); +	return -ENOMEM;  }  static void __exit rtas_flash_cleanup(void)  { +	int i; +  	rtas_flash_term_hook = NULL; -	if (flash_block_cache) -		kmem_cache_destroy(flash_block_cache); +	for (i = 0; i < ARRAY_SIZE(rtas_flash_files); i++) { +		const struct rtas_flash_file *f = &rtas_flash_files[i]; +		remove_proc_entry(f->filename, NULL); +	} -	remove_flash_pde(firmware_flash_pde); -	remove_flash_pde(firmware_update_pde); -	remove_flash_pde(validate_pde); -	remove_flash_pde(manage_pde); +	kmem_cache_destroy(flash_block_cache); +	kfree(rtas_validate_flash_data.buf);  }  module_init(rtas_flash_init); diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 3acb28e245b..95068bf569a 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -866,10 +866,12 @@ static long restore_tm_user_regs(struct pt_regs *regs,  		do_load_up_transact_fpu(¤t->thread);  		regs->msr |= (MSR_FP | current->thread.fpexc_mode);  	} +#ifdef CONFIG_ALTIVEC  	if (msr & MSR_VEC) {  		do_load_up_transact_altivec(¤t->thread);  		regs->msr |= MSR_VEC;  	} +#endif  	return 0;  } diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 995f8543cb5..c1794286098 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -522,10 +522,12 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,  		do_load_up_transact_fpu(¤t->thread);  		regs->msr |= (MSR_FP | current->thread.fpexc_mode);  	} +#ifdef CONFIG_ALTIVEC  	if (msr & MSR_VEC) {  		do_load_up_transact_altivec(¤t->thread);  		regs->msr |= MSR_VEC;  	} +#endif  	return err;  } diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 76bd9da8cb7..ee7ac5e6e28 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -669,7 +669,7 @@ __cpuinit void start_secondary(void *unused)  	local_irq_enable(); -	cpu_idle(); +	cpu_startup_entry(CPUHP_ONLINE);  	BUG();  } diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index d0bafc0cdf0..cd6e19d263b 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c @@ -61,91 +61,6 @@ asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,  	return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));  } -#ifdef CONFIG_SYSVIPC -long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, -	       u32 fifth) -{ -	int version; - -	version = call >> 16; /* hack for backward compatibility */ -	call &= 0xffff; - -	switch (call) { - -	case SEMTIMEDOP: -		if (fifth) -			/* sign extend semid */ -			return compat_sys_semtimedop((int)first, -						     compat_ptr(ptr), second, -						     compat_ptr(fifth)); -		/* else fall through for normal semop() */ -	case SEMOP: -		/* struct sembuf is the same on 32 and 64bit :)) */ -		/* sign extend semid */ -		return sys_semtimedop((int)first, compat_ptr(ptr), second, -				      NULL); -	case SEMGET: -		/* sign extend key, nsems */ -		return sys_semget((int)first, (int)second, third); -	case SEMCTL: -		/* sign extend semid, semnum */ -		return compat_sys_semctl((int)first, (int)second, third, -					 compat_ptr(ptr)); - -	case MSGSND: -		/* sign extend msqid */ -		return compat_sys_msgsnd((int)first, (int)second, third, -					 compat_ptr(ptr)); -	case MSGRCV: -		/* sign extend msqid, msgtyp */ -		return compat_sys_msgrcv((int)first, second, (int)fifth, -					 third, version, compat_ptr(ptr)); -	case MSGGET: -		/* sign extend key */ -		return sys_msgget((int)first, second); -	case MSGCTL: -		/* sign extend msqid */ -		return compat_sys_msgctl((int)first, second, compat_ptr(ptr)); - -	case SHMAT: -		/* sign extend shmid */ -		return compat_sys_shmat((int)first, second, third, version, -					compat_ptr(ptr)); -	case SHMDT: -		return sys_shmdt(compat_ptr(ptr)); -	case SHMGET: -		/* sign extend key_t */ -		return sys_shmget((int)first, second, third); -	case SHMCTL: -		/* sign extend shmid */ -		return compat_sys_shmctl((int)first, second, compat_ptr(ptr)); - -	default: -		return -ENOSYS; -	} - -	return -ENOSYS; -} -#endif - -/* Note: it is necessary to treat out_fd and in_fd as unsigned ints,  - * with the corresponding cast to a signed int to insure that the  - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long compat_sys_sendfile_wrapper(u32 out_fd, u32 in_fd, -					    compat_off_t __user *offset, u32 count) -{ -	return compat_sys_sendfile((int)out_fd, (int)in_fd, offset, count); -} - -asmlinkage long compat_sys_sendfile64_wrapper(u32 out_fd, u32 in_fd, -					      compat_loff_t __user *offset, u32 count) -{ -	return sys_sendfile((int)out_fd, (int)in_fd, -			    (off_t __user *)offset, count); -} -  unsigned long compat_sys_mmap2(unsigned long addr, size_t len,  			  unsigned long prot, unsigned long flags,  			  unsigned long fd, unsigned long pgoff) @@ -195,13 +110,6 @@ asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long h  	return sys_ftruncate(fd, (high << 32) | low);  } -long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf, -			  size_t len) -{ -	return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low, -				  buf, len); -} -  long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,  		     size_t len, int advice)  { @@ -209,23 +117,6 @@ long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,  			     advice);  } -asmlinkage long compat_sys_add_key(const char __user *_type, -			      const char __user *_description, -			      const void __user *_payload, -			      u32 plen, -			      u32 ringid) -{ -	return sys_add_key(_type, _description, _payload, plen, ringid); -} - -asmlinkage long compat_sys_request_key(const char __user *_type, -				  const char __user *_description, -				  const char __user *_callout_info, -				  u32 destringid) -{ -	return sys_request_key(_type, _description, _callout_info, destringid); -} -  asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,  				   unsigned offset_hi, unsigned offset_lo,  				   unsigned nbytes_hi, unsigned nbytes_lo) diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index 84dbace657c..2da67e7a16d 100644 --- a/arch/powerpc/kernel/tm.S +++ b/arch/powerpc/kernel/tm.S @@ -309,6 +309,7 @@ _GLOBAL(tm_recheckpoint)  	or	r5, r6, r5			/* Set MSR.FP+.VSX/.VEC */  	mtmsr	r5 +#ifdef CONFIG_ALTIVEC  	/* FP and VEC registers:  These are recheckpointed from thread.fpr[]  	 * and thread.vr[] respectively.  The thread.transact_fpr[] version  	 * is more modern, and will be loaded subsequently by any FPUnavailable @@ -323,6 +324,7 @@ _GLOBAL(tm_recheckpoint)  	REST_32VRS(0, r5, r3)			/* r5 scratch, r3 THREAD ptr */  	ld	r5, THREAD_VRSAVE(r3)  	mtspr	SPRN_VRSAVE, r5 +#endif  dont_restore_vec:  	andi.	r0, r4, MSR_FP diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index f9748498fe5..13b86709349 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -156,15 +156,13 @@ static struct console udbg_console = {  	.index	= 0,  }; -static int early_console_initialized; -  /*   * Called by setup_system after ppc_md->probe and ppc_md->early_init.   * Call it again after setting udbg_putc in ppc_md->setup_arch.   */  void __init register_early_udbg_console(void)  { -	if (early_console_initialized) +	if (early_console)  		return;  	if (!udbg_putc) @@ -174,7 +172,7 @@ void __init register_early_udbg_console(void)  		printk(KERN_INFO "early console immortal !\n");  		udbg_console.flags &= ~CON_BOOT;  	} -	early_console_initialized = 1; +	early_console = &udbg_console;  	register_console(&udbg_console);  } diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c index bc77834dbf4..59f419b935f 100644 --- a/arch/powerpc/kernel/uprobes.c +++ b/arch/powerpc/kernel/uprobes.c @@ -31,6 +31,16 @@  #define UPROBE_TRAP_NR	UINT_MAX  /** + * is_trap_insn - check if the instruction is a trap variant + * @insn: instruction to be checked. + * Returns true if @insn is a trap variant. + */ +bool is_trap_insn(uprobe_opcode_t *insn) +{ +	return (is_trap(*insn)); +} + +/**   * arch_uprobe_analyze_insn   * @mm: the probed address space.   * @arch_uprobe: the probepoint information. @@ -43,12 +53,6 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,  	if (addr & 0x03)  		return -EINVAL; -	/* -	 * We currently don't support a uprobe on an already -	 * existing breakpoint instruction underneath -	 */ -	if (is_trap(auprobe->ainsn)) -		return -ENOTSUPP;  	return 0;  } @@ -188,3 +192,16 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)  	return false;  } + +unsigned long +arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs) +{ +	unsigned long orig_ret_vaddr; + +	orig_ret_vaddr = regs->link; + +	/* Replace the return addr with trampoline addr */ +	regs->link = trampoline_vaddr; + +	return orig_ret_vaddr; +}  |