aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-05 16:55:52 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-05 16:55:52 -0700
commit93273f5d8ace9bc03f0dc35ea98d229ed40f7860 (patch)
treecb13bf3e1cb0189be87387f7ac5ed45b638a1e5f
parentaeb7d5ed8d98be6d0ea91cbb4b5ee8d52538a14e (diff)
downloadpatches-93273f5d8ace9bc03f0dc35ea98d229ed40f7860.tar.gz
patches
-rw-r--r--drivers-uio-un-restrict-sysfs-pointers-for-uio.patch31
-rw-r--r--goldfish_pipe-an-implementation-of-more-parallel-pipe.patch1256
-rw-r--r--lib-vsprintf-add-pap-padp-options.patch77
-rw-r--r--lib-vsprintf-additional-kernel-pointer-filtering-options.patch221
-rw-r--r--lib-vsprintf-default-kptr_restrict-to-the-maximum-value.patch26
-rw-r--r--lib-vsprintf-physical-address-kernel-pointer-filtering-options.patch131
-rw-r--r--lib-vsprintf-whitelist-stack-traces.patch57
-rw-r--r--series7
8 files changed, 1806 insertions, 0 deletions
diff --git a/drivers-uio-un-restrict-sysfs-pointers-for-uio.patch b/drivers-uio-un-restrict-sysfs-pointers-for-uio.patch
new file mode 100644
index 00000000000000..7223ab865eef62
--- /dev/null
+++ b/drivers-uio-un-restrict-sysfs-pointers-for-uio.patch
@@ -0,0 +1,31 @@
+From: Chris Fries <cfries@google.com>
+Date: Thu, 27 Apr 2017 23:30:55 -0500
+Subject: drivers: uio: Un-restrict sysfs pointers for UIO
+
+The addr and size on the UIO devices are required by userspace to function
+properly. Let's unrestrict these by adding the 'P' modifier to %p and %pa.
+
+Signed-off-by: Chris Fries <cfries@google.com>
+---
+
+---
+ drivers/uio/uio.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/uio/uio.c
++++ b/drivers/uio/uio.c
+@@ -56,12 +56,12 @@ static ssize_t map_name_show(struct uio_
+
+ static ssize_t map_addr_show(struct uio_mem *mem, char *buf)
+ {
+- return sprintf(buf, "%pa\n", &mem->addr);
++ return sprintf(buf, "%paP\n", &mem->addr);
+ }
+
+ static ssize_t map_size_show(struct uio_mem *mem, char *buf)
+ {
+- return sprintf(buf, "%pa\n", &mem->size);
++ return sprintf(buf, "%paP\n", &mem->size);
+ }
+
+ static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
diff --git a/goldfish_pipe-an-implementation-of-more-parallel-pipe.patch b/goldfish_pipe-an-implementation-of-more-parallel-pipe.patch
new file mode 100644
index 00000000000000..3477c8d04aeb70
--- /dev/null
+++ b/goldfish_pipe-an-implementation-of-more-parallel-pipe.patch
@@ -0,0 +1,1256 @@
+From c53b6059ba261505317a4d8de63832846c9c92fb Mon Sep 17 00:00:00 2001
+From: Jin Qian <jinqian@android.com>
+Date: Mon, 27 Feb 2017 12:06:21 -0800
+Subject: goldfish_pipe: An implementation of more parallel pipe
+
+From: Jin Qian <jinqian@android.com>
+
+This is a driver code for a redesigned android pipe.
+Currently it works for x86 and x64 emulators with the following
+performance results:
+ ADB push to /dev/null,
+ Ubuntu,
+ 400 MB file,
+ times are for (1 / 10 / 100) parallel adb commands
+x86 adb push: (4.4s / 11.5s / 2m10s) -> (2.8s / 6s / 51s)
+x64 adb push: (7s / 15s / (too long, 6m+) -> (2.7s / 6.2s / 52s)
+
+ADB pull and push to /data/ have the same %% of speedup
+More importantly, I don't see any signs of slowdowns when
+run in parallel with Antutu benchmark, so it is definitely
+making much better job at multithreading.
+
+Signed-off-by: Yurii Zubrytskyi <zyy@google.com>
+Signed-off-by: Jin Qian <jinqian@android.com>
+---
+ drivers/platform/goldfish/goldfish_pipe.c | 976 +++++++++++++++--------
+
+---
+ drivers/platform/goldfish/goldfish_pipe.c | 976 +++++++++++++++++++-----------
+ 1 file changed, 644 insertions(+), 332 deletions(-)
+
+--- a/drivers/platform/goldfish/goldfish_pipe.c
++++ b/drivers/platform/goldfish/goldfish_pipe.c
+@@ -1,8 +1,8 @@
+ /*
+- * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2012 Intel, Inc.
+ * Copyright (C) 2013 Intel, Inc.
+ * Copyright (C) 2014 Linaro Limited
++ * Copyright (C) 2011-2016 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+@@ -46,6 +46,7 @@
+ * exchange is properly mapped during a transfer.
+ */
+
++
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
+ #include <linux/kernel.h>
+@@ -63,122 +64,232 @@
+ #include <linux/acpi.h>
+
+ /*
++ * Update this when something changes in the driver's behavior so the host
++ * can benefit from knowing it
++ */
++enum {
++ PIPE_DRIVER_VERSION = 2,
++ PIPE_CURRENT_DEVICE_VERSION = 2
++};
++
++/*
+ * IMPORTANT: The following constants must match the ones used and defined
+ * in external/qemu/hw/goldfish_pipe.c in the Android source tree.
+ */
+
+-/* pipe device registers */
+-#define PIPE_REG_COMMAND 0x00 /* write: value = command */
+-#define PIPE_REG_STATUS 0x04 /* read */
+-#define PIPE_REG_CHANNEL 0x08 /* read/write: channel id */
+-#define PIPE_REG_CHANNEL_HIGH 0x30 /* read/write: channel id */
+-#define PIPE_REG_SIZE 0x0c /* read/write: buffer size */
+-#define PIPE_REG_ADDRESS 0x10 /* write: physical address */
+-#define PIPE_REG_ADDRESS_HIGH 0x34 /* write: physical address */
+-#define PIPE_REG_WAKES 0x14 /* read: wake flags */
+-#define PIPE_REG_PARAMS_ADDR_LOW 0x18 /* read/write: batch data address */
+-#define PIPE_REG_PARAMS_ADDR_HIGH 0x1c /* read/write: batch data address */
+-#define PIPE_REG_ACCESS_PARAMS 0x20 /* write: batch access */
+-#define PIPE_REG_VERSION 0x24 /* read: device version */
+-
+-/* list of commands for PIPE_REG_COMMAND */
+-#define CMD_OPEN 1 /* open new channel */
+-#define CMD_CLOSE 2 /* close channel (from guest) */
+-#define CMD_POLL 3 /* poll read/write status */
+-
+ /* List of bitflags returned in status of CMD_POLL command */
+-#define PIPE_POLL_IN (1 << 0)
+-#define PIPE_POLL_OUT (1 << 1)
+-#define PIPE_POLL_HUP (1 << 2)
+-
+-/* The following commands are related to write operations */
+-#define CMD_WRITE_BUFFER 4 /* send a user buffer to the emulator */
+-#define CMD_WAKE_ON_WRITE 5 /* tell the emulator to wake us when writing
+- is possible */
+-#define CMD_READ_BUFFER 6 /* receive a user buffer from the emulator */
+-#define CMD_WAKE_ON_READ 7 /* tell the emulator to wake us when reading
+- * is possible */
++enum PipePollFlags {
++ PIPE_POLL_IN = 1 << 0,
++ PIPE_POLL_OUT = 1 << 1,
++ PIPE_POLL_HUP = 1 << 2
++};
+
+ /* Possible status values used to signal errors - see goldfish_pipe_error_convert */
+-#define PIPE_ERROR_INVAL -1
+-#define PIPE_ERROR_AGAIN -2
+-#define PIPE_ERROR_NOMEM -3
+-#define PIPE_ERROR_IO -4
++enum PipeErrors {
++ PIPE_ERROR_INVAL = -1,
++ PIPE_ERROR_AGAIN = -2,
++ PIPE_ERROR_NOMEM = -3,
++ PIPE_ERROR_IO = -4
++};
+
+ /* Bit-flags used to signal events from the emulator */
+-#define PIPE_WAKE_CLOSED (1 << 0) /* emulator closed pipe */
+-#define PIPE_WAKE_READ (1 << 1) /* pipe can now be read from */
+-#define PIPE_WAKE_WRITE (1 << 2) /* pipe can now be written to */
+-
+-struct access_params {
+- unsigned long channel;
+- u32 size;
+- unsigned long address;
+- u32 cmd;
+- u32 result;
+- /* reserved for future extension */
++enum PipeWakeFlags {
++ PIPE_WAKE_CLOSED = 1 << 0, /* emulator closed pipe */
++ PIPE_WAKE_READ = 1 << 1, /* pipe can now be read from */
++ PIPE_WAKE_WRITE = 1 << 2 /* pipe can now be written to */
++};
++
++/* Bit flags for the 'flags' field */
++enum PipeFlagsBits {
++ BIT_CLOSED_ON_HOST = 0, /* pipe closed by host */
++ BIT_WAKE_ON_WRITE = 1, /* want to be woken on writes */
++ BIT_WAKE_ON_READ = 2, /* want to be woken on reads */
++};
++
++enum PipeRegs {
++ PIPE_REG_CMD = 0,
++
++ PIPE_REG_SIGNAL_BUFFER_HIGH = 4,
++ PIPE_REG_SIGNAL_BUFFER = 8,
++ PIPE_REG_SIGNAL_BUFFER_COUNT = 12,
++
++ PIPE_REG_OPEN_BUFFER_HIGH = 20,
++ PIPE_REG_OPEN_BUFFER = 24,
++
++ PIPE_REG_VERSION = 36,
++
++ PIPE_REG_GET_SIGNALLED = 48,
++};
++
++enum PipeCmdCode {
++ PIPE_CMD_OPEN = 1, /* to be used by the pipe device itself */
++ PIPE_CMD_CLOSE,
++ PIPE_CMD_POLL,
++ PIPE_CMD_WRITE,
++ PIPE_CMD_WAKE_ON_WRITE,
++ PIPE_CMD_READ,
++ PIPE_CMD_WAKE_ON_READ,
++
++ /*
++ * TODO(zyy): implement a deferred read/write execution to allow
++ * parallel processing of pipe operations on the host.
++ */
++ PIPE_CMD_WAKE_ON_DONE_IO,
++};
++
++enum {
++ MAX_BUFFERS_PER_COMMAND = 336,
++ MAX_SIGNALLED_PIPES = 64,
++ INITIAL_PIPES_CAPACITY = 64
++};
++
++struct goldfish_pipe_dev;
++struct goldfish_pipe;
++struct goldfish_pipe_command;
++
++/* A per-pipe command structure, shared with the host */
++struct goldfish_pipe_command {
++ s32 cmd; /* PipeCmdCode, guest -> host */
++ s32 id; /* pipe id, guest -> host */
++ s32 status; /* command execution status, host -> guest */
++ s32 reserved; /* to pad to 64-bit boundary */
++ union {
++ /* Parameters for PIPE_CMD_{READ,WRITE} */
++ struct {
++ /* number of buffers, guest -> host */
++ u32 buffers_count;
++ /* number of consumed bytes, host -> guest */
++ s32 consumed_size;
++ /* buffer pointers, guest -> host */
++ u64 ptrs[MAX_BUFFERS_PER_COMMAND];
++ /* buffer sizes, guest -> host */
++ u32 sizes[MAX_BUFFERS_PER_COMMAND];
++ } rw_params;
++ };
++};
++
++/* A single signalled pipe information */
++struct signalled_pipe_buffer {
++ u32 id;
+ u32 flags;
+ };
+
+-/* The global driver data. Holds a reference to the i/o page used to
+- * communicate with the emulator, and a wake queue for blocked tasks
+- * waiting to be awoken.
+- */
+-struct goldfish_pipe_dev {
+- spinlock_t lock;
+- unsigned char __iomem *base;
+- struct access_params *aps;
+- int irq;
+- u32 version;
++/* Parameters for the PIPE_CMD_OPEN command */
++struct open_command_param {
++ u64 command_buffer_ptr;
++ u32 rw_params_max_count;
+ };
+
+-static struct goldfish_pipe_dev pipe_dev[1];
++/* Device-level set of buffers shared with the host */
++struct goldfish_pipe_dev_buffers {
++ struct open_command_param open_command_params;
++ struct signalled_pipe_buffer signalled_pipe_buffers[
++ MAX_SIGNALLED_PIPES];
++};
+
+ /* This data type models a given pipe instance */
+ struct goldfish_pipe {
+- struct goldfish_pipe_dev *dev;
+- struct mutex lock;
++ /* pipe ID - index into goldfish_pipe_dev::pipes array */
++ u32 id;
++ /* The wake flags pipe is waiting for
++ * Note: not protected with any lock, uses atomic operations
++ * and barriers to make it thread-safe.
++ */
+ unsigned long flags;
++ /* wake flags host have signalled,
++ * - protected by goldfish_pipe_dev::lock
++ */
++ unsigned long signalled_flags;
++
++ /* A pointer to command buffer */
++ struct goldfish_pipe_command *command_buffer;
++
++ /* doubly linked list of signalled pipes, protected by
++ * goldfish_pipe_dev::lock
++ */
++ struct goldfish_pipe *prev_signalled;
++ struct goldfish_pipe *next_signalled;
++
++ /*
++ * A pipe's own lock. Protects the following:
++ * - *command_buffer - makes sure a command can safely write its
++ * parameters to the host and read the results back.
++ */
++ struct mutex lock;
++
++ /* A wake queue for sleeping until host signals an event */
+ wait_queue_head_t wake_queue;
++ /* Pointer to the parent goldfish_pipe_dev instance */
++ struct goldfish_pipe_dev *dev;
+ };
+
++/* The global driver data. Holds a reference to the i/o page used to
++ * communicate with the emulator, and a wake queue for blocked tasks
++ * waiting to be awoken.
++ */
++struct goldfish_pipe_dev {
++ /*
++ * Global device spinlock. Protects the following members:
++ * - pipes, pipes_capacity
++ * - [*pipes, *pipes + pipes_capacity) - array data
++ * - first_signalled_pipe,
++ * goldfish_pipe::prev_signalled,
++ * goldfish_pipe::next_signalled,
++ * goldfish_pipe::signalled_flags - all singnalled-related fields,
++ * in all allocated pipes
++ * - open_command_params - PIPE_CMD_OPEN-related buffers
++ *
++ * It looks like a lot of different fields, but the trick is that
++ * the only operation that happens often is the signalled pipes array
++ * manipulation. That's why it's OK for now to keep the rest of the
++ * fields under the same lock. If we notice too much contention because
++ * of PIPE_CMD_OPEN, then we should add a separate lock there.
++ */
++ spinlock_t lock;
+
+-/* Bit flags for the 'flags' field */
+-enum {
+- BIT_CLOSED_ON_HOST = 0, /* pipe closed by host */
+- BIT_WAKE_ON_WRITE = 1, /* want to be woken on writes */
+- BIT_WAKE_ON_READ = 2, /* want to be woken on reads */
++ /*
++ * Array of the pipes of |pipes_capacity| elements,
++ * indexed by goldfish_pipe::id
++ */
++ struct goldfish_pipe **pipes;
++ u32 pipes_capacity;
++
++ /* Pointers to the buffers host uses for interaction with this driver */
++ struct goldfish_pipe_dev_buffers *buffers;
++
++ /* Head of a doubly linked list of signalled pipes */
++ struct goldfish_pipe *first_signalled_pipe;
++
++ /* Some device-specific data */
++ int irq;
++ int version;
++ unsigned char __iomem *base;
+ };
+
++struct goldfish_pipe_dev pipe_dev[1] = {};
+
+-static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd)
++static int goldfish_cmd_locked(struct goldfish_pipe *pipe, enum PipeCmdCode cmd)
+ {
+- unsigned long flags;
+- u32 status;
+- struct goldfish_pipe_dev *dev = pipe->dev;
+-
+- spin_lock_irqsave(&dev->lock, flags);
+- gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+- dev->base + PIPE_REG_CHANNEL_HIGH);
+- writel(cmd, dev->base + PIPE_REG_COMMAND);
+- status = readl(dev->base + PIPE_REG_STATUS);
+- spin_unlock_irqrestore(&dev->lock, flags);
+- return status;
++ pipe->command_buffer->cmd = cmd;
++ /* failure by default */
++ pipe->command_buffer->status = PIPE_ERROR_INVAL;
++ writel(pipe->id, pipe->dev->base + PIPE_REG_CMD);
++ return pipe->command_buffer->status;
+ }
+
+-static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd)
++static int goldfish_cmd(struct goldfish_pipe *pipe, enum PipeCmdCode cmd)
+ {
+- unsigned long flags;
+- struct goldfish_pipe_dev *dev = pipe->dev;
++ int status;
+
+- spin_lock_irqsave(&dev->lock, flags);
+- gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+- dev->base + PIPE_REG_CHANNEL_HIGH);
+- writel(cmd, dev->base + PIPE_REG_COMMAND);
+- spin_unlock_irqrestore(&dev->lock, flags);
++ if (mutex_lock_interruptible(&pipe->lock))
++ return PIPE_ERROR_IO;
++ status = goldfish_cmd_locked(pipe, cmd);
++ mutex_unlock(&pipe->lock);
++ return status;
+ }
+
+-/* This function converts an error code returned by the emulator through
++/*
++ * This function converts an error code returned by the emulator through
+ * the PIPE_REG_STATUS i/o register into a valid negative errno value.
+ */
+ static int goldfish_pipe_error_convert(int status)
+@@ -195,184 +306,202 @@ static int goldfish_pipe_error_convert(i
+ }
+ }
+
+-/*
+- * Notice: QEMU will return 0 for un-known register access, indicating
+- * param_acess is supported or not
+- */
+-static int valid_batchbuffer_addr(struct goldfish_pipe_dev *dev,
+- struct access_params *aps)
++static int pin_user_pages(unsigned long first_page, unsigned long last_page,
++ unsigned int last_page_size, int is_write,
++ struct page *pages[MAX_BUFFERS_PER_COMMAND],
++ unsigned int *iter_last_page_size)
++{
++ int ret;
++ int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1;
++
++ if (requested_pages > MAX_BUFFERS_PER_COMMAND) {
++ requested_pages = MAX_BUFFERS_PER_COMMAND;
++ *iter_last_page_size = PAGE_SIZE;
++ } else {
++ *iter_last_page_size = last_page_size;
++ }
++
++ ret = get_user_pages_fast(
++ first_page, requested_pages, !is_write, pages);
++ if (ret <= 0)
++ return -EFAULT;
++ if (ret < requested_pages)
++ *iter_last_page_size = PAGE_SIZE;
++ return ret;
++
++}
++
++static void release_user_pages(struct page **pages, int pages_count,
++ int is_write, s32 consumed_size)
+ {
+- u32 aph, apl;
+- u64 paddr;
+- aph = readl(dev->base + PIPE_REG_PARAMS_ADDR_HIGH);
+- apl = readl(dev->base + PIPE_REG_PARAMS_ADDR_LOW);
++ int i;
+
+- paddr = ((u64)aph << 32) | apl;
+- if (paddr != (__pa(aps)))
+- return 0;
+- return 1;
++ for (i = 0; i < pages_count; i++) {
++ if (!is_write && consumed_size > 0)
++ set_page_dirty(pages[i]);
++ put_page(pages[i]);
++ }
++}
++
++/* Populate the call parameters, merging adjacent pages together */
++static void populate_rw_params(
++ struct page **pages, int pages_count,
++ unsigned long address, unsigned long address_end,
++ unsigned long first_page, unsigned long last_page,
++ unsigned int iter_last_page_size, int is_write,
++ struct goldfish_pipe_command *command)
++{
++ /*
++ * Process the first page separately - it's the only page that
++ * needs special handling for its start address.
++ */
++ unsigned long xaddr = page_to_phys(pages[0]);
++ unsigned long xaddr_prev = xaddr;
++ int buffer_idx = 0;
++ int i = 1;
++ int size_on_page = first_page == last_page
++ ? (int)(address_end - address)
++ : (PAGE_SIZE - (address & ~PAGE_MASK));
++ command->rw_params.ptrs[0] = (u64)(xaddr | (address & ~PAGE_MASK));
++ command->rw_params.sizes[0] = size_on_page;
++ for (; i < pages_count; ++i) {
++ xaddr = page_to_phys(pages[i]);
++ size_on_page = (i == pages_count - 1) ?
++ iter_last_page_size : PAGE_SIZE;
++ if (xaddr == xaddr_prev + PAGE_SIZE) {
++ command->rw_params.sizes[buffer_idx] += size_on_page;
++ } else {
++ ++buffer_idx;
++ command->rw_params.ptrs[buffer_idx] = (u64)xaddr;
++ command->rw_params.sizes[buffer_idx] = size_on_page;
++ }
++ xaddr_prev = xaddr;
++ }
++ command->rw_params.buffers_count = buffer_idx + 1;
+ }
+
+-/* 0 on success */
+-static int setup_access_params_addr(struct platform_device *pdev,
+- struct goldfish_pipe_dev *dev)
++static int transfer_max_buffers(struct goldfish_pipe *pipe,
++ unsigned long address, unsigned long address_end, int is_write,
++ unsigned long last_page, unsigned int last_page_size,
++ s32 *consumed_size, int *status)
+ {
+- dma_addr_t dma_handle;
+- struct access_params *aps;
++ struct page *pages[MAX_BUFFERS_PER_COMMAND];
++ unsigned long first_page = address & PAGE_MASK;
++ unsigned int iter_last_page_size;
++ int pages_count = pin_user_pages(first_page, last_page,
++ last_page_size, is_write,
++ pages, &iter_last_page_size);
+
+- aps = dmam_alloc_coherent(&pdev->dev, sizeof(struct access_params),
+- &dma_handle, GFP_KERNEL);
+- if (!aps)
+- return -ENOMEM;
++ if (pages_count < 0)
++ return pages_count;
+
+- writel(upper_32_bits(dma_handle), dev->base + PIPE_REG_PARAMS_ADDR_HIGH);
+- writel(lower_32_bits(dma_handle), dev->base + PIPE_REG_PARAMS_ADDR_LOW);
++ /* Serialize access to the pipe command buffers */
++ if (mutex_lock_interruptible(&pipe->lock))
++ return -ERESTARTSYS;
+
+- if (valid_batchbuffer_addr(dev, aps)) {
+- dev->aps = aps;
+- return 0;
+- } else
+- return -1;
++ populate_rw_params(pages, pages_count, address, address_end,
++ first_page, last_page, iter_last_page_size, is_write,
++ pipe->command_buffer);
++
++ /* Transfer the data */
++ *status = goldfish_cmd_locked(pipe,
++ is_write ? PIPE_CMD_WRITE : PIPE_CMD_READ);
++
++ *consumed_size = pipe->command_buffer->rw_params.consumed_size;
++
++ mutex_unlock(&pipe->lock);
++
++ release_user_pages(pages, pages_count, is_write, *consumed_size);
++
++ return 0;
+ }
+
+-/* A value that will not be set by qemu emulator */
+-#define INITIAL_BATCH_RESULT (0xdeadbeaf)
+-static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd,
+- unsigned long address, unsigned long avail,
+- struct goldfish_pipe *pipe, int *status)
+-{
+- struct access_params *aps = dev->aps;
+-
+- if (aps == NULL)
+- return -1;
+-
+- aps->result = INITIAL_BATCH_RESULT;
+- aps->channel = (unsigned long)pipe;
+- aps->size = avail;
+- aps->address = address;
+- aps->cmd = cmd;
+- writel(cmd, dev->base + PIPE_REG_ACCESS_PARAMS);
+- /*
+- * If the aps->result has not changed, that means
+- * that the batch command failed
+- */
+- if (aps->result == INITIAL_BATCH_RESULT)
+- return -1;
+- *status = aps->result;
++static int wait_for_host_signal(struct goldfish_pipe *pipe, int is_write)
++{
++ u32 wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ;
++
++ set_bit(wakeBit, &pipe->flags);
++
++ /* Tell the emulator we're going to wait for a wake event */
++ (void)goldfish_cmd(pipe,
++ is_write ? PIPE_CMD_WAKE_ON_WRITE : PIPE_CMD_WAKE_ON_READ);
++
++ while (test_bit(wakeBit, &pipe->flags)) {
++ if (wait_event_interruptible(
++ pipe->wake_queue,
++ !test_bit(wakeBit, &pipe->flags)))
++ return -ERESTARTSYS;
++
++ if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))
++ return -EIO;
++ }
++
+ return 0;
+ }
+
+-static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer,
+- size_t bufflen, int is_write)
++static ssize_t goldfish_pipe_read_write(struct file *filp,
++ char __user *buffer, size_t bufflen, int is_write)
+ {
+- unsigned long irq_flags;
+ struct goldfish_pipe *pipe = filp->private_data;
+- struct goldfish_pipe_dev *dev = pipe->dev;
+- unsigned long address, address_end;
+ int count = 0, ret = -EINVAL;
++ unsigned long address, address_end, last_page;
++ unsigned int last_page_size;
+
+ /* If the emulator already closed the pipe, no need to go further */
+- if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))
++ if (unlikely(test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)))
+ return -EIO;
+-
+ /* Null reads or writes succeeds */
+ if (unlikely(bufflen == 0))
+ return 0;
+-
+ /* Check the buffer range for access */
+- if (!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ,
+- buffer, bufflen))
++ if (unlikely(!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ,
++ buffer, bufflen)))
+ return -EFAULT;
+
+- /* Serialize access to the pipe */
+- if (mutex_lock_interruptible(&pipe->lock))
+- return -ERESTARTSYS;
+-
+- address = (unsigned long)(void *)buffer;
++ address = (unsigned long)buffer;
+ address_end = address + bufflen;
++ last_page = (address_end - 1) & PAGE_MASK;
++ last_page_size = ((address_end - 1) & ~PAGE_MASK) + 1;
+
+ while (address < address_end) {
+- unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE;
+- unsigned long next = page_end < address_end ? page_end
+- : address_end;
+- unsigned long avail = next - address;
+- int status, wakeBit;
+- struct page *page;
+-
+- /* Either vaddr or paddr depending on the device version */
+- unsigned long xaddr;
++ s32 consumed_size;
++ int status;
+
+- /*
+- * We grab the pages on a page-by-page basis in case user
+- * space gives us a potentially huge buffer but the read only
+- * returns a small amount, then there's no need to pin that
+- * much memory to the process.
+- */
+- ret = get_user_pages_unlocked(address, 1, &page,
+- is_write ? 0 : FOLL_WRITE);
++ ret = transfer_max_buffers(pipe, address, address_end, is_write,
++ last_page, last_page_size, &consumed_size,
++ &status);
+ if (ret < 0)
+ break;
+
+- if (dev->version) {
+- /* Device version 1 or newer (qemu-android) expects the
+- * physical address.
++ if (consumed_size > 0) {
++ /* No matter what's the status, we've transferred
++ * something.
+ */
+- xaddr = page_to_phys(page) | (address & ~PAGE_MASK);
+- } else {
+- /* Device version 0 (classic emulator) expects the
+- * virtual address.
+- */
+- xaddr = address;
++ count += consumed_size;
++ address += consumed_size;
+ }
+-
+- /* Now, try to transfer the bytes in the current page */
+- spin_lock_irqsave(&dev->lock, irq_flags);
+- if (access_with_param(dev,
+- is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER,
+- xaddr, avail, pipe, &status)) {
+- gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+- dev->base + PIPE_REG_CHANNEL_HIGH);
+- writel(avail, dev->base + PIPE_REG_SIZE);
+- gf_write_ptr((void *)xaddr,
+- dev->base + PIPE_REG_ADDRESS,
+- dev->base + PIPE_REG_ADDRESS_HIGH);
+- writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER,
+- dev->base + PIPE_REG_COMMAND);
+- status = readl(dev->base + PIPE_REG_STATUS);
+- }
+- spin_unlock_irqrestore(&dev->lock, irq_flags);
+-
+- if (status > 0 && !is_write)
+- set_page_dirty(page);
+- put_page(page);
+-
+- if (status > 0) { /* Correct transfer */
+- count += status;
+- address += status;
++ if (status > 0)
+ continue;
+- } else if (status == 0) { /* EOF */
++ if (status == 0) {
++ /* EOF */
+ ret = 0;
+ break;
+- } else if (status < 0 && count > 0) {
++ }
++ if (count > 0) {
+ /*
+- * An error occurred and we already transferred
+- * something on one of the previous pages.
++ * An error occurred, but we already transferred
++ * something on one of the previous iterations.
+ * Just return what we already copied and log this
+ * err.
+- *
+- * Note: This seems like an incorrect approach but
+- * cannot change it until we check if any user space
+- * ABI relies on this behavior.
+ */
+ if (status != PIPE_ERROR_AGAIN)
+- pr_info_ratelimited("goldfish_pipe: backend returned error %d on %s\n",
++ pr_info_ratelimited("goldfish_pipe: backend error %d on %s\n",
+ status, is_write ? "write" : "read");
+- ret = 0;
+ break;
+ }
+
+ /*
+- * If the error is not PIPE_ERROR_AGAIN, or if we are not in
++ * If the error is not PIPE_ERROR_AGAIN, or if we are in
+ * non-blocking mode, just return the error code.
+ */
+ if (status != PIPE_ERROR_AGAIN ||
+@@ -381,139 +510,214 @@ static ssize_t goldfish_pipe_read_write(
+ break;
+ }
+
+- /*
+- * The backend blocked the read/write, wait until the backend
+- * tells us it's ready to process more data.
+- */
+- wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ;
+- set_bit(wakeBit, &pipe->flags);
+-
+- /* Tell the emulator we're going to wait for a wake event */
+- goldfish_cmd(pipe,
+- is_write ? CMD_WAKE_ON_WRITE : CMD_WAKE_ON_READ);
+-
+- /* Unlock the pipe, then wait for the wake signal */
+- mutex_unlock(&pipe->lock);
+-
+- while (test_bit(wakeBit, &pipe->flags)) {
+- if (wait_event_interruptible(
+- pipe->wake_queue,
+- !test_bit(wakeBit, &pipe->flags)))
+- return -ERESTARTSYS;
+-
+- if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))
+- return -EIO;
+- }
+-
+- /* Try to re-acquire the lock */
+- if (mutex_lock_interruptible(&pipe->lock))
+- return -ERESTARTSYS;
++ status = wait_for_host_signal(pipe, is_write);
++ if (status < 0)
++ return status;
+ }
+- mutex_unlock(&pipe->lock);
+
+- if (ret < 0)
+- return ret;
+- else
++ if (count > 0)
+ return count;
++ return ret;
+ }
+
+ static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer,
+- size_t bufflen, loff_t *ppos)
++ size_t bufflen, loff_t *ppos)
+ {
+- return goldfish_pipe_read_write(filp, buffer, bufflen, 0);
++ return goldfish_pipe_read_write(filp, buffer, bufflen,
++ /* is_write */ 0);
+ }
+
+ static ssize_t goldfish_pipe_write(struct file *filp,
+ const char __user *buffer, size_t bufflen,
+ loff_t *ppos)
+ {
+- return goldfish_pipe_read_write(filp, (char __user *)buffer,
+- bufflen, 1);
++ return goldfish_pipe_read_write(filp,
++ /* cast away the const */(char __user *)buffer, bufflen,
++ /* is_write */ 1);
+ }
+
+-
+ static unsigned int goldfish_pipe_poll(struct file *filp, poll_table *wait)
+ {
+ struct goldfish_pipe *pipe = filp->private_data;
+ unsigned int mask = 0;
+ int status;
+
+- mutex_lock(&pipe->lock);
+-
+ poll_wait(filp, &pipe->wake_queue, wait);
+
+- status = goldfish_cmd_status(pipe, CMD_POLL);
+-
+- mutex_unlock(&pipe->lock);
++ status = goldfish_cmd(pipe, PIPE_CMD_POLL);
++ if (status < 0)
++ return -ERESTARTSYS;
+
+ if (status & PIPE_POLL_IN)
+ mask |= POLLIN | POLLRDNORM;
+-
+ if (status & PIPE_POLL_OUT)
+ mask |= POLLOUT | POLLWRNORM;
+-
+ if (status & PIPE_POLL_HUP)
+ mask |= POLLHUP;
+-
+ if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))
+ mask |= POLLERR;
+
+ return mask;
+ }
+
+-static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id)
++static void signalled_pipes_add_locked(struct goldfish_pipe_dev *dev,
++ u32 id, u32 flags)
+ {
+- struct goldfish_pipe_dev *dev = dev_id;
+- unsigned long irq_flags;
+- int count = 0;
++ struct goldfish_pipe *pipe;
+
+- /*
+- * We're going to read from the emulator a list of (channel,flags)
+- * pairs corresponding to the wake events that occurred on each
+- * blocked pipe (i.e. channel).
+- */
+- spin_lock_irqsave(&dev->lock, irq_flags);
+- for (;;) {
+- /* First read the channel, 0 means the end of the list */
+- struct goldfish_pipe *pipe;
+- unsigned long wakes;
+- unsigned long channel = 0;
++ if (WARN_ON(id >= dev->pipes_capacity))
++ return;
+
+-#ifdef CONFIG_64BIT
+- channel = (u64)readl(dev->base + PIPE_REG_CHANNEL_HIGH) << 32;
++ pipe = dev->pipes[id];
++ if (!pipe)
++ return;
++ pipe->signalled_flags |= flags;
++
++ if (pipe->prev_signalled || pipe->next_signalled
++ || dev->first_signalled_pipe == pipe)
++ return; /* already in the list */
++ pipe->next_signalled = dev->first_signalled_pipe;
++ if (dev->first_signalled_pipe)
++ dev->first_signalled_pipe->prev_signalled = pipe;
++ dev->first_signalled_pipe = pipe;
++}
++
++static void signalled_pipes_remove_locked(struct goldfish_pipe_dev *dev,
++ struct goldfish_pipe *pipe) {
++ if (pipe->prev_signalled)
++ pipe->prev_signalled->next_signalled = pipe->next_signalled;
++ if (pipe->next_signalled)
++ pipe->next_signalled->prev_signalled = pipe->prev_signalled;
++ if (pipe == dev->first_signalled_pipe)
++ dev->first_signalled_pipe = pipe->next_signalled;
++ pipe->prev_signalled = NULL;
++ pipe->next_signalled = NULL;
++}
+
+- if (channel == 0)
+- break;
+-#endif
+- channel |= readl(dev->base + PIPE_REG_CHANNEL);
++static struct goldfish_pipe *signalled_pipes_pop_front(
++ struct goldfish_pipe_dev *dev, int *wakes)
++{
++ struct goldfish_pipe *pipe;
++ unsigned long flags;
+
+- if (channel == 0)
+- break;
++ spin_lock_irqsave(&dev->lock, flags);
+
+- /* Convert channel to struct pipe pointer + read wake flags */
+- wakes = readl(dev->base + PIPE_REG_WAKES);
+- pipe = (struct goldfish_pipe *)(ptrdiff_t)channel;
++ pipe = dev->first_signalled_pipe;
++ if (pipe) {
++ *wakes = pipe->signalled_flags;
++ pipe->signalled_flags = 0;
++ /*
++ * This is an optimized version of
++ * signalled_pipes_remove_locked()
++ * - We want to make it as fast as possible to
++ * wake the sleeping pipe operations faster.
++ */
++ dev->first_signalled_pipe = pipe->next_signalled;
++ if (dev->first_signalled_pipe)
++ dev->first_signalled_pipe->prev_signalled = NULL;
++ pipe->next_signalled = NULL;
++ }
+
+- /* Did the emulator just closed a pipe? */
++ spin_unlock_irqrestore(&dev->lock, flags);
++ return pipe;
++}
++
++static void goldfish_interrupt_task(unsigned long unused)
++{
++ struct goldfish_pipe_dev *dev = pipe_dev;
++ /* Iterate over the signalled pipes and wake them one by one */
++ struct goldfish_pipe *pipe;
++ int wakes;
++
++ while ((pipe = signalled_pipes_pop_front(dev, &wakes)) != NULL) {
+ if (wakes & PIPE_WAKE_CLOSED) {
+- set_bit(BIT_CLOSED_ON_HOST, &pipe->flags);
+- wakes |= PIPE_WAKE_READ | PIPE_WAKE_WRITE;
++ pipe->flags = 1 << BIT_CLOSED_ON_HOST;
++ } else {
++ if (wakes & PIPE_WAKE_READ)
++ clear_bit(BIT_WAKE_ON_READ, &pipe->flags);
++ if (wakes & PIPE_WAKE_WRITE)
++ clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags);
+ }
+- if (wakes & PIPE_WAKE_READ)
+- clear_bit(BIT_WAKE_ON_READ, &pipe->flags);
+- if (wakes & PIPE_WAKE_WRITE)
+- clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags);
+-
++ /*
++ * wake_up_interruptible() implies a write barrier, so don't
++ * explicitly add another one here.
++ */
+ wake_up_interruptible(&pipe->wake_queue);
+- count++;
+ }
+- spin_unlock_irqrestore(&dev->lock, irq_flags);
++}
++DECLARE_TASKLET(goldfish_interrupt_tasklet, goldfish_interrupt_task, 0);
++
++/*
++ * The general idea of the interrupt handling:
++ *
++ * 1. device raises an interrupt if there's at least one signalled pipe
++ * 2. IRQ handler reads the signalled pipes and their count from the device
++ * 3. device writes them into a shared buffer and returns the count
++ * it only resets the IRQ if it has returned all signalled pipes,
++ * otherwise it leaves it raised, so IRQ handler will be called
++ * again for the next chunk
++ * 4. IRQ handler adds all returned pipes to the device's signalled pipes list
++ * 5. IRQ handler launches a tasklet to process the signalled pipes from the
++ * list in a separate context
++ */
++static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id)
++{
++ u32 count;
++ u32 i;
++ unsigned long flags;
++ struct goldfish_pipe_dev *dev = dev_id;
++
++ if (dev != pipe_dev)
++ return IRQ_NONE;
++
++ /* Request the signalled pipes from the device */
++ spin_lock_irqsave(&dev->lock, flags);
++
++ count = readl(dev->base + PIPE_REG_GET_SIGNALLED);
++ if (count == 0) {
++ spin_unlock_irqrestore(&dev->lock, flags);
++ return IRQ_NONE;
++ }
++ if (count > MAX_SIGNALLED_PIPES)
++ count = MAX_SIGNALLED_PIPES;
+
+- return (count == 0) ? IRQ_NONE : IRQ_HANDLED;
++ for (i = 0; i < count; ++i)
++ signalled_pipes_add_locked(dev,
++ dev->buffers->signalled_pipe_buffers[i].id,
++ dev->buffers->signalled_pipe_buffers[i].flags);
++
++ spin_unlock_irqrestore(&dev->lock, flags);
++
++ tasklet_schedule(&goldfish_interrupt_tasklet);
++ return IRQ_HANDLED;
++}
++
++static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev)
++{
++ int id;
++
++ for (id = 0; id < dev->pipes_capacity; ++id)
++ if (!dev->pipes[id])
++ return id;
++
++ {
++ /* Reallocate the array */
++ u32 new_capacity = 2 * dev->pipes_capacity;
++ struct goldfish_pipe **pipes =
++ kcalloc(new_capacity, sizeof(*pipes), GFP_KERNEL);
++ if (!pipes)
++ return -ENOMEM;
++ memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity);
++ kfree(dev->pipes);
++ dev->pipes = pipes;
++ id = dev->pipes_capacity;
++ dev->pipes_capacity = new_capacity;
++ }
++ return id;
+ }
+
+ /**
+- * goldfish_pipe_open - open a channel to the AVD
++ * goldfish_pipe_open - open a channel to the AVD
+ * @inode: inode of device
+ * @file: file struct of opener
+ *
+@@ -525,12 +729,13 @@ static irqreturn_t goldfish_pipe_interru
+ */
+ static int goldfish_pipe_open(struct inode *inode, struct file *file)
+ {
+- struct goldfish_pipe *pipe;
+ struct goldfish_pipe_dev *dev = pipe_dev;
+- int32_t status;
++ unsigned long flags;
++ int id;
++ int status;
+
+ /* Allocate new pipe kernel object */
+- pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
++ struct goldfish_pipe *pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
+ if (pipe == NULL)
+ return -ENOMEM;
+
+@@ -539,29 +744,69 @@ static int goldfish_pipe_open(struct ino
+ init_waitqueue_head(&pipe->wake_queue);
+
+ /*
+- * Now, tell the emulator we're opening a new pipe. We use the
+- * pipe object's address as the channel identifier for simplicity.
++ * Command buffer needs to be allocated on its own page to make sure
++ * it is physically contiguous in host's address space.
+ */
++ pipe->command_buffer =
++ (struct goldfish_pipe_command *)__get_free_page(GFP_KERNEL);
++ if (!pipe->command_buffer) {
++ status = -ENOMEM;
++ goto err_pipe;
++ }
+
+- status = goldfish_cmd_status(pipe, CMD_OPEN);
+- if (status < 0) {
+- kfree(pipe);
+- return status;
++ spin_lock_irqsave(&dev->lock, flags);
++
++ id = get_free_pipe_id_locked(dev);
++ if (id < 0) {
++ status = id;
++ goto err_id_locked;
+ }
+
++ dev->pipes[id] = pipe;
++ pipe->id = id;
++ pipe->command_buffer->id = id;
++
++ /* Now tell the emulator we're opening a new pipe. */
++ dev->buffers->open_command_params.rw_params_max_count =
++ MAX_BUFFERS_PER_COMMAND;
++ dev->buffers->open_command_params.command_buffer_ptr =
++ (u64)(unsigned long)__pa(pipe->command_buffer);
++ status = goldfish_cmd_locked(pipe, PIPE_CMD_OPEN);
++ spin_unlock_irqrestore(&dev->lock, flags);
++ if (status < 0)
++ goto err_cmd;
+ /* All is done, save the pipe into the file's private data field */
+ file->private_data = pipe;
+ return 0;
++
++err_cmd:
++ spin_lock_irqsave(&dev->lock, flags);
++ dev->pipes[id] = NULL;
++err_id_locked:
++ spin_unlock_irqrestore(&dev->lock, flags);
++ free_page((unsigned long)pipe->command_buffer);
++err_pipe:
++ kfree(pipe);
++ return status;
+ }
+
+ static int goldfish_pipe_release(struct inode *inode, struct file *filp)
+ {
++ unsigned long flags;
+ struct goldfish_pipe *pipe = filp->private_data;
++ struct goldfish_pipe_dev *dev = pipe->dev;
+
+ /* The guest is closing the channel, so tell the emulator right now */
+- goldfish_cmd(pipe, CMD_CLOSE);
+- kfree(pipe);
++ (void)goldfish_cmd(pipe, PIPE_CMD_CLOSE);
++
++ spin_lock_irqsave(&dev->lock, flags);
++ dev->pipes[pipe->id] = NULL;
++ signalled_pipes_remove_locked(dev, pipe);
++ spin_unlock_irqrestore(&dev->lock, flags);
++
+ filp->private_data = NULL;
++ free_page((unsigned long)pipe->command_buffer);
++ kfree(pipe);
+ return 0;
+ }
+
+@@ -574,18 +819,91 @@ static const struct file_operations gold
+ .release = goldfish_pipe_release,
+ };
+
+-static struct miscdevice goldfish_pipe_device = {
++static struct miscdevice goldfish_pipe_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "goldfish_pipe",
+ .fops = &goldfish_pipe_fops,
+ };
+
++static int goldfish_pipe_device_init(struct platform_device *pdev)
++{
++ char *page;
++ struct goldfish_pipe_dev *dev = pipe_dev;
++ int err = devm_request_irq(&pdev->dev, dev->irq,
++ goldfish_pipe_interrupt,
++ IRQF_SHARED, "goldfish_pipe", dev);
++ if (err) {
++ dev_err(&pdev->dev, "unable to allocate IRQ for v2\n");
++ return err;
++ }
++
++ err = misc_register(&goldfish_pipe_dev);
++ if (err) {
++ dev_err(&pdev->dev, "unable to register v2 device\n");
++ return err;
++ }
++
++ dev->first_signalled_pipe = NULL;
++ dev->pipes_capacity = INITIAL_PIPES_CAPACITY;
++ dev->pipes = kcalloc(dev->pipes_capacity, sizeof(*dev->pipes),
++ GFP_KERNEL);
++ if (!dev->pipes)
++ return -ENOMEM;
++
++ /*
++ * We're going to pass two buffers, open_command_params and
++ * signalled_pipe_buffers, to the host. This means each of those buffers
++ * needs to be contained in a single physical page. The easiest choice
++ * is to just allocate a page and place the buffers in it.
++ */
++ if (WARN_ON(sizeof(*dev->buffers) > PAGE_SIZE))
++ return -ENOMEM;
++
++ page = (char *)__get_free_page(GFP_KERNEL);
++ if (!page) {
++ kfree(dev->pipes);
++ return -ENOMEM;
++ }
++ dev->buffers = (struct goldfish_pipe_dev_buffers *)page;
++
++ /* Send the buffer addresses to the host */
++ {
++ u64 paddr = __pa(&dev->buffers->signalled_pipe_buffers);
++
++ writel((u32)(unsigned long)(paddr >> 32),
++ dev->base + PIPE_REG_SIGNAL_BUFFER_HIGH);
++ writel((u32)(unsigned long)paddr,
++ dev->base + PIPE_REG_SIGNAL_BUFFER);
++ writel((u32)MAX_SIGNALLED_PIPES,
++ dev->base + PIPE_REG_SIGNAL_BUFFER_COUNT);
++
++ paddr = __pa(&dev->buffers->open_command_params);
++ writel((u32)(unsigned long)(paddr >> 32),
++ dev->base + PIPE_REG_OPEN_BUFFER_HIGH);
++ writel((u32)(unsigned long)paddr,
++ dev->base + PIPE_REG_OPEN_BUFFER);
++ }
++ return 0;
++}
++
++static void goldfish_pipe_device_deinit(struct platform_device *pdev)
++{
++ struct goldfish_pipe_dev *dev = pipe_dev;
++
++ misc_deregister(&goldfish_pipe_dev);
++ kfree(dev->pipes);
++ free_page((unsigned long)dev->buffers);
++}
++
+ static int goldfish_pipe_probe(struct platform_device *pdev)
+ {
+ int err;
+ struct resource *r;
+ struct goldfish_pipe_dev *dev = pipe_dev;
+
++ if (WARN_ON(sizeof(struct goldfish_pipe_command) > PAGE_SIZE))
++ return -ENOMEM;
++
+ /* not thread safe, but this should not happen */
+ WARN_ON(dev->base != NULL);
+
+@@ -609,26 +927,21 @@ static int goldfish_pipe_probe(struct pl
+ }
+ dev->irq = r->start;
+
+- err = devm_request_irq(&pdev->dev, dev->irq, goldfish_pipe_interrupt,
+- IRQF_SHARED, "goldfish_pipe", dev);
+- if (err) {
+- dev_err(&pdev->dev, "unable to allocate IRQ\n");
+- goto error;
+- }
+-
+- err = misc_register(&goldfish_pipe_device);
+- if (err) {
+- dev_err(&pdev->dev, "unable to register device\n");
+- goto error;
+- }
+- setup_access_params_addr(pdev, dev);
+-
+- /* Although the pipe device in the classic Android emulator does not
+- * recognize the 'version' register, it won't treat this as an error
+- * either and will simply return 0, which is fine.
++ /*
++ * Exchange the versions with the host device
++ *
++ * Note: v1 driver used to not report its version, so we write it before
++ * reading device version back: this allows the host implementation to
++ * detect the old driver (if there was no version write before read).
+ */
++ writel((u32)PIPE_DRIVER_VERSION, dev->base + PIPE_REG_VERSION);
+ dev->version = readl(dev->base + PIPE_REG_VERSION);
+- return 0;
++ if (WARN_ON(dev->version < PIPE_CURRENT_DEVICE_VERSION))
++ return -EINVAL;
++
++ err = goldfish_pipe_device_init(pdev);
++ if (!err)
++ return 0;
+
+ error:
+ dev->base = NULL;
+@@ -638,7 +951,7 @@ error:
+ static int goldfish_pipe_remove(struct platform_device *pdev)
+ {
+ struct goldfish_pipe_dev *dev = pipe_dev;
+- misc_deregister(&goldfish_pipe_device);
++ goldfish_pipe_device_deinit(pdev);
+ dev->base = NULL;
+ return 0;
+ }
+@@ -655,17 +968,16 @@ static const struct of_device_id goldfis
+ };
+ MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match);
+
+-static struct platform_driver goldfish_pipe = {
++static struct platform_driver goldfish_pipe_driver = {
+ .probe = goldfish_pipe_probe,
+ .remove = goldfish_pipe_remove,
+ .driver = {
+ .name = "goldfish_pipe",
+- .owner = THIS_MODULE,
+ .of_match_table = goldfish_pipe_of_match,
+ .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match),
+ }
+ };
+
+-module_platform_driver(goldfish_pipe);
++module_platform_driver(goldfish_pipe_driver);
+ MODULE_AUTHOR("David Turner <digit@google.com>");
+ MODULE_LICENSE("GPL");
diff --git a/lib-vsprintf-add-pap-padp-options.patch b/lib-vsprintf-add-pap-padp-options.patch
new file mode 100644
index 00000000000000..1e20d375c4a032
--- /dev/null
+++ b/lib-vsprintf-add-pap-padp-options.patch
@@ -0,0 +1,77 @@
+From: Chris Fries <cfries@google.com>
+Date: Thu, 27 Apr 2017 23:29:40 -0500
+Subject: lib: vsprintf: Add "%paP", "%padP" options
+
+Add %paP and %padP for physical address that need to always be shown
+regardless of kptr restrictions.
+
+Signed-off-by: Chris Fries <cfries@google.com>
+---
+
+---
+ Documentation/printk-formats.txt | 10 ++++++----
+ lib/vsprintf.c | 12 +++++++++---
+ 2 files changed, 15 insertions(+), 7 deletions(-)
+
+--- a/Documentation/printk-formats.txt
++++ b/Documentation/printk-formats.txt
+@@ -82,18 +82,20 @@ Struct Resources:
+
+ Physical addresses types phys_addr_t:
+
+- %pa[p] 0x01234567 or 0x0123456789abcdef
++ %pa[p][P] 0x01234567 or 0x0123456789abcdef
+
+ For printing a phys_addr_t type (and its derivatives, such as
+ resource_size_t) which can vary based on build options, regardless of
+- the width of the CPU data path. Passed by reference.
++ the width of the CPU data path. Passed by reference. Use the trailing
++ 'P' if it needs to be always shown.
+
+ DMA addresses types dma_addr_t:
+
+- %pad 0x01234567 or 0x0123456789abcdef
++ %pad[P] 0x01234567 or 0x0123456789abcdef
+
+ For printing a dma_addr_t type which can vary based on build options,
+- regardless of the width of the CPU data path. Passed by reference.
++ regardless of the width of the CPU data path. Passed by reference. Use
++ the trailing 'P' if it needs to be always shown.
+
+ Raw buffer as an escaped string:
+
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -1394,23 +1394,29 @@ static noinline_for_stack
+ char *address_val(char *buf, char *end, const void *addr, const char *fmt)
+ {
+ unsigned long long num;
++ int cleanse = kptr_restrict_cleanse_addresses();
++ int decleanse_idx = 1;
+ int size;
+
+ switch (fmt[1]) {
+ case 'd':
+ num = *(const dma_addr_t *)addr;
+ size = sizeof(dma_addr_t);
++ decleanse_idx = 2;
+ break;
+ case 'p':
++ decleanse_idx = 2;
++ /* fall thru */
+ default:
+ num = *(const phys_addr_t *)addr;
+ size = sizeof(phys_addr_t);
+ break;
+ }
+
+- return special_hex_number(buf, end,
+- kptr_restrict_cleanse_addresses() ? 0UL : num,
+- size);
++ /* 'P' on the tail means don't restrict the pointer. */
++ cleanse = cleanse && (fmt[decleanse_idx] != 'P');
++
++ return special_hex_number(buf, end, cleanse ? 0UL : num, size);
+ }
+
+ static noinline_for_stack
diff --git a/lib-vsprintf-additional-kernel-pointer-filtering-options.patch b/lib-vsprintf-additional-kernel-pointer-filtering-options.patch
new file mode 100644
index 00000000000000..4a06692e178438
--- /dev/null
+++ b/lib-vsprintf-additional-kernel-pointer-filtering-options.patch
@@ -0,0 +1,221 @@
+From: Dave Weinstein <olorin@google.com>
+Date: Wed, 11 Jan 2017 15:39:07 -0800
+Subject: lib: vsprintf: additional kernel pointer filtering options
+
+Add the kptr_restrict setting of 3 which results in both
+%p and %pK values being replaced by zeros.
+
+Add an additional %pP value inspired by the Grsecurity
+option which explicitly whitelists pointers for output.
+
+This patch is based on work by William Roberts
+<william.c.roberts@intel.com>
+
+Signed-off-by: Dave Weinstein <olorin@google.com>
+
+---
+ Documentation/printk-formats.txt | 5 ++
+ Documentation/sysctl/kernel.txt | 3 +
+ kernel/sysctl.c | 3 -
+ lib/vsprintf.c | 81 +++++++++++++++++++++++++--------------
+ 4 files changed, 63 insertions(+), 29 deletions(-)
+
+--- a/Documentation/printk-formats.txt
++++ b/Documentation/printk-formats.txt
+@@ -64,6 +64,11 @@ Kernel Pointers:
+ users. The behaviour of %pK depends on the kptr_restrict sysctl - see
+ Documentation/sysctl/kernel.txt for more details.
+
++ %pP 0x01234567 or 0x0123456789abcdef
++
++ For printing kernel pointers which should always be shown, even to
++ unprivileged users.
++
+ Struct Resources:
+
+ %pr [mem 0x60000000-0x6fffffff flags 0x2200] or
+--- a/Documentation/sysctl/kernel.txt
++++ b/Documentation/sysctl/kernel.txt
+@@ -392,6 +392,9 @@ values to unprivileged users is a concer
+ When kptr_restrict is set to (2), kernel pointers printed using
+ %pK will be replaced with 0's regardless of privileges.
+
++When kptr_restrict is set to (3), kernel pointers printed using
++%p and %pK will be replaced with 0's regardless of privileges.
++
+ ==============================================================
+
+ l2cr: (PPC only)
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -129,6 +129,7 @@ static unsigned long one_ul = 1;
+ static int one_hundred = 100;
+ static int one_thousand = 1000;
+ #ifdef CONFIG_PRINTK
++static int three = 3;
+ static int ten_thousand = 10000;
+ #endif
+ #ifdef CONFIG_PERF_EVENTS
+@@ -830,7 +831,7 @@ static struct ctl_table kern_table[] = {
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax_sysadmin,
+ .extra1 = &zero,
+- .extra2 = &two,
++ .extra2 = &three,
+ },
+ #endif
+ {
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -395,6 +395,16 @@ struct printf_spec {
+ #define FIELD_WIDTH_MAX ((1 << 23) - 1)
+ #define PRECISION_MAX ((1 << 15) - 1)
+
++int kptr_restrict __read_mostly;
++
++/*
++ * Always cleanse %p and %pK specifiers
++ */
++static inline int kptr_restrict_always_cleanse_pointers(void)
++{
++ return kptr_restrict >= 3;
++}
++
+ static noinline_for_stack
+ char *number(char *buf, char *end, unsigned long long num,
+ struct printf_spec spec)
+@@ -1470,8 +1480,6 @@ char *flags_string(char *buf, char *end,
+ return format_flags(buf, end, flags, names);
+ }
+
+-int kptr_restrict __read_mostly;
+-
+ /*
+ * Show a '%p' thing. A kernel extension is that the '%p' is followed
+ * by an extra set of alphanumeric characters that are extended format
+@@ -1540,6 +1548,7 @@ int kptr_restrict __read_mostly;
+ * Do not use this feature without some mechanism to verify the
+ * correctness of the format string and va_list arguments.
+ * - 'K' For a kernel pointer that should be hidden from unprivileged users
++ * - 'P' For a kernel pointer that should be shown to all users
+ * - 'NF' For a netdev_features_t
+ * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
+ * a certain separator (' ' by default):
+@@ -1569,6 +1578,9 @@ int kptr_restrict __read_mostly;
+ * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
+ * function pointers are really function descriptors, which contain a
+ * pointer to the real address.
++ *
++ * Note: That for kptr_restrict set to 3, %p and %pK have the same
++ * meaning.
+ */
+ static noinline_for_stack
+ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
+@@ -1576,7 +1588,7 @@ char *pointer(const char *fmt, char *buf
+ {
+ const int default_width = 2 * sizeof(void *);
+
+- if (!ptr && *fmt != 'K') {
++ if (!ptr && *fmt != 'K' && !kptr_restrict_always_cleanse_pointers()) {
+ /*
+ * Print (null) with the same width as a pointer so it makes
+ * tabular output look nice.
+@@ -1657,10 +1669,43 @@ char *pointer(const char *fmt, char *buf
+ va_end(va);
+ return buf;
+ }
++ case 'N':
++ return netdev_bits(buf, end, ptr, fmt);
++ case 'a':
++ return address_val(buf, end, ptr, fmt);
++ case 'd':
++ return dentry_name(buf, end, ptr, spec, fmt);
++ case 'C':
++ return clock(buf, end, ptr, spec, fmt);
++ case 'D':
++ return dentry_name(buf, end,
++ ((const struct file *)ptr)->f_path.dentry,
++ spec, fmt);
++#ifdef CONFIG_BLOCK
++ case 'g':
++ return bdev_name(buf, end, ptr, spec, fmt);
++#endif
++
++ case 'G':
++ return flags_string(buf, end, ptr, fmt);
++ case 'P':
++ /*
++ * an explicitly whitelisted kernel pointer should never be
++ * cleansed
++ */
++ break;
++ default:
++ /*
++ * plain %p, no extension, check if we should always cleanse and
++ * treat like %pK.
++ */
++ if (!kptr_restrict_always_cleanse_pointers())
++ break;
++ /* fallthrough */
+ case 'K':
+ switch (kptr_restrict) {
+ case 0:
+- /* Always print %pK values */
++ /* Always print %p values */
+ break;
+ case 1: {
+ const struct cred *cred;
+@@ -1679,7 +1724,7 @@ char *pointer(const char *fmt, char *buf
+ * Only print the real pointer value if the current
+ * process has CAP_SYSLOG and is running with the
+ * same credentials it started with. This is because
+- * access to files is checked at open() time, but %pK
++ * access to files is checked at open() time, but %p
+ * checks permission at read() time. We don't want to
+ * leak pointer values if a binary opens a file using
+ * %pK and then elevates privileges before reading it.
+@@ -1691,33 +1736,13 @@ char *pointer(const char *fmt, char *buf
+ ptr = NULL;
+ break;
+ }
+- case 2:
++ case 2: /* restrict only %pK */
++ case 3: /* restrict all non-extensioned %p and %pK */
+ default:
+- /* Always print 0's for %pK */
+ ptr = NULL;
+ break;
+ }
+ break;
+-
+- case 'N':
+- return netdev_bits(buf, end, ptr, fmt);
+- case 'a':
+- return address_val(buf, end, ptr, fmt);
+- case 'd':
+- return dentry_name(buf, end, ptr, spec, fmt);
+- case 'C':
+- return clock(buf, end, ptr, spec, fmt);
+- case 'D':
+- return dentry_name(buf, end,
+- ((const struct file *)ptr)->f_path.dentry,
+- spec, fmt);
+-#ifdef CONFIG_BLOCK
+- case 'g':
+- return bdev_name(buf, end, ptr, spec, fmt);
+-#endif
+-
+- case 'G':
+- return flags_string(buf, end, ptr, fmt);
+ }
+ spec.flags |= SMALL;
+ if (spec.field_width == -1) {
+@@ -1726,7 +1751,7 @@ char *pointer(const char *fmt, char *buf
+ }
+ spec.base = 16;
+
+- return number(buf, end, (unsigned long) ptr, spec);
++ return number(buf, end, (unsigned long long) ptr, spec);
+ }
+
+ /*
diff --git a/lib-vsprintf-default-kptr_restrict-to-the-maximum-value.patch b/lib-vsprintf-default-kptr_restrict-to-the-maximum-value.patch
new file mode 100644
index 00000000000000..e247b29c635926
--- /dev/null
+++ b/lib-vsprintf-default-kptr_restrict-to-the-maximum-value.patch
@@ -0,0 +1,26 @@
+From: Dave Weinstein <olorin@google.com>
+Date: Wed, 11 Jan 2017 16:27:59 -0800
+Subject: lib: vsprintf: default kptr_restrict to the maximum value
+
+Set the initial value of kptr_restrict to the maximum
+setting rather than the minimum setting, to ensure that
+early boot logging is not leaking information.
+
+Signed-off-by: Dave Weinstein <olorin@google.com>
+---
+
+---
+ lib/vsprintf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -395,7 +395,7 @@ struct printf_spec {
+ #define FIELD_WIDTH_MAX ((1 << 23) - 1)
+ #define PRECISION_MAX ((1 << 15) - 1)
+
+-int kptr_restrict __read_mostly;
++int kptr_restrict __read_mostly = 4;
+
+ /*
+ * Always cleanse %p and %pK specifiers
diff --git a/lib-vsprintf-physical-address-kernel-pointer-filtering-options.patch b/lib-vsprintf-physical-address-kernel-pointer-filtering-options.patch
new file mode 100644
index 00000000000000..47d3c8f520c257
--- /dev/null
+++ b/lib-vsprintf-physical-address-kernel-pointer-filtering-options.patch
@@ -0,0 +1,131 @@
+From: Dave Weinstein <olorin@google.com>
+Date: Wed, 11 Jan 2017 16:13:09 -0800
+Subject: lib: vsprintf: physical address kernel pointer filtering options
+
+Add the kptr_restrict setting of 4 which results in %pa and
+%p[rR] values being replaced by zeros.
+
+Signed-off-by: Dave Weinstein <olorin@google.com>
+---
+
+---
+ Documentation/sysctl/kernel.txt | 8 +++++++-
+ kernel/sysctl.c | 3 +--
+ lib/vsprintf.c | 33 ++++++++++++++++++++++++++++++---
+ 3 files changed, 38 insertions(+), 6 deletions(-)
+
+--- a/Documentation/sysctl/kernel.txt
++++ b/Documentation/sysctl/kernel.txt
+@@ -393,7 +393,13 @@ When kptr_restrict is set to (2), kernel
+ %pK will be replaced with 0's regardless of privileges.
+
+ When kptr_restrict is set to (3), kernel pointers printed using
+-%p and %pK will be replaced with 0's regardless of privileges.
++%p and %pK will be replaced with 0's regardless of privileges,
++however kernel pointers printed using %pP will continue to be printed.
++
++When kptr_restrict is set to (4), kernel pointers printed with
++%p, %pK, %pa, and %p[rR] will be replaced with 0's regardless of
++privileges. Kernel pointers printed using %pP will continue to be
++printed.
+
+ ==============================================================
+
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -129,7 +129,6 @@ static unsigned long one_ul = 1;
+ static int one_hundred = 100;
+ static int one_thousand = 1000;
+ #ifdef CONFIG_PRINTK
+-static int three = 3;
+ static int ten_thousand = 10000;
+ #endif
+ #ifdef CONFIG_PERF_EVENTS
+@@ -831,7 +830,7 @@ static struct ctl_table kern_table[] = {
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax_sysadmin,
+ .extra1 = &zero,
+- .extra2 = &three,
++ .extra2 = &four,
+ },
+ #endif
+ {
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -405,6 +405,22 @@ static inline int kptr_restrict_always_c
+ return kptr_restrict >= 3;
+ }
+
++/*
++ * Always cleanse physical addresses (%pa* specifiers)
++ */
++static inline int kptr_restrict_cleanse_addresses(void)
++{
++ return kptr_restrict >= 4;
++}
++
++/*
++ * Always cleanse resource addresses (%p[rR] specifiers)
++ */
++static inline int kptr_restrict_cleanse_resources(void)
++{
++ return kptr_restrict >= 4;
++}
++
+ static noinline_for_stack
+ char *number(char *buf, char *end, unsigned long long num,
+ struct printf_spec spec)
+@@ -757,6 +773,7 @@ char *resource_string(char *buf, char *e
+
+ char *p = sym, *pend = sym + sizeof(sym);
+ int decode = (fmt[0] == 'R') ? 1 : 0;
++ int cleanse = kptr_restrict_cleanse_resources();
+ const struct printf_spec *specp;
+
+ *p++ = '[';
+@@ -784,10 +801,11 @@ char *resource_string(char *buf, char *e
+ p = string(p, pend, "size ", str_spec);
+ p = number(p, pend, resource_size(res), *specp);
+ } else {
+- p = number(p, pend, res->start, *specp);
++ p = number(p, pend, cleanse ? 0UL : res->start, *specp);
+ if (res->start != res->end) {
+ *p++ = '-';
+- p = number(p, pend, res->end, *specp);
++ p = number(p, pend, cleanse ?
++ res->end - res->start : res->end, *specp);
+ }
+ }
+ if (decode) {
+@@ -1390,7 +1408,9 @@ char *address_val(char *buf, char *end,
+ break;
+ }
+
+- return special_hex_number(buf, end, num, size);
++ return special_hex_number(buf, end,
++ kptr_restrict_cleanse_addresses() ? 0UL : num,
++ size);
+ }
+
+ static noinline_for_stack
+@@ -1581,6 +1601,12 @@ char *flags_string(char *buf, char *end,
+ *
+ * Note: That for kptr_restrict set to 3, %p and %pK have the same
+ * meaning.
++ *
++ * Note: That for kptr_restrict set to 4, %pa will null out the physical
++ * address.
++ *
++ * Note: That for kptr_restrict set to 4, %p[rR] will null out the memory
++ * address.
+ */
+ static noinline_for_stack
+ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
+@@ -1738,6 +1764,7 @@ char *pointer(const char *fmt, char *buf
+ }
+ case 2: /* restrict only %pK */
+ case 3: /* restrict all non-extensioned %p and %pK */
++ case 4: /* restrict all non-extensioned %p, %pK, %pa*, %p[rR] */
+ default:
+ ptr = NULL;
+ break;
diff --git a/lib-vsprintf-whitelist-stack-traces.patch b/lib-vsprintf-whitelist-stack-traces.patch
new file mode 100644
index 00000000000000..eeee7bd64b02ac
--- /dev/null
+++ b/lib-vsprintf-whitelist-stack-traces.patch
@@ -0,0 +1,57 @@
+From: Dave Weinstein <olorin@google.com>
+Date: Wed, 11 Jan 2017 16:02:44 -0800
+Subject: lib: vsprintf: whitelist stack traces
+
+Use the %pP functionality to explicitly allow kernel
+pointers to be logged for stack traces
+
+Signed-off-by: Dave Weinstein <olorin@google.com>
+
+---
+ arch/arm64/kernel/traps.c | 4 ++--
+ include/linux/kallsyms.h | 2 +-
+ kernel/printk/printk.c | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/arm64/kernel/traps.c
++++ b/arch/arm64/kernel/traps.c
+@@ -146,7 +146,7 @@ static void dump_backtrace(struct pt_reg
+ unsigned long irq_stack_ptr;
+ int skip;
+
+- pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
++ pr_debug("%s(regs = %pP tsk = %pP)\n", __func__, regs, tsk);
+
+ if (!tsk)
+ tsk = current;
+@@ -252,7 +252,7 @@ static int __die(const char *str, int er
+
+ print_modules();
+ __show_regs(regs);
+- pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n",
++ pr_emerg("Process %.*s (pid: %d, stack limit = 0x%pP)\n",
+ TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk),
+ end_of_stack(tsk));
+
+--- a/include/linux/kallsyms.h
++++ b/include/linux/kallsyms.h
+@@ -122,7 +122,7 @@ static inline void print_symbol(const ch
+
+ static inline void print_ip_sym(unsigned long ip)
+ {
+- printk("[<%p>] %pS\n", (void *) ip, (void *) ip);
++ printk("[<%pP>] %pS\n", (void *) ip, (void *) ip);
+ }
+
+ #endif /*_LINUX_KALLSYMS_H*/
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3110,7 +3110,7 @@ void show_regs_print_info(const char *lo
+ {
+ dump_stack_print_info(log_lvl);
+
+- printk("%stask: %p task.stack: %p\n",
++ printk("%stask: %pP task.stack: %pP\n",
+ log_lvl, current, task_stack_page(current));
+ }
+
diff --git a/series b/series
index 41096ea726b6ec..bfb1855d3ca3ad 100644
--- a/series
+++ b/series
@@ -1,3 +1,10 @@
+#goldfish_pipe-an-implementation-of-more-parallel-pipe.patch
+lib-vsprintf-additional-kernel-pointer-filtering-options.patch
+lib-vsprintf-whitelist-stack-traces.patch
+lib-vsprintf-physical-address-kernel-pointer-filtering-options.patch
+lib-vsprintf-default-kptr_restrict-to-the-maximum-value.patch
+lib-vsprintf-add-pap-padp-options.patch
+drivers-uio-un-restrict-sysfs-pointers-for-uio.patch
0001-goldfish_pipe-An-implementation-of-more-parallel-pip.patch
0002-CHROMIUM-android-fix-warning-when-releasing-active-s.patch
0003-goldfish-Add-goldfish-sync-driver.patch