Re: [RESEND PATCH 2/4] x86: add phys addr validity check for /dev/mem mmap

2014-09-30 Thread Frantisek Hrbata
On Tue, Sep 30, 2014 at 07:27:51AM -0700, Dave Hansen wrote:
> On 09/30/2014 05:41 AM, Frantisek Hrbata wrote:
> > Does it make sense to replace "count" with "size" so it's consistent with 
> > the
> > rest or do you prefer "nr_bytes" or as Dave proposed "len_bytes"?
> 
> I don't care what it is as long as it has a unit in it.

Hi Dave/Thomas,

I sent v2 of this patch set, which uses the "len_bytes". Again, I'm sorry I
forgot to fix this the first time.

Many thanks

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 4/4] x86: remove high_memory check from valid_phys_addr_range

2014-09-30 Thread Frantisek Hrbata
There is no need to block read/write access to /dev/mem for phys. addr. above
high_memory for non-system RAM. The only limitation should be
boot_cpu_data.x86_phys_bits(max phys. addr. size).

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/mm/mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 77a13f8..788f2b7 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -127,7 +127,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
-   return addr + count <= __pa(high_memory);
+   return arch_pfn_possible((addr + count) >> PAGE_SHIFT);
 }
 
 int valid_mmap_phys_addr_range(unsigned long pfn, size_t len_bytes)
-- 
1.9.3

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


[PATCH v2 2/4] x86: add phys addr validity check for /dev/mem mmap

2014-09-30 Thread Frantisek Hrbata
t main(int argc, char *argv[])
{
int fd;
long ps;
char *map;
char c;

ps = sysconf(_SC_PAGE_SIZE);
if (ps == -1)
die("cannot get page size");

fd = open("/dev/mem", O_RDONLY|O_LARGEFILE);
if (fd == -1)
die("cannot open /dev/mem");

map = (char *)syscall(SYS_mmap2, NULL, ps, PROT_READ, MAP_SHARED, fd, 
OFFSET);
if (map == MAP_FAILED)
die("cannot mmap");

c = map[0];

if (munmap(map, ps) == -1)
die("cannot munmap");

if (close(fd) == -1)
die("cannot close");

return 0;
}
-8<--

V3: use len_bytes instead of count, thanks to Dave Hansen and Thomas Gleixner
V2: fix pfn check in valid_mmap_phys_addr_range, thanks to Dave Hansen

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 12 
 2 files changed, 16 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index b8237d8..49ede3c 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -243,6 +243,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t len_bytes);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 919b912..77a13f8 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include 
 #include 
 
+#include "physaddr.h"
+
 struct va_alignment __read_mostly va_align = {
.flags = -1,
 };
@@ -122,3 +124,13 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count <= __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t len_bytes)
+{
+   return arch_pfn_possible(pfn + (len_bytes >> PAGE_SHIFT));
+}
-- 
1.9.3

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


[PATCH v2 3/4] x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr

2014-09-30 Thread Frantisek Hrbata
So far (xlate|unxlate)_dev_mem_ptr for read/write /dev/mem relies on a generic
high_memory check in valid_phys_addr_range(), which does not allow to access any
memory above high_memory whatsoever. By adding the high_memory check to
(xlate|unxlate)_dev_mem_ptr, it still will be possible to use __va safely for
kernel mapped memory and it will also allow read/write to access non-system RAM
above high_memory once the high_memory check is removed from
valid_phys_addr_range.

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/mm/ioremap.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da..1ae7323 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -320,8 +320,11 @@ void *xlate_dev_mem_ptr(unsigned long phys)
void *addr;
unsigned long start = phys & PAGE_MASK;
 
-   /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
-   if (page_is_ram(start >> PAGE_SHIFT))
+   /*
+* If page is RAM and is mapped by kernel, we can use __va.
+* Otherwise ioremap and unmap.
+*/
+   if (page_is_ram(start >> PAGE_SHIFT) && phys <= __pa(high_memory))
return __va(phys);
 
addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
@@ -333,7 +336,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
 
 void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 {
-   if (page_is_ram(phys >> PAGE_SHIFT))
+   if (page_is_ram(phys >> PAGE_SHIFT) && phys <= __pa(high_memory))
return;
 
iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
-- 
1.9.3

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


[PATCH v2 0/4] x86: /dev/mem fixes

2014-09-30 Thread Frantisek Hrbata
This is a second version of the patch set. The only change is in

2/4 x86: add phys addr validity check for /dev/mem mmap

where the "count" was replaced with "len_bytes" for better readability.

The rest is just a refresh because of this change.

The original message follows ...

Hi all,

this is a combination of two patch sets I sent a while ago
1) Prevent possible PTE corruption with /dev/mem mmap
2) x86: allow read/write /dev/mem to access non-system RAM above high_memory

The original thread with both patch sets can be found here
   https://lkml.org/lkml/2014/8/14/229
   lkml: <1408025927-16826-1-git-send-email-fhrb...@redhat.com>

1) Prevent possible PTE corruption with /dev/mem mmap
x86: add arch_pfn_possible helper
x86: add phys addr validity check for /dev/mem mmap

Many thanks goes to Dave Hansen, who helped with the "final" check. Other than
that it did not get much attention, except H. Peter Anvin's complain that having
two checks for mmap and read/write for /dev/mem access is ridiculous. I for sure
do not object to this, but AFAICT it's not that simple to unify them and it's 
not
"directly" related to the PTE corruption. Please note that there are other
archs(ia64, arm) using these check. But I for sure can be missing something.

What this patch set does is using the existing interface to implement x86 
specific
check in the least invasive way.

Anyway I tried to remove the high_memory check with a follow-up patch set 2)

2) x86: allow read/write /dev/mem to access non-system RAM above high_memory
x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
x86: remove high_memory check from valid_phys_addr_range

This is an attempt to remove the high_memory limit for the read/write access to
/dev/mem. IMHO there is no reason for this limit on x86. It is presented in
the generic valid_phys_addr_range, which is used only by (read|write)_mem. IIUIC
it's main purpose is for the generic xlate_dev_mem_ptr, which is using only the
direct kernel mapping __va translation. Since the valid_phys_addr_range is
called as the first check in (read|write)_mem, it basically does not allow to
access anything above high_memory on x86.

The first patch adds high_memory check to x86's (xlate|unxlate)_dev_mem_ptr, so
the direct kernel mapping can be safely used for system RAM bellow high_memory.
This is IMHO the only valid reason to use high_memory check in (read|write)_mem.

The second patch removes the high_memory check from valid_phys_addr_range,
allowing read/write to access non-system RAM above high_memory. So far this
was possible only by using mmap.

I hope I haven't overlooked something.

Many thanks

Frantisek Hrbata (4):
  x86: add arch_pfn_possible helper
  x86: add phys addr validity check for /dev/mem mmap
  x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
  x86: remove high_memory check from valid_phys_addr_range

 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/ioremap.c |  9 ++---
 arch/x86/mm/mmap.c| 12 
 arch/x86/mm/physaddr.h|  9 +++--
 4 files changed, 29 insertions(+), 5 deletions(-)

-- 
1.9.3

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


[PATCH v2 1/4] x86: add arch_pfn_possible helper

2014-09-30 Thread Frantisek Hrbata
Add helper to check maximum possible pfn on x86. Also make the current
phys_addr_valid helper using it internally.

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/mm/physaddr.h | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/physaddr.h b/arch/x86/mm/physaddr.h
index a3cd5a0..9df8e3a 100644
--- a/arch/x86/mm/physaddr.h
+++ b/arch/x86/mm/physaddr.h
@@ -1,10 +1,15 @@
 #include 
 
-static inline int phys_addr_valid(resource_size_t addr)
+static inline int arch_pfn_possible(unsigned long pfn)
 {
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
-   return !(addr >> boot_cpu_data.x86_phys_bits);
+   return !(pfn >> (boot_cpu_data.x86_phys_bits - PAGE_SHIFT));
 #else
return 1;
 #endif
 }
+
+static inline int phys_addr_valid(resource_size_t addr)
+{
+   return arch_pfn_possible(addr >> PAGE_SHIFT);
+}
-- 
1.9.3

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


Re: [RESEND PATCH 2/4] x86: add phys addr validity check for /dev/mem mmap

2014-09-30 Thread Frantisek Hrbata
On Mon, Sep 29, 2014 at 10:15:28PM +0200, Thomas Gleixner wrote:
> On Mon, 29 Sep 2014, Frantisek Hrbata wrote:
> > V2: fix pfn check in valid_mmap_phys_addr_range, thanks to Dave Hansen
> 
> AFAICT, Dave also asked you to change size_t count into something more
> intuitive, i.e. nr_bytes or such.

Hi,

mea culpa, I for unknown reason changed it from "size" to "count". I guess some
cut mess. The correct prototype used elsewhere in kernel is

int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)

Does it make sense to replace "count" with "size" so it's consistent with the
rest or do you prefer "nr_bytes" or as Dave proposed "len_bytes"?

I will fix this and I'm sorry Dave I did not change it as discussed. It totally
slipped my mind.

Many thanks Thomas.

> 
> > +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
> 
> And right he is. I really had to look twice to see that count is
> actually number of bytes and not number of pages, which is what you
> expect after pfn.
> 
> > +{
> > +   return arch_pfn_possible(pfn + (count >> PAGE_SHIFT));
> > +}
> 
> Thanks,
> 
>   tglx

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RESEND PATCH 2/4] x86: add phys addr validity check for /dev/mem mmap

2014-09-30 Thread Frantisek Hrbata
On Mon, Sep 29, 2014 at 10:15:28PM +0200, Thomas Gleixner wrote:
 On Mon, 29 Sep 2014, Frantisek Hrbata wrote:
  V2: fix pfn check in valid_mmap_phys_addr_range, thanks to Dave Hansen
 
 AFAICT, Dave also asked you to change size_t count into something more
 intuitive, i.e. nr_bytes or such.

Hi,

mea culpa, I for unknown reason changed it from size to count. I guess some
cutpaste mess. The correct prototype used elsewhere in kernel is

int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)

Does it make sense to replace count with size so it's consistent with the
rest or do you prefer nr_bytes or as Dave proposed len_bytes?

I will fix this and I'm sorry Dave I did not change it as discussed. It totally
slipped my mind.

Many thanks Thomas.

 
  +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
 
 And right he is. I really had to look twice to see that count is
 actually number of bytes and not number of pages, which is what you
 expect after pfn.
 
  +{
  +   return arch_pfn_possible(pfn + (count  PAGE_SHIFT));
  +}
 
 Thanks,
 
   tglx

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 1/4] x86: add arch_pfn_possible helper

2014-09-30 Thread Frantisek Hrbata
Add helper to check maximum possible pfn on x86. Also make the current
phys_addr_valid helper using it internally.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/mm/physaddr.h | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/physaddr.h b/arch/x86/mm/physaddr.h
index a3cd5a0..9df8e3a 100644
--- a/arch/x86/mm/physaddr.h
+++ b/arch/x86/mm/physaddr.h
@@ -1,10 +1,15 @@
 #include asm/processor.h
 
-static inline int phys_addr_valid(resource_size_t addr)
+static inline int arch_pfn_possible(unsigned long pfn)
 {
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
-   return !(addr  boot_cpu_data.x86_phys_bits);
+   return !(pfn  (boot_cpu_data.x86_phys_bits - PAGE_SHIFT));
 #else
return 1;
 #endif
 }
+
+static inline int phys_addr_valid(resource_size_t addr)
+{
+   return arch_pfn_possible(addr  PAGE_SHIFT);
+}
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 0/4] x86: /dev/mem fixes

2014-09-30 Thread Frantisek Hrbata
This is a second version of the patch set. The only change is in

2/4 x86: add phys addr validity check for /dev/mem mmap

where the count was replaced with len_bytes for better readability.

The rest is just a refresh because of this change.

The original message follows ...

Hi all,

this is a combination of two patch sets I sent a while ago
1) Prevent possible PTE corruption with /dev/mem mmap
2) x86: allow read/write /dev/mem to access non-system RAM above high_memory

The original thread with both patch sets can be found here
   https://lkml.org/lkml/2014/8/14/229
   lkml: 1408025927-16826-1-git-send-email-fhrb...@redhat.com

1) Prevent possible PTE corruption with /dev/mem mmap
x86: add arch_pfn_possible helper
x86: add phys addr validity check for /dev/mem mmap

Many thanks goes to Dave Hansen, who helped with the final check. Other than
that it did not get much attention, except H. Peter Anvin's complain that having
two checks for mmap and read/write for /dev/mem access is ridiculous. I for sure
do not object to this, but AFAICT it's not that simple to unify them and it's 
not
directly related to the PTE corruption. Please note that there are other
archs(ia64, arm) using these check. But I for sure can be missing something.

What this patch set does is using the existing interface to implement x86 
specific
check in the least invasive way.

Anyway I tried to remove the high_memory check with a follow-up patch set 2)

2) x86: allow read/write /dev/mem to access non-system RAM above high_memory
x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
x86: remove high_memory check from valid_phys_addr_range

This is an attempt to remove the high_memory limit for the read/write access to
/dev/mem. IMHO there is no reason for this limit on x86. It is presented in
the generic valid_phys_addr_range, which is used only by (read|write)_mem. IIUIC
it's main purpose is for the generic xlate_dev_mem_ptr, which is using only the
direct kernel mapping __va translation. Since the valid_phys_addr_range is
called as the first check in (read|write)_mem, it basically does not allow to
access anything above high_memory on x86.

The first patch adds high_memory check to x86's (xlate|unxlate)_dev_mem_ptr, so
the direct kernel mapping can be safely used for system RAM bellow high_memory.
This is IMHO the only valid reason to use high_memory check in (read|write)_mem.

The second patch removes the high_memory check from valid_phys_addr_range,
allowing read/write to access non-system RAM above high_memory. So far this
was possible only by using mmap.

I hope I haven't overlooked something.

Many thanks

Frantisek Hrbata (4):
  x86: add arch_pfn_possible helper
  x86: add phys addr validity check for /dev/mem mmap
  x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
  x86: remove high_memory check from valid_phys_addr_range

 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/ioremap.c |  9 ++---
 arch/x86/mm/mmap.c| 12 
 arch/x86/mm/physaddr.h|  9 +++--
 4 files changed, 29 insertions(+), 5 deletions(-)

-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 3/4] x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr

2014-09-30 Thread Frantisek Hrbata
So far (xlate|unxlate)_dev_mem_ptr for read/write /dev/mem relies on a generic
high_memory check in valid_phys_addr_range(), which does not allow to access any
memory above high_memory whatsoever. By adding the high_memory check to
(xlate|unxlate)_dev_mem_ptr, it still will be possible to use __va safely for
kernel mapped memory and it will also allow read/write to access non-system RAM
above high_memory once the high_memory check is removed from
valid_phys_addr_range.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/mm/ioremap.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da..1ae7323 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -320,8 +320,11 @@ void *xlate_dev_mem_ptr(unsigned long phys)
void *addr;
unsigned long start = phys  PAGE_MASK;
 
-   /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
-   if (page_is_ram(start  PAGE_SHIFT))
+   /*
+* If page is RAM and is mapped by kernel, we can use __va.
+* Otherwise ioremap and unmap.
+*/
+   if (page_is_ram(start  PAGE_SHIFT)  phys = __pa(high_memory))
return __va(phys);
 
addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
@@ -333,7 +336,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
 
 void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 {
-   if (page_is_ram(phys  PAGE_SHIFT))
+   if (page_is_ram(phys  PAGE_SHIFT)  phys = __pa(high_memory))
return;
 
iounmap((void __iomem *)((unsigned long)addr  PAGE_MASK));
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 4/4] x86: remove high_memory check from valid_phys_addr_range

2014-09-30 Thread Frantisek Hrbata
There is no need to block read/write access to /dev/mem for phys. addr. above
high_memory for non-system RAM. The only limitation should be
boot_cpu_data.x86_phys_bits(max phys. addr. size).

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/mm/mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 77a13f8..788f2b7 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -127,7 +127,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
-   return addr + count = __pa(high_memory);
+   return arch_pfn_possible((addr + count)  PAGE_SHIFT);
 }
 
 int valid_mmap_phys_addr_range(unsigned long pfn, size_t len_bytes)
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 2/4] x86: add phys addr validity check for /dev/mem mmap

2014-09-30 Thread Frantisek Hrbata
 OFFSET 0x200

int main(int argc, char *argv[])
{
int fd;
long ps;
char *map;
char c;

ps = sysconf(_SC_PAGE_SIZE);
if (ps == -1)
die(cannot get page size);

fd = open(/dev/mem, O_RDONLY|O_LARGEFILE);
if (fd == -1)
die(cannot open /dev/mem);

map = (char *)syscall(SYS_mmap2, NULL, ps, PROT_READ, MAP_SHARED, fd, 
OFFSET);
if (map == MAP_FAILED)
die(cannot mmap);

c = map[0];

if (munmap(map, ps) == -1)
die(cannot munmap);

if (close(fd) == -1)
die(cannot close);

return 0;
}
-8--

V3: use len_bytes instead of count, thanks to Dave Hansen and Thomas Gleixner
V2: fix pfn check in valid_mmap_phys_addr_range, thanks to Dave Hansen

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 12 
 2 files changed, 16 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index b8237d8..49ede3c 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -243,6 +243,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t len_bytes);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 919b912..77a13f8 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include linux/sched.h
 #include asm/elf.h
 
+#include physaddr.h
+
 struct va_alignment __read_mostly va_align = {
.flags = -1,
 };
@@ -122,3 +124,13 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm-get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count = __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t len_bytes)
+{
+   return arch_pfn_possible(pfn + (len_bytes  PAGE_SHIFT));
+}
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RESEND PATCH 2/4] x86: add phys addr validity check for /dev/mem mmap

2014-09-30 Thread Frantisek Hrbata
On Tue, Sep 30, 2014 at 07:27:51AM -0700, Dave Hansen wrote:
 On 09/30/2014 05:41 AM, Frantisek Hrbata wrote:
  Does it make sense to replace count with size so it's consistent with 
  the
  rest or do you prefer nr_bytes or as Dave proposed len_bytes?
 
 I don't care what it is as long as it has a unit in it.

Hi Dave/Thomas,

I sent v2 of this patch set, which uses the len_bytes. Again, I'm sorry I
forgot to fix this the first time.

Many thanks

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND PATCH 1/4] x86: add arch_pfn_possible helper

2014-09-29 Thread Frantisek Hrbata
Add helper to check maximum possible pfn on x86. Also make the current
phys_addr_valid helper using it internally.

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/mm/physaddr.h | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/physaddr.h b/arch/x86/mm/physaddr.h
index a3cd5a0..9df8e3a 100644
--- a/arch/x86/mm/physaddr.h
+++ b/arch/x86/mm/physaddr.h
@@ -1,10 +1,15 @@
 #include 
 
-static inline int phys_addr_valid(resource_size_t addr)
+static inline int arch_pfn_possible(unsigned long pfn)
 {
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
-   return !(addr >> boot_cpu_data.x86_phys_bits);
+   return !(pfn >> (boot_cpu_data.x86_phys_bits - PAGE_SHIFT));
 #else
return 1;
 #endif
 }
+
+static inline int phys_addr_valid(resource_size_t addr)
+{
+   return arch_pfn_possible(addr >> PAGE_SHIFT);
+}
-- 
1.9.3

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


[RESEND PATCH 2/4] x86: add phys addr validity check for /dev/mem mmap

2014-09-29 Thread Frantisek Hrbata
t main(int argc, char *argv[])
{
int fd;
long ps;
char *map;
char c;

ps = sysconf(_SC_PAGE_SIZE);
if (ps == -1)
die("cannot get page size");

fd = open("/dev/mem", O_RDONLY|O_LARGEFILE);
if (fd == -1)
die("cannot open /dev/mem");

map = (char *)syscall(SYS_mmap2, NULL, ps, PROT_READ, MAP_SHARED, fd, 
OFFSET);
if (map == MAP_FAILED)
die("cannot mmap");

c = map[0];

if (munmap(map, ps) == -1)
die("cannot munmap");

if (close(fd) == -1)
die("cannot close");

return 0;
}
-----8<--

V2: fix pfn check in valid_mmap_phys_addr_range, thanks to Dave Hansen

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 12 
 2 files changed, 16 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index b8237d8..55c59d5 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -243,6 +243,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t count);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 919b912..c8acb10 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include 
 #include 
 
+#include "physaddr.h"
+
 struct va_alignment __read_mostly va_align = {
.flags = -1,
 };
@@ -122,3 +124,13 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count <= __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
+{
+   return arch_pfn_possible(pfn + (count >> PAGE_SHIFT));
+}
-- 
1.9.3

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


[RESEND PATCH 3/4] x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr

2014-09-29 Thread Frantisek Hrbata
So far (xlate|unxlate)_dev_mem_ptr for read/write /dev/mem relies on a generic
high_memory check in valid_phys_addr_range(), which does not allow to access any
memory above high_memory whatsoever. By adding the high_memory check to
(xlate|unxlate)_dev_mem_ptr, it still will be possible to use __va safely for
kernel mapped memory and it will also allow read/write to access non-system RAM
above high_memory once the high_memory check is removed from
valid_phys_addr_range.

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/mm/ioremap.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da..1ae7323 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -320,8 +320,11 @@ void *xlate_dev_mem_ptr(unsigned long phys)
void *addr;
unsigned long start = phys & PAGE_MASK;
 
-   /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
-   if (page_is_ram(start >> PAGE_SHIFT))
+   /*
+* If page is RAM and is mapped by kernel, we can use __va.
+* Otherwise ioremap and unmap.
+*/
+   if (page_is_ram(start >> PAGE_SHIFT) && phys <= __pa(high_memory))
return __va(phys);
 
addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
@@ -333,7 +336,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
 
 void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 {
-   if (page_is_ram(phys >> PAGE_SHIFT))
+   if (page_is_ram(phys >> PAGE_SHIFT) && phys <= __pa(high_memory))
return;
 
iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
-- 
1.9.3

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


[RESEND PATCH 4/4] x86: remove high_memory check from valid_phys_addr_range

2014-09-29 Thread Frantisek Hrbata
There is no need to block read/write access to /dev/mem for phys. addr. above
high_memory for non-system RAM. The only limitation should be
boot_cpu_data.x86_phys_bits(max phys. addr. size).

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/mm/mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index c8acb10..7fa0242 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -127,7 +127,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
-   return addr + count <= __pa(high_memory);
+   return arch_pfn_possible((addr + count) >> PAGE_SHIFT);
 }
 
 int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
-- 
1.9.3

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


[RESEND PATCH 0/4] x86: /dev/mem fixes

2014-09-29 Thread Frantisek Hrbata
Hi all,

this is a combination of two patch sets I sent a while ago
1) Prevent possible PTE corruption with /dev/mem mmap
2) x86: allow read/write /dev/mem to access non-system RAM above high_memory

The original thread with both patch sets can be found here
   https://lkml.org/lkml/2014/8/14/229
   lkml: <1408025927-16826-1-git-send-email-fhrb...@redhat.com>

1) Prevent possible PTE corruption with /dev/mem mmap
x86: add arch_pfn_possible helper
x86: add phys addr validity check for /dev/mem mmap

Many thanks goes to Dave Hansen, who helped with the "final" check. Other than
that it did not get much attention, except H. Peter Anvin's complain that having
two checks for mmap and read/write for /dev/mem access is ridiculous. I for sure
do not object to this, but AFAICT it's not that simple to unify them and it's 
not
"directly" related to the PTE corruption. Please note that there are other
archs(ia64, arm) using these check. But I for sure can be missing something.

What this patch set does is using the existing interface to implement x86 
specific
check in the least invasive way.

Anyway I tried to remove the high_memory check with a follow-up patch set 2)

2) x86: allow read/write /dev/mem to access non-system RAM above high_memory
x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
x86: remove high_memory check from valid_phys_addr_range

This is an attempt to remove the high_memory limit for the read/write access to
/dev/mem. IMHO there is no reason for this limit on x86. It is presented in
the generic valid_phys_addr_range, which is used only by (read|write)_mem. IIUIC
it's main purpose is for the generic xlate_dev_mem_ptr, which is using only the
direct kernel mapping __va translation. Since the valid_phys_addr_range is
called as the first check in (read|write)_mem, it basically does not allow to
access anything above high_memory on x86.

The first patch adds high_memory check to x86's (xlate|unxlate)_dev_mem_ptr, so
the direct kernel mapping can be safely used for system RAM bellow high_memory.
This is IMHO the only valid reason to use high_memory check in (read|write)_mem.

The second patch removes the high_memory check from valid_phys_addr_range,
allowing read/write to access non-system RAM above high_memory. So far this
was possible only by using mmap.

I hope I haven't overlooked something.

Many thanks

Frantisek Hrbata (4):
  x86: add arch_pfn_possible helper
  x86: add phys addr validity check for /dev/mem mmap
  x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
  x86: remove high_memory check from valid_phys_addr_range

 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/ioremap.c |  9 ++---
 arch/x86/mm/mmap.c| 12 
 arch/x86/mm/physaddr.h|  9 +++--
 4 files changed, 29 insertions(+), 5 deletions(-)

-- 
1.9.3

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


[RESEND PATCH 0/4] x86: /dev/mem fixes

2014-09-29 Thread Frantisek Hrbata
Hi all,

this is a combination of two patch sets I sent a while ago
1) Prevent possible PTE corruption with /dev/mem mmap
2) x86: allow read/write /dev/mem to access non-system RAM above high_memory

The original thread with both patch sets can be found here
   https://lkml.org/lkml/2014/8/14/229
   lkml: 1408025927-16826-1-git-send-email-fhrb...@redhat.com

1) Prevent possible PTE corruption with /dev/mem mmap
x86: add arch_pfn_possible helper
x86: add phys addr validity check for /dev/mem mmap

Many thanks goes to Dave Hansen, who helped with the final check. Other than
that it did not get much attention, except H. Peter Anvin's complain that having
two checks for mmap and read/write for /dev/mem access is ridiculous. I for sure
do not object to this, but AFAICT it's not that simple to unify them and it's 
not
directly related to the PTE corruption. Please note that there are other
archs(ia64, arm) using these check. But I for sure can be missing something.

What this patch set does is using the existing interface to implement x86 
specific
check in the least invasive way.

Anyway I tried to remove the high_memory check with a follow-up patch set 2)

2) x86: allow read/write /dev/mem to access non-system RAM above high_memory
x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
x86: remove high_memory check from valid_phys_addr_range

This is an attempt to remove the high_memory limit for the read/write access to
/dev/mem. IMHO there is no reason for this limit on x86. It is presented in
the generic valid_phys_addr_range, which is used only by (read|write)_mem. IIUIC
it's main purpose is for the generic xlate_dev_mem_ptr, which is using only the
direct kernel mapping __va translation. Since the valid_phys_addr_range is
called as the first check in (read|write)_mem, it basically does not allow to
access anything above high_memory on x86.

The first patch adds high_memory check to x86's (xlate|unxlate)_dev_mem_ptr, so
the direct kernel mapping can be safely used for system RAM bellow high_memory.
This is IMHO the only valid reason to use high_memory check in (read|write)_mem.

The second patch removes the high_memory check from valid_phys_addr_range,
allowing read/write to access non-system RAM above high_memory. So far this
was possible only by using mmap.

I hope I haven't overlooked something.

Many thanks

Frantisek Hrbata (4):
  x86: add arch_pfn_possible helper
  x86: add phys addr validity check for /dev/mem mmap
  x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
  x86: remove high_memory check from valid_phys_addr_range

 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/ioremap.c |  9 ++---
 arch/x86/mm/mmap.c| 12 
 arch/x86/mm/physaddr.h|  9 +++--
 4 files changed, 29 insertions(+), 5 deletions(-)

-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND PATCH 4/4] x86: remove high_memory check from valid_phys_addr_range

2014-09-29 Thread Frantisek Hrbata
There is no need to block read/write access to /dev/mem for phys. addr. above
high_memory for non-system RAM. The only limitation should be
boot_cpu_data.x86_phys_bits(max phys. addr. size).

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/mm/mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index c8acb10..7fa0242 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -127,7 +127,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
-   return addr + count = __pa(high_memory);
+   return arch_pfn_possible((addr + count)  PAGE_SHIFT);
 }
 
 int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND PATCH 3/4] x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr

2014-09-29 Thread Frantisek Hrbata
So far (xlate|unxlate)_dev_mem_ptr for read/write /dev/mem relies on a generic
high_memory check in valid_phys_addr_range(), which does not allow to access any
memory above high_memory whatsoever. By adding the high_memory check to
(xlate|unxlate)_dev_mem_ptr, it still will be possible to use __va safely for
kernel mapped memory and it will also allow read/write to access non-system RAM
above high_memory once the high_memory check is removed from
valid_phys_addr_range.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/mm/ioremap.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da..1ae7323 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -320,8 +320,11 @@ void *xlate_dev_mem_ptr(unsigned long phys)
void *addr;
unsigned long start = phys  PAGE_MASK;
 
-   /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
-   if (page_is_ram(start  PAGE_SHIFT))
+   /*
+* If page is RAM and is mapped by kernel, we can use __va.
+* Otherwise ioremap and unmap.
+*/
+   if (page_is_ram(start  PAGE_SHIFT)  phys = __pa(high_memory))
return __va(phys);
 
addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
@@ -333,7 +336,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
 
 void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 {
-   if (page_is_ram(phys  PAGE_SHIFT))
+   if (page_is_ram(phys  PAGE_SHIFT)  phys = __pa(high_memory))
return;
 
iounmap((void __iomem *)((unsigned long)addr  PAGE_MASK));
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND PATCH 2/4] x86: add phys addr validity check for /dev/mem mmap

2014-09-29 Thread Frantisek Hrbata
 OFFSET 0x200

int main(int argc, char *argv[])
{
int fd;
long ps;
char *map;
char c;

ps = sysconf(_SC_PAGE_SIZE);
if (ps == -1)
die(cannot get page size);

fd = open(/dev/mem, O_RDONLY|O_LARGEFILE);
if (fd == -1)
die(cannot open /dev/mem);

map = (char *)syscall(SYS_mmap2, NULL, ps, PROT_READ, MAP_SHARED, fd, 
OFFSET);
if (map == MAP_FAILED)
die(cannot mmap);

c = map[0];

if (munmap(map, ps) == -1)
die(cannot munmap);

if (close(fd) == -1)
die(cannot close);

return 0;
}
-8--

V2: fix pfn check in valid_mmap_phys_addr_range, thanks to Dave Hansen

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 12 
 2 files changed, 16 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index b8237d8..55c59d5 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -243,6 +243,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t count);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 919b912..c8acb10 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include linux/sched.h
 #include asm/elf.h
 
+#include physaddr.h
+
 struct va_alignment __read_mostly va_align = {
.flags = -1,
 };
@@ -122,3 +124,13 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm-get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count = __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
+{
+   return arch_pfn_possible(pfn + (count  PAGE_SHIFT));
+}
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND PATCH 1/4] x86: add arch_pfn_possible helper

2014-09-29 Thread Frantisek Hrbata
Add helper to check maximum possible pfn on x86. Also make the current
phys_addr_valid helper using it internally.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/mm/physaddr.h | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/physaddr.h b/arch/x86/mm/physaddr.h
index a3cd5a0..9df8e3a 100644
--- a/arch/x86/mm/physaddr.h
+++ b/arch/x86/mm/physaddr.h
@@ -1,10 +1,15 @@
 #include asm/processor.h
 
-static inline int phys_addr_valid(resource_size_t addr)
+static inline int arch_pfn_possible(unsigned long pfn)
 {
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
-   return !(addr  boot_cpu_data.x86_phys_bits);
+   return !(pfn  (boot_cpu_data.x86_phys_bits - PAGE_SHIFT));
 #else
return 1;
 #endif
 }
+
+static inline int phys_addr_valid(resource_size_t addr)
+{
+   return arch_pfn_possible(addr  PAGE_SHIFT);
+}
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr

2014-08-20 Thread Frantisek Hrbata
So far (xlate|unxlate)_dev_mem_ptr for read/write /dev/mem relies on a generic
high_memory check in valid_phys_addr_range(), which does not allow to access any
memory above high_memory whatsoever. By adding the high_memory check to
(xlate|unxlate)_dev_mem_ptr, it still will be possible to use __va safely for
kernel mapped memory and it will also allow read/write to access non-system RAM
above high_memory once the high_memory check is removed from
valid_phys_addr_range.

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/mm/ioremap.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da..1ae7323 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -320,8 +320,11 @@ void *xlate_dev_mem_ptr(unsigned long phys)
void *addr;
unsigned long start = phys & PAGE_MASK;
 
-   /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
-   if (page_is_ram(start >> PAGE_SHIFT))
+   /*
+* If page is RAM and is mapped by kernel, we can use __va.
+* Otherwise ioremap and unmap.
+*/
+   if (page_is_ram(start >> PAGE_SHIFT) && phys <= __pa(high_memory))
return __va(phys);
 
addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
@@ -333,7 +336,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
 
 void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 {
-   if (page_is_ram(phys >> PAGE_SHIFT))
+   if (page_is_ram(phys >> PAGE_SHIFT) && phys <= __pa(high_memory))
return;
 
iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
-- 
1.9.3

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


[PATCH 0/2] x86: allow read/write /dev/mem to access non-system RAM above high_memory

2014-08-20 Thread Frantisek Hrbata
Hi,

this patch set depends on the following patches posted earlier.

[PATCH V2 1/2] x86: add arch_pfn_possible helper
   lkml: Message-Id: <1408103043-31015-2-git-send-email-fhrb...@redhat.com>
[PATCH V2 2/2] x86: add phys addr validity check for /dev/mem mmap
   lkml: Message-Id: <1408103043-31015-3-git-send-email-fhrb...@redhat.com>

This is an attempt to remove the high_memory limit for the read/write access to
/dev/mem. IMHO there is no reason for this limit on x86. It is presented in 
the generic valid_phys_addr_range, which is used only by (read|write)_mem. IIUIC
it's main purpose is for the generic xlate_dev_mem_ptr, which is using only the
direct kernel mapping __va translation. Since the valid_phys_addr_range is
called as the first check in (read|write)_mem, it basically does not allow to
access anything above high_memory on x86.

The first patch adds high_memory check to x86's (xlate|unxlate)_dev_mem_ptr, so
the direct kernel mapping can be safely used for system RAM bellow high_memory.
This is IMHO the only valid reason to use high_memory check in (read|write)_mem.

The second patch removes the high_memory check from valid_phys_addr_range,
allowing read/write to access non-system RAM above high_memory. So far this was
possible only by using mmap.

I hope I haven't overlooked something.

Many thanks

Frantisek Hrbata (2):
  x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
  x86: remove high_memory check from valid_phys_addr_range

 arch/x86/mm/ioremap.c | 9 ++---
 arch/x86/mm/mmap.c| 2 +-
 2 files changed, 7 insertions(+), 4 deletions(-)

-- 
1.9.3

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


[PATCH 2/2] x86: remove high_memory check from valid_phys_addr_range

2014-08-20 Thread Frantisek Hrbata
There is no need to block read/write access to /dev/mem for phys. addr. above
high_memory for non-system RAM. The only limitation should be
boot_cpu_data.x86_phys_bits(max phys. addr. size).

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/mm/mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 110473e..16f222d 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -127,7 +127,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
-   return addr + count <= __pa(high_memory);
+   return arch_pfn_possible((addr + count) >> PAGE_SHIFT);
 }
 
 int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
-- 
1.9.3

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


[PATCH 2/2] x86: remove high_memory check from valid_phys_addr_range

2014-08-20 Thread Frantisek Hrbata
There is no need to block read/write access to /dev/mem for phys. addr. above
high_memory for non-system RAM. The only limitation should be
boot_cpu_data.x86_phys_bits(max phys. addr. size).

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/mm/mmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 110473e..16f222d 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -127,7 +127,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
-   return addr + count = __pa(high_memory);
+   return arch_pfn_possible((addr + count)  PAGE_SHIFT);
 }
 
 int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr

2014-08-20 Thread Frantisek Hrbata
So far (xlate|unxlate)_dev_mem_ptr for read/write /dev/mem relies on a generic
high_memory check in valid_phys_addr_range(), which does not allow to access any
memory above high_memory whatsoever. By adding the high_memory check to
(xlate|unxlate)_dev_mem_ptr, it still will be possible to use __va safely for
kernel mapped memory and it will also allow read/write to access non-system RAM
above high_memory once the high_memory check is removed from
valid_phys_addr_range.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/mm/ioremap.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da..1ae7323 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -320,8 +320,11 @@ void *xlate_dev_mem_ptr(unsigned long phys)
void *addr;
unsigned long start = phys  PAGE_MASK;
 
-   /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
-   if (page_is_ram(start  PAGE_SHIFT))
+   /*
+* If page is RAM and is mapped by kernel, we can use __va.
+* Otherwise ioremap and unmap.
+*/
+   if (page_is_ram(start  PAGE_SHIFT)  phys = __pa(high_memory))
return __va(phys);
 
addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
@@ -333,7 +336,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
 
 void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 {
-   if (page_is_ram(phys  PAGE_SHIFT))
+   if (page_is_ram(phys  PAGE_SHIFT)  phys = __pa(high_memory))
return;
 
iounmap((void __iomem *)((unsigned long)addr  PAGE_MASK));
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/2] x86: allow read/write /dev/mem to access non-system RAM above high_memory

2014-08-20 Thread Frantisek Hrbata
Hi,

this patch set depends on the following patches posted earlier.

[PATCH V2 1/2] x86: add arch_pfn_possible helper
   lkml: Message-Id: 1408103043-31015-2-git-send-email-fhrb...@redhat.com
[PATCH V2 2/2] x86: add phys addr validity check for /dev/mem mmap
   lkml: Message-Id: 1408103043-31015-3-git-send-email-fhrb...@redhat.com

This is an attempt to remove the high_memory limit for the read/write access to
/dev/mem. IMHO there is no reason for this limit on x86. It is presented in 
the generic valid_phys_addr_range, which is used only by (read|write)_mem. IIUIC
it's main purpose is for the generic xlate_dev_mem_ptr, which is using only the
direct kernel mapping __va translation. Since the valid_phys_addr_range is
called as the first check in (read|write)_mem, it basically does not allow to
access anything above high_memory on x86.

The first patch adds high_memory check to x86's (xlate|unxlate)_dev_mem_ptr, so
the direct kernel mapping can be safely used for system RAM bellow high_memory.
This is IMHO the only valid reason to use high_memory check in (read|write)_mem.

The second patch removes the high_memory check from valid_phys_addr_range,
allowing read/write to access non-system RAM above high_memory. So far this was
possible only by using mmap.

I hope I haven't overlooked something.

Many thanks

Frantisek Hrbata (2):
  x86: add high_memory check to (xlate|unxlate)_dev_mem_ptr
  x86: remove high_memory check from valid_phys_addr_range

 arch/x86/mm/ioremap.c | 9 ++---
 arch/x86/mm/mmap.c| 2 +-
 2 files changed, 7 insertions(+), 4 deletions(-)

-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 2/2] x86: add phys addr validity check for /dev/mem mmap

2014-08-18 Thread Frantisek Hrbata
On Fri, Aug 15, 2014 at 11:10:25AM -0700, Dave Hansen wrote:
> On 08/15/2014 04:44 AM, Frantisek Hrbata wrote:
> > +int valid_phys_addr_range(phys_addr_t addr, size_t count)
> > +{
> > +   return addr + count <= __pa(high_memory);
> > +}
> > +
> > +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
> > +{
> > +   return arch_pfn_possible(pfn + (count >> PAGE_SHIFT));
> > +}
> 
> It definitely fixes the issue as you described it.

Hi Dave,

many thanks for your time and help with this!

> 
> It's a bit unfortunate that the highmem check isn't tied in to the
> _existing_ /dev/mem limitations in some way, but it's not a deal breaker
> for me.

Agreed, I will do some more testing with the "patch" I proposed earlier in our
discussion. Meaning the one moving the high_memory check out of the
valid_phys_addr_range() to the xlate_dev_mem_ptr() for x86. IMHO this should
work fine and it should remove the high_memory limitation. But I for sure can be
missing something. If the testing goes well I will post the patch.

> 
> The only other thing is to make sure this doesn't add some limitation to
> 64-bit where we can't map things above the end of memory (end of memory
> == high_memory on 64-bit).  As long as you've done this, I can't see a
> downside.

Yes, from what I have tested, this patch should not introduce any new
limitation, except fixing the PTE problem. Also please note
that this kind of check is already done in ioremap by calling the
phys_addr_valid(). Again, I hope I haven't overlooked something.

Peter and others: Could you please consider including this fix? Of course only
if you do not have any other objections or problems with it.

Many thanks!

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 2/2] x86: add phys addr validity check for /dev/mem mmap

2014-08-18 Thread Frantisek Hrbata
On Fri, Aug 15, 2014 at 11:10:25AM -0700, Dave Hansen wrote:
 On 08/15/2014 04:44 AM, Frantisek Hrbata wrote:
  +int valid_phys_addr_range(phys_addr_t addr, size_t count)
  +{
  +   return addr + count = __pa(high_memory);
  +}
  +
  +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
  +{
  +   return arch_pfn_possible(pfn + (count  PAGE_SHIFT));
  +}
 
 It definitely fixes the issue as you described it.

Hi Dave,

many thanks for your time and help with this!

 
 It's a bit unfortunate that the highmem check isn't tied in to the
 _existing_ /dev/mem limitations in some way, but it's not a deal breaker
 for me.

Agreed, I will do some more testing with the patch I proposed earlier in our
discussion. Meaning the one moving the high_memory check out of the
valid_phys_addr_range() to the xlate_dev_mem_ptr() for x86. IMHO this should
work fine and it should remove the high_memory limitation. But I for sure can be
missing something. If the testing goes well I will post the patch.

 
 The only other thing is to make sure this doesn't add some limitation to
 64-bit where we can't map things above the end of memory (end of memory
 == high_memory on 64-bit).  As long as you've done this, I can't see a
 downside.

Yes, from what I have tested, this patch should not introduce any new
limitation, except fixing the PTE problem. Also please note
that this kind of check is already done in ioremap by calling the
phys_addr_valid(). Again, I hope I haven't overlooked something.

Peter and others: Could you please consider including this fix? Of course only
if you do not have any other objections or problems with it.

Many thanks!

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 2/2] x86: add phys addr validity check for /dev/mem mmap

2014-08-15 Thread Frantisek Hrbata
t main(int argc, char *argv[])
{
int fd;
long ps;
char *map;
char c;

ps = sysconf(_SC_PAGE_SIZE);
if (ps == -1)
die("cannot get page size");

fd = open("/dev/mem", O_RDONLY|O_LARGEFILE);
if (fd == -1)
die("cannot open /dev/mem");

map = (char *)syscall(SYS_mmap2, NULL, ps, PROT_READ, MAP_SHARED, fd, 
OFFSET);
if (map == MAP_FAILED)
die("cannot mmap");

c = map[0];

if (munmap(map, ps) == -1)
die("cannot munmap");

if (close(fd) == -1)
die("cannot close");

return 0;
}
-----8<--

V2: fix pfn check in valid_mmap_phys_addr_range, thanks to Dave Hansen

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 12 
 2 files changed, 16 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index b8237d8..55c59d5 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -243,6 +243,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t count);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 25e7e13..110473e 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include 
 #include 
 
+#include "physaddr.h"
+
 struct __read_mostly va_alignment va_align = {
.flags = -1,
 };
@@ -122,3 +124,13 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count <= __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
+{
+   return arch_pfn_possible(pfn + (count >> PAGE_SHIFT));
+}
-- 
1.9.3

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


[PATCH V2 0/2] Prevent possible PTE corruption with /dev/mem mmap

2014-08-15 Thread Frantisek Hrbata
Thanks to Dave Hansen for pointing out problems related to the pfn check in the
first version. I tried to fix it by adding a new arch_pfn_possible helper to
arch/x86/mm/physaddr.h. Please note that I'm not quite sure about the name and
the location(physaddr.h). Maybe we can keep the check directly in the
valid_mmap_phys_addr_range. I will leave this to a discussion and fix it if
required.

Question: Do we need the CONFIG_PHYS_ADDR_T_64BIT ifdef? The
boot_cpu_data.x86_phys_bits is set for all x86. So at this point it seems to me
more like an "optimization" for x86_32 or something kept from historic
reasons. I'm just curious and I of course may be missing something.

Many thanks

Frantisek Hrbata (2):
  x86: add arch_pfn_possible helper
  x86: add phys addr validity check for /dev/mem mmap

 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 12 
 arch/x86/mm/physaddr.h|  9 +++--
 3 files changed, 23 insertions(+), 2 deletions(-)

-- 
1.9.3

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


[PATCH V2 1/2] x86: add arch_pfn_possible helper

2014-08-15 Thread Frantisek Hrbata
Add helper to check maximum possible pfn on x86. Also make the current
phys_addr_valid helper using it internally.

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/mm/physaddr.h | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/physaddr.h b/arch/x86/mm/physaddr.h
index a3cd5a0..9df8e3a 100644
--- a/arch/x86/mm/physaddr.h
+++ b/arch/x86/mm/physaddr.h
@@ -1,10 +1,15 @@
 #include 
 
-static inline int phys_addr_valid(resource_size_t addr)
+static inline int arch_pfn_possible(unsigned long pfn)
 {
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
-   return !(addr >> boot_cpu_data.x86_phys_bits);
+   return !(pfn >> (boot_cpu_data.x86_phys_bits - PAGE_SHIFT));
 #else
return 1;
 #endif
 }
+
+static inline int phys_addr_valid(resource_size_t addr)
+{
+   return arch_pfn_possible(addr >> PAGE_SHIFT);
+}
-- 
1.9.3

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


Re: [PATCH 1/1] x86: add phys addr validity check for /dev/mem mmap

2014-08-15 Thread Frantisek Hrbata
self-nack

As pointed by Dave Hansen, the check is just wrong. I will post V2.

Many thanks Dave!

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] x86: add phys addr validity check for /dev/mem mmap

2014-08-15 Thread Frantisek Hrbata
self-nack

As pointed by Dave Hansen, the check is just wrong. I will post V2.

Many thanks Dave!

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 0/2] Prevent possible PTE corruption with /dev/mem mmap

2014-08-15 Thread Frantisek Hrbata
Thanks to Dave Hansen for pointing out problems related to the pfn check in the
first version. I tried to fix it by adding a new arch_pfn_possible helper to
arch/x86/mm/physaddr.h. Please note that I'm not quite sure about the name and
the location(physaddr.h). Maybe we can keep the check directly in the
valid_mmap_phys_addr_range. I will leave this to a discussion and fix it if
required.

Question: Do we need the CONFIG_PHYS_ADDR_T_64BIT ifdef? The
boot_cpu_data.x86_phys_bits is set for all x86. So at this point it seems to me
more like an optimization for x86_32 or something kept from historic
reasons. I'm just curious and I of course may be missing something.

Many thanks

Frantisek Hrbata (2):
  x86: add arch_pfn_possible helper
  x86: add phys addr validity check for /dev/mem mmap

 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 12 
 arch/x86/mm/physaddr.h|  9 +++--
 3 files changed, 23 insertions(+), 2 deletions(-)

-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 1/2] x86: add arch_pfn_possible helper

2014-08-15 Thread Frantisek Hrbata
Add helper to check maximum possible pfn on x86. Also make the current
phys_addr_valid helper using it internally.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/mm/physaddr.h | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/physaddr.h b/arch/x86/mm/physaddr.h
index a3cd5a0..9df8e3a 100644
--- a/arch/x86/mm/physaddr.h
+++ b/arch/x86/mm/physaddr.h
@@ -1,10 +1,15 @@
 #include asm/processor.h
 
-static inline int phys_addr_valid(resource_size_t addr)
+static inline int arch_pfn_possible(unsigned long pfn)
 {
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
-   return !(addr  boot_cpu_data.x86_phys_bits);
+   return !(pfn  (boot_cpu_data.x86_phys_bits - PAGE_SHIFT));
 #else
return 1;
 #endif
 }
+
+static inline int phys_addr_valid(resource_size_t addr)
+{
+   return arch_pfn_possible(addr  PAGE_SHIFT);
+}
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 2/2] x86: add phys addr validity check for /dev/mem mmap

2014-08-15 Thread Frantisek Hrbata
 OFFSET 0x200

int main(int argc, char *argv[])
{
int fd;
long ps;
char *map;
char c;

ps = sysconf(_SC_PAGE_SIZE);
if (ps == -1)
die(cannot get page size);

fd = open(/dev/mem, O_RDONLY|O_LARGEFILE);
if (fd == -1)
die(cannot open /dev/mem);

map = (char *)syscall(SYS_mmap2, NULL, ps, PROT_READ, MAP_SHARED, fd, 
OFFSET);
if (map == MAP_FAILED)
die(cannot mmap);

c = map[0];

if (munmap(map, ps) == -1)
die(cannot munmap);

if (close(fd) == -1)
die(cannot close);

return 0;
}
-8--

V2: fix pfn check in valid_mmap_phys_addr_range, thanks to Dave Hansen

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 12 
 2 files changed, 16 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index b8237d8..55c59d5 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -243,6 +243,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t count);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 25e7e13..110473e 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include linux/sched.h
 #include asm/elf.h
 
+#include physaddr.h
+
 struct __read_mostly va_alignment va_align = {
.flags = -1,
 };
@@ -122,3 +124,13 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm-get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count = __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
+{
+   return arch_pfn_possible(pfn + (count  PAGE_SHIFT));
+}
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] x86: add phys addr validity check for /dev/mem mmap

2014-08-14 Thread Frantisek Hrbata
On Thu, Aug 14, 2014 at 10:20:53AM -0700, H. Peter Anvin wrote:
> On 08/14/2014 09:36 AM, Dave Hansen wrote:
> > Thanks for dredging this back up!
> > 
> > On 08/14/2014 07:18 AM, Frantisek Hrbata wrote:
> >> +int valid_phys_addr_range(phys_addr_t addr, size_t count)
> >> +{
> >> +  return addr + count <= __pa(high_memory);
> >> +}
> > 
> > Is this correct on 32-bit?  It would limit /dev/mem to memory below 896MB.
> > 
> 
> Last I checked, /dev/mem was already broken for highmem... which is
> actually a problem.  I would prefer to see it fixed.
> 
>   -hpa
> 

Hi Peter,

thank you for jumping in again. I'm not going to pretent I fully understand this
code, as proven by Dave :), but wouldn't it help just to move the high_memory
check directly to the xlate_dev_mem_ptr. Meaning no high_memory check in
valid_phys_addr_range for x86. I sent more info in my reply to Dave's mail.

Again many thanks.


-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] x86: add phys addr validity check for /dev/mem mmap

2014-08-14 Thread Frantisek Hrbata
On Thu, Aug 14, 2014 at 09:36:03AM -0700, Dave Hansen wrote:
> Thanks for dredging this back up!
> 
> On 08/14/2014 07:18 AM, Frantisek Hrbata wrote:
> > +int valid_phys_addr_range(phys_addr_t addr, size_t count)
> > +{
> > +   return addr + count <= __pa(high_memory);
> > +}
> 
> Is this correct on 32-bit?  It would limit /dev/mem to memory below 896MB.

Unfortunatelly this is how it works right now. Please note that at this moment
x86 is using the default checks from drivers/char/mem.c. The
valid_phys_addr_range is used just for read/write. Meaning yes, you cannot 
access
/dev/mem above high_memory via read/write, which is 896MB on x86_32.

I simply copied this generic check. There is no change compared to the current
behaviour.

BTW I think this can be simply fixed by moving the high_memory check directly to
the xlate_dev_mem_ptr function.

Something like the following. Please note this is not even compile tested.

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da..7ebc241 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -321,7 +321,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
unsigned long start = phys & PAGE_MASK;
 
/* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
-   if (page_is_ram(start >> PAGE_SHIFT))
+   if (page_is_ram(start >> PAGE_SHIFT) && phys <= __pa(high_memory))
return __va(phys);
 
addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
@@ -333,7 +333,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
 
 void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 {
-   if (page_is_ram(phys >> PAGE_SHIFT))
+   if (page_is_ram(phys >> PAGE_SHIFT) && phys <= __pa(high_memory))
return;
 
iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));


IIUIC the whole high_memory check is here only because of the kernel identity
mapping and as a generic check because of the generic xlate_dev_mem_ptr.

include/asm-generic/io.h: #define xlate_dev_mem_ptr(p)__va(p)

> 
> > +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
> > +{
> 
> Nit: please add units to things like "count".  len_bytes would be nice
> for this kind of thing, especially since it's passed *with* a pfn it
> would be easy to think it is a count in pages.

Sure I have no problem with this. But please note that I just took the already
used/presented interface from drivers/char/mem.c.

> 
> > +   /* pgoff + count overflow is checked in do_mmap_pgoff */
> > +   pfn += count >> PAGE_SHIFT;
> > +
> > +   if (pfn >> BITS_PER_LONG - PAGE_SHIFT)
> > +   return -EOVERFLOW;
> 
> Is this -EOVERFLOW correct?  It is called like this:
> 
> > static int mmap_mem(struct file *file, struct vm_area_struct *vma)
> > {
> > if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
> > return -EINVAL;
> 
> So I think we need to return true/false:0/1.  -EOVERFLOW would be true,
> and that if() would pass.

Facepalm, sure this is completely wrong. We of course need to return zero. I
thought it would be more descriptive to use -EOVERFLOW, even though we get
-EINVAL in the end. I will fix this. Many thanks for pointing this out.

> 
> > +   return phys_addr_valid(pfn << PAGE_SHIFT);
> > +}
> 
> Maybe I'm dumb, but it took me a minute to figure out what you were
> trying to do with the: "(pfn >> BITS_PER_LONG - PAGE_SHIFT)".  In any
> case, I think it is wrong on 32-bit.
> 
> On 32-bit, BITS_PER_LONG=32, and PAGE_SIZE=12, and a paddr=0x1
> or pfn=0x10 (4GB) is perfectly valid with PAE enabled.  But, this
> code pfn>>(32-12) would result in 0x1 and return -EOVERFLOW.

Right, I did not realized this.

> 
> I think something like this would be easier to read and actually work on
> 32-bit:
> 
> static inline int arch_pfn_possible(unsigned long pfn)
> {
>   unsigned long max_arch_pfn = 1UL << (boot_cpu_data.x86_phys_bits -
> PAGE_SHIFT);
>   return pfn < max_arch_pfn;
> }

Actually I wanted to use exactly this instead of calling phys_addr_valid, 
because
we can avoid the whole overflow check, but it seemed natural to use what is
already available. But you are right for sure. This needs to be fixed also.

Dave, many thanks for your feedback, it's really appreciated!

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/1] Prevent possible PTE corruption with /dev/mem mmap

2014-08-14 Thread Frantisek Hrbata
Hi all,

after some time this issue popped up again. Please note that the patch was send
to lkml two times.

https://lkml.org/lkml/2013/4/2/297
  lkml: <1364905733-23937-1-git-send-email-fhrb...@redhat.com>
https://lkml.org/lkml/2013/10/2/359
  lkml: <20131002160514.GA25471@localhost.localdomain>

It did not get much attention, except H. Peter Anvin's complain that having two
checks for mmap and read/write for /dev/mem access is ridiculous. I for sure do
not object to this, but AFAICT it's not that simple to unify them and it's not
"directly" related to the PTE corruption. Please note that there are other
archs(ia64, arm) using these check. But I for sure can be missing something.

What the patch does is using the existing interface to implement x86 specific
check in the least invasive way.

Peter: I by no means want to be pushy. Just that after I looked into this a
little bit more, I don't see a better and more straightforward way how to fix
this. I will be grateful for any suggestions and help. If we want/need to fix
this in a different way, I can for sure try, but I will need at least some
guidance.

So I'm posting this once more with a hope it will get more attention or at least
to start the discussion how/if this should be fixed.

The patch is the same except I added a check for phys addr overflow before
calling phys_addr_valid. Maybe this check should be in do_mmap_pgoff.

Many thanks

Frantisek Hrbata (1):
  x86: add phys addr validity check for /dev/mem mmap

 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 18 ++
 2 files changed, 22 insertions(+)

-- 
1.9.3

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


[PATCH 1/1] x86: add phys addr validity check for /dev/mem mmap

2014-08-14 Thread Frantisek Hrbata
t main(int argc, char *argv[])
{
int fd;
long ps;
char *map;
char c;

ps = sysconf(_SC_PAGE_SIZE);
if (ps == -1)
die("cannot get page size");

fd = open("/dev/mem", O_RDONLY|O_LARGEFILE);
if (fd == -1)
die("cannot open /dev/mem");

map = (char *)syscall(SYS_mmap2, NULL, ps, PROT_READ, MAP_SHARED, fd, 
OFFSET);
if (map == MAP_FAILED)
die("cannot mmap");

c = map[0];

if (munmap(map, ps) == -1)
die("cannot munmap");

if (close(fd) == -1)
    die("cannot close");

return 0;
}
-8<--

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 18 ++
 2 files changed, 22 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index b8237d8..55c59d5 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -243,6 +243,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t count);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 25e7e13..b5be2ad 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include 
 #include 
 
+#include "physaddr.h"
+
 struct __read_mostly va_alignment va_align = {
.flags = -1,
 };
@@ -122,3 +124,19 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count <= __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
+{
+   /* pgoff + count overflow is checked in do_mmap_pgoff */
+   pfn += count >> PAGE_SHIFT;
+
+   if (pfn >> BITS_PER_LONG - PAGE_SHIFT)
+   return -EOVERFLOW;
+
+   return phys_addr_valid(pfn << PAGE_SHIFT);
+}
-- 
1.9.3

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


[PATCH 1/1] x86: add phys addr validity check for /dev/mem mmap

2014-08-14 Thread Frantisek Hrbata
 OFFSET 0x200

int main(int argc, char *argv[])
{
int fd;
long ps;
char *map;
char c;

ps = sysconf(_SC_PAGE_SIZE);
if (ps == -1)
die(cannot get page size);

fd = open(/dev/mem, O_RDONLY|O_LARGEFILE);
if (fd == -1)
die(cannot open /dev/mem);

map = (char *)syscall(SYS_mmap2, NULL, ps, PROT_READ, MAP_SHARED, fd, 
OFFSET);
if (map == MAP_FAILED)
die(cannot mmap);

c = map[0];

if (munmap(map, ps) == -1)
die(cannot munmap);

if (close(fd) == -1)
die(cannot close);

return 0;
}
-8--

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 18 ++
 2 files changed, 22 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index b8237d8..55c59d5 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -243,6 +243,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t count);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 25e7e13..b5be2ad 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include linux/sched.h
 #include asm/elf.h
 
+#include physaddr.h
+
 struct __read_mostly va_alignment va_align = {
.flags = -1,
 };
@@ -122,3 +124,19 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm-get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count = __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
+{
+   /* pgoff + count overflow is checked in do_mmap_pgoff */
+   pfn += count  PAGE_SHIFT;
+
+   if (pfn  BITS_PER_LONG - PAGE_SHIFT)
+   return -EOVERFLOW;
+
+   return phys_addr_valid(pfn  PAGE_SHIFT);
+}
-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/1] Prevent possible PTE corruption with /dev/mem mmap

2014-08-14 Thread Frantisek Hrbata
Hi all,

after some time this issue popped up again. Please note that the patch was send
to lkml two times.

https://lkml.org/lkml/2013/4/2/297
  lkml: 1364905733-23937-1-git-send-email-fhrb...@redhat.com
https://lkml.org/lkml/2013/10/2/359
  lkml: 20131002160514.GA25471@localhost.localdomain

It did not get much attention, except H. Peter Anvin's complain that having two
checks for mmap and read/write for /dev/mem access is ridiculous. I for sure do
not object to this, but AFAICT it's not that simple to unify them and it's not
directly related to the PTE corruption. Please note that there are other
archs(ia64, arm) using these check. But I for sure can be missing something.

What the patch does is using the existing interface to implement x86 specific
check in the least invasive way.

Peter: I by no means want to be pushy. Just that after I looked into this a
little bit more, I don't see a better and more straightforward way how to fix
this. I will be grateful for any suggestions and help. If we want/need to fix
this in a different way, I can for sure try, but I will need at least some
guidance.

So I'm posting this once more with a hope it will get more attention or at least
to start the discussion how/if this should be fixed.

The patch is the same except I added a check for phys addr overflow before
calling phys_addr_valid. Maybe this check should be in do_mmap_pgoff.

Many thanks

Frantisek Hrbata (1):
  x86: add phys addr validity check for /dev/mem mmap

 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 18 ++
 2 files changed, 22 insertions(+)

-- 
1.9.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] x86: add phys addr validity check for /dev/mem mmap

2014-08-14 Thread Frantisek Hrbata
On Thu, Aug 14, 2014 at 09:36:03AM -0700, Dave Hansen wrote:
 Thanks for dredging this back up!
 
 On 08/14/2014 07:18 AM, Frantisek Hrbata wrote:
  +int valid_phys_addr_range(phys_addr_t addr, size_t count)
  +{
  +   return addr + count = __pa(high_memory);
  +}
 
 Is this correct on 32-bit?  It would limit /dev/mem to memory below 896MB.

Unfortunatelly this is how it works right now. Please note that at this moment
x86 is using the default checks from drivers/char/mem.c. The
valid_phys_addr_range is used just for read/write. Meaning yes, you cannot 
access
/dev/mem above high_memory via read/write, which is 896MB on x86_32.

I simply copied this generic check. There is no change compared to the current
behaviour.

BTW I think this can be simply fixed by moving the high_memory check directly to
the xlate_dev_mem_ptr function.

Something like the following. Please note this is not even compile tested.

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da..7ebc241 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -321,7 +321,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
unsigned long start = phys  PAGE_MASK;
 
/* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
-   if (page_is_ram(start  PAGE_SHIFT))
+   if (page_is_ram(start  PAGE_SHIFT)  phys = __pa(high_memory))
return __va(phys);
 
addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
@@ -333,7 +333,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
 
 void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 {
-   if (page_is_ram(phys  PAGE_SHIFT))
+   if (page_is_ram(phys  PAGE_SHIFT)  phys = __pa(high_memory))
return;
 
iounmap((void __iomem *)((unsigned long)addr  PAGE_MASK));


IIUIC the whole high_memory check is here only because of the kernel identity
mapping and as a generic check because of the generic xlate_dev_mem_ptr.

include/asm-generic/io.h: #define xlate_dev_mem_ptr(p)__va(p)

 
  +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
  +{
 
 Nit: please add units to things like count.  len_bytes would be nice
 for this kind of thing, especially since it's passed *with* a pfn it
 would be easy to think it is a count in pages.

Sure I have no problem with this. But please note that I just took the already
used/presented interface from drivers/char/mem.c.

 
  +   /* pgoff + count overflow is checked in do_mmap_pgoff */
  +   pfn += count  PAGE_SHIFT;
  +
  +   if (pfn  BITS_PER_LONG - PAGE_SHIFT)
  +   return -EOVERFLOW;
 
 Is this -EOVERFLOW correct?  It is called like this:
 
  static int mmap_mem(struct file *file, struct vm_area_struct *vma)
  {
  if (!valid_mmap_phys_addr_range(vma-vm_pgoff, size))
  return -EINVAL;
 
 So I think we need to return true/false:0/1.  -EOVERFLOW would be true,
 and that if() would pass.

Facepalm, sure this is completely wrong. We of course need to return zero. I
thought it would be more descriptive to use -EOVERFLOW, even though we get
-EINVAL in the end. I will fix this. Many thanks for pointing this out.

 
  +   return phys_addr_valid(pfn  PAGE_SHIFT);
  +}
 
 Maybe I'm dumb, but it took me a minute to figure out what you were
 trying to do with the: (pfn  BITS_PER_LONG - PAGE_SHIFT).  In any
 case, I think it is wrong on 32-bit.
 
 On 32-bit, BITS_PER_LONG=32, and PAGE_SIZE=12, and a paddr=0x1
 or pfn=0x10 (4GB) is perfectly valid with PAE enabled.  But, this
 code pfn(32-12) would result in 0x1 and return -EOVERFLOW.

Right, I did not realized this.

 
 I think something like this would be easier to read and actually work on
 32-bit:
 
 static inline int arch_pfn_possible(unsigned long pfn)
 {
   unsigned long max_arch_pfn = 1UL  (boot_cpu_data.x86_phys_bits -
 PAGE_SHIFT);
   return pfn  max_arch_pfn;
 }

Actually I wanted to use exactly this instead of calling phys_addr_valid, 
because
we can avoid the whole overflow check, but it seemed natural to use what is
already available. But you are right for sure. This needs to be fixed also.

Dave, many thanks for your feedback, it's really appreciated!

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] x86: add phys addr validity check for /dev/mem mmap

2014-08-14 Thread Frantisek Hrbata
On Thu, Aug 14, 2014 at 10:20:53AM -0700, H. Peter Anvin wrote:
 On 08/14/2014 09:36 AM, Dave Hansen wrote:
  Thanks for dredging this back up!
  
  On 08/14/2014 07:18 AM, Frantisek Hrbata wrote:
  +int valid_phys_addr_range(phys_addr_t addr, size_t count)
  +{
  +  return addr + count = __pa(high_memory);
  +}
  
  Is this correct on 32-bit?  It would limit /dev/mem to memory below 896MB.
  
 
 Last I checked, /dev/mem was already broken for highmem... which is
 actually a problem.  I would prefer to see it fixed.
 
   -hpa
 

Hi Peter,

thank you for jumping in again. I'm not going to pretent I fully understand this
code, as proven by Dave :), but wouldn't it help just to move the high_memory
check directly to the xlate_dev_mem_ptr. Meaning no high_memory check in
valid_phys_addr_range for x86. I sent more info in my reply to Dave's mail.

Again many thanks.


-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RESEND PATCH] x86: add phys addr validity check for /dev/mem mmap

2013-10-02 Thread Frantisek Hrbata
On Wed, Oct 02, 2013 at 11:36:09AM -0700, H. Peter Anvin wrote:
> On 10/02/2013 11:31 AM, Frantisek Hrbata wrote:
> > On Wed, Oct 02, 2013 at 10:46:35AM -0700, H. Peter Anvin wrote:
> >> On 10/02/2013 09:05 AM, Frantisek Hrbata wrote:
> >>> +
> >>> +int valid_phys_addr_range(phys_addr_t addr, size_t count)
> >>> +{
> >>> + return addr + count <= __pa(high_memory);
> >>> +}
> >>> +
> >>> +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
> >>> +{
> >>> + resource_size_t addr = (pfn << PAGE_SHIFT) + count;
> >>> + return phys_addr_valid(addr);
> >>> +}
> >>>
> >>
> >> The latter has overflow problems.
> > 
> > Could you please specify what overflow problems do you mean?
> 
> Consider if pfn + count overflows and wraps around, or if (pfn <<
> PAGE_SHIFT) pushes bits out to the left.

Ok, maybe I'm missing something, but isn't this handled in
do_mmap_pgoff?

/* offset overflow? */
if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
return -EOVERFLOW;

Anyway I can take a closer look and if this can really happen I can fix it.
   
> 
> >> The former I realize matches the current /dev/mem, but it is still just
> >> plain wrong in multiple ways.
> > 
> > I guess that you are talking about /dev/mem implementation generelly, 
> > because
> > this patch is exactly the same as the first one. All I'm trying to do here 
> > is to
> > fix this simple problem, which was reported by a customer, using IMHO the 
> > least
> > invasive way. Anyway is there any description what is wrong with /dev/mem
> > implementation? Maybe I can try to take a look.
> > 
> 
> The bottom line is that read/write to /dev/mem should be able to access
> the same memory that we can mmap().  Having two different tests is
> ridiculous.

Ok, I can try to look into this. I just want to point out that some other archs
like arm are doing it the same way. I simply replaced the generic check 
functions
in drivers/char/mem.c with x86 specific ones.

Thanks

> 
>   -hpa
> 
> 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RESEND PATCH] x86: add phys addr validity check for /dev/mem mmap

2013-10-02 Thread Frantisek Hrbata
On Wed, Oct 02, 2013 at 10:46:35AM -0700, H. Peter Anvin wrote:
> On 10/02/2013 09:05 AM, Frantisek Hrbata wrote:
> > +
> > +int valid_phys_addr_range(phys_addr_t addr, size_t count)
> > +{
> > +   return addr + count <= __pa(high_memory);
> > +}
> > +
> > +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
> > +{
> > +   resource_size_t addr = (pfn << PAGE_SHIFT) + count;
> > +   return phys_addr_valid(addr);
> > +}
> > 
> 
> The latter has overflow problems.

Could you please specify what overflow problems do you mean?

> 
> The former I realize matches the current /dev/mem, but it is still just
> plain wrong in multiple ways.

I guess that you are talking about /dev/mem implementation generelly, because
this patch is exactly the same as the first one. All I'm trying to do here is to
fix this simple problem, which was reported by a customer, using IMHO the least
invasive way. Anyway is there any description what is wrong with /dev/mem
implementation? Maybe I can try to take a look.

Many thanks

> 
>   -hpa
> 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND PATCH] x86: add phys addr validity check for /dev/mem mmap

2013-10-02 Thread Frantisek Hrbata
07fff2d34da50 R08: 
0003 R09: 0008000a
Oct  2 11:24:02 amd-pence-01 kernel: R10: 0001 R11: 
0202 R12: 00400590
Oct  2 11:24:02 amd-pence-01 kernel: R13: 7fff2d34db30 R14: 
 R15: 
Oct  2 11:24:02 amd-pence-01 kernel: FS:  7f911ffce700() 
GS:880136cc() knlGS:
Oct  2 11:24:02 amd-pence-01 kernel: CS:  0010 DS:  ES:  CR0: 
8005003b
Oct  2 11:24:02 amd-pence-01 kernel: CR2: 7f911ffc8000 CR3: 
c39ec000 CR4: 000407e0
Oct  2 11:24:02 amd-pence-01 kernel:
Oct  2 11:24:02 amd-pence-01 kernel: RIP  [<00400776>] 0x400775
Oct  2 11:24:02 amd-pence-01 kernel: RSP <7fff2d34da10>
Oct  2 11:24:02 amd-pence-01 kernel: ---[ end trace 8a123cd70049eebc ]---
---------8<--

Please note the PTE value 8008000a0225.

Signed-off-by: Frantisek Hrbata 
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 13 +
 2 files changed, 17 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 34f69cb..af9f363 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -242,6 +242,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t count);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 25e7e13..ef02a93 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include 
 #include 
 
+#include "physaddr.h"
+
 struct __read_mostly va_alignment va_align = {
.flags = -1,
 };
@@ -122,3 +124,14 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count <= __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
+{
+   resource_size_t addr = (pfn << PAGE_SHIFT) + count;
+   return phys_addr_valid(addr);
+}
-- 
1.8.3.1


-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND PATCH] x86: add phys addr validity check for /dev/mem mmap

2013-10-02 Thread Frantisek Hrbata
:02 amd-pence-01 kernel: R10: 0001 R11: 
0202 R12: 00400590
Oct  2 11:24:02 amd-pence-01 kernel: R13: 7fff2d34db30 R14: 
 R15: 
Oct  2 11:24:02 amd-pence-01 kernel: FS:  7f911ffce700() 
GS:880136cc() knlGS:
Oct  2 11:24:02 amd-pence-01 kernel: CS:  0010 DS:  ES:  CR0: 
8005003b
Oct  2 11:24:02 amd-pence-01 kernel: CR2: 7f911ffc8000 CR3: 
c39ec000 CR4: 000407e0
Oct  2 11:24:02 amd-pence-01 kernel:
Oct  2 11:24:02 amd-pence-01 kernel: RIP  [00400776] 0x400775
Oct  2 11:24:02 amd-pence-01 kernel: RSP 7fff2d34da10
Oct  2 11:24:02 amd-pence-01 kernel: ---[ end trace 8a123cd70049eebc ]---
-8--

Please note the PTE value 8008000a0225.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 arch/x86/include/asm/io.h |  4 
 arch/x86/mm/mmap.c| 13 +
 2 files changed, 17 insertions(+)

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 34f69cb..af9f363 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -242,6 +242,10 @@ static inline void flush_write_buffers(void)
 #endif
 }
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t count);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t count);
+
 #endif /* __KERNEL__ */
 
 extern void native_io_delay(void);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 25e7e13..ef02a93 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,8 @@
 #include linux/sched.h
 #include asm/elf.h
 
+#include physaddr.h
+
 struct __read_mostly va_alignment va_align = {
.flags = -1,
 };
@@ -122,3 +124,14 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm-get_unmapped_area = arch_get_unmapped_area_topdown;
}
 }
+
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
+{
+   return addr + count = __pa(high_memory);
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
+{
+   resource_size_t addr = (pfn  PAGE_SHIFT) + count;
+   return phys_addr_valid(addr);
+}
-- 
1.8.3.1


-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RESEND PATCH] x86: add phys addr validity check for /dev/mem mmap

2013-10-02 Thread Frantisek Hrbata
On Wed, Oct 02, 2013 at 10:46:35AM -0700, H. Peter Anvin wrote:
 On 10/02/2013 09:05 AM, Frantisek Hrbata wrote:
  +
  +int valid_phys_addr_range(phys_addr_t addr, size_t count)
  +{
  +   return addr + count = __pa(high_memory);
  +}
  +
  +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
  +{
  +   resource_size_t addr = (pfn  PAGE_SHIFT) + count;
  +   return phys_addr_valid(addr);
  +}
  
 
 The latter has overflow problems.

Could you please specify what overflow problems do you mean?

 
 The former I realize matches the current /dev/mem, but it is still just
 plain wrong in multiple ways.

I guess that you are talking about /dev/mem implementation generelly, because
this patch is exactly the same as the first one. All I'm trying to do here is to
fix this simple problem, which was reported by a customer, using IMHO the least
invasive way. Anyway is there any description what is wrong with /dev/mem
implementation? Maybe I can try to take a look.

Many thanks

 
   -hpa
 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RESEND PATCH] x86: add phys addr validity check for /dev/mem mmap

2013-10-02 Thread Frantisek Hrbata
On Wed, Oct 02, 2013 at 11:36:09AM -0700, H. Peter Anvin wrote:
 On 10/02/2013 11:31 AM, Frantisek Hrbata wrote:
  On Wed, Oct 02, 2013 at 10:46:35AM -0700, H. Peter Anvin wrote:
  On 10/02/2013 09:05 AM, Frantisek Hrbata wrote:
  +
  +int valid_phys_addr_range(phys_addr_t addr, size_t count)
  +{
  + return addr + count = __pa(high_memory);
  +}
  +
  +int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
  +{
  + resource_size_t addr = (pfn  PAGE_SHIFT) + count;
  + return phys_addr_valid(addr);
  +}
 
 
  The latter has overflow problems.
  
  Could you please specify what overflow problems do you mean?
 
 Consider if pfn + count overflows and wraps around, or if (pfn 
 PAGE_SHIFT) pushes bits out to the left.

Ok, maybe I'm missing something, but isn't this handled in
do_mmap_pgoff?

/* offset overflow? */
if ((pgoff + (len  PAGE_SHIFT))  pgoff)
return -EOVERFLOW;

Anyway I can take a closer look and if this can really happen I can fix it.
   
 
  The former I realize matches the current /dev/mem, but it is still just
  plain wrong in multiple ways.
  
  I guess that you are talking about /dev/mem implementation generelly, 
  because
  this patch is exactly the same as the first one. All I'm trying to do here 
  is to
  fix this simple problem, which was reported by a customer, using IMHO the 
  least
  invasive way. Anyway is there any description what is wrong with /dev/mem
  implementation? Maybe I can try to take a look.
  
 
 The bottom line is that read/write to /dev/mem should be able to access
 the same memory that we can mmap().  Having two different tests is
 ridiculous.

Ok, I can try to look into this. I just want to point out that some other archs
like arm are doing it the same way. I simply replaced the generic check 
functions
in drivers/char/mem.c with x86 specific ones.

Thanks

 
   -hpa
 
 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 2/4] gcov: add support for gcc 4.7 gcov format

2013-09-19 Thread Frantisek Hrbata
On Thu, Sep 19, 2013 at 11:04:16AM +0200, Peter Oberparleiter wrote:
> On 04.09.2013 16:42, Frantisek Hrbata wrote:
> > The gcov in-memory format changed in gcc 4.7. The biggest change, which
> > requires this special implementation, is that gcov_info no longer contains
> > array of counters for each counter type for all functions and gcov_fn_info 
> > is
> > not used for mapping of function's counters to these arrays(offset). Now 
> > each
> > gcov_fn_info contans it's counters, which makes things a little bit easier.
> > 
> > This is heavily based on the previous gcc_3_4.c implementation and patches
> > provided by Peter Oberparleiter. Specially the buffer gcda implementation 
> > for
> > iterator.
> > 
> > v2: - removed const definition for gcov_fn_info in gcov_info
> > - use vmalloc for counter values in gcov_info_dup
> > - use iter buffer for gcda
> > 
> > Signed-off-by: Frantisek Hrbata 
> 
> The patch is missing an include statement:
> 
>   CC  kernel/gcov/gcc_4_7.o
> kernel/gcov/gcc_4_7.c: In function ‘gcov_info_dup’:
> kernel/gcov/gcc_4_7.c:293:4: error: implicit declaration of function 
> ‘vmalloc’ [-Werror=implicit-function-declaration]
> kernel/gcov/gcc_4_7.c:293:20: warning: assignment makes pointer from integer 
> without a cast [enabled by default]
> 
> With that added, it compiles and works with gcc 4.3.4 and 4.7.2 on
> kernel 3.21-rc1 on s390x.
> 
> --- a/kernel/gcov/gcc_4_7.c
> +++ b/kernel/gcov/gcc_4_7.c
> @@ -15,6 +15,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include "gcov.h"
> 
>  #define GCOV_COUNTERS8
> 

Hi Peter,

I'm sorry I missed that. Many thanks. In addition, do you have any other
objedtions to the code? Andrew already added the patches to the -mm tree.
Andrew, should I post a follow up patch adding the vmalloc.h include or is it
possible to fix it directly as you did for the previous patches? 
Again I'm sorry for the inconvenience.

Many thanks

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 2/4] gcov: add support for gcc 4.7 gcov format

2013-09-19 Thread Frantisek Hrbata
On Wed, Sep 18, 2013 at 02:31:27PM -0700, Andrew Morton wrote:
> On Wed, 18 Sep 2013 14:27:05 -0700 Joe Perches  wrote:
> 
> > On Wed, 2013-09-18 at 14:22 -0700, Andrew Morton wrote:
> > > On Wed,  4 Sep 2013 16:42:54 +0200 Frantisek Hrbata  
> > > wrote:
> > > > The gcov in-memory format changed in gcc 4.7. The biggest change, which
> > > > requires this special implementation, is that gcov_info no longer 
> > > > contains
> > > > array of counters for each counter type for all functions and 
> > > > gcov_fn_info is
> > > > not used for mapping of function's counters to these arrays(offset). 
> > > > Now each
> > > > gcov_fn_info contans it's counters, which makes things a little bit 
> > > > easier.
> > > > 
> > > > This is heavily based on the previous gcc_3_4.c implementation and 
> > > > patches
> > > > provided by Peter Oberparleiter. Specially the buffer gcda 
> > > > implementation for
> > > > iterator.
> > > 
> > > A couple of little tweaks:
> > []
> > > +++ a/kernel/gcov/gcc_4_7.c
> > []
> > > @@ -267,8 +266,8 @@ struct gcov_info *gcov_info_dup(struct g
> > >   if (!dup->filename)
> > >   goto err_free;
> > >  
> > > - dup->functions = kzalloc(sizeof(struct gcov_fn_info *) *
> > > - info->n_functions, GFP_KERNEL);
> > > + dup->functions = kcalloc(sizeof(struct gcov_fn_info *),
> > > +  info->n_functions, GFP_KERNEL);
> > 
> > kcalloc(n, size_t, flags)
> > 
> > dup->functions = kcalloc(info->n_functions,
> >  sizeof(struct gcov_fn_info *), GFP_KERNEL);
> > 
> 
> Already did that after checkpatch whined at me.  Stupid thing.

Many thanks Andrew and I'm really sorry about the "style problems". Lesson well
learned: use checkpatch before posting.

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 2/4] gcov: add support for gcc 4.7 gcov format

2013-09-19 Thread Frantisek Hrbata
On Wed, Sep 18, 2013 at 02:31:27PM -0700, Andrew Morton wrote:
 On Wed, 18 Sep 2013 14:27:05 -0700 Joe Perches j...@perches.com wrote:
 
  On Wed, 2013-09-18 at 14:22 -0700, Andrew Morton wrote:
   On Wed,  4 Sep 2013 16:42:54 +0200 Frantisek Hrbata fhrb...@redhat.com 
   wrote:
The gcov in-memory format changed in gcc 4.7. The biggest change, which
requires this special implementation, is that gcov_info no longer 
contains
array of counters for each counter type for all functions and 
gcov_fn_info is
not used for mapping of function's counters to these arrays(offset). 
Now each
gcov_fn_info contans it's counters, which makes things a little bit 
easier.

This is heavily based on the previous gcc_3_4.c implementation and 
patches
provided by Peter Oberparleiter. Specially the buffer gcda 
implementation for
iterator.
   
   A couple of little tweaks:
  []
   +++ a/kernel/gcov/gcc_4_7.c
  []
   @@ -267,8 +266,8 @@ struct gcov_info *gcov_info_dup(struct g
 if (!dup-filename)
 goto err_free;

   - dup-functions = kzalloc(sizeof(struct gcov_fn_info *) *
   - info-n_functions, GFP_KERNEL);
   + dup-functions = kcalloc(sizeof(struct gcov_fn_info *),
   +  info-n_functions, GFP_KERNEL);
  
  kcalloc(n, size_t, flags)
  
  dup-functions = kcalloc(info-n_functions,
   sizeof(struct gcov_fn_info *), GFP_KERNEL);
  
 
 Already did that after checkpatch whined at me.  Stupid thing.

Many thanks Andrew and I'm really sorry about the style problems. Lesson well
learned: use checkpatch before posting.

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 2/4] gcov: add support for gcc 4.7 gcov format

2013-09-19 Thread Frantisek Hrbata
On Thu, Sep 19, 2013 at 11:04:16AM +0200, Peter Oberparleiter wrote:
 On 04.09.2013 16:42, Frantisek Hrbata wrote:
  The gcov in-memory format changed in gcc 4.7. The biggest change, which
  requires this special implementation, is that gcov_info no longer contains
  array of counters for each counter type for all functions and gcov_fn_info 
  is
  not used for mapping of function's counters to these arrays(offset). Now 
  each
  gcov_fn_info contans it's counters, which makes things a little bit easier.
  
  This is heavily based on the previous gcc_3_4.c implementation and patches
  provided by Peter Oberparleiter. Specially the buffer gcda implementation 
  for
  iterator.
  
  v2: - removed const definition for gcov_fn_info in gcov_info
  - use vmalloc for counter values in gcov_info_dup
  - use iter buffer for gcda
  
  Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
 
 The patch is missing an include statement:
 
   CC  kernel/gcov/gcc_4_7.o
 kernel/gcov/gcc_4_7.c: In function ‘gcov_info_dup’:
 kernel/gcov/gcc_4_7.c:293:4: error: implicit declaration of function 
 ‘vmalloc’ [-Werror=implicit-function-declaration]
 kernel/gcov/gcc_4_7.c:293:20: warning: assignment makes pointer from integer 
 without a cast [enabled by default]
 
 With that added, it compiles and works with gcc 4.3.4 and 4.7.2 on
 kernel 3.21-rc1 on s390x.
 
 --- a/kernel/gcov/gcc_4_7.c
 +++ b/kernel/gcov/gcc_4_7.c
 @@ -15,6 +15,7 @@
  #include linux/slab.h
  #include linux/string.h
  #include linux/seq_file.h
 +#include linux/vmalloc.h
  #include gcov.h
 
  #define GCOV_COUNTERS8
 

Hi Peter,

I'm sorry I missed that. Many thanks. In addition, do you have any other
objedtions to the code? Andrew already added the patches to the -mm tree.
Andrew, should I post a follow up patch adding the vmalloc.h include or is it
possible to fix it directly as you did for the previous patches? 
Again I'm sorry for the inconvenience.

Many thanks

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 4/4] kernel: add support for init_array constructors

2013-09-10 Thread Frantisek Hrbata
On Tue, Sep 10, 2013 at 03:05:57PM +0930, Rusty Russell wrote:
> Frantisek Hrbata  writes:
> > On Mon, Sep 09, 2013 at 10:44:03AM +0930, Rusty Russell wrote:
> >> Kyle McMartin  writes:
> >> > On Fri, Sep 06, 2013 at 07:51:18PM +0200, Frantisek Hrbata wrote:
> >> >> > > v2: - reuse mod->ctors for .init_array section for modules, because 
> >> >> > > gcc uses
> >> >> > >   .ctors or .init_array, but not both at the same time
> >> >> > >
> >> >> > > Signed-off-by: Frantisek Hrbata 
> >> >> > 
> >> >> > Might be nice to document which gcc version changed this, so people 
> >> >> > can
> >> >> > choose whether to cherry-pick this change?
> >> >> 
> >> >> Thank you for pointing this out. As per gcc git this was introduced by 
> >> >> commit
> >> >> ef1da80 and released in 4.7 version.
> >> >> 
> >> >> $ git describe --contains ef1da80
> >> >> gcc-4_7_0-release~4358
> >> >> 
> >> >> Do you want me to post v3 with this info included in the descrition?
> >> >> 
> >> >
> >> > It actually depends on the combination of binutils/ld and gcc you use, 
> >> > not
> >> > simply which gcc version you use. :/
> >> 
> >> Indeed, and seems it was binutils 20110507 which actually handled it
> >> properly.
> >> 
> >> AFAICT it's theoretically possible to have .ctors and .init_array in a
> >> module.  Unlikely, but the patch should check for both and refuse to
> >> load the module in that case.  Otherwise weird things would happen.
> >
> > I'm not sure if coexistence of .ctors and .init_array sections should 
> > result in
> > denial of module, but I for sure know nothing about this :). Could you maybe
> > privide one example of the "weird thing"?
> 
> Well, if we have both ctors and init_array, and we only call the ctors,
> part of the module will be uninitialized.
> 
> I was thinking about something like the following (based on your
> previous patch).
> 
> Thoughts?
> Rusty.

Thank you Rusty, from what I can say it looks ok to me. So I would go with this
version. Is there anything that needs to be done to consider this as the
correct version of the 4/4 patch? Meaning should we repost this as v3 or could
your version of the patch be picked as you posted it?

> 
> From: Frantisek Hrbata 
> Subject: kernel: add support for init_array constructors
> 
> This adds the .init_array section as yet another section with constructors. 
> This
> is needed because gcc could add __gcov_init calls to .init_array or .ctors
> section, depending on gcc (and binutils) version .
> 
> v2: - reuse mod->ctors for .init_array section for modules, because gcc uses
>   .ctors or .init_array, but not both at the same time
> v3: - fail to load if that does happen somehow.
> 
> Signed-off-by: Frantisek Hrbata 
> Signed-off-by: Rusty Russell 
> 
> diff --git a/include/asm-generic/vmlinux.lds.h 
> b/include/asm-generic/vmlinux.lds.h
> index 83e2c31..bc2121f 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -473,6 +473,7 @@
>  #define KERNEL_CTORS()   . = ALIGN(8);  \
>   VMLINUX_SYMBOL(__ctors_start) = .; \
>   *(.ctors)  \
> + *(.init_array) \
>   VMLINUX_SYMBOL(__ctors_end) = .;
>  #else
>  #define KERNEL_CTORS()
> diff --git a/kernel/module.c b/kernel/module.c
> index dc58274..d3f5a58 100644
> --- a/kernel/module.c
> +++ b/kernel/module.c
> @@ -2738,7 +2738,7 @@ static int check_modinfo(struct module *mod, struct 
> load_info *info, int flags)
>   return 0;
>  }
>  
> -static void find_module_sections(struct module *mod, struct load_info *info)
> +static int find_module_sections(struct module *mod, struct load_info *info)
>  {
>   mod->kp = section_objs(info, "__param",
>  sizeof(*mod->kp), >num_kp);
> @@ -2768,6 +2768,18 @@ static void find_module_sections(struct module *mod, 
> struct load_info *info)
>  #ifdef CONFIG_CONSTRUCTORS
>   mod->ctors = section_objs(info, ".ctors",
> sizeof(*mod->ctors), >num_ctors);
> + if (!mod->ctors)
> + mod->ctors = section_objs(info, ".init_array",
> + sizeof(*mod-&g

Re: [PATCH v2 4/4] kernel: add support for init_array constructors

2013-09-10 Thread Frantisek Hrbata
On Tue, Sep 10, 2013 at 03:05:57PM +0930, Rusty Russell wrote:
 Frantisek Hrbata fhrb...@redhat.com writes:
  On Mon, Sep 09, 2013 at 10:44:03AM +0930, Rusty Russell wrote:
  Kyle McMartin k...@infradead.org writes:
   On Fri, Sep 06, 2013 at 07:51:18PM +0200, Frantisek Hrbata wrote:
 v2: - reuse mod-ctors for .init_array section for modules, because 
 gcc uses
   .ctors or .init_array, but not both at the same time

 Signed-off-by: Frantisek Hrbata fhrb...@redhat.com

Might be nice to document which gcc version changed this, so people 
can
choose whether to cherry-pick this change?
   
   Thank you for pointing this out. As per gcc git this was introduced by 
   commit
   ef1da80 and released in 4.7 version.
   
   $ git describe --contains ef1da80
   gcc-4_7_0-release~4358
   
   Do you want me to post v3 with this info included in the descrition?
   
  
   It actually depends on the combination of binutils/ld and gcc you use, 
   not
   simply which gcc version you use. :/
  
  Indeed, and seems it was binutils 20110507 which actually handled it
  properly.
  
  AFAICT it's theoretically possible to have .ctors and .init_array in a
  module.  Unlikely, but the patch should check for both and refuse to
  load the module in that case.  Otherwise weird things would happen.
 
  I'm not sure if coexistence of .ctors and .init_array sections should 
  result in
  denial of module, but I for sure know nothing about this :). Could you maybe
  privide one example of the weird thing?
 
 Well, if we have both ctors and init_array, and we only call the ctors,
 part of the module will be uninitialized.
 
 I was thinking about something like the following (based on your
 previous patch).
 
 Thoughts?
 Rusty.

Thank you Rusty, from what I can say it looks ok to me. So I would go with this
version. Is there anything that needs to be done to consider this as the
correct version of the 4/4 patch? Meaning should we repost this as v3 or could
your version of the patch be picked as you posted it?

 
 From: Frantisek Hrbata fhrb...@redhat.com
 Subject: kernel: add support for init_array constructors
 
 This adds the .init_array section as yet another section with constructors. 
 This
 is needed because gcc could add __gcov_init calls to .init_array or .ctors
 section, depending on gcc (and binutils) version .
 
 v2: - reuse mod-ctors for .init_array section for modules, because gcc uses
   .ctors or .init_array, but not both at the same time
 v3: - fail to load if that does happen somehow.
 
 Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
 Signed-off-by: Rusty Russell ru...@rustcorp.com.au
 
 diff --git a/include/asm-generic/vmlinux.lds.h 
 b/include/asm-generic/vmlinux.lds.h
 index 83e2c31..bc2121f 100644
 --- a/include/asm-generic/vmlinux.lds.h
 +++ b/include/asm-generic/vmlinux.lds.h
 @@ -473,6 +473,7 @@
  #define KERNEL_CTORS()   . = ALIGN(8);  \
   VMLINUX_SYMBOL(__ctors_start) = .; \
   *(.ctors)  \
 + *(.init_array) \
   VMLINUX_SYMBOL(__ctors_end) = .;
  #else
  #define KERNEL_CTORS()
 diff --git a/kernel/module.c b/kernel/module.c
 index dc58274..d3f5a58 100644
 --- a/kernel/module.c
 +++ b/kernel/module.c
 @@ -2738,7 +2738,7 @@ static int check_modinfo(struct module *mod, struct 
 load_info *info, int flags)
   return 0;
  }
  
 -static void find_module_sections(struct module *mod, struct load_info *info)
 +static int find_module_sections(struct module *mod, struct load_info *info)
  {
   mod-kp = section_objs(info, __param,
  sizeof(*mod-kp), mod-num_kp);
 @@ -2768,6 +2768,18 @@ static void find_module_sections(struct module *mod, 
 struct load_info *info)
  #ifdef CONFIG_CONSTRUCTORS
   mod-ctors = section_objs(info, .ctors,
 sizeof(*mod-ctors), mod-num_ctors);
 + if (!mod-ctors)
 + mod-ctors = section_objs(info, .init_array,
 + sizeof(*mod-ctors), mod-num_ctors);
 + else if (find_sec(info, .init_array)) {
 + /*
 +  * This shouldn't happen with same compiler and binutils
 +  * building all parts of the module.
 +  */
 + printk(KERN_WARNING %s: has both .ctors and .init_array.\n,
 +mod-name);
 + return -EINVAL;
 + }
  #endif
  
  #ifdef CONFIG_TRACEPOINTS
 @@ -2806,6 +2818,8 @@ static void find_module_sections(struct module *mod, 
 struct load_info *info)
  
   info-debug = section_objs(info, __verbose,
  sizeof(*info-debug), info-num_debug);
 +
 + return 0;
  }
  
  static int move_module(struct module *mod, struct load_info *info)
 @@ -3263,7 +3277,9 @@ static int load_module(struct load_info *info, const 
 char __user *uargs,
  
   /* Now we've got everything

Re: [PATCH v2 4/4] kernel: add support for init_array constructors

2013-09-09 Thread Frantisek Hrbata
On Mon, Sep 09, 2013 at 10:44:03AM +0930, Rusty Russell wrote:
> Kyle McMartin  writes:
> > On Fri, Sep 06, 2013 at 07:51:18PM +0200, Frantisek Hrbata wrote:
> >> > > v2: - reuse mod->ctors for .init_array section for modules, because 
> >> > > gcc uses
> >> > >   .ctors or .init_array, but not both at the same time
> >> > >
> >> > > Signed-off-by: Frantisek Hrbata 
> >> > 
> >> > Might be nice to document which gcc version changed this, so people can
> >> > choose whether to cherry-pick this change?
> >> 
> >> Thank you for pointing this out. As per gcc git this was introduced by 
> >> commit
> >> ef1da80 and released in 4.7 version.
> >> 
> >> $ git describe --contains ef1da80
> >> gcc-4_7_0-release~4358
> >> 
> >> Do you want me to post v3 with this info included in the descrition?
> >> 
> >
> > It actually depends on the combination of binutils/ld and gcc you use, not
> > simply which gcc version you use. :/
> 
> Indeed, and seems it was binutils 20110507 which actually handled it
> properly.
> 
> AFAICT it's theoretically possible to have .ctors and .init_array in a
> module.  Unlikely, but the patch should check for both and refuse to
> load the module in that case.  Otherwise weird things would happen.

I'm not sure if coexistence of .ctors and .init_array sections should result in
denial of module, but I for sure know nothing about this :). Could you maybe
privide one example of the "weird thing"?

Anyway many thanks for taking time to look at this. Below is my attepmt to
implement the check you proposed. 

untested/uncompiled

diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 83e2c31..bc2121f 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -473,6 +473,7 @@
 #define KERNEL_CTORS() . = ALIGN(8);  \
VMLINUX_SYMBOL(__ctors_start) = .; \
*(.ctors)  \
+   *(.init_array) \
VMLINUX_SYMBOL(__ctors_end) = .;
 #else
 #define KERNEL_CTORS()
diff --git a/include/linux/module.h b/include/linux/module.h
index 05f2447..e775b41 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -380,6 +380,8 @@ struct module
/* Constructor functions. */
ctor_fn_t *ctors;
unsigned int num_ctors;
+   ctor_fn_t *init_array;
+   unsigned int num_init_array;
 #endif
 };
 #ifndef MODULE_ARCH_INIT
diff --git a/kernel/module.c b/kernel/module.c
index dc58274..831b92d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2768,6 +2768,9 @@ static void find_module_sections(struct module *mod, 
struct load_info *info)
 #ifdef CONFIG_CONSTRUCTORS
mod->ctors = section_objs(info, ".ctors",
  sizeof(*mod->ctors), >num_ctors);
+   mod->init_array = section_objs(info, ".init_array",
+ sizeof(*mod->init_array),
+ >num_init_array);
 #endif
 
 #ifdef CONFIG_TRACEPOINTS
@@ -2808,6 +2811,18 @@ static void find_module_sections(struct module *mod, 
struct load_info *info)
   sizeof(*info->debug), >num_debug);
 }
 
+static void check_module_sections(struct module *mod)
+{
+#ifdef CONFIG_CONSTRUCTORS
+   if (mod->ctors && mod->init_array) {
+   pr_err("%s: .ctors and .init_array sections mishmash\n",
+   mod->name);
+   return -EINVAL;
+   }
+#endif
+   return 0;
+}
+
 static int move_module(struct module *mod, struct load_info *info)
 {
int i;
@@ -3032,6 +3047,9 @@ static void do_mod_ctors(struct module *mod)
 
for (i = 0; i < mod->num_ctors; i++)
mod->ctors[i]();
+
+   for (i = 0; i < mod->num_init_array; i++)
+   mod->init_array[i]();
 #endif
 }
 
@@ -3265,6 +3283,10 @@ static int load_module(struct load_info *info, const 
char __user *uargs,
 * find optional sections. */
find_module_sections(mod, info);
 
+   err = check_module_sections(mod);
+   if (err)
+   goto free_unload;
+
err = check_module_license_and_versions(mod);
if (err)
goto free_unload;
-- 
1.8.3.1

> 
> Cheers,
> Rusty.

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 4/4] kernel: add support for init_array constructors

2013-09-09 Thread Frantisek Hrbata
On Mon, Sep 09, 2013 at 10:44:03AM +0930, Rusty Russell wrote:
 Kyle McMartin k...@infradead.org writes:
  On Fri, Sep 06, 2013 at 07:51:18PM +0200, Frantisek Hrbata wrote:
v2: - reuse mod-ctors for .init_array section for modules, because 
gcc uses
  .ctors or .init_array, but not both at the same time
   
Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
   
   Might be nice to document which gcc version changed this, so people can
   choose whether to cherry-pick this change?
  
  Thank you for pointing this out. As per gcc git this was introduced by 
  commit
  ef1da80 and released in 4.7 version.
  
  $ git describe --contains ef1da80
  gcc-4_7_0-release~4358
  
  Do you want me to post v3 with this info included in the descrition?
  
 
  It actually depends on the combination of binutils/ld and gcc you use, not
  simply which gcc version you use. :/
 
 Indeed, and seems it was binutils 20110507 which actually handled it
 properly.
 
 AFAICT it's theoretically possible to have .ctors and .init_array in a
 module.  Unlikely, but the patch should check for both and refuse to
 load the module in that case.  Otherwise weird things would happen.

I'm not sure if coexistence of .ctors and .init_array sections should result in
denial of module, but I for sure know nothing about this :). Could you maybe
privide one example of the weird thing?

Anyway many thanks for taking time to look at this. Below is my attepmt to
implement the check you proposed. 

untested/uncompiled

diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 83e2c31..bc2121f 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -473,6 +473,7 @@
 #define KERNEL_CTORS() . = ALIGN(8);  \
VMLINUX_SYMBOL(__ctors_start) = .; \
*(.ctors)  \
+   *(.init_array) \
VMLINUX_SYMBOL(__ctors_end) = .;
 #else
 #define KERNEL_CTORS()
diff --git a/include/linux/module.h b/include/linux/module.h
index 05f2447..e775b41 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -380,6 +380,8 @@ struct module
/* Constructor functions. */
ctor_fn_t *ctors;
unsigned int num_ctors;
+   ctor_fn_t *init_array;
+   unsigned int num_init_array;
 #endif
 };
 #ifndef MODULE_ARCH_INIT
diff --git a/kernel/module.c b/kernel/module.c
index dc58274..831b92d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2768,6 +2768,9 @@ static void find_module_sections(struct module *mod, 
struct load_info *info)
 #ifdef CONFIG_CONSTRUCTORS
mod-ctors = section_objs(info, .ctors,
  sizeof(*mod-ctors), mod-num_ctors);
+   mod-init_array = section_objs(info, .init_array,
+ sizeof(*mod-init_array),
+ mod-num_init_array);
 #endif
 
 #ifdef CONFIG_TRACEPOINTS
@@ -2808,6 +2811,18 @@ static void find_module_sections(struct module *mod, 
struct load_info *info)
   sizeof(*info-debug), info-num_debug);
 }
 
+static void check_module_sections(struct module *mod)
+{
+#ifdef CONFIG_CONSTRUCTORS
+   if (mod-ctors  mod-init_array) {
+   pr_err(%s: .ctors and .init_array sections mishmash\n,
+   mod-name);
+   return -EINVAL;
+   }
+#endif
+   return 0;
+}
+
 static int move_module(struct module *mod, struct load_info *info)
 {
int i;
@@ -3032,6 +3047,9 @@ static void do_mod_ctors(struct module *mod)
 
for (i = 0; i  mod-num_ctors; i++)
mod-ctors[i]();
+
+   for (i = 0; i  mod-num_init_array; i++)
+   mod-init_array[i]();
 #endif
 }
 
@@ -3265,6 +3283,10 @@ static int load_module(struct load_info *info, const 
char __user *uargs,
 * find optional sections. */
find_module_sections(mod, info);
 
+   err = check_module_sections(mod);
+   if (err)
+   goto free_unload;
+
err = check_module_license_and_versions(mod);
if (err)
goto free_unload;
-- 
1.8.3.1

 
 Cheers,
 Rusty.

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 4/4] kernel: add support for init_array constructors

2013-09-06 Thread Frantisek Hrbata
On Fri, Sep 06, 2013 at 11:43:08AM +0930, Rusty Russell wrote:
> Frantisek Hrbata  writes:
> > This adds the .init_array section as yet another section with constructors. 
> > This
> > is needed because gcc could add __gcov_init calls to .init_array or .ctors
> > section, depending on gcc version.
> >
> > v2: - reuse mod->ctors for .init_array section for modules, because gcc uses
> >   .ctors or .init_array, but not both at the same time
> >
> > Signed-off-by: Frantisek Hrbata 
> 
> Might be nice to document which gcc version changed this, so people can
> choose whether to cherry-pick this change?

Thank you for pointing this out. As per gcc git this was introduced by commit
ef1da80 and released in 4.7 version.

$ git describe --contains ef1da80
gcc-4_7_0-release~4358

Do you want me to post v3 with this info included in the descrition?

> 
> Acked-by: Rusty Russell 

Many thanks

> 
> > ---
> >  include/asm-generic/vmlinux.lds.h | 1 +
> >  kernel/module.c   | 3 +++
> >  2 files changed, 4 insertions(+)
> >
> > diff --git a/include/asm-generic/vmlinux.lds.h 
> > b/include/asm-generic/vmlinux.lds.h
> > index 69732d2..c55d8d9 100644
> > --- a/include/asm-generic/vmlinux.lds.h
> > +++ b/include/asm-generic/vmlinux.lds.h
> > @@ -468,6 +468,7 @@
> >  #define KERNEL_CTORS() . = ALIGN(8);  \
> > VMLINUX_SYMBOL(__ctors_start) = .; \
> > *(.ctors)  \
> > +   *(.init_array) \
> > VMLINUX_SYMBOL(__ctors_end) = .;
> >  #else
> >  #define KERNEL_CTORS()
> > diff --git a/kernel/module.c b/kernel/module.c
> > index 2069158..bbbd953 100644
> > --- a/kernel/module.c
> > +++ b/kernel/module.c
> > @@ -2760,6 +2760,9 @@ static void find_module_sections(struct module *mod, 
> > struct load_info *info)
> >  #ifdef CONFIG_CONSTRUCTORS
> > mod->ctors = section_objs(info, ".ctors",
> >   sizeof(*mod->ctors), >num_ctors);
> > +   if (!mod->ctors)
> > +   mod->ctors = section_objs(info, ".init_array",
> > +   sizeof(*mod->ctors), >num_ctors);
> >  #endif
> >  
> >  #ifdef CONFIG_TRACEPOINTS
> > -- 
> > 1.8.3.1

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 4/4] kernel: add support for init_array constructors

2013-09-06 Thread Frantisek Hrbata
On Fri, Sep 06, 2013 at 11:43:08AM +0930, Rusty Russell wrote:
 Frantisek Hrbata fhrb...@redhat.com writes:
  This adds the .init_array section as yet another section with constructors. 
  This
  is needed because gcc could add __gcov_init calls to .init_array or .ctors
  section, depending on gcc version.
 
  v2: - reuse mod-ctors for .init_array section for modules, because gcc uses
.ctors or .init_array, but not both at the same time
 
  Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
 
 Might be nice to document which gcc version changed this, so people can
 choose whether to cherry-pick this change?

Thank you for pointing this out. As per gcc git this was introduced by commit
ef1da80 and released in 4.7 version.

$ git describe --contains ef1da80
gcc-4_7_0-release~4358

Do you want me to post v3 with this info included in the descrition?

 
 Acked-by: Rusty Russell ru...@rustcorp.com.au

Many thanks

 
  ---
   include/asm-generic/vmlinux.lds.h | 1 +
   kernel/module.c   | 3 +++
   2 files changed, 4 insertions(+)
 
  diff --git a/include/asm-generic/vmlinux.lds.h 
  b/include/asm-generic/vmlinux.lds.h
  index 69732d2..c55d8d9 100644
  --- a/include/asm-generic/vmlinux.lds.h
  +++ b/include/asm-generic/vmlinux.lds.h
  @@ -468,6 +468,7 @@
   #define KERNEL_CTORS() . = ALIGN(8);  \
  VMLINUX_SYMBOL(__ctors_start) = .; \
  *(.ctors)  \
  +   *(.init_array) \
  VMLINUX_SYMBOL(__ctors_end) = .;
   #else
   #define KERNEL_CTORS()
  diff --git a/kernel/module.c b/kernel/module.c
  index 2069158..bbbd953 100644
  --- a/kernel/module.c
  +++ b/kernel/module.c
  @@ -2760,6 +2760,9 @@ static void find_module_sections(struct module *mod, 
  struct load_info *info)
   #ifdef CONFIG_CONSTRUCTORS
  mod-ctors = section_objs(info, .ctors,
sizeof(*mod-ctors), mod-num_ctors);
  +   if (!mod-ctors)
  +   mod-ctors = section_objs(info, .init_array,
  +   sizeof(*mod-ctors), mod-num_ctors);
   #endif
   
   #ifdef CONFIG_TRACEPOINTS
  -- 
  1.8.3.1

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 0/4] add support for gcov format introduced in gcc 4.7

2013-09-04 Thread Frantisek Hrbata
This is an attempt to bring support for modified gcov format in gcc 4.7 to
the kernel. It tries to leverage the existing layout/abstraction, which was
designed keeping in mind that the gcov format could change, but some changes had
to be make. Mostly because the current model does not take into account that
even the core gcov structures, like gcov_info, could change. One part that could
be problematic is the addition of the .init_array section for constructors.

Tested with lcov and seems to be working fine, giving similar results as for the
older format.

v2: Included suggestions/code provided by Peter Oberparleiter. Detailed
description in patches.

Frantisek Hrbata (4):
  gcov: move gcov structs definitions to a gcc version specific file
  gcov: add support for gcc 4.7 gcov format
  gcov: compile specific gcov implementation based on gcc version
  kernel: add support for init_array constructors

 Documentation/gcov.txt|   4 +
 include/asm-generic/vmlinux.lds.h |   1 +
 kernel/gcov/Kconfig   |  30 ++
 kernel/gcov/Makefile  |  32 ++-
 kernel/gcov/base.c|  32 ++-
 kernel/gcov/fs.c  |  27 +-
 kernel/gcov/gcc_3_4.c | 115 
 kernel/gcov/gcc_4_7.c | 562 ++
 kernel/gcov/gcov.h|  65 +
 kernel/module.c   |   3 +
 10 files changed, 790 insertions(+), 81 deletions(-)
 create mode 100644 kernel/gcov/gcc_4_7.c

-- 
1.8.3.1

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


[PATCH v2 1/4] gcov: move gcov structs definitions to a gcc version specific file

2013-09-04 Thread Frantisek Hrbata
Since also the gcov structures(gcov_info, gcov_fn_info, gcov_ctr_info) can
change between gcc releases, as shown in gcc 4.7, they cannot be defined in a
common header and need to be moved to a specific gcc implemention file. This
also requires to make the gcov_info structure opaque for the common code and to
introduce simple helpers for accessing data inside gcov_info.

Signed-off-by: Frantisek Hrbata 
---
 kernel/gcov/base.c|  26 ++--
 kernel/gcov/fs.c  |  27 ++--
 kernel/gcov/gcc_3_4.c | 115 ++
 kernel/gcov/gcov.h|  65 +---
 4 files changed, 153 insertions(+), 80 deletions(-)

diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c
index 9b22d03..912576a 100644
--- a/kernel/gcov/base.c
+++ b/kernel/gcov/base.c
@@ -20,7 +20,6 @@
 #include 
 #include "gcov.h"
 
-static struct gcov_info *gcov_info_head;
 static int gcov_events_enabled;
 static DEFINE_MUTEX(gcov_lock);
 
@@ -34,7 +33,7 @@ void __gcov_init(struct gcov_info *info)
 
mutex_lock(_lock);
if (gcov_version == 0) {
-   gcov_version = info->version;
+   gcov_version = gcov_info_version(info);
/*
 * Printing gcc's version magic may prove useful for debugging
 * incompatibility reports.
@@ -45,8 +44,7 @@ void __gcov_init(struct gcov_info *info)
 * Add new profiling data structure to list and inform event
 * listener.
 */
-   info->next = gcov_info_head;
-   gcov_info_head = info;
+   gcov_info_link(info);
if (gcov_events_enabled)
gcov_event(GCOV_ADD, info);
mutex_unlock(_lock);
@@ -91,13 +89,15 @@ EXPORT_SYMBOL(__gcov_merge_delta);
  */
 void gcov_enable_events(void)
 {
-   struct gcov_info *info;
+   struct gcov_info *info = NULL;
 
mutex_lock(_lock);
gcov_events_enabled = 1;
+
/* Perform event callback for previously registered entries. */
-   for (info = gcov_info_head; info; info = info->next)
+   while ((info = gcov_info_next(info)))
gcov_event(GCOV_ADD, info);
+
mutex_unlock(_lock);
 }
 
@@ -112,25 +112,23 @@ static int gcov_module_notifier(struct notifier_block 
*nb, unsigned long event,
void *data)
 {
struct module *mod = data;
-   struct gcov_info *info;
-   struct gcov_info *prev;
+   struct gcov_info *info = NULL;
+   struct gcov_info *prev = NULL;
 
if (event != MODULE_STATE_GOING)
return NOTIFY_OK;
mutex_lock(_lock);
-   prev = NULL;
+
/* Remove entries located in module from linked list. */
-   for (info = gcov_info_head; info; info = info->next) {
+   while ((info = gcov_info_next(info))) {
if (within(info, mod->module_core, mod->core_size)) {
-   if (prev)
-   prev->next = info->next;
-   else
-   gcov_info_head = info->next;
+   gcov_info_unlink(prev, info);
if (gcov_events_enabled)
gcov_event(GCOV_REMOVE, info);
} else
prev = info;
}
+
mutex_unlock(_lock);
 
return NOTIFY_OK;
diff --git a/kernel/gcov/fs.c b/kernel/gcov/fs.c
index 9bd0934..27e12ce 100644
--- a/kernel/gcov/fs.c
+++ b/kernel/gcov/fs.c
@@ -242,7 +242,7 @@ static struct gcov_node *get_node_by_name(const char *name)
 
list_for_each_entry(node, _head, all) {
info = get_node_info(node);
-   if (info && (strcmp(info->filename, name) == 0))
+   if (info && (strcmp(gcov_info_filename(info), name) == 0))
return node;
}
 
@@ -279,7 +279,7 @@ static ssize_t gcov_seq_write(struct file *file, const char 
__user *addr,
seq = file->private_data;
info = gcov_iter_get_info(seq->private);
mutex_lock(_lock);
-   node = get_node_by_name(info->filename);
+   node = get_node_by_name(gcov_info_filename(info));
if (node) {
/* Reset counts or remove node for unloaded modules. */
if (node->num_loaded == 0)
@@ -376,8 +376,9 @@ static void add_links(struct gcov_node *node, struct dentry 
*parent)
if (!node->links)
return;
for (i = 0; i < num; i++) {
-   target = get_link_target(get_node_info(node)->filename,
-_link[i]);
+   target = get_link_target(
+   gcov_info_filename(get_node_info(node)),
+   _link[i]);
if (!target)
goto out_err;
basename = strrchr(target, '/');
@@ -576,7 +577,7 @@ static void add_

[PATCH v2 2/4] gcov: add support for gcc 4.7 gcov format

2013-09-04 Thread Frantisek Hrbata
The gcov in-memory format changed in gcc 4.7. The biggest change, which
requires this special implementation, is that gcov_info no longer contains
array of counters for each counter type for all functions and gcov_fn_info is
not used for mapping of function's counters to these arrays(offset). Now each
gcov_fn_info contans it's counters, which makes things a little bit easier.

This is heavily based on the previous gcc_3_4.c implementation and patches
provided by Peter Oberparleiter. Specially the buffer gcda implementation for
iterator.

v2: - removed const definition for gcov_fn_info in gcov_info
- use vmalloc for counter values in gcov_info_dup
- use iter buffer for gcda

Signed-off-by: Frantisek Hrbata 
---
 kernel/gcov/base.c|   6 +
 kernel/gcov/gcc_4_7.c | 562 ++
 2 files changed, 568 insertions(+)
 create mode 100644 kernel/gcov/gcc_4_7.c

diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c
index 912576a..f45b75b 100644
--- a/kernel/gcov/base.c
+++ b/kernel/gcov/base.c
@@ -79,6 +79,12 @@ void __gcov_merge_delta(gcov_type *counters, unsigned int 
n_counters)
 }
 EXPORT_SYMBOL(__gcov_merge_delta);
 
+void __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
+{
+   /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_ior);
+
 /**
  * gcov_enable_events - enable event reporting through gcov_event()
  *
diff --git a/kernel/gcov/gcc_4_7.c b/kernel/gcov/gcc_4_7.c
new file mode 100644
index 000..d91afee
--- /dev/null
+++ b/kernel/gcov/gcc_4_7.c
@@ -0,0 +1,562 @@
+/*
+ *  This code provides functions to handle gcc's profiling data format
+ *  introduced with gcc 4.7.
+ *
+ *  This file is based heavily on gcc_3_4.c file.
+ *
+ *  For a better understanding, refer to gcc source:
+ *  gcc/gcov-io.h
+ *  libgcc/libgcov.c
+ *
+ *  Uses gcc-internal data definitions.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include "gcov.h"
+
+#define GCOV_COUNTERS  8
+#define GCOV_TAG_FUNCTION_LENGTH   3
+
+static struct gcov_info *gcov_info_head;
+
+/**
+ * struct gcov_ctr_info - information about counters for a single function
+ * @num: number of counter values for this type
+ * @values: array of counter values for this type
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the values array.
+ */
+struct gcov_ctr_info {
+   unsigned int num;
+   gcov_type *values;
+};
+
+/**
+ * struct gcov_fn_info - profiling meta data per function
+ * @key: comdat key
+ * @ident: unique ident of function
+ * @lineno_checksum: function lineo_checksum
+ * @cfg_checksum: function cfg checksum
+ * @ctrs: instrumented counters
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time.
+ *
+ * Information about a single function.  This uses the trailing array
+ * idiom. The number of counters is determined from the merge pointer
+ * array in gcov_info.  The key is used to detect which of a set of
+ * comdat functions was selected -- it points to the gcov_info object
+ * of the object file containing the selected comdat function.
+ */
+struct gcov_fn_info {
+   const struct gcov_info *key;
+   unsigned int ident;
+   unsigned int lineno_checksum;
+   unsigned int cfg_checksum;
+   struct gcov_ctr_info ctrs[0];
+};
+
+/**
+ * struct gcov_info - profiling data per object file
+ * @version: gcov version magic indicating the gcc version used for compilation
+ * @next: list head for a singly-linked list
+ * @stamp: uniquifying time stamp
+ * @filename: name of the associated gcov data file
+ * @merge: merge functions (null for unused counter type)
+ * @n_functions: number of instrumented functions
+ * @functions: pointer to pointers to function information
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the next pointer.
+ */
+struct gcov_info {
+   unsigned int version;
+   struct gcov_info *next;
+   unsigned int stamp;
+   const char *filename;
+   void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int);
+   unsigned int n_functions;
+   struct gcov_fn_info **functions;
+};
+
+/**
+ * gcov_info_filename - return info filename
+ * @info: profiling data set
+ */
+const char *gcov_info_filename(struct gcov_info *info)
+{
+   return info->filename;
+}
+
+/**
+ * gcov_info_version - return info version
+ * @info: profiling data set
+ */
+unsigned int gcov_info_version(struct gcov_info *info)
+{
+   return info->version;
+}
+
+/**
+ * gcov_info_next - return next profiling data set
+ * @info: profiling data set
+ *
+ * Returns next gcov_info following @info or first gcov_info in the chain if
+ * @info is %NULL.
+ */
+struct gcov_info *gcov_info_next(struct gcov_info *info)
+{
+   if (!info)
+   return gcov_info_head;
+
+   return info->next;
+}
+
+/**
+ * gcov_info_link - link/add profiling d

[PATCH v2 4/4] kernel: add support for init_array constructors

2013-09-04 Thread Frantisek Hrbata
This adds the .init_array section as yet another section with constructors. This
is needed because gcc could add __gcov_init calls to .init_array or .ctors
section, depending on gcc version.

v2: - reuse mod->ctors for .init_array section for modules, because gcc uses
  .ctors or .init_array, but not both at the same time

Signed-off-by: Frantisek Hrbata 
---
 include/asm-generic/vmlinux.lds.h | 1 +
 kernel/module.c   | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 69732d2..c55d8d9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -468,6 +468,7 @@
 #define KERNEL_CTORS() . = ALIGN(8);  \
VMLINUX_SYMBOL(__ctors_start) = .; \
*(.ctors)  \
+   *(.init_array) \
VMLINUX_SYMBOL(__ctors_end) = .;
 #else
 #define KERNEL_CTORS()
diff --git a/kernel/module.c b/kernel/module.c
index 2069158..bbbd953 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2760,6 +2760,9 @@ static void find_module_sections(struct module *mod, 
struct load_info *info)
 #ifdef CONFIG_CONSTRUCTORS
mod->ctors = section_objs(info, ".ctors",
  sizeof(*mod->ctors), >num_ctors);
+   if (!mod->ctors)
+   mod->ctors = section_objs(info, ".init_array",
+   sizeof(*mod->ctors), >num_ctors);
 #endif
 
 #ifdef CONFIG_TRACEPOINTS
-- 
1.8.3.1

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


[PATCH v2 3/4] gcov: compile specific gcov implementation based on gcc version

2013-09-04 Thread Frantisek Hrbata
Compile the correct gcov implementation file for the specific gcc version.

v2: - added possibility to explicitly select gcc version during configuration,
  this is based on code provided by Peter Oberparleiter.
- added a note about gcov format selection to gcov.txt

Signed-off-by: Frantisek Hrbata 
---
 Documentation/gcov.txt |  4 
 kernel/gcov/Kconfig| 30 ++
 kernel/gcov/Makefile   | 32 +++-
 3 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/Documentation/gcov.txt b/Documentation/gcov.txt
index e7ca647..7b72778 100644
--- a/Documentation/gcov.txt
+++ b/Documentation/gcov.txt
@@ -50,6 +50,10 @@ Configure the kernel with:
 CONFIG_DEBUG_FS=y
 CONFIG_GCOV_KERNEL=y
 
+select the gcc's gcov format, default is autodetect based on gcc version:
+
+CONFIG_GCOV_FORMAT_AUTODETECT=y
+
 and to get coverage data for the entire kernel:
 
 CONFIG_GCOV_PROFILE_ALL=y
diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig
index d4da55d..d04ce8a 100644
--- a/kernel/gcov/Kconfig
+++ b/kernel/gcov/Kconfig
@@ -46,4 +46,34 @@ config GCOV_PROFILE_ALL
larger and run slower. Also be sure to exclude files from profiling
which are not linked to the kernel image to prevent linker errors.
 
+choice
+   prompt "Specify GCOV format"
+   depends on GCOV_KERNEL
+   default GCOV_FORMAT_AUTODETECT
+   ---help---
+   The gcov format is usually determined by the GCC version, but there are
+   exceptions where format changes are integrated in lower-version GCCs.
+   In such a case use this option to adjust the format used in the kernel
+   accordingly.
+
+   If unsure, choose "Autodetect".
+
+config GCOV_FORMAT_AUTODETECT
+   bool "Autodetect"
+   ---help---
+   Select this option to use the format that corresponds to your GCC
+   version.
+
+config GCOV_FORMAT_3_4
+   bool "GCC 3.4 format"
+   ---help---
+   Select this option to use the format defined by GCC 3.4.
+
+config GCOV_FORMAT_4_7
+   bool "GCC 4.7 format"
+   ---help---
+   Select this option to use the format defined by GCC 4.7.
+
+endchoice
+
 endmenu
diff --git a/kernel/gcov/Makefile b/kernel/gcov/Makefile
index e97ca59..52aa7e8 100644
--- a/kernel/gcov/Makefile
+++ b/kernel/gcov/Makefile
@@ -1,3 +1,33 @@
 ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
 
-obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
+# if-lt
+# Usage VAR := $(call if-lt, $(a), $(b))
+# Returns 1 if (a < b)
+if-lt = $(shell [ $(1) -lt $(2) ] && echo 1)
+
+ifeq ($(CONFIG_GCOV_FORMAT_3_4),y)
+  cc-ver := 0304
+else ifeq ($(CONFIG_GCOV_FORMAT_4_7),y)
+  cc-ver := 0407
+else
+# Use cc-version if available, otherwise set 0
+#
+# scripts/Kbuild.include, which contains cc-version function, is not included
+# during make clean "make -f scripts/Makefile.clean obj=kernel/gcov"
+# Meaning cc-ver is empty causing if-lt test to fail with
+# "/bin/sh: line 0: [: -lt: unary operator expected" error mesage.
+# This has no affect on the clean phase, but the error message could be
+# confusing/annoying. So this dummy workaround sets cc-ver to zero if 
cc-version
+# is not available. We can probably move if-lt to Kbuild.include, so it's also
+# not defined during clean or to include Kbuild.include in
+# scripts/Makefile.clean. But the following workaround seems least invasive.
+  cc-ver := $(if $(call cc-version),$(call cc-version),0)
+endif
+
+obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
+
+ifeq ($(call if-lt, $(cc-ver), 0407),1)
+  obj-$(CONFIG_GCOV_KERNEL) += gcc_3_4.o
+else
+  obj-$(CONFIG_GCOV_KERNEL) += gcc_4_7.o
+endif
-- 
1.8.3.1

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


[PATCH v2 3/4] gcov: compile specific gcov implementation based on gcc version

2013-09-04 Thread Frantisek Hrbata
Compile the correct gcov implementation file for the specific gcc version.

v2: - added possibility to explicitly select gcc version during configuration,
  this is based on code provided by Peter Oberparleiter.
- added a note about gcov format selection to gcov.txt

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 Documentation/gcov.txt |  4 
 kernel/gcov/Kconfig| 30 ++
 kernel/gcov/Makefile   | 32 +++-
 3 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/Documentation/gcov.txt b/Documentation/gcov.txt
index e7ca647..7b72778 100644
--- a/Documentation/gcov.txt
+++ b/Documentation/gcov.txt
@@ -50,6 +50,10 @@ Configure the kernel with:
 CONFIG_DEBUG_FS=y
 CONFIG_GCOV_KERNEL=y
 
+select the gcc's gcov format, default is autodetect based on gcc version:
+
+CONFIG_GCOV_FORMAT_AUTODETECT=y
+
 and to get coverage data for the entire kernel:
 
 CONFIG_GCOV_PROFILE_ALL=y
diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig
index d4da55d..d04ce8a 100644
--- a/kernel/gcov/Kconfig
+++ b/kernel/gcov/Kconfig
@@ -46,4 +46,34 @@ config GCOV_PROFILE_ALL
larger and run slower. Also be sure to exclude files from profiling
which are not linked to the kernel image to prevent linker errors.
 
+choice
+   prompt Specify GCOV format
+   depends on GCOV_KERNEL
+   default GCOV_FORMAT_AUTODETECT
+   ---help---
+   The gcov format is usually determined by the GCC version, but there are
+   exceptions where format changes are integrated in lower-version GCCs.
+   In such a case use this option to adjust the format used in the kernel
+   accordingly.
+
+   If unsure, choose Autodetect.
+
+config GCOV_FORMAT_AUTODETECT
+   bool Autodetect
+   ---help---
+   Select this option to use the format that corresponds to your GCC
+   version.
+
+config GCOV_FORMAT_3_4
+   bool GCC 3.4 format
+   ---help---
+   Select this option to use the format defined by GCC 3.4.
+
+config GCOV_FORMAT_4_7
+   bool GCC 4.7 format
+   ---help---
+   Select this option to use the format defined by GCC 4.7.
+
+endchoice
+
 endmenu
diff --git a/kernel/gcov/Makefile b/kernel/gcov/Makefile
index e97ca59..52aa7e8 100644
--- a/kernel/gcov/Makefile
+++ b/kernel/gcov/Makefile
@@ -1,3 +1,33 @@
 ccflags-y := -DSRCTREE='$(srctree)' -DOBJTREE='$(objtree)'
 
-obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
+# if-lt
+# Usage VAR := $(call if-lt, $(a), $(b))
+# Returns 1 if (a  b)
+if-lt = $(shell [ $(1) -lt $(2) ]  echo 1)
+
+ifeq ($(CONFIG_GCOV_FORMAT_3_4),y)
+  cc-ver := 0304
+else ifeq ($(CONFIG_GCOV_FORMAT_4_7),y)
+  cc-ver := 0407
+else
+# Use cc-version if available, otherwise set 0
+#
+# scripts/Kbuild.include, which contains cc-version function, is not included
+# during make clean make -f scripts/Makefile.clean obj=kernel/gcov
+# Meaning cc-ver is empty causing if-lt test to fail with
+# /bin/sh: line 0: [: -lt: unary operator expected error mesage.
+# This has no affect on the clean phase, but the error message could be
+# confusing/annoying. So this dummy workaround sets cc-ver to zero if 
cc-version
+# is not available. We can probably move if-lt to Kbuild.include, so it's also
+# not defined during clean or to include Kbuild.include in
+# scripts/Makefile.clean. But the following workaround seems least invasive.
+  cc-ver := $(if $(call cc-version),$(call cc-version),0)
+endif
+
+obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
+
+ifeq ($(call if-lt, $(cc-ver), 0407),1)
+  obj-$(CONFIG_GCOV_KERNEL) += gcc_3_4.o
+else
+  obj-$(CONFIG_GCOV_KERNEL) += gcc_4_7.o
+endif
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 2/4] gcov: add support for gcc 4.7 gcov format

2013-09-04 Thread Frantisek Hrbata
The gcov in-memory format changed in gcc 4.7. The biggest change, which
requires this special implementation, is that gcov_info no longer contains
array of counters for each counter type for all functions and gcov_fn_info is
not used for mapping of function's counters to these arrays(offset). Now each
gcov_fn_info contans it's counters, which makes things a little bit easier.

This is heavily based on the previous gcc_3_4.c implementation and patches
provided by Peter Oberparleiter. Specially the buffer gcda implementation for
iterator.

v2: - removed const definition for gcov_fn_info in gcov_info
- use vmalloc for counter values in gcov_info_dup
- use iter buffer for gcda

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 kernel/gcov/base.c|   6 +
 kernel/gcov/gcc_4_7.c | 562 ++
 2 files changed, 568 insertions(+)
 create mode 100644 kernel/gcov/gcc_4_7.c

diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c
index 912576a..f45b75b 100644
--- a/kernel/gcov/base.c
+++ b/kernel/gcov/base.c
@@ -79,6 +79,12 @@ void __gcov_merge_delta(gcov_type *counters, unsigned int 
n_counters)
 }
 EXPORT_SYMBOL(__gcov_merge_delta);
 
+void __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
+{
+   /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_ior);
+
 /**
  * gcov_enable_events - enable event reporting through gcov_event()
  *
diff --git a/kernel/gcov/gcc_4_7.c b/kernel/gcov/gcc_4_7.c
new file mode 100644
index 000..d91afee
--- /dev/null
+++ b/kernel/gcov/gcc_4_7.c
@@ -0,0 +1,562 @@
+/*
+ *  This code provides functions to handle gcc's profiling data format
+ *  introduced with gcc 4.7.
+ *
+ *  This file is based heavily on gcc_3_4.c file.
+ *
+ *  For a better understanding, refer to gcc source:
+ *  gcc/gcov-io.h
+ *  libgcc/libgcov.c
+ *
+ *  Uses gcc-internal data definitions.
+ */
+
+#include linux/errno.h
+#include linux/slab.h
+#include linux/string.h
+#include linux/seq_file.h
+#include gcov.h
+
+#define GCOV_COUNTERS  8
+#define GCOV_TAG_FUNCTION_LENGTH   3
+
+static struct gcov_info *gcov_info_head;
+
+/**
+ * struct gcov_ctr_info - information about counters for a single function
+ * @num: number of counter values for this type
+ * @values: array of counter values for this type
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the values array.
+ */
+struct gcov_ctr_info {
+   unsigned int num;
+   gcov_type *values;
+};
+
+/**
+ * struct gcov_fn_info - profiling meta data per function
+ * @key: comdat key
+ * @ident: unique ident of function
+ * @lineno_checksum: function lineo_checksum
+ * @cfg_checksum: function cfg checksum
+ * @ctrs: instrumented counters
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time.
+ *
+ * Information about a single function.  This uses the trailing array
+ * idiom. The number of counters is determined from the merge pointer
+ * array in gcov_info.  The key is used to detect which of a set of
+ * comdat functions was selected -- it points to the gcov_info object
+ * of the object file containing the selected comdat function.
+ */
+struct gcov_fn_info {
+   const struct gcov_info *key;
+   unsigned int ident;
+   unsigned int lineno_checksum;
+   unsigned int cfg_checksum;
+   struct gcov_ctr_info ctrs[0];
+};
+
+/**
+ * struct gcov_info - profiling data per object file
+ * @version: gcov version magic indicating the gcc version used for compilation
+ * @next: list head for a singly-linked list
+ * @stamp: uniquifying time stamp
+ * @filename: name of the associated gcov data file
+ * @merge: merge functions (null for unused counter type)
+ * @n_functions: number of instrumented functions
+ * @functions: pointer to pointers to function information
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the next pointer.
+ */
+struct gcov_info {
+   unsigned int version;
+   struct gcov_info *next;
+   unsigned int stamp;
+   const char *filename;
+   void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int);
+   unsigned int n_functions;
+   struct gcov_fn_info **functions;
+};
+
+/**
+ * gcov_info_filename - return info filename
+ * @info: profiling data set
+ */
+const char *gcov_info_filename(struct gcov_info *info)
+{
+   return info-filename;
+}
+
+/**
+ * gcov_info_version - return info version
+ * @info: profiling data set
+ */
+unsigned int gcov_info_version(struct gcov_info *info)
+{
+   return info-version;
+}
+
+/**
+ * gcov_info_next - return next profiling data set
+ * @info: profiling data set
+ *
+ * Returns next gcov_info following @info or first gcov_info in the chain if
+ * @info is %NULL.
+ */
+struct gcov_info *gcov_info_next(struct gcov_info *info)
+{
+   if (!info)
+   return gcov_info_head;
+
+   return info-next

[PATCH v2 4/4] kernel: add support for init_array constructors

2013-09-04 Thread Frantisek Hrbata
This adds the .init_array section as yet another section with constructors. This
is needed because gcc could add __gcov_init calls to .init_array or .ctors
section, depending on gcc version.

v2: - reuse mod-ctors for .init_array section for modules, because gcc uses
  .ctors or .init_array, but not both at the same time

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 include/asm-generic/vmlinux.lds.h | 1 +
 kernel/module.c   | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 69732d2..c55d8d9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -468,6 +468,7 @@
 #define KERNEL_CTORS() . = ALIGN(8);  \
VMLINUX_SYMBOL(__ctors_start) = .; \
*(.ctors)  \
+   *(.init_array) \
VMLINUX_SYMBOL(__ctors_end) = .;
 #else
 #define KERNEL_CTORS()
diff --git a/kernel/module.c b/kernel/module.c
index 2069158..bbbd953 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2760,6 +2760,9 @@ static void find_module_sections(struct module *mod, 
struct load_info *info)
 #ifdef CONFIG_CONSTRUCTORS
mod-ctors = section_objs(info, .ctors,
  sizeof(*mod-ctors), mod-num_ctors);
+   if (!mod-ctors)
+   mod-ctors = section_objs(info, .init_array,
+   sizeof(*mod-ctors), mod-num_ctors);
 #endif
 
 #ifdef CONFIG_TRACEPOINTS
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 1/4] gcov: move gcov structs definitions to a gcc version specific file

2013-09-04 Thread Frantisek Hrbata
Since also the gcov structures(gcov_info, gcov_fn_info, gcov_ctr_info) can
change between gcc releases, as shown in gcc 4.7, they cannot be defined in a
common header and need to be moved to a specific gcc implemention file. This
also requires to make the gcov_info structure opaque for the common code and to
introduce simple helpers for accessing data inside gcov_info.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 kernel/gcov/base.c|  26 ++--
 kernel/gcov/fs.c  |  27 ++--
 kernel/gcov/gcc_3_4.c | 115 ++
 kernel/gcov/gcov.h|  65 +---
 4 files changed, 153 insertions(+), 80 deletions(-)

diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c
index 9b22d03..912576a 100644
--- a/kernel/gcov/base.c
+++ b/kernel/gcov/base.c
@@ -20,7 +20,6 @@
 #include linux/mutex.h
 #include gcov.h
 
-static struct gcov_info *gcov_info_head;
 static int gcov_events_enabled;
 static DEFINE_MUTEX(gcov_lock);
 
@@ -34,7 +33,7 @@ void __gcov_init(struct gcov_info *info)
 
mutex_lock(gcov_lock);
if (gcov_version == 0) {
-   gcov_version = info-version;
+   gcov_version = gcov_info_version(info);
/*
 * Printing gcc's version magic may prove useful for debugging
 * incompatibility reports.
@@ -45,8 +44,7 @@ void __gcov_init(struct gcov_info *info)
 * Add new profiling data structure to list and inform event
 * listener.
 */
-   info-next = gcov_info_head;
-   gcov_info_head = info;
+   gcov_info_link(info);
if (gcov_events_enabled)
gcov_event(GCOV_ADD, info);
mutex_unlock(gcov_lock);
@@ -91,13 +89,15 @@ EXPORT_SYMBOL(__gcov_merge_delta);
  */
 void gcov_enable_events(void)
 {
-   struct gcov_info *info;
+   struct gcov_info *info = NULL;
 
mutex_lock(gcov_lock);
gcov_events_enabled = 1;
+
/* Perform event callback for previously registered entries. */
-   for (info = gcov_info_head; info; info = info-next)
+   while ((info = gcov_info_next(info)))
gcov_event(GCOV_ADD, info);
+
mutex_unlock(gcov_lock);
 }
 
@@ -112,25 +112,23 @@ static int gcov_module_notifier(struct notifier_block 
*nb, unsigned long event,
void *data)
 {
struct module *mod = data;
-   struct gcov_info *info;
-   struct gcov_info *prev;
+   struct gcov_info *info = NULL;
+   struct gcov_info *prev = NULL;
 
if (event != MODULE_STATE_GOING)
return NOTIFY_OK;
mutex_lock(gcov_lock);
-   prev = NULL;
+
/* Remove entries located in module from linked list. */
-   for (info = gcov_info_head; info; info = info-next) {
+   while ((info = gcov_info_next(info))) {
if (within(info, mod-module_core, mod-core_size)) {
-   if (prev)
-   prev-next = info-next;
-   else
-   gcov_info_head = info-next;
+   gcov_info_unlink(prev, info);
if (gcov_events_enabled)
gcov_event(GCOV_REMOVE, info);
} else
prev = info;
}
+
mutex_unlock(gcov_lock);
 
return NOTIFY_OK;
diff --git a/kernel/gcov/fs.c b/kernel/gcov/fs.c
index 9bd0934..27e12ce 100644
--- a/kernel/gcov/fs.c
+++ b/kernel/gcov/fs.c
@@ -242,7 +242,7 @@ static struct gcov_node *get_node_by_name(const char *name)
 
list_for_each_entry(node, all_head, all) {
info = get_node_info(node);
-   if (info  (strcmp(info-filename, name) == 0))
+   if (info  (strcmp(gcov_info_filename(info), name) == 0))
return node;
}
 
@@ -279,7 +279,7 @@ static ssize_t gcov_seq_write(struct file *file, const char 
__user *addr,
seq = file-private_data;
info = gcov_iter_get_info(seq-private);
mutex_lock(node_lock);
-   node = get_node_by_name(info-filename);
+   node = get_node_by_name(gcov_info_filename(info));
if (node) {
/* Reset counts or remove node for unloaded modules. */
if (node-num_loaded == 0)
@@ -376,8 +376,9 @@ static void add_links(struct gcov_node *node, struct dentry 
*parent)
if (!node-links)
return;
for (i = 0; i  num; i++) {
-   target = get_link_target(get_node_info(node)-filename,
-gcov_link[i]);
+   target = get_link_target(
+   gcov_info_filename(get_node_info(node)),
+   gcov_link[i]);
if (!target)
goto out_err;
basename = strrchr(target, '/');
@@ -576,7 +577,7 @@ static void add_node(struct gcov_info *info

[PATCH v2 0/4] add support for gcov format introduced in gcc 4.7

2013-09-04 Thread Frantisek Hrbata
This is an attempt to bring support for modified gcov format in gcc 4.7 to
the kernel. It tries to leverage the existing layout/abstraction, which was
designed keeping in mind that the gcov format could change, but some changes had
to be make. Mostly because the current model does not take into account that
even the core gcov structures, like gcov_info, could change. One part that could
be problematic is the addition of the .init_array section for constructors.

Tested with lcov and seems to be working fine, giving similar results as for the
older format.

v2: Included suggestions/code provided by Peter Oberparleiter. Detailed
description in patches.

Frantisek Hrbata (4):
  gcov: move gcov structs definitions to a gcc version specific file
  gcov: add support for gcc 4.7 gcov format
  gcov: compile specific gcov implementation based on gcc version
  kernel: add support for init_array constructors

 Documentation/gcov.txt|   4 +
 include/asm-generic/vmlinux.lds.h |   1 +
 kernel/gcov/Kconfig   |  30 ++
 kernel/gcov/Makefile  |  32 ++-
 kernel/gcov/base.c|  32 ++-
 kernel/gcov/fs.c  |  27 +-
 kernel/gcov/gcc_3_4.c | 115 
 kernel/gcov/gcc_4_7.c | 562 ++
 kernel/gcov/gcov.h|  65 +
 kernel/module.c   |   3 +
 10 files changed, 790 insertions(+), 81 deletions(-)
 create mode 100644 kernel/gcov/gcc_4_7.c

-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-28 Thread Frantisek Hrbata
On Wed, Aug 28, 2013 at 03:46:05PM +0200, Peter Oberparleiter wrote:
> On 27.08.2013 15:34, Frantisek Hrbata wrote:
> > On Mon, Aug 26, 2013 at 04:14:07PM +0200, Peter Oberparleiter wrote:
> >> On 24.08.2013 21:44, Frantisek Hrbata wrote:
> >>> On Fri, Aug 23, 2013 at 05:21:12PM +0200, Peter Oberparleiter wrote:
> >>>> On 23.08.2013 17:15, Peter Oberparleiter wrote:
> >>>>> On 23.08.2013 10:39, Frantisek Hrbata wrote:
> >>>>>> Compile the correct gcov implementation file for a specific gcc 
> >>>>>> version. In
> >>>>>> the future, if another file is added, the conditions will need to be 
> >>>>>> somehow
> >>>>>> adjusted to if-elif-else case, but at this point the simple 
> >>>>>> cc-ifversion should
> >>>>>> be enough.
> >>>>
> >>>> As promised, I'm also adding the patch that makes the format-specific 
> >>>> part
> >>>> of gcov-kernel a loadable kernel module:
> >>>>
> >>>> ---
> >>>> kernel: gcov: make format-specific code loadable
> >>>>
> >>>> Turn the format-specific part of gcov-kernel into a loadable kernel
> >>>> module. This enables the use of gcov-kernel with kernel modules
> >>>> that were compiled with a version of GCC that produces a different
> >>>> gcov format when compared to the version of GCC that was used to
> >>>> compile the kernel.
> >>>
> >>> If I understand it correctly, this would mean that you will be able to 
> >>> use only
> >>> one implementation of gcov format at the time. Meaning you will be able 
> >>> to get
> >>> coverage data for module, but not for kernel if it was compiled with 
> >>> different
> >>> gcc(gcda format). This is probably ok if you work only on your module, 
> >>> but I'm
> >>> not sure this is generally the right approach. In this case I would 
> >>> probably
> >>> rather see some support for more gcov formats at the same time(e.g. set of
> >>> callback operations per gcov version). Again I'm probably missing 
> >>> something, but
> >>> I still cannot see reason why to add such feature. If you want gcov 
> >>> support just
> >>> compile your kernel and modules with the same gcc version(gcda format). 
> >>> But if
> >>> this is really needed maybe it would be better to consider some parallel 
> >>> support
> >>> for more gcov formats based on the gcov_info version.
> >>
> >> The callback approach has other drawbacks (see previous mail).
> > 
> > Agreed, I did not realized these problems for the first time when I was 
> > thinking
> > about the callback approach.
> > 
> >>
> >>> Would it be possible to add support for the modified gcc 4.7 gcov format 
> >>> and
> >>> deal with this later? I can incorporate your changes: iter to use buffer,
> >>> .init_array for modules and possibility to explicitly select the gcda 
> >>> format.
> >>> In this case we will have at least the basic support in kernel. This is 
> >>> just me
> >>> thinking out loud.
> >>
> >> I think that's an approach I can live with. Maybe the need for a 
> >> multi-version
> >> support will surface again later in a more refined form, but until then 
> >> there
> >> should be no reason to delay base GCC 4.7 support any further.
> > 
> > Great. I can incorporate the changes you proposed and post V2. Or do you 
> > prefer
> > to post it by your self? Based on the info and patches you already provided 
> > I
> > guess you already have something ready. Simply what suits you best :).
> 
> If it's not too much hassle, I'd prefer that you post V2 of your patches. Also
> I guess it would make sense to put Andrew Morton on CC since the initial
> gcov-patches were picked up by him.

Ok, no problem. I will prepare v2. Again many thanks Peter for your help and
input. It's really appreciated.

> 
> -- 
> Peter Oberparleiter
> Linux on System z Development - IBM Germany
> 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-28 Thread Frantisek Hrbata
On Wed, Aug 28, 2013 at 03:46:05PM +0200, Peter Oberparleiter wrote:
 On 27.08.2013 15:34, Frantisek Hrbata wrote:
  On Mon, Aug 26, 2013 at 04:14:07PM +0200, Peter Oberparleiter wrote:
  On 24.08.2013 21:44, Frantisek Hrbata wrote:
  On Fri, Aug 23, 2013 at 05:21:12PM +0200, Peter Oberparleiter wrote:
  On 23.08.2013 17:15, Peter Oberparleiter wrote:
  On 23.08.2013 10:39, Frantisek Hrbata wrote:
  Compile the correct gcov implementation file for a specific gcc 
  version. In
  the future, if another file is added, the conditions will need to be 
  somehow
  adjusted to if-elif-else case, but at this point the simple 
  cc-ifversion should
  be enough.
 
  As promised, I'm also adding the patch that makes the format-specific 
  part
  of gcov-kernel a loadable kernel module:
 
  ---
  kernel: gcov: make format-specific code loadable
 
  Turn the format-specific part of gcov-kernel into a loadable kernel
  module. This enables the use of gcov-kernel with kernel modules
  that were compiled with a version of GCC that produces a different
  gcov format when compared to the version of GCC that was used to
  compile the kernel.
 
  If I understand it correctly, this would mean that you will be able to 
  use only
  one implementation of gcov format at the time. Meaning you will be able 
  to get
  coverage data for module, but not for kernel if it was compiled with 
  different
  gcc(gcda format). This is probably ok if you work only on your module, 
  but I'm
  not sure this is generally the right approach. In this case I would 
  probably
  rather see some support for more gcov formats at the same time(e.g. set of
  callback operations per gcov version). Again I'm probably missing 
  something, but
  I still cannot see reason why to add such feature. If you want gcov 
  support just
  compile your kernel and modules with the same gcc version(gcda format). 
  But if
  this is really needed maybe it would be better to consider some parallel 
  support
  for more gcov formats based on the gcov_info version.
 
  The callback approach has other drawbacks (see previous mail).
  
  Agreed, I did not realized these problems for the first time when I was 
  thinking
  about the callback approach.
  
 
  Would it be possible to add support for the modified gcc 4.7 gcov format 
  and
  deal with this later? I can incorporate your changes: iter to use buffer,
  .init_array for modules and possibility to explicitly select the gcda 
  format.
  In this case we will have at least the basic support in kernel. This is 
  just me
  thinking out loud.
 
  I think that's an approach I can live with. Maybe the need for a 
  multi-version
  support will surface again later in a more refined form, but until then 
  there
  should be no reason to delay base GCC 4.7 support any further.
  
  Great. I can incorporate the changes you proposed and post V2. Or do you 
  prefer
  to post it by your self? Based on the info and patches you already provided 
  I
  guess you already have something ready. Simply what suits you best :).
 
 If it's not too much hassle, I'd prefer that you post V2 of your patches. Also
 I guess it would make sense to put Andrew Morton on CC since the initial
 gcov-patches were picked up by him.

Ok, no problem. I will prepare v2. Again many thanks Peter for your help and
input. It's really appreciated.

 
 -- 
 Peter Oberparleiter
 Linux on System z Development - IBM Germany
 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 2/4] gcov: add support for gcc 4.7 gcov format

2013-08-27 Thread Frantisek Hrbata
On Mon, Aug 26, 2013 at 02:45:10PM +0200, Peter Oberparleiter wrote:
> On 23.08.2013 23:00, Frantisek Hrbata wrote:
> > On Fri, Aug 23, 2013 at 05:12:19PM +0200, Peter Oberparleiter wrote:
> >> On 23.08.2013 10:39, Frantisek Hrbata wrote:
> >>> The gcov in-memory format changed in gcc 4.7. The biggest change, which
> >>> requires this special implementation, is that gcov_info no longer contains
> >>> array of counters for each counter type for all functions and 
> >>> gcov_fn_info is
> >>> not used for mapping of function's counters to these arrays(offset). Now 
> >>> each
> >>> gcov_fn_info contans it's counters, which makes things a little bit 
> >>> easier.
> >>
> >> By now I've come to the conclusion that I may have over-engineered
> >> gcov_iter_next in the original GCC 3.4 implementation. This became 
> >> especially
> >> apparent when someone tried to adjust that code to also work with a 
> >> specific
> >> android GCC version - adding a simple field to the output file format 
> >> required
> >> major complex changes.
> >>
> >> Therefore in my version of the GCC 4.7 support, I opted to replace this 
> >> logic
> >> with the simpler approach of generating the gcov data file in-memory during
> >> open (gcov_iter_new) and reducing gcov_iter_next/gcov_iter_write to simple
> >> copy-from-buffer functions.
> > 
> > Yes, this seems reasonable and much easier approach to me, but we will end 
> > up
> > with three copies of one gcov(gcda) file data in memory: data from gcc, our
> > buffer and the buffer in seq file. But I guess this is not a big problem,
> > unless someone opens a huge amount of gcda files in parallel. Generally I
> > like this idea. This will be also probably faster then writing 1 or 2 ints 
> > per
> > one iter write.
> 
> You're right about the data being in multiple buffers for the time that a 
> .gcda
> file is opened, but as you mentioned, this shouldn't be a problem since 
> usually
> only one .gcda file is open at a time. Also the reduction in code complexity 
> is
> in my opinion well worth it.

agreed

> 
> >> Since I can see the need to change the format code again in the future,
> >> I think it would be easier to simplify this part of the code 
> >> correspondingly.
> >> I'm adding my version of this part of the implementation as discussion 
> >> input
> >> below (the relevant part starts at convert_to_gcda()).
> > 
> > I have really only two nits to the code(please see below). I spent some time
> > checking the new seq/iter implementation and it seems ok to me. Generally I 
> > like
> > how simple this change is done.
> > 
> >>
> >> ---
> >> kernel: gcov: add support for gcc 4.7 gcov format
> >>
> >> GCC 4.7 changed the format of gcov related data structures, both
> >> on-disk and in memory. Add support for the new format.
> >>
> >> Signed-off-by: Peter Oberparleiter 
> >> ---
> >>  kernel/gcov/Makefile  |4
> >>  kernel/gcov/gcc_4_7.c |  510 
> >> ++
> >>  2 files changed, 513 insertions(+), 1 deletion(-)
> >>
> >> --- a/kernel/gcov/Makefile
> >> +++ b/kernel/gcov/Makefile
> >> @@ -1,3 +1,5 @@
> >>  ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
> >>
> >> -obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
> >> +obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
> >> +obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -lt, 0407, gcc_3_4.o)
> >> +obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -ge, 0407, gcc_4_7.o)
> >> --- /dev/null
> >> +++ b/kernel/gcov/gcc_4_7.c
> >> @@ -0,0 +1,510 @@
> >> +/*
> >> + *  This code provides functions to handle gcc's profiling data format
> >> + *  introduced with gcc 4.7. Future versions of gcc may change the gcov
> >> + *  format (as happened before), so all format-specific information needs
> >> + *  to be kept modular and easily exchangeable.
> >> + *
> >> + *  This file is based on gcc-internal definitions. Functions and data
> >> + *  structures are defined to be compatible with gcc counterparts.
> >> + *  For a better understanding, refer to gcc source: gcc/gcov-io.h.
> >> + *
> >> + *Copyright IBM Corp. 2013
> >> + *Author(s): Peter Oberparleiter 
> >> + *
> >> + *Uses gcc-internal 

Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-27 Thread Frantisek Hrbata
On Mon, Aug 26, 2013 at 04:14:07PM +0200, Peter Oberparleiter wrote:
> On 24.08.2013 21:44, Frantisek Hrbata wrote:
> > On Fri, Aug 23, 2013 at 05:21:12PM +0200, Peter Oberparleiter wrote:
> >> On 23.08.2013 17:15, Peter Oberparleiter wrote:
> >>> On 23.08.2013 10:39, Frantisek Hrbata wrote:
> >>>> Compile the correct gcov implementation file for a specific gcc version. 
> >>>> In
> >>>> the future, if another file is added, the conditions will need to be 
> >>>> somehow
> >>>> adjusted to if-elif-else case, but at this point the simple cc-ifversion 
> >>>> should
> >>>> be enough.
> >>
> >> As promised, I'm also adding the patch that makes the format-specific part
> >> of gcov-kernel a loadable kernel module:
> >>
> >> ---
> >> kernel: gcov: make format-specific code loadable
> >>
> >> Turn the format-specific part of gcov-kernel into a loadable kernel
> >> module. This enables the use of gcov-kernel with kernel modules
> >> that were compiled with a version of GCC that produces a different
> >> gcov format when compared to the version of GCC that was used to
> >> compile the kernel.
> > 
> > If I understand it correctly, this would mean that you will be able to use 
> > only
> > one implementation of gcov format at the time. Meaning you will be able to 
> > get
> > coverage data for module, but not for kernel if it was compiled with 
> > different
> > gcc(gcda format). This is probably ok if you work only on your module, but 
> > I'm
> > not sure this is generally the right approach. In this case I would probably
> > rather see some support for more gcov formats at the same time(e.g. set of
> > callback operations per gcov version). Again I'm probably missing 
> > something, but
> > I still cannot see reason why to add such feature. If you want gcov support 
> > just
> > compile your kernel and modules with the same gcc version(gcda format). But 
> > if
> > this is really needed maybe it would be better to consider some parallel 
> > support
> > for more gcov formats based on the gcov_info version.
> 
> The callback approach has other drawbacks (see previous mail).

Agreed, I did not realized these problems for the first time when I was thinking
about the callback approach.

> 
> > Would it be possible to add support for the modified gcc 4.7 gcov format and
> > deal with this later? I can incorporate your changes: iter to use buffer,
> > .init_array for modules and possibility to explicitly select the gcda 
> > format.
> > In this case we will have at least the basic support in kernel. This is 
> > just me
> > thinking out loud.
> 
> I think that's an approach I can live with. Maybe the need for a multi-version
> support will surface again later in a more refined form, but until then there
> should be no reason to delay base GCC 4.7 support any further.

Great. I can incorporate the changes you proposed and post V2. Or do you prefer
to post it by your self? Based on the info and patches you already provided I
guess you already have something ready. Simply what suits you best :).

Many thanks Peter

> 
> 
> -- 
> Peter Oberparleiter
> Linux on System z Development - IBM Germany
> 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-27 Thread Frantisek Hrbata
On Mon, Aug 26, 2013 at 02:56:04PM +0200, Peter Oberparleiter wrote:
> On 24.08.2013 21:12, Frantisek Hrbata wrote:
> > On Fri, Aug 23, 2013 at 05:15:19PM +0200, Peter Oberparleiter wrote:
> >> Also it is my understanding that there are some distribution-specific 
> >> versions
> >> of GCC that include the 4.7. gcov format code but report GCC version 4.6. 
> >> With
> >> the auto-detection code implemented like this, gcov-kernel won't work 
> >> correctly.
> >> For that purpose I've implemented a configuration option to allow users to
> >> force a specific version of gcov format.
> > 
> > Ah, I was not aware of this inconsistency in versioning. This raises a 
> > question
> > if it would not be better to deal directly with version in the gcov_info
> > instead of these config options. This would of course mean some kind of gcov
> > operations callbacks per gcov version(you already mentioned the file
> > operations approach).
> 
> Using the version information from gcov_info would make the support easier to 
> use,
> but I see 2 problems with this approach:
> 
> 1. How do you decide which version applies to any given gcov_info struct?
> Since gcov_info is opaque this would require a compatibility check inside
> the version specific code. And each version specific code assumes a different
> layout for gcov_info, so in an (unlikely) worst case scenario, the 
> compatibility
> check might fail (false positive or access beyond end of data structure) due 
> to
> these differences
> 
> 2. There's no easy way to "force" compatibility, for example in the case
> mentioned above where a GCC 4.6 produces GCC 4.7 gcov format data.

Yes, you are right of course. Problem imho is that user-space program is always
linked with the correct libgcov. Meaning the gcov structures and the code
dumping the gcda are tied and known(compatible) at the compilation(link) time.
So there is no need to deal with different gcov_info layouts. After a little bit
more thinking the "per gcov_info version callbacks" does not seem as the right
way to go anymore. At this point I think the easier and probably the safest way
would be the module approach as you originally proposed. Anyway I would leave
this aside for now and we will see if someone requests this in the future. 

For now I would propose to simply support only one gcov version at the time.
Meaning if you want to use gcov, compile your kernel and modules with the same
gcc version. And add the possibility to explicitly select gcov version(3.4 or
4.7) during configuration as you proposed in your patch.

IMHO this should be a good start :)

> 
> >> I'm attaching the corresponding patch below:
> >>
> >> ---
> >> kernel: gcov: make data format configurable
> >>
> >> Make the format of the generated gcov data configurable. This may be
> >> required for example for pre-4.7 GCCs that contain the 4.7 gcov data
> >> format changes.
> >>
> >> Signed-off-by: Peter Oberparleiter 
> >> ---
> >>  kernel/gcov/Kconfig  |   30 ++
> >>  kernel/gcov/Makefile |   21 +++--
> >>  2 files changed, 49 insertions(+), 2 deletions(-)
> >>
> >> --- a/kernel/gcov/Kconfig
> >> +++ b/kernel/gcov/Kconfig
> >> @@ -46,4 +46,34 @@ config GCOV_PROFILE_ALL
> >>larger and run slower. Also be sure to exclude files from profiling
> >>which are not linked to the kernel image to prevent linker errors.
> >>
> >> +choice
> >> +  prompt "Specify GCOV format"
> >> +  depends on GCOV_KERNEL
> >> +  default GCOV_FORMAT_AUTODETECT
> >> +  ---help---
> >> +  The gcov format is usually determined by the GCC version, but there are
> >> +  exceptions where format changes are integrated in lower-version GCCs.
> >> +  In such a case use this option to adjust the format used in the kernel
> >> +  accordingly.
> >> +
> >> +  If unsure, choose "Autodetect".
> >> +
> >> +config GCOV_FORMAT_AUTODETECT
> >> +  bool "Autodetect"
> >> +  ---help---
> >> +  Select this option to use the format that corresponds to your GCC
> >> +  version.
> >> +
> >> +config GCOV_FORMAT_3_4
> >> +  bool "GCC 3.4 format"
> >> +  ---help---
> >> +  Select this option to use the format defined by GCC 3.4.
> >> +
> >> +config GCOV_FORMAT_4_7
> >> +  bool "GCC 4.7 format"
> >> +  ---help---
> >> +  Select this option to use the format defined by GCC 4.7.

Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-27 Thread Frantisek Hrbata
On Mon, Aug 26, 2013 at 02:56:04PM +0200, Peter Oberparleiter wrote:
 On 24.08.2013 21:12, Frantisek Hrbata wrote:
  On Fri, Aug 23, 2013 at 05:15:19PM +0200, Peter Oberparleiter wrote:
  Also it is my understanding that there are some distribution-specific 
  versions
  of GCC that include the 4.7. gcov format code but report GCC version 4.6. 
  With
  the auto-detection code implemented like this, gcov-kernel won't work 
  correctly.
  For that purpose I've implemented a configuration option to allow users to
  force a specific version of gcov format.
  
  Ah, I was not aware of this inconsistency in versioning. This raises a 
  question
  if it would not be better to deal directly with version in the gcov_info
  instead of these config options. This would of course mean some kind of gcov
  operations callbacks per gcov version(you already mentioned the file
  operations approach).
 
 Using the version information from gcov_info would make the support easier to 
 use,
 but I see 2 problems with this approach:
 
 1. How do you decide which version applies to any given gcov_info struct?
 Since gcov_info is opaque this would require a compatibility check inside
 the version specific code. And each version specific code assumes a different
 layout for gcov_info, so in an (unlikely) worst case scenario, the 
 compatibility
 check might fail (false positive or access beyond end of data structure) due 
 to
 these differences
 
 2. There's no easy way to force compatibility, for example in the case
 mentioned above where a GCC 4.6 produces GCC 4.7 gcov format data.

Yes, you are right of course. Problem imho is that user-space program is always
linked with the correct libgcov. Meaning the gcov structures and the code
dumping the gcda are tied and known(compatible) at the compilation(link) time.
So there is no need to deal with different gcov_info layouts. After a little bit
more thinking the per gcov_info version callbacks does not seem as the right
way to go anymore. At this point I think the easier and probably the safest way
would be the module approach as you originally proposed. Anyway I would leave
this aside for now and we will see if someone requests this in the future. 

For now I would propose to simply support only one gcov version at the time.
Meaning if you want to use gcov, compile your kernel and modules with the same
gcc version. And add the possibility to explicitly select gcov version(3.4 or
4.7) during configuration as you proposed in your patch.

IMHO this should be a good start :)

 
  I'm attaching the corresponding patch below:
 
  ---
  kernel: gcov: make data format configurable
 
  Make the format of the generated gcov data configurable. This may be
  required for example for pre-4.7 GCCs that contain the 4.7 gcov data
  format changes.
 
  Signed-off-by: Peter Oberparleiter ober...@linux.vnet.ibm.com
  ---
   kernel/gcov/Kconfig  |   30 ++
   kernel/gcov/Makefile |   21 +++--
   2 files changed, 49 insertions(+), 2 deletions(-)
 
  --- a/kernel/gcov/Kconfig
  +++ b/kernel/gcov/Kconfig
  @@ -46,4 +46,34 @@ config GCOV_PROFILE_ALL
 larger and run slower. Also be sure to exclude files from profiling
 which are not linked to the kernel image to prevent linker errors.
 
  +choice
  +  prompt Specify GCOV format
  +  depends on GCOV_KERNEL
  +  default GCOV_FORMAT_AUTODETECT
  +  ---help---
  +  The gcov format is usually determined by the GCC version, but there are
  +  exceptions where format changes are integrated in lower-version GCCs.
  +  In such a case use this option to adjust the format used in the kernel
  +  accordingly.
  +
  +  If unsure, choose Autodetect.
  +
  +config GCOV_FORMAT_AUTODETECT
  +  bool Autodetect
  +  ---help---
  +  Select this option to use the format that corresponds to your GCC
  +  version.
  +
  +config GCOV_FORMAT_3_4
  +  bool GCC 3.4 format
  +  ---help---
  +  Select this option to use the format defined by GCC 3.4.
  +
  +config GCOV_FORMAT_4_7
  +  bool GCC 4.7 format
  +  ---help---
  +  Select this option to use the format defined by GCC 4.7.
  +
  +endchoice
  +
   endmenu
  --- a/kernel/gcov/Makefile
  +++ b/kernel/gcov/Makefile
  @@ -1,5 +1,22 @@
   ccflags-y := -DSRCTREE='$(srctree)' -DOBJTREE='$(objtree)'
 
  +# if-lt
  +# Usage VAR := $(call if-lt, $(a), $(b))
  +# Returns 1 if (a  b)
  +if-lt = $(shell [ $(1) -lt $(2) ]  echo 1)
  +
  +ifeq ($(CONFIG_GCOV_FORMAT_3_4),y)
  +  cc-ver := 0304
  +else ifeq ($(CONFIG_GCOV_FORMAT_4_7),y)
  +  cc-ver := 0407
  +else
  +  cc-ver := $(call cc-version)
  +endif
  +
   obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
  -obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -lt, 0407, gcc_3_4.o)
  -obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -ge, 0407, gcc_4_7.o)
  +
  +ifeq ($(call if-lt, $(cc-ver), 0407),1)
  +  obj-$(CONFIG_GCOV_KERNEL) += gcc_3_4.o
  +else
  +  obj-$(CONFIG_GCOV_KERNEL) += gcc_4_7.o
  +endif
 
 
  -- 
  Peter Oberparleiter
  Linux

Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-27 Thread Frantisek Hrbata
On Mon, Aug 26, 2013 at 04:14:07PM +0200, Peter Oberparleiter wrote:
 On 24.08.2013 21:44, Frantisek Hrbata wrote:
  On Fri, Aug 23, 2013 at 05:21:12PM +0200, Peter Oberparleiter wrote:
  On 23.08.2013 17:15, Peter Oberparleiter wrote:
  On 23.08.2013 10:39, Frantisek Hrbata wrote:
  Compile the correct gcov implementation file for a specific gcc version. 
  In
  the future, if another file is added, the conditions will need to be 
  somehow
  adjusted to if-elif-else case, but at this point the simple cc-ifversion 
  should
  be enough.
 
  As promised, I'm also adding the patch that makes the format-specific part
  of gcov-kernel a loadable kernel module:
 
  ---
  kernel: gcov: make format-specific code loadable
 
  Turn the format-specific part of gcov-kernel into a loadable kernel
  module. This enables the use of gcov-kernel with kernel modules
  that were compiled with a version of GCC that produces a different
  gcov format when compared to the version of GCC that was used to
  compile the kernel.
  
  If I understand it correctly, this would mean that you will be able to use 
  only
  one implementation of gcov format at the time. Meaning you will be able to 
  get
  coverage data for module, but not for kernel if it was compiled with 
  different
  gcc(gcda format). This is probably ok if you work only on your module, but 
  I'm
  not sure this is generally the right approach. In this case I would probably
  rather see some support for more gcov formats at the same time(e.g. set of
  callback operations per gcov version). Again I'm probably missing 
  something, but
  I still cannot see reason why to add such feature. If you want gcov support 
  just
  compile your kernel and modules with the same gcc version(gcda format). But 
  if
  this is really needed maybe it would be better to consider some parallel 
  support
  for more gcov formats based on the gcov_info version.
 
 The callback approach has other drawbacks (see previous mail).

Agreed, I did not realized these problems for the first time when I was thinking
about the callback approach.

 
  Would it be possible to add support for the modified gcc 4.7 gcov format and
  deal with this later? I can incorporate your changes: iter to use buffer,
  .init_array for modules and possibility to explicitly select the gcda 
  format.
  In this case we will have at least the basic support in kernel. This is 
  just me
  thinking out loud.
 
 I think that's an approach I can live with. Maybe the need for a multi-version
 support will surface again later in a more refined form, but until then there
 should be no reason to delay base GCC 4.7 support any further.

Great. I can incorporate the changes you proposed and post V2. Or do you prefer
to post it by your self? Based on the info and patches you already provided I
guess you already have something ready. Simply what suits you best :).

Many thanks Peter

 
 
 -- 
 Peter Oberparleiter
 Linux on System z Development - IBM Germany
 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 2/4] gcov: add support for gcc 4.7 gcov format

2013-08-27 Thread Frantisek Hrbata
On Mon, Aug 26, 2013 at 02:45:10PM +0200, Peter Oberparleiter wrote:
 On 23.08.2013 23:00, Frantisek Hrbata wrote:
  On Fri, Aug 23, 2013 at 05:12:19PM +0200, Peter Oberparleiter wrote:
  On 23.08.2013 10:39, Frantisek Hrbata wrote:
  The gcov in-memory format changed in gcc 4.7. The biggest change, which
  requires this special implementation, is that gcov_info no longer contains
  array of counters for each counter type for all functions and 
  gcov_fn_info is
  not used for mapping of function's counters to these arrays(offset). Now 
  each
  gcov_fn_info contans it's counters, which makes things a little bit 
  easier.
 
  By now I've come to the conclusion that I may have over-engineered
  gcov_iter_next in the original GCC 3.4 implementation. This became 
  especially
  apparent when someone tried to adjust that code to also work with a 
  specific
  android GCC version - adding a simple field to the output file format 
  required
  major complex changes.
 
  Therefore in my version of the GCC 4.7 support, I opted to replace this 
  logic
  with the simpler approach of generating the gcov data file in-memory during
  open (gcov_iter_new) and reducing gcov_iter_next/gcov_iter_write to simple
  copy-from-buffer functions.
  
  Yes, this seems reasonable and much easier approach to me, but we will end 
  up
  with three copies of one gcov(gcda) file data in memory: data from gcc, our
  buffer and the buffer in seq file. But I guess this is not a big problem,
  unless someone opens a huge amount of gcda files in parallel. Generally I
  like this idea. This will be also probably faster then writing 1 or 2 ints 
  per
  one iter write.
 
 You're right about the data being in multiple buffers for the time that a 
 .gcda
 file is opened, but as you mentioned, this shouldn't be a problem since 
 usually
 only one .gcda file is open at a time. Also the reduction in code complexity 
 is
 in my opinion well worth it.

agreed

 
  Since I can see the need to change the format code again in the future,
  I think it would be easier to simplify this part of the code 
  correspondingly.
  I'm adding my version of this part of the implementation as discussion 
  input
  below (the relevant part starts at convert_to_gcda()).
  
  I have really only two nits to the code(please see below). I spent some time
  checking the new seq/iter implementation and it seems ok to me. Generally I 
  like
  how simple this change is done.
  
 
  ---
  kernel: gcov: add support for gcc 4.7 gcov format
 
  GCC 4.7 changed the format of gcov related data structures, both
  on-disk and in memory. Add support for the new format.
 
  Signed-off-by: Peter Oberparleiter ober...@linux.vnet.ibm.com
  ---
   kernel/gcov/Makefile  |4
   kernel/gcov/gcc_4_7.c |  510 
  ++
   2 files changed, 513 insertions(+), 1 deletion(-)
 
  --- a/kernel/gcov/Makefile
  +++ b/kernel/gcov/Makefile
  @@ -1,3 +1,5 @@
   ccflags-y := -DSRCTREE='$(srctree)' -DOBJTREE='$(objtree)'
 
  -obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
  +obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
  +obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -lt, 0407, gcc_3_4.o)
  +obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -ge, 0407, gcc_4_7.o)
  --- /dev/null
  +++ b/kernel/gcov/gcc_4_7.c
  @@ -0,0 +1,510 @@
  +/*
  + *  This code provides functions to handle gcc's profiling data format
  + *  introduced with gcc 4.7. Future versions of gcc may change the gcov
  + *  format (as happened before), so all format-specific information needs
  + *  to be kept modular and easily exchangeable.
  + *
  + *  This file is based on gcc-internal definitions. Functions and data
  + *  structures are defined to be compatible with gcc counterparts.
  + *  For a better understanding, refer to gcc source: gcc/gcov-io.h.
  + *
  + *Copyright IBM Corp. 2013
  + *Author(s): Peter Oberparleiter ober...@linux.vnet.ibm.com
  + *
  + *Uses gcc-internal data definitions.
  + */
  +
  +#include linux/errno.h
  +#include linux/slab.h
  +#include linux/string.h
  +#include linux/seq_file.h
  +#include linux/vmalloc.h
  +#include linux/types.h
  +#include gcov.h
  +
  +/*
  + * Profiling data types used for gcc 4.7 and above - these are defined by
  + * gcc and need to be kept as close to the original definition as 
  possible to
  + * remain compatible.
  + */
  +#define GCOV_COUNTERS 8
  +#define GCOV_DATA_MAGIC   ((unsigned int) 0x67636461)
  +#define GCOV_TAG_FUNCTION ((unsigned int) 0x0100)
  +#define GCOV_TAG_COUNTER_BASE ((unsigned int) 0x01a1)
  +#define GCOV_TAG_FOR_COUNTER(count)   
  \
  +  (GCOV_TAG_COUNTER_BASE + ((unsigned int) (count)  17))
  +
  +#if BITS_PER_LONG = 64
  +typedef long gcov_type;
  +#else
  +typedef long long gcov_type;
  +#endif
  +
  +/**
  + * struct gcov_ctr_info - profiling data per function and counter type
  + * @num: number of counter values

Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-24 Thread Frantisek Hrbata
On Fri, Aug 23, 2013 at 05:21:12PM +0200, Peter Oberparleiter wrote:
> On 23.08.2013 17:15, Peter Oberparleiter wrote:
> > On 23.08.2013 10:39, Frantisek Hrbata wrote:
> >> Compile the correct gcov implementation file for a specific gcc version. In
> >> the future, if another file is added, the conditions will need to be 
> >> somehow
> >> adjusted to if-elif-else case, but at this point the simple cc-ifversion 
> >> should
> >> be enough.
> 
> As promised, I'm also adding the patch that makes the format-specific part
> of gcov-kernel a loadable kernel module:
> 
> ---
> kernel: gcov: make format-specific code loadable
> 
> Turn the format-specific part of gcov-kernel into a loadable kernel
> module. This enables the use of gcov-kernel with kernel modules
> that were compiled with a version of GCC that produces a different
> gcov format when compared to the version of GCC that was used to
> compile the kernel.

If I understand it correctly, this would mean that you will be able to use only
one implementation of gcov format at the time. Meaning you will be able to get
coverage data for module, but not for kernel if it was compiled with different
gcc(gcda format). This is probably ok if you work only on your module, but I'm
not sure this is generally the right approach. In this case I would probably
rather see some support for more gcov formats at the same time(e.g. set of
callback operations per gcov version). Again I'm probably missing something, but
I still cannot see reason why to add such feature. If you want gcov support just
compile your kernel and modules with the same gcc version(gcda format). But if
this is really needed maybe it would be better to consider some parallel support
for more gcov formats based on the gcov_info version.

Would it be possible to add support for the modified gcc 4.7 gcov format and
deal with this later? I can incorporate your changes: iter to use buffer,
.init_array for modules and possibility to explicitly select the gcda format.
In this case we will have at least the basic support in kernel. This is just me
thinking out loud.

Many thanks Peter!

> 
> Signed-off-by: Peter Oberparleiter 
> ---
>  kernel/gcov/Kconfig  |   19 +--
>  kernel/gcov/Makefile |7 ---
>  2 files changed, 21 insertions(+), 5 deletions(-)
> 
> --- a/kernel/gcov/Kconfig
> +++ b/kernel/gcov/Kconfig
> @@ -29,8 +29,23 @@ config GCOV_KERNEL
>   and:
>   GCOV_PROFILE := n
> 
> - Note that the debugfs filesystem has to be mounted to access
> - profiling data.
> + Note that GCOV_KERNEL_FS has to specified as well and the debugfs
> + filesystem has to be mounted to access profiling data.
> +
> +config GCOV_KERNEL_FS
> + tristate "Provide gcov data files in debugfs"
> + depends on GCOV_KERNEL
> + default y
> + ---help---
> + Make profiling data available in debugfs at /sys/kernel/debug/gcov.
> +
> + Say M if you want to enable collecting coverage data for kernel modules
> + which are compiled using a gcc version different from the one that
> + was used to compile the kernel. In that case, re-compile the gcov
> + kernel module with corresponding format support and load that module
> + instead.
> +
> + If unsure, say Y.
> 
>  config GCOV_PROFILE_ALL
>   bool "Profile entire Kernel"
> --- a/kernel/gcov/Makefile
> +++ b/kernel/gcov/Makefile
> @@ -13,10 +13,11 @@ else
>cc-ver := $(call cc-version)
>  endif
> 
> -obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
> +obj-$(CONFIG_GCOV_KERNEL) += base.o
> +obj-$(CONFIG_GCOV_KERNEL_FS) += gcov.o
> 
>  ifeq ($(call if-lt, $(cc-ver), 0407),1)
> -  obj-$(CONFIG_GCOV_KERNEL) += gcc_3_4.o
> +  gcov-objs += fs.o gcc_3_4.o
>  else
> -  obj-$(CONFIG_GCOV_KERNEL) += gcc_4_7.o
> +  gcov-objs += fs.o gcc_4_7.o
>  endif
> 
> -- 
> Peter Oberparleiter
> Linux on System z Development - IBM Germany
> 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-24 Thread Frantisek Hrbata
On Fri, Aug 23, 2013 at 05:15:19PM +0200, Peter Oberparleiter wrote:
> On 23.08.2013 10:39, Frantisek Hrbata wrote:
> > Compile the correct gcov implementation file for a specific gcc version. In
> > the future, if another file is added, the conditions will need to be somehow
> > adjusted to if-elif-else case, but at this point the simple cc-ifversion 
> > should
> > be enough.
> 
> Looks good, though I think this could be merged into the main 4.7 format 
> patch,
> since without it, the 4.7 code will never be reached.

Sure, I can merge these two patches.

> 
> Also it is my understanding that there are some distribution-specific versions
> of GCC that include the 4.7. gcov format code but report GCC version 4.6. With
> the auto-detection code implemented like this, gcov-kernel won't work 
> correctly.
> For that purpose I've implemented a configuration option to allow users to
> force a specific version of gcov format.

Ah, I was not aware of this inconsistency in versioning. This raises a question
if it would not be better to deal directly with version in the gcov_info
instead of these config options. This would of course mean some kind of gcov
operations callbacks per gcov version(you already mentioned the file
operations approach).

> 
> I'm attaching the corresponding patch below:
> 
> ---
> kernel: gcov: make data format configurable
> 
> Make the format of the generated gcov data configurable. This may be
> required for example for pre-4.7 GCCs that contain the 4.7 gcov data
> format changes.
> 
> Signed-off-by: Peter Oberparleiter 
> ---
>  kernel/gcov/Kconfig  |   30 ++
>  kernel/gcov/Makefile |   21 +++--
>  2 files changed, 49 insertions(+), 2 deletions(-)
> 
> --- a/kernel/gcov/Kconfig
> +++ b/kernel/gcov/Kconfig
> @@ -46,4 +46,34 @@ config GCOV_PROFILE_ALL
>   larger and run slower. Also be sure to exclude files from profiling
>   which are not linked to the kernel image to prevent linker errors.
> 
> +choice
> + prompt "Specify GCOV format"
> + depends on GCOV_KERNEL
> + default GCOV_FORMAT_AUTODETECT
> + ---help---
> + The gcov format is usually determined by the GCC version, but there are
> + exceptions where format changes are integrated in lower-version GCCs.
> + In such a case use this option to adjust the format used in the kernel
> + accordingly.
> +
> + If unsure, choose "Autodetect".
> +
> +config GCOV_FORMAT_AUTODETECT
> + bool "Autodetect"
> + ---help---
> + Select this option to use the format that corresponds to your GCC
> + version.
> +
> +config GCOV_FORMAT_3_4
> + bool "GCC 3.4 format"
> + ---help---
> + Select this option to use the format defined by GCC 3.4.
> +
> +config GCOV_FORMAT_4_7
> + bool "GCC 4.7 format"
> + ---help---
> + Select this option to use the format defined by GCC 4.7.
> +
> +endchoice
> +
>  endmenu
> --- a/kernel/gcov/Makefile
> +++ b/kernel/gcov/Makefile
> @@ -1,5 +1,22 @@
>  ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
> 
> +# if-lt
> +# Usage VAR := $(call if-lt, $(a), $(b))
> +# Returns 1 if (a < b)
> +if-lt = $(shell [ $(1) -lt $(2) ] && echo 1)
> +
> +ifeq ($(CONFIG_GCOV_FORMAT_3_4),y)
> +  cc-ver := 0304
> +else ifeq ($(CONFIG_GCOV_FORMAT_4_7),y)
> +  cc-ver := 0407
> +else
> +  cc-ver := $(call cc-version)
> +endif
> +
>  obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
> -obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -lt, 0407, gcc_3_4.o)
> -obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -ge, 0407, gcc_4_7.o)
> +
> +ifeq ($(call if-lt, $(cc-ver), 0407),1)
> +  obj-$(CONFIG_GCOV_KERNEL) += gcc_3_4.o
> +else
> +  obj-$(CONFIG_GCOV_KERNEL) += gcc_4_7.o
> +endif
> 
> 
> -- 
> Peter Oberparleiter
> Linux on System z Development - IBM Germany
> 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-24 Thread Frantisek Hrbata
On Fri, Aug 23, 2013 at 05:15:19PM +0200, Peter Oberparleiter wrote:
 On 23.08.2013 10:39, Frantisek Hrbata wrote:
  Compile the correct gcov implementation file for a specific gcc version. In
  the future, if another file is added, the conditions will need to be somehow
  adjusted to if-elif-else case, but at this point the simple cc-ifversion 
  should
  be enough.
 
 Looks good, though I think this could be merged into the main 4.7 format 
 patch,
 since without it, the 4.7 code will never be reached.

Sure, I can merge these two patches.

 
 Also it is my understanding that there are some distribution-specific versions
 of GCC that include the 4.7. gcov format code but report GCC version 4.6. With
 the auto-detection code implemented like this, gcov-kernel won't work 
 correctly.
 For that purpose I've implemented a configuration option to allow users to
 force a specific version of gcov format.

Ah, I was not aware of this inconsistency in versioning. This raises a question
if it would not be better to deal directly with version in the gcov_info
instead of these config options. This would of course mean some kind of gcov
operations callbacks per gcov version(you already mentioned the file
operations approach).

 
 I'm attaching the corresponding patch below:
 
 ---
 kernel: gcov: make data format configurable
 
 Make the format of the generated gcov data configurable. This may be
 required for example for pre-4.7 GCCs that contain the 4.7 gcov data
 format changes.
 
 Signed-off-by: Peter Oberparleiter ober...@linux.vnet.ibm.com
 ---
  kernel/gcov/Kconfig  |   30 ++
  kernel/gcov/Makefile |   21 +++--
  2 files changed, 49 insertions(+), 2 deletions(-)
 
 --- a/kernel/gcov/Kconfig
 +++ b/kernel/gcov/Kconfig
 @@ -46,4 +46,34 @@ config GCOV_PROFILE_ALL
   larger and run slower. Also be sure to exclude files from profiling
   which are not linked to the kernel image to prevent linker errors.
 
 +choice
 + prompt Specify GCOV format
 + depends on GCOV_KERNEL
 + default GCOV_FORMAT_AUTODETECT
 + ---help---
 + The gcov format is usually determined by the GCC version, but there are
 + exceptions where format changes are integrated in lower-version GCCs.
 + In such a case use this option to adjust the format used in the kernel
 + accordingly.
 +
 + If unsure, choose Autodetect.
 +
 +config GCOV_FORMAT_AUTODETECT
 + bool Autodetect
 + ---help---
 + Select this option to use the format that corresponds to your GCC
 + version.
 +
 +config GCOV_FORMAT_3_4
 + bool GCC 3.4 format
 + ---help---
 + Select this option to use the format defined by GCC 3.4.
 +
 +config GCOV_FORMAT_4_7
 + bool GCC 4.7 format
 + ---help---
 + Select this option to use the format defined by GCC 4.7.
 +
 +endchoice
 +
  endmenu
 --- a/kernel/gcov/Makefile
 +++ b/kernel/gcov/Makefile
 @@ -1,5 +1,22 @@
  ccflags-y := -DSRCTREE='$(srctree)' -DOBJTREE='$(objtree)'
 
 +# if-lt
 +# Usage VAR := $(call if-lt, $(a), $(b))
 +# Returns 1 if (a  b)
 +if-lt = $(shell [ $(1) -lt $(2) ]  echo 1)
 +
 +ifeq ($(CONFIG_GCOV_FORMAT_3_4),y)
 +  cc-ver := 0304
 +else ifeq ($(CONFIG_GCOV_FORMAT_4_7),y)
 +  cc-ver := 0407
 +else
 +  cc-ver := $(call cc-version)
 +endif
 +
  obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
 -obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -lt, 0407, gcc_3_4.o)
 -obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -ge, 0407, gcc_4_7.o)
 +
 +ifeq ($(call if-lt, $(cc-ver), 0407),1)
 +  obj-$(CONFIG_GCOV_KERNEL) += gcc_3_4.o
 +else
 +  obj-$(CONFIG_GCOV_KERNEL) += gcc_4_7.o
 +endif
 
 
 -- 
 Peter Oberparleiter
 Linux on System z Development - IBM Germany
 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-24 Thread Frantisek Hrbata
On Fri, Aug 23, 2013 at 05:21:12PM +0200, Peter Oberparleiter wrote:
 On 23.08.2013 17:15, Peter Oberparleiter wrote:
  On 23.08.2013 10:39, Frantisek Hrbata wrote:
  Compile the correct gcov implementation file for a specific gcc version. In
  the future, if another file is added, the conditions will need to be 
  somehow
  adjusted to if-elif-else case, but at this point the simple cc-ifversion 
  should
  be enough.
 
 As promised, I'm also adding the patch that makes the format-specific part
 of gcov-kernel a loadable kernel module:
 
 ---
 kernel: gcov: make format-specific code loadable
 
 Turn the format-specific part of gcov-kernel into a loadable kernel
 module. This enables the use of gcov-kernel with kernel modules
 that were compiled with a version of GCC that produces a different
 gcov format when compared to the version of GCC that was used to
 compile the kernel.

If I understand it correctly, this would mean that you will be able to use only
one implementation of gcov format at the time. Meaning you will be able to get
coverage data for module, but not for kernel if it was compiled with different
gcc(gcda format). This is probably ok if you work only on your module, but I'm
not sure this is generally the right approach. In this case I would probably
rather see some support for more gcov formats at the same time(e.g. set of
callback operations per gcov version). Again I'm probably missing something, but
I still cannot see reason why to add such feature. If you want gcov support just
compile your kernel and modules with the same gcc version(gcda format). But if
this is really needed maybe it would be better to consider some parallel support
for more gcov formats based on the gcov_info version.

Would it be possible to add support for the modified gcc 4.7 gcov format and
deal with this later? I can incorporate your changes: iter to use buffer,
.init_array for modules and possibility to explicitly select the gcda format.
In this case we will have at least the basic support in kernel. This is just me
thinking out loud.

Many thanks Peter!

 
 Signed-off-by: Peter Oberparleiter ober...@linux.vnet.ibm.com
 ---
  kernel/gcov/Kconfig  |   19 +--
  kernel/gcov/Makefile |7 ---
  2 files changed, 21 insertions(+), 5 deletions(-)
 
 --- a/kernel/gcov/Kconfig
 +++ b/kernel/gcov/Kconfig
 @@ -29,8 +29,23 @@ config GCOV_KERNEL
   and:
   GCOV_PROFILE := n
 
 - Note that the debugfs filesystem has to be mounted to access
 - profiling data.
 + Note that GCOV_KERNEL_FS has to specified as well and the debugfs
 + filesystem has to be mounted to access profiling data.
 +
 +config GCOV_KERNEL_FS
 + tristate Provide gcov data files in debugfs
 + depends on GCOV_KERNEL
 + default y
 + ---help---
 + Make profiling data available in debugfs at /sys/kernel/debug/gcov.
 +
 + Say M if you want to enable collecting coverage data for kernel modules
 + which are compiled using a gcc version different from the one that
 + was used to compile the kernel. In that case, re-compile the gcov
 + kernel module with corresponding format support and load that module
 + instead.
 +
 + If unsure, say Y.
 
  config GCOV_PROFILE_ALL
   bool Profile entire Kernel
 --- a/kernel/gcov/Makefile
 +++ b/kernel/gcov/Makefile
 @@ -13,10 +13,11 @@ else
cc-ver := $(call cc-version)
  endif
 
 -obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
 +obj-$(CONFIG_GCOV_KERNEL) += base.o
 +obj-$(CONFIG_GCOV_KERNEL_FS) += gcov.o
 
  ifeq ($(call if-lt, $(cc-ver), 0407),1)
 -  obj-$(CONFIG_GCOV_KERNEL) += gcc_3_4.o
 +  gcov-objs += fs.o gcc_3_4.o
  else
 -  obj-$(CONFIG_GCOV_KERNEL) += gcc_4_7.o
 +  gcov-objs += fs.o gcc_4_7.o
  endif
 
 -- 
 Peter Oberparleiter
 Linux on System z Development - IBM Germany
 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 2/4] gcov: add support for gcc 4.7 gcov format

2013-08-23 Thread Frantisek Hrbata
On Fri, Aug 23, 2013 at 05:12:19PM +0200, Peter Oberparleiter wrote:
> On 23.08.2013 10:39, Frantisek Hrbata wrote:
> > The gcov in-memory format changed in gcc 4.7. The biggest change, which
> > requires this special implementation, is that gcov_info no longer contains
> > array of counters for each counter type for all functions and gcov_fn_info 
> > is
> > not used for mapping of function's counters to these arrays(offset). Now 
> > each
> > gcov_fn_info contans it's counters, which makes things a little bit easier.
> 
> By now I've come to the conclusion that I may have over-engineered
> gcov_iter_next in the original GCC 3.4 implementation. This became especially
> apparent when someone tried to adjust that code to also work with a specific
> android GCC version - adding a simple field to the output file format required
> major complex changes.
> 
> Therefore in my version of the GCC 4.7 support, I opted to replace this logic
> with the simpler approach of generating the gcov data file in-memory during
> open (gcov_iter_new) and reducing gcov_iter_next/gcov_iter_write to simple
> copy-from-buffer functions.

Yes, this seems reasonable and much easier approach to me, but we will end up
with three copies of one gcov(gcda) file data in memory: data from gcc, our
buffer and the buffer in seq file. But I guess this is not a big problem,
unless someone opens a huge amount of gcda files in parallel. Generally I
like this idea. This will be also probably faster then writing 1 or 2 ints per
one iter write.

> 
> Since I can see the need to change the format code again in the future,
> I think it would be easier to simplify this part of the code correspondingly.
> I'm adding my version of this part of the implementation as discussion input
> below (the relevant part starts at convert_to_gcda()).

I have really only two nits to the code(please see below). I spent some time
checking the new seq/iter implementation and it seems ok to me. Generally I like
how simple this change is done.

> 
> ---
> kernel: gcov: add support for gcc 4.7 gcov format
> 
> GCC 4.7 changed the format of gcov related data structures, both
> on-disk and in memory. Add support for the new format.
> 
> Signed-off-by: Peter Oberparleiter 
> ---
>  kernel/gcov/Makefile  |4
>  kernel/gcov/gcc_4_7.c |  510 
> ++
>  2 files changed, 513 insertions(+), 1 deletion(-)
> 
> --- a/kernel/gcov/Makefile
> +++ b/kernel/gcov/Makefile
> @@ -1,3 +1,5 @@
>  ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
> 
> -obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
> +obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
> +obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -lt, 0407, gcc_3_4.o)
> +obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -ge, 0407, gcc_4_7.o)
> --- /dev/null
> +++ b/kernel/gcov/gcc_4_7.c
> @@ -0,0 +1,510 @@
> +/*
> + *  This code provides functions to handle gcc's profiling data format
> + *  introduced with gcc 4.7. Future versions of gcc may change the gcov
> + *  format (as happened before), so all format-specific information needs
> + *  to be kept modular and easily exchangeable.
> + *
> + *  This file is based on gcc-internal definitions. Functions and data
> + *  structures are defined to be compatible with gcc counterparts.
> + *  For a better understanding, refer to gcc source: gcc/gcov-io.h.
> + *
> + *Copyright IBM Corp. 2013
> + *Author(s): Peter Oberparleiter 
> + *
> + *Uses gcc-internal data definitions.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include "gcov.h"
> +
> +/*
> + * Profiling data types used for gcc 4.7 and above - these are defined by
> + * gcc and need to be kept as close to the original definition as possible to
> + * remain compatible.
> + */
> +#define GCOV_COUNTERS8
> +#define GCOV_DATA_MAGIC  ((unsigned int) 0x67636461)
> +#define GCOV_TAG_FUNCTION((unsigned int) 0x0100)
> +#define GCOV_TAG_COUNTER_BASE((unsigned int) 0x01a1)
> +#define GCOV_TAG_FOR_COUNTER(count)  \
> + (GCOV_TAG_COUNTER_BASE + ((unsigned int) (count) << 17))
> +
> +#if BITS_PER_LONG >= 64
> +typedef long gcov_type;
> +#else
> +typedef long long gcov_type;
> +#endif
> +
> +/**
> + * struct gcov_ctr_info - profiling data per function and counter type
> + * @num: number of counter values for this type
> + * @values: array of counter values for this type
> + *
> + * This data is generated by gcc during compilation and doesn't change
> + * at run-time with the exception of the values ar

Re: [RFC PATCH 4/4] kernel: add support for init_array constructors

2013-08-23 Thread Frantisek Hrbata
On Fri, Aug 23, 2013 at 05:13:31PM +0200, Peter Oberparleiter wrote:
> On 23.08.2013 10:39, Frantisek Hrbata wrote:
> > This adds the .init_array section as yet another section with constructors. 
> > This
> > is needed because gcc is adding __gcov_init calls to .init_array.
> > 
> > Signed-off-by: Frantisek Hrbata 
> > ---
> >  include/asm-generic/vmlinux.lds.h | 1 +
> >  include/linux/module.h| 2 ++
> >  kernel/module.c   | 6 ++
> >  3 files changed, 9 insertions(+)
> > 
> > diff --git a/include/asm-generic/vmlinux.lds.h 
> > b/include/asm-generic/vmlinux.lds.h
> > index 69732d2..c55d8d9 100644
> > --- a/include/asm-generic/vmlinux.lds.h
> > +++ b/include/asm-generic/vmlinux.lds.h
> > @@ -468,6 +468,7 @@
> >  #define KERNEL_CTORS() . = ALIGN(8);  \
> > VMLINUX_SYMBOL(__ctors_start) = .; \
> > *(.ctors)  \
> > +   *(.init_array) \
> 
> This is exactly how I (would) have done it.
> 
> > VMLINUX_SYMBOL(__ctors_end) = .;
> >  #else
> >  #define KERNEL_CTORS()
> > diff --git a/include/linux/module.h b/include/linux/module.h
> > index 46f1ea0..89ff829 100644
> > --- a/include/linux/module.h
> > +++ b/include/linux/module.h
> > @@ -374,6 +374,8 @@ struct module
> > /* Constructor functions. */
> > ctor_fn_t *ctors;
> > unsigned int num_ctors;
> > +   ctor_fn_t *init_array;
> > +   unsigned int num_init_array;
> 
> I think it would be safe to re-use the ctors-related fields here. Each GCC
> version will only ever create either of .ctors or .init_array, but never
> both. 
> The only case where separate fields would be required, would be when
> linking a kernel module from multiple object files compiled with different
> versions of GCC.

Ah ok, I was not aware of this.

> 
> >  #endif
> >  };
> >  #ifndef MODULE_ARCH_INIT
> > diff --git a/kernel/module.c b/kernel/module.c
> > index 2069158..581ae89 100644
> > --- a/kernel/module.c
> > +++ b/kernel/module.c
> > @@ -2760,6 +2760,9 @@ static void find_module_sections(struct module *mod, 
> > struct load_info *info)
> >  #ifdef CONFIG_CONSTRUCTORS
> > mod->ctors = section_objs(info, ".ctors",
> >   sizeof(*mod->ctors), >num_ctors);
> 
> When reusing mod->ctors, you could check for mod->ctors == NULL here and
> fill in the values from section_objs(".init_array").

Yes, in the case that we only have .ctors or .init_array section, this sounds
as the right approach.

> 
> > +   mod->init_array = section_objs(info, ".init_array",
> > + sizeof(*mod->init_array),
> > + >num_init_array);
> >  #endif
> > 
> >  #ifdef CONFIG_TRACEPOINTS
> > @@ -3024,6 +3027,9 @@ static void do_mod_ctors(struct module *mod)
> > 
> > for (i = 0; i < mod->num_ctors; i++)
> > mod->ctors[i]();
> > +
> > +   for (i = 0; i < mod->num_init_array; i++)
> > +   mod->init_array[i]();
> >  #endif
> >  }
> > 
> 
> -- 
> Peter Oberparleiter
> Linux on System z Development - IBM Germany
> 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 1/4] gcov: move gcov structs definitions to a gcc version specific file

2013-08-23 Thread Frantisek Hrbata
On Fri, Aug 23, 2013 at 05:09:58PM +0200, Peter Oberparleiter wrote:
> On 23.08.2013 10:39, Frantisek Hrbata wrote:
> > Since also the gcov structures(gcov_info, gcov_fn_info, gcov_ctr_info) can
> > change between gcc releases, as shown in gcc 4.7, they cannot be defined in 
> > a
> > common header and need to be moved to a specific gcc implemention file. This
> > also requires to make the gcov_info structure opaque for the common code 
> > and to
> > introduce simple helpers for accessing data inside gcov_info.
> 
> I've taken a similar approach in my version, although I stopped at isolating
> the code that handles the linked list. I like your version better since it's
> more consistent.

:) I also have doubts with the list "abstraction", it isn't very nice. I tried
to keep the changes as simple as possible in the generic code. I'm not sayint it
is the right approach, but your design is pretty good, so I had no urges to
change it more deeper. I'm of course open to any suggestions.

> 
> > diff --git a/kernel/gcov/gcc_3_4.c b/kernel/gcov/gcc_3_4.c
> > index ae5bb42..27bc88a 100644
> > --- a/kernel/gcov/gcc_3_4.c
> > +++ b/kernel/gcov/gcc_3_4.c
> > @@ -21,6 +21,121 @@
> >  #include 
> >  #include "gcov.h"
> > 
> > +#define GCOV_COUNTERS  5
> 
> The value for GCOV_COUNTERS has been changed with GCC 4.3. Before it was 5,
> starting with GCC 4.3 the value is 8. While this is not strictly necessary, 
> I'm
> wondering if this should be added here to prevent any unwanted side-effects.

Yes I was thinking about this two. My first idea was to use some define, maybe
in the Makefile during the gcc version check and set the number of counters
properly later based on this define. Something like

#if GCOV_GCC_VERIONS >= 0430
#define GCOV_COUNTERS 8
#elif ...

for the gcc_3_4.c implementation.

But I'm not sure what the new counters are good for and if they are really
needed for the coverage info. This would require deeper understanding what
and how the types of counters are used. At this point a simply did not change 
the
value for the format before gcc 4.7, because each counter type has a tag and
this should be backward compatible. We only miss the new counters. Again this is
something that probably deserves more attention. Thanks for pointing this out!

> 
> -- 
> Peter Oberparleiter
> Linux on System z Development - IBM Germany
> 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 0/4] add support for gcov format introduced in gcc 4.7

2013-08-23 Thread Frantisek Hrbata
On Fri, Aug 23, 2013 at 05:08:07PM +0200, Peter Oberparleiter wrote:
> On 23.08.2013 10:39, Frantisek Hrbata wrote:
> > This is an attempt to bring support for modified gcov format in gcc 4.7 to
> > the kernel. It tries to leverage the existing layout/abstraction, which was
> > designed keeping in mind that the gcov format could change, but some 
> > changes had
> > to be make. Mostly because the current model does not take into account that
> > even the core gcov structures, like gcov_info, could change. One part that 
> > could
> > be problematic is the addition of the .init_array section for constructors.
> 
> It appears that gcc 4.7 support for gcov-kernel is quite important to a
> number of people, at least that is what I derive from the fact that I
> now know of 3 people who've been working on this support separately from
> each other: you, myself (I've been close to posting my own version to
> LKML) and Christophe Guillon.

First, thank you for your quick reply. Second, great, I was worried there is no
interest to have the new format supported, because it's quite some time gcc 4.7
is out.

> 
> It's apparent now that I made a mistake delaying the discussion of the
> effort for too long, but I think your posting the patches opens up a
> good opportunity to combine the best of all previous efforts.

To be honest I ran into this problem 14 days ago when I was asked to take a
look. So I cannot say I know everything about gcov format and stuff around it.
I mostly followed your original code after I got some idea of the gcov in-memory
layout. Meaning, I'm glad that there is also yours and Christophe's code and
I for sure welcome the "combine the best of all previous efforts" approach, even
if it means dropping my code :).

> 
> Most of your code looks very familiar. There's one feature missing though
> that Christophe brought up as a requirement: the ability for gcov-kernel
> to cope with kernel modules being compiled with GCC versions implementing
> a different gcov format (apparently this can happen in some embedded
> setups).

Here follows quote from the gcc/gcov-io.h file


Coverage information is held in two files.  A notes file, which is
generated by the compiler, and a data file, which is generated by
the program under test.  Both files use a similar structure.  We do
not attempt to make these files backwards compatible with previous
versions, as you only need coverage information when developing a
program.  We do hold version information, so that mismatches can be
detected, and we use a format that allows tools to skip information
they do not understand or are not interested in.


Also from my experience, I would expect that the gcov will be used during
development, meaning re-compilation isn't a big problem here. I for sure can be
missing something and I'm by no means saying it wouldn't be useful feature. Just
that it would complite things a little bit.

> 
> Christophe proposed run-time version checking and a file-ops type function
> table which is chosen based on info->version. I found this approach
> somewhat intrusive and this would also not have covered the case where a
> new GCC versions was used to compile kernel modules for which the base
> kernel has no support. I tried to solve this requirement by combining
> two changes:
> 
> 1) make the gcov-format generated by gcov-kernel compile-time configurable
> 2) separate the gcov-format specific code into a loadable kernel module

So if I understand it correctly you would separate the input
format(gcov_info) from the output(gcda files). Meaning no matter which gcc
compiled the module you can select the gcda format. And even if the kernel does
not know the new format you can simply compile a module supporting it, instead
of the whole kernel.

Can you please give me an example why this is needed? As I wrote I'm not that
familiar with gcov and I'm probably missing something, but I do not understand
why this(handling several versions at runtime, not only the one used by gcc
during compilation) is useful(note my comment above about the gcov used during
development).

> 
> This way, the gcov-format specific part of gcov-kernel could be replaced
> when working with a different version GCC. I'll post the corresponding
> patches as reply in another mail.

Great, I will take a look, but it may take me some time :).

> 
> Back to your patches: I tested them and they work fine on s390x when
> compiled with GCC 4.3.4 and 4.7.2. I'll provide some more specific
> comments as replies to your patch-mails.

Many thanks!

> 
> 
> Regards,
>   Peter Oberparleiter
> 
> -- 
> Peter Oberparleiter
> Linux on System z Development - IBM Germany
> 

-- 
Frantisek Hrbata
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 4/4] kernel: add support for init_array constructors

2013-08-23 Thread Frantisek Hrbata
This adds the .init_array section as yet another section with constructors. This
is needed because gcc is adding __gcov_init calls to .init_array.

Signed-off-by: Frantisek Hrbata 
---
 include/asm-generic/vmlinux.lds.h | 1 +
 include/linux/module.h| 2 ++
 kernel/module.c   | 6 ++
 3 files changed, 9 insertions(+)

diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 69732d2..c55d8d9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -468,6 +468,7 @@
 #define KERNEL_CTORS() . = ALIGN(8);  \
VMLINUX_SYMBOL(__ctors_start) = .; \
*(.ctors)  \
+   *(.init_array) \
VMLINUX_SYMBOL(__ctors_end) = .;
 #else
 #define KERNEL_CTORS()
diff --git a/include/linux/module.h b/include/linux/module.h
index 46f1ea0..89ff829 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -374,6 +374,8 @@ struct module
/* Constructor functions. */
ctor_fn_t *ctors;
unsigned int num_ctors;
+   ctor_fn_t *init_array;
+   unsigned int num_init_array;
 #endif
 };
 #ifndef MODULE_ARCH_INIT
diff --git a/kernel/module.c b/kernel/module.c
index 2069158..581ae89 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2760,6 +2760,9 @@ static void find_module_sections(struct module *mod, 
struct load_info *info)
 #ifdef CONFIG_CONSTRUCTORS
mod->ctors = section_objs(info, ".ctors",
  sizeof(*mod->ctors), >num_ctors);
+   mod->init_array = section_objs(info, ".init_array",
+ sizeof(*mod->init_array),
+ >num_init_array);
 #endif
 
 #ifdef CONFIG_TRACEPOINTS
@@ -3024,6 +3027,9 @@ static void do_mod_ctors(struct module *mod)
 
for (i = 0; i < mod->num_ctors; i++)
mod->ctors[i]();
+
+   for (i = 0; i < mod->num_init_array; i++)
+   mod->init_array[i]();
 #endif
 }
 
-- 
1.8.3.1

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


[RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-23 Thread Frantisek Hrbata
Compile the correct gcov implementation file for a specific gcc version. In
the future, if another file is added, the conditions will need to be somehow
adjusted to if-elif-else case, but at this point the simple cc-ifversion should
be enough.

Signed-off-by: Frantisek Hrbata 
---
 kernel/gcov/Makefile | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/kernel/gcov/Makefile b/kernel/gcov/Makefile
index e97ca59..d57b712 100644
--- a/kernel/gcov/Makefile
+++ b/kernel/gcov/Makefile
@@ -1,3 +1,6 @@
 ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
 
-obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
+obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
+
+obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -ge, 0407, gcc_4_7.o)
+obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -lt, 0407, gcc_3_4.o)
-- 
1.8.3.1

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


[RFC PATCH 2/4] gcov: add support for gcc 4.7 gcov format

2013-08-23 Thread Frantisek Hrbata
The gcov in-memory format changed in gcc 4.7. The biggest change, which
requires this special implementation, is that gcov_info no longer contains
array of counters for each counter type for all functions and gcov_fn_info is
not used for mapping of function's counters to these arrays(offset). Now each
gcov_fn_info contans it's counters, which makes things a little bit easier.

This is heavily based on the previous gcc_3_4.c implementation.

Signed-off-by: Frantisek Hrbata 
---
 kernel/gcov/base.c|   6 +
 kernel/gcov/gcc_4_7.c | 612 ++
 2 files changed, 618 insertions(+)
 create mode 100644 kernel/gcov/gcc_4_7.c

diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c
index 912576a..f45b75b 100644
--- a/kernel/gcov/base.c
+++ b/kernel/gcov/base.c
@@ -79,6 +79,12 @@ void __gcov_merge_delta(gcov_type *counters, unsigned int 
n_counters)
 }
 EXPORT_SYMBOL(__gcov_merge_delta);
 
+void __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
+{
+   /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_ior);
+
 /**
  * gcov_enable_events - enable event reporting through gcov_event()
  *
diff --git a/kernel/gcov/gcc_4_7.c b/kernel/gcov/gcc_4_7.c
new file mode 100644
index 000..31bee00
--- /dev/null
+++ b/kernel/gcov/gcc_4_7.c
@@ -0,0 +1,612 @@
+/*
+ *  This code provides functions to handle gcc's profiling data format
+ *  introduced with gcc 4.7.
+ *
+ *  This file is based heavily on gcc_3_4.c file.
+ *
+ *  For a better understanding, refer to gcc source:
+ *  gcc/gcov-io.h
+ *  libgcc/libgcov.c
+ *
+ *  Uses gcc-internal data definitions.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include "gcov.h"
+
+#define GCOV_COUNTERS  8
+#define GCOV_TAG_FUNCTION_LENGTH   3
+
+static struct gcov_info *gcov_info_head;
+
+/**
+ * struct gcov_ctr_info - information about counters for a single function
+ * @num: number of counter values for this type
+ * @values: array of counter values for this type
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the values array.
+ */
+struct gcov_ctr_info {
+   unsigned int num;
+   gcov_type *values;
+};
+
+/**
+ * struct gcov_fn_info - profiling meta data per function
+ * @key: comdat key
+ * @ident: unique ident of function
+ * @lineno_checksum: function lineo_checksum
+ * @cfg_checksum: function cfg checksum
+ * @ctrs: instrumented counters
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time.
+ *
+ * Information about a single function.  This uses the trailing array
+ * idiom. The number of counters is determined from the merge pointer
+ * array in gcov_info.  The key is used to detect which of a set of
+ * comdat functions was selected -- it points to the gcov_info object
+ * of the object file containing the selected comdat function.
+ */
+struct gcov_fn_info {
+   const struct gcov_info *key;
+   unsigned int ident;
+   unsigned int lineno_checksum;
+   unsigned int cfg_checksum;
+   struct gcov_ctr_info ctrs[0];
+};
+
+/**
+ * struct gcov_info - profiling data per object file
+ * @version: gcov version magic indicating the gcc version used for compilation
+ * @next: list head for a singly-linked list
+ * @stamp: uniquifying time stamp
+ * @filename: name of the associated gcov data file
+ * @merge: merge functions (null for unused counter type)
+ * @n_functions: number of instrumented functions
+ * @functions: pointer to pointers to function information
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the next pointer.
+ */
+struct gcov_info {
+   unsigned int version;
+   struct gcov_info *next;
+   unsigned int stamp;
+   const char *filename;
+   void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int);
+   unsigned int n_functions;
+   const struct gcov_fn_info *const *functions;
+};
+
+/**
+ * gcov_info_filename - return info filename
+ * @info: profiling data set
+ */
+const char *gcov_info_filename(struct gcov_info *info)
+{
+   return info->filename;
+}
+
+/**
+ * gcov_info_version - return info version
+ * @info: profiling data set
+ */
+unsigned int gcov_info_version(struct gcov_info *info)
+{
+   return info->version;
+}
+
+/**
+ * gcov_info_next - return next profiling data set
+ * @info: profiling data set
+ *
+ * Returns next gcov_info following @info or first gcov_info in the chain if
+ * @info is %NULL.
+ */
+struct gcov_info *gcov_info_next(struct gcov_info *info)
+{
+   if (!info)
+   return gcov_info_head;
+
+   return info->next;
+}
+
+/**
+ * gcov_info_link - link/add profiling data set to the list
+ * @info: profiling data set
+ */
+void gcov_info_link(struct gcov_info *info)
+{
+   info->next = gcov_info_head;
+   gcov_info_head = info;
+}
+
+/**
+ * gcov_info_unlink - unlink/remove profiling 

[RFC PATCH 1/4] gcov: move gcov structs definitions to a gcc version specific file

2013-08-23 Thread Frantisek Hrbata
Since also the gcov structures(gcov_info, gcov_fn_info, gcov_ctr_info) can
change between gcc releases, as shown in gcc 4.7, they cannot be defined in a
common header and need to be moved to a specific gcc implemention file. This
also requires to make the gcov_info structure opaque for the common code and to
introduce simple helpers for accessing data inside gcov_info.

Signed-off-by: Frantisek Hrbata 
---
 kernel/gcov/base.c|  26 ++--
 kernel/gcov/fs.c  |  27 ++--
 kernel/gcov/gcc_3_4.c | 115 ++
 kernel/gcov/gcov.h|  65 +---
 4 files changed, 153 insertions(+), 80 deletions(-)

diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c
index 9b22d03..912576a 100644
--- a/kernel/gcov/base.c
+++ b/kernel/gcov/base.c
@@ -20,7 +20,6 @@
 #include 
 #include "gcov.h"
 
-static struct gcov_info *gcov_info_head;
 static int gcov_events_enabled;
 static DEFINE_MUTEX(gcov_lock);
 
@@ -34,7 +33,7 @@ void __gcov_init(struct gcov_info *info)
 
mutex_lock(_lock);
if (gcov_version == 0) {
-   gcov_version = info->version;
+   gcov_version = gcov_info_version(info);
/*
 * Printing gcc's version magic may prove useful for debugging
 * incompatibility reports.
@@ -45,8 +44,7 @@ void __gcov_init(struct gcov_info *info)
 * Add new profiling data structure to list and inform event
 * listener.
 */
-   info->next = gcov_info_head;
-   gcov_info_head = info;
+   gcov_info_link(info);
if (gcov_events_enabled)
gcov_event(GCOV_ADD, info);
mutex_unlock(_lock);
@@ -91,13 +89,15 @@ EXPORT_SYMBOL(__gcov_merge_delta);
  */
 void gcov_enable_events(void)
 {
-   struct gcov_info *info;
+   struct gcov_info *info = NULL;
 
mutex_lock(_lock);
gcov_events_enabled = 1;
+
/* Perform event callback for previously registered entries. */
-   for (info = gcov_info_head; info; info = info->next)
+   while ((info = gcov_info_next(info)))
gcov_event(GCOV_ADD, info);
+
mutex_unlock(_lock);
 }
 
@@ -112,25 +112,23 @@ static int gcov_module_notifier(struct notifier_block 
*nb, unsigned long event,
void *data)
 {
struct module *mod = data;
-   struct gcov_info *info;
-   struct gcov_info *prev;
+   struct gcov_info *info = NULL;
+   struct gcov_info *prev = NULL;
 
if (event != MODULE_STATE_GOING)
return NOTIFY_OK;
mutex_lock(_lock);
-   prev = NULL;
+
/* Remove entries located in module from linked list. */
-   for (info = gcov_info_head; info; info = info->next) {
+   while ((info = gcov_info_next(info))) {
if (within(info, mod->module_core, mod->core_size)) {
-   if (prev)
-   prev->next = info->next;
-   else
-   gcov_info_head = info->next;
+   gcov_info_unlink(prev, info);
if (gcov_events_enabled)
gcov_event(GCOV_REMOVE, info);
} else
prev = info;
}
+
mutex_unlock(_lock);
 
return NOTIFY_OK;
diff --git a/kernel/gcov/fs.c b/kernel/gcov/fs.c
index 9bd0934..27e12ce 100644
--- a/kernel/gcov/fs.c
+++ b/kernel/gcov/fs.c
@@ -242,7 +242,7 @@ static struct gcov_node *get_node_by_name(const char *name)
 
list_for_each_entry(node, _head, all) {
info = get_node_info(node);
-   if (info && (strcmp(info->filename, name) == 0))
+   if (info && (strcmp(gcov_info_filename(info), name) == 0))
return node;
}
 
@@ -279,7 +279,7 @@ static ssize_t gcov_seq_write(struct file *file, const char 
__user *addr,
seq = file->private_data;
info = gcov_iter_get_info(seq->private);
mutex_lock(_lock);
-   node = get_node_by_name(info->filename);
+   node = get_node_by_name(gcov_info_filename(info));
if (node) {
/* Reset counts or remove node for unloaded modules. */
if (node->num_loaded == 0)
@@ -376,8 +376,9 @@ static void add_links(struct gcov_node *node, struct dentry 
*parent)
if (!node->links)
return;
for (i = 0; i < num; i++) {
-   target = get_link_target(get_node_info(node)->filename,
-_link[i]);
+   target = get_link_target(
+   gcov_info_filename(get_node_info(node)),
+   _link[i]);
if (!target)
goto out_err;
basename = strrchr(target, '/');
@@ -576,7 +577,7 @@ static void add_

[RFC PATCH 0/4] add support for gcov format introduced in gcc 4.7

2013-08-23 Thread Frantisek Hrbata
This is an attempt to bring support for modified gcov format in gcc 4.7 to
the kernel. It tries to leverage the existing layout/abstraction, which was
designed keeping in mind that the gcov format could change, but some changes had
to be make. Mostly because the current model does not take into account that
even the core gcov structures, like gcov_info, could change. One part that could
be problematic is the addition of the .init_array section for constructors.

Tested with lcov and seems to be working fine, giving similar results as for the
older format.

Frantisek Hrbata (4):
  gcov: move gcov structs definitions to a gcc version specific file
  gcov: add support for gcc 4.7 gcov format
  gcov: compile specific gcov implementation based on gcc version
  kernel: add support for init_array constructors

 include/asm-generic/vmlinux.lds.h |   1 +
 include/linux/module.h|   2 +
 kernel/gcov/Makefile  |   5 +-
 kernel/gcov/base.c|  32 +-
 kernel/gcov/fs.c  |  27 +-
 kernel/gcov/gcc_3_4.c | 115 +++
 kernel/gcov/gcc_4_7.c | 612 ++
 kernel/gcov/gcov.h|  65 +---
 kernel/module.c   |   6 +
 9 files changed, 784 insertions(+), 81 deletions(-)
 create mode 100644 kernel/gcov/gcc_4_7.c

-- 
1.8.3.1

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


[RFC PATCH 0/4] add support for gcov format introduced in gcc 4.7

2013-08-23 Thread Frantisek Hrbata
This is an attempt to bring support for modified gcov format in gcc 4.7 to
the kernel. It tries to leverage the existing layout/abstraction, which was
designed keeping in mind that the gcov format could change, but some changes had
to be make. Mostly because the current model does not take into account that
even the core gcov structures, like gcov_info, could change. One part that could
be problematic is the addition of the .init_array section for constructors.

Tested with lcov and seems to be working fine, giving similar results as for the
older format.

Frantisek Hrbata (4):
  gcov: move gcov structs definitions to a gcc version specific file
  gcov: add support for gcc 4.7 gcov format
  gcov: compile specific gcov implementation based on gcc version
  kernel: add support for init_array constructors

 include/asm-generic/vmlinux.lds.h |   1 +
 include/linux/module.h|   2 +
 kernel/gcov/Makefile  |   5 +-
 kernel/gcov/base.c|  32 +-
 kernel/gcov/fs.c  |  27 +-
 kernel/gcov/gcc_3_4.c | 115 +++
 kernel/gcov/gcc_4_7.c | 612 ++
 kernel/gcov/gcov.h|  65 +---
 kernel/module.c   |   6 +
 9 files changed, 784 insertions(+), 81 deletions(-)
 create mode 100644 kernel/gcov/gcc_4_7.c

-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 1/4] gcov: move gcov structs definitions to a gcc version specific file

2013-08-23 Thread Frantisek Hrbata
Since also the gcov structures(gcov_info, gcov_fn_info, gcov_ctr_info) can
change between gcc releases, as shown in gcc 4.7, they cannot be defined in a
common header and need to be moved to a specific gcc implemention file. This
also requires to make the gcov_info structure opaque for the common code and to
introduce simple helpers for accessing data inside gcov_info.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 kernel/gcov/base.c|  26 ++--
 kernel/gcov/fs.c  |  27 ++--
 kernel/gcov/gcc_3_4.c | 115 ++
 kernel/gcov/gcov.h|  65 +---
 4 files changed, 153 insertions(+), 80 deletions(-)

diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c
index 9b22d03..912576a 100644
--- a/kernel/gcov/base.c
+++ b/kernel/gcov/base.c
@@ -20,7 +20,6 @@
 #include linux/mutex.h
 #include gcov.h
 
-static struct gcov_info *gcov_info_head;
 static int gcov_events_enabled;
 static DEFINE_MUTEX(gcov_lock);
 
@@ -34,7 +33,7 @@ void __gcov_init(struct gcov_info *info)
 
mutex_lock(gcov_lock);
if (gcov_version == 0) {
-   gcov_version = info-version;
+   gcov_version = gcov_info_version(info);
/*
 * Printing gcc's version magic may prove useful for debugging
 * incompatibility reports.
@@ -45,8 +44,7 @@ void __gcov_init(struct gcov_info *info)
 * Add new profiling data structure to list and inform event
 * listener.
 */
-   info-next = gcov_info_head;
-   gcov_info_head = info;
+   gcov_info_link(info);
if (gcov_events_enabled)
gcov_event(GCOV_ADD, info);
mutex_unlock(gcov_lock);
@@ -91,13 +89,15 @@ EXPORT_SYMBOL(__gcov_merge_delta);
  */
 void gcov_enable_events(void)
 {
-   struct gcov_info *info;
+   struct gcov_info *info = NULL;
 
mutex_lock(gcov_lock);
gcov_events_enabled = 1;
+
/* Perform event callback for previously registered entries. */
-   for (info = gcov_info_head; info; info = info-next)
+   while ((info = gcov_info_next(info)))
gcov_event(GCOV_ADD, info);
+
mutex_unlock(gcov_lock);
 }
 
@@ -112,25 +112,23 @@ static int gcov_module_notifier(struct notifier_block 
*nb, unsigned long event,
void *data)
 {
struct module *mod = data;
-   struct gcov_info *info;
-   struct gcov_info *prev;
+   struct gcov_info *info = NULL;
+   struct gcov_info *prev = NULL;
 
if (event != MODULE_STATE_GOING)
return NOTIFY_OK;
mutex_lock(gcov_lock);
-   prev = NULL;
+
/* Remove entries located in module from linked list. */
-   for (info = gcov_info_head; info; info = info-next) {
+   while ((info = gcov_info_next(info))) {
if (within(info, mod-module_core, mod-core_size)) {
-   if (prev)
-   prev-next = info-next;
-   else
-   gcov_info_head = info-next;
+   gcov_info_unlink(prev, info);
if (gcov_events_enabled)
gcov_event(GCOV_REMOVE, info);
} else
prev = info;
}
+
mutex_unlock(gcov_lock);
 
return NOTIFY_OK;
diff --git a/kernel/gcov/fs.c b/kernel/gcov/fs.c
index 9bd0934..27e12ce 100644
--- a/kernel/gcov/fs.c
+++ b/kernel/gcov/fs.c
@@ -242,7 +242,7 @@ static struct gcov_node *get_node_by_name(const char *name)
 
list_for_each_entry(node, all_head, all) {
info = get_node_info(node);
-   if (info  (strcmp(info-filename, name) == 0))
+   if (info  (strcmp(gcov_info_filename(info), name) == 0))
return node;
}
 
@@ -279,7 +279,7 @@ static ssize_t gcov_seq_write(struct file *file, const char 
__user *addr,
seq = file-private_data;
info = gcov_iter_get_info(seq-private);
mutex_lock(node_lock);
-   node = get_node_by_name(info-filename);
+   node = get_node_by_name(gcov_info_filename(info));
if (node) {
/* Reset counts or remove node for unloaded modules. */
if (node-num_loaded == 0)
@@ -376,8 +376,9 @@ static void add_links(struct gcov_node *node, struct dentry 
*parent)
if (!node-links)
return;
for (i = 0; i  num; i++) {
-   target = get_link_target(get_node_info(node)-filename,
-gcov_link[i]);
+   target = get_link_target(
+   gcov_info_filename(get_node_info(node)),
+   gcov_link[i]);
if (!target)
goto out_err;
basename = strrchr(target, '/');
@@ -576,7 +577,7 @@ static void add_node(struct gcov_info *info

[RFC PATCH 2/4] gcov: add support for gcc 4.7 gcov format

2013-08-23 Thread Frantisek Hrbata
The gcov in-memory format changed in gcc 4.7. The biggest change, which
requires this special implementation, is that gcov_info no longer contains
array of counters for each counter type for all functions and gcov_fn_info is
not used for mapping of function's counters to these arrays(offset). Now each
gcov_fn_info contans it's counters, which makes things a little bit easier.

This is heavily based on the previous gcc_3_4.c implementation.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 kernel/gcov/base.c|   6 +
 kernel/gcov/gcc_4_7.c | 612 ++
 2 files changed, 618 insertions(+)
 create mode 100644 kernel/gcov/gcc_4_7.c

diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c
index 912576a..f45b75b 100644
--- a/kernel/gcov/base.c
+++ b/kernel/gcov/base.c
@@ -79,6 +79,12 @@ void __gcov_merge_delta(gcov_type *counters, unsigned int 
n_counters)
 }
 EXPORT_SYMBOL(__gcov_merge_delta);
 
+void __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
+{
+   /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_ior);
+
 /**
  * gcov_enable_events - enable event reporting through gcov_event()
  *
diff --git a/kernel/gcov/gcc_4_7.c b/kernel/gcov/gcc_4_7.c
new file mode 100644
index 000..31bee00
--- /dev/null
+++ b/kernel/gcov/gcc_4_7.c
@@ -0,0 +1,612 @@
+/*
+ *  This code provides functions to handle gcc's profiling data format
+ *  introduced with gcc 4.7.
+ *
+ *  This file is based heavily on gcc_3_4.c file.
+ *
+ *  For a better understanding, refer to gcc source:
+ *  gcc/gcov-io.h
+ *  libgcc/libgcov.c
+ *
+ *  Uses gcc-internal data definitions.
+ */
+
+#include linux/errno.h
+#include linux/slab.h
+#include linux/string.h
+#include linux/seq_file.h
+#include gcov.h
+
+#define GCOV_COUNTERS  8
+#define GCOV_TAG_FUNCTION_LENGTH   3
+
+static struct gcov_info *gcov_info_head;
+
+/**
+ * struct gcov_ctr_info - information about counters for a single function
+ * @num: number of counter values for this type
+ * @values: array of counter values for this type
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the values array.
+ */
+struct gcov_ctr_info {
+   unsigned int num;
+   gcov_type *values;
+};
+
+/**
+ * struct gcov_fn_info - profiling meta data per function
+ * @key: comdat key
+ * @ident: unique ident of function
+ * @lineno_checksum: function lineo_checksum
+ * @cfg_checksum: function cfg checksum
+ * @ctrs: instrumented counters
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time.
+ *
+ * Information about a single function.  This uses the trailing array
+ * idiom. The number of counters is determined from the merge pointer
+ * array in gcov_info.  The key is used to detect which of a set of
+ * comdat functions was selected -- it points to the gcov_info object
+ * of the object file containing the selected comdat function.
+ */
+struct gcov_fn_info {
+   const struct gcov_info *key;
+   unsigned int ident;
+   unsigned int lineno_checksum;
+   unsigned int cfg_checksum;
+   struct gcov_ctr_info ctrs[0];
+};
+
+/**
+ * struct gcov_info - profiling data per object file
+ * @version: gcov version magic indicating the gcc version used for compilation
+ * @next: list head for a singly-linked list
+ * @stamp: uniquifying time stamp
+ * @filename: name of the associated gcov data file
+ * @merge: merge functions (null for unused counter type)
+ * @n_functions: number of instrumented functions
+ * @functions: pointer to pointers to function information
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the next pointer.
+ */
+struct gcov_info {
+   unsigned int version;
+   struct gcov_info *next;
+   unsigned int stamp;
+   const char *filename;
+   void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int);
+   unsigned int n_functions;
+   const struct gcov_fn_info *const *functions;
+};
+
+/**
+ * gcov_info_filename - return info filename
+ * @info: profiling data set
+ */
+const char *gcov_info_filename(struct gcov_info *info)
+{
+   return info-filename;
+}
+
+/**
+ * gcov_info_version - return info version
+ * @info: profiling data set
+ */
+unsigned int gcov_info_version(struct gcov_info *info)
+{
+   return info-version;
+}
+
+/**
+ * gcov_info_next - return next profiling data set
+ * @info: profiling data set
+ *
+ * Returns next gcov_info following @info or first gcov_info in the chain if
+ * @info is %NULL.
+ */
+struct gcov_info *gcov_info_next(struct gcov_info *info)
+{
+   if (!info)
+   return gcov_info_head;
+
+   return info-next;
+}
+
+/**
+ * gcov_info_link - link/add profiling data set to the list
+ * @info: profiling data set
+ */
+void gcov_info_link(struct gcov_info *info)
+{
+   info-next = gcov_info_head;
+   gcov_info_head = info

[RFC PATCH 3/4] gcov: compile specific gcov implementation based on gcc version

2013-08-23 Thread Frantisek Hrbata
Compile the correct gcov implementation file for a specific gcc version. In
the future, if another file is added, the conditions will need to be somehow
adjusted to if-elif-else case, but at this point the simple cc-ifversion should
be enough.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 kernel/gcov/Makefile | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/kernel/gcov/Makefile b/kernel/gcov/Makefile
index e97ca59..d57b712 100644
--- a/kernel/gcov/Makefile
+++ b/kernel/gcov/Makefile
@@ -1,3 +1,6 @@
 ccflags-y := -DSRCTREE='$(srctree)' -DOBJTREE='$(objtree)'
 
-obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
+obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o
+
+obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -ge, 0407, gcc_4_7.o)
+obj-$(CONFIG_GCOV_KERNEL) += $(call cc-ifversion, -lt, 0407, gcc_3_4.o)
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH 4/4] kernel: add support for init_array constructors

2013-08-23 Thread Frantisek Hrbata
This adds the .init_array section as yet another section with constructors. This
is needed because gcc is adding __gcov_init calls to .init_array.

Signed-off-by: Frantisek Hrbata fhrb...@redhat.com
---
 include/asm-generic/vmlinux.lds.h | 1 +
 include/linux/module.h| 2 ++
 kernel/module.c   | 6 ++
 3 files changed, 9 insertions(+)

diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 69732d2..c55d8d9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -468,6 +468,7 @@
 #define KERNEL_CTORS() . = ALIGN(8);  \
VMLINUX_SYMBOL(__ctors_start) = .; \
*(.ctors)  \
+   *(.init_array) \
VMLINUX_SYMBOL(__ctors_end) = .;
 #else
 #define KERNEL_CTORS()
diff --git a/include/linux/module.h b/include/linux/module.h
index 46f1ea0..89ff829 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -374,6 +374,8 @@ struct module
/* Constructor functions. */
ctor_fn_t *ctors;
unsigned int num_ctors;
+   ctor_fn_t *init_array;
+   unsigned int num_init_array;
 #endif
 };
 #ifndef MODULE_ARCH_INIT
diff --git a/kernel/module.c b/kernel/module.c
index 2069158..581ae89 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2760,6 +2760,9 @@ static void find_module_sections(struct module *mod, 
struct load_info *info)
 #ifdef CONFIG_CONSTRUCTORS
mod-ctors = section_objs(info, .ctors,
  sizeof(*mod-ctors), mod-num_ctors);
+   mod-init_array = section_objs(info, .init_array,
+ sizeof(*mod-init_array),
+ mod-num_init_array);
 #endif
 
 #ifdef CONFIG_TRACEPOINTS
@@ -3024,6 +3027,9 @@ static void do_mod_ctors(struct module *mod)
 
for (i = 0; i  mod-num_ctors; i++)
mod-ctors[i]();
+
+   for (i = 0; i  mod-num_init_array; i++)
+   mod-init_array[i]();
 #endif
 }
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   >