summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/crash_dump.c5
-rw-r--r--arch/powerpc/kernel/fadump.c5
-rw-r--r--arch/powerpc/kernel/idle.c89
-rw-r--r--arch/powerpc/kernel/kvm.c7
-rw-r--r--arch/powerpc/kernel/lparcfg.c11
-rw-r--r--arch/powerpc/kernel/proc_powerpc.c21
-rw-r--r--arch/powerpc/kernel/process.c14
-rw-r--r--arch/powerpc/kernel/rtas_flash.c450
-rw-r--r--arch/powerpc/kernel/smp.c2
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c109
-rw-r--r--arch/powerpc/kernel/udbg.c6
-rw-r--r--arch/powerpc/kernel/uprobes.c29
12 files changed, 274 insertions, 474 deletions
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index b3ba516..9ec3fe1 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/fadump.c b/arch/powerpc/kernel/fadump.c
index 06c8202..2230fd0 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 ea78761..939ea7e 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);
-
- } else {
- /*
- * Go into low thread priority and possibly
- * low power mode.
- */
- HMT_low();
- HMT_very_low();
- }
- }
+ sched_preempt_enable_no_resched();
+ cpu_die();
+}
+#endif
- 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();
+void arch_cpu_idle(void)
+{
+ ppc64_runlatch_off();
+
+ 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 a61b133..6782221 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 ab297f4..d92f387 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
@@ -689,27 +687,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/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c
index f19d0bd..feb8580 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 c0dea6f..ceb4e7b 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -831,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",
@@ -850,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)
@@ -1362,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 243e184..5b30224 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -120,9 +120,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,
@@ -143,23 +144,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)
@@ -209,10 +210,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 */
@@ -232,13 +233,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:
@@ -260,29 +262,46 @@ 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));
}
@@ -294,16 +313,15 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf,
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
@@ -312,7 +330,7 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
if (uf->flist == NULL) {
uf->flist = kmem_cache_zalloc(flash_block_cache, GFP_KERNEL);
if (!uf->flist)
- return -ENOMEM;
+ goto nomem;
}
fl = uf->flist;
@@ -323,7 +341,7 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
/* Need to allocate another block_list */
fl->next = kmem_cache_zalloc(flash_block_cache, GFP_KERNEL);
if (!fl->next)
- return -ENOMEM;
+ goto nomem;
fl = fl->next;
next_free = 0;
}
@@ -332,52 +350,37 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
count = RTAS_BLK_SIZE;
p = kmem_cache_zalloc(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;
@@ -386,55 +389,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;
+ int msglen, status;
- args_buf = dp->data;
- if (args_buf == NULL)
- return 0;
-
- 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");
@@ -474,14 +484,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);
}
@@ -489,24 +499,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;
}
@@ -529,31 +533,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;
@@ -646,75 +648,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,
-};
-
-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,
+ const struct file_operations fops;
};
-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) {
@@ -722,84 +706,56 @@ 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;
- }
+ rtas_validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL);
+ if (!rtas_validate_flash_data.buf)
+ return -ENOMEM;
- 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;
-
- 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,
+ NULL);
+ 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;
-
- validate_pde = create_flash_pde("powerpc/rtas/" VALIDATE_FLASH_NAME,
- &validate_flash_operations);
- if (validate_pde == NULL) {
- rc = -ENOMEM;
- goto cleanup;
- }
+ for (i = 0; i < ARRAY_SIZE(rtas_flash_files); i++) {
+ const struct rtas_flash_file *f = &rtas_flash_files[i];
+ int token;
- rc = initialize_flash_pde_data("ibm,validate-flash-image",
- sizeof(struct rtas_validate_flash_t),
- validate_pde);
- if (rc != 0)
- goto cleanup;
-
- manage_pde = create_flash_pde("powerpc/rtas/" MANAGE_FLASH_NAME,
- &manage_flash_operations);
- if (manage_pde == NULL) {
- rc = -ENOMEM;
- goto cleanup;
- }
+ if (!proc_create(f->filename, S_IRUSR | S_IWUSR, NULL, &f->fops))
+ goto enomem;
- rc = initialize_flash_pde_data("ibm,manage-flash-image",
- sizeof(struct rtas_manage_flash_t),
- manage_pde);
- if (rc != 0)
- 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;
+ }
rtas_flash_term_hook = rtas_flash_firmware;
-
- flash_block_cache = kmem_cache_create("rtas_flash_cache",
- RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
- NULL);
- 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 (rtas_firmware_flash_list) {
@@ -807,13 +763,13 @@ static void __exit rtas_flash_cleanup(void)
rtas_firmware_flash_list = 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/smp.c b/arch/powerpc/kernel/smp.c
index 76bd9da..ee7ac5e 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 d0bafc0..cd6e19d 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/udbg.c b/arch/powerpc/kernel/udbg.c
index f974849..13b8670 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 bc77834..59f419b 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;
+}