* [PATCH 7/7] [v3] drivers/misc: introduce Freescale hypervisor management driver
From: Timur Tabi @ 2011-06-03 20:47 UTC (permalink / raw)
To: alan, arnd, kumar.gala, benh, greg, akpm, linuxppc-dev,
linux-kernel, linux-console
The Freescale hypervisor management driver provides several services to
drivers and applications related to the Freescale hypervisor:
1. An ioctl interface for querying and managing partitions
2. A file interface to reading incoming doorbells
3. An interrupt handler for shutting down the partition upon receiving the
shutdown doorbell from a manager partition
4. An interface for receiving callbacks when a managed partition shuts down.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
drivers/misc/Kconfig | 7 +
drivers/misc/Makefile | 1 +
drivers/misc/fsl_hypervisor.c | 954 ++++++++++++++++++++++++++++++++++++++++
include/linux/Kbuild | 1 +
include/linux/fsl_hypervisor.h | 214 +++++++++
5 files changed, 1177 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/fsl_hypervisor.c
create mode 100644 include/linux/fsl_hypervisor.h
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d80dcde..3e016b3 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -216,6 +216,13 @@ config ENCLOSURE_SERVICES
driver (SCSI/ATA) which supports enclosures
or a SCSI enclosure device (SES) to use these services.
+config FSL_HV_MANAGER
+ tristate "Freescale hypervisor management driver"
+ depends on FSL_SOC
+ help
+ This driver allows applications to communicate with the Freescale
+ Hypervisor.
+
config SGI_XP
tristate "Support communication between SGI SSIs"
depends on NET
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 848e846..d93bd76 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
+obj-$(CONFIG_FSL_HV_MANAGER) += fsl_hypervisor.o
obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
obj-$(CONFIG_SGI_XP) += sgi-xp/
obj-$(CONFIG_SGI_GRU) += sgi-gru/
diff --git a/drivers/misc/fsl_hypervisor.c b/drivers/misc/fsl_hypervisor.c
new file mode 100644
index 0000000..64d38379
--- /dev/null
+++ b/drivers/misc/fsl_hypervisor.c
@@ -0,0 +1,954 @@
+/*
+ * Freescale Hypervisor Management Driver
+
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * This driver contains functions to support the Freescale hypervisor.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/of.h>
+#include <linux/reboot.h>
+#include <linux/uaccess.h>
+#include <linux/notifier.h>
+
+#include <linux/io.h>
+#include <asm/fsl_hcalls.h>
+
+#include <linux/fsl_hypervisor.h>
+
+static BLOCKING_NOTIFIER_HEAD(failover_subscribers);
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_PARTITION_RESTART
+ *
+ * Restart a running partition
+ */
+static long ioctl_restart(struct fsl_hv_ioctl_restart __user *p)
+{
+ struct fsl_hv_ioctl_restart param;
+
+ /* Get the parameters from the user */
+ if (copy_from_user(¶m, p, sizeof(struct fsl_hv_ioctl_restart)))
+ return -EFAULT;
+
+ param.ret = fh_partition_restart(param.partition);
+
+ if (copy_to_user(&p->ret, ¶m.ret, sizeof(__u32)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_PARTITION_STATUS
+ *
+ * Query the status of a partition
+ */
+static long ioctl_status(struct fsl_hv_ioctl_status __user *p)
+{
+ struct fsl_hv_ioctl_status param;
+ u32 status;
+
+ /* Get the parameters from the user */
+ if (copy_from_user(¶m, p, sizeof(struct fsl_hv_ioctl_status)))
+ return -EFAULT;
+
+ param.ret = fh_partition_get_status(param.partition, &status);
+ if (!param.ret)
+ param.status = status;
+
+ if (copy_to_user(p, ¶m, sizeof(struct fsl_hv_ioctl_status)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_PARTITION_START
+ *
+ * Start a stopped partition.
+ */
+static long ioctl_start(struct fsl_hv_ioctl_start __user *p)
+{
+ struct fsl_hv_ioctl_start param;
+
+ /* Get the parameters from the user */
+ if (copy_from_user(¶m, p, sizeof(struct fsl_hv_ioctl_start)))
+ return -EFAULT;
+
+ param.ret = fh_partition_start(param.partition, param.entry_point,
+ param.load);
+
+ if (copy_to_user(&p->ret, ¶m.ret, sizeof(__u32)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_PARTITION_STOP
+ *
+ * Stop a running partition
+ */
+static long ioctl_stop(struct fsl_hv_ioctl_stop __user *p)
+{
+ struct fsl_hv_ioctl_stop param;
+
+ /* Get the parameters from the user */
+ if (copy_from_user(¶m, p, sizeof(struct fsl_hv_ioctl_stop)))
+ return -EFAULT;
+
+ param.ret = fh_partition_stop(param.partition);
+
+ if (copy_to_user(&p->ret, ¶m.ret, sizeof(__u32)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_MEMCPY
+ *
+ * The FH_MEMCPY hypercall takes an array of address/address/size structures
+ * to represent the data being copied. As a convenience to the user, this
+ * ioctl takes a user-create buffer and a pointer to a guest physically
+ * contiguous buffer in the remote partition, and creates the
+ * address/address/size array for the hypercall.
+ */
+static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
+{
+ struct fsl_hv_ioctl_memcpy param;
+
+ struct page **pages = NULL;
+ void *sg_list_unaligned = NULL;
+ struct fh_sg_list *sg_list = NULL;
+
+ unsigned int num_pages;
+ unsigned long lb_offset; /* Offset within a page of the local buffer */
+
+ unsigned int i;
+ long ret = 0;
+ int num_pinned; /* return value from get_user_pages() */
+ phys_addr_t remote_paddr; /* The next address in the remote buffer */
+ uint32_t count; /* The number of bytes left to copy */
+
+ /* Get the parameters from the user */
+ if (copy_from_user(¶m, p, sizeof(struct fsl_hv_ioctl_memcpy)))
+ return -EFAULT;
+
+ /* One partition must be local, the other must be remote. In other
+ words, if source and target are both -1, or are both not -1, then
+ return an error. */
+ if ((param.source == -1) == (param.target == -1))
+ return -EINVAL;
+
+ /*
+ * The array of pages returned by get_user_pages() covers only
+ * page-aligned memory. Since the user buffer is probably not
+ * page-aligned, we need to handle the discrepancy.
+ *
+ * We calculate the offset within a page of the S/G list, and make
+ * adjustments accordingly. This will result in a page list that looks
+ * like this:
+ *
+ * ---- <-- first page starts before the buffer
+ * | |
+ * |////|-> ----
+ * |////| | |
+ * ---- | |
+ * | |
+ * ---- | |
+ * |////| | |
+ * |////| | |
+ * |////| | |
+ * ---- | |
+ * | |
+ * ---- | |
+ * |////| | |
+ * |////| | |
+ * |////| | |
+ * ---- | |
+ * | |
+ * ---- | |
+ * |////| | |
+ * |////|-> ----
+ * | | <-- last page ends after the buffer
+ * ----
+ *
+ * The distance between the start of the first page and the start of the
+ * buffer is lb_offset. The hashed (///) areas are the parts of the
+ * page list that contain the actual buffer.
+ *
+ * The advantage of this approach is that the number of pages is
+ * equal to the number of entries in the S/G list that we give to the
+ * hypervisor.
+ */
+ lb_offset = param.local_vaddr & (PAGE_SIZE - 1);
+ num_pages = (param.count + lb_offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ /* Allocate the buffers we need */
+
+ /* pages is an array of struct page pointers that's initialized by
+ get_user_pages() */
+ pages = kzalloc(num_pages * sizeof(struct page *), GFP_KERNEL);
+ if (!pages) {
+ pr_debug("fsl-hv: could not allocate page list\n");
+ return -ENOMEM;
+ }
+
+ /* sg_list is the list of fh_sg_list objects that we pass to the
+ hypervisor */
+ sg_list_unaligned = kmalloc(num_pages * sizeof(struct fh_sg_list) +
+ sizeof(struct fh_sg_list) - 1, GFP_KERNEL);
+ if (!sg_list_unaligned) {
+ pr_debug("fsl-hv: could not allocate S/G list\n");
+ ret = -ENOMEM;
+ goto exit;
+ }
+ sg_list = PTR_ALIGN(sg_list_unaligned, sizeof(struct fh_sg_list));
+
+ /* Get the physical addresses of the source buffer */
+ down_read(¤t->mm->mmap_sem);
+ num_pinned = get_user_pages(current, current->mm,
+ param.local_vaddr - lb_offset, num_pages,
+ (param.source == -1) ? READ : WRITE,
+ 0, pages, NULL);
+ up_read(¤t->mm->mmap_sem);
+
+ if (num_pinned != num_pages) {
+ /* get_user_pages() failed */
+ pr_debug("fsl-hv: could not lock source buffer\n");
+ ret = (num_pinned < 0) ? num_pinned : -EFAULT;
+ goto exit;
+ }
+
+ /*
+ * Build the fh_sg_list[] array. The first page is special
+ * because it's misaligned.
+ */
+ if (param.source == -1) {
+ sg_list[0].source = page_to_phys(pages[0]) + lb_offset;
+ sg_list[0].target = param.remote_paddr;
+ } else {
+ sg_list[0].source = param.remote_paddr;
+ sg_list[0].target = page_to_phys(pages[0]) + lb_offset;
+ }
+ sg_list[0].size = min_t(uint64_t, param.count, PAGE_SIZE - lb_offset);
+
+ remote_paddr = param.remote_paddr + sg_list[0].size;
+ count = param.count - sg_list[0].size;
+
+ for (i = 1; i < num_pages; i++) {
+ if (param.source == -1) {
+ /* local to remote */
+ sg_list[i].source = page_to_phys(pages[i]);
+ sg_list[i].target = remote_paddr;
+ } else {
+ /* remote to local */
+ sg_list[i].source = remote_paddr;
+ sg_list[i].target = page_to_phys(pages[i]);
+ }
+ sg_list[i].size = min_t(uint64_t, count, PAGE_SIZE);
+
+ remote_paddr += sg_list[i].size;
+ count -= sg_list[i].size;
+ }
+
+ param.ret = fh_partition_memcpy(param.source, param.target,
+ virt_to_phys(sg_list), num_pages);
+
+exit:
+ if (pages) {
+ for (i = 0; i < num_pages; i++)
+ if (pages[i])
+ put_page(pages[i]);
+ }
+
+ kfree(sg_list_unaligned);
+ kfree(pages);
+
+ if (!ret)
+ if (copy_to_user(&p->ret, ¶m.ret, sizeof(__u32)))
+ return -EFAULT;
+
+ return ret;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_DOORBELL
+ *
+ * Ring a doorbell
+ */
+static long ioctl_doorbell(struct fsl_hv_ioctl_doorbell __user *p)
+{
+ struct fsl_hv_ioctl_doorbell param;
+
+ /* Get the parameters from the user */
+ if (copy_from_user(¶m, p, sizeof(struct fsl_hv_ioctl_doorbell)))
+ return -EFAULT;
+
+ param.ret = ev_doorbell_send(param.doorbell);
+
+ if (copy_to_user(&p->ret, ¶m.ret, sizeof(__u32)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
+{
+ struct fsl_hv_ioctl_prop param;
+ char __user *upath, *upropname;
+ void __user *upropval;
+ char *path = NULL, *propname = NULL;
+ void *propval = NULL;
+ int ret = 0;
+
+ /* Get the parameters from the user */
+ if (copy_from_user(¶m, p, sizeof(struct fsl_hv_ioctl_prop)))
+ return -EFAULT;
+
+ upath = (char __user *)(uintptr_t)param.path;
+ upropname = (char __user *)(uintptr_t)param.propname;
+ upropval = (void __user *)(uintptr_t)param.propval;
+
+ path = strndup_user(upath, FH_DTPROP_MAX_PATHLEN);
+ if (IS_ERR(path)) {
+ ret = PTR_ERR(path);
+ goto out;
+ }
+
+ propname = strndup_user(upropname, FH_DTPROP_MAX_PATHLEN);
+ if (IS_ERR(propname)) {
+ ret = PTR_ERR(propname);
+ goto out;
+ }
+
+ if (param.proplen > FH_DTPROP_MAX_PROPLEN) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ propval = kmalloc(param.proplen, GFP_KERNEL);
+ if (!propval) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (set) {
+ if (copy_from_user(propval, upropval, param.proplen)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ param.ret = fh_partition_set_dtprop(param.handle,
+ virt_to_phys(path),
+ virt_to_phys(propname),
+ virt_to_phys(propval),
+ param.proplen);
+ } else {
+ param.ret = fh_partition_get_dtprop(param.handle,
+ virt_to_phys(path),
+ virt_to_phys(propname),
+ virt_to_phys(propval),
+ ¶m.proplen);
+
+ if (param.ret == 0) {
+ if (copy_to_user(upropval, propval, param.proplen) ||
+ put_user(param.proplen, &p->proplen)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ }
+ }
+
+ if (put_user(param.ret, &p->ret))
+ ret = -EFAULT;
+
+out:
+ kfree(path);
+ kfree(propval);
+ kfree(propname);
+
+ return ret;
+}
+
+/*
+ * Ioctl main entry point
+ */
+static long fsl_hv_ioctl(struct file *file, unsigned int cmd,
+ unsigned long argaddr)
+{
+ void __user *arg = (void __user *)argaddr;
+ long ret;
+ size_t size;
+
+ /* Make sure the application is called the right driver. */
+ if (_IOC_TYPE(cmd) != 0) {
+ pr_debug("fsl-hv: ioctl type %u should be 0\n", _IOC_TYPE(cmd));
+ return -EINVAL;
+ }
+
+ /* Make sure the application set the direction flag correctly. */
+ if (_IOC_DIR(cmd) != (_IOC_READ | _IOC_WRITE)) {
+ pr_debug("fsl-hv: ioctl direction should be _IOWR\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Make sure the application is passing the right structure to us.
+ * For backwards compatibility with older applications, we only check
+ * if the size is too small, rather than unequal.
+ */
+
+ switch (_IOC_NR(cmd)) {
+ case FSL_HV_IOCTL_PARTITION_RESTART:
+ size = sizeof(struct fsl_hv_ioctl_restart);
+ if (_IOC_SIZE(cmd) < size)
+ goto size_error;
+ ret = ioctl_restart(arg);
+ break;
+ case FSL_HV_IOCTL_PARTITION_GET_STATUS:
+ size = sizeof(struct fsl_hv_ioctl_status);
+ if (_IOC_SIZE(cmd) < size)
+ goto size_error;
+ ret = ioctl_status(arg);
+ break;
+ case FSL_HV_IOCTL_PARTITION_START:
+ size = sizeof(struct fsl_hv_ioctl_start);
+ if (_IOC_SIZE(cmd) < size)
+ goto size_error;
+ ret = ioctl_start(arg);
+ break;
+ case FSL_HV_IOCTL_PARTITION_STOP:
+ size = sizeof(struct fsl_hv_ioctl_stop);
+ if (_IOC_SIZE(cmd) < size)
+ goto size_error;
+ ret = ioctl_stop(arg);
+ break;
+ case FSL_HV_IOCTL_MEMCPY:
+ size = sizeof(struct fsl_hv_ioctl_memcpy);
+ if (_IOC_SIZE(cmd) < size)
+ goto size_error;
+ ret = ioctl_memcpy(arg);
+ break;
+ case FSL_HV_IOCTL_DOORBELL:
+ size = sizeof(struct fsl_hv_ioctl_doorbell);
+ if (_IOC_SIZE(cmd) < size)
+ goto size_error;
+ ret = ioctl_doorbell(arg);
+ break;
+ case FSL_HV_IOCTL_GETPROP:
+ size = sizeof(struct fsl_hv_ioctl_prop);
+ if (_IOC_SIZE(cmd) < size)
+ goto size_error;
+ ret = ioctl_dtprop(arg, 0);
+ break;
+ case FSL_HV_IOCTL_SETPROP:
+ size = sizeof(struct fsl_hv_ioctl_prop);
+ if (_IOC_SIZE(cmd) < size)
+ goto size_error;
+ ret = ioctl_dtprop(arg, 1);
+ break;
+ default:
+ pr_debug("fsl-hv: unknown ioctl %u\n", _IOC_NR(cmd));
+ return -ENOTTY;
+ }
+
+ return ret;
+
+size_error:
+ pr_debug("fsl-hv: ioctl %u parameter size %u should be %zu\n",
+ _IOC_NR(cmd), _IOC_SIZE(cmd), size);
+ return -EINVAL;
+}
+
+/* Linked list of processes that have us open */
+static struct list_head db_list;
+
+/* spinlock for db_list */
+static DEFINE_SPINLOCK(db_list_lock);
+
+/* The size of the doorbell event queue. This must be a power of two. */
+#define QSIZE 16
+
+/* Returns the next head/tail pointer, wrapping around the queue if necessary */
+#define nextp(x) (((x) + 1) & (QSIZE - 1))
+
+/* Per-open data structure */
+struct doorbell_queue {
+ struct list_head list;
+ spinlock_t lock;
+ wait_queue_head_t wait;
+ unsigned int head;
+ unsigned int tail;
+ uint32_t q[QSIZE];
+};
+
+/* Linked list of ISRs that we registered */
+struct list_head isr_list;
+
+/* Per-ISR data structure */
+struct doorbell_isr {
+ struct list_head list;
+ unsigned int irq;
+ uint32_t doorbell; /* The doorbell handle */
+ uint32_t partition; /* The partition handle, if used */
+};
+
+/*
+ * Add a doorbell to all of the doorbell queues
+ */
+static void fsl_hv_queue_doorbell(uint32_t doorbell)
+{
+ struct doorbell_queue *dbq;
+ unsigned long flags;
+
+ /* Prevent another core from modifying db_list */
+ spin_lock_irqsave(&db_list_lock, flags);
+
+ list_for_each_entry(dbq, &db_list, list) {
+ if (dbq->head != nextp(dbq->tail)) {
+ dbq->q[dbq->tail] = doorbell;
+ /* This memory barrier eliminates the need to grab
+ * the spinlock for dbq. */
+ smp_wmb();
+ dbq->tail = nextp(dbq->tail);
+ wake_up_interruptible(&dbq->wait);
+ }
+ }
+
+ spin_unlock_irqrestore(&db_list_lock, flags);
+}
+
+/*
+ * Interrupt handler for all doorbells
+ *
+ * We use the same interrupt handler for all doorbells. Whenever a doorbell
+ * is rung, and we receive an interrupt, we just put the handle for that
+ * doorbell (passed to us as *data) into all of the queues.
+ */
+static irqreturn_t fsl_hv_isr(int irq, void *data)
+{
+ fsl_hv_queue_doorbell((uintptr_t) data);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * State change thread function
+ *
+ * The state change notification arrives in an interrupt, but we can't call
+ * blocking_notifier_call_chain() in an interrupt handler. We could call
+ * atomic_notifier_call_chain(), but that would require the clients' call-back
+ * function to run in interrupt context. Since we don't want to impose that
+ * restriction on the clients, we use a threaded IRQ to process the
+ * notification in kernel context.
+ */
+static irqreturn_t fsl_hv_state_change_thread(int irq, void *data)
+{
+ struct doorbell_isr *dbisr = data;
+
+ blocking_notifier_call_chain(&failover_subscribers, dbisr->partition,
+ NULL);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Interrupt handler for state-change doorbells
+ */
+static irqreturn_t fsl_hv_state_change_isr(int irq, void *data)
+{
+ unsigned int status;
+ struct doorbell_isr *dbisr = data;
+ int ret;
+
+ /* It's still a doorbell, so add it to all the queues */
+ fsl_hv_queue_doorbell(dbisr->doorbell);
+
+ /* Determine the new state, and if it's stopped, notify the clients. */
+ ret = fh_partition_get_status(dbisr->partition, &status);
+ if (!ret && (status == FH_PARTITION_STOPPED))
+ return IRQ_WAKE_THREAD;
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * fsl_hv_poll - returns a bitmask indicating whether a read will block
+ *
+ * @return unsigned int
+ */
+static unsigned int fsl_hv_poll(struct file *filp, struct poll_table_struct *p)
+{
+ struct doorbell_queue *dbq = filp->private_data;
+ unsigned long flags;
+ unsigned int mask;
+
+ spin_lock_irqsave(&dbq->lock, flags);
+
+ poll_wait(filp, &dbq->wait, p);
+ mask = (dbq->head == dbq->tail) ? 0 : (POLLIN | POLLRDNORM);
+
+ spin_unlock_irqrestore(&dbq->lock, flags);
+
+ return mask;
+}
+
+/**
+ * fsl_hv_read - return the handles for any incoming doorbells
+ *
+ * If there are doorbell handles in the queue for this open instance, then
+ * return them to the caller as an array of 32-bit integers. Otherwise,
+ * block until there is at least one handle to return.
+ */
+static ssize_t fsl_hv_read(struct file *filp, char __user *buf, size_t len,
+ loff_t *off)
+{
+ struct doorbell_queue *dbq = filp->private_data;
+ uint32_t __user *p = (uint32_t __user *) buf; /* for put_user() */
+ unsigned long flags;
+ ssize_t count = 0;
+
+ /* Make sure we stop when the user buffer is full. */
+ while (len >= sizeof(uint32_t)) {
+ uint32_t dbell; /* Local copy of doorbell queue data */
+
+ spin_lock_irqsave(&dbq->lock, flags);
+
+ /* If the queue is empty, then either we're done or we need
+ * to block. If the application specified O_NONBLOCK, then
+ * we return the appropriate error code.
+ */
+ if (dbq->head == dbq->tail) {
+ spin_unlock_irqrestore(&dbq->lock, flags);
+ if (count)
+ break;
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ if (wait_event_interruptible(dbq->wait,
+ dbq->head != dbq->tail))
+ return -ERESTARTSYS;
+ continue;
+ }
+
+ /* Even though we have an smp_wmb() in the ISR, the core
+ * might speculatively execute the "dbell = ..." below while
+ * it's evaluating the if-statement above. In that case, the
+ * value put into dbell could be stale if the core accepts the
+ * speculation. To prevent that, we need a read memory barrier
+ * here as well.
+ */
+ smp_rmb();
+
+ /* Copy the data to a temporary local buffer, because
+ * we can't call copy_to_user() from inside a spinlock
+ */
+ dbell = dbq->q[dbq->head];
+ dbq->head = nextp(dbq->head);
+
+ spin_unlock_irqrestore(&dbq->lock, flags);
+
+ if (put_user(dbell, p))
+ return -EFAULT;
+ p++;
+ count += sizeof(uint32_t);
+ len -= sizeof(uint32_t);
+ }
+
+ return count;
+}
+
+/**
+ * fsl_hv_open - open the driver
+ *
+ * Open the driver and prepare for reading doorbells.
+ *
+ * Every time an application opens the driver, we create a doorbell queue
+ * for that file handle. This queue is used for any incoming doorbells.
+ */
+static int fsl_hv_open(struct inode *inode, struct file *filp)
+{
+ struct doorbell_queue *dbq;
+ unsigned long flags;
+ int ret = 0;
+
+ dbq = kzalloc(sizeof(struct doorbell_queue), GFP_KERNEL);
+ if (!dbq) {
+ pr_err("fsl-hv: out of memory\n");
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&dbq->lock);
+ init_waitqueue_head(&dbq->wait);
+
+ spin_lock_irqsave(&db_list_lock, flags);
+ list_add(&dbq->list, &db_list);
+ spin_unlock_irqrestore(&db_list_lock, flags);
+
+ filp->private_data = dbq;
+
+ return ret;
+}
+
+/**
+ * fsl_hv_close - close the driver
+ */
+static int fsl_hv_close(struct inode *inode, struct file *filp)
+{
+ struct doorbell_queue *dbq = filp->private_data;
+ unsigned long flags;
+
+ int ret = 0;
+
+ spin_lock_irqsave(&db_list_lock, flags);
+ list_del(&dbq->list);
+ spin_unlock_irqrestore(&db_list_lock, flags);
+
+ kfree(dbq);
+
+ return ret;
+}
+
+static const struct file_operations fsl_hv_fops = {
+ .owner = THIS_MODULE,
+ .open = fsl_hv_open,
+ .release = fsl_hv_close,
+ .poll = fsl_hv_poll,
+ .read = fsl_hv_read,
+ .unlocked_ioctl = fsl_hv_ioctl,
+};
+
+static struct miscdevice fsl_hv_misc_dev = {
+ MISC_DYNAMIC_MINOR,
+ "fsl-hv",
+ &fsl_hv_fops
+};
+
+static irqreturn_t fsl_hv_shutdown_isr(int irq, void *data)
+{
+ orderly_poweroff(false);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * get_parent_handle -- returns the handle of the parent of the given node
+ *
+ * The handle is the value of the 'reg' property
+ */
+static int get_parent_handle(struct device_node *np)
+{
+ struct device_node *parent;
+ const uint32_t *prop;
+ int len;
+
+ parent = of_get_parent(np);
+ if (!parent)
+ /* It's not really possible for this to fail */
+ return -ENODEV;
+
+ prop = of_get_property(parent, "reg", &len);
+ of_node_put(parent);
+
+ if (!prop || (len != sizeof(uint32_t)))
+ /* This can happen only if the node is malformed */
+ return -ENODEV;
+
+ return *prop;
+}
+
+/**
+ * fsl_hv_failover_register -- register a callback for failover events
+ *
+ * This function is called by device drivers to register their callback
+ * functions for fail-over events.
+ */
+int fsl_hv_failover_register(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&failover_subscribers, nb);
+}
+EXPORT_SYMBOL(fsl_hv_failover_register);
+
+/**
+ * fsl_hv_failover_unregister -- unregister a callback for failover events
+ */
+int fsl_hv_failover_unregister(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&failover_subscribers, nb);
+}
+EXPORT_SYMBOL(fsl_hv_failover_unregister);
+
+/**
+ * has_fsl_hypervisor - return TRUE if we're running under FSL hypervisor
+ *
+ * This function checks to see if we're running under the Freescale
+ * hypervisor, and returns zero if we're not, or non-zero if we are.
+ *
+ * First, it checks if MSR[GS]==1, which means we're running under some
+ * hypervisor. Then it checks if there is a hypervisor node in the device
+ * tree. Currently, that means there needs to be a node in the root called
+ * "hypervisor" and which has a property named "fsl,hv-version".
+ */
+static int has_fsl_hypervisor(void)
+{
+ struct device_node *node;
+ int ret;
+
+ if (!(mfmsr() & MSR_GS))
+ return 0;
+
+ node = of_find_node_by_path("/hypervisor");
+ if (!node)
+ return 0;
+
+ ret = of_find_property(node, "fsl,hv-version", NULL) != NULL;
+
+ of_node_put(node);
+
+ return ret;
+}
+
+/**
+ * fsl_hypervisor_init: Freescale hypervisor management driver init
+ *
+ * This function is called when this module is loaded.
+ *
+ * Register ourselves as a miscellaneous driver. This will register the
+ * fops structure and create the right sysfs entries for udev.
+ */
+static int __init fsl_hypervisor_init(void)
+{
+ struct device_node *np;
+ struct doorbell_isr *dbisr, *n;
+ int ret;
+
+ pr_info("Freescale hypervisor management driver\n");
+
+ if (!has_fsl_hypervisor()) {
+ pr_info("fsl-hv: no hypervisor found\n");
+ return -ENODEV;
+ }
+
+ ret = misc_register(&fsl_hv_misc_dev);
+ if (ret) {
+ pr_err("fsl-hv: cannot register device\n");
+ return ret;
+ }
+
+ INIT_LIST_HEAD(&db_list);
+ INIT_LIST_HEAD(&isr_list);
+
+ for_each_compatible_node(np, NULL, "epapr,hv-receive-doorbell") {
+ unsigned int irq;
+ const uint32_t *handle;
+
+ handle = of_get_property(np, "interrupts", NULL);
+ irq = irq_of_parse_and_map(np, 0);
+ if (!handle || (irq == NO_IRQ)) {
+ pr_err("fsl-hv: no 'interrupts' property in %s node\n",
+ np->full_name);
+ continue;
+ }
+
+ dbisr = kzalloc(sizeof(*dbisr), GFP_KERNEL);
+ if (!dbisr)
+ goto out_of_memory;
+
+ dbisr->irq = irq;
+ dbisr->doorbell = *handle;
+
+ if (of_device_is_compatible(np, "fsl,hv-shutdown-doorbell")) {
+ /* The shutdown doorbell gets its own ISR */
+ ret = request_irq(irq, fsl_hv_shutdown_isr, 0,
+ np->name, NULL);
+ } else if (of_device_is_compatible(np,
+ "fsl,hv-state-change-doorbell")) {
+ /* The state change doorbell triggers a notification if
+ * the state of the managed partition changes to
+ * "stopped". We need a separate interrupt handler for
+ * that, and we also need to know the handle of the
+ * target partition, not just the handle of the
+ * doorbell.
+ */
+ dbisr->partition = ret = get_parent_handle(np);
+ if (ret < 0) {
+ pr_err("fsl-hv: node %s has missing or "
+ "malformed parent\n", np->full_name);
+ kfree(dbisr);
+ continue;
+ }
+ ret = request_threaded_irq(irq, fsl_hv_state_change_isr,
+ fsl_hv_state_change_thread,
+ 0, np->name, dbisr);
+ } else
+ ret = request_irq(irq, fsl_hv_isr, 0, np->name, dbisr);
+
+ if (ret < 0) {
+ pr_err("fsl-hv: could not request irq %u for node %s\n",
+ irq, np->full_name);
+ kfree(dbisr);
+ continue;
+ }
+
+ list_add(&dbisr->list, &isr_list);
+
+ pr_info("fsl-hv: registered handler for doorbell %u\n",
+ *handle);
+ }
+
+ return 0;
+
+out_of_memory:
+ list_for_each_entry_safe(dbisr, n, &isr_list, list) {
+ free_irq(dbisr->irq, dbisr);
+ list_del(&dbisr->list);
+ kfree(dbisr);
+ }
+
+ misc_deregister(&fsl_hv_misc_dev);
+
+ return -ENOMEM;
+}
+
+/**
+ * fsl_hypervisor_exit: Freescale hypervisor management driver termination
+ *
+ * This function is called when this driver is unloaded.
+ */
+static void __exit fsl_hypervisor_exit(void)
+{
+ struct doorbell_isr *dbisr, *n;
+
+ list_for_each_entry_safe(dbisr, n, &isr_list, list) {
+ free_irq(dbisr->irq, dbisr);
+ list_del(&dbisr->list);
+ kfree(dbisr);
+ }
+
+ misc_deregister(&fsl_hv_misc_dev);
+}
+
+module_init(fsl_hypervisor_init);
+module_exit(fsl_hypervisor_exit);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale hypervisor management driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 75cf611..68c341a 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -134,6 +134,7 @@ header-y += firewire-cdev.h
header-y += firewire-constants.h
header-y += flat.h
header-y += fs.h
+header-y += fsl_hypervisor.h
header-y += fuse.h
header-y += futex.h
header-y += gameport.h
diff --git a/include/linux/fsl_hypervisor.h b/include/linux/fsl_hypervisor.h
new file mode 100644
index 0000000..4d1e11a
--- /dev/null
+++ b/include/linux/fsl_hypervisor.h
@@ -0,0 +1,214 @@
+/*
+ * Freescale hypervisor ioctl interface
+ *
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of this
+ * software, even if advised of the possibility of such damage.
+ *
+ * This file is used by the Freescale hypervisor management driver. It can
+ * also be included by applications that need to communicate with the driver
+ * via the ioctl interface.
+ */
+
+#ifndef FSL_HYPERVISOR_H
+#define FSL_HYPERVISOR_H
+
+#include <linux/types.h>
+
+/**
+ * struct fsl_hv_ioctl_restart: restart a partition
+ * @ret: return error code from the hypervisor
+ * @partition: the ID of the partition to restart, or -1 for the
+ * calling partition
+ *
+ * Used by FSL_HV_IOCTL_PARTITION_RESTART
+ */
+struct fsl_hv_ioctl_restart {
+ __u32 ret;
+ __u32 partition;
+};
+
+/**
+ * struct fsl_hv_ioctl_status: get a partition's status
+ * @ret: return error code from the hypervisor
+ * @partition: the ID of the partition to query, or -1 for the
+ * calling partition
+ * @status: The returned status of the partition
+ *
+ * Used by FSL_HV_IOCTL_PARTITION_GET_STATUS
+ *
+ * Values of 'status':
+ * 0 = Stopped
+ * 1 = Running
+ * 2 = Starting
+ * 3 = Stopping
+ */
+struct fsl_hv_ioctl_status {
+ __u32 ret;
+ __u32 partition;
+ __u32 status;
+};
+
+/**
+ * struct fsl_hv_ioctl_start: start a partition
+ * @ret: return error code from the hypervisor
+ * @partition: the ID of the partition to control
+ * @entry_point: The offset within the guest IMA to start execution
+ * @load: If non-zero, reload the partition's images before starting
+ *
+ * Used by FSL_HV_IOCTL_PARTITION_START
+ */
+struct fsl_hv_ioctl_start {
+ __u32 ret;
+ __u32 partition;
+ __u32 entry_point;
+ __u32 load;
+};
+
+/**
+ * struct fsl_hv_ioctl_stop: stop a partition
+ * @ret: return error code from the hypervisor
+ * @partition: the ID of the partition to stop, or -1 for the calling
+ * partition
+ *
+ * Used by FSL_HV_IOCTL_PARTITION_STOP
+ */
+struct fsl_hv_ioctl_stop {
+ __u32 ret;
+ __u32 partition;
+};
+
+/**
+ * struct fsl_hv_ioctl_memcpy: copy memory between partitions
+ * @ret: return error code from the hypervisor
+ * @source: the partition ID of the source partition, or -1 for this
+ * partition
+ * @target: the partition ID of the target partition, or -1 for this
+ * partition
+ * @local_addr: user-space virtual address of a buffer in the local
+ * partition
+ * @remote_addr: guest physical address of a buffer in the
+ * remote partition
+ * @count: the number of bytes to copy. Both the local and remote
+ * buffers must be at least 'count' bytes long
+ *
+ * Used by FSL_HV_IOCTL_MEMCPY
+ *
+ * The 'local' partition is the partition that calls this ioctl. The
+ * 'remote' partition is a different partition. The data is copied from
+ * the 'source' paritition' to the 'target' partition.
+ *
+ * The buffer in the remote partition must be guest physically
+ * contiguous.
+ *
+ * This ioctl does not support copying memory between two remote
+ * partitions or within the same partition, so either 'source' or
+ * 'target' (but not both) must be -1. In other words, either
+ *
+ * source == local and target == remote
+ * or
+ * source == remote and target == local
+ */
+struct fsl_hv_ioctl_memcpy {
+ __u32 ret;
+ __u32 source;
+ __u32 target;
+ __u64 local_vaddr;
+ __u64 remote_paddr;
+ __u64 count;
+};
+
+/**
+ * struct fsl_hv_ioctl_doorbell: ring a doorbell
+ * @ret: return error code from the hypervisor
+ * @doorbell: the handle of the doorbell to ring doorbell
+ *
+ * Used by FSL_HV_IOCTL_DOORBELL
+ */
+struct fsl_hv_ioctl_doorbell {
+ __u32 ret;
+ __u32 doorbell;
+};
+
+/**
+ * struct fsl_hv_ioctl_prop: get/set a device tree property
+ * @ret: return error code from the hypervisor
+ * @handle: handle of partition whose tree to access
+ * @path: virtual address of path name of node to access
+ * @propname: virtual address of name of property to access
+ * @propval: virtual address of property data buffer
+ * @proplen: Size of property data buffer
+ *
+ * Used by FSL_HV_IOCTL_DOORBELL
+ */
+struct fsl_hv_ioctl_prop {
+ __u32 ret;
+ __u32 handle;
+ __u64 path;
+ __u64 propname;
+ __u64 propval;
+ __u32 proplen;
+};
+
+/*
+ * ioctl commands.
+ */
+enum {
+ FSL_HV_IOCTL_PARTITION_RESTART = 1, /* Boot another partition */
+ FSL_HV_IOCTL_PARTITION_GET_STATUS = 2, /* Boot another partition */
+ FSL_HV_IOCTL_PARTITION_START = 3, /* Boot another partition */
+ FSL_HV_IOCTL_PARTITION_STOP = 4, /* Stop this or another partition */
+ FSL_HV_IOCTL_MEMCPY = 5, /* Copy data from one partition to another */
+ FSL_HV_IOCTL_DOORBELL = 6, /* Ring a doorbell */
+
+ /* Get a property from another guest's device tree */
+ FSL_HV_IOCTL_GETPROP = 7,
+
+ /* Set a property in another guest's device tree */
+ FSL_HV_IOCTL_SETPROP = 8,
+};
+
+#ifdef __KERNEL__
+
+/**
+ * fsl_hv_event_register -- register a callback for failover events
+ *
+ * This function is called by device drivers to register their callback
+ * functions for fail-over events.
+ */
+int fsl_hv_failover_register(struct notifier_block *nb);
+
+/**
+ * fsl_hv_event_unregister -- unregister a callback for failover events
+ */
+int fsl_hv_failover_unregister(struct notifier_block *nb);
+
+#endif
+
+#endif
--
1.7.3.4
^ permalink raw reply related
* Re: Hooking up SM501 on TQM5200 (MPC5200) board via device tree?
From: Grant Likely @ 2011-06-03 20:51 UTC (permalink / raw)
To: Josh Triplett; +Cc: devicetree-discuss, linuxppc-dev, linux-kernel, Jamey Sharp
In-Reply-To: <20110601050659.GA7789@leaf>
On Tue, May 31, 2011 at 10:07:01PM -0700, Josh Triplett wrote:
> We have a TQM5200 board, which has GPIO lines hooked up to an SM501.
> I've managed to come up with the following patch to the tqm5200 device
> tree, which manages to convince the sm501 driver to attach an sm501-fb:
>
> --- a/arch/powerpc/boot/dts/tqm5200.dts 2009-11-23 03:13:27.000000000 -0800
> +++ b/arch/powerpc/boot/dts/tqm5200.dts 2011-05-31 22:00:28.000580627 -0700
> @@ -177,7 +177,8 @@
> compatible = "fsl,mpc5200-lpb","simple-bus";
> #address-cells = <2>;
> #size-cells = <1>;
> - ranges = <0 0 0xfc000000 0x02000000>;
> + ranges = <0 0 0xfc000000 0x02000000
> + 1 0 0xe0000000 0x04000000>;
>
> flash@0,0 {
> compatible = "cfi-flash";
> @@ -187,6 +188,13 @@
> #size-cells = <1>;
> #address-cells = <1>;
> };
> +
> + display@1,0 {
> + compatible = "smi,sm501";
> + reg = <1 0x00000000 0x00800000
> + 1 0x03e00000 0x00200000>;
> + interrupts = <1 1 3>;
> + };
> };
>
> pci@f0000d00 {
>
>
> However, this doesn't hook up the sm501-gpio bits. Reading the sm501
> driver carefully, it looks like it only hooks up sm501-gpio if it has
> platform_data available which sets some flags and other information.
> So, if I understand correctly, hooking up sm501-gpio would require
> adding functionality the driver to get the GPIO information from the
> device tree in preference to the platform_data, if available, and fall
> back to the platform_data for existing users?
>
> What should the necessary device tree properties look like to replace
> sm501_initdata?
>
> - Josh Triplett
You need to look at Documentation/devicetree/bindings/gpio/gpio.txt.
Also, you need to add bits to the sm501-gpio driver to register a
dynamically allocated range of gpio pins and to populate the
gpiochip->of_node pointer. If that points at a device tree node, then
the core code will take care of setting up translation for you.
g.
^ permalink raw reply
* Re: [RFT][PATCH 3.0] ssb: fix PCI(e) driver regression causing oops on PCI cards
From: Rafał Miłecki @ 2011-06-03 21:24 UTC (permalink / raw)
To: linux-wireless, Michael Büsch, John W. Linville,
Andreas Schwab
Cc: linuxppc-dev, b43-dev
In-Reply-To: <BANLkTinSdDZv7gshYfi4mK5N9K-E7vk3Yw@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 549 bytes --]
On Jun 1, 2011 9:14 PM, "Rafał Miłecki" <zajec5@gmail.com> wrote:
>
> 2011/6/1 Rafał Miłecki <zajec5@gmail.com>:
> > We were incorrectly executing PCIe specific workarounds on PCI cards.
> > This resulted in:
> > Machine check in kernel mode.
> > Caused by (from SRR1=149030): Transfer error ack signal
> > Oops: Machine check, sig: 7 [#1]
>
> John, I've tested this patch myself on my PCI BCM4318, including
> checking for 0xFFFFFFFF reads in MMIO dumps.
>
> The patch is correct, please take it for 3.0.
Ping, ping, ping John.
[-- Attachment #2: Type: text/html, Size: 768 bytes --]
^ permalink raw reply
* [PATCH -v2] Audit: push audit success and retcode into arch ptrace.h
From: Eric Paris @ 2011-06-03 22:04 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mips, linux-ia64, linux-sh, heiko.carstens, paulus, ralf,
hpa, sparclinux, linux-s390, richard, x86, mingo, fenghua.yu,
user-mode-linux-devel, microblaze-uclinux, jdike, viro, tglx,
monstr, tony.luck, oleg, eparis, lethal, schwidefsky, linux390,
akpm, linuxppc-dev, davem
The audit system previously expected arches calling to audit_syscall_exit to
supply as arguments if the syscall was a success and what the return code was.
Audit also provides a helper AUDITSC_RESULT which was supposed to simplify things
by converting from negative retcodes to an audit internal magic value stating
success or failure. This helper was wrong and could indicate that a valid
pointer returned to userspace was a failed syscall. The fix is to fix the
layering foolishness. We now pass audit_syscall_exit a struct pt_reg and it
in turns calls back into arch code to collect the return value and to
determine if the syscall was a success or failure. We also define a generic
is_syscall_success() macro which determines success/failure based on if the
value is < -MAX_ERRNO. This works for arches like x86 which do not use a
separate mechanism to indicate syscall failure.
In arch/sh/kernel/ptrace_64.c I see that we were using regs[9] in the old
audit code as the return value. But the ptrace_64.h code defined the macro
regs_return_value() as regs[3]. I have no idea which one is correct, but this
patch now uses the regs_return_value() function, so it now uses regs[3].
We make both the is_syscall_success() and regs_return_value() static inlines
instead of macros. The reason is because the audit function must take a void*
for the regs. (uml calls theirs struct uml_pt_regs instead of just struct
pt_regs so audit_syscall_exit can't take a struct pt_regs). Since the audit
function takes a void* we need to use static inlines to cast it back to the
arch correct structure to dereference it.
The other major change is that on some arches, like ia64, we change
regs_return_value() to give us the negative value on syscall failure. The
only other user of this macro, kretprobe_example.c, won't notice and it makes
the value signed consistently for the audit functions across all archs.
Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Acked-by: H. Peter Anvin <hpa@zytor.com> [for x86 portion]
---
arch/ia64/include/asm/ptrace.h | 13 ++++++++++++-
arch/ia64/kernel/ptrace.c | 9 +--------
arch/microblaze/include/asm/ptrace.h | 5 +++++
arch/microblaze/kernel/ptrace.c | 3 +--
arch/mips/include/asm/ptrace.h | 14 +++++++++++++-
arch/mips/kernel/ptrace.c | 4 +---
arch/powerpc/include/asm/ptrace.h | 10 +++++++++-
arch/powerpc/kernel/ptrace.c | 4 +---
arch/s390/include/asm/ptrace.h | 6 +++++-
arch/s390/kernel/ptrace.c | 4 +---
arch/sh/include/asm/ptrace_32.h | 5 ++++-
arch/sh/include/asm/ptrace_64.h | 5 ++++-
arch/sh/kernel/ptrace_32.c | 4 +---
arch/sh/kernel/ptrace_64.c | 4 +---
arch/sparc/include/asm/ptrace.h | 10 +++++++++-
arch/sparc/kernel/ptrace_64.c | 11 +----------
arch/um/kernel/ptrace.c | 4 ++--
arch/um/sys-i386/shared/sysdep/ptrace.h | 4 ++++
arch/um/sys-x86_64/shared/sysdep/ptrace.h | 4 ++++
arch/x86/ia32/ia32entry.S | 10 +++++-----
arch/x86/kernel/entry_32.S | 8 ++++----
arch/x86/kernel/entry_64.S | 10 +++++-----
arch/x86/kernel/ptrace.c | 3 +--
arch/x86/kernel/vm86_32.c | 4 ++--
include/linux/audit.h | 22 ++++++++++++++--------
include/linux/ptrace.h | 10 ++++++++++
kernel/auditsc.c | 16 ++++++++++++----
27 files changed, 132 insertions(+), 74 deletions(-)
diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h
index 7ae9c3f..801ee1a 100644
--- a/arch/ia64/include/asm/ptrace.h
+++ b/arch/ia64/include/asm/ptrace.h
@@ -246,7 +246,18 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
return regs->ar_bspstore;
}
-#define regs_return_value(regs) ((regs)->r8)
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+ return regs->r10 != -1;
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+ if (is_syscall_success(regs))
+ return regs->r8;
+ else
+ return -regs->r8;
+}
/* Conserve space in histogram by encoding slot bits in address
* bits 2 and 3 rather than bits 0 and 1.
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 8848f43..2c15408 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1268,14 +1268,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
{
int step;
- if (unlikely(current->audit_context)) {
- int success = AUDITSC_RESULT(regs.r10);
- long result = regs.r8;
-
- if (success != AUDITSC_SUCCESS)
- result = -result;
- audit_syscall_exit(success, result);
- }
+ audit_syscall_exit(®s);
step = test_thread_flag(TIF_SINGLESTEP);
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h
index d9b6630..bec1c74 100644
--- a/arch/microblaze/include/asm/ptrace.h
+++ b/arch/microblaze/include/asm/ptrace.h
@@ -61,6 +61,11 @@ struct pt_regs {
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)
+static inline long regs_return_value(struct pt_regs *regs)
+{
+ return regs->r3;
+}
+
void show_regs(struct pt_regs *);
#else /* __KERNEL__ */
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 6a8e0cc..9747fa5 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -159,8 +159,7 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
int step;
- if (unlikely(current->audit_context))
- audit_syscall_exit(AUDITSC_RESULT(regs->r3), regs->r3);
+ audit_syscall_exit(regs);
step = test_thread_flag(TIF_SINGLESTEP);
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index de39b1f..7d40950 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -137,7 +137,19 @@ extern int ptrace_set_watch_regs(struct task_struct *child,
*/
#define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER)
-#define regs_return_value(_regs) ((_regs)->regs[2])
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+ return !regs->regs[7];
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+ if (is_syscall_success(regs))
+ return regs->regs[2];
+ else
+ return -regs->regs[2];
+}
+
#define instruction_pointer(regs) ((regs)->cp0_epc)
#define profile_pc(regs) instruction_pointer(regs)
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 4e6ea1f..ab0f196 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -572,9 +572,7 @@ out:
*/
asmlinkage void syscall_trace_leave(struct pt_regs *regs)
{
- if (unlikely(current->audit_context))
- audit_syscall_exit(AUDITSC_RESULT(regs->regs[7]),
- -regs->regs[2]);
+ audit_syscall_exit(regs);
if (!(current->ptrace & PT_PTRACED))
return;
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 48223f9..679aa7b 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -86,7 +86,15 @@ struct pt_regs {
#define instruction_pointer(regs) ((regs)->nip)
#define user_stack_pointer(regs) ((regs)->gpr[1])
#define kernel_stack_pointer(regs) ((regs)->gpr[1])
-#define regs_return_value(regs) ((regs)->gpr[3])
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+ return !(regs->ccr & 0x10000000);
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+ return regs->gpr[3];
+}
#ifdef CONFIG_SMP
extern unsigned long profile_pc(struct pt_regs *regs);
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index cb22024..d801ab7 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1741,9 +1741,7 @@ void do_syscall_trace_leave(struct pt_regs *regs)
{
int step;
- if (unlikely(current->audit_context))
- audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
- regs->result);
+ audit_syscall_exit(regs);
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_exit(regs, regs->result);
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 9ad628a..df397e8 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -544,9 +544,13 @@ extern void show_regs(struct pt_regs * regs);
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
#define user_stack_pointer(regs)((regs)->gprs[15])
-#define regs_return_value(regs)((regs)->gprs[2])
#define profile_pc(regs) instruction_pointer(regs)
+static inline long regs_return_value(struct pt_regs *regs)
+{
+ return regs->gprs[2];
+}
+
int regs_query_register_offset(const char *name);
const char *regs_query_register_name(unsigned int offset);
unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset);
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index ef86ad2..d4d6fcb 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -753,9 +753,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
{
- if (unlikely(current->audit_context))
- audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
- regs->gprs[2]);
+ audit_syscall_exit(regs);
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_exit(regs, regs->gprs[2]);
diff --git a/arch/sh/include/asm/ptrace_32.h b/arch/sh/include/asm/ptrace_32.h
index 6c2239c..2d3e906 100644
--- a/arch/sh/include/asm/ptrace_32.h
+++ b/arch/sh/include/asm/ptrace_32.h
@@ -76,7 +76,10 @@ struct pt_dspregs {
#ifdef __KERNEL__
#define MAX_REG_OFFSET offsetof(struct pt_regs, tra)
-#define regs_return_value(_regs) ((_regs)->regs[0])
+static inline long regs_return_value(struct pt_regs *regs)
+{
+ return regs->regs[0];
+}
#endif /* __KERNEL__ */
diff --git a/arch/sh/include/asm/ptrace_64.h b/arch/sh/include/asm/ptrace_64.h
index bf9be77..eb3fcce 100644
--- a/arch/sh/include/asm/ptrace_64.h
+++ b/arch/sh/include/asm/ptrace_64.h
@@ -13,7 +13,10 @@ struct pt_regs {
#ifdef __KERNEL__
#define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7])
-#define regs_return_value(_regs) ((_regs)->regs[3])
+static inline long regs_return_value(struct pt_regs *regs)
+{
+ return regs->regs[3];
+}
#endif /* __KERNEL__ */
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 3d7b209..5fce97e 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -529,9 +529,7 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
int step;
- if (unlikely(current->audit_context))
- audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
- regs->regs[0]);
+ audit_syscall_exit(regs);
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_exit(regs, regs->regs[0]);
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c
index c8f9764..ba720d6 100644
--- a/arch/sh/kernel/ptrace_64.c
+++ b/arch/sh/kernel/ptrace_64.c
@@ -548,9 +548,7 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
int step;
- if (unlikely(current->audit_context))
- audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
- regs->regs[9]);
+ audit_syscall_exit(regs);
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_exit(regs, regs->regs[9]);
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index c7ad3fe..10f98ca 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -206,7 +206,15 @@ do { current_thread_info()->syscall_noerror = 1; \
#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
#define instruction_pointer(regs) ((regs)->tpc)
#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
-#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+ return !(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY));
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+ return regs->u_regs[UREG_I0];
+}
#ifdef CONFIG_SMP
extern unsigned long profile_pc(struct pt_regs *);
#else
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 96ee50a..c73c8c5 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -1086,17 +1086,8 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
asmlinkage void syscall_trace_leave(struct pt_regs *regs)
{
-#ifdef CONFIG_AUDITSYSCALL
- if (unlikely(current->audit_context)) {
- unsigned long tstate = regs->tstate;
- int result = AUDITSC_SUCCESS;
+ audit_syscall_exit(regs);
- if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
- result = AUDITSC_FAILURE;
-
- audit_syscall_exit(result, regs->u_regs[UREG_I0]);
- }
-#endif
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_exit(regs, regs->u_regs[UREG_G1]);
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 701b672..839141d 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -203,8 +203,8 @@ void syscall_trace(struct uml_pt_regs *regs, int entryexit)
UPT_SYSCALL_ARG2(regs),
UPT_SYSCALL_ARG3(regs),
UPT_SYSCALL_ARG4(regs));
- else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
- UPT_SYSCALL_RET(regs));
+ else
+ audit_syscall_exit(regs);
}
/* Fake a debug trap */
diff --git a/arch/um/sys-i386/shared/sysdep/ptrace.h b/arch/um/sys-i386/shared/sysdep/ptrace.h
index d50e62e..54ca089 100644
--- a/arch/um/sys-i386/shared/sysdep/ptrace.h
+++ b/arch/um/sys-i386/shared/sysdep/ptrace.h
@@ -162,6 +162,10 @@ struct syscall_args {
#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
#define UPT_SYSCALL_RET(r) UPT_EAX(r)
+static inline long regs_return_value(struct uml_pt_regs *regs)
+{
+ return UPT_SYSCALL_RET(regs);
+}
#define UPT_FAULTINFO(r) (&(r)->faultinfo)
diff --git a/arch/um/sys-x86_64/shared/sysdep/ptrace.h b/arch/um/sys-x86_64/shared/sysdep/ptrace.h
index fdba545..0924e20 100644
--- a/arch/um/sys-x86_64/shared/sysdep/ptrace.h
+++ b/arch/um/sys-x86_64/shared/sysdep/ptrace.h
@@ -124,6 +124,10 @@ struct uml_pt_regs {
#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
#define UPT_SYSCALL_NR(r) ((r)->syscall)
#define UPT_SYSCALL_RET(r) UPT_RAX(r)
+static inline long regs_return_value(struct uml_pt_regs *regs)
+{
+ return UPT_SYSCALL_RET(regs);
+}
extern int user_context(unsigned long sp);
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index c1870dd..6d1572f 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -14,6 +14,7 @@
#include <asm/segment.h>
#include <asm/irqflags.h>
#include <linux/linkage.h>
+#include <linux/err.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
#include <linux/elf-em.h>
@@ -210,13 +211,12 @@ sysexit_from_sys_call:
TRACE_IRQS_ON
sti
movl %eax,%esi /* second arg, syscall return value */
- cmpl $0,%eax /* is it < 0? */
- setl %al /* 1 if so, 0 if not */
+ cmpl $-MAX_ERRNO,%eax /* is it an error ? */
+ setbe %al /* 1 if so, 0 if not */
movzbl %al,%edi /* zero-extend that into %edi */
- inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
- call audit_syscall_exit
+ call __audit_syscall_exit
GET_THREAD_INFO(%r10)
- movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall return value */
+ movq RAX-ARGOFFSET(%rsp),%rax /* reload syscall return value */
movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
cli
TRACE_IRQS_OFF
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 5c1a919..584112a 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -54,6 +54,7 @@
#include <asm/ftrace.h>
#include <asm/irq_vectors.h>
#include <asm/cpufeature.h>
+#include <linux/err.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
#include <linux/elf-em.h>
@@ -465,11 +466,10 @@ sysexit_audit:
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_ANY)
movl %eax,%edx /* second arg, syscall return value */
- cmpl $0,%eax /* is it < 0? */
- setl %al /* 1 if so, 0 if not */
+ cmpl $-MAX_ERRNO,%eax /* is it an error ? */
+ setbe %al /* 1 if so, 0 if not */
movzbl %al,%eax /* zero-extend that */
- inc %eax /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
- call audit_syscall_exit
+ call __audit_syscall_exit
DISABLE_INTERRUPTS(CLBR_ANY)
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 8a445a0..b7b1f88 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -53,6 +53,7 @@
#include <asm/paravirt.h>
#include <asm/ftrace.h>
#include <asm/percpu.h>
+#include <linux/err.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
#include <linux/elf-em.h>
@@ -564,17 +565,16 @@ auditsys:
jmp system_call_fastpath
/*
- * Return fast path for syscall audit. Call audit_syscall_exit()
+ * Return fast path for syscall audit. Call __audit_syscall_exit()
* directly and then jump back to the fast path with TIF_SYSCALL_AUDIT
* masked off.
*/
sysret_audit:
movq RAX-ARGOFFSET(%rsp),%rsi /* second arg, syscall return value */
- cmpq $0,%rsi /* is it < 0? */
- setl %al /* 1 if so, 0 if not */
+ cmpq $-MAX_ERRNO,%rsi /* is it < -MAX_ERRNO? */
+ setbe %al /* 1 if so, 0 if not */
movzbl %al,%edi /* zero-extend that into %edi */
- inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
- call audit_syscall_exit
+ call __audit_syscall_exit
movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
jmp sysret_check
#endif /* CONFIG_AUDITSYSCALL */
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 807c2a2..5c6281e 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1412,8 +1412,7 @@ void syscall_trace_leave(struct pt_regs *regs)
{
bool step;
- if (unlikely(current->audit_context))
- audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
+ audit_syscall_exit(regs);
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_exit(regs, regs->ax);
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 863f875..af17e1c 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -335,9 +335,9 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
if (info->flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(tsk->mm);
- /*call audit_syscall_exit since we do not exit via the normal paths */
+ /*call __audit_syscall_exit since we do not exit via the normal paths */
if (unlikely(current->audit_context))
- audit_syscall_exit(AUDITSC_RESULT(0), 0);
+ __audit_syscall_exit(1, 0);
__asm__ __volatile__(
"movl %0,%%esp\n\t"
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 208efd6..0452dfc 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -26,6 +26,7 @@
#include <linux/types.h>
#include <linux/elf-em.h>
+#include <linux/ptrace.h>
/* The netlink messages for the audit system is divided into blocks:
* 1000 - 1099 are for commanding the audit system
@@ -410,10 +411,6 @@ struct audit_field {
void *lsm_rule;
};
-#define AUDITSC_INVALID 0
-#define AUDITSC_SUCCESS 1
-#define AUDITSC_FAILURE 2
-#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
extern int __init audit_register_class(int class, unsigned *list);
extern int audit_classify_syscall(int abi, unsigned syscall);
extern int audit_classify_arch(int arch);
@@ -426,7 +423,7 @@ extern void audit_free(struct task_struct *task);
extern void audit_syscall_entry(int arch,
int major, unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3);
-extern void audit_syscall_exit(int failed, long return_code);
+extern void __audit_syscall_exit(int ret_success, long ret_value);
extern void __audit_getname(const char *name);
extern void audit_putname(const char *name);
extern void __audit_inode(const char *name, const struct dentry *dentry);
@@ -441,6 +438,15 @@ static inline int audit_dummy_context(void)
void *p = current->audit_context;
return !p || *(int *)p;
}
+static inline void audit_syscall_exit(void *pt_regs)
+{
+ if (unlikely(current->audit_context)) {
+ int success = is_syscall_success(pt_regs);
+ int return_code = regs_return_value(pt_regs);
+
+ __audit_syscall_exit(success, return_code);
+ }
+}
static inline void audit_getname(const char *name)
{
if (unlikely(!audit_dummy_context()))
@@ -560,12 +566,12 @@ static inline void audit_mmap_fd(int fd, int flags)
extern int audit_n_rules;
extern int audit_signals;
-#else
+#else /* CONFIG_AUDITSYSCALL */
#define audit_finish_fork(t)
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
#define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0)
-#define audit_syscall_exit(f,r) do { ; } while (0)
+#define audit_syscall_exit(r) do { ; } while (0)
#define audit_dummy_context() 1
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
@@ -597,7 +603,7 @@ extern int audit_signals;
#define audit_rng(d, c, l) (0)
#define audit_n_rules 0
#define audit_signals 0
-#endif
+#endif /* CONFIG_AUDITSYSCALL */
#ifdef CONFIG_AUDIT
/* These are defined in audit.c */
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 9178d5c..29bb846 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -98,6 +98,7 @@
#include <linux/compiler.h> /* For unlikely. */
#include <linux/sched.h> /* For struct task_struct. */
+#include <linux/err.h> /* for IS_ERR_VALUE */
extern long arch_ptrace(struct task_struct *child, long request,
@@ -223,6 +224,15 @@ static inline void ptrace_release_task(struct task_struct *task)
#define force_successful_syscall_return() do { } while (0)
#endif
+#ifndef is_syscall_success
+/*
+ * On most systems we can tell if a syscall is a success based on if the retval
+ * is an error value. On some systems like ia64 and powerpc they have different
+ * indicators of success/failure and must define their own.
+ */
+#define is_syscall_success(regs) (!IS_ERR_VALUE((unsigned long)(regs_return_value(regs))))
+#endif
+
/*
* <asm/ptrace.h> should define the following things inside #ifdef __KERNEL__.
*
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 9c61afe..d21a34f 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -70,6 +70,11 @@
#include "audit.h"
+/* flags stating the success for a syscall */
+#define AUDITSC_INVALID 0
+#define AUDITSC_SUCCESS 1
+#define AUDITSC_FAILURE 2
+
/* AUDIT_NAMES is the number of slots we reserve in the audit_context
* for saving names from getname(). If we get more names we will allocate
* a name dynamically and also add those to the list anchored by names_list. */
@@ -1737,8 +1742,7 @@ void audit_finish_fork(struct task_struct *child)
/**
* audit_syscall_exit - deallocate audit context after a system call
- * @valid: success/failure flag
- * @return_code: syscall return value
+ * @pt_regs: syscall registers
*
* Tear down after system call. If the audit context has been marked as
* auditable (either because of the AUDIT_RECORD_CONTEXT state from
@@ -1746,13 +1750,17 @@ void audit_finish_fork(struct task_struct *child)
* message), then write out the syscall information. In call cases,
* free the names stored from getname().
*/
-void audit_syscall_exit(int valid, long return_code)
+void __audit_syscall_exit(int success, long return_code)
{
struct task_struct *tsk = current;
struct audit_context *context;
- context = audit_get_context(tsk, valid, return_code);
+ if (success)
+ success = AUDITSC_SUCCESS;
+ else
+ success = AUDITSC_FAILURE;
+ context = audit_get_context(tsk, success, return_code);
if (likely(!context))
return;
^ permalink raw reply related
* [PATCH] powerpc/book3e-64: use a separate TLB handler when linear map is bolted
From: Scott Wood @ 2011-06-03 22:12 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
On MMUs such as FSL where we can guarantee the entire linear mapping is
bolted, we don't need to worry about linear TLB misses. If on top of
that we do a full table walk, we get rid of all recursive TLB faults, and
can dispense with some state saving. This gains a few percent on
TLB-miss-heavy workloads, and around 50% on a benchmark that had a high
rate of virtual page table faults under the normal handler.
While touching the EX_TLB layout, remove EX_TLB_MMUCR0, EX_TLB_SRR0, and
EX_TLB_SRR1 as they're not used.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
This turned out to be a little faster than the virtual pmd approach
on the sort benchmark as well as lmbench's lat_mem_rd with page stride.
It's slightly slower than virtual pmd (around 1%), but still faster than
current code, on linear tests such as lmbench's bw_mem cp.
arch/powerpc/include/asm/exception-64e.h | 47 ++++---
arch/powerpc/include/asm/mmu_context.h | 2 +
arch/powerpc/mm/tlb_low_64e.S | 206 ++++++++++++++++++++++++++++++
arch/powerpc/mm/tlb_nohash.c | 30 +++-
4 files changed, 259 insertions(+), 26 deletions(-)
diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h
index 6d53f31..1e001f0 100644
--- a/arch/powerpc/include/asm/exception-64e.h
+++ b/arch/powerpc/include/asm/exception-64e.h
@@ -50,28 +50,26 @@
/* The TLB miss exception uses different slots */
-#define EX_TLB_R10 ( 0 * 8)
-#define EX_TLB_R11 ( 1 * 8)
-#define EX_TLB_R12 ( 2 * 8)
+#define EX_TLB_PGD ( 0 * 8)
+#define EX_TLB_R10 ( 1 * 8)
+#define EX_TLB_R11 ( 2 * 8)
#define EX_TLB_R13 ( 3 * 8)
#define EX_TLB_R14 ( 4 * 8)
#define EX_TLB_R15 ( 5 * 8)
#define EX_TLB_R16 ( 6 * 8)
#define EX_TLB_CR ( 7 * 8)
-#define EX_TLB_DEAR ( 8 * 8) /* Level 0 and 2 only */
-#define EX_TLB_ESR ( 9 * 8) /* Level 0 and 2 only */
-#define EX_TLB_SRR0 (10 * 8)
-#define EX_TLB_SRR1 (11 * 8)
-#define EX_TLB_MMUCR0 (12 * 8) /* Level 0 */
-#define EX_TLB_MAS1 (12 * 8) /* Level 0 */
-#define EX_TLB_MAS2 (13 * 8) /* Level 0 */
+#define EX_TLB_R12 ( 8 * 8)
+#define EX_TLB_DEAR ( 9 * 8) /* Level 0 and 2 only */
+#define EX_TLB_ESR (10 * 8) /* Level 0 and 2 only */
+#define EX_TLB_SRR0 (11 * 8)
+#define EX_TLB_SRR1 (12 * 8)
#ifdef CONFIG_BOOK3E_MMU_TLB_STATS
-#define EX_TLB_R8 (14 * 8)
-#define EX_TLB_R9 (15 * 8)
-#define EX_TLB_LR (16 * 8)
-#define EX_TLB_SIZE (17 * 8)
+#define EX_TLB_R8 (13 * 8)
+#define EX_TLB_R9 (14 * 8)
+#define EX_TLB_LR (15 * 8)
+#define EX_TLB_SIZE (16 * 8)
#else
-#define EX_TLB_SIZE (14 * 8)
+#define EX_TLB_SIZE (13 * 8)
#endif
#define START_EXCEPTION(label) \
@@ -168,6 +166,16 @@ exc_##label##_book3e:
ld r9,EX_TLB_R9(r12); \
ld r8,EX_TLB_R8(r12); \
mtlr r16;
+#define TLB_MISS_PROLOG_STATS_BOLTED \
+ mflr r10; \
+ std r8,PACA_EXTLB+EX_TLB_R8(r13); \
+ std r9,PACA_EXTLB+EX_TLB_R9(r13); \
+ std r10,PACA_EXTLB+EX_TLB_LR(r13);
+#define TLB_MISS_RESTORE_STATS_BOLTED \
+ ld r16,PACA_EXTLB+EX_TLB_LR(r13); \
+ ld r9,PACA_EXTLB+EX_TLB_R9(r13); \
+ ld r8,PACA_EXTLB+EX_TLB_R8(r13); \
+ mtlr r16;
#define TLB_MISS_STATS_D(name) \
addi r9,r13,MMSTAT_DSTATS+name; \
bl .tlb_stat_inc;
@@ -183,17 +191,20 @@ exc_##label##_book3e:
61: addi r9,r13,MMSTAT_ISTATS+name; \
62: bl .tlb_stat_inc;
#define TLB_MISS_STATS_SAVE_INFO \
- std r14,EX_TLB_ESR(r12); /* save ESR */ \
-
-
+ std r14,EX_TLB_ESR(r12); /* save ESR */
+#define TLB_MISS_STATS_SAVE_INFO_BOLTED \
+ std r14,PACA_EXTLB+EX_TLB_ESR(r13); /* save ESR */
#else
#define TLB_MISS_PROLOG_STATS
#define TLB_MISS_RESTORE_STATS
+#define TLB_MISS_PROLOG_STATS_BOLTED
+#define TLB_MISS_RESTORE_STATS_BOLTED
#define TLB_MISS_STATS_D(name)
#define TLB_MISS_STATS_I(name)
#define TLB_MISS_STATS_X(name)
#define TLB_MISS_STATS_Y(name)
#define TLB_MISS_STATS_SAVE_INFO
+#define TLB_MISS_STATS_SAVE_INFO_BOLTED
#endif
#define SET_IVOR(vector_number, vector_offset) \
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
index a73668a..9d9e444 100644
--- a/arch/powerpc/include/asm/mmu_context.h
+++ b/arch/powerpc/include/asm/mmu_context.h
@@ -54,6 +54,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
/* 64-bit Book3E keeps track of current PGD in the PACA */
#ifdef CONFIG_PPC_BOOK3E_64
get_paca()->pgd = next->pgd;
+ get_paca()->extlb[0][EX_TLB_PGD / 8] = (unsigned long)next->pgd;
#endif
/* Nothing else to do if we aren't actually switching */
if (prev == next)
@@ -110,6 +111,7 @@ static inline void enter_lazy_tlb(struct mm_struct *mm,
/* 64-bit Book3E keeps track of current PGD in the PACA */
#ifdef CONFIG_PPC_BOOK3E_64
get_paca()->pgd = NULL;
+ get_paca()->extlb[0][EX_TLB_PGD / 8] = 0;
#endif
}
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index af08922..0f4ab86 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -30,6 +30,212 @@
#define VPTE_PGD_SHIFT (VPTE_PUD_SHIFT + PUD_INDEX_SIZE)
#define VPTE_INDEX_SIZE (VPTE_PGD_SHIFT + PGD_INDEX_SIZE)
+/**********************************************************************
+ * *
+ * TLB miss handling for Book3E with a bolted linear mapping *
+ * No virtual page table, no nested TLB misses *
+ * *
+ **********************************************************************/
+
+.macro tlb_prolog_bolted addr
+ mtspr SPRN_SPRG_TLB_SCRATCH,r13
+ mfspr r13,SPRN_SPRG_PACA
+ std r10,PACA_EXTLB+EX_TLB_R10(r13)
+ mfcr r10
+ std r11,PACA_EXTLB+EX_TLB_R11(r13)
+ mfspr r11,SPRN_SPRG_TLB_SCRATCH
+ std r16,PACA_EXTLB+EX_TLB_R16(r13)
+ mfspr r16,\addr /* get faulting address */
+ std r14,PACA_EXTLB+EX_TLB_R14(r13)
+ ld r14,PACA_EXTLB+EX_TLB_PGD(r13)
+ std r15,PACA_EXTLB+EX_TLB_R15(r13)
+ std r10,PACA_EXTLB+EX_TLB_CR(r13)
+ std r11,PACA_EXTLB+EX_TLB_R13(r13)
+ TLB_MISS_PROLOG_STATS_BOLTED
+.endm
+
+.macro tlb_epilog_bolted
+ ld r14,PACA_EXTLB+EX_TLB_CR(r13)
+ ld r10,PACA_EXTLB+EX_TLB_R10(r13)
+ ld r11,PACA_EXTLB+EX_TLB_R11(r13)
+ mtcr r14
+ ld r14,PACA_EXTLB+EX_TLB_R14(r13)
+ ld r15,PACA_EXTLB+EX_TLB_R15(r13)
+ TLB_MISS_RESTORE_STATS_BOLTED
+ ld r16,PACA_EXTLB+EX_TLB_R16(r13)
+ ld r13,PACA_EXTLB+EX_TLB_R13(r13)
+.endm
+
+/* Data TLB miss */
+ START_EXCEPTION(data_tlb_miss_bolted)
+ tlb_prolog_bolted SPRN_DEAR
+
+ /* We need _PAGE_PRESENT and _PAGE_ACCESSED set */
+
+ /* We do the user/kernel test for the PID here along with the RW test
+ */
+ /* We pre-test some combination of permissions to avoid double
+ * faults:
+ *
+ * We move the ESR:ST bit into the position of _PAGE_BAP_SW in the PTE
+ * ESR_ST is 0x00800000
+ * _PAGE_BAP_SW is 0x00000010
+ * So the shift is >> 19. This tests for supervisor writeability.
+ * If the page happens to be supervisor writeable and not user
+ * writeable, we will take a new fault later, but that should be
+ * a rare enough case.
+ *
+ * We also move ESR_ST in _PAGE_DIRTY position
+ * _PAGE_DIRTY is 0x00001000 so the shift is >> 11
+ *
+ * MAS1 is preset for all we need except for TID that needs to
+ * be cleared for kernel translations
+ */
+
+ mfspr r11,SPRN_ESR
+
+ srdi r15,r16,60 /* get region */
+ rldicl. r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
+ bne- dtlb_miss_fault_bolted
+
+ rlwinm r10,r11,32-19,27,27
+ rlwimi r10,r11,32-16,19,19
+ cmpwi r15,0
+ ori r10,r10,_PAGE_PRESENT
+ oris r11,r10,_PAGE_ACCESSED@h
+
+ TLB_MISS_STATS_SAVE_INFO_BOLTED
+ bne tlb_miss_kernel_bolted
+
+tlb_miss_common_bolted:
+/*
+ * This is the guts of the TLB miss handler for bolted-linear.
+ * We are entered with:
+ *
+ * r16 = faulting address
+ * r15 = crap (free to use)
+ * r14 = page table base
+ * r13 = PACA
+ * r11 = PTE permission mask
+ * r10 = crap (free to use)
+ */
+ rldicl r15,r16,64-PGDIR_SHIFT+3,64-PGD_INDEX_SIZE-3
+ cmpldi cr0,r14,0
+ clrrdi r15,r15,3
+ beq tlb_miss_fault_bolted
+
+BEGIN_MMU_FTR_SECTION
+ /* Set the TLB reservation and search for existing entry. Then load
+ * the entry.
+ */
+ PPC_TLBSRX_DOT(0,r16)
+ ldx r14,r14,r15
+ beq normal_tlb_miss_done
+MMU_FTR_SECTION_ELSE
+ ldx r14,r14,r15
+ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_USE_TLBRSRV)
+
+ rldicl r15,r16,64-PUD_SHIFT+3,64-PUD_INDEX_SIZE-3
+ clrrdi r15,r15,3
+
+ cmpldi cr0,r14,0
+ beq tlb_miss_fault_bolted
+
+ ldx r14,r14,r15
+
+ rldicl r15,r16,64-PMD_SHIFT+3,64-PMD_INDEX_SIZE-3
+ clrrdi r15,r15,3
+
+ cmpldi cr0,r14,0
+ beq tlb_miss_fault_bolted
+
+ ldx r14,r14,r15
+
+ rldicl r15,r16,64-PAGE_SHIFT+3,64-PTE_INDEX_SIZE-3
+ clrrdi r15,r15,3
+
+ cmpldi cr0,r14,0
+ beq tlb_miss_fault_bolted
+
+ ldx r14,r14,r15
+
+ /* Check if required permissions are met */
+ andc. r15,r11,r14
+ rldicr r15,r14,64-(PTE_RPN_SHIFT-PAGE_SHIFT),63-PAGE_SHIFT
+ bne- tlb_miss_fault_bolted
+
+ /* Now we build the MAS:
+ *
+ * MAS 0 : Fully setup with defaults in MAS4 and TLBnCFG
+ * MAS 1 : Almost fully setup
+ * - PID already updated by caller if necessary
+ * - TSIZE need change if !base page size, not
+ * yet implemented for now
+ * MAS 2 : Defaults not useful, need to be redone
+ * MAS 3+7 : Needs to be done
+ */
+ clrrdi r11,r16,12 /* Clear low crap in EA */
+ clrldi r15,r15,12 /* Clear crap at the top */
+ rlwimi r11,r14,32-19,27,31 /* Insert WIMGE */
+ rlwimi r15,r14,32-8,22,25 /* Move in U bits */
+ mtspr SPRN_MAS2,r11
+ andi. r11,r14,_PAGE_DIRTY
+ rlwimi r15,r14,32-2,26,31 /* Move in BAP bits */
+
+ /* Mask out SW and UW if !DIRTY (XXX optimize this !) */
+ bne 1f
+ li r11,MAS3_SW|MAS3_UW
+ andc r15,r15,r11
+1:
+ mtspr SPRN_MAS7_MAS3,r15
+ tlbwe
+
+ TLB_MISS_STATS_X(MMSTAT_TLB_MISS_NORM_OK)
+ tlb_epilog_bolted
+ rfi
+
+itlb_miss_kernel_bolted:
+ li r11,_PAGE_PRESENT|_PAGE_BAP_SX /* Base perm */
+ oris r11,r11,_PAGE_ACCESSED@h
+tlb_miss_kernel_bolted:
+ mfspr r10,SPRN_MAS1
+ ld r14,PACA_KERNELPGD(r13)
+ cmpldi cr0,r15,8 /* Check for vmalloc region */
+ rlwinm r10,r10,0,16,1 /* Clear TID */
+ mtspr SPRN_MAS1,r10
+ beq+ tlb_miss_common_bolted
+
+tlb_miss_fault_bolted:
+ /* We need to check if it was an instruction miss */
+ andi. r10,r11,_PAGE_EXEC|_PAGE_BAP_SX
+ bne itlb_miss_fault_bolted
+dtlb_miss_fault_bolted:
+ TLB_MISS_STATS_D(MMSTAT_TLB_MISS_NORM_FAULT)
+ tlb_epilog_bolted
+ b exc_data_storage_book3e
+itlb_miss_fault_bolted:
+ TLB_MISS_STATS_I(MMSTAT_TLB_MISS_NORM_FAULT)
+ tlb_epilog_bolted
+ b exc_instruction_storage_book3e
+
+/* Instruction TLB miss */
+ START_EXCEPTION(instruction_tlb_miss_bolted)
+ tlb_prolog_bolted SPRN_SRR0
+
+ rldicl. r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
+ srdi r15,r16,60 /* get region */
+ TLB_MISS_STATS_SAVE_INFO_BOLTED
+ bne- itlb_miss_fault_bolted
+
+ li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
+
+ /* We do the user/kernel test for the PID here along with the RW test
+ */
+
+ cmpldi cr0,r15,0 /* Check for user region */
+ oris r11,r11,_PAGE_ACCESSED@h
+ beq tlb_miss_common_bolted
+ b itlb_miss_kernel_bolted
/**********************************************************************
* *
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index 0bdad3a..2ba051e 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -443,14 +443,27 @@ static void setup_page_sizes(void)
}
}
-static void setup_mmu_htw(void)
+static void __patch_exception(int exc, unsigned long addr)
{
extern unsigned int interrupt_base_book3e;
- extern unsigned int exc_data_tlb_miss_htw_book3e;
- extern unsigned int exc_instruction_tlb_miss_htw_book3e;
+ unsigned int *ibase = &interrupt_base_book3e;
+
+ /* Our exceptions vectors start with a NOP and -then- a branch
+ * to deal with single stepping from userspace which stops on
+ * the second instruction. Thus we need to patch the second
+ * instruction of the exception, not the first one
+ */
+
+ patch_branch(ibase + (exc / 4) + 1, addr, 0);
+}
- unsigned int *ibase = &interrupt_base_book3e;
+#define patch_exception(exc, name) do { \
+ extern unsigned int name; \
+ __patch_exception((exc), (unsigned long)&name); \
+} while (0)
+static void setup_mmu_htw(void)
+{
/* Check if HW tablewalk is present, and if yes, enable it by:
*
* - patching the TLB miss handlers to branch to the
@@ -467,10 +480,8 @@ static void setup_mmu_htw(void)
* the second instruction. Thus we need to patch the second
* instruction of the exception, not the first one
*/
- patch_branch(ibase + (0x1c0 / 4) + 1,
- (unsigned long)&exc_data_tlb_miss_htw_book3e, 0);
- patch_branch(ibase + (0x1e0 / 4) + 1,
- (unsigned long)&exc_instruction_tlb_miss_htw_book3e, 0);
+ patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e);
+ patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e);
book3e_htw_enabled = 1;
}
pr_info("MMU: Book3E Page Tables %s\n",
@@ -549,6 +560,9 @@ static void __early_init_mmu(int boot_cpu)
/* limit memory so we dont have linear faults */
memblock_enforce_memory_limit(linear_map_top);
memblock_analyze();
+
+ patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
+ patch_exception(0x1e0, exc_instruction_tlb_miss_bolted_book3e);
}
#endif
--
1.7.4.1
^ permalink raw reply related
* Re: PROBLEM: 2.6.39 doesn’t boot on POWER MAC
From: Giuliano Pochini @ 2011-06-03 22:36 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Andrey Gusev, paulus, stable
In-Reply-To: <1307070645.23876.9.camel@pasglop>
On Fri, 03 Jun 2011 13:10:45 +1000
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> On Fri, 2011-06-03 at 12:41 +1000, Benjamin Herrenschmidt wrote:
> > On Fri, 2011-06-03 at 00:00 +0200, Giuliano Pochini wrote:
> > > On Sat, 28 May 2011 11:55:14 +0400
> > > Andrey Gusev <ronne@list.ru> wrote:
> > >
> > > > Hi!
> > > > A kernel 2.6.39 doesn't boot on my POWER MAC G4.
> > >
> > > Same problem with my dual-G4 MDD. A few more infos:
> > > The machine hangs just after the message "Returning from prom_init" (still
> > > in the OF screen).
> > > The kernel works fine with the option maxcpus=1, but it locks up as soon as
> > > I try to enable the second CPU with echo 1 > /sys.../online.
> >
> > I just verified that current upstream 3.0-rc1+ does boot fine.
>
> The fix is:
>
> c560bbceaf6b06e52f1ef20131b76a3fdc0a2c19
> powerpc/4xx: Fix regression in SMP on 476
> [...]
Yes, that patch fixed the problem. Thanks.
--
Giuliano.
^ permalink raw reply
* Re: [PATCH -v2] Audit: push audit success and retcode into arch ptrace.h
From: Tony Luck @ 2011-06-03 22:52 UTC (permalink / raw)
To: Eric Paris
Cc: linux-mips, linux-ia64, linux-sh, heiko.carstens, oleg, paulus,
hpa, sparclinux, linux-s390, richard, x86, mingo, fenghua.yu,
user-mode-linux-devel, microblaze-uclinux, jdike, viro, tglx,
monstr, linux-kernel, ralf, lethal, schwidefsky, linux390, akpm,
linuxppc-dev, davem
In-Reply-To: <20110603220451.23134.47368.stgit@paris.rdu.redhat.com>
On Fri, Jun 3, 2011 at 3:04 PM, Eric Paris <eparis@redhat.com> wrote:
> The other major change is that on some arches, like ia64, we change
> regs_return_value() to give us the negative value on syscall failure. =A0=
The
> only other user of this macro, kretprobe_example.c, won't notice and it m=
akes
> the value signed consistently for the audit functions across all archs.
v2 builds and boots on ia64 now
Acked-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Eric Paris <eparis@redhat.com>
> Acked-by: Acked-by: H. Peter Anvin <hpa@zytor.com> [for x86 portion]
^^^^^^^^^^^^^^^^^^^^ :-)
-Tony
^ permalink raw reply
* Re: [PATCH] Add cpufreq driver for Momentum Maple boards
From: Dmitry Eremin-Solenikov @ 2011-06-04 9:00 UTC (permalink / raw)
To: cpufreq; +Cc: Dave Jones, Paul Mackerras, linuxppc-dev
In-Reply-To: <BANLkTikGyV8aG1twBt7Jt_=j-fSBDiGzAg@mail.gmail.com>
On 5/30/11, Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> wrote:
> Hello,
>
> On 5/21/11, Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> wrote:
>> Add simple cpufreq driver for Maple-based boards (ppc970fx evaluation
>> kit and others). Driver is based on a cpufreq driver for 64-bit powermac
>> boxes with all pmac-dependant features removed and simple cleanup
>> applied.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
>> ---
>> arch/powerpc/kernel/misc_64.S | 4 +-
>> arch/powerpc/platforms/Kconfig | 8 +
>> arch/powerpc/platforms/maple/Makefile | 1 +
>> arch/powerpc/platforms/maple/cpufreq.c | 317
>> ++++++++++++++++++++++++++++++++
>> 4 files changed, 328 insertions(+), 2 deletions(-)
>> create mode 100644 arch/powerpc/platforms/maple/cpufreq.c
>
> What about this patch?
Pinging again. Any problems/comments/objections to this patch?
--
With best wishes
Dmitry
^ permalink raw reply
* Re: PROBLEM: 2.6.39 doesn’t boot on POWER MAC
From: Andrey Gusev @ 2011-06-04 9:02 UTC (permalink / raw)
To: Giuliano Pochini; +Cc: linuxppc-dev, paulus, stable
In-Reply-To: <20110604003602.13bc1a55@Jay>
04.06.2011 02:36, Giuliano Pochini пишет:
> On Fri, 03 Jun 2011 13:10:45 +1000
> Benjamin Herrenschmidt<benh@kernel.crashing.org> wrote:
>
>> On Fri, 2011-06-03 at 12:41 +1000, Benjamin Herrenschmidt wrote:
>>> On Fri, 2011-06-03 at 00:00 +0200, Giuliano Pochini wrote:
>>>> On Sat, 28 May 2011 11:55:14 +0400
>>>> Andrey Gusev<ronne@list.ru> wrote:
>>>>
>>>>> Hi!
>>>>> A kernel 2.6.39 doesn't boot on my POWER MAC G4.
>>>> Same problem with my dual-G4 MDD. A few more infos:
>>>> The machine hangs just after the message "Returning from prom_init" (still
>>>> in the OF screen).
>>>> The kernel works fine with the option maxcpus=1, but it locks up as soon as
>>>> I try to enable the second CPU with echo 1> /sys.../online.
>>> I just verified that current upstream 3.0-rc1+ does boot fine.
>> The fix is:
>>
>> c560bbceaf6b06e52f1ef20131b76a3fdc0a2c19
>> powerpc/4xx: Fix regression in SMP on 476
>> [...]
> Yes, that patch fixed the problem. Thanks.
>
>
The upstream 3.0-rc1 boots on my machine fine too.
^ permalink raw reply
* Re: [PATCH] Add cpufreq driver for Momentum Maple boards
From: Benjamin Herrenschmidt @ 2011-06-04 10:29 UTC (permalink / raw)
To: Dmitry Eremin-Solenikov; +Cc: Dave Jones, Paul Mackerras, linuxppc-dev, cpufreq
In-Reply-To: <BANLkTik6Ln1JGmN7isQ1tWPAf0upzHMvkg@mail.gmail.com>
On Sat, 2011-06-04 at 13:00 +0400, Dmitry Eremin-Solenikov wrote:
> On 5/30/11, Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> wrote:
> > Hello,
> >
> > On 5/21/11, Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> wrote:
> >> Add simple cpufreq driver for Maple-based boards (ppc970fx evaluation
> >> kit and others). Driver is based on a cpufreq driver for 64-bit powermac
> >> boxes with all pmac-dependant features removed and simple cleanup
> >> applied.
> >>
> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
> >> ---
> >> arch/powerpc/kernel/misc_64.S | 4 +-
> >> arch/powerpc/platforms/Kconfig | 8 +
> >> arch/powerpc/platforms/maple/Makefile | 1 +
> >> arch/powerpc/platforms/maple/cpufreq.c | 317
> >> ++++++++++++++++++++++++++++++++
> >> 4 files changed, 328 insertions(+), 2 deletions(-)
> >> create mode 100644 arch/powerpc/platforms/maple/cpufreq.c
> >
> > What about this patch?
>
> Pinging again. Any problems/comments/objections to this patch?
Well, obviously nobody had time to review it yet....
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH] Add cpufreq driver for Momentum Maple boards
From: Dmitry Eremin-Solenikov @ 2011-06-04 10:39 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Dave Jones, Paul Mackerras, linuxppc-dev, cpufreq
In-Reply-To: <1307183381.23876.27.camel@pasglop>
On 6/4/11, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> On Sat, 2011-06-04 at 13:00 +0400, Dmitry Eremin-Solenikov wrote:
>> On 5/30/11, Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> wrote:
>> > Hello,
>> >
>> > On 5/21/11, Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> wrote:
>> >> Add simple cpufreq driver for Maple-based boards (ppc970fx evaluation
>> >> kit and others). Driver is based on a cpufreq driver for 64-bit
>> >> powermac
>> >> boxes with all pmac-dependant features removed and simple cleanup
>> >> applied.
>> >>
>> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
>> >> ---
>> >> arch/powerpc/kernel/misc_64.S | 4 +-
>> >> arch/powerpc/platforms/Kconfig | 8 +
>> >> arch/powerpc/platforms/maple/Makefile | 1 +
>> >> arch/powerpc/platforms/maple/cpufreq.c | 317
>> >> ++++++++++++++++++++++++++++++++
>> >> 4 files changed, 328 insertions(+), 2 deletions(-)
>> >> create mode 100644 arch/powerpc/platforms/maple/cpufreq.c
>> >
>> > What about this patch?
>>
>> Pinging again. Any problems/comments/objections to this patch?
>
> Well, obviously nobody had time to review it yet....
I'm just a bit impatient. It has been already two weeks...
--
With best wishes
Dmitry
^ permalink raw reply
* [PATCH 1/2] ppc/85xx: create a platform node for PCI EDAC device
From: Dmitry Eremin-Solenikov @ 2011-06-04 10:42 UTC (permalink / raw)
To: bluesmoke-devel, linuxppc-dev, Benjamin Herrenschmidt,
Paul Mackerras
In-Reply-To: <20110602124823.3b814b3f@schlenkerla.am.freescale.net>
As a device for pci node isn't created, create a special platform_device
for PCI EDAC device on MPC85xx.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
arch/powerpc/sysdev/fsl_pci.c | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 68ca929..2498229 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -381,6 +381,34 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
return 0;
}
+static int __init fsl_add_pci_err(void)
+{
+ struct device_node *np;
+
+ /* Only PCI, not PCI Express! */
+ for_each_compatible_node(np, "pci", "fsl,mpc8540-pci") {
+ struct resource r[2] = {};
+
+ if (of_address_to_resource(np, 0, &r[0])) {
+ printk(KERN_WARNING
+ "Can't get register base for PCI EDAC!\n");
+ continue;
+ }
+ r[0].start += 0xe00;
+
+ if (of_irq_to_resource(np, 0, &r[1]) == NO_IRQ) {
+ printk(KERN_WARNING
+ "Can't get irq for PCI EDAC!\n");
+ continue;
+ }
+ platform_device_register_simple("mpc85xx_pci_err", -1,
+ r, ARRAY_SIZE(r));
+ }
+
+ return 0;
+}
+device_initcall(fsl_add_pci_err);
+
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548E, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543E, quirk_fsl_pcie_header);
--
1.7.4.4
^ permalink raw reply related
* debugging kernel oops
From: ps2k @ 2011-06-04 11:13 UTC (permalink / raw)
To: linuxppc-dev
Hi All,
I'm new to linux development. We are often seeing kernel oops and failure to
handle paging requests. Any idea how to debug these issues. We have a NAND
flash. I don't know how paging works on an embedded device with flash
memories and not sure why is it needed.
Any help would be greatly appreciated.
Thanks
psk
Jun 1 23:30:01 sbc kernel: [53181.318784] Call Trace:
Jun 1 23:30:01 sbc kernel: [53181.318793] [caab5c50] [c0008114]
show_stack+0x4c/0x1ac (unreliable)
Jun 1 23:30:01 sbc kernel: [53181.318828] [caab5c90] [c0045b4c]
__schedule_bug+0x64/0x78
Jun 1 23:30:01 sbc kernel: [53181.318852] [caab5ca0] [c027d774]
schedule+0x320/0x340
Jun 1 23:30:01 sbc kernel: [53181.318870] [caab5ce0] [c0045d94]
__cond_resched+0x24/0x50
Jun 1 23:30:01 sbc kernel: [53181.318888] [caab5cf0] [c027dd90]
cond_resched+0x50/0x58
Jun 1 23:30:01 sbc kernel: [53181.318906] [caab5d00] [c007bb50]
generic_file_buffered_write+0x1ac/0x67c
Jun 1 23:30:01 sbc kernel: [53181.318934] [caab5d90] [c007c2a8]
__generic_file_aio_write_nolock+0x288/0x50c
Jun 1 23:30:01 sbc kernel: [53181.318954] [caab5e00] [c007c594]
generic_file_aio_write+0x68/0xf8
Jun 1 23:30:01 sbc kernel: [53181.318974] [caab5e30] [c00a0c14]
do_sync_write+0xc4/0x138
Jun 1 23:30:01 sbc kernel: [53181.319000] [caab5ef0] [c00a15bc]
vfs_write+0xb4/0x108
Jun 1 23:30:01 sbc kernel: [53181.319018] [caab5f10] [c00a1ba8]
sys_write+0x4c/0x90
Jun 1 23:30:01 sbc kernel: [53181.319036] [caab5f40] [c00101b8]
ret_from_syscall+0x0/0x38
Jun 1 23:30:01 sbc kernel: [53181.319062] --- Exception: c01 at 0xfe506c4
Jun 1 23:30:01 sbc kernel: [53181.319076] LR = 0x10072040
Jun 1 23:30:01 sbc kernel: [53181.375060] Page fault in user mode
within_atomic() = 1 mm = d4cee5a0
Jun 1 23:30:01 sbc kernel: [53181.375091] NIP = fe51434 MSR = 2000f932
Jun 1 23:30:01 sbc kernel: [53181.375105] Oops: Weird page fault, sig: 11
[#1]
Jun 1 23:30:01 sbc kernel: [53181.375113] PREEMPT MPC836x RDK
Jun 1 23:30:01 sbc kernel: [53181.375123] Modules linked in:
Jun 1 23:30:01 sbc kernel: [53181.375134] NIP: 0fe51434 LR: 1006ce70 CTR:
0fe51434
Jun 1 23:30:01 sbc kernel: [53181.375148] REGS: caab5f50 TRAP: 0401 Not
tainted (2.6.24-sbc-2.0.2.7131)
Jun 1 23:30:01 sbc kernel: [53181.375159] MSR: 2000f932 <EE,PR,FP,ME,IR,DR>
CR: 48000442 XER: 00000000
Jun 1 23:30:01 sbc kernel: [53181.375188] TASK = d4cf0430[8646] 'cp'
THREAD: caab4000
Jun 1 23:30:01 sbc kernel: [53181.375246] NIP [0fe51434] 0xfe51434
Jun 1 23:30:01 sbc kernel: [53181.375260] LR [1006ce70] 0x1006ce70
Jun 1 23:30:01 sbc kernel: [53181.375271] Call Trace:
Jun 1 23:30:01 sbc kernel: [53181.375354] Call Trace:
Jun 1 23:30:01 sbc kernel: [53181.375362] [caab5c10] [c0008114]
show_stack+0x4c/0x1ac (unreliable)
Jun 1 23:30:01 sbc kernel: [53181.375394] [caab5c50] [c0045b4c]
__schedule_bug+0x64/0x78
Jun 1 23:30:01 sbc kernel: [53181.375417] [caab5c60] [c027d774]
schedule+0x320/0x340
Jun 1 23:30:01 sbc kernel: [53181.375435] [caab5ca0] [c0045d94]
__cond_resched+0x24/0x50
Jun 1 23:30:01 sbc kernel: [53181.375453] [caab5cb0] [c027dd90]
cond_resched+0x50/0x58
Jun 1 23:30:01 sbc kernel: [53181.375471] [caab5cc0] [c008a7d8]
unmap_vmas+0x5c4/0x5f4
Jun 1 23:30:01 sbc kernel: [53181.375493] [caab5d40] [c008e574]
exit_mmap+0x74/0x11c
Jun 1 23:30:01 sbc kernel: [53181.375513] [caab5d70] [c0048914]
mmput+0x50/0x108
Jun 1 23:30:01 sbc kernel: [53181.375532] [caab5d80] [c004d034]
exit_mm+0xa8/0x110
Jun 1 23:30:01 sbc kernel: [53181.375553] [caab5da0] [c004ecb8]
do_exit+0x13c/0x7bc
Jun 1 23:30:01 sbc kernel: [53181.375571] [caab5de0] [c000e160]
kernel_bad_stack+0x0/0x4c
Jun 1 23:30:01 sbc kernel: [53181.375593] [caab5e10] [c0013120]
do_page_fault+0xb8/0x4e4
Jun 1 23:30:01 sbc kernel: [53181.375611] [caab5f40] [c00105e8]
handle_page_fault+0xc/0x80
Jun 1 23:30:01 sbc kernel: [53181.375632] --- Exception: 401 at 0xfe51434
Jun 1 23:30:01 sbc kernel: [53181.375645] LR = 0x1006ce70
Jun 2 01:30:01 sbc kernel: [ 6381.530572] Unable to handle kernel paging
request for data at address 0xe1054000
Jun 2 01:30:01 sbc kernel: [ 6381.531024] Faulting instruction address:
0xc0149954
Jun 2 01:30:01 sbc kernel: [ 6381.531303] Oops: Kernel access of bad area,
sig: 11 [#1]
Jun 2 01:30:01 sbc kernel: [ 6381.531320] PREEMPT MPC836x RDK
Jun 2 01:30:01 sbc kernel: [ 6381.531329] Modules linked in:
Jun 2 01:30:01 sbc kernel: [ 6381.531340] NIP: c0149954 LR: c014990c CTR:
00000018
Jun 2 01:30:01 sbc kernel: [ 6381.531354] REGS: d21cdb10 TRAP: 0300 Not
tainted (2.6.24-sbc-2.0.2.7131)
Jun 2 01:30:01 sbc kernel: [ 6381.531365] MSR: 00009032 <EE,ME,IR,DR> CR:
48044448 XER: 20000000
Jun 2 01:30:01 sbc kernel: [ 6381.531388] DAR: e1054000, DSISR: 20000000
Jun 2 01:30:01 sbc kernel: [ 6381.531398] TASK = d8610450[1994] 'cp'
THREAD: d21cc000
Jun 2 01:30:01 sbc kernel: [ 6381.531507] NIP [c0149954]
deflate_fast+0x144/0x34c
Jun 2 01:30:01 sbc kernel: [ 6381.531534] LR [c014990c]
deflate_fast+0xfc/0x34c
Jun 2 01:30:01 sbc kernel: [ 6381.531548] Call Trace:
Jun 2 01:30:01 sbc kernel: [ 6381.531556] [d21cdbc0] [c0149ab8]
deflate_fast+0x2a8/0x34c (unreliable)
Jun 2 01:30:01 sbc kernel: [ 6381.531576] [d21cdbe0] [c0149e38]
zlib_deflate+0x110/0x334
Jun 2 01:30:01 sbc kernel: [ 6381.531593] [d21cdc00] [c012567c]
jffs2_zlib_compress+0xf8/0x1c4
Jun 2 01:30:01 sbc kernel: [ 6381.531620] [d21cdc30] [c0114ba4]
jffs2_compress+0xdc/0x1f0
Jun 2 01:30:01 sbc kernel: [ 6381.531637] [d21cdc60] [c011bfd0]
jffs2_write_inode_range+0xb0/0x34c
Jun 2 01:30:01 sbc kernel: [ 6381.531655] [d21cdcc0] [c0116580]
jffs2_write_end+0xd8/0x23c
Jun 2 01:30:01 sbc kernel: [ 6381.531672] [d21cdd00] [c007bb40]
generic_file_buffered_write+0x19c/0x67c
Jun 2 01:30:01 sbc kernel: [ 6381.531699] [d21cdd90] [c007c2a8]
__generic_file_aio_write_nolock+0x288/0x50c
Jun 2 01:30:01 sbc kernel: [ 6381.531719] [d21cde00] [c007c594]
generic_file_aio_write+0x68/0xf8
Jun 2 01:30:01 sbc kernel: [ 6381.531738] [d21cde30] [c00a0c14]
do_sync_write+0xc4/0x138
Jun 2 01:30:01 sbc kernel: [ 6381.531762] [d21cdef0] [c00a15bc]
vfs_write+0xb4/0x108
Jun 2 01:30:01 sbc kernel: [ 6381.531779] [d21cdf10] [c00a1ba8]
sys_write+0x4c/0x90
Jun 2 01:30:01 sbc kernel: [ 6381.531795] [d21cdf40] [c00101b8]
ret_from_syscall+0x0/0x38
Jun 2 01:30:01 sbc kernel: [ 6381.531820] --- Exception: c01 at 0xfe506c4
Jun 2 01:30:01 sbc kernel: [ 6381.531833] LR = 0x10072040
Jun 2 01:30:01 sbc kernel: [ 6381.531841] Instruction dump:
Jun 2 01:30:01 sbc kernel: [ 6381.531850] 419d0148 2b890002 409d0140
380bffff 901f0058 813f0064 817f0030 39090001
Jun 2 01:30:01 sbc kernel: [ 6381.531874] 815f0050 911f0064 7d685a14
813f0040 <880b0002> 7d295030 817f004c 7c004a78
--
View this message in context: http://old.nabble.com/debugging-kernel-oops-tp31771757p31771757.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.
^ permalink raw reply
* [PATCH 0/8] Use printk_ratelimited instead of printk_ratelimit
From: Christian Dietrich @ 2011-06-04 15:35 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras,
Venkatesh Pallipadi (Venki), Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, x86, Avi Kivity, Marcelo Tosatti, Rusty Russell,
David Airlie, Neil Brown, Doug Gilbert, James E.J. Bottomley,
Greg Kroah-Hartman, Al Viro, Michael Ellerman, Anton Blanchard,
Kumar Gala, Alexey Kardashevskiy, Milton Miller, Scott Wood,
Meador Inge, Kevin Tian, Fengzhe Zhang, John Stultz,
Lucas De Marchi, David S. Miller, Grant Likely,
MichaÅ MirosÅaw, Richard Cochran,
linuxppc-dev, linux-kernel, kvm, lguest, dri-devel, linux-raid,
linux-scsi, devel, trivial
Hi,
since printk_ratelimit() shouldn't be used anymore, I replaced it at several
points, where it was possible with printk_ratelimited(FMT,...). This shouldn't
change the behaviour in most cases, except that the printk will use an local
ratelimit instead of an global one shared with all other printk_ratelimit
calls.
I just must made patches for a few places where it is used. If you think that
it is worth converting all printk_ratelimits, i will send more patches. The
changes where done against v3.0-rc1-106-g4f1ba49.
greetz chris
Christian Dietrich (8):
powerpc/rtas-rtc: remove sideeffects of printk_ratelimit
drivers/octeon: use printk_ratelimited instead of printk_ratelimit
scsi/sg: use printk_ratelimited instead of printk_ratelimit
md/raid: use printk_ratelimited instead of printk_ratelimit
drivers/char/rtc: use printk_ratelimited instead of printk_ratelimit
drivers/gpu/drm: use printk_ratelimited instead of printk_ratelimit
arch/powerpc: use printk_ratelimited instead of printk_ratelimit
arch/x86: use printk_ratelimited instead of printk_ratelimit
arch/powerpc/kernel/rtas-rtc.c | 29 +++++++++------
arch/powerpc/kernel/signal_32.c | 57 +++++++++++++++++--------------
arch/powerpc/kernel/signal_64.c | 17 +++++----
arch/powerpc/kernel/traps.c | 22 +++++------
arch/powerpc/mm/fault.c | 10 +++---
arch/powerpc/sysdev/mpic.c | 11 +++---
arch/x86/kernel/hpet.c | 6 ++--
arch/x86/kernel/irq.c | 9 ++---
arch/x86/kvm/i8259.c | 7 ++--
arch/x86/lguest/boot.c | 6 ++--
drivers/char/rtc.c | 7 ++--
drivers/gpu/drm/drm_ioc32.c | 9 +++--
drivers/md/raid1.c | 22 ++++++-----
drivers/md/raid10.c | 22 ++++++-----
drivers/md/raid5.c | 39 ++++++++++-----------
drivers/scsi/sg.c | 18 +++++----
drivers/staging/octeon/ethernet-mdio.c | 27 +++++++-------
drivers/staging/octeon/ethernet-rgmii.c | 33 +++++++++---------
drivers/staging/octeon/ethernet-rx.c | 24 +++++++------
drivers/staging/octeon/ethernet-sgmii.c | 14 ++++---
drivers/staging/octeon/ethernet-tx.c | 11 +++---
drivers/staging/octeon/ethernet-util.h | 4 --
drivers/staging/octeon/ethernet-xaui.c | 22 ++++++-----
23 files changed, 221 insertions(+), 205 deletions(-)
^ permalink raw reply
* [PATCH 1/8] powerpc/rtas-rtc: remove sideeffects of printk_ratelimit
From: Christian Dietrich @ 2011-06-04 15:35 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev,
linux-kernel, trivial
In-Reply-To: <cover.1307199715.git.christian.dietrich@informatik.uni-erlangen.de>
Don't use printk_ratelimit() as an additional condition for returning
on an error. Because when the ratelimit is reached, printk_ratelimit
will return 0 and e.g. in rtas_get_boot_time won't check for an error
condition.
Signed-off-by: Christian Dietrich <christian.dietrich@informatik.uni-erlangen.de>
---
arch/powerpc/kernel/rtas-rtc.c | 29 +++++++++++++++++------------
1 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c
index 77578c0..c57c193 100644
--- a/arch/powerpc/kernel/rtas-rtc.c
+++ b/arch/powerpc/kernel/rtas-rtc.c
@@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/rtc.h>
#include <linux/delay.h>
+#include <linux/ratelimit.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/time.h>
@@ -29,9 +30,10 @@ unsigned long __init rtas_get_boot_time(void)
}
} while (wait_time && (get_tb() < max_wait_tb));
- if (error != 0 && printk_ratelimit()) {
- printk(KERN_WARNING "error: reading the clock failed (%d)\n",
- error);
+ if (error != 0) {
+ printk_ratelimited(KERN_WARNING
+ "error: reading the clock failed (%d)\n",
+ error);
return 0;
}
@@ -55,19 +57,21 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm)
wait_time = rtas_busy_delay_time(error);
if (wait_time) {
- if (in_interrupt() && printk_ratelimit()) {
+ if (in_interrupt()) {
memset(rtc_tm, 0, sizeof(struct rtc_time));
- printk(KERN_WARNING "error: reading clock"
- " would delay interrupt\n");
+ printk_ratelimited(KERN_WARNING
+ "error: reading clock "
+ "would delay interrupt\n");
return; /* delay not allowed */
}
msleep(wait_time);
}
} while (wait_time && (get_tb() < max_wait_tb));
- if (error != 0 && printk_ratelimit()) {
- printk(KERN_WARNING "error: reading the clock failed (%d)\n",
- error);
+ if (error != 0) {
+ printk_ratelimited(KERN_WARNING
+ "error: reading the clock failed (%d)\n",
+ error);
return;
}
@@ -99,9 +103,10 @@ int rtas_set_rtc_time(struct rtc_time *tm)
}
} while (wait_time && (get_tb() < max_wait_tb));
- if (error != 0 && printk_ratelimit())
- printk(KERN_WARNING "error: setting the clock failed (%d)\n",
- error);
+ if (error != 0)
+ printk_ratelimited(KERN_WARNING
+ "error: setting the clock failed (%d)\n",
+ error);
return 0;
}
--
1.7.1
^ permalink raw reply related
* [PATCH 7/8] arch/powerpc: use printk_ratelimited instead of printk_ratelimit
From: Christian Dietrich @ 2011-06-04 15:36 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Al Viro, Michael Ellerman,
Anton Blanchard, Kumar Gala, Alexey Kardashevskiy, Phil Carmody,
Milton Miller, Scott Wood, Meador Inge, linuxppc-dev,
linux-kernel, trivial
In-Reply-To: <cover.1307199715.git.christian.dietrich@informatik.uni-erlangen.de>
Since printk_ratelimit() shouldn't be used anymore (see comment in
include/linux/printk.h), replace it with printk_ratelimited.
Signed-off-by: Christian Dietrich <christian.dietrich@informatik.uni-erlangen.de>
---
arch/powerpc/kernel/signal_32.c | 57 +++++++++++++++++++++-----------------
arch/powerpc/kernel/signal_64.c | 17 ++++++-----
arch/powerpc/kernel/traps.c | 22 +++++++--------
arch/powerpc/mm/fault.c | 10 +++---
arch/powerpc/sysdev/mpic.c | 11 +++----
5 files changed, 60 insertions(+), 57 deletions(-)
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index b96a3a0..78b76dc 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -25,6 +25,7 @@
#include <linux/errno.h>
#include <linux/elf.h>
#include <linux/ptrace.h>
+#include <linux/ratelimit.h>
#ifdef CONFIG_PPC64
#include <linux/syscalls.h>
#include <linux/compat.h>
@@ -892,11 +893,12 @@ badframe:
printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp);
#endif
- if (show_unhandled_signals && printk_ratelimit())
- printk(KERN_INFO "%s[%d]: bad frame in handle_rt_signal32: "
- "%p nip %08lx lr %08lx\n",
- current->comm, current->pid,
- addr, regs->nip, regs->link);
+ if (show_unhandled_signals)
+ printk_ratelimited(KERN_INFO
+ "%s[%d]: bad frame in handle_rt_signal32: "
+ "%p nip %08lx lr %08lx\n",
+ current->comm, current->pid,
+ addr, regs->nip, regs->link);
force_sigsegv(sig, current);
return 0;
@@ -1058,11 +1060,12 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
return 0;
bad:
- if (show_unhandled_signals && printk_ratelimit())
- printk(KERN_INFO "%s[%d]: bad frame in sys_rt_sigreturn: "
- "%p nip %08lx lr %08lx\n",
- current->comm, current->pid,
- rt_sf, regs->nip, regs->link);
+ if (show_unhandled_signals)
+ printk_ratelimited(KERN_INFO
+ "%s[%d]: bad frame in sys_rt_sigreturn: "
+ "%p nip %08lx lr %08lx\n",
+ current->comm, current->pid,
+ rt_sf, regs->nip, regs->link);
force_sig(SIGSEGV, current);
return 0;
@@ -1149,12 +1152,12 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
* We kill the task with a SIGSEGV in this situation.
*/
if (do_setcontext(ctx, regs, 1)) {
- if (show_unhandled_signals && printk_ratelimit())
- printk(KERN_INFO "%s[%d]: bad frame in "
- "sys_debug_setcontext: %p nip %08lx "
- "lr %08lx\n",
- current->comm, current->pid,
- ctx, regs->nip, regs->link);
+ if (show_unhandled_signals)
+ printk_ratelimited(KERN_INFO "%s[%d]: bad frame in "
+ "sys_debug_setcontext: %p nip %08lx "
+ "lr %08lx\n",
+ current->comm, current->pid,
+ ctx, regs->nip, regs->link);
force_sig(SIGSEGV, current);
goto out;
@@ -1236,11 +1239,12 @@ badframe:
printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp);
#endif
- if (show_unhandled_signals && printk_ratelimit())
- printk(KERN_INFO "%s[%d]: bad frame in handle_signal32: "
- "%p nip %08lx lr %08lx\n",
- current->comm, current->pid,
- frame, regs->nip, regs->link);
+ if (show_unhandled_signals)
+ printk_ratelimited(KERN_INFO
+ "%s[%d]: bad frame in handle_signal32: "
+ "%p nip %08lx lr %08lx\n",
+ current->comm, current->pid,
+ frame, regs->nip, regs->link);
force_sigsegv(sig, current);
return 0;
@@ -1288,11 +1292,12 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
return 0;
badframe:
- if (show_unhandled_signals && printk_ratelimit())
- printk(KERN_INFO "%s[%d]: bad frame in sys_sigreturn: "
- "%p nip %08lx lr %08lx\n",
- current->comm, current->pid,
- addr, regs->nip, regs->link);
+ if (show_unhandled_signals)
+ printk_ratelimited(KERN_INFO
+ "%s[%d]: bad frame in sys_sigreturn: "
+ "%p nip %08lx lr %08lx\n",
+ current->comm, current->pid,
+ addr, regs->nip, regs->link);
force_sig(SIGSEGV, current);
return 0;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index da989ff..e91c736 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -24,6 +24,7 @@
#include <linux/elf.h>
#include <linux/ptrace.h>
#include <linux/module.h>
+#include <linux/ratelimit.h>
#include <asm/sigcontext.h>
#include <asm/ucontext.h>
@@ -380,10 +381,10 @@ badframe:
printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n",
regs, uc, &uc->uc_mcontext);
#endif
- if (show_unhandled_signals && printk_ratelimit())
- printk(regs->msr & MSR_64BIT ? fmt64 : fmt32,
- current->comm, current->pid, "rt_sigreturn",
- (long)uc, regs->nip, regs->link);
+ if (show_unhandled_signals)
+ printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
+ current->comm, current->pid, "rt_sigreturn",
+ (long)uc, regs->nip, regs->link);
force_sig(SIGSEGV, current);
return 0;
@@ -468,10 +469,10 @@ badframe:
printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp);
#endif
- if (show_unhandled_signals && printk_ratelimit())
- printk(regs->msr & MSR_64BIT ? fmt64 : fmt32,
- current->comm, current->pid, "setup_rt_frame",
- (long)frame, regs->nip, regs->link);
+ if (show_unhandled_signals)
+ printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
+ current->comm, current->pid, "setup_rt_frame",
+ (long)frame, regs->nip, regs->link);
force_sigsegv(signr, current);
return 0;
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 0ff4ab9..7929aef 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -34,6 +34,7 @@
#include <linux/bug.h>
#include <linux/kdebug.h>
#include <linux/debugfs.h>
+#include <linux/ratelimit.h>
#include <asm/emulated_ops.h>
#include <asm/pgtable.h>
@@ -197,12 +198,11 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
if (die("Exception in kernel mode", regs, signr))
return;
} else if (show_unhandled_signals &&
- unhandled_signal(current, signr) &&
- printk_ratelimit()) {
- printk(regs->msr & MSR_64BIT ? fmt64 : fmt32,
- current->comm, current->pid, signr,
- addr, regs->nip, regs->link, code);
- }
+ unhandled_signal(current, signr)) {
+ printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
+ current->comm, current->pid, signr,
+ addr, regs->nip, regs->link, code);
+ }
memset(&info, 0, sizeof(info));
info.si_signo = signr;
@@ -1342,9 +1342,8 @@ void altivec_assist_exception(struct pt_regs *regs)
} else {
/* didn't recognize the instruction */
/* XXX quick hack for now: set the non-Java bit in the VSCR */
- if (printk_ratelimit())
- printk(KERN_ERR "Unrecognized altivec instruction "
- "in %s at %lx\n", current->comm, regs->nip);
+ printk_ratelimited(KERN_ERR "Unrecognized altivec instruction "
+ "in %s at %lx\n", current->comm, regs->nip);
current->thread.vscr.u[3] |= 0x10000;
}
}
@@ -1548,9 +1547,8 @@ u32 ppc_warn_emulated;
void ppc_warn_emulated_print(const char *type)
{
- if (printk_ratelimit())
- pr_warning("%s used emulated %s instruction\n", current->comm,
- type);
+ pr_warn_ratelimited("%s used emulated %s instruction\n", current->comm,
+ type);
}
static int __init ppc_warn_emulated_init(void)
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 54f4fb9..ad35f66 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -31,6 +31,7 @@
#include <linux/kdebug.h>
#include <linux/perf_event.h>
#include <linux/magic.h>
+#include <linux/ratelimit.h>
#include <asm/firmware.h>
#include <asm/page.h>
@@ -346,11 +347,10 @@ bad_area_nosemaphore:
return 0;
}
- if (is_exec && (error_code & DSISR_PROTFAULT)
- && printk_ratelimit())
- printk(KERN_CRIT "kernel tried to execute NX-protected"
- " page (%lx) - exploit attempt? (uid: %d)\n",
- address, current_uid());
+ if (is_exec && (error_code & DSISR_PROTFAULT))
+ printk_ratelimited(KERN_CRIT "kernel tried to execute NX-protected"
+ " page (%lx) - exploit attempt? (uid: %d)\n",
+ address, current_uid());
return SIGSEGV;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 3a8de5b..58d7a53 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -29,6 +29,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/syscore_ops.h>
+#include <linux/ratelimit.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
@@ -1648,9 +1649,8 @@ static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg)
return NO_IRQ;
}
if (unlikely(mpic->protected && test_bit(src, mpic->protected))) {
- if (printk_ratelimit())
- printk(KERN_WARNING "%s: Got protected source %d !\n",
- mpic->name, (int)src);
+ printk_ratelimited(KERN_WARNING "%s: Got protected source %d !\n",
+ mpic->name, (int)src);
mpic_eoi(mpic);
return NO_IRQ;
}
@@ -1688,9 +1688,8 @@ unsigned int mpic_get_coreint_irq(void)
return NO_IRQ;
}
if (unlikely(mpic->protected && test_bit(src, mpic->protected))) {
- if (printk_ratelimit())
- printk(KERN_WARNING "%s: Got protected source %d !\n",
- mpic->name, (int)src);
+ printk_ratelimited(KERN_WARNING "%s: Got protected source %d !\n",
+ mpic->name, (int)src);
return NO_IRQ;
}
--
1.7.1
^ permalink raw reply related
* Re: [PATCH -v2] Audit: push audit success and retcode into arch ptrace.h
From: Richard Weinberger @ 2011-06-04 22:36 UTC (permalink / raw)
To: Eric Paris
Cc: linux-mips, linux-ia64, linux-sh, heiko.carstens, oleg, paulus,
hpa, sparclinux, linux-s390, x86, mingo, fenghua.yu,
user-mode-linux-devel, microblaze-uclinux, jdike, viro, tglx,
monstr, tony.luck, linux-kernel, ralf, lethal, schwidefsky,
linux390, akpm, linuxppc-dev, davem
In-Reply-To: <20110603220451.23134.47368.stgit@paris.rdu.redhat.com>
Am Samstag 04 Juni 2011, 00:04:51 schrieb Eric Paris:
> The audit system previously expected arches calling to audit_syscall_exit
> to supply as arguments if the syscall was a success and what the return
> code was. Audit also provides a helper AUDITSC_RESULT which was supposed
> to simplify things by converting from negative retcodes to an audit
> internal magic value stating success or failure. This helper was wrong
> and could indicate that a valid pointer returned to userspace was a failed
> syscall. The fix is to fix the layering foolishness. We now pass
> audit_syscall_exit a struct pt_reg and it in turns calls back into arch
> code to collect the return value and to determine if the syscall was a
> success or failure. We also define a generic is_syscall_success() macro
> which determines success/failure based on if the value is < -MAX_ERRNO.
> This works for arches like x86 which do not use a separate mechanism to
> indicate syscall failure.
>
> In arch/sh/kernel/ptrace_64.c I see that we were using regs[9] in the old
> audit code as the return value. But the ptrace_64.h code defined the macro
> regs_return_value() as regs[3]. I have no idea which one is correct, but
> this patch now uses the regs_return_value() function, so it now uses
> regs[3].
>
> We make both the is_syscall_success() and regs_return_value() static
> inlines instead of macros. The reason is because the audit function must
> take a void* for the regs. (uml calls theirs struct uml_pt_regs instead
> of just struct pt_regs so audit_syscall_exit can't take a struct pt_regs).
> Since the audit function takes a void* we need to use static inlines to
> cast it back to the arch correct structure to dereference it.
>
> The other major change is that on some arches, like ia64, we change
> regs_return_value() to give us the negative value on syscall failure. The
> only other user of this macro, kretprobe_example.c, won't notice and it
> makes the value signed consistently for the audit functions across all
> archs.
>
> Signed-off-by: Eric Paris <eparis@redhat.com>
> Acked-by: Acked-by: H. Peter Anvin <hpa@zytor.com> [for x86 portion]
The UML part is now fine for me. :-)
Acked-by: Richard Weinberger <richard@nod.at>
Thanks,
//richard
^ permalink raw reply
* [PATCH] powerpc/e5500: enable caam crypto driver by default
From: Kim Phillips @ 2011-06-05 22:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Kumar Gala
e55xx based SoCs have SEC4 h/w, so enable the SEC4 driver,
caam, and the algorithms it supports, and disable the
SEC2/3 driver, talitos.
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
---
arch/powerpc/configs/e55xx_smp_defconfig | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/configs/e55xx_smp_defconfig b/arch/powerpc/configs/e55xx_smp_defconfig
index d322835..c92c204 100644
--- a/arch/powerpc/configs/e55xx_smp_defconfig
+++ b/arch/powerpc/configs/e55xx_smp_defconfig
@@ -100,5 +100,8 @@ CONFIG_DEBUG_INFO=y
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_VIRQ_DEBUG=y
CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DEV_TALITOS=y
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
--
1.7.5.4
^ permalink raw reply related
* Re: 3.0-rc1: powerpc hangs at Kernel virtual memory layout
From: Christian Kujau @ 2011-06-06 2:11 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: zajec5, linux ppc dev, LKML
In-Reply-To: <1307000008.29297.59.camel@pasglop>
On Thu, 2 Jun 2011 at 17:33, Benjamin Herrenschmidt wrote:
> It -looks- to me that something goes wrong in the tty code when a large
> file is piped through a pty, causing the kernel to hang for minutes in
> the workqueue / ldisk flush code. I've just sent an initial report to
> Alan Cox about it and am currently bisecting it.
This was the "tty vs workqueue oddities" thread, right? FWIW,
55db4c64eddf37 ("Revert "tty: make receive_buf() return the amout of bytes
received"") seems to have fixed it on this powerpc machine as well.
With your "ssb: pci: Don't call PCIe specific workarounds on PCI cores"
patch applied, powerpc32 seems to be quite happy with 3.0-rc1+
Thanks,
Christian.
--
BOFH excuse #382:
Someone was smoking in the computer room and set off the halon systems.
^ permalink raw reply
* [PATCH] Fix doorbell type shift
From: Michael Neuling @ 2011-06-06 2:48 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Kumar Gala; +Cc: linuxppc-dev, Milton Miller
doorbell type is defined as bits 32:36 so should be shifted by 63-36 =
27 rather than 28.
We never noticed this bug as we've only every used type PPC_DBELL = 0.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/include/asm/dbell.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: linux-ozlabs/arch/powerpc/include/asm/dbell.h
===================================================================
--- linux-ozlabs.orig/arch/powerpc/include/asm/dbell.h
+++ linux-ozlabs/arch/powerpc/include/asm/dbell.h
@@ -18,7 +18,7 @@
#include <asm/ppc-opcode.h>
#define PPC_DBELL_MSG_BRDCAST (0x04000000)
-#define PPC_DBELL_TYPE(x) (((x) & 0xf) << 28)
+#define PPC_DBELL_TYPE(x) (((x) & 0xf) << (63-36))
enum ppc_dbell {
PPC_DBELL = 0, /* doorbell */
PPC_DBELL_CRIT = 1, /* critical doorbell */
^ permalink raw reply
* Re: 3.0-rc1: powerpc hangs at Kernel virtual memory layout
From: Benjamin Herrenschmidt @ 2011-06-06 3:46 UTC (permalink / raw)
To: Christian Kujau; +Cc: zajec5, linux ppc dev, LKML
In-Reply-To: <alpine.DEB.2.01.1106051907190.21697@trent.utfs.org>
On Sun, 2011-06-05 at 19:11 -0700, Christian Kujau wrote:
> On Thu, 2 Jun 2011 at 17:33, Benjamin Herrenschmidt wrote:
> > It -looks- to me that something goes wrong in the tty code when a large
> > file is piped through a pty, causing the kernel to hang for minutes in
> > the workqueue / ldisk flush code. I've just sent an initial report to
> > Alan Cox about it and am currently bisecting it.
>
> This was the "tty vs workqueue oddities" thread, right? FWIW,
> 55db4c64eddf37 ("Revert "tty: make receive_buf() return the amout of bytes
> received"") seems to have fixed it on this powerpc machine as well.
Yup.
> With your "ssb: pci: Don't call PCIe specific workarounds on PCI cores"
> patch applied, powerpc32 seems to be quite happy with 3.0-rc1+
Good :-)
Cheers,
Ben.
^ permalink raw reply
* [PATCH][v2] powerpc/85xx: Add P1010RDB board support
From: Prabhakar Kushwaha @ 2011-06-06 4:45 UTC (permalink / raw)
To: linuxppc-dev, devicetree-discuss
Cc: meet2prabhu, Poonam Aggrwal, Prabhakar Kushwaha
P1010RDB Overview
-----------------
1Gbyte DDR3 (on board DDR)
32Mbyte 16bit NOR flash
32Mbyte SLC NAND Flash
256 Kbit M24256 I2C EEPROM
128 Mbit SPI Flash memory
I2C Board 128x8 bit memory
SD/MMC connector to interface with the SD memory card
2 SATA interface
1 internal SATA connect to 2.5. 160G SATA2 HDD
1 eSATA connector to rear panel
USB 2.0
x1 USB 2.0 port: connected via a UTMI PHY to Mini-AB interface.
x1 USB 2.0 port: directly connected to Mini-AB interface Ethernet
eTSEC1: Connected to RGMII PHY VSC8641XKO
eTSEC2: Connected to SGMII PHY VSC8221
eTSEC3: Connected to SGMII PHY VSC8221 eCAN
Two DB-9 female connectors for Field bus interface UART
DUART interface: supports two UARTs up to 115200 bps for console display
Signed-off-by: Poonam Aggrwal <poonam.aggrwal@freescale.com>
Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
---
Based upon http://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git (branch next)
Changes for v2:
- updated tbi-handle location
arch/powerpc/boot/dts/p1010rdb.dts | 278 +++++++++++++++++++++++
arch/powerpc/boot/dts/p1010si.dtsi | 378 ++++++++++++++++++++++++++++++++
arch/powerpc/configs/mpc85xx_defconfig | 1 +
arch/powerpc/platforms/85xx/Kconfig | 10 +
arch/powerpc/platforms/85xx/Makefile | 1 +
arch/powerpc/platforms/85xx/p1010rdb.c | 122 ++++++++++
6 files changed, 790 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/boot/dts/p1010rdb.dts
create mode 100644 arch/powerpc/boot/dts/p1010si.dtsi
create mode 100644 arch/powerpc/platforms/85xx/p1010rdb.c
diff --git a/arch/powerpc/boot/dts/p1010rdb.dts b/arch/powerpc/boot/dts/p1010rdb.dts
new file mode 100644
index 0000000..773cc16
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1010rdb.dts
@@ -0,0 +1,278 @@
+/*
+ * P1010 RDB Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/include/ "p1010si.dtsi"
+
+/ {
+ model = "fsl,P1010RDB";
+ compatible = "fsl,P1010RDB";
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ };
+
+ memory {
+ device_type = "memory";
+ };
+
+ ifc@ffe1e000 {
+ /* NOR, NAND Flashes and CPLD on board */
+ ranges = <0x0 0x0 0x0 0xee000000 0x02000000
+ 0x1 0x0 0x0 0xff800000 0x00010000
+ 0x3 0x0 0x0 0xffb00000 0x00000020>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x2000000>;
+ bank-width = <2>;
+ device-width = <1>;
+
+ partition@40000 {
+ /* 256KB for DTB Image */
+ reg = <0x00040000 0x00040000>;
+ label = "NOR DTB Image";
+ };
+
+ partition@80000 {
+ /* 7 MB for Linux Kernel Image */
+ reg = <0x00080000 0x00700000>;
+ label = "NOR Linux Kernel Image";
+ };
+
+ partition@800000 {
+ /* 20MB for JFFS2 based Root file System */
+ reg = <0x00800000 0x01400000>;
+ label = "NOR JFFS2 Root File System";
+ };
+
+ partition@1f00000 {
+ /* This location must not be altered */
+ /* 512KB for u-boot Bootloader Image */
+ /* 512KB for u-boot Environment Variables */
+ reg = <0x01f00000 0x00100000>;
+ label = "NOR U-Boot Image";
+ read-only;
+ };
+ };
+
+ nand@1,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,ifc-nand";
+ reg = <0x1 0x0 0x10000>;
+
+ partition@0 {
+ /* This location must not be altered */
+ /* 1MB for u-boot Bootloader Image */
+ reg = <0x0 0x00100000>;
+ label = "NAND U-Boot Image";
+ read-only;
+ };
+
+ partition@100000 {
+ /* 1MB for DTB Image */
+ reg = <0x00100000 0x00100000>;
+ label = "NAND DTB Image";
+ };
+
+ partition@200000 {
+ /* 4MB for Linux Kernel Image */
+ reg = <0x00200000 0x00400000>;
+ label = "NAND Linux Kernel Image";
+ };
+
+ partition@600000 {
+ /* 4MB for Compressed Root file System Image */
+ reg = <0x00600000 0x00400000>;
+ label = "NAND Compressed RFS Image";
+ };
+
+ partition@a00000 {
+ /* 15MB for JFFS2 based Root file System */
+ reg = <0x00a00000 0x00f00000>;
+ label = "NAND JFFS2 Root File System";
+ };
+
+ partition@1900000 {
+ /* 7MB for User Area */
+ reg = <0x01900000 0x00700000>;
+ label = "NAND User area";
+ };
+ };
+
+ cpld@3,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p1010rdb-cpld";
+ reg = <0x3 0x0 0x0000020>;
+ bank-width = <1>;
+ device-width = <1>;
+ };
+ };
+
+ soc@ffe00000 {
+ spi@7000 {
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25sl12801";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+
+ partition@0 {
+ /* 1MB for u-boot Bootloader Image */
+ /* 1MB for Environment */
+ reg = <0x0 0x00100000>;
+ label = "SPI Flash U-Boot Image";
+ read-only;
+ };
+
+ partition@100000 {
+ /* 512KB for DTB Image */
+ reg = <0x00100000 0x00080000>;
+ label = "SPI Flash DTB Image";
+ };
+
+ partition@180000 {
+ /* 4MB for Linux Kernel Image */
+ reg = <0x00180000 0x00400000>;
+ label = "SPI Flash Linux Kernel Image";
+ };
+
+ partition@580000 {
+ /* 4MB for Compressed RFS Image */
+ reg = <0x00580000 0x00400000>;
+ label = "SPI Flash Compressed RFSImage";
+ };
+
+ partition@980000 {
+ /* 6.5MB for JFFS2 based RFS */
+ reg = <0x00980000 0x00680000>;
+ label = "SPI Flash JFFS2 RFS";
+ };
+ };
+ };
+
+ can0@1c000 {
+ fsl,flexcan-clock-source = "platform";
+ };
+
+ can1@1d000 {
+ fsl,flexcan-clock-source = "platform";
+ };
+
+ usb@22000 {
+ phy_type = "utmi";
+ };
+
+ mdio@24000 {
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <3 1>;
+ reg = <0x1>;
+ };
+
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+ reg = <0x0>;
+ };
+
+ phy2: ethernet-phy@2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+ reg = <0x2>;
+ };
+ };
+
+ enet0: ethernet@b0000 {
+ phy-handle = <&phy0>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ enet1: ethernet@b1000 {
+ phy-handle = <&phy1>;
+ phy-connection-type = "sgmii";
+ };
+
+ enet2: ethernet@b2000 {
+ phy-handle = <&phy2>;
+ phy-connection-type = "sgmii";
+ };
+ };
+
+ pci0: pcie@ffe09000 {
+ ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+ pcie@0 {
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
+ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
+ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
+ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
+ >;
+
+ ranges = <0x2000000 0x0 0xa0000000
+ 0x2000000 0x0 0xa0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ pci1: pcie@ffe0a000 {
+ ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+ pcie@0 {
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
+ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
+ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
+ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
+ >;
+ ranges = <0x2000000 0x0 0x80000000
+ 0x2000000 0x0 0x80000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/p1010si.dtsi b/arch/powerpc/boot/dts/p1010si.dtsi
new file mode 100644
index 0000000..6e741ff
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1010si.dtsi
@@ -0,0 +1,378 @@
+/*
+ * P1010si Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+/ {
+ compatible = "fsl,P1010";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,P1010@0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ ifc@ffe1e000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,ifc", "simple-bus";
+ reg = <0x0 0xffe1e000 0 0x2000>;
+ interrupts = <16 2 19 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ soc@ffe00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,p1010-immr", "simple-bus";
+ ranges = <0x0 0x0 0xffe00000 0x100000>;
+ bus-frequency = <0>; // Filled out by uboot.
+
+ ecm-law@0 {
+ compatible = "fsl,ecm-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <12>;
+ };
+
+ ecm@1000 {
+ compatible = "fsl,p1010-ecm", "fsl,ecm";
+ reg = <0x1000 0x1000>;
+ interrupts = <16 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ memory-controller@2000 {
+ compatible = "fsl,p1010-memory-controller";
+ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+
+ i2c@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3000 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+
+ i2c@3100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x3100 0x100>;
+ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+
+ serial0: serial@4500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ serial1: serial@4600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ spi@7000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc8536-espi";
+ reg = <0x7000 0x1000>;
+ interrupts = <59 0x2>;
+ interrupt-parent = <&mpic>;
+ fsl,espi-num-chipselects = <1>;
+ };
+
+ gpio: gpio-controller@f000 {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8572-gpio";
+ reg = <0xf000 0x100>;
+ interrupts = <47 0x2>;
+ interrupt-parent = <&mpic>;
+ gpio-controller;
+ };
+
+ sata@18000 {
+ compatible = "fsl,pq-sata-v2";
+ reg = <0x18000 0x1000>;
+ cell-index = <1>;
+ interrupts = <74 0x2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ sata@19000 {
+ compatible = "fsl,pq-sata-v2";
+ reg = <0x19000 0x1000>;
+ cell-index = <2>;
+ interrupts = <41 0x2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ can0@1c000 {
+ compatible = "fsl,flexcan-v1.0";
+ reg = <0x1c000 0x1000>;
+ interrupts = <48 0x2>;
+ interrupt-parent = <&mpic>;
+ fsl,flexcan-clock-divider = <2>;
+ };
+
+ can1@1d000 {
+ compatible = "fsl,flexcan-v1.0";
+ reg = <0x1d000 0x1000>;
+ interrupts = <61 0x2>;
+ interrupt-parent = <&mpic>;
+ fsl,flexcan-clock-divider = <2>;
+ };
+
+ L2: l2-cache-controller@20000 {
+ compatible = "fsl,p1010-l2-cache-controller",
+ "fsl,p1014-l2-cache-controller";
+ reg = <0x20000 0x1000>;
+ cache-line-size = <32>; // 32 bytes
+ cache-size = <0x40000>; // L2,256K
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+
+ dma@21300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p1010-dma", "fsl,eloplus-dma";
+ reg = <0x21300 0x4>;
+ ranges = <0x0 0x21100 0x200>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupt-parent = <&mpic>;
+ interrupts = <20 2>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupt-parent = <&mpic>;
+ interrupts = <21 2>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupt-parent = <&mpic>;
+ interrupts = <22 2>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupt-parent = <&mpic>;
+ interrupts = <23 2>;
+ };
+ };
+
+ usb@22000 {
+ compatible = "fsl-usb2-dr";
+ reg = <0x22000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&mpic>;
+ interrupts = <28 0x2>;
+ dr_mode = "host";
+ };
+
+ mdio@24000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,etsec2-mdio";
+ reg = <0x24000 0x1000 0xb0030 0x4>;
+ };
+
+ mdio@25000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,etsec2-tbi";
+ reg = <0x25000 0x1000 0xb1030 0x4>;
+ tbi0: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ mdio@26000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,etsec2-tbi";
+ reg = <0x26000 0x1000 0xb1030 0x4>;
+ tbi1: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ sdhci@2e000 {
+ compatible = "fsl,esdhc";
+ reg = <0x2e000 0x1000>;
+ interrupts = <72 0x8>;
+ interrupt-parent = <&mpic>;
+ /* Filled in by U-Boot */
+ clock-frequency = <0>;
+ fsl,sdhci-auto-cmd12;
+ };
+
+ enet0: ethernet@b0000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "fsl,etsec2";
+ fsl,num_rx_queues = <0x8>;
+ fsl,num_tx_queues = <0x8>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupt-parent = <&mpic>;
+
+ queue-group@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb0000 0x1000>;
+ fsl,rx-bit-map = <0xff>;
+ fsl,tx-bit-map = <0xff>;
+ interrupts = <29 2 30 2 34 2>;
+ };
+
+ };
+
+ enet1: ethernet@b1000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "fsl,etsec2";
+ fsl,num_rx_queues = <0x8>;
+ fsl,num_tx_queues = <0x8>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupt-parent = <&mpic>;
+ tbi-handle = <&tbi0>;
+
+ queue-group@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb1000 0x1000>;
+ fsl,rx-bit-map = <0xff>;
+ fsl,tx-bit-map = <0xff>;
+ interrupts = <35 2 36 2 40 2>;
+ };
+
+ };
+
+ enet2: ethernet@b2000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "fsl,etsec2";
+ fsl,num_rx_queues = <0x8>;
+ fsl,num_tx_queues = <0x8>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupt-parent = <&mpic>;
+ tbi-handle = <&tbi1>;
+
+ queue-group@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb2000 0x1000>;
+ fsl,rx-bit-map = <0xff>;
+ fsl,tx-bit-map = <0xff>;
+ interrupts = <31 2 32 2 33 2>;
+ };
+
+ };
+
+ mpic: pic@40000 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi@41600 {
+ compatible = "fsl,p1010-msi", "fsl,mpic-msi";
+ reg = <0x41600 0x80>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0
+ 0xe1 0
+ 0xe2 0
+ 0xe3 0
+ 0xe4 0
+ 0xe5 0
+ 0xe6 0
+ 0xe7 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+ global-utilities@e0000 { //global utilities block
+ compatible = "fsl,p1010-guts";
+ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+ };
+
+ pci0: pcie@ffe09000 {
+ compatible = "fsl,p1010-pcie", "fsl,qoriq-pcie-v2.3", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0 0xffe09000 0 0x1000>;
+ bus-range = <0 255>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+
+ pci1: pcie@ffe0a000 {
+ compatible = "fsl,p1010-pcie", "fsl,qoriq-pcie-v2.3", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0 0xffe0a000 0 0x1000>;
+ bus-range = <0 255>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+ interrupts = <16 2>;
+ };
+};
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 96b89df..306f4a0 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -25,6 +25,7 @@ CONFIG_MPC85xx_MDS=y
CONFIG_MPC8536_DS=y
CONFIG_MPC85xx_DS=y
CONFIG_MPC85xx_RDB=y
+CONFIG_P1010_RDB=y
CONFIG_P1022_DS=y
CONFIG_SOCRATES=y
CONFIG_KSI8560=y
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index b6976e1..07a3d29 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -67,6 +67,16 @@ config MPC85xx_RDB
help
This option enables support for the MPC85xx RDB (P2020 RDB) board
+config P1010_RDB
+ bool "Freescale P1010RDB"
+ select DEFAULT_UIMAGE
+ help
+ This option enables support for the MPC85xx RDB (P1010 RDB) board
+
+ P1010RDB contains P1010Si, which provides CPU performance up to 800
+ MHz and 1600 DMIPS, additional functionality and faster interfaces
+ (DDR3/3L, SATA II, and PCI Express).
+
config P1022_DS
bool "Freescale P1022 DS"
select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index dd70db7..07b40bf 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_MPC8536_DS) += mpc8536_ds.o
obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o
obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
+obj-$(CONFIG_P1010_RDB) += p1010rdb.o
obj-$(CONFIG_P1022_DS) += p1022_ds.o
obj-$(CONFIG_P3041_DS) += p3041_ds.o corenet_ds.o
obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c
new file mode 100644
index 0000000..d7387fa
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p1010rdb.c
@@ -0,0 +1,122 @@
+/*
+ * P1010RDB Board Setup
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/of_platform.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+void __init p1010_rdb_pic_init(void)
+{
+ struct mpic *mpic;
+ struct resource r;
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "open-pic");
+ if (np == NULL) {
+ printk(KERN_ERR "Could not find open-pic node\n");
+ return;
+ }
+
+ if (of_address_to_resource(np, 0, &r)) {
+ printk(KERN_ERR "Failed to map mpic register space\n");
+ of_node_put(np);
+ return;
+ }
+
+ mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET |
+ MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
+ 0, 256, " OpenPIC ");
+
+ BUG_ON(mpic == NULL);
+ of_node_put(np);
+
+ mpic_init(mpic);
+
+}
+
+
+/*
+ * Setup the architecture
+ */
+static void __init p1010_rdb_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+ struct device_node *np;
+#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("p1010_rdb_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+ for_each_node_by_type(np, "pci") {
+ if (of_device_is_compatible(np, "fsl,p1010-pcie"))
+ fsl_add_bridge(np, 0);
+ }
+
+#endif
+
+ printk(KERN_INFO "P1010 RDB board from Freescale Semiconductor\n");
+}
+
+static struct of_device_id __initdata p1010rdb_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .compatible = "simple-bus", },
+ {},
+};
+
+static int __init p1010rdb_publish_devices(void)
+{
+ return of_platform_bus_probe(NULL, p1010rdb_ids, NULL);
+}
+machine_device_initcall(p1010_rdb, p1010rdb_publish_devices);
+machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p1010_rdb_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (of_flat_dt_is_compatible(root, "fsl,P1010RDB"))
+ return 1;
+ return 0;
+}
+
+define_machine(p1010_rdb) {
+ .name = "P1010 RDB",
+ .probe = p1010_rdb_probe,
+ .setup_arch = p1010_rdb_setup_arch,
+ .init_IRQ = p1010_rdb_pic_init,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
--
1.7.3
^ permalink raw reply related
* Re: [PATCH] Fix build warning of the defconfigs
From: Hans-Christian Egtvedt @ 2011-06-06 6:24 UTC (permalink / raw)
To: Wanlong Gao
Cc: linux-mips, david.woodhouse, linux-sh, paulus, gxt, sam, linux,
manuel.lauss, rientjes, mingo, vapier, arnd, u.kleine-koenig,
anton, linux-arm-kernel, linux-kernel, ralf, lethal,
uclinux-dist-devel, akpm, linuxppc-dev
In-Reply-To: <1306945763-6583-1-git-send-email-wanlong.gao@gmail.com>
On Thu, 2011-06-02 at 00:29 +0800, Wanlong Gao wrote:
> RTC_CLASS is changed to bool.
> So value 'm' is invalid.
>
> Signed-off-by: Wanlong Gao <wanlong.gao@gmail.com>
<snipp>
> arch/avr32/configs/atngw100_mrmt_defconfig | 2 +-
>
For the AVR32 related changes.
Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
<snipp>
--
Hans-Christian Egtvedt
^ permalink raw reply
* Re: [RFC][PATCH] powerpc: Use the #address-cells information to parse memory/reg
From: Suzuki Poulose @ 2011-06-06 7:18 UTC (permalink / raw)
To: Simon Horman
Cc: Sebastian Andrzej Siewior, kexec@lists.infradead.org, lkml,
linux ppc dev, Vivek Goyal
In-Reply-To: <4DE3396E.4090801@in.ibm.com>
On 05/30/11 12:00, Suzuki Poulose wrote:
> Use the #address-cells, #size-cells information to parse the memory/reg info
> from device tree.
>
> The format of memory/reg is based on the #address-cells,#size-cells. Currently,
> the kexec-tools doesn't use the above values in parsing the memory/reg values.
> Hence the kexec cannot handle cases where #address-cells, #size-cells are
> different, (for e.g, PPC440X ).
>
> This patch introduces a read_memory_region_limits(), which parses the
> memory/reg contents based on the values of #address-cells and #size-cells.
>
> Changed the add_usable_mem_property() to accept FILE* fp instead of int fd,
> as most of the other users of read_memory_region_limits() deals with FILE*.
>
> Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
Could you please let me know your thoughts/comments about this patch ?
Thanks
Suzuki
>
> ---
> kexec/arch/ppc/crashdump-powerpc.c | 23 ------
> kexec/arch/ppc/fs2dt.c | 31 ++------
> kexec/arch/ppc/kexec-ppc.c | 136 ++++++++++++++++++++++++++-----------
> kexec/arch/ppc/kexec-ppc.h | 6 +
> 4 files changed, 118 insertions(+), 78 deletions(-)
>
> Index: kexec-tools-2.0.4/kexec/arch/ppc/kexec-ppc.c
> ===================================================================
> --- kexec-tools-2.0.4.orig/kexec/arch/ppc/kexec-ppc.c
> +++ kexec-tools-2.0.4/kexec/arch/ppc/kexec-ppc.c
> @@ -26,6 +26,7 @@
>
> #include "config.h"
>
> +unsigned long dt_address_cells = 0, dt_size_cells = 0;
> uint64_t rmo_top;
> unsigned long long crash_base = 0, crash_size = 0;
> unsigned long long initrd_base = 0, initrd_size = 0;
> @@ -34,6 +35,92 @@ unsigned int rtas_base, rtas_size;
> int max_memory_ranges;
> const char *ramdisk;
>
> +/*
> + * Reads the #address-cells and #size-cells on this platform.
> + * This is used to parse the memory/reg info from the device-tree
> + */
> +int init_memory_region_info()
> +{
> + size_t res = 0;
> + FILE *fp;
> + char *file;
> +
> + file = "/proc/device-tree/#address-cells";
> + fp = fopen(file, "r");
> + if (!fp) {
> + fprintf(stderr,"Unable to open %s\n", file);
> + return -1;
> + }
> +
> + res = fread(&dt_address_cells,sizeof(unsigned long),1,fp);
> + if (res != 1) {
> + fprintf(stderr,"Error reading %s\n", file);
> + return -1;
> + }
> + fclose(fp);
> + dt_address_cells *= sizeof(unsigned long);
> +
> + file = "/proc/device-tree/#size-cells";
> + fp = fopen(file, "r");
> + if (!fp) {
> + fprintf(stderr,"Unable to open %s\n", file);
> + return -1;
> + }
> +
> + res = fread(&dt_size_cells,sizeof(unsigned long),1,fp);
> + if (res != 1) {
> + fprintf(stderr,"Error reading %s\n", file);
> + return -1;
> + }
> + fclose(fp);
> + dt_size_cells *= sizeof(unsigned long);
> +
> + return 0;
> +}
> +
> +#define MAXBYTES 128
> +/*
> + * Reads the memory region info from the device-tree node pointed
> + * by @fp and fills the *start, *end with the boundaries of the region
> + */
> +int read_memory_region_limits(FILE* fp, unsigned long long *start,
> + unsigned long long *end)
> +{
> + char buf[MAXBYTES];
> + unsigned long *p;
> + unsigned long nbytes = dt_address_cells + dt_size_cells;
> +
> + if (fread(buf, 1, MAXBYTES, fp) != nbytes) {
> + fprintf(stderr, "Error reading the memory region info\n");
> + return -1;
> + }
> +
> + p = (unsigned long*)buf;
> + if (dt_address_cells == sizeof(unsigned long)) {
> + *start = p[0];
> + p++;
> + } else if (dt_address_cells == sizeof(unsigned long long)) {
> + *start = ((unsigned long long *)p)[0];
> + p = (unsigned long long *)p + 1;
> + } else {
> + fprintf(stderr,"Unsupported value for #address-cells : %ld\n",
> + dt_address_cells);
> + return -1;
> + }
> +
> + if (dt_size_cells == sizeof(unsigned long))
> + *end = *start + p[0];
> + else if (dt_size_cells == sizeof(unsigned long long))
> + *end = *start + ((unsigned long long *)p)[0];
> + else {
> + fprintf(stderr,"Unsupported value for #size-cells : %ld\n",
> + dt_size_cells);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> void arch_reuse_initrd(void)
> {
> reuse_initrd = 1;
> @@ -182,9 +269,6 @@ static int sort_base_ranges(void)
> return 0;
> }
>
> -
> -#define MAXBYTES 128
> -
> static int realloc_memory_ranges(void)
> {
> size_t memory_range_len;
> @@ -248,6 +332,8 @@ static int get_base_ranges(void)
> return -1;
> }
> while ((mentry = readdir(dmem)) != NULL) {
> + unsigned long long start, end;
> +
> if (strcmp(mentry->d_name, "reg"))
> continue;
> strcat(fname, "/reg");
> @@ -257,8 +343,7 @@ static int get_base_ranges(void)
> closedir(dir);
> return -1;
> }
> - if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
> - perror(fname);
> + if (read_memory_region_limits(file, &start, &end) != 0) {
> fclose(file);
> closedir(dmem);
> closedir(dir);
> @@ -271,24 +356,8 @@ static int get_base_ranges(void)
> }
> }
>
> - if (n == sizeof(uint32_t) * 2) {
> - base_memory_range[local_memory_ranges].start =
> - ((uint32_t *)buf)[0];
> - base_memory_range[local_memory_ranges].end =
> - base_memory_range[local_memory_ranges].start +
> - ((uint32_t *)buf)[1];
> - }
> - else if (n == sizeof(uint64_t) * 2) {
> - base_memory_range[local_memory_ranges].start =
> - ((uint64_t *)buf)[0];
> - base_memory_range[local_memory_ranges].end =
> - base_memory_range[local_memory_ranges].start +
> - ((uint64_t *)buf)[1];
> - }
> - else {
> - fprintf(stderr, "Mem node has invalid size: %d\n", n);
> - return -1;
> - }
> + base_memory_range[local_memory_ranges].start = start;
> + base_memory_range[local_memory_ranges].end = end;
> base_memory_range[local_memory_ranges].type = RANGE_RAM;
> local_memory_ranges++;
> dbgprintf("%016llx-%016llx : %x\n",
> @@ -577,20 +646,10 @@ static int get_devtree_details(unsigned
> perror(fname);
> goto error_opencdir;
> }
> - if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
> - perror(fname);
> - goto error_openfile;
> - }
> - if (n == sizeof(uint64_t)) {
> - rmo_base = ((uint32_t *)buf)[0];
> - rmo_top = rmo_base + ((uint32_t *)buf)[1];
> - } else if (n == 16) {
> - rmo_base = ((uint64_t *)buf)[0];
> - rmo_top = rmo_base + ((uint64_t *)buf)[1];
> - } else {
> - fprintf(stderr, "Mem node has invalid size: %d\n", n);
> + if (read_memory_region_limits(file, &rmo_base, &rmo_top) != 0) {
> goto error_openfile;
> }
> +
> if (rmo_top > 0x30000000UL)
> rmo_top = 0x30000000UL;
>
> @@ -664,7 +723,6 @@ error_opendir:
> return -1;
> }
>
> -
> /* Setup a sorted list of memory ranges. */
> static int setup_memory_ranges(unsigned long kexec_flags)
> {
> @@ -756,7 +814,6 @@ out:
> return -1;
> }
>
> -
> /* Return a list of valid memory ranges */
> int get_memory_ranges_dt(struct memory_range **range, int *ranges,
> unsigned long kexec_flags)
> @@ -778,6 +835,11 @@ int get_memory_ranges_dt(struct memory_r
> int get_memory_ranges(struct memory_range **range, int *ranges,
> unsigned long kexec_flags)
> {
> + int res = 0;
> +
> + res = init_memory_region_info();
> + if (res != 0)
> + return res;
> #ifdef WITH_GAMECUBE
> return get_memory_ranges_gc(range, ranges, kexec_flags);
> #else
> Index: kexec-tools-2.0.4/kexec/arch/ppc/kexec-ppc.h
> ===================================================================
> --- kexec-tools-2.0.4.orig/kexec/arch/ppc/kexec-ppc.h
> +++ kexec-tools-2.0.4/kexec/arch/ppc/kexec-ppc.h
> @@ -69,6 +69,12 @@ extern unsigned long long initrd_base, i
> extern unsigned long long ramdisk_base, ramdisk_size;
> extern unsigned char reuse_initrd;
> extern const char *ramdisk;
> +
> +/* Method to parse the memory/reg nodes in device-tree */
> +extern unsigned long dt_address_cells, dt_size_cells;
> +extern int init_memory_region_info(void);
> +extern int read_memory_region_limits(FILE *fp, unsigned long long *start,
> + unsigned long long *end);
> #define COMMAND_LINE_SIZE 512 /* from kernel */
> /*fs2dt*/
> void reserve(unsigned long long where, unsigned long long length);
> Index: kexec-tools-2.0.4/kexec/arch/ppc/crashdump-powerpc.c
> ===================================================================
> --- kexec-tools-2.0.4.orig/kexec/arch/ppc/crashdump-powerpc.c
> +++ kexec-tools-2.0.4/kexec/arch/ppc/crashdump-powerpc.c
> @@ -130,9 +130,8 @@ static int get_crash_memory_ranges(struc
> closedir(dir);
> goto err;
> }
> - n = fread(buf, 1, MAXBYTES, file);
> - if (n < 0) {
> - perror(fname);
> + n = read_memory_region_limits(file, &start, &end);
> + if (n != 0) {
> fclose(file);
> closedir(dmem);
> closedir(dir);
> @@ -146,24 +145,6 @@ static int get_crash_memory_ranges(struc
> goto err;
> }
>
> - /*
> - * FIXME: This code fails on platforms that
> - * have more than one memory range specified
> - * in the device-tree's /memory/reg property.
> - * or where the #address-cells and #size-cells
> - * are not identical.
> - *
> - * We should interpret the /memory/reg property
> - * based on the values of the #address-cells and
> - * #size-cells properites.
> - */
> - if (n == (sizeof(unsigned long) * 2)) {
> - start = ((unsigned long *)buf)[0];
> - end = start + ((unsigned long *)buf)[1];
> - } else {
> - start = ((unsigned long long *)buf)[0];
> - end = start + ((unsigned long long *)buf)[1];
> - }
> if (start == 0 && end >= (BACKUP_SRC_END + 1))
> start = BACKUP_SRC_END + 1;
>
> Index: kexec-tools-2.0.4/kexec/arch/ppc/fs2dt.c
> ===================================================================
> --- kexec-tools-2.0.4.orig/kexec/arch/ppc/fs2dt.c
> +++ kexec-tools-2.0.4/kexec/arch/ppc/fs2dt.c
> @@ -122,7 +122,7 @@ static unsigned propnum(const char *name
> return offset;
> }
>
> -static void add_usable_mem_property(int fd, int len)
> +static void add_usable_mem_property(FILE* fp, int len)
> {
> char fname[MAXPATH], *bname;
> unsigned long buf[2];
> @@ -137,21 +137,11 @@ static void add_usable_mem_property(int
> if (strncmp(bname, "/memory@", 8) && strcmp(bname, "/memory"))
> return;
>
> - if (len < 2 * sizeof(unsigned long))
> - die("unrecoverable error: not enough data for mem property\n");
> - len = 2 * sizeof(unsigned long);
> -
> - if (lseek(fd, 0, SEEK_SET) < 0)
> + if (fseek(fp, 0, SEEK_SET) < 0)
> die("unrecoverable error: error seeking in \"%s\": %s\n",
> pathname, strerror(errno));
> - if (read(fd, buf, len) != len)
> - die("unrecoverable error: error reading \"%s\": %s\n",
> - pathname, strerror(errno));
> -
> - if (~0ULL - buf[0] < buf[1])
> - die("unrecoverable error: mem property overflow\n");
> - base = buf[0];
> - end = base + buf[1];
> + if (read_memory_region_limits(fp, &base, &end) != 0)
> + die("unrecoverable error: error parsing memory/reg limits\n");
>
> for (range = 0; range < usablemem_rgns.size; range++) {
> loc_base = usablemem_rgns.ranges[range].start;
> @@ -194,8 +184,9 @@ static void add_usable_mem_property(int
> static void putprops(char *fn, struct dirent **nlist, int numlist)
> {
> struct dirent *dp;
> - int i = 0, fd, len;
> + int i = 0, len;
> struct stat statbuf;
> + FILE *fp;
>
> for (i = 0; i < numlist; i++) {
> dp = nlist[i];
> @@ -243,12 +234,12 @@ static void putprops(char *fn, struct di
> *dt++ = len;
> *dt++ = propnum(fn);
>
> - fd = open(pathname, O_RDONLY);
> - if (fd == -1)
> + fp = fopen(pathname, "r");
> + if (fp == NULL)
> die("unrecoverable error: could not open \"%s\": %s\n",
> pathname, strerror(errno));
>
> - if (read(fd, dt, len) != len)
> + if (fread(dt, 1, len, fp) != len)
> die("unrecoverable error: could not read \"%s\": %s\n",
> pathname, strerror(errno));
>
> @@ -290,8 +281,8 @@ static void putprops(char *fn, struct di
>
> dt += (len + 3)/4;
> if (!strcmp(dp->d_name, "reg") && usablemem_rgns.size)
> - add_usable_mem_property(fd, len);
> - close(fd);
> + add_usable_mem_property(fp, len);
> + fclose(fp);
> }
>
> fn[0] = '\0';
>
> _______________________________________________
> kexec mailing list
> kexec@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply
* Re: [RFC][PATCH] powerpc: Use the #address-cells information to parse memory/reg
From: Sebastian Andrzej Siewior @ 2011-06-06 8:51 UTC (permalink / raw)
To: Suzuki Poulose
Cc: kexec@lists.infradead.org, lkml, Simon Horman, linux ppc dev,
Vivek Goyal
In-Reply-To: <4DEC7F49.8060000@in.ibm.com>
Suzuki Poulose wrote:
> Could you please let me know your thoughts/comments about this patch ?
I'm mostly fine with it.
Maaxim copied fs2dt.c from ppc64 to ppc. So I guess ppc64 has the same
problem. ARM and MIPS is soon having DT support and kexec is probably also
on their list so I would hate to see them to either copy the DT parsing
file or having their own implementation.
Maybe we should try to use libfdt for dt parsing. It has /proc import
support so it should be fine for our needs. It is already in tree and used
by ppc32 if a basic dtb is specified. I'm not sure if the /proc interface
is part of dtc or libfdt.
I'm not saying this has to be done now but maybe later before ARM and/or
MIPS comes along needs something similar for their needs. If the libfdt is
too complex for sucking in the dtb from /proc then maybe something else
that generic and can be shared between booth ppc architectures and the
other ones.
> Thanks
> Suzuki
>
>>
>> Index: kexec-tools-2.0.4/kexec/arch/ppc/kexec-ppc.c
>> ===================================================================
>> --- kexec-tools-2.0.4.orig/kexec/arch/ppc/kexec-ppc.c
>> +++ kexec-tools-2.0.4/kexec/arch/ppc/kexec-ppc.c
>> @@ -34,6 +35,92 @@ unsigned int rtas_base, rtas_size;
>> int max_memory_ranges;
>> const char *ramdisk;
>>
>> +/*
>> + * Reads the #address-cells and #size-cells on this platform.
>> + * This is used to parse the memory/reg info from the device-tree
>> + */
>> +int init_memory_region_info()
>> +{
>> + size_t res = 0;
>> + FILE *fp;
>> + char *file;
>> +
>> + file = "/proc/device-tree/#address-cells";
>> + fp = fopen(file, "r");
>> + if (!fp) {
>> + fprintf(stderr,"Unable to open %s\n", file);
>> + return -1;
>> + }
>> +
>> + res = fread(&dt_address_cells,sizeof(unsigned long),1,fp);
>> + if (res != 1) {
>> + fprintf(stderr,"Error reading %s\n", file);
>> + return -1;
>> + }
>> + fclose(fp);
>> + dt_address_cells *= sizeof(unsigned long);
This should be sizeof(unsigned int). I know we on 32bit.
>> + file = "/proc/device-tree/#size-cells";
>> + fp = fopen(file, "r");
>> + if (!fp) {
>> + fprintf(stderr,"Unable to open %s\n", file);
>> + return -1;
>> + }
>> +
>> + res = fread(&dt_size_cells,sizeof(unsigned long),1,fp);
>> + if (res != 1) {
>> + fprintf(stderr,"Error reading %s\n", file);
>> + return -1;
>> + }
>> + fclose(fp);
>> + dt_size_cells *= sizeof(unsigned long);
same here.
>> +
>> + return 0;
>> +}
>> +
Sebastian
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox