[PATCH] doc: sysfs-pci: update enable 'rom' file instructions

2018-03-13 Thread Kenny Ballou
Update the instructions for enabling and disabling read access to the
special sysfs 'rom' file for PCI devices.  The function that interprets
user data for enabling and disabling the device actually expects _at
least_ 2 bytes, more than what is expressly implied by "1" or "0".

It should also be noted, that the code path for enabling read access to
the special file can receive any length of input as long as it doesn't
start with "0".  However, this is not added to the documentation as this
is, perhaps, not a "feature" of the file system we want to encourage.

This patch is submitted in place of accepting [pci: use kstrtobool over
ad hoc string parsing][0] as to not break existing functionality.
Similarly, this patch is in reference to a bugzilla report: [Sysfs PCI
rom file functionality does not match documentation][1].

[0]: https://www.spinics.net/lists/linux-pci/msg69073.html
[1]: https://bugzilla.kernel.org/show_bug.cgi?id=111301

Reported-by: google...@yahoo.com
Signed-off-by: Kenny Ballou 
---
 Documentation/filesystems/sysfs-pci.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/sysfs-pci.txt 
b/Documentation/filesystems/sysfs-pci.txt
index 06f1d64c6f70..0cc9a32ebab0 100644
--- a/Documentation/filesystems/sysfs-pci.txt
+++ b/Documentation/filesystems/sysfs-pci.txt
@@ -75,8 +75,8 @@ may not be reversed.
 
 The 'rom' file is special in that it provides read-only access to the device's
 ROM file, if available.  It's disabled by default, however, so applications
-should write the string "1" to the file to enable it before attempting a read
-call, and disable it following the access by writing "0" to the file.  Note
+should write the string "1\n" to the file to enable it before attempting a read
+call, and disable it following the access by writing "0\n" to the file.  Note
 that the device must be enabled for a rom read to return data successfully.
 In the event a driver is not bound to the device, it can be enabled using the
 'enable' file, documented above.
-- 
2.16.1

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] doc: fs: sysfs-pci: remove trailing whitespace

2018-03-13 Thread Kenny Ballou
Remove the trailing whitespace found in
`Documentation/filesystems/sysfs-pci.txt`.

Signed-off-by: Kenny Ballou 
---
 Documentation/filesystems/sysfs-pci.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/sysfs-pci.txt 
b/Documentation/filesystems/sysfs-pci.txt
index 06f1d64c6f70..093bb0fa630f 100644
--- a/Documentation/filesystems/sysfs-pci.txt
+++ b/Documentation/filesystems/sysfs-pci.txt
@@ -67,11 +67,11 @@ don't support mmapping of certain resources, so be sure to 
check the return
 value from any attempted mmap.  The most notable of these are I/O port
 resources, which also provide read/write access.
 
-The 'enable' file provides a counter that indicates how many times the device 
+The 'enable' file provides a counter that indicates how many times the device
 has been enabled.  If the 'enable' file currently returns '4', and a '1' is
 echoed into it, it will then return '5'.  Echoing a '0' into it will decrease
 the count.  Even when it returns to 0, though, some of the initialisation
-may not be reversed.  
+may not be reversed.
 
 The 'rom' file is special in that it provides read-only access to the device's
 ROM file, if available.  It's disabled by default, however, so applications
-- 
2.16.1

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/8] Uprobe: Export uprobe_map_info along with uprobe_{build/free}_map_info()

2018-03-13 Thread Jerome Glisse
On Tue, Mar 13, 2018 at 06:25:59PM +0530, Ravi Bangoria wrote:
> These exported data structure and functions will be used by other
> files in later patches.
> 
> No functionality changes.
> 
> Signed-off-by: Ravi Bangoria 

Reviewed-by: Jérôme Glisse 

> ---
>  include/linux/uprobes.h |  9 +
>  kernel/events/uprobes.c | 14 +++---
>  2 files changed, 12 insertions(+), 11 deletions(-)
> 
> diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
> index 0a294e9..7bd2760 100644
> --- a/include/linux/uprobes.h
> +++ b/include/linux/uprobes.h
> @@ -109,12 +109,19 @@ enum rp_check {
>   RP_CHECK_RET,
>  };
>  
> +struct address_space;
>  struct xol_area;
>  
>  struct uprobes_state {
>   struct xol_area *xol_area;
>  };
>  
> +struct uprobe_map_info {
> + struct uprobe_map_info *next;
> + struct mm_struct *mm;
> + unsigned long vaddr;
> +};
> +
>  extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned 
> long vaddr);
>  extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, 
> unsigned long vaddr);
>  extern bool is_swbp_insn(uprobe_opcode_t *insn);
> @@ -149,6 +156,8 @@ struct uprobes_state {
>  extern bool arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs 
> *regs);
>  extern void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
>void *src, unsigned long len);
> +extern struct uprobe_map_info *uprobe_free_map_info(struct uprobe_map_info 
> *info);
> +extern struct uprobe_map_info *uprobe_build_map_info(struct address_space 
> *mapping, loff_t offset, bool is_register);
>  #else /* !CONFIG_UPROBES */
>  struct uprobes_state {
>  };
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index 081b88c1..e7830b8 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -695,23 +695,15 @@ static void delete_uprobe(struct uprobe *uprobe)
>   put_uprobe(uprobe);
>  }
>  
> -struct uprobe_map_info {
> - struct uprobe_map_info *next;
> - struct mm_struct *mm;
> - unsigned long vaddr;
> -};
> -
> -static inline struct uprobe_map_info *
> -uprobe_free_map_info(struct uprobe_map_info *info)
> +struct uprobe_map_info *uprobe_free_map_info(struct uprobe_map_info *info)
>  {
>   struct uprobe_map_info *next = info->next;
>   kfree(info);
>   return next;
>  }
>  
> -static struct uprobe_map_info *
> -uprobe_build_map_info(struct address_space *mapping, loff_t offset,
> -   bool is_register)
> +struct uprobe_map_info *uprobe_build_map_info(struct address_space *mapping,
> +   loff_t offset, bool is_register)
>  {
>   unsigned long pgoff = offset >> PAGE_SHIFT;
>   struct vm_area_struct *vma;
> -- 
> 1.8.3.1
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/8] Uprobe: Rename map_info to uprobe_map_info

2018-03-13 Thread Jerome Glisse
On Tue, Mar 13, 2018 at 06:25:58PM +0530, Ravi Bangoria wrote:
> map_info is very generic name, rename it to uprobe_map_info.
> Renaming will help to export this structure outside of the
> file.
> 
> Also rename free_map_info() to uprobe_free_map_info() and
> build_map_info() to uprobe_build_map_info().
> 
> No functionality changes.
> 
> Signed-off-by: Ravi Bangoria 

Same coccinelle comments as previously.

Reviewed-by: Jérôme Glisse 

> ---
>  kernel/events/uprobes.c | 32 +---
>  1 file changed, 17 insertions(+), 15 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index 535fd39..081b88c1 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -695,27 +695,29 @@ static void delete_uprobe(struct uprobe *uprobe)
>   put_uprobe(uprobe);
>  }
>  
> -struct map_info {
> - struct map_info *next;
> +struct uprobe_map_info {
> + struct uprobe_map_info *next;
>   struct mm_struct *mm;
>   unsigned long vaddr;
>  };
>  
> -static inline struct map_info *free_map_info(struct map_info *info)
> +static inline struct uprobe_map_info *
> +uprobe_free_map_info(struct uprobe_map_info *info)
>  {
> - struct map_info *next = info->next;
> + struct uprobe_map_info *next = info->next;
>   kfree(info);
>   return next;
>  }
>  
> -static struct map_info *
> -build_map_info(struct address_space *mapping, loff_t offset, bool 
> is_register)
> +static struct uprobe_map_info *
> +uprobe_build_map_info(struct address_space *mapping, loff_t offset,
> +   bool is_register)
>  {
>   unsigned long pgoff = offset >> PAGE_SHIFT;
>   struct vm_area_struct *vma;
> - struct map_info *curr = NULL;
> - struct map_info *prev = NULL;
> - struct map_info *info;
> + struct uprobe_map_info *curr = NULL;
> + struct uprobe_map_info *prev = NULL;
> + struct uprobe_map_info *info;
>   int more = 0;
>  
>   again:
> @@ -729,7 +731,7 @@ static inline struct map_info *free_map_info(struct 
> map_info *info)
>* Needs GFP_NOWAIT to avoid i_mmap_rwsem recursion 
> through
>* reclaim. This is optimistic, no harm done if it 
> fails.
>*/
> - prev = kmalloc(sizeof(struct map_info),
> + prev = kmalloc(sizeof(struct uprobe_map_info),
>   GFP_NOWAIT | __GFP_NOMEMALLOC | 
> __GFP_NOWARN);
>   if (prev)
>   prev->next = NULL;
> @@ -762,7 +764,7 @@ static inline struct map_info *free_map_info(struct 
> map_info *info)
>   }
>  
>   do {
> - info = kmalloc(sizeof(struct map_info), GFP_KERNEL);
> + info = kmalloc(sizeof(struct uprobe_map_info), GFP_KERNEL);
>   if (!info) {
>   curr = ERR_PTR(-ENOMEM);
>   goto out;
> @@ -774,7 +776,7 @@ static inline struct map_info *free_map_info(struct 
> map_info *info)
>   goto again;
>   out:
>   while (prev)
> - prev = free_map_info(prev);
> + prev = uprobe_free_map_info(prev);
>   return curr;
>  }
>  
> @@ -782,11 +784,11 @@ static inline struct map_info *free_map_info(struct 
> map_info *info)
>  register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
>  {
>   bool is_register = !!new;
> - struct map_info *info;
> + struct uprobe_map_info *info;
>   int err = 0;
>  
>   percpu_down_write(_mmap_sem);
> - info = build_map_info(uprobe->inode->i_mapping,
> + info = uprobe_build_map_info(uprobe->inode->i_mapping,
>   uprobe->offset, is_register);
>   if (IS_ERR(info)) {
>   err = PTR_ERR(info);
> @@ -825,7 +827,7 @@ static inline struct map_info *free_map_info(struct 
> map_info *info)
>   up_write(>mmap_sem);
>   free:
>   mmput(mm);
> - info = free_map_info(info);
> + info = uprobe_free_map_info(info);
>   }
>   out:
>   percpu_up_write(_mmap_sem);
> -- 
> 1.8.3.1
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/8] mm: Prefix vma_ to vaddr_to_offset() and offset_to_vaddr()

2018-03-13 Thread Jerome Glisse
On Tue, Mar 13, 2018 at 06:25:57PM +0530, Ravi Bangoria wrote:
> No functionality changes.
> 
> Signed-off-by: Ravi Bangoria 

Doing this with coccinelle would have been nicer but this is small
enough to review without too much fatigue :)

Reviewed-by: Jérôme Glisse 

> ---
>  include/linux/mm.h  |  4 ++--
>  kernel/events/uprobes.c | 14 +++---
>  2 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 95909f2..d7ee526 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2275,13 +2275,13 @@ struct vm_unmapped_area_info {
>  }
>  
>  static inline unsigned long
> -offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
> +vma_offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
>  {
>   return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
>  }
>  
>  static inline loff_t
> -vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
> +vma_vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
>  {
>   return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
>  }
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index bd6f230..535fd39 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -748,7 +748,7 @@ static inline struct map_info *free_map_info(struct 
> map_info *info)
>   curr = info;
>  
>   info->mm = vma->vm_mm;
> - info->vaddr = offset_to_vaddr(vma, offset);
> + info->vaddr = vma_offset_to_vaddr(vma, offset);
>   }
>   i_mmap_unlock_read(mapping);
>  
> @@ -807,7 +807,7 @@ static inline struct map_info *free_map_info(struct 
> map_info *info)
>   goto unlock;
>  
>   if (vma->vm_start > info->vaddr ||
> - vaddr_to_offset(vma, info->vaddr) != uprobe->offset)
> + vma_vaddr_to_offset(vma, info->vaddr) != uprobe->offset)
>   goto unlock;
>  
>   if (is_register) {
> @@ -977,7 +977,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct 
> mm_struct *mm)
>   uprobe->offset >= offset + vma->vm_end - vma->vm_start)
>   continue;
>  
> - vaddr = offset_to_vaddr(vma, uprobe->offset);
> + vaddr = vma_offset_to_vaddr(vma, uprobe->offset);
>   err |= remove_breakpoint(uprobe, mm, vaddr);
>   }
>   up_read(>mmap_sem);
> @@ -1023,7 +1023,7 @@ static void build_probe_list(struct inode *inode,
>   struct uprobe *u;
>  
>   INIT_LIST_HEAD(head);
> - min = vaddr_to_offset(vma, start);
> + min = vma_vaddr_to_offset(vma, start);
>   max = min + (end - start) - 1;
>  
>   spin_lock(_treelock);
> @@ -1076,7 +1076,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
>   list_for_each_entry_safe(uprobe, u, _list, pending_list) {
>   if (!fatal_signal_pending(current) &&
>   filter_chain(uprobe, UPROBE_FILTER_MMAP, vma->vm_mm)) {
> - unsigned long vaddr = offset_to_vaddr(vma, 
> uprobe->offset);
> + unsigned long vaddr = vma_offset_to_vaddr(vma, 
> uprobe->offset);
>   install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
>   }
>   put_uprobe(uprobe);
> @@ -1095,7 +1095,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
>  
>   inode = file_inode(vma->vm_file);
>  
> - min = vaddr_to_offset(vma, start);
> + min = vma_vaddr_to_offset(vma, start);
>   max = min + (end - start) - 1;
>  
>   spin_lock(_treelock);
> @@ -1730,7 +1730,7 @@ static struct uprobe *find_active_uprobe(unsigned long 
> bp_vaddr, int *is_swbp)
>   if (vma && vma->vm_start <= bp_vaddr) {
>   if (valid_vma(vma, false)) {
>   struct inode *inode = file_inode(vma->vm_file);
> - loff_t offset = vaddr_to_offset(vma, bp_vaddr);
> + loff_t offset = vma_vaddr_to_offset(vma, bp_vaddr);
>  
>   uprobe = find_uprobe(inode, offset);
>   }
> -- 
> 1.8.3.1
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/8] Uprobe: Export vaddr <-> offset conversion functions

2018-03-13 Thread Jerome Glisse
On Tue, Mar 13, 2018 at 06:25:56PM +0530, Ravi Bangoria wrote:
> No functionality changes.
> 
> Signed-off-by: Ravi Bangoria 

Reviewed-by: Jérôme Glisse 

> ---
>  include/linux/mm.h  | 12 
>  kernel/events/uprobes.c | 10 --
>  2 files changed, 12 insertions(+), 10 deletions(-)
> 
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index ad06d42..95909f2 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2274,6 +2274,18 @@ struct vm_unmapped_area_info {
>   return unmapped_area(info);
>  }
>  
> +static inline unsigned long
> +offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
> +{
> + return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
> +}
> +
> +static inline loff_t
> +vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
> +{
> + return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
> +}
> +
>  /* truncate.c */
>  extern void truncate_inode_pages(struct address_space *, loff_t);
>  extern void truncate_inode_pages_range(struct address_space *,
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index ce6848e..bd6f230 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -130,16 +130,6 @@ static bool valid_vma(struct vm_area_struct *vma, bool 
> is_register)
>   return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC;
>  }
>  
> -static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t 
> offset)
> -{
> - return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
> -}
> -
> -static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long 
> vaddr)
> -{
> - return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
> -}
> -
>  /**
>   * __replace_page - replace page in vma by new page.
>   * based on replace_page in mm/ksm.c
> -- 
> 1.8.3.1
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 4/4] tty: serial: msm_geni_serial: Add serial driver support for GENI based QUP

2018-03-13 Thread Karthik Ramasubramanian


On 3/2/2018 5:11 PM, Evan Green wrote:
>> +
>> +#ifdef CONFIG_CONSOLE_POLL
>> +#define RX_BYTES_PW 1
>> +#else
>> +#define RX_BYTES_PW 4
>> +#endif
> 
> This seems fishy to me. Does either setting work? If so, why not just
> have one value?
Yes, either one works. In the interrupt driven mode, sometimes due to
increased interrupt latency the RX FIFO may overflow if we use only 1
byte per FIFO word - given there are no flow control lines in the debug
uart. Hence using 4 bytes in the FIFO word will help to prevent the FIFO
overflow - especially in the case where commands are executed through
scripts.

In polling mode, using 1 byte per word helps to use the hardware to
buffer the data instead of software buffering especially when the
framework keeps reading one byte at a time.
> 
>> +static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
>> +   int offset, int bit_field, bool set)
>> +{
>> +   u32 reg;
>> +   struct qcom_geni_serial_port *port;
>> +   unsigned int baud;
>> +   unsigned int fifo_bits;
>> +   unsigned long timeout_us = 2;
>> +
>> +   /* Ensure polling is not re-ordered before the prior writes/reads */
>> +   mb();
>> +
>> +   if (uport->private_data) {
>> +   port = to_dev_port(uport, uport);
>> +   baud = port->cur_baud;
>> +   if (!baud)
>> +   baud = 115200;
>> +   fifo_bits = port->tx_fifo_depth * port->tx_fifo_width;
>> +   /*
>> +* Total polling iterations based on FIFO worth of bytes to 
>> be
>> +* sent at current baud .Add a little fluff to the wait.
>> +*/
>> +   timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500;
> 
> This fluff is a little mysterious, can it be explained at all? Do you
> think the fluff factor is in units of time (as you have it) or bits?
> Time makes sense I guess if we're worried about clock source
> differences.
The fluff is in micro-seconds and can help with unforeseen delays in
emulation platforms.
> 
>> +
>> +static void qcom_geni_serial_console_write(struct console *co, const char 
>> *s,
>> + unsigned int count)
>> +{
>> +   struct uart_port *uport;
>> +   struct qcom_geni_serial_port *port;
>> +   bool locked = true;
>> +   unsigned long flags;
>> +
>> +   WARN_ON(co->index < 0 || co->index >= GENI_UART_CONS_PORTS);
>> +
>> +   port = get_port_from_line(co->index);
>> +   if (IS_ERR(port))
>> +   return;
>> +
>> +   uport = >uport;
>> +   if (oops_in_progress)
>> +   locked = spin_trylock_irqsave(>lock, flags);
>> +   else
>> +   spin_lock_irqsave(>lock, flags);
>> +
>> +   if (locked) {
>> +   __qcom_geni_serial_console_write(uport, s, count);
>> +   spin_unlock_irqrestore(>lock, flags);
> 
> I too am a little lost on the locking here. What exactly is the lock
> protecting? Looks like for the most part it's trying to synchronize
> with the ISR? What specifically in the ISR? I just wanted to go
> through and check to make sure whatever the shared resource is is
> appropriately protected.
The lock protects 2 simultaneous writers from putting the hardware in
the bad state. The output of the command entered in a shell can trigger
a write in the interrupt context while logging activity can trigger a
simultaneous write.
> 
>> +   }
>> +}
>> +
>> +static int handle_rx_console(struct uart_port *uport, u32 rx_bytes, bool 
>> drop)
>> +{
>> +   u32 i = rx_bytes;
>> +   u32 rx_fifo;
>> +   unsigned char *buf;
>> +   struct tty_port *tport;
>> +   struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
>> +
>> +   tport = >state->port;
>> +   while (i > 0) {
>> +   int c;
>> +   int bytes = i > port->rx_bytes_pw ? port->rx_bytes_pw : i;
> 
> Please replace this with a min macro.
Ok.
> 
>> +static int qcom_geni_serial_handle_tx(struct uart_port *uport)
>> +{
>> +   int ret = 0;
>> +   struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
>> +   struct circ_buf *xmit = >state->xmit;
>> +   size_t avail;
>> +   size_t remaining;
>> +   int i = 0;
>> +   u32 status;
>> +   unsigned int chunk;
>> +   int tail;
>> +
>> +   chunk = uart_circ_chars_pending(xmit);
>> +   status = readl_relaxed(uport->membase + SE_GENI_TX_FIFO_STATUS);
>> +   /* Both FIFO and framework buffer are drained */
>> +   if ((chunk == port->xmit_size) && !status) {
>> +   port->xmit_size = 0;
>> +   uart_circ_clear(xmit);
>> +   qcom_geni_serial_stop_tx(uport);
>> +   goto out_write_wakeup;
>> +   }
>> +   chunk -= port->xmit_size;
>> +
>> +   avail = (port->tx_fifo_depth - port->tx_wm) * port->tx_bytes_pw;
>> +   tail = (xmit->tail + port->xmit_size) & (UART_XMIT_SIZE - 

[PATCH 2/8] mm: Prefix vma_ to vaddr_to_offset() and offset_to_vaddr()

2018-03-13 Thread Ravi Bangoria
No functionality changes.

Signed-off-by: Ravi Bangoria 
---
 include/linux/mm.h  |  4 ++--
 kernel/events/uprobes.c | 14 +++---
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 95909f2..d7ee526 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2275,13 +2275,13 @@ struct vm_unmapped_area_info {
 }
 
 static inline unsigned long
-offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
+vma_offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
 {
return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
 }
 
 static inline loff_t
-vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
+vma_vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
 {
return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
 }
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index bd6f230..535fd39 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -748,7 +748,7 @@ static inline struct map_info *free_map_info(struct 
map_info *info)
curr = info;
 
info->mm = vma->vm_mm;
-   info->vaddr = offset_to_vaddr(vma, offset);
+   info->vaddr = vma_offset_to_vaddr(vma, offset);
}
i_mmap_unlock_read(mapping);
 
@@ -807,7 +807,7 @@ static inline struct map_info *free_map_info(struct 
map_info *info)
goto unlock;
 
if (vma->vm_start > info->vaddr ||
-   vaddr_to_offset(vma, info->vaddr) != uprobe->offset)
+   vma_vaddr_to_offset(vma, info->vaddr) != uprobe->offset)
goto unlock;
 
if (is_register) {
@@ -977,7 +977,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct 
mm_struct *mm)
uprobe->offset >= offset + vma->vm_end - vma->vm_start)
continue;
 
-   vaddr = offset_to_vaddr(vma, uprobe->offset);
+   vaddr = vma_offset_to_vaddr(vma, uprobe->offset);
err |= remove_breakpoint(uprobe, mm, vaddr);
}
up_read(>mmap_sem);
@@ -1023,7 +1023,7 @@ static void build_probe_list(struct inode *inode,
struct uprobe *u;
 
INIT_LIST_HEAD(head);
-   min = vaddr_to_offset(vma, start);
+   min = vma_vaddr_to_offset(vma, start);
max = min + (end - start) - 1;
 
spin_lock(_treelock);
@@ -1076,7 +1076,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
list_for_each_entry_safe(uprobe, u, _list, pending_list) {
if (!fatal_signal_pending(current) &&
filter_chain(uprobe, UPROBE_FILTER_MMAP, vma->vm_mm)) {
-   unsigned long vaddr = offset_to_vaddr(vma, 
uprobe->offset);
+   unsigned long vaddr = vma_offset_to_vaddr(vma, 
uprobe->offset);
install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
}
put_uprobe(uprobe);
@@ -1095,7 +1095,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
 
inode = file_inode(vma->vm_file);
 
-   min = vaddr_to_offset(vma, start);
+   min = vma_vaddr_to_offset(vma, start);
max = min + (end - start) - 1;
 
spin_lock(_treelock);
@@ -1730,7 +1730,7 @@ static struct uprobe *find_active_uprobe(unsigned long 
bp_vaddr, int *is_swbp)
if (vma && vma->vm_start <= bp_vaddr) {
if (valid_vma(vma, false)) {
struct inode *inode = file_inode(vma->vm_file);
-   loff_t offset = vaddr_to_offset(vma, bp_vaddr);
+   loff_t offset = vma_vaddr_to_offset(vma, bp_vaddr);
 
uprobe = find_uprobe(inode, offset);
}
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/8] Uprobe: Rename map_info to uprobe_map_info

2018-03-13 Thread Ravi Bangoria
map_info is very generic name, rename it to uprobe_map_info.
Renaming will help to export this structure outside of the
file.

Also rename free_map_info() to uprobe_free_map_info() and
build_map_info() to uprobe_build_map_info().

No functionality changes.

Signed-off-by: Ravi Bangoria 
---
 kernel/events/uprobes.c | 32 +---
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 535fd39..081b88c1 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -695,27 +695,29 @@ static void delete_uprobe(struct uprobe *uprobe)
put_uprobe(uprobe);
 }
 
-struct map_info {
-   struct map_info *next;
+struct uprobe_map_info {
+   struct uprobe_map_info *next;
struct mm_struct *mm;
unsigned long vaddr;
 };
 
-static inline struct map_info *free_map_info(struct map_info *info)
+static inline struct uprobe_map_info *
+uprobe_free_map_info(struct uprobe_map_info *info)
 {
-   struct map_info *next = info->next;
+   struct uprobe_map_info *next = info->next;
kfree(info);
return next;
 }
 
-static struct map_info *
-build_map_info(struct address_space *mapping, loff_t offset, bool is_register)
+static struct uprobe_map_info *
+uprobe_build_map_info(struct address_space *mapping, loff_t offset,
+ bool is_register)
 {
unsigned long pgoff = offset >> PAGE_SHIFT;
struct vm_area_struct *vma;
-   struct map_info *curr = NULL;
-   struct map_info *prev = NULL;
-   struct map_info *info;
+   struct uprobe_map_info *curr = NULL;
+   struct uprobe_map_info *prev = NULL;
+   struct uprobe_map_info *info;
int more = 0;
 
  again:
@@ -729,7 +731,7 @@ static inline struct map_info *free_map_info(struct 
map_info *info)
 * Needs GFP_NOWAIT to avoid i_mmap_rwsem recursion 
through
 * reclaim. This is optimistic, no harm done if it 
fails.
 */
-   prev = kmalloc(sizeof(struct map_info),
+   prev = kmalloc(sizeof(struct uprobe_map_info),
GFP_NOWAIT | __GFP_NOMEMALLOC | 
__GFP_NOWARN);
if (prev)
prev->next = NULL;
@@ -762,7 +764,7 @@ static inline struct map_info *free_map_info(struct 
map_info *info)
}
 
do {
-   info = kmalloc(sizeof(struct map_info), GFP_KERNEL);
+   info = kmalloc(sizeof(struct uprobe_map_info), GFP_KERNEL);
if (!info) {
curr = ERR_PTR(-ENOMEM);
goto out;
@@ -774,7 +776,7 @@ static inline struct map_info *free_map_info(struct 
map_info *info)
goto again;
  out:
while (prev)
-   prev = free_map_info(prev);
+   prev = uprobe_free_map_info(prev);
return curr;
 }
 
@@ -782,11 +784,11 @@ static inline struct map_info *free_map_info(struct 
map_info *info)
 register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
 {
bool is_register = !!new;
-   struct map_info *info;
+   struct uprobe_map_info *info;
int err = 0;
 
percpu_down_write(_mmap_sem);
-   info = build_map_info(uprobe->inode->i_mapping,
+   info = uprobe_build_map_info(uprobe->inode->i_mapping,
uprobe->offset, is_register);
if (IS_ERR(info)) {
err = PTR_ERR(info);
@@ -825,7 +827,7 @@ static inline struct map_info *free_map_info(struct 
map_info *info)
up_write(>mmap_sem);
  free:
mmput(mm);
-   info = free_map_info(info);
+   info = uprobe_free_map_info(info);
}
  out:
percpu_up_write(_mmap_sem);
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/8] perf probe: Support SDT markers having reference counter (semaphore)

2018-03-13 Thread Ravi Bangoria
With this, perf buildid-cache will save SDT markers with reference
counter in probe cache. Perf probe will be able to probe markers
having reference counter. Ex,

  # readelf -n /tmp/tick | grep -A1 loop2
Name: loop2
... Semaphore: 0x10020036

  # ./perf buildid-cache --add /tmp/tick
  # ./perf probe sdt_tick:loop2
  # ./perf stat -e sdt_tick:loop2 /tmp/tick
hi: 0
hi: 1
hi: 2
^C
 Performance counter stats for '/tmp/tick':
 3  sdt_tick:loop2
   2.561851452 seconds time elapsed

Signed-off-by: Ravi Bangoria 
---
 tools/perf/util/probe-event.c | 21 +
 tools/perf/util/probe-event.h |  1 +
 tools/perf/util/probe-file.c  | 22 +++---
 tools/perf/util/symbol-elf.c  | 10 ++
 tools/perf/util/symbol.h  |  1 +
 5 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index e1dbc98..2cbe68a 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1832,6 +1832,12 @@ int parse_probe_trace_command(const char *cmd, struct 
probe_trace_event *tev)
tp->offset = strtoul(fmt2_str, NULL, 10);
}
 
+   if (tev->uprobes) {
+   fmt2_str = strchr(p, '(');
+   if (fmt2_str)
+   tp->ref_ctr_offset = strtoul(fmt2_str + 1, NULL, 0);
+   }
+
tev->nargs = argc - 2;
tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
if (tev->args == NULL) {
@@ -2054,15 +2060,22 @@ char *synthesize_probe_trace_command(struct 
probe_trace_event *tev)
}
 
/* Use the tp->address for uprobes */
-   if (tev->uprobes)
-   err = strbuf_addf(, "%s:0x%lx", tp->module, tp->address);
-   else if (!strncmp(tp->symbol, "0x", 2))
+   if (tev->uprobes) {
+   if (tp->ref_ctr_offset)
+   err = strbuf_addf(, "%s:0x%lx(0x%lx)", tp->module,
+ tp->address, tp->ref_ctr_offset);
+   else
+   err = strbuf_addf(, "%s:0x%lx", tp->module,
+ tp->address);
+   } else if (!strncmp(tp->symbol, "0x", 2)) {
/* Absolute address. See try_to_find_absolute_address() */
err = strbuf_addf(, "%s%s0x%lx", tp->module ?: "",
  tp->module ? ":" : "", tp->address);
-   else
+   } else {
err = strbuf_addf(, "%s%s%s+%lu", tp->module ?: "",
tp->module ? ":" : "", tp->symbol, tp->offset);
+   }
+
if (err)
goto error;
 
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 45b14f0..15a98c3 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -27,6 +27,7 @@ struct probe_trace_point {
char*symbol;/* Base symbol */
char*module;/* Module name */
unsigned long   offset; /* Offset from symbol */
+   unsigned long   ref_ctr_offset; /* SDT reference counter offset */
unsigned long   address;/* Actual address of the trace point */
boolretprobe;   /* Return probe flag */
 };
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 4ae1123..08ba3a6 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -701,6 +701,12 @@ static unsigned long long sdt_note__get_addr(struct 
sdt_note *note)
 : (unsigned long long)note->addr.a64[0];
 }
 
+static unsigned long long sdt_note__get_ref_ctr_offset(struct sdt_note *note)
+{
+   return note->bit32 ? (unsigned long long)note->addr.a32[2]
+   : (unsigned long long)note->addr.a64[2];
+}
+
 static const char * const type_to_suffix[] = {
":s64", "", "", "", ":s32", "", ":s16", ":s8",
"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
@@ -776,14 +782,24 @@ static char *synthesize_sdt_probe_command(struct sdt_note 
*note,
 {
struct strbuf buf;
char *ret = NULL, **args;
-   int i, args_count;
+   int i, args_count, err;
+   unsigned long long ref_ctr_offset;
 
if (strbuf_init(, 32) < 0)
return NULL;
 
-   if (strbuf_addf(, "p:%s/%s %s:0x%llx",
+   ref_ctr_offset = sdt_note__get_ref_ctr_offset(note);
+
+   if (ref_ctr_offset)
+   err = strbuf_addf(, "p:%s/%s %s:0x%llx(0x%llx)",
sdtgrp, note->name, pathname,
-   sdt_note__get_addr(note)) < 0)
+   sdt_note__get_addr(note), ref_ctr_offset);
+   else
+   err = strbuf_addf(, "p:%s/%s %s:0x%llx",
+   sdtgrp, note->name, pathname,
+   sdt_note__get_addr(note));
+
+ 

[PATCH 8/8] trace_uprobe/sdt: Document about reference counter

2018-03-13 Thread Ravi Bangoria
No functionality changes.

Signed-off-by: Ravi Bangoria 
---
 Documentation/trace/uprobetracer.txt | 16 +---
 kernel/trace/trace.c |  2 +-
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/Documentation/trace/uprobetracer.txt 
b/Documentation/trace/uprobetracer.txt
index bf526a7c..8fb13b0 100644
--- a/Documentation/trace/uprobetracer.txt
+++ b/Documentation/trace/uprobetracer.txt
@@ -19,15 +19,25 @@ user to calculate the offset of the probepoint in the 
object.
 
 Synopsis of uprobe_tracer
 -
-  p[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] : Set a uprobe
-  r[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] : Set a return uprobe (uretprobe)
-  -:[GRP/]EVENT   : Clear uprobe or uretprobe event
+  p[:[GRP/]EVENT] PATH:OFFSET[(REF_CTR_OFFSET)] [FETCHARGS]
+  r[:[GRP/]EVENT] PATH:OFFSET[(REF_CTR_OFFSET)] [FETCHARGS]
+  -:[GRP/]EVENT
+
+  p : Set a uprobe
+  r : Set a return uprobe (uretprobe)
+  - : Clear uprobe or uretprobe event
 
   GRP   : Group name. If omitted, "uprobes" is the default value.
   EVENT : Event name. If omitted, the event name is generated based
   on PATH+OFFSET.
   PATH  : Path to an executable or a library.
   OFFSET: Offset where the probe is inserted.
+  REF_CTR_OFFSET: Reference counter offset. Optional field. Reference count
+  gate the invocation of probe. If present, by default
+  reference count is 0. Kernel needs to increment it before
+  tracing the probe and decrement it when done. This is
+  identical to semaphore in Userspace Statically Defined
+  Tracepoints (USDT).
 
   FETCHARGS : Arguments. Each probe can have up to 128 args.
%REG : Fetch register REG
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 20a2300..2104d03 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4604,7 +4604,7 @@ static int tracing_trace_options_open(struct inode 
*inode, struct file *file)
   "place (kretprobe): [:][+]|\n"
 #endif
 #ifdef CONFIG_UPROBE_EVENTS
-   "\tplace: :\n"
+  "   place (uprobe): :[(ref_ctr_offset)]\n"
 #endif
"\t args: =fetcharg[:type]\n"
"\t fetcharg: %, @, @[+|-],\n"
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/8] trace_uprobe/sdt: Fix multiple update of same reference counter

2018-03-13 Thread Ravi Bangoria
For tiny binaries/libraries, different mmap regions points to the
same file portion. In such cases, we may increment reference counter
multiple times. But while de-registration, reference counter will get
decremented only by once leaving reference counter > 0 even if no one
is tracing on that marker.

Ensure increment and decrement happens in sync by keeping list of
mms in trace_uprobe. Increment reference counter only if mm is not
present in the list and decrement only if mm is present in the list.

Example

  # echo "p:sdt_tick/loop2 /tmp/tick:0x6e4(0x10036)" > uprobe_events

Before patch:

  # perf stat -a -e sdt_tick:loop2
  # /tmp/tick
  # dd if=/proc/`pgrep tick`/mem bs=1 count=1 skip=$(( 0x10020036 )) 
2>/dev/null | xxd
   000: 02   .

  # pkill perf
  # dd if=/proc/`pgrep tick`/mem bs=1 count=1 skip=$(( 0x10020036 )) 
2>/dev/null | xxd
  000: 01   .

After patch:

  # perf stat -a -e sdt_tick:loop2
  # /tmp/tick
  # dd if=/proc/`pgrep tick`/mem bs=1 count=1 skip=$(( 0x10020036 )) 
2>/dev/null | xxd
  000: 01   .

  # pkill perf
  # dd if=/proc/`pgrep tick`/mem bs=1 count=1 skip=$(( 0x10020036 )) 
2>/dev/null | xxd
  000: 00   .

Signed-off-by: Ravi Bangoria 
---
 kernel/trace/trace_uprobe.c | 105 +++-
 1 file changed, 103 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index b6c9b48..9bf3f7a 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -50,6 +50,11 @@ struct trace_uprobe_filter {
struct list_headperf_events;
 };
 
+struct sdt_mm_list {
+   struct mm_struct *mm;
+   struct sdt_mm_list *next;
+};
+
 /*
  * uprobe event core functions
  */
@@ -61,6 +66,8 @@ struct trace_uprobe {
char*filename;
unsigned long   offset;
unsigned long   ref_ctr_offset;
+   struct sdt_mm_list  *sml;
+   struct rw_semaphore sml_rw_sem;
unsigned long   nhit;
struct trace_probe  tp;
 };
@@ -274,6 +281,7 @@ static inline bool is_ret_probe(struct trace_uprobe *tu)
if (is_ret)
tu->consumer.ret_handler = uretprobe_dispatcher;
init_trace_uprobe_filter(>filter);
+   init_rwsem(>sml_rw_sem);
return tu;
 
 error:
@@ -921,6 +929,74 @@ static void uretprobe_trace_func(struct trace_uprobe *tu, 
unsigned long func,
return trace_handle_return(s);
 }
 
+static bool sdt_check_mm_list(struct trace_uprobe *tu, struct mm_struct *mm)
+{
+   struct sdt_mm_list *tmp = tu->sml;
+
+   if (!tu->sml || !mm)
+   return false;
+
+   while (tmp) {
+   if (tmp->mm == mm)
+   return true;
+   tmp = tmp->next;
+   }
+
+   return false;
+}
+
+static void sdt_add_mm_list(struct trace_uprobe *tu, struct mm_struct *mm)
+{
+   struct sdt_mm_list *tmp;
+
+   tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+   if (!tmp)
+   return;
+
+   tmp->mm = mm;
+   tmp->next = tu->sml;
+   tu->sml = tmp;
+}
+
+static void sdt_del_mm_list(struct trace_uprobe *tu, struct mm_struct *mm)
+{
+   struct sdt_mm_list *prev, *curr;
+
+   if (!tu->sml)
+   return;
+
+   if (tu->sml->mm == mm) {
+   curr = tu->sml;
+   tu->sml = tu->sml->next;
+   kfree(curr);
+   return;
+   }
+
+   prev = tu->sml;
+   curr = tu->sml->next;
+   while (curr) {
+   if (curr->mm == mm) {
+   prev->next = curr->next;
+   kfree(curr);
+   return;
+   }
+   prev = curr;
+   curr = curr->next;
+   }
+}
+
+static void sdt_flush_mm_list(struct trace_uprobe *tu)
+{
+   struct sdt_mm_list *next, *curr = tu->sml;
+
+   while (curr) {
+   next = curr->next;
+   kfree(curr);
+   curr = next;
+   }
+   tu->sml = NULL;
+}
+
 static bool sdt_valid_vma(struct trace_uprobe *tu, struct vm_area_struct *vma)
 {
unsigned long vaddr = vma_offset_to_vaddr(vma, tu->ref_ctr_offset);
@@ -989,17 +1065,25 @@ static void sdt_increment_ref_ctr(struct trace_uprobe 
*tu)
if (IS_ERR(info))
goto out;
 
+   down_write(>sml_rw_sem);
while (info) {
+   if (sdt_check_mm_list(tu, info->mm))
+   goto cont;
+
down_write(>mm->mmap_sem);
 
vma = sdt_find_vma(info->mm, tu);
vaddr = vma_offset_to_vaddr(vma, tu->ref_ctr_offset);
-   sdt_update_ref_ctr(info->mm, vaddr, 1);
+   if 

[PATCH 5/8] trace_uprobe: Support SDT markers having reference count (semaphore)

2018-03-13 Thread Ravi Bangoria
Userspace Statically Defined Tracepoints[1] are dtrace style markers
inside userspace applications. These markers are added by developer at
important places in the code. Each marker source expands to a single
nop instruction in the compiled code but there may be additional
overhead for computing the marker arguments which expands to couple of
instructions. In case the overhead is more, execution of it can be
ommited by runtime if() condition when no one is tracing on the marker:

if (reference_counter > 0) {
Execute marker instructions;
}

Default value of reference counter is 0. Tracer has to increment the
reference counter before tracing on a marker and decrement it when
done with the tracing.

Implement the reference counter logic in trace_uprobe, leaving core
uprobe infrastructure as is, except one new callback from uprobe_mmap()
to trace_uprobe.

trace_uprobe definition with reference counter will now be:

  :[(ref_ctr_offset)]

There are two different cases while enabling the marker,
 1. Trace existing process. In this case, find all suitable processes
and increment the reference counter in them.
 2. Enable trace before running target binary. In this case, all mmaps
will get notified to trace_uprobe and trace_uprobe will increment
the reference counter if corresponding uprobe is enabled.

At the time of disabling probes, decrement reference counter in all
existing target processes.

[1] https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation

Note: 'reference counter' is called as 'semaphore' in original Dtrace
(or Systemtap, bcc and even in ELF) documentation and code. But the
term 'semaphore' is misleading in this context. This is just a counter
used to hold number of tracers tracing on a marker. This is not really
used for any synchronization. So we are referring it as 'reference
counter' in kernel / perf code.

Signed-off-by: Ravi Bangoria 
Signed-off-by: Fengguang Wu 
[Fengguang reported/fixed build failure in RFC patch]
---
 include/linux/uprobes.h |   2 +
 kernel/events/uprobes.c |   6 ++
 kernel/trace/trace_uprobe.c | 172 +++-
 3 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index 7bd2760..2d4df65 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -122,6 +122,8 @@ struct uprobe_map_info {
unsigned long vaddr;
 };
 
+extern void (*uprobe_mmap_callback)(struct vm_area_struct *vma);
+
 extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned 
long vaddr);
 extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, 
unsigned long vaddr);
 extern bool is_swbp_insn(uprobe_opcode_t *insn);
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index e7830b8..06821bb 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1041,6 +1041,9 @@ static void build_probe_list(struct inode *inode,
spin_unlock(_treelock);
 }
 
+/* Rightnow the only user of this is trace_uprobe. */
+void (*uprobe_mmap_callback)(struct vm_area_struct *vma);
+
 /*
  * Called from mmap_region/vma_adjust with mm->mmap_sem acquired.
  *
@@ -1053,6 +1056,9 @@ int uprobe_mmap(struct vm_area_struct *vma)
struct uprobe *uprobe, *u;
struct inode *inode;
 
+   if (uprobe_mmap_callback)
+   uprobe_mmap_callback(vma);
+
if (no_uprobe_events() || !valid_vma(vma, true))
return 0;
 
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 2014f43..b6c9b48 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -25,6 +25,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "trace_probe.h"
 
@@ -58,6 +60,7 @@ struct trace_uprobe {
struct inode*inode;
char*filename;
unsigned long   offset;
+   unsigned long   ref_ctr_offset;
unsigned long   nhit;
struct trace_probe  tp;
 };
@@ -362,10 +365,10 @@ static int create_trace_uprobe(int argc, char **argv)
 {
struct trace_uprobe *tu;
struct inode *inode;
-   char *arg, *event, *group, *filename;
+   char *arg, *event, *group, *filename, *rctr, *rctr_end;
char buf[MAX_EVENT_NAME_LEN];
struct path path;
-   unsigned long offset;
+   unsigned long offset, ref_ctr_offset;
bool is_delete, is_return;
int i, ret;
 
@@ -375,6 +378,7 @@ static int create_trace_uprobe(int argc, char **argv)
is_return = false;
event = NULL;
group = NULL;
+   ref_ctr_offset = 0;
 
/* argc must be >= 1 */
if (argv[0][0] == '-')
@@ -454,6 +458,26 @@ static int create_trace_uprobe(int argc, char **argv)
goto fail_address_parse;
}
 
+   /* 

[PATCH 1/8] Uprobe: Export vaddr <-> offset conversion functions

2018-03-13 Thread Ravi Bangoria
No functionality changes.

Signed-off-by: Ravi Bangoria 
---
 include/linux/mm.h  | 12 
 kernel/events/uprobes.c | 10 --
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index ad06d42..95909f2 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2274,6 +2274,18 @@ struct vm_unmapped_area_info {
return unmapped_area(info);
 }
 
+static inline unsigned long
+offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
+{
+   return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
+}
+
+static inline loff_t
+vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
+{
+   return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
+}
+
 /* truncate.c */
 extern void truncate_inode_pages(struct address_space *, loff_t);
 extern void truncate_inode_pages_range(struct address_space *,
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ce6848e..bd6f230 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -130,16 +130,6 @@ static bool valid_vma(struct vm_area_struct *vma, bool 
is_register)
return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC;
 }
 
-static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
-{
-   return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
-}
-
-static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
-{
-   return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
-}
-
 /**
  * __replace_page - replace page in vma by new page.
  * based on replace_page in mm/ksm.c
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/8] trace_uprobe: Support SDT markers having reference count (semaphore)

2018-03-13 Thread Ravi Bangoria
Userspace Statically Defined Tracepoints[1] are dtrace style markers
inside userspace applications. These markers are added by developer at
important places in the code. Each marker source expands to a single
nop instruction in the compiled code but there may be additional
overhead for computing the marker arguments which expands to couple of
instructions. In case the overhead is more, execution of it can be
omitted by runtime if() condition when no one is tracing on the marker:

if (reference_counter > 0) {
Execute marker instructions;
}   

Default value of reference counter is 0. Tracer has to increment the 
reference counter before tracing on a marker and decrement it when
done with the tracing.

Currently, perf tool has limited supports for SDT markers. I.e. it
can not trace markers surrounded by reference counter. Also, it's
not easy to add reference counter logic in userspace tool like perf,
so basic idea for this patchset is to add reference counter logic in
the trace_uprobe infrastructure. Ex,[2]

  # cat tick.c
... 
for (i = 0; i < 100; i++) {
DTRACE_PROBE1(tick, loop1, i);
if (TICK_LOOP2_ENABLED()) {
DTRACE_PROBE1(tick, loop2, i); 
}
printf("hi: %d\n", i); 
sleep(1);
}   
... 

Here tick:loop1 is marker without reference counter where as tick:loop2
is surrounded by reference counter condition.

  # perf buildid-cache --add /tmp/tick
  # perf probe sdt_tick:loop1
  # perf probe sdt_tick:loop2

  # perf stat -e sdt_tick:loop1,sdt_tick:loop2 -- /tmp/tick
  hi: 0
  hi: 1
  hi: 2
  ^C
  Performance counter stats for '/tmp/tick':
 3  sdt_tick:loop1
 0  sdt_tick:loop2
 2.747086086 seconds time elapsed


Perf failed to record data for tick:loop2. Same experiment with this
patch series:

  # ./perf buildid-cache --add /tmp/tick
  # ./perf probe sdt_tick:loop2
  # ./perf stat -e sdt_tick:loop2 /tmp/tick
hi: 0
hi: 1
hi: 2
^C  
 Performance counter stats for '/tmp/tick':
 3  sdt_tick:loop2
   2.561851452 seconds time elapsed

[1] https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation
[2] https://github.com/iovisor/bcc/issues/327#issuecomment-200576506
[3] https://lkml.org/lkml/2017/12/6/976


Note: 'reference counter' is called as 'semaphore' in original Dtrace
(or Systemtap, bcc and even in ELF) documentation and code. But the 
term 'semaphore' is misleading in this context. This is just a counter
used to hold number of tracers tracing on a marker. This is not really
used for any synchronization. So we are referring it as 'reference
counter' in kernel / perf code.

RFC series can be found at:
  https://lkml.org/lkml/2018/2/28/76

Ravi Bangoria (8):
  Uprobe: Export vaddr <-> offset conversion functions
  mm: Prefix vma_ to vaddr_to_offset() and offset_to_vaddr()
  Uprobe: Rename map_info to uprobe_map_info
  Uprobe: Export uprobe_map_info along with
uprobe_{build/free}_map_info()
  trace_uprobe: Support SDT markers having reference count (semaphore)
  trace_uprobe/sdt: Fix multiple update of same reference counter
  perf probe: Support SDT markers having reference counter (semaphore)
  trace_uprobe/sdt: Document about reference counter

 Documentation/trace/uprobetracer.txt |  16 +-
 include/linux/mm.h   |  12 ++
 include/linux/uprobes.h  |  11 ++
 kernel/events/uprobes.c  |  62 
 kernel/trace/trace.c |   2 +-
 kernel/trace/trace_uprobe.c  | 273 ++-
 tools/perf/util/probe-event.c|  21 ++-
 tools/perf/util/probe-event.h|   1 +
 tools/perf/util/probe-file.c |  22 ++-
 tools/perf/util/symbol-elf.c |  10 ++
 tools/perf/util/symbol.h |   1 +
 11 files changed, 382 insertions(+), 49 deletions(-)

-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[trivial PATCH] Documentation/sparse: fix typo

2018-03-13 Thread Eric Engestrom
Signed-off-by: Eric Engestrom 
---
 Documentation/dev-tools/sparse.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/dev-tools/sparse.rst 
b/Documentation/dev-tools/sparse.rst
index 78aa00a604a009071361..c401c952a340a50fa769 100644
--- a/Documentation/dev-tools/sparse.rst
+++ b/Documentation/dev-tools/sparse.rst
@@ -67,7 +67,7 @@ __releases - The specified lock is held on function entry, 
but not exit.
 
 If the function enters and exits without the lock held, acquiring and
 releasing the lock inside the function in a balanced way, no
-annotation is needed.  The tree annotations above are for cases where
+annotation is needed.  The three annotations above are for cases where
 sparse would otherwise report a context imbalance.
 
 Getting sparse
-- 
Cheers,
  Eric

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 7/8] [PATCH 7/8] drivers/hwmon: Add a generic PECI hwmon client driver

2018-03-13 Thread Stef van Os

Hi Jae,

I tried version 1 and 2 of your PECI patch on our (AST2500 / Xeon E5 v4) 
system. The V1 patchset works as expected (reading back temperature 0 
until PECI is up), but the hwmon driver probe fails with version 2. It 
communicates with the Xeon and assumes during kernel boot of the Aspeed 
that PECI to the Xeon's is already up and running, but our system 
enables the main Xeon supplies from AST2500 userspace.


If I load the hwmon driver as a module to load later on, the driver does 
not call probe like e.g. a I2C driver on the I2C bus does. Am I using V2 
wrongly?


BR,
Stef

On 02/21/2018 05:16 PM, Jae Hyun Yoo wrote:

This commit adds a generic PECI hwmon client driver implementation.

Signed-off-by: Jae Hyun Yoo 
---
  drivers/hwmon/Kconfig  |  10 +
  drivers/hwmon/Makefile |   1 +
  drivers/hwmon/peci-hwmon.c | 928 +
  3 files changed, 939 insertions(+)
  create mode 100644 drivers/hwmon/peci-hwmon.c

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index ef23553ff5cb..f22e0c31f597 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1246,6 +1246,16 @@ config SENSORS_NCT7904
  This driver can also be built as a module.  If so, the module
  will be called nct7904.
  
+config SENSORS_PECI_HWMON

+   tristate "PECI hwmon support"
+   depends on PECI
+   help
+ If you say yes here you get support for the generic PECI hwmon
+ driver.
+
+ This driver can also be built as a module.  If so, the module
+ will be called peci-hwmon.
+
  config SENSORS_NSA320
tristate "ZyXEL NSA320 and compatible fan speed and temperature sensors"
depends on GPIOLIB && OF
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index f814b4ace138..946f54b168e5 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -135,6 +135,7 @@ obj-$(CONFIG_SENSORS_NCT7802)   += nct7802.o
  obj-$(CONFIG_SENSORS_NCT7904) += nct7904.o
  obj-$(CONFIG_SENSORS_NSA320)  += nsa320-hwmon.o
  obj-$(CONFIG_SENSORS_NTC_THERMISTOR)  += ntc_thermistor.o
+obj-$(CONFIG_SENSORS_PECI_HWMON)   += peci-hwmon.o
  obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
  obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
  obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
diff --git a/drivers/hwmon/peci-hwmon.c b/drivers/hwmon/peci-hwmon.c
new file mode 100644
index ..edd27744adcb
--- /dev/null
+++ b/drivers/hwmon/peci-hwmon.c
@@ -0,0 +1,928 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018 Intel Corporation
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DIMM_SLOT_NUMS_MAX12  /* Max DIMM numbers (channel ranks x 2) */
+#define CORE_NUMS_MAX 28  /* Max core numbers (max on SKX Platinum) */
+#define TEMP_TYPE_PECI6   /* Sensor type 6: Intel PECI */
+
+#define CORE_TEMP_ATTRS   5
+#define DIMM_TEMP_ATTRS   2
+#define ATTR_NAME_LEN 24
+
+#define DEFAULT_ATTR_GRP_NUMS 5
+
+#define UPDATE_INTERVAL_MIN   HZ
+#define DIMM_MASK_CHECK_DELAY msecs_to_jiffies(5000)
+
+enum sign {
+   POS,
+   NEG
+};
+
+struct temp_data {
+   bool valid;
+   s32  value;
+   unsigned long last_updated;
+};
+
+struct temp_group {
+   struct temp_data tjmax;
+   struct temp_data tcontrol;
+   struct temp_data tthrottle;
+   struct temp_data dts_margin;
+   struct temp_data die;
+   struct temp_data core[CORE_NUMS_MAX];
+   struct temp_data dimm[DIMM_SLOT_NUMS_MAX];
+};
+
+struct core_temp_group {
+   struct sensor_device_attribute sd_attrs[CORE_TEMP_ATTRS];
+   char attr_name[CORE_TEMP_ATTRS][ATTR_NAME_LEN];
+   struct attribute *attrs[CORE_TEMP_ATTRS + 1];
+   struct attribute_group attr_group;
+};
+
+struct dimm_temp_group {
+   struct sensor_device_attribute sd_attrs[DIMM_TEMP_ATTRS];
+   char attr_name[DIMM_TEMP_ATTRS][ATTR_NAME_LEN];
+   struct attribute *attrs[DIMM_TEMP_ATTRS + 1];
+   struct attribute_group attr_group;
+};
+
+struct peci_hwmon {
+   struct peci_client *client;
+   struct device *dev;
+   struct device *hwmon_dev;
+   struct workqueue_struct *work_queue;
+   struct delayed_work work_handler;
+   char name[PECI_NAME_SIZE];
+   struct temp_group temp;
+   u8 addr;
+   uint cpu_no;
+   u32 core_mask;
+   u32 dimm_mask;
+   const struct attribute_group *core_attr_groups[CORE_NUMS_MAX + 1];
+   const struct attribute_group *dimm_attr_groups[DIMM_SLOT_NUMS_MAX + 1];
+   uint global_idx;
+   uint core_idx;
+   uint dimm_idx;
+};
+
+enum label {
+   L_DIE,
+   L_DTS,
+   L_TCONTROL,
+   L_TTHROTTLE,
+   L_TJMAX,
+   L_MAX
+};
+
+static const char *peci_label[L_MAX] = {
+   "Die\n",
+   "DTS margin to Tcontrol\n",
+   "Tcontrol\n",
+   "Tthrottle\n",
+   "Tjmax\n",
+};
+
+static int 

Re: [PATCH V4] thermal: Add cooling device's statistics in sysfs

2018-03-13 Thread Viresh Kumar
On 13-03-18, 15:02, Zhang Rui wrote:
> Hi, Viresh,
> 
> I will queue it for 4.17, with just one minor fix below.
> 
> On 二, 2018-01-16 at 15:22 +0530, Viresh Kumar wrote:

> > +   cdev->stats = stats;
> > +   stats->last_time = ktime_get();
> > +   stats->max_states = states;
> > +   cdev->stats = stats;
> > +
> 
> cdev->stats is set twice here, I will remove the first one.

Thanks for catching that :)

-- 
viresh
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html