[PATCH] mm: slub: re-initialize randomized freelist sequence in calculate_sizes

2020-08-08 Thread kpark3469
From: Sahara 

Slab cache flags are exported to sysfs and are allowed to get modified
from userspace. Some of those may call calculate_sizes function because
the changed flag can take an effect on slab object size and layout,
which means kmem_cache may have different order and objects.
The freelist pointer corruption occurs if some slab flags are modified
while CONFIG_SLAB_FREELIST_RANDOM is turned on.

 $ echo 0 > /sys/kernel/slab/zs_handle/store_user
 $ echo 0 > /sys/kernel/slab/zspage/store_user
 $ mkswap /dev/block/zram0
 $ swapon /dev/block/zram0 -p 32758

 =
 BUG zs_handle (Not tainted): Freepointer corrupt
 -

 Disabling lock debugging due to kernel taint
 INFO: Slab 0xffbf29603600 objects=102 used=102 fp=0x 
flags=0x0200
 INFO: Object 0xffca580d8d78 @offset=3448 fp=0xffca580d8ed0

 Redzone f3cddd6c: bb bb bb bb bb bb bb bb  

 Object 82d5d74e: 6b 6b 6b 6b 6b 6b 6b a5  
kkk.
 Redzone 8fd80359: bb bb bb bb bb bb bb bb  

 Padding c7f56047: 5a 5a 5a 5a 5a 5a 5a 5a  


In this example, an Android device tries to use zram as a swap and to
turn off store_user in order to reduce the slub object size.
When calculate_sizes is called in kmem_cache_open, size, order and
objects for zs_handle is:
 size:360, order:0, objects:22
However, if the SLAB_STORE_USER bit is cleared in store_user_store:
 size: 56, order:1, objects:73

All the size, order, and objects is changed by calculate_sizes(), but
the size of the random_seq array is still old value(22). As a result,
out-of-bound array access can occur at shuffle_freelist() when slab
allocation is requested.

This patch fixes the problem by re-allocating the random_seq array
with re-calculated correct objects value.

Fixes: 210e7a43fa905 ("mm: SLUB freelist randomization")
Reported-by: Ari-Pekka Verta 
Reported-by: Timo Simola 
Signed-off-by: Sahara 
---
 mm/slub.c | 23 ---
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/mm/slub.c b/mm/slub.c
index f226d66408ee..be1e4d6682b8 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3704,7 +3704,22 @@ static int calculate_sizes(struct kmem_cache *s, int 
forced_order)
if (oo_objects(s->oo) > oo_objects(s->max))
s->max = s->oo;
 
-   return !!oo_objects(s->oo);
+   if (!oo_objects(s->oo))
+   return 0;
+
+   /*
+* Initialize the pre-computed randomized freelist if slab is up.
+* If the randomized freelist random_seq is already initialized,
+* free and re-initialize it with re-calculated value.
+*/
+   if (slab_state >= UP) {
+   if (s->random_seq)
+   cache_random_seq_destroy(s);
+   if (init_cache_random_seq(s))
+   return 0;
+   }
+
+   return 1;
 }
 
 static int kmem_cache_open(struct kmem_cache *s, slab_flags_t flags)
@@ -3748,12 +3763,6 @@ static int kmem_cache_open(struct kmem_cache *s, 
slab_flags_t flags)
s->remote_node_defrag_ratio = 1000;
 #endif
 
-   /* Initialize the pre-computed randomized freelist if slab is up */
-   if (slab_state >= UP) {
-   if (init_cache_random_seq(s))
-   goto error;
-   }
-
if (!init_kmem_cache_nodes(s))
goto error;
 
-- 
2.17.1



[PATCH] tty: serial_core: recover uport->cons->cflag on uart_close

2019-06-16 Thread kpark3469
From: Sahara 

Since uart_close was converted to use tty_port_close, uart_shutdown
also moved to uart_tty_port_shutdown, which means it does not backup
tty's termios to uart_port.console.cflag when console is closed and
uart_console is true.
By losing this value, serial console was not set correctly especially
after suspend/resume when there is no consumer of console device.
This problem resets console driver's configuration to an unwanted value
and may give a performance regression in the system eventually.
This patch fixes the bug introduced from v4.9 kernel.

Fixes: 761ed4a94582 ("tty: serial_core: convert uart_close to use 
tty_port_close")
Reported-by: Jouni Linnamaa 
Signed-off-by: Sahara 
---
 drivers/tty/serial/serial_core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 83f4dd0bfd74..a52afceb2f4e 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1533,6 +1533,7 @@ static void uart_set_termios(struct tty_struct *tty,
 static void uart_close(struct tty_struct *tty, struct file *filp)
 {
struct uart_state *state = tty->driver_data;
+   struct uart_port *uport = uart_port_check(state);
 
if (!state) {
struct uart_driver *drv = tty->driver->driver_state;
@@ -1548,6 +1549,8 @@ static void uart_close(struct tty_struct *tty, struct 
file *filp)
 
pr_debug("uart_close(%d) called\n", tty->index);
 
+   if (uport && uart_console(uport))
+   uport->cons->cflag = tty->termios.c_cflag;
tty_port_close(tty->port, tty, filp);
 }
 
-- 
2.17.1



[PATCH] tty: pty: Fix race condition between release_one_tty and pty_write

2019-02-10 Thread kpark3469
From: Sahara 

Especially when a linked tty is used such as pty, the linked tty
port's buf works have not been cancelled while master tty port's
buf work has been cancelled. Since release_one_tty and flush_to_ldisc
run in workqueue threads separately, when pty_cleanup happens and
link tty port is freed, flush_to_ldisc tries to access freed port
and port->itty, eventually it causes a panic.
This patch utilizes the magic value with holding the tty_mutex to
check if the tty->link is valid.

Fixes: 2b022ab7542d ("pty: cancel pty slave port buf's work in tty_release")
Signed-off-by: Sahara 
---
 drivers/tty/pty.c| 7 +++
 drivers/tty/tty_io.c | 3 +++
 2 files changed, 10 insertions(+)

diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 00099a84..ef72031 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -116,6 +116,12 @@ static int pty_write(struct tty_struct *tty, const 
unsigned char *buf, int c)
if (tty->stopped)
return 0;
 
+   mutex_lock(_mutex);
+   if (to->magic != TTY_MAGIC) {
+   mutex_unlock(_mutex);
+   return -EIO;
+   }
+
if (c > 0) {
spin_lock_irqsave(>port->lock, flags);
/* Stuff the data into the input queue of the other end */
@@ -125,6 +131,7 @@ static int pty_write(struct tty_struct *tty, const unsigned 
char *buf, int c)
tty_flip_buffer_push(to->port);
spin_unlock_irqrestore(>port->lock, flags);
}
+   mutex_unlock(_mutex);
return c;
 }
 
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 23c6fd2..6c4a206 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1446,10 +1446,13 @@ static void release_one_tty(struct work_struct *work)
struct tty_driver *driver = tty->driver;
struct module *owner = driver->owner;
 
+   mutex_lock(_mutex);
if (tty->ops->cleanup)
tty->ops->cleanup(tty);
 
tty->magic = 0;
+   mutex_unlock(_mutex);
+
tty_driver_kref_put(driver);
module_put(owner);
 
-- 
2.7.4



[PATCH v2] mm: clean up page_is_poisoned in linux/mm.h

2018-06-04 Thread kpark3469
From: Sahara 

When bd33ef368135("mm: enable page poisoning early at boot") got
rid of the PAGE_EXT_DEBUG_POISON, page_is_poisoned in the header
left behind. This patch cleans up the leftovers under the table.

Acked-by: Michal Hocko 
Signed-off-by: Sahara 
---
 include/linux/mm.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index c6fa9a2..a53b0ad 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2522,12 +2522,10 @@ extern int apply_to_page_range(struct mm_struct *mm, 
unsigned long address,
 #ifdef CONFIG_PAGE_POISONING
 extern bool page_poisoning_enabled(void);
 extern void kernel_poison_pages(struct page *page, int numpages, int enable);
-extern bool page_is_poisoned(struct page *page);
 #else
 static inline bool page_poisoning_enabled(void) { return false; }
 static inline void kernel_poison_pages(struct page *page, int numpages,
int enable) { }
-static inline bool page_is_poisoned(struct page *page) { return false; }
 #endif
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
-- 
2.7.4



[PATCH v2] mm: clean up page_is_poisoned in linux/mm.h

2018-06-04 Thread kpark3469
From: Sahara 

When bd33ef368135("mm: enable page poisoning early at boot") got
rid of the PAGE_EXT_DEBUG_POISON, page_is_poisoned in the header
left behind. This patch cleans up the leftovers under the table.

Acked-by: Michal Hocko 
Signed-off-by: Sahara 
---
 include/linux/mm.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index c6fa9a2..a53b0ad 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2522,12 +2522,10 @@ extern int apply_to_page_range(struct mm_struct *mm, 
unsigned long address,
 #ifdef CONFIG_PAGE_POISONING
 extern bool page_poisoning_enabled(void);
 extern void kernel_poison_pages(struct page *page, int numpages, int enable);
-extern bool page_is_poisoned(struct page *page);
 #else
 static inline bool page_poisoning_enabled(void) { return false; }
 static inline void kernel_poison_pages(struct page *page, int numpages,
int enable) { }
-static inline bool page_is_poisoned(struct page *page) { return false; }
 #endif
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
-- 
2.7.4



[PATCH] mm: clean up page_is_poisoned in linux/mm.h

2018-06-03 Thread kpark3469
From: Sahara 

When bd33ef36("mm: enable page poisoning early at boot") got rid of
the PAGE_EXT_DEBUG_POISON, page_is_poisoned in the header left
behind. This patch cleans up the leftovers under the table.

Signed-off-by: Sahara 
---
 include/linux/mm.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index c6fa9a2..a53b0ad 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2522,12 +2522,10 @@ extern int apply_to_page_range(struct mm_struct *mm, 
unsigned long address,
 #ifdef CONFIG_PAGE_POISONING
 extern bool page_poisoning_enabled(void);
 extern void kernel_poison_pages(struct page *page, int numpages, int enable);
-extern bool page_is_poisoned(struct page *page);
 #else
 static inline bool page_poisoning_enabled(void) { return false; }
 static inline void kernel_poison_pages(struct page *page, int numpages,
int enable) { }
-static inline bool page_is_poisoned(struct page *page) { return false; }
 #endif
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
-- 
2.7.4



[PATCH] mm: clean up page_is_poisoned in linux/mm.h

2018-06-03 Thread kpark3469
From: Sahara 

When bd33ef36("mm: enable page poisoning early at boot") got rid of
the PAGE_EXT_DEBUG_POISON, page_is_poisoned in the header left
behind. This patch cleans up the leftovers under the table.

Signed-off-by: Sahara 
---
 include/linux/mm.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index c6fa9a2..a53b0ad 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2522,12 +2522,10 @@ extern int apply_to_page_range(struct mm_struct *mm, 
unsigned long address,
 #ifdef CONFIG_PAGE_POISONING
 extern bool page_poisoning_enabled(void);
 extern void kernel_poison_pages(struct page *page, int numpages, int enable);
-extern bool page_is_poisoned(struct page *page);
 #else
 static inline bool page_poisoning_enabled(void) { return false; }
 static inline void kernel_poison_pages(struct page *page, int numpages,
int enable) { }
-static inline bool page_is_poisoned(struct page *page) { return false; }
 #endif
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
-- 
2.7.4



[PATCH v4 3/3] x86: usercopy: reimplement arch_within_stack_frames with unwinder

2018-04-10 Thread kpark3469
From: Sahara 

The old arch_within_stack_frames which used the frame pointer is
now reimplemented to use frame pointer unwinder apis. So the main
functionality is same as before.

Signed-off-by: Sahara 
---
 arch/x86/include/asm/unwind.h  |  5 
 arch/x86/kernel/stacktrace.c   | 64 +-
 arch/x86/kernel/unwind_frame.c |  4 +--
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h
index 1f86e1b..6f04906f 100644
--- a/arch/x86/include/asm/unwind.h
+++ b/arch/x86/include/asm/unwind.h
@@ -87,6 +87,11 @@ void unwind_init(void);
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
void *orc, size_t orc_size);
 #else
+#ifdef CONFIG_UNWINDER_FRAME_POINTER
+#define FRAME_HEADER_SIZE (sizeof(long) * 2)
+size_t regs_size(struct pt_regs *regs);
+#endif
+
 static inline void unwind_init(void) {}
 static inline
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index ff178a0..3de1105 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -13,6 +13,33 @@
 #include 
 
 
+static inline void *get_cur_frame(struct unwind_state *state)
+{
+   void *frame = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs)
+   frame = (void *)state->regs;
+   else
+   frame = (void *)state->bp;
+#endif
+   return frame;
+}
+
+static inline void *get_frame_end(struct unwind_state *state)
+{
+   void *frame_end = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs) {
+   frame_end = (void *)state->regs + regs_size(state->regs);
+   } else {
+   frame_end = (void *)state->bp + FRAME_HEADER_SIZE;
+   }
+#endif
+   return frame_end;
+}
+
 /*
  * Walks up the stack frames to make sure that the specified object is
  * entirely contained by a single stack frame.
@@ -26,31 +53,42 @@ int arch_within_stack_frames(const void * const stack,
 const void * const stackend,
 const void *obj, unsigned long len)
 {
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(2);
-   if (oldframe)
-   frame = __builtin_frame_address(3);
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   struct unwind_state state;
+   void *prev_frame_end = NULL;
/*
 * low --> high
 * [saved bp][saved ip][args][local vars][saved bp][saved ip]
 * ^^
 *   allow copies only within here
+*
+* Skip 3 non-inlined frames: arch_within_stack_frames(),
+* check_stack_object() and __check_object_size().
+*
 */
-   while (stack <= frame && frame < stackend) {
+   unsigned int discard_frames = 3;
+
+   for (unwind_start(, current, NULL, NULL); !unwind_done();
+unwind_next_frame()) {
/*
 * If obj + len extends past the last frame, this
 * check won't pass and the next frame will be 0,
 * causing us to bail out and correctly report
 * the copy as invalid.
 */
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
+   if (discard_frames) {
+   discard_frames--;
+   } else {
+   void *frame = get_cur_frame();
+
+   if (!frame || !prev_frame_end)
+   return NOT_STACK;
+   if (obj + len <= frame)
+   return obj >= prev_frame_end ?
+   GOOD_FRAME : BAD_STACK;
+   }
+   /* save current frame end before move to next frame */
+   prev_frame_end = get_frame_end();
}
return BAD_STACK;
 #else
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index 3dc26f9..c8bfa5c 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -8,8 +8,6 @@
 #include 
 #include 
 
-#define FRAME_HEADER_SIZE (sizeof(long) * 2)
-
 unsigned long unwind_get_return_address(struct unwind_state *state)
 {
if (unwind_done(state))
@@ -69,7 +67,7 @@ static void unwind_dump(struct unwind_state *state)
}
 }
 
-static size_t regs_size(struct pt_regs *regs)
+size_t regs_size(struct pt_regs *regs)
 {
/* x86_32 regs 

[PATCH v4 3/3] x86: usercopy: reimplement arch_within_stack_frames with unwinder

2018-04-10 Thread kpark3469
From: Sahara 

The old arch_within_stack_frames which used the frame pointer is
now reimplemented to use frame pointer unwinder apis. So the main
functionality is same as before.

Signed-off-by: Sahara 
---
 arch/x86/include/asm/unwind.h  |  5 
 arch/x86/kernel/stacktrace.c   | 64 +-
 arch/x86/kernel/unwind_frame.c |  4 +--
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h
index 1f86e1b..6f04906f 100644
--- a/arch/x86/include/asm/unwind.h
+++ b/arch/x86/include/asm/unwind.h
@@ -87,6 +87,11 @@ void unwind_init(void);
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
void *orc, size_t orc_size);
 #else
+#ifdef CONFIG_UNWINDER_FRAME_POINTER
+#define FRAME_HEADER_SIZE (sizeof(long) * 2)
+size_t regs_size(struct pt_regs *regs);
+#endif
+
 static inline void unwind_init(void) {}
 static inline
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index ff178a0..3de1105 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -13,6 +13,33 @@
 #include 
 
 
+static inline void *get_cur_frame(struct unwind_state *state)
+{
+   void *frame = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs)
+   frame = (void *)state->regs;
+   else
+   frame = (void *)state->bp;
+#endif
+   return frame;
+}
+
+static inline void *get_frame_end(struct unwind_state *state)
+{
+   void *frame_end = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs) {
+   frame_end = (void *)state->regs + regs_size(state->regs);
+   } else {
+   frame_end = (void *)state->bp + FRAME_HEADER_SIZE;
+   }
+#endif
+   return frame_end;
+}
+
 /*
  * Walks up the stack frames to make sure that the specified object is
  * entirely contained by a single stack frame.
@@ -26,31 +53,42 @@ int arch_within_stack_frames(const void * const stack,
 const void * const stackend,
 const void *obj, unsigned long len)
 {
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(2);
-   if (oldframe)
-   frame = __builtin_frame_address(3);
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   struct unwind_state state;
+   void *prev_frame_end = NULL;
/*
 * low --> high
 * [saved bp][saved ip][args][local vars][saved bp][saved ip]
 * ^^
 *   allow copies only within here
+*
+* Skip 3 non-inlined frames: arch_within_stack_frames(),
+* check_stack_object() and __check_object_size().
+*
 */
-   while (stack <= frame && frame < stackend) {
+   unsigned int discard_frames = 3;
+
+   for (unwind_start(, current, NULL, NULL); !unwind_done();
+unwind_next_frame()) {
/*
 * If obj + len extends past the last frame, this
 * check won't pass and the next frame will be 0,
 * causing us to bail out and correctly report
 * the copy as invalid.
 */
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
+   if (discard_frames) {
+   discard_frames--;
+   } else {
+   void *frame = get_cur_frame();
+
+   if (!frame || !prev_frame_end)
+   return NOT_STACK;
+   if (obj + len <= frame)
+   return obj >= prev_frame_end ?
+   GOOD_FRAME : BAD_STACK;
+   }
+   /* save current frame end before move to next frame */
+   prev_frame_end = get_frame_end();
}
return BAD_STACK;
 #else
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index 3dc26f9..c8bfa5c 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -8,8 +8,6 @@
 #include 
 #include 
 
-#define FRAME_HEADER_SIZE (sizeof(long) * 2)
-
 unsigned long unwind_get_return_address(struct unwind_state *state)
 {
if (unwind_done(state))
@@ -69,7 +67,7 @@ static void unwind_dump(struct unwind_state *state)
}
 }
 
-static size_t regs_size(struct pt_regs *regs)
+size_t regs_size(struct pt_regs *regs)
 {
/* x86_32 regs from kernel mode are two words shorter: */
if 

[PATCH v4 0/3] usercopy: reimplement arch_within_stack_frames

2018-04-10 Thread kpark3469
From: Sahara 

This series of patches introduce the arm64 arch_within_stack_frames
implementation using stacktrace functions. Also the base code is
moved from thread_info.h to stacktrace.h. x86 code is reimplemented
to use frame pointer unwinder functions.

Note: The code is still missing in case of using x86 ORC unwinder and
guess unwinder.

v2 changes:
 - Remove 'arm64: usercopy: consider dynamic array stack variable'
 - minor fix in x86 arch_within_stack_frames code.
v3 changes:
 - Fix build problem caused by circular inclusion of header in x86 UP config
v4 changes:
 - Fix build problem caused by page_ext.h change

James Morse (1):
  arm64: usercopy: implement arch_within_stack_frames

Sahara (2):
  stacktrace: move arch_within_stack_frames from thread_info.h
  x86: usercopy: reimplement arch_within_stack_frames with unwinder

 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 +
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/include/asm/unwind.h  |  5 +++
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 87 ++
 arch/x86/kernel/unwind_frame.c |  4 +-
 include/linux/stacktrace.h | 24 +++
 include/linux/thread_info.h| 21 -
 mm/usercopy.c  |  2 +-
 10 files changed, 197 insertions(+), 76 deletions(-)

-- 
2.7.4



[PATCH v4 0/3] usercopy: reimplement arch_within_stack_frames

2018-04-10 Thread kpark3469
From: Sahara 

This series of patches introduce the arm64 arch_within_stack_frames
implementation using stacktrace functions. Also the base code is
moved from thread_info.h to stacktrace.h. x86 code is reimplemented
to use frame pointer unwinder functions.

Note: The code is still missing in case of using x86 ORC unwinder and
guess unwinder.

v2 changes:
 - Remove 'arm64: usercopy: consider dynamic array stack variable'
 - minor fix in x86 arch_within_stack_frames code.
v3 changes:
 - Fix build problem caused by circular inclusion of header in x86 UP config
v4 changes:
 - Fix build problem caused by page_ext.h change

James Morse (1):
  arm64: usercopy: implement arch_within_stack_frames

Sahara (2):
  stacktrace: move arch_within_stack_frames from thread_info.h
  x86: usercopy: reimplement arch_within_stack_frames with unwinder

 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 +
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/include/asm/unwind.h  |  5 +++
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 87 ++
 arch/x86/kernel/unwind_frame.c |  4 +-
 include/linux/stacktrace.h | 24 +++
 include/linux/thread_info.h| 21 -
 mm/usercopy.c  |  2 +-
 10 files changed, 197 insertions(+), 76 deletions(-)

-- 
2.7.4



[PATCH v4 2/3] arm64: usercopy: implement arch_within_stack_frames

2018-04-10 Thread kpark3469
From: James Morse 

This implements arch_within_stack_frames() for arm64 that should
validate if a given object is contained by a kernel stack frame.

Signed-off-by: James Morse 
Reviewed-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 ++
 2 files changed, 77 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index eb2cf49..4498ff4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -128,6 +128,7 @@ config ARM64
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
select HAVE_KRETPROBES
+   select HAVE_ARCH_WITHIN_STACK_FRAMES
select IOMMU_DMA if IOMMU_SUPPORT
select IRQ_DOMAIN
select IRQ_FORCED_THREADING
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index d5718a0..5eb3784 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -27,6 +27,11 @@
 #include 
 #include 
 
+#define FAKE_FRAME(frame, my_func) do {\
+   frame.fp = (unsigned long)__builtin_frame_address(0);   \
+   frame.pc = (unsigned long)my_func;  \
+} while (0)
+
 /*
  * AArch64 PCS assigns the frame pointer to x29.
  *
@@ -100,6 +105,77 @@ void notrace walk_stackframe(struct task_struct *tsk, 
struct stackframe *frame,
}
 }
 
+struct check_frame_arg {
+   unsigned long obj_start;
+   unsigned long obj_end;
+   unsigned long frame_start;
+   int discard_frames;
+   int err;
+};
+
+static int check_frame(struct stackframe *frame, void *d)
+{
+   struct check_frame_arg *arg = d;
+   unsigned long frame_end = frame->fp;
+
+   /* object overlaps multiple frames */
+   if (arg->obj_start < frame->fp && frame->fp < arg->obj_end) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   /*
+* Discard frames and check object is in a frame written early
+* enough.
+*/
+   if (arg->discard_frames)
+   arg->discard_frames--;
+   else if ((arg->frame_start <= arg->obj_start &&
+   arg->obj_start < frame_end) &&
+   (arg->frame_start < arg->obj_end && arg->obj_end <= frame_end))
+   return 1;
+
+   /* object exists in a previous frame */
+   if (arg->obj_end < arg->frame_start) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   arg->frame_start = frame_end + 0x10;
+
+   return 0;
+}
+
+/* Check obj doesn't overlap a stack frame record */
+int arch_within_stack_frames(const void *stack,
+const void *stack_end,
+const void *obj, unsigned long obj_len)
+{
+   struct stackframe frame;
+   struct check_frame_arg arg;
+
+   if (!IS_ENABLED(CONFIG_FRAME_POINTER))
+   return NOT_STACK;
+
+   arg.err = GOOD_FRAME;
+   arg.obj_start = (unsigned long)obj;
+   arg.obj_end = arg.obj_start + obj_len;
+
+   FAKE_FRAME(frame, arch_within_stack_frames);
+   arg.frame_start = frame.fp;
+
+   /*
+* Skip 4 non-inlined frames: ,
+* arch_within_stack_frames(), check_stack_object() and
+* __check_object_size().
+*/
+   arg.discard_frames = 4;
+
+   walk_stackframe(current, , check_frame, );
+
+   return arg.err;
+}
+
 #ifdef CONFIG_STACKTRACE
 struct stack_trace_data {
struct stack_trace *trace;
-- 
2.7.4



[PATCH v4 1/3] stacktrace: move arch_within_stack_frames from thread_info.h

2018-04-10 Thread kpark3469
From: Sahara 

Since the inlined arch_within_stack_frames function was placed within
asm/thread_info.h, using stacktrace functions to unwind stack was
restricted. Now in order to have this function use more abundant apis,
it is moved to architecture's stacktrace.c. And, it is changed from
inline to noinline function to clearly have three depth calls like:

do_usercopy_stack()
  copy_[to|from]_user() : inline
check_copy_size() : inline
  __check_object_size()
check_stack_object()
  arch_within_stack_frames()

With this change, the x86's implementation was slightly changed also.

Signed-off-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 49 
 include/linux/stacktrace.h | 24 ++
 include/linux/thread_info.h| 21 
 mm/usercopy.c  |  2 +-
 6 files changed, 76 insertions(+), 73 deletions(-)

diff --git a/arch/x86/include/asm/thread_info.h 
b/arch/x86/include/asm/thread_info.h
index a5d9521..e25d70a 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -156,59 +156,10 @@ struct thread_info {
  *
  * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
-#ifndef __ASSEMBLY__
-
-/*
- * Walks up the stack frames to make sure that the specified object is
- * entirely contained by a single stack frame.
- *
- * Returns:
- * GOOD_FRAME  if within a frame
- * BAD_STACK   if placed across a frame boundary (or outside stack)
- * NOT_STACK   unable to determine (no frame pointers, etc)
- */
-static inline int arch_within_stack_frames(const void * const stack,
-  const void * const stackend,
-  const void *obj, unsigned long len)
-{
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(1);
-   if (oldframe)
-   frame = __builtin_frame_address(2);
-   /*
-* low --> high
-* [saved bp][saved ip][args][local vars][saved bp][saved ip]
-* ^^
-*   allow copies only within here
-*/
-   while (stack <= frame && frame < stackend) {
-   /*
-* If obj + len extends past the last frame, this
-* check won't pass and the next frame will be 0,
-* causing us to bail out and correctly report
-* the copy as invalid.
-*/
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
-   }
-   return BAD_STACK;
-#else
-   return NOT_STACK;
-#endif
-}
-
-#else /* !__ASSEMBLY__ */
-
+#ifdef __ASSEMBLY__
 #ifdef CONFIG_X86_64
 # define cpu_current_top_of_stack (cpu_tss_rw + TSS_sp1)
 #endif
-
 #endif
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 02d6f5c..3b8afd5 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -70,7 +70,7 @@ obj-$(CONFIG_IA32_EMULATION)  += tls.o
 obj-y  += step.o
 obj-$(CONFIG_INTEL_TXT)+= tboot.o
 obj-$(CONFIG_ISA_DMA_API)  += i8237.o
-obj-$(CONFIG_STACKTRACE)   += stacktrace.o
+obj-y  += stacktrace.o
 obj-y  += cpu/
 obj-y  += acpi/
 obj-y  += reboot.o
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 093f2ea..ff178a0 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -12,6 +12,54 @@
 #include 
 #include 
 
+
+/*
+ * Walks up the stack frames to make sure that the specified object is
+ * entirely contained by a single stack frame.
+ *
+ * Returns:
+ * GOOD_FRAME  if within a frame
+ * BAD_STACK   if placed across a frame boundary (or outside stack)
+ * NOT_STACK   unable to determine (no frame pointers, etc)
+ */
+int arch_within_stack_frames(const void * const stack,
+const void * const stackend,
+const void *obj, unsigned long len)
+{
+#if defined(CONFIG_FRAME_POINTER)
+   const void *frame = NULL;
+   const void *oldframe;
+
+   oldframe = __builtin_frame_address(2);
+   if (oldframe)
+   frame = __builtin_frame_address(3);
+   /*
+* low --> high
+ 

[PATCH v4 2/3] arm64: usercopy: implement arch_within_stack_frames

2018-04-10 Thread kpark3469
From: James Morse 

This implements arch_within_stack_frames() for arm64 that should
validate if a given object is contained by a kernel stack frame.

Signed-off-by: James Morse 
Reviewed-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 ++
 2 files changed, 77 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index eb2cf49..4498ff4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -128,6 +128,7 @@ config ARM64
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
select HAVE_KRETPROBES
+   select HAVE_ARCH_WITHIN_STACK_FRAMES
select IOMMU_DMA if IOMMU_SUPPORT
select IRQ_DOMAIN
select IRQ_FORCED_THREADING
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index d5718a0..5eb3784 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -27,6 +27,11 @@
 #include 
 #include 
 
+#define FAKE_FRAME(frame, my_func) do {\
+   frame.fp = (unsigned long)__builtin_frame_address(0);   \
+   frame.pc = (unsigned long)my_func;  \
+} while (0)
+
 /*
  * AArch64 PCS assigns the frame pointer to x29.
  *
@@ -100,6 +105,77 @@ void notrace walk_stackframe(struct task_struct *tsk, 
struct stackframe *frame,
}
 }
 
+struct check_frame_arg {
+   unsigned long obj_start;
+   unsigned long obj_end;
+   unsigned long frame_start;
+   int discard_frames;
+   int err;
+};
+
+static int check_frame(struct stackframe *frame, void *d)
+{
+   struct check_frame_arg *arg = d;
+   unsigned long frame_end = frame->fp;
+
+   /* object overlaps multiple frames */
+   if (arg->obj_start < frame->fp && frame->fp < arg->obj_end) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   /*
+* Discard frames and check object is in a frame written early
+* enough.
+*/
+   if (arg->discard_frames)
+   arg->discard_frames--;
+   else if ((arg->frame_start <= arg->obj_start &&
+   arg->obj_start < frame_end) &&
+   (arg->frame_start < arg->obj_end && arg->obj_end <= frame_end))
+   return 1;
+
+   /* object exists in a previous frame */
+   if (arg->obj_end < arg->frame_start) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   arg->frame_start = frame_end + 0x10;
+
+   return 0;
+}
+
+/* Check obj doesn't overlap a stack frame record */
+int arch_within_stack_frames(const void *stack,
+const void *stack_end,
+const void *obj, unsigned long obj_len)
+{
+   struct stackframe frame;
+   struct check_frame_arg arg;
+
+   if (!IS_ENABLED(CONFIG_FRAME_POINTER))
+   return NOT_STACK;
+
+   arg.err = GOOD_FRAME;
+   arg.obj_start = (unsigned long)obj;
+   arg.obj_end = arg.obj_start + obj_len;
+
+   FAKE_FRAME(frame, arch_within_stack_frames);
+   arg.frame_start = frame.fp;
+
+   /*
+* Skip 4 non-inlined frames: ,
+* arch_within_stack_frames(), check_stack_object() and
+* __check_object_size().
+*/
+   arg.discard_frames = 4;
+
+   walk_stackframe(current, , check_frame, );
+
+   return arg.err;
+}
+
 #ifdef CONFIG_STACKTRACE
 struct stack_trace_data {
struct stack_trace *trace;
-- 
2.7.4



[PATCH v4 1/3] stacktrace: move arch_within_stack_frames from thread_info.h

2018-04-10 Thread kpark3469
From: Sahara 

Since the inlined arch_within_stack_frames function was placed within
asm/thread_info.h, using stacktrace functions to unwind stack was
restricted. Now in order to have this function use more abundant apis,
it is moved to architecture's stacktrace.c. And, it is changed from
inline to noinline function to clearly have three depth calls like:

do_usercopy_stack()
  copy_[to|from]_user() : inline
check_copy_size() : inline
  __check_object_size()
check_stack_object()
  arch_within_stack_frames()

With this change, the x86's implementation was slightly changed also.

Signed-off-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 49 
 include/linux/stacktrace.h | 24 ++
 include/linux/thread_info.h| 21 
 mm/usercopy.c  |  2 +-
 6 files changed, 76 insertions(+), 73 deletions(-)

diff --git a/arch/x86/include/asm/thread_info.h 
b/arch/x86/include/asm/thread_info.h
index a5d9521..e25d70a 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -156,59 +156,10 @@ struct thread_info {
  *
  * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
-#ifndef __ASSEMBLY__
-
-/*
- * Walks up the stack frames to make sure that the specified object is
- * entirely contained by a single stack frame.
- *
- * Returns:
- * GOOD_FRAME  if within a frame
- * BAD_STACK   if placed across a frame boundary (or outside stack)
- * NOT_STACK   unable to determine (no frame pointers, etc)
- */
-static inline int arch_within_stack_frames(const void * const stack,
-  const void * const stackend,
-  const void *obj, unsigned long len)
-{
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(1);
-   if (oldframe)
-   frame = __builtin_frame_address(2);
-   /*
-* low --> high
-* [saved bp][saved ip][args][local vars][saved bp][saved ip]
-* ^^
-*   allow copies only within here
-*/
-   while (stack <= frame && frame < stackend) {
-   /*
-* If obj + len extends past the last frame, this
-* check won't pass and the next frame will be 0,
-* causing us to bail out and correctly report
-* the copy as invalid.
-*/
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
-   }
-   return BAD_STACK;
-#else
-   return NOT_STACK;
-#endif
-}
-
-#else /* !__ASSEMBLY__ */
-
+#ifdef __ASSEMBLY__
 #ifdef CONFIG_X86_64
 # define cpu_current_top_of_stack (cpu_tss_rw + TSS_sp1)
 #endif
-
 #endif
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 02d6f5c..3b8afd5 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -70,7 +70,7 @@ obj-$(CONFIG_IA32_EMULATION)  += tls.o
 obj-y  += step.o
 obj-$(CONFIG_INTEL_TXT)+= tboot.o
 obj-$(CONFIG_ISA_DMA_API)  += i8237.o
-obj-$(CONFIG_STACKTRACE)   += stacktrace.o
+obj-y  += stacktrace.o
 obj-y  += cpu/
 obj-y  += acpi/
 obj-y  += reboot.o
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 093f2ea..ff178a0 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -12,6 +12,54 @@
 #include 
 #include 
 
+
+/*
+ * Walks up the stack frames to make sure that the specified object is
+ * entirely contained by a single stack frame.
+ *
+ * Returns:
+ * GOOD_FRAME  if within a frame
+ * BAD_STACK   if placed across a frame boundary (or outside stack)
+ * NOT_STACK   unable to determine (no frame pointers, etc)
+ */
+int arch_within_stack_frames(const void * const stack,
+const void * const stackend,
+const void *obj, unsigned long len)
+{
+#if defined(CONFIG_FRAME_POINTER)
+   const void *frame = NULL;
+   const void *oldframe;
+
+   oldframe = __builtin_frame_address(2);
+   if (oldframe)
+   frame = __builtin_frame_address(3);
+   /*
+* low --> high
+* [saved bp][saved ip][args][local vars][saved bp][saved ip]
+*   

[PATCH v3 3/3] x86: usercopy: reimplement arch_within_stack_frames with unwinder

2018-04-09 Thread kpark3469
From: Sahara 

The old arch_within_stack_frames which used the frame pointer is
now reimplemented to use frame pointer unwinder apis. So the main
functionality is same as before.

Signed-off-by: Sahara 
---
 arch/x86/include/asm/unwind.h  |  5 
 arch/x86/kernel/stacktrace.c   | 64 +-
 arch/x86/kernel/unwind_frame.c |  4 +--
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h
index 1f86e1b..6f04906f 100644
--- a/arch/x86/include/asm/unwind.h
+++ b/arch/x86/include/asm/unwind.h
@@ -87,6 +87,11 @@ void unwind_init(void);
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
void *orc, size_t orc_size);
 #else
+#ifdef CONFIG_UNWINDER_FRAME_POINTER
+#define FRAME_HEADER_SIZE (sizeof(long) * 2)
+size_t regs_size(struct pt_regs *regs);
+#endif
+
 static inline void unwind_init(void) {}
 static inline
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index ff178a0..3de1105 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -13,6 +13,33 @@
 #include 
 
 
+static inline void *get_cur_frame(struct unwind_state *state)
+{
+   void *frame = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs)
+   frame = (void *)state->regs;
+   else
+   frame = (void *)state->bp;
+#endif
+   return frame;
+}
+
+static inline void *get_frame_end(struct unwind_state *state)
+{
+   void *frame_end = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs) {
+   frame_end = (void *)state->regs + regs_size(state->regs);
+   } else {
+   frame_end = (void *)state->bp + FRAME_HEADER_SIZE;
+   }
+#endif
+   return frame_end;
+}
+
 /*
  * Walks up the stack frames to make sure that the specified object is
  * entirely contained by a single stack frame.
@@ -26,31 +53,42 @@ int arch_within_stack_frames(const void * const stack,
 const void * const stackend,
 const void *obj, unsigned long len)
 {
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(2);
-   if (oldframe)
-   frame = __builtin_frame_address(3);
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   struct unwind_state state;
+   void *prev_frame_end = NULL;
/*
 * low --> high
 * [saved bp][saved ip][args][local vars][saved bp][saved ip]
 * ^^
 *   allow copies only within here
+*
+* Skip 3 non-inlined frames: arch_within_stack_frames(),
+* check_stack_object() and __check_object_size().
+*
 */
-   while (stack <= frame && frame < stackend) {
+   unsigned int discard_frames = 3;
+
+   for (unwind_start(, current, NULL, NULL); !unwind_done();
+unwind_next_frame()) {
/*
 * If obj + len extends past the last frame, this
 * check won't pass and the next frame will be 0,
 * causing us to bail out and correctly report
 * the copy as invalid.
 */
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
+   if (discard_frames) {
+   discard_frames--;
+   } else {
+   void *frame = get_cur_frame();
+
+   if (!frame || !prev_frame_end)
+   return NOT_STACK;
+   if (obj + len <= frame)
+   return obj >= prev_frame_end ?
+   GOOD_FRAME : BAD_STACK;
+   }
+   /* save current frame end before move to next frame */
+   prev_frame_end = get_frame_end();
}
return BAD_STACK;
 #else
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index 3dc26f9..c8bfa5c 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -8,8 +8,6 @@
 #include 
 #include 
 
-#define FRAME_HEADER_SIZE (sizeof(long) * 2)
-
 unsigned long unwind_get_return_address(struct unwind_state *state)
 {
if (unwind_done(state))
@@ -69,7 +67,7 @@ static void unwind_dump(struct unwind_state *state)
}
 }
 
-static size_t regs_size(struct pt_regs *regs)
+size_t regs_size(struct pt_regs *regs)
 {
/* x86_32 regs 

[PATCH v3 3/3] x86: usercopy: reimplement arch_within_stack_frames with unwinder

2018-04-09 Thread kpark3469
From: Sahara 

The old arch_within_stack_frames which used the frame pointer is
now reimplemented to use frame pointer unwinder apis. So the main
functionality is same as before.

Signed-off-by: Sahara 
---
 arch/x86/include/asm/unwind.h  |  5 
 arch/x86/kernel/stacktrace.c   | 64 +-
 arch/x86/kernel/unwind_frame.c |  4 +--
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h
index 1f86e1b..6f04906f 100644
--- a/arch/x86/include/asm/unwind.h
+++ b/arch/x86/include/asm/unwind.h
@@ -87,6 +87,11 @@ void unwind_init(void);
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
void *orc, size_t orc_size);
 #else
+#ifdef CONFIG_UNWINDER_FRAME_POINTER
+#define FRAME_HEADER_SIZE (sizeof(long) * 2)
+size_t regs_size(struct pt_regs *regs);
+#endif
+
 static inline void unwind_init(void) {}
 static inline
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index ff178a0..3de1105 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -13,6 +13,33 @@
 #include 
 
 
+static inline void *get_cur_frame(struct unwind_state *state)
+{
+   void *frame = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs)
+   frame = (void *)state->regs;
+   else
+   frame = (void *)state->bp;
+#endif
+   return frame;
+}
+
+static inline void *get_frame_end(struct unwind_state *state)
+{
+   void *frame_end = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs) {
+   frame_end = (void *)state->regs + regs_size(state->regs);
+   } else {
+   frame_end = (void *)state->bp + FRAME_HEADER_SIZE;
+   }
+#endif
+   return frame_end;
+}
+
 /*
  * Walks up the stack frames to make sure that the specified object is
  * entirely contained by a single stack frame.
@@ -26,31 +53,42 @@ int arch_within_stack_frames(const void * const stack,
 const void * const stackend,
 const void *obj, unsigned long len)
 {
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(2);
-   if (oldframe)
-   frame = __builtin_frame_address(3);
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   struct unwind_state state;
+   void *prev_frame_end = NULL;
/*
 * low --> high
 * [saved bp][saved ip][args][local vars][saved bp][saved ip]
 * ^^
 *   allow copies only within here
+*
+* Skip 3 non-inlined frames: arch_within_stack_frames(),
+* check_stack_object() and __check_object_size().
+*
 */
-   while (stack <= frame && frame < stackend) {
+   unsigned int discard_frames = 3;
+
+   for (unwind_start(, current, NULL, NULL); !unwind_done();
+unwind_next_frame()) {
/*
 * If obj + len extends past the last frame, this
 * check won't pass and the next frame will be 0,
 * causing us to bail out and correctly report
 * the copy as invalid.
 */
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
+   if (discard_frames) {
+   discard_frames--;
+   } else {
+   void *frame = get_cur_frame();
+
+   if (!frame || !prev_frame_end)
+   return NOT_STACK;
+   if (obj + len <= frame)
+   return obj >= prev_frame_end ?
+   GOOD_FRAME : BAD_STACK;
+   }
+   /* save current frame end before move to next frame */
+   prev_frame_end = get_frame_end();
}
return BAD_STACK;
 #else
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index 3dc26f9..c8bfa5c 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -8,8 +8,6 @@
 #include 
 #include 
 
-#define FRAME_HEADER_SIZE (sizeof(long) * 2)
-
 unsigned long unwind_get_return_address(struct unwind_state *state)
 {
if (unwind_done(state))
@@ -69,7 +67,7 @@ static void unwind_dump(struct unwind_state *state)
}
 }
 
-static size_t regs_size(struct pt_regs *regs)
+size_t regs_size(struct pt_regs *regs)
 {
/* x86_32 regs from kernel mode are two words shorter: */
if 

[PATCH v3 2/3] arm64: usercopy: implement arch_within_stack_frames

2018-04-09 Thread kpark3469
From: James Morse 

This implements arch_within_stack_frames() for arm64 that should
validate if a given object is contained by a kernel stack frame.

Signed-off-by: James Morse 
Reviewed-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 ++
 2 files changed, 77 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 177be0d..72d0747 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -128,6 +128,7 @@ config ARM64
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
select HAVE_KRETPROBES
+   select HAVE_ARCH_WITHIN_STACK_FRAMES
select IOMMU_DMA if IOMMU_SUPPORT
select IRQ_DOMAIN
select IRQ_FORCED_THREADING
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index d5718a0..5eb3784 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -27,6 +27,11 @@
 #include 
 #include 
 
+#define FAKE_FRAME(frame, my_func) do {\
+   frame.fp = (unsigned long)__builtin_frame_address(0);   \
+   frame.pc = (unsigned long)my_func;  \
+} while (0)
+
 /*
  * AArch64 PCS assigns the frame pointer to x29.
  *
@@ -100,6 +105,77 @@ void notrace walk_stackframe(struct task_struct *tsk, 
struct stackframe *frame,
}
 }
 
+struct check_frame_arg {
+   unsigned long obj_start;
+   unsigned long obj_end;
+   unsigned long frame_start;
+   int discard_frames;
+   int err;
+};
+
+static int check_frame(struct stackframe *frame, void *d)
+{
+   struct check_frame_arg *arg = d;
+   unsigned long frame_end = frame->fp;
+
+   /* object overlaps multiple frames */
+   if (arg->obj_start < frame->fp && frame->fp < arg->obj_end) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   /*
+* Discard frames and check object is in a frame written early
+* enough.
+*/
+   if (arg->discard_frames)
+   arg->discard_frames--;
+   else if ((arg->frame_start <= arg->obj_start &&
+   arg->obj_start < frame_end) &&
+   (arg->frame_start < arg->obj_end && arg->obj_end <= frame_end))
+   return 1;
+
+   /* object exists in a previous frame */
+   if (arg->obj_end < arg->frame_start) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   arg->frame_start = frame_end + 0x10;
+
+   return 0;
+}
+
+/* Check obj doesn't overlap a stack frame record */
+int arch_within_stack_frames(const void *stack,
+const void *stack_end,
+const void *obj, unsigned long obj_len)
+{
+   struct stackframe frame;
+   struct check_frame_arg arg;
+
+   if (!IS_ENABLED(CONFIG_FRAME_POINTER))
+   return NOT_STACK;
+
+   arg.err = GOOD_FRAME;
+   arg.obj_start = (unsigned long)obj;
+   arg.obj_end = arg.obj_start + obj_len;
+
+   FAKE_FRAME(frame, arch_within_stack_frames);
+   arg.frame_start = frame.fp;
+
+   /*
+* Skip 4 non-inlined frames: ,
+* arch_within_stack_frames(), check_stack_object() and
+* __check_object_size().
+*/
+   arg.discard_frames = 4;
+
+   walk_stackframe(current, , check_frame, );
+
+   return arg.err;
+}
+
 #ifdef CONFIG_STACKTRACE
 struct stack_trace_data {
struct stack_trace *trace;
-- 
2.7.4



[PATCH v3 2/3] arm64: usercopy: implement arch_within_stack_frames

2018-04-09 Thread kpark3469
From: James Morse 

This implements arch_within_stack_frames() for arm64 that should
validate if a given object is contained by a kernel stack frame.

Signed-off-by: James Morse 
Reviewed-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 ++
 2 files changed, 77 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 177be0d..72d0747 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -128,6 +128,7 @@ config ARM64
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
select HAVE_KRETPROBES
+   select HAVE_ARCH_WITHIN_STACK_FRAMES
select IOMMU_DMA if IOMMU_SUPPORT
select IRQ_DOMAIN
select IRQ_FORCED_THREADING
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index d5718a0..5eb3784 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -27,6 +27,11 @@
 #include 
 #include 
 
+#define FAKE_FRAME(frame, my_func) do {\
+   frame.fp = (unsigned long)__builtin_frame_address(0);   \
+   frame.pc = (unsigned long)my_func;  \
+} while (0)
+
 /*
  * AArch64 PCS assigns the frame pointer to x29.
  *
@@ -100,6 +105,77 @@ void notrace walk_stackframe(struct task_struct *tsk, 
struct stackframe *frame,
}
 }
 
+struct check_frame_arg {
+   unsigned long obj_start;
+   unsigned long obj_end;
+   unsigned long frame_start;
+   int discard_frames;
+   int err;
+};
+
+static int check_frame(struct stackframe *frame, void *d)
+{
+   struct check_frame_arg *arg = d;
+   unsigned long frame_end = frame->fp;
+
+   /* object overlaps multiple frames */
+   if (arg->obj_start < frame->fp && frame->fp < arg->obj_end) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   /*
+* Discard frames and check object is in a frame written early
+* enough.
+*/
+   if (arg->discard_frames)
+   arg->discard_frames--;
+   else if ((arg->frame_start <= arg->obj_start &&
+   arg->obj_start < frame_end) &&
+   (arg->frame_start < arg->obj_end && arg->obj_end <= frame_end))
+   return 1;
+
+   /* object exists in a previous frame */
+   if (arg->obj_end < arg->frame_start) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   arg->frame_start = frame_end + 0x10;
+
+   return 0;
+}
+
+/* Check obj doesn't overlap a stack frame record */
+int arch_within_stack_frames(const void *stack,
+const void *stack_end,
+const void *obj, unsigned long obj_len)
+{
+   struct stackframe frame;
+   struct check_frame_arg arg;
+
+   if (!IS_ENABLED(CONFIG_FRAME_POINTER))
+   return NOT_STACK;
+
+   arg.err = GOOD_FRAME;
+   arg.obj_start = (unsigned long)obj;
+   arg.obj_end = arg.obj_start + obj_len;
+
+   FAKE_FRAME(frame, arch_within_stack_frames);
+   arg.frame_start = frame.fp;
+
+   /*
+* Skip 4 non-inlined frames: ,
+* arch_within_stack_frames(), check_stack_object() and
+* __check_object_size().
+*/
+   arg.discard_frames = 4;
+
+   walk_stackframe(current, , check_frame, );
+
+   return arg.err;
+}
+
 #ifdef CONFIG_STACKTRACE
 struct stack_trace_data {
struct stack_trace *trace;
-- 
2.7.4



[PATCH v3 1/3] stacktrace: move arch_within_stack_frames from thread_info.h

2018-04-09 Thread kpark3469
From: Sahara 

Since the inlined arch_within_stack_frames function was placed within
asm/thread_info.h, using stacktrace functions to unwind stack was
restricted. Now in order to have this function use more abundant apis,
it is moved to architecture's stacktrace.c. And, it is changed from
inline to noinline function to clearly have three depth calls like:

do_usercopy_stack()
  copy_[to|from]_user() : inline
check_copy_size() : inline
  __check_object_size()
check_stack_object()
  arch_within_stack_frames()

With this change, the x86's implementation was slightly changed also.

Signed-off-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 49 
 include/linux/page_ext.h   |  1 -
 include/linux/stacktrace.h | 24 ++
 include/linux/thread_info.h| 21 
 mm/usercopy.c  |  2 +-
 7 files changed, 76 insertions(+), 74 deletions(-)

diff --git a/arch/x86/include/asm/thread_info.h 
b/arch/x86/include/asm/thread_info.h
index a5d9521..e25d70a 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -156,59 +156,10 @@ struct thread_info {
  *
  * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
-#ifndef __ASSEMBLY__
-
-/*
- * Walks up the stack frames to make sure that the specified object is
- * entirely contained by a single stack frame.
- *
- * Returns:
- * GOOD_FRAME  if within a frame
- * BAD_STACK   if placed across a frame boundary (or outside stack)
- * NOT_STACK   unable to determine (no frame pointers, etc)
- */
-static inline int arch_within_stack_frames(const void * const stack,
-  const void * const stackend,
-  const void *obj, unsigned long len)
-{
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(1);
-   if (oldframe)
-   frame = __builtin_frame_address(2);
-   /*
-* low --> high
-* [saved bp][saved ip][args][local vars][saved bp][saved ip]
-* ^^
-*   allow copies only within here
-*/
-   while (stack <= frame && frame < stackend) {
-   /*
-* If obj + len extends past the last frame, this
-* check won't pass and the next frame will be 0,
-* causing us to bail out and correctly report
-* the copy as invalid.
-*/
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
-   }
-   return BAD_STACK;
-#else
-   return NOT_STACK;
-#endif
-}
-
-#else /* !__ASSEMBLY__ */
-
+#ifdef __ASSEMBLY__
 #ifdef CONFIG_X86_64
 # define cpu_current_top_of_stack (cpu_tss_rw + TSS_sp1)
 #endif
-
 #endif
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 02d6f5c..3b8afd5 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -70,7 +70,7 @@ obj-$(CONFIG_IA32_EMULATION)  += tls.o
 obj-y  += step.o
 obj-$(CONFIG_INTEL_TXT)+= tboot.o
 obj-$(CONFIG_ISA_DMA_API)  += i8237.o
-obj-$(CONFIG_STACKTRACE)   += stacktrace.o
+obj-y  += stacktrace.o
 obj-y  += cpu/
 obj-y  += acpi/
 obj-y  += reboot.o
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 093f2ea..ff178a0 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -12,6 +12,54 @@
 #include 
 #include 
 
+
+/*
+ * Walks up the stack frames to make sure that the specified object is
+ * entirely contained by a single stack frame.
+ *
+ * Returns:
+ * GOOD_FRAME  if within a frame
+ * BAD_STACK   if placed across a frame boundary (or outside stack)
+ * NOT_STACK   unable to determine (no frame pointers, etc)
+ */
+int arch_within_stack_frames(const void * const stack,
+const void * const stackend,
+const void *obj, unsigned long len)
+{
+#if defined(CONFIG_FRAME_POINTER)
+   const void *frame = NULL;
+   const void *oldframe;
+
+   oldframe = __builtin_frame_address(2);
+   if (oldframe)
+   frame = __builtin_frame_address(3);
+   /*
+* low 

[PATCH v3 1/3] stacktrace: move arch_within_stack_frames from thread_info.h

2018-04-09 Thread kpark3469
From: Sahara 

Since the inlined arch_within_stack_frames function was placed within
asm/thread_info.h, using stacktrace functions to unwind stack was
restricted. Now in order to have this function use more abundant apis,
it is moved to architecture's stacktrace.c. And, it is changed from
inline to noinline function to clearly have three depth calls like:

do_usercopy_stack()
  copy_[to|from]_user() : inline
check_copy_size() : inline
  __check_object_size()
check_stack_object()
  arch_within_stack_frames()

With this change, the x86's implementation was slightly changed also.

Signed-off-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 49 
 include/linux/page_ext.h   |  1 -
 include/linux/stacktrace.h | 24 ++
 include/linux/thread_info.h| 21 
 mm/usercopy.c  |  2 +-
 7 files changed, 76 insertions(+), 74 deletions(-)

diff --git a/arch/x86/include/asm/thread_info.h 
b/arch/x86/include/asm/thread_info.h
index a5d9521..e25d70a 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -156,59 +156,10 @@ struct thread_info {
  *
  * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
-#ifndef __ASSEMBLY__
-
-/*
- * Walks up the stack frames to make sure that the specified object is
- * entirely contained by a single stack frame.
- *
- * Returns:
- * GOOD_FRAME  if within a frame
- * BAD_STACK   if placed across a frame boundary (or outside stack)
- * NOT_STACK   unable to determine (no frame pointers, etc)
- */
-static inline int arch_within_stack_frames(const void * const stack,
-  const void * const stackend,
-  const void *obj, unsigned long len)
-{
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(1);
-   if (oldframe)
-   frame = __builtin_frame_address(2);
-   /*
-* low --> high
-* [saved bp][saved ip][args][local vars][saved bp][saved ip]
-* ^^
-*   allow copies only within here
-*/
-   while (stack <= frame && frame < stackend) {
-   /*
-* If obj + len extends past the last frame, this
-* check won't pass and the next frame will be 0,
-* causing us to bail out and correctly report
-* the copy as invalid.
-*/
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
-   }
-   return BAD_STACK;
-#else
-   return NOT_STACK;
-#endif
-}
-
-#else /* !__ASSEMBLY__ */
-
+#ifdef __ASSEMBLY__
 #ifdef CONFIG_X86_64
 # define cpu_current_top_of_stack (cpu_tss_rw + TSS_sp1)
 #endif
-
 #endif
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 02d6f5c..3b8afd5 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -70,7 +70,7 @@ obj-$(CONFIG_IA32_EMULATION)  += tls.o
 obj-y  += step.o
 obj-$(CONFIG_INTEL_TXT)+= tboot.o
 obj-$(CONFIG_ISA_DMA_API)  += i8237.o
-obj-$(CONFIG_STACKTRACE)   += stacktrace.o
+obj-y  += stacktrace.o
 obj-y  += cpu/
 obj-y  += acpi/
 obj-y  += reboot.o
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 093f2ea..ff178a0 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -12,6 +12,54 @@
 #include 
 #include 
 
+
+/*
+ * Walks up the stack frames to make sure that the specified object is
+ * entirely contained by a single stack frame.
+ *
+ * Returns:
+ * GOOD_FRAME  if within a frame
+ * BAD_STACK   if placed across a frame boundary (or outside stack)
+ * NOT_STACK   unable to determine (no frame pointers, etc)
+ */
+int arch_within_stack_frames(const void * const stack,
+const void * const stackend,
+const void *obj, unsigned long len)
+{
+#if defined(CONFIG_FRAME_POINTER)
+   const void *frame = NULL;
+   const void *oldframe;
+
+   oldframe = __builtin_frame_address(2);
+   if (oldframe)
+   frame = __builtin_frame_address(3);
+   /*
+* low --> high
+* [saved bp][saved 

[PATCH v3 0/3] usercopy: reimplement arch_within_stack_frames

2018-04-09 Thread kpark3469
From: Sahara 

This series of patches introduce the arm64 arch_within_stack_frames
implementation using stacktrace functions. Also the base code is
moved from thread_info.h to stacktrace.h. x86 code is reimplemented
to use frame pointer unwinder functions.

Note: The code is still missing in case of using x86 ORC unwinder and
guess unwinder.

v2 changes:
 - Remove 'arm64: usercopy: consider dynamic array stack variable'
 - minor fix in x86 arch_within_stack_frames code.
v3 changes:
 - Fix build problem caused by circular inclusion of header in x86 UP config

James Morse (1):
  arm64: usercopy: implement arch_within_stack_frames

Sahara (2):
  stacktrace: move arch_within_stack_frames from thread_info.h
  x86: usercopy: reimplement arch_within_stack_frames with unwinder

 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 +
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/include/asm/unwind.h  |  5 +++
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 87 ++
 arch/x86/kernel/unwind_frame.c |  4 +-
 include/linux/page_ext.h   |  1 -
 include/linux/stacktrace.h | 24 +++
 include/linux/thread_info.h| 21 -
 mm/usercopy.c  |  2 +-
 11 files changed, 197 insertions(+), 77 deletions(-)

-- 
2.7.4



[PATCH v3 0/3] usercopy: reimplement arch_within_stack_frames

2018-04-09 Thread kpark3469
From: Sahara 

This series of patches introduce the arm64 arch_within_stack_frames
implementation using stacktrace functions. Also the base code is
moved from thread_info.h to stacktrace.h. x86 code is reimplemented
to use frame pointer unwinder functions.

Note: The code is still missing in case of using x86 ORC unwinder and
guess unwinder.

v2 changes:
 - Remove 'arm64: usercopy: consider dynamic array stack variable'
 - minor fix in x86 arch_within_stack_frames code.
v3 changes:
 - Fix build problem caused by circular inclusion of header in x86 UP config

James Morse (1):
  arm64: usercopy: implement arch_within_stack_frames

Sahara (2):
  stacktrace: move arch_within_stack_frames from thread_info.h
  x86: usercopy: reimplement arch_within_stack_frames with unwinder

 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 +
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/include/asm/unwind.h  |  5 +++
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 87 ++
 arch/x86/kernel/unwind_frame.c |  4 +-
 include/linux/page_ext.h   |  1 -
 include/linux/stacktrace.h | 24 +++
 include/linux/thread_info.h| 21 -
 mm/usercopy.c  |  2 +-
 11 files changed, 197 insertions(+), 77 deletions(-)

-- 
2.7.4



[PATCH v2 2/3] arm64: usercopy: implement arch_within_stack_frames

2018-04-09 Thread kpark3469
From: James Morse 

This implements arch_within_stack_frames() for arm64 that should
validate if a given object is contained by a kernel stack frame.

Signed-off-by: James Morse 
Reviewed-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 ++
 2 files changed, 77 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 177be0d..72d0747 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -128,6 +128,7 @@ config ARM64
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
select HAVE_KRETPROBES
+   select HAVE_ARCH_WITHIN_STACK_FRAMES
select IOMMU_DMA if IOMMU_SUPPORT
select IRQ_DOMAIN
select IRQ_FORCED_THREADING
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 33c4028..9918698 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -26,6 +26,11 @@
 #include 
 #include 
 
+#define FAKE_FRAME(frame, my_func) do {\
+   frame.fp = (unsigned long)__builtin_frame_address(0);   \
+   frame.pc = (unsigned long)my_func;  \
+} while (0)
+
 /*
  * AArch64 PCS assigns the frame pointer to x29.
  *
@@ -99,6 +104,77 @@ void notrace walk_stackframe(struct task_struct *tsk, 
struct stackframe *frame,
}
 }
 
+struct check_frame_arg {
+   unsigned long obj_start;
+   unsigned long obj_end;
+   unsigned long frame_start;
+   int discard_frames;
+   int err;
+};
+
+static int check_frame(struct stackframe *frame, void *d)
+{
+   struct check_frame_arg *arg = d;
+   unsigned long frame_end = frame->fp;
+
+   /* object overlaps multiple frames */
+   if (arg->obj_start < frame->fp && frame->fp < arg->obj_end) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   /*
+* Discard frames and check object is in a frame written early
+* enough.
+*/
+   if (arg->discard_frames)
+   arg->discard_frames--;
+   else if ((arg->frame_start <= arg->obj_start &&
+   arg->obj_start < frame_end) &&
+   (arg->frame_start < arg->obj_end && arg->obj_end <= frame_end))
+   return 1;
+
+   /* object exists in a previous frame */
+   if (arg->obj_end < arg->frame_start) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   arg->frame_start = frame_end + 0x10;
+
+   return 0;
+}
+
+/* Check obj doesn't overlap a stack frame record */
+int arch_within_stack_frames(const void *stack,
+const void *stack_end,
+const void *obj, unsigned long obj_len)
+{
+   struct stackframe frame;
+   struct check_frame_arg arg;
+
+   if (!IS_ENABLED(CONFIG_FRAME_POINTER))
+   return NOT_STACK;
+
+   arg.err = GOOD_FRAME;
+   arg.obj_start = (unsigned long)obj;
+   arg.obj_end = arg.obj_start + obj_len;
+
+   FAKE_FRAME(frame, arch_within_stack_frames);
+   arg.frame_start = frame.fp;
+
+   /*
+* Skip 4 non-inlined frames: ,
+* arch_within_stack_frames(), check_stack_object() and
+* __check_object_size().
+*/
+   arg.discard_frames = 4;
+
+   walk_stackframe(current, , check_frame, );
+
+   return arg.err;
+}
+
 #ifdef CONFIG_STACKTRACE
 struct stack_trace_data {
struct stack_trace *trace;
-- 
2.7.4



[PATCH v2 3/3] x86: usercopy: reimplement arch_within_stack_frames with unwinder

2018-04-09 Thread kpark3469
From: Sahara 

The old arch_within_stack_frames which used the frame pointer is
now reimplemented to use frame pointer unwinder apis. So the main
functionality is same as before.

Signed-off-by: Sahara 
---
 arch/x86/include/asm/unwind.h  |  5 
 arch/x86/kernel/stacktrace.c   | 64 +-
 arch/x86/kernel/unwind_frame.c |  4 +--
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h
index 1f86e1b..6f04906f 100644
--- a/arch/x86/include/asm/unwind.h
+++ b/arch/x86/include/asm/unwind.h
@@ -87,6 +87,11 @@ void unwind_init(void);
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
void *orc, size_t orc_size);
 #else
+#ifdef CONFIG_UNWINDER_FRAME_POINTER
+#define FRAME_HEADER_SIZE (sizeof(long) * 2)
+size_t regs_size(struct pt_regs *regs);
+#endif
+
 static inline void unwind_init(void) {}
 static inline
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index f433a33..11ec101 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -12,6 +12,33 @@
 #include 
 
 
+static inline void *get_cur_frame(struct unwind_state *state)
+{
+   void *frame = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs)
+   frame = (void *)state->regs;
+   else
+   frame = (void *)state->bp;
+#endif
+   return frame;
+}
+
+static inline void *get_frame_end(struct unwind_state *state)
+{
+   void *frame_end = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs) {
+   frame_end = (void *)state->regs + regs_size(state->regs);
+   } else {
+   frame_end = (void *)state->bp + FRAME_HEADER_SIZE;
+   }
+#endif
+   return frame_end;
+}
+
 /*
  * Walks up the stack frames to make sure that the specified object is
  * entirely contained by a single stack frame.
@@ -25,31 +52,42 @@ int arch_within_stack_frames(const void * const stack,
 const void * const stackend,
 const void *obj, unsigned long len)
 {
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(2);
-   if (oldframe)
-   frame = __builtin_frame_address(3);
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   struct unwind_state state;
+   void *prev_frame_end = NULL;
/*
 * low --> high
 * [saved bp][saved ip][args][local vars][saved bp][saved ip]
 * ^^
 *   allow copies only within here
+*
+* Skip 3 non-inlined frames: arch_within_stack_frames(),
+* check_stack_object() and __check_object_size().
+*
 */
-   while (stack <= frame && frame < stackend) {
+   unsigned int discard_frames = 3;
+
+   for (unwind_start(, current, NULL, NULL); !unwind_done();
+unwind_next_frame()) {
/*
 * If obj + len extends past the last frame, this
 * check won't pass and the next frame will be 0,
 * causing us to bail out and correctly report
 * the copy as invalid.
 */
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
+   if (discard_frames) {
+   discard_frames--;
+   } else {
+   void *frame = get_cur_frame();
+
+   if (!frame || !prev_frame_end)
+   return NOT_STACK;
+   if (obj + len <= frame)
+   return obj >= prev_frame_end ?
+   GOOD_FRAME : BAD_STACK;
+   }
+   /* save current frame end before move to next frame */
+   prev_frame_end = get_frame_end();
}
return BAD_STACK;
 #else
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index 3dc26f9..c8bfa5c 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -8,8 +8,6 @@
 #include 
 #include 
 
-#define FRAME_HEADER_SIZE (sizeof(long) * 2)
-
 unsigned long unwind_get_return_address(struct unwind_state *state)
 {
if (unwind_done(state))
@@ -69,7 +67,7 @@ static void unwind_dump(struct unwind_state *state)
}
 }
 
-static size_t regs_size(struct pt_regs *regs)
+size_t regs_size(struct pt_regs *regs)
 {
/* x86_32 regs 

[PATCH v2 2/3] arm64: usercopy: implement arch_within_stack_frames

2018-04-09 Thread kpark3469
From: James Morse 

This implements arch_within_stack_frames() for arm64 that should
validate if a given object is contained by a kernel stack frame.

Signed-off-by: James Morse 
Reviewed-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 76 ++
 2 files changed, 77 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 177be0d..72d0747 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -128,6 +128,7 @@ config ARM64
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
select HAVE_KRETPROBES
+   select HAVE_ARCH_WITHIN_STACK_FRAMES
select IOMMU_DMA if IOMMU_SUPPORT
select IRQ_DOMAIN
select IRQ_FORCED_THREADING
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 33c4028..9918698 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -26,6 +26,11 @@
 #include 
 #include 
 
+#define FAKE_FRAME(frame, my_func) do {\
+   frame.fp = (unsigned long)__builtin_frame_address(0);   \
+   frame.pc = (unsigned long)my_func;  \
+} while (0)
+
 /*
  * AArch64 PCS assigns the frame pointer to x29.
  *
@@ -99,6 +104,77 @@ void notrace walk_stackframe(struct task_struct *tsk, 
struct stackframe *frame,
}
 }
 
+struct check_frame_arg {
+   unsigned long obj_start;
+   unsigned long obj_end;
+   unsigned long frame_start;
+   int discard_frames;
+   int err;
+};
+
+static int check_frame(struct stackframe *frame, void *d)
+{
+   struct check_frame_arg *arg = d;
+   unsigned long frame_end = frame->fp;
+
+   /* object overlaps multiple frames */
+   if (arg->obj_start < frame->fp && frame->fp < arg->obj_end) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   /*
+* Discard frames and check object is in a frame written early
+* enough.
+*/
+   if (arg->discard_frames)
+   arg->discard_frames--;
+   else if ((arg->frame_start <= arg->obj_start &&
+   arg->obj_start < frame_end) &&
+   (arg->frame_start < arg->obj_end && arg->obj_end <= frame_end))
+   return 1;
+
+   /* object exists in a previous frame */
+   if (arg->obj_end < arg->frame_start) {
+   arg->err = BAD_STACK;
+   return 1;
+   }
+
+   arg->frame_start = frame_end + 0x10;
+
+   return 0;
+}
+
+/* Check obj doesn't overlap a stack frame record */
+int arch_within_stack_frames(const void *stack,
+const void *stack_end,
+const void *obj, unsigned long obj_len)
+{
+   struct stackframe frame;
+   struct check_frame_arg arg;
+
+   if (!IS_ENABLED(CONFIG_FRAME_POINTER))
+   return NOT_STACK;
+
+   arg.err = GOOD_FRAME;
+   arg.obj_start = (unsigned long)obj;
+   arg.obj_end = arg.obj_start + obj_len;
+
+   FAKE_FRAME(frame, arch_within_stack_frames);
+   arg.frame_start = frame.fp;
+
+   /*
+* Skip 4 non-inlined frames: ,
+* arch_within_stack_frames(), check_stack_object() and
+* __check_object_size().
+*/
+   arg.discard_frames = 4;
+
+   walk_stackframe(current, , check_frame, );
+
+   return arg.err;
+}
+
 #ifdef CONFIG_STACKTRACE
 struct stack_trace_data {
struct stack_trace *trace;
-- 
2.7.4



[PATCH v2 3/3] x86: usercopy: reimplement arch_within_stack_frames with unwinder

2018-04-09 Thread kpark3469
From: Sahara 

The old arch_within_stack_frames which used the frame pointer is
now reimplemented to use frame pointer unwinder apis. So the main
functionality is same as before.

Signed-off-by: Sahara 
---
 arch/x86/include/asm/unwind.h  |  5 
 arch/x86/kernel/stacktrace.c   | 64 +-
 arch/x86/kernel/unwind_frame.c |  4 +--
 3 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h
index 1f86e1b..6f04906f 100644
--- a/arch/x86/include/asm/unwind.h
+++ b/arch/x86/include/asm/unwind.h
@@ -87,6 +87,11 @@ void unwind_init(void);
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
void *orc, size_t orc_size);
 #else
+#ifdef CONFIG_UNWINDER_FRAME_POINTER
+#define FRAME_HEADER_SIZE (sizeof(long) * 2)
+size_t regs_size(struct pt_regs *regs);
+#endif
+
 static inline void unwind_init(void) {}
 static inline
 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index f433a33..11ec101 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -12,6 +12,33 @@
 #include 
 
 
+static inline void *get_cur_frame(struct unwind_state *state)
+{
+   void *frame = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs)
+   frame = (void *)state->regs;
+   else
+   frame = (void *)state->bp;
+#endif
+   return frame;
+}
+
+static inline void *get_frame_end(struct unwind_state *state)
+{
+   void *frame_end = NULL;
+
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   if (state->regs) {
+   frame_end = (void *)state->regs + regs_size(state->regs);
+   } else {
+   frame_end = (void *)state->bp + FRAME_HEADER_SIZE;
+   }
+#endif
+   return frame_end;
+}
+
 /*
  * Walks up the stack frames to make sure that the specified object is
  * entirely contained by a single stack frame.
@@ -25,31 +52,42 @@ int arch_within_stack_frames(const void * const stack,
 const void * const stackend,
 const void *obj, unsigned long len)
 {
-#if defined(CONFIG_FRAME_POINTER)
-   const void *frame = NULL;
-   const void *oldframe;
-
-   oldframe = __builtin_frame_address(2);
-   if (oldframe)
-   frame = __builtin_frame_address(3);
+#if defined(CONFIG_UNWINDER_FRAME_POINTER)
+   struct unwind_state state;
+   void *prev_frame_end = NULL;
/*
 * low --> high
 * [saved bp][saved ip][args][local vars][saved bp][saved ip]
 * ^^
 *   allow copies only within here
+*
+* Skip 3 non-inlined frames: arch_within_stack_frames(),
+* check_stack_object() and __check_object_size().
+*
 */
-   while (stack <= frame && frame < stackend) {
+   unsigned int discard_frames = 3;
+
+   for (unwind_start(, current, NULL, NULL); !unwind_done();
+unwind_next_frame()) {
/*
 * If obj + len extends past the last frame, this
 * check won't pass and the next frame will be 0,
 * causing us to bail out and correctly report
 * the copy as invalid.
 */
-   if (obj + len <= frame)
-   return obj >= oldframe + 2 * sizeof(void *) ?
-   GOOD_FRAME : BAD_STACK;
-   oldframe = frame;
-   frame = *(const void * const *)frame;
+   if (discard_frames) {
+   discard_frames--;
+   } else {
+   void *frame = get_cur_frame();
+
+   if (!frame || !prev_frame_end)
+   return NOT_STACK;
+   if (obj + len <= frame)
+   return obj >= prev_frame_end ?
+   GOOD_FRAME : BAD_STACK;
+   }
+   /* save current frame end before move to next frame */
+   prev_frame_end = get_frame_end();
}
return BAD_STACK;
 #else
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index 3dc26f9..c8bfa5c 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -8,8 +8,6 @@
 #include 
 #include 
 
-#define FRAME_HEADER_SIZE (sizeof(long) * 2)
-
 unsigned long unwind_get_return_address(struct unwind_state *state)
 {
if (unwind_done(state))
@@ -69,7 +67,7 @@ static void unwind_dump(struct unwind_state *state)
}
 }
 
-static size_t regs_size(struct pt_regs *regs)
+size_t regs_size(struct pt_regs *regs)
 {
/* x86_32 regs from kernel mode are two words shorter: */
if 

[PATCH v2 1/3] stacktrace: move arch_within_stack_frames from thread_info.h

2018-04-09 Thread kpark3469
From: Sahara 

Since the inlined arch_within_stack_frames function was placed within
asm/thread_info.h, using stacktrace functions to unwind stack was
restricted. Now in order to have this function use more abundant apis,
it is moved to architecture's stacktrace.c. And, it is changed from
inline to noinline function to clearly have three depth calls like:

do_usercopy_stack()
  copy_[to|from]_user() : inline
check_copy_size() : inline
  __check_object_size()
check_stack_object()
  arch_within_stack_frames()

With this change, the x86's implementation was slightly changed also.
And, linux/stacktrace.h includes asm/stacktrace.h from now on.

Signed-off-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/arm/kernel/stacktrace.c   |  1 -
 arch/arm64/kernel/stacktrace.c |  1 -
 arch/mips/kernel/stacktrace.c  |  1 -
 arch/mips/oprofile/backtrace.c |  1 -
 arch/sh/kernel/stacktrace.c|  1 -
 arch/sparc/kernel/stacktrace.c |  1 -
 arch/um/kernel/stacktrace.c|  1 -
 arch/unicore32/kernel/process.c|  1 -
 arch/unicore32/kernel/stacktrace.c |  2 --
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 50 -
 arch/xtensa/kernel/stacktrace.c|  1 -
 include/linux/page_ext.h   |  1 -
 include/linux/stacktrace.h | 25 +++
 include/linux/thread_info.h| 21 
 kernel/sysctl.c|  1 -
 mm/usercopy.c  |  2 +-
 18 files changed, 77 insertions(+), 87 deletions(-)

diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index a56e7c8..d7d629b 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -4,7 +4,6 @@
 #include 
 
 #include 
-#include 
 #include 
 
 #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index d5718a0..33c4028 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -25,7 +25,6 @@
 
 #include 
 #include 
-#include 
 
 /*
  * AArch64 PCS assigns the frame pointer to x29.
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c
index 7c7c902..0b44e10 100644
--- a/arch/mips/kernel/stacktrace.c
+++ b/arch/mips/kernel/stacktrace.c
@@ -8,7 +8,6 @@
 #include 
 #include 
 #include 
-#include 
 
 /*
  * Save stack-backtrace addresses into a stack_trace buffer:
diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c
index 806fb79..845ff8c 100644
--- a/arch/mips/oprofile/backtrace.c
+++ b/arch/mips/oprofile/backtrace.c
@@ -4,7 +4,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 7a73d27..7a7ac4c 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/arch/sh/kernel/stacktrace.c
@@ -16,7 +16,6 @@
 #include 
 #include 
 #include 
-#include 
 
 static int save_stack_stack(void *data, char *name)
 {
diff --git a/arch/sparc/kernel/stacktrace.c b/arch/sparc/kernel/stacktrace.c
index be4c14c..42cdf86 100644
--- a/arch/sparc/kernel/stacktrace.c
+++ b/arch/sparc/kernel/stacktrace.c
@@ -5,7 +5,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "kstack.h"
 
diff --git a/arch/um/kernel/stacktrace.c b/arch/um/kernel/stacktrace.c
index ebe7bcf..a0d556e 100644
--- a/arch/um/kernel/stacktrace.c
+++ b/arch/um/kernel/stacktrace.c
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include 
-#include 
 
 void dump_trace(struct task_struct *tsk,
const struct stacktrace_ops *ops,
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
index 2bc10b8..ffca651 100644
--- a/arch/unicore32/kernel/process.c
+++ b/arch/unicore32/kernel/process.c
@@ -36,7 +36,6 @@
 
 #include 
 #include 
-#include 
 
 #include "setup.h"
 
diff --git a/arch/unicore32/kernel/stacktrace.c 
b/arch/unicore32/kernel/stacktrace.c
index 9976e76..f9cd2a4 100644
--- a/arch/unicore32/kernel/stacktrace.c
+++ b/arch/unicore32/kernel/stacktrace.c
@@ -14,8 +14,6 @@
 #include 
 #include 
 
-#include 
-
 #if defined(CONFIG_FRAME_POINTER)
 /*
  * Unwind the current stack frame and store the new register values in the
diff --git a/arch/x86/include/asm/thread_info.h 
b/arch/x86/include/asm/thread_info.h
index a5d9521..e25d70a 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -156,59 +156,10 @@ struct thread_info {
  *
  * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
-#ifndef __ASSEMBLY__
-
-/*
- * Walks up the stack frames to make sure that the specified object is
- * entirely contained by a single stack frame.
- *
- * Returns:
- * GOOD_FRAME  if within a frame
- * BAD_STACK   if placed across a 

[PATCH v2 1/3] stacktrace: move arch_within_stack_frames from thread_info.h

2018-04-09 Thread kpark3469
From: Sahara 

Since the inlined arch_within_stack_frames function was placed within
asm/thread_info.h, using stacktrace functions to unwind stack was
restricted. Now in order to have this function use more abundant apis,
it is moved to architecture's stacktrace.c. And, it is changed from
inline to noinline function to clearly have three depth calls like:

do_usercopy_stack()
  copy_[to|from]_user() : inline
check_copy_size() : inline
  __check_object_size()
check_stack_object()
  arch_within_stack_frames()

With this change, the x86's implementation was slightly changed also.
And, linux/stacktrace.h includes asm/stacktrace.h from now on.

Signed-off-by: Sahara 
Reviewed-by: Kees Cook 
---
 arch/arm/kernel/stacktrace.c   |  1 -
 arch/arm64/kernel/stacktrace.c |  1 -
 arch/mips/kernel/stacktrace.c  |  1 -
 arch/mips/oprofile/backtrace.c |  1 -
 arch/sh/kernel/stacktrace.c|  1 -
 arch/sparc/kernel/stacktrace.c |  1 -
 arch/um/kernel/stacktrace.c|  1 -
 arch/unicore32/kernel/process.c|  1 -
 arch/unicore32/kernel/stacktrace.c |  2 --
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 50 -
 arch/xtensa/kernel/stacktrace.c|  1 -
 include/linux/page_ext.h   |  1 -
 include/linux/stacktrace.h | 25 +++
 include/linux/thread_info.h| 21 
 kernel/sysctl.c|  1 -
 mm/usercopy.c  |  2 +-
 18 files changed, 77 insertions(+), 87 deletions(-)

diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index a56e7c8..d7d629b 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -4,7 +4,6 @@
 #include 
 
 #include 
-#include 
 #include 
 
 #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index d5718a0..33c4028 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -25,7 +25,6 @@
 
 #include 
 #include 
-#include 
 
 /*
  * AArch64 PCS assigns the frame pointer to x29.
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c
index 7c7c902..0b44e10 100644
--- a/arch/mips/kernel/stacktrace.c
+++ b/arch/mips/kernel/stacktrace.c
@@ -8,7 +8,6 @@
 #include 
 #include 
 #include 
-#include 
 
 /*
  * Save stack-backtrace addresses into a stack_trace buffer:
diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c
index 806fb79..845ff8c 100644
--- a/arch/mips/oprofile/backtrace.c
+++ b/arch/mips/oprofile/backtrace.c
@@ -4,7 +4,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 7a73d27..7a7ac4c 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/arch/sh/kernel/stacktrace.c
@@ -16,7 +16,6 @@
 #include 
 #include 
 #include 
-#include 
 
 static int save_stack_stack(void *data, char *name)
 {
diff --git a/arch/sparc/kernel/stacktrace.c b/arch/sparc/kernel/stacktrace.c
index be4c14c..42cdf86 100644
--- a/arch/sparc/kernel/stacktrace.c
+++ b/arch/sparc/kernel/stacktrace.c
@@ -5,7 +5,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include "kstack.h"
 
diff --git a/arch/um/kernel/stacktrace.c b/arch/um/kernel/stacktrace.c
index ebe7bcf..a0d556e 100644
--- a/arch/um/kernel/stacktrace.c
+++ b/arch/um/kernel/stacktrace.c
@@ -14,7 +14,6 @@
 #include 
 #include 
 #include 
-#include 
 
 void dump_trace(struct task_struct *tsk,
const struct stacktrace_ops *ops,
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
index 2bc10b8..ffca651 100644
--- a/arch/unicore32/kernel/process.c
+++ b/arch/unicore32/kernel/process.c
@@ -36,7 +36,6 @@
 
 #include 
 #include 
-#include 
 
 #include "setup.h"
 
diff --git a/arch/unicore32/kernel/stacktrace.c 
b/arch/unicore32/kernel/stacktrace.c
index 9976e76..f9cd2a4 100644
--- a/arch/unicore32/kernel/stacktrace.c
+++ b/arch/unicore32/kernel/stacktrace.c
@@ -14,8 +14,6 @@
 #include 
 #include 
 
-#include 
-
 #if defined(CONFIG_FRAME_POINTER)
 /*
  * Unwind the current stack frame and store the new register values in the
diff --git a/arch/x86/include/asm/thread_info.h 
b/arch/x86/include/asm/thread_info.h
index a5d9521..e25d70a 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -156,59 +156,10 @@ struct thread_info {
  *
  * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
-#ifndef __ASSEMBLY__
-
-/*
- * Walks up the stack frames to make sure that the specified object is
- * entirely contained by a single stack frame.
- *
- * Returns:
- * GOOD_FRAME  if within a frame
- * BAD_STACK   if placed across a frame boundary (or outside stack)
- * NOT_STACK   unable to determine 

[PATCH v2 0/3] usercopy: reimplement arch_within_stack_frames

2018-04-09 Thread kpark3469
From: Sahara 

This series of patches introduce the arm64 arch_within_stack_frames
implementation using stacktrace functions. Also the base code is
moved from thread_info.h to stacktrace.h. x86 code is reimplemented
to use frame pointer unwinder functions.

Note: The code is still missing in case of using x86 ORC unwinder and
guess unwinder.

v2 changes:
 - Remove 'arm64: usercopy: consider dynamic array stack variable'
 - minor fix in x86 arch_within_stack_frames code.

James Morse (1):
  arm64: usercopy: implement arch_within_stack_frames

Sahara (2):
  stacktrace: move arch_within_stack_frames from thread_info.h
  x86: usercopy: reimplement arch_within_stack_frames with unwinder

 arch/arm/kernel/stacktrace.c   |  1 -
 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 77 -
 arch/mips/kernel/stacktrace.c  |  1 -
 arch/mips/oprofile/backtrace.c |  1 -
 arch/sh/kernel/stacktrace.c|  1 -
 arch/sparc/kernel/stacktrace.c |  1 -
 arch/um/kernel/stacktrace.c|  1 -
 arch/unicore32/kernel/process.c|  1 -
 arch/unicore32/kernel/stacktrace.c |  2 -
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/include/asm/unwind.h  |  5 +++
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 88 +-
 arch/x86/kernel/unwind_frame.c |  4 +-
 arch/xtensa/kernel/stacktrace.c|  1 -
 include/linux/page_ext.h   |  1 -
 include/linux/stacktrace.h | 25 +++
 include/linux/thread_info.h| 21 -
 kernel/sysctl.c|  1 -
 mm/usercopy.c  |  2 +-
 21 files changed, 198 insertions(+), 90 deletions(-)

-- 
2.7.4



[PATCH v2 0/3] usercopy: reimplement arch_within_stack_frames

2018-04-09 Thread kpark3469
From: Sahara 

This series of patches introduce the arm64 arch_within_stack_frames
implementation using stacktrace functions. Also the base code is
moved from thread_info.h to stacktrace.h. x86 code is reimplemented
to use frame pointer unwinder functions.

Note: The code is still missing in case of using x86 ORC unwinder and
guess unwinder.

v2 changes:
 - Remove 'arm64: usercopy: consider dynamic array stack variable'
 - minor fix in x86 arch_within_stack_frames code.

James Morse (1):
  arm64: usercopy: implement arch_within_stack_frames

Sahara (2):
  stacktrace: move arch_within_stack_frames from thread_info.h
  x86: usercopy: reimplement arch_within_stack_frames with unwinder

 arch/arm/kernel/stacktrace.c   |  1 -
 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/stacktrace.c | 77 -
 arch/mips/kernel/stacktrace.c  |  1 -
 arch/mips/oprofile/backtrace.c |  1 -
 arch/sh/kernel/stacktrace.c|  1 -
 arch/sparc/kernel/stacktrace.c |  1 -
 arch/um/kernel/stacktrace.c|  1 -
 arch/unicore32/kernel/process.c|  1 -
 arch/unicore32/kernel/stacktrace.c |  2 -
 arch/x86/include/asm/thread_info.h | 51 +-
 arch/x86/include/asm/unwind.h  |  5 +++
 arch/x86/kernel/Makefile   |  2 +-
 arch/x86/kernel/stacktrace.c   | 88 +-
 arch/x86/kernel/unwind_frame.c |  4 +-
 arch/xtensa/kernel/stacktrace.c|  1 -
 include/linux/page_ext.h   |  1 -
 include/linux/stacktrace.h | 25 +++
 include/linux/thread_info.h| 21 -
 kernel/sysctl.c|  1 -
 mm/usercopy.c  |  2 +-
 21 files changed, 198 insertions(+), 90 deletions(-)

-- 
2.7.4



[PATCH] pty: cancel pty slave port buf's work in tty_release

2017-12-12 Thread kpark3469
From: Sahara 

In case that CONFIG_SLUB_DEBUG is on and pty is used, races between
release_one_tty and flush_to_ldisc work threads may happen and lead
to use-after-free condition on tty->link->port. Because SLUB_DEBUG
is turned on, freed tty->link->port is filled with POISON_FREE value.
So far without SLUB_DEBUG, port was filled with zero and flush_to_ldisc
could return without a problem by checking if tty is NULL.

CPU 0 CPU 1
- -
release_tty   pty_write
   cancel_work_sync(tty) to = tty->link
   tty_kref_put(tty->link)   tty_schedule_flip(to->port)
  << workqueue >> ...
  release_one_tty ...
 pty_cleanup  ...
kfree(tty->link->port)   << workqueue >>
 flush_to_ldisc
tty = READ_ONCE(port->itty)
tty is 0x6b6b6b6b6b6b6b6b
!!PANIC!! access tty->ldisc

 Unable to handle kernel paging request at virtual address 6b6b6b6b6b6b6b93
 pgd = ffc0eb1c3000
 [6b6b6b6b6b6b6b93] *pgd=, *pud=
 [ cut here ]
 Kernel BUG at ff800851154c [verbose debug info unavailable]
 Internal error: Oops - BUG: 9604 [#1] PREEMPT SMP
 CPU: 3 PID: 265 Comm: kworker/u8:9 Tainted: GW 3.18.31-g0a58eeb #1
 Hardware name: Qualcomm Technologies, Inc. MSM 8996pro v1.1 + PMI8996 Carbide 
(DT)
 Workqueue: events_unbound flush_to_ldisc
 task: ffc0ed610ec0 ti: ffc0ed624000 task.ti: ffc0ed624000
 PC is at ldsem_down_read_trylock+0x0/0x4c
 LR is at tty_ldisc_ref+0x24/0x4c
 pc : [] lr : [] pstate: 80400145
 sp : ffc0ed627cd0
 x29: ffc0ed627cd0 x28: 
 x27: ff8009e05000 x26: ffc0d382cfa0
 x25:  x24: ff800a012f08
 x23:  x22: ffc0703fbc88
 x21: 6b6b6b6b6b6b6b6b x20: 6b6b6b6b6b6b6b93
 x19:  x18: 0001
 x17: 00e8f80d6f53 x16: 0001
 x15: 007f7d826fff x14: 00a0
 x13:  x12: 0109
 x11:  x10: 
 x9 : ffc0ed624000 x8 : ffc0ed611580
 x7 :  x6 : ff800a42e000
 x5 : 03fc x4 : 03bd1201
 x3 : 0001 x2 : 0001
 x1 : ff800851004c x0 : 6b6b6b6b6b6b6b93

Signed-off-by: Sahara 
---
 drivers/tty/tty_io.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index dc60aee..a6ca634 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1476,6 +1476,8 @@ static void release_tty(struct tty_struct *tty, int idx)
if (tty->link)
tty->link->port->itty = NULL;
tty_buffer_cancel_work(tty->port);
+   if (tty->link)
+   tty_buffer_cancel_work(tty->link->port);
 
tty_kref_put(tty->link);
tty_kref_put(tty);
-- 
2.7.4



[PATCH] pty: cancel pty slave port buf's work in tty_release

2017-12-12 Thread kpark3469
From: Sahara 

In case that CONFIG_SLUB_DEBUG is on and pty is used, races between
release_one_tty and flush_to_ldisc work threads may happen and lead
to use-after-free condition on tty->link->port. Because SLUB_DEBUG
is turned on, freed tty->link->port is filled with POISON_FREE value.
So far without SLUB_DEBUG, port was filled with zero and flush_to_ldisc
could return without a problem by checking if tty is NULL.

CPU 0 CPU 1
- -
release_tty   pty_write
   cancel_work_sync(tty) to = tty->link
   tty_kref_put(tty->link)   tty_schedule_flip(to->port)
  << workqueue >> ...
  release_one_tty ...
 pty_cleanup  ...
kfree(tty->link->port)   << workqueue >>
 flush_to_ldisc
tty = READ_ONCE(port->itty)
tty is 0x6b6b6b6b6b6b6b6b
!!PANIC!! access tty->ldisc

 Unable to handle kernel paging request at virtual address 6b6b6b6b6b6b6b93
 pgd = ffc0eb1c3000
 [6b6b6b6b6b6b6b93] *pgd=, *pud=
 [ cut here ]
 Kernel BUG at ff800851154c [verbose debug info unavailable]
 Internal error: Oops - BUG: 9604 [#1] PREEMPT SMP
 CPU: 3 PID: 265 Comm: kworker/u8:9 Tainted: GW 3.18.31-g0a58eeb #1
 Hardware name: Qualcomm Technologies, Inc. MSM 8996pro v1.1 + PMI8996 Carbide 
(DT)
 Workqueue: events_unbound flush_to_ldisc
 task: ffc0ed610ec0 ti: ffc0ed624000 task.ti: ffc0ed624000
 PC is at ldsem_down_read_trylock+0x0/0x4c
 LR is at tty_ldisc_ref+0x24/0x4c
 pc : [] lr : [] pstate: 80400145
 sp : ffc0ed627cd0
 x29: ffc0ed627cd0 x28: 
 x27: ff8009e05000 x26: ffc0d382cfa0
 x25:  x24: ff800a012f08
 x23:  x22: ffc0703fbc88
 x21: 6b6b6b6b6b6b6b6b x20: 6b6b6b6b6b6b6b93
 x19:  x18: 0001
 x17: 00e8f80d6f53 x16: 0001
 x15: 007f7d826fff x14: 00a0
 x13:  x12: 0109
 x11:  x10: 
 x9 : ffc0ed624000 x8 : ffc0ed611580
 x7 :  x6 : ff800a42e000
 x5 : 03fc x4 : 03bd1201
 x3 : 0001 x2 : 0001
 x1 : ff800851004c x0 : 6b6b6b6b6b6b6b93

Signed-off-by: Sahara 
---
 drivers/tty/tty_io.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index dc60aee..a6ca634 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1476,6 +1476,8 @@ static void release_tty(struct tty_struct *tty, int idx)
if (tty->link)
tty->link->port->itty = NULL;
tty_buffer_cancel_work(tty->port);
+   if (tty->link)
+   tty_buffer_cancel_work(tty->link->port);
 
tty_kref_put(tty->link);
tty_kref_put(tty);
-- 
2.7.4



[PATCH] ARM: compressed/head.S: use addruart properly

2014-08-26 Thread kpark3469
From: Sahara 

This patch fixes compile error in compressed/head.S, when DEBUG
is defined. Since addruart macro accepts 3 params, rp, rv, and tmp,
loadsp macro also needs to be fixed. Or you will meet the following
error messages:
Error: ARM register expected -- `mov ,#(5<<1)'
Error: shift expression expected -- `add r3,r3,'

Signed-off-by: Sahara 
---
 arch/arm/boot/compressed/head.S |   22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 413fd94..9f1a6cd 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -24,19 +24,19 @@
 #if defined(CONFIG_DEBUG_ICEDCC)
 
 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c0, c5, 0
.endm
 #elif defined(CONFIG_CPU_XSCALE)
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c8, c0, 0
.endm
 #else
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c1, c0, 0
@@ -52,17 +52,17 @@
.endm
 
 #if defined(CONFIG_ARCH_SA1100)
-   .macro  loadsp, rb, tmp
-   mov \rb, #0x8000@ physical base address
+   .macro  loadsp, rp, rv, tmp
+   mov \rp, #0x8000@ physical base address
 #ifdef CONFIG_DEBUG_LL_SER3
-   add \rb, \rb, #0x0005   @ Ser3
+   add \rp, \rp, #0x0005   @ Ser3
 #else
-   add \rb, \rb, #0x0001   @ Ser1
+   add \rp, \rp, #0x0001   @ Ser1
 #endif
.endm
 #else
-   .macro  loadsp, rb, tmp
-   addruart \rb, \tmp
+   .macro  loadsp, rp, rv, tmp
+   addruart \rp, \rv, \tmp
.endm
 #endif
 #endif
@@ -1209,7 +1209,7 @@ phex: adr r3, phexbuf
b   1b
 
 @ puts corrupts {r0, r1, r2, r3}
-puts:  loadsp  r3, r1
+puts:  loadsp  r3, r2, r1
 1: ldrbr2, [r0], #1
teq r2, #0
moveq   pc, lr
@@ -1225,9 +1225,9 @@ puts: loadsp  r3, r1
mov pc, lr
 @ putc corrupts {r0, r1, r2, r3}
 putc:
+   loadsp  r3, r2, r1
mov r2, r0
mov r0, #0
-   loadsp  r3, r1
b   2b
 
 @ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr}
-- 
1.7.9.5

--
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/


[PATCHv2] ARM: debug: uncompress debug support for omap2plus

2014-08-26 Thread kpark3469
From: Sahara 

Since OMAP low-level debug code places data in the .data section,
The symbol DEBUG_UNCOMPRESS was defined with !DEBUG_OMAP2PLUS_UART.
This patch removes the part using data section in debug/omap2plus.S,
so DEBUG_UNCOMPRESS is now available on OMAP system.

Signed-off-by: Sahara 
Tested-by: Afzal Mohammed  (on am335x beagle
bone white)
---
 arch/arm/Kconfig.debug |3 +-
 arch/arm/include/debug/omap2plus.S |   96 ++--
 2 files changed, 27 insertions(+), 72 deletions(-)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index b11ad54..c0ad3e4 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1220,8 +1220,7 @@ config DEBUG_UART_8250_FLOW_CONTROL
 config DEBUG_UNCOMPRESS
bool
depends on ARCH_MULTIPLATFORM || ARCH_MSM || PLAT_SAMSUNG
-   default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \
-(!DEBUG_TEGRA_UART || !ZBOOT_ROM)
+   default y if DEBUG_LL && (!DEBUG_TEGRA_UART || !ZBOOT_ROM)
help
  This option influences the normal decompressor output for
  multiplatform kernels.  Normally, multiplatform kernels disable
diff --git a/arch/arm/include/debug/omap2plus.S 
b/arch/arm/include/debug/omap2plus.S
index 6d867ae..0b7ec89 100644
--- a/arch/arm/include/debug/omap2plus.S
+++ b/arch/arm/include/debug/omap2plus.S
@@ -58,115 +58,71 @@
 
 #define UART_OFFSET(addr)  ((addr) & 0x00ff)
 
-   .pushsection .data
-omap_uart_phys:.word   0
-omap_uart_virt:.word   0
-omap_uart_lsr: .word   0
-   .popsection
-
.macro  addruart, rp, rv, tmp
 
-   /* Use omap_uart_phys/virt if already configured */
-10:adr \rp, 99f@ get effective addr of 99f
-   ldr \rv, [\rp]  @ get absolute addr of 99f
-   sub \rv, \rv, \rp   @ offset between the two
-   ldr \rp, [\rp, #4]  @ abs addr of omap_uart_phys
-   sub \tmp, \rp, \rv  @ make it effective
-   ldr \rp, [\tmp, #0] @ omap_uart_phys
-   ldr \rv, [\tmp, #4] @ omap_uart_virt
-   cmp \rp, #0 @ is port configured?
-   cmpne   \rv, #0
-   bne 100f@ already configured
-
/* Configure the UART offset from the phys/virt base */
-#ifdef CONFIG_DEBUG_OMAP2UART1
+#if defined(CONFIG_DEBUG_OMAP2UART1)
mov \rp, #UART_OFFSET(OMAP2_UART1_BASE) @ omap2/3/4
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP2UART2
+#elif defined(CONFIG_DEBUG_OMAP2UART2)
mov \rp, #UART_OFFSET(OMAP2_UART2_BASE) @ omap2/3/4
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP2UART3
+#elif defined(CONFIG_DEBUG_OMAP2UART3)
mov \rp, #UART_OFFSET(OMAP2_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP3UART3
+#elif defined(CONFIG_DEBUG_OMAP3UART3)
mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
add \rp, \rp, #0x00fb
add \rp, \rp, #0x6000   @ OMAP3_UART3_BASE
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP4UART3
+#elif defined(CONFIG_DEBUG_OMAP4UART3)
mov \rp, #UART_OFFSET(OMAP4_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP3UART4
+#elif defined(CONFIG_DEBUG_OMAP3UART4)
mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
add \rp, \rp, #0x00fb
add \rp, \rp, #0x00028000   @ OMAP3_UART4_BASE
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP4UART4
+#elif defined(CONFIG_DEBUG_OMAP4UART4)
mov \rp, #UART_OFFSET(OMAP4_UART4_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART1
+#elif defined(CONFIG_DEBUG_TI81XXUART1)
mov \rp, #UART_OFFSET(TI81XX_UART1_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART2
+#elif defined(CONFIG_DEBUG_TI81XXUART2)
mov \rp, #UART_OFFSET(TI81XX_UART2_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART3
+#elif defined(CONFIG_DEBUG_TI81XXUART3)
mov \rp, #UART_OFFSET(TI81XX_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_AM33XXUART1
+#elif defined(CONFIG_DEBUG_AM33XXUART1)
ldr \rp, =AM33XX_UART1_BASE
and \rp, \rp, #0x00ff
b   97f
-#endif
-#ifdef CONFIG_DEBUG_ZOOM_UART
+#elif defined(CONFIG_DEBUG_ZOOM_UART)
ldr \rp, =ZOOM_UART_BASE
-   str \rp, [\tmp, #0] @ omap_uart_phys
-   ldr \rp, =ZOOM_UART_VIRT
-   str \rp, [\tmp, #4] @ omap_uart_virt
-   mov \rp, #(UART_LSR << ZOOM_PORT_SHIFT)
-

[PATCHv2] ARM: debug: uncompress debug support for omap2plus

2014-08-26 Thread kpark3469
From: Sahara 

Since OMAP low-level debug code places data in the .data section,
The symbol DEBUG_UNCOMPRESS was defined with !DEBUG_OMAP2PLUS_UART.
This patch removes the part using data section in debug/omap2plus.S,
so DEBUG_UNCOMPRESS is now available on OMAP system.

Signed-off-by: Sahara 
Tested-by: Afzal Mohammed  (on am335x beagle
bone white)
---
 arch/arm/Kconfig.debug |3 +-
 arch/arm/include/debug/omap2plus.S |   96 ++--
 2 files changed, 27 insertions(+), 72 deletions(-)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index b11ad54..c0ad3e4 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1220,8 +1220,7 @@ config DEBUG_UART_8250_FLOW_CONTROL
 config DEBUG_UNCOMPRESS
bool
depends on ARCH_MULTIPLATFORM || ARCH_MSM || PLAT_SAMSUNG
-   default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \
-(!DEBUG_TEGRA_UART || !ZBOOT_ROM)
+   default y if DEBUG_LL && (!DEBUG_TEGRA_UART || !ZBOOT_ROM)
help
  This option influences the normal decompressor output for
  multiplatform kernels.  Normally, multiplatform kernels disable
diff --git a/arch/arm/include/debug/omap2plus.S 
b/arch/arm/include/debug/omap2plus.S
index 6d867ae..0b7ec89 100644
--- a/arch/arm/include/debug/omap2plus.S
+++ b/arch/arm/include/debug/omap2plus.S
@@ -58,115 +58,71 @@
 
 #define UART_OFFSET(addr)  ((addr) & 0x00ff)
 
-   .pushsection .data
-omap_uart_phys:.word   0
-omap_uart_virt:.word   0
-omap_uart_lsr: .word   0
-   .popsection
-
.macro  addruart, rp, rv, tmp
 
-   /* Use omap_uart_phys/virt if already configured */
-10:adr \rp, 99f@ get effective addr of 99f
-   ldr \rv, [\rp]  @ get absolute addr of 99f
-   sub \rv, \rv, \rp   @ offset between the two
-   ldr \rp, [\rp, #4]  @ abs addr of omap_uart_phys
-   sub \tmp, \rp, \rv  @ make it effective
-   ldr \rp, [\tmp, #0] @ omap_uart_phys
-   ldr \rv, [\tmp, #4] @ omap_uart_virt
-   cmp \rp, #0 @ is port configured?
-   cmpne   \rv, #0
-   bne 100f@ already configured
-
/* Configure the UART offset from the phys/virt base */
-#ifdef CONFIG_DEBUG_OMAP2UART1
+#if defined(CONFIG_DEBUG_OMAP2UART1)
mov \rp, #UART_OFFSET(OMAP2_UART1_BASE) @ omap2/3/4
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP2UART2
+#elif defined(CONFIG_DEBUG_OMAP2UART2)
mov \rp, #UART_OFFSET(OMAP2_UART2_BASE) @ omap2/3/4
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP2UART3
+#elif defined(CONFIG_DEBUG_OMAP2UART3)
mov \rp, #UART_OFFSET(OMAP2_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP3UART3
+#elif defined(CONFIG_DEBUG_OMAP3UART3)
mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
add \rp, \rp, #0x00fb
add \rp, \rp, #0x6000   @ OMAP3_UART3_BASE
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP4UART3
+#elif defined(CONFIG_DEBUG_OMAP4UART3)
mov \rp, #UART_OFFSET(OMAP4_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP3UART4
+#elif defined(CONFIG_DEBUG_OMAP3UART4)
mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
add \rp, \rp, #0x00fb
add \rp, \rp, #0x00028000   @ OMAP3_UART4_BASE
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP4UART4
+#elif defined(CONFIG_DEBUG_OMAP4UART4)
mov \rp, #UART_OFFSET(OMAP4_UART4_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART1
+#elif defined(CONFIG_DEBUG_TI81XXUART1)
mov \rp, #UART_OFFSET(TI81XX_UART1_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART2
+#elif defined(CONFIG_DEBUG_TI81XXUART2)
mov \rp, #UART_OFFSET(TI81XX_UART2_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART3
+#elif defined(CONFIG_DEBUG_TI81XXUART3)
mov \rp, #UART_OFFSET(TI81XX_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_AM33XXUART1
+#elif defined(CONFIG_DEBUG_AM33XXUART1)
ldr \rp, =AM33XX_UART1_BASE
and \rp, \rp, #0x00ff
b   97f
-#endif
-#ifdef CONFIG_DEBUG_ZOOM_UART
+#elif defined(CONFIG_DEBUG_ZOOM_UART)
ldr \rp, =ZOOM_UART_BASE
-   str \rp, [\tmp, #0] @ omap_uart_phys
-   ldr \rp, =ZOOM_UART_VIRT
-   str \rp, [\tmp, #4] @ omap_uart_virt
-   mov \rp, #(UART_LSR << ZOOM_PORT_SHIFT)
-

[PATCHv2] ARM: debug: uncompress debug support for omap2plus

2014-08-26 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

Since OMAP low-level debug code places data in the .data section,
The symbol DEBUG_UNCOMPRESS was defined with !DEBUG_OMAP2PLUS_UART.
This patch removes the part using data section in debug/omap2plus.S,
so DEBUG_UNCOMPRESS is now available on OMAP system.

Signed-off-by: Sahara keun-o.p...@windriver.com
Tested-by: Afzal Mohammed afzal.mohd...@gmail.com (on am335x beagle
bone white)
---
 arch/arm/Kconfig.debug |3 +-
 arch/arm/include/debug/omap2plus.S |   96 ++--
 2 files changed, 27 insertions(+), 72 deletions(-)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index b11ad54..c0ad3e4 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1220,8 +1220,7 @@ config DEBUG_UART_8250_FLOW_CONTROL
 config DEBUG_UNCOMPRESS
bool
depends on ARCH_MULTIPLATFORM || ARCH_MSM || PLAT_SAMSUNG
-   default y if DEBUG_LL  !DEBUG_OMAP2PLUS_UART  \
-(!DEBUG_TEGRA_UART || !ZBOOT_ROM)
+   default y if DEBUG_LL  (!DEBUG_TEGRA_UART || !ZBOOT_ROM)
help
  This option influences the normal decompressor output for
  multiplatform kernels.  Normally, multiplatform kernels disable
diff --git a/arch/arm/include/debug/omap2plus.S 
b/arch/arm/include/debug/omap2plus.S
index 6d867ae..0b7ec89 100644
--- a/arch/arm/include/debug/omap2plus.S
+++ b/arch/arm/include/debug/omap2plus.S
@@ -58,115 +58,71 @@
 
 #define UART_OFFSET(addr)  ((addr)  0x00ff)
 
-   .pushsection .data
-omap_uart_phys:.word   0
-omap_uart_virt:.word   0
-omap_uart_lsr: .word   0
-   .popsection
-
.macro  addruart, rp, rv, tmp
 
-   /* Use omap_uart_phys/virt if already configured */
-10:adr \rp, 99f@ get effective addr of 99f
-   ldr \rv, [\rp]  @ get absolute addr of 99f
-   sub \rv, \rv, \rp   @ offset between the two
-   ldr \rp, [\rp, #4]  @ abs addr of omap_uart_phys
-   sub \tmp, \rp, \rv  @ make it effective
-   ldr \rp, [\tmp, #0] @ omap_uart_phys
-   ldr \rv, [\tmp, #4] @ omap_uart_virt
-   cmp \rp, #0 @ is port configured?
-   cmpne   \rv, #0
-   bne 100f@ already configured
-
/* Configure the UART offset from the phys/virt base */
-#ifdef CONFIG_DEBUG_OMAP2UART1
+#if defined(CONFIG_DEBUG_OMAP2UART1)
mov \rp, #UART_OFFSET(OMAP2_UART1_BASE) @ omap2/3/4
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP2UART2
+#elif defined(CONFIG_DEBUG_OMAP2UART2)
mov \rp, #UART_OFFSET(OMAP2_UART2_BASE) @ omap2/3/4
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP2UART3
+#elif defined(CONFIG_DEBUG_OMAP2UART3)
mov \rp, #UART_OFFSET(OMAP2_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP3UART3
+#elif defined(CONFIG_DEBUG_OMAP3UART3)
mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
add \rp, \rp, #0x00fb
add \rp, \rp, #0x6000   @ OMAP3_UART3_BASE
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP4UART3
+#elif defined(CONFIG_DEBUG_OMAP4UART3)
mov \rp, #UART_OFFSET(OMAP4_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP3UART4
+#elif defined(CONFIG_DEBUG_OMAP3UART4)
mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
add \rp, \rp, #0x00fb
add \rp, \rp, #0x00028000   @ OMAP3_UART4_BASE
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP4UART4
+#elif defined(CONFIG_DEBUG_OMAP4UART4)
mov \rp, #UART_OFFSET(OMAP4_UART4_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART1
+#elif defined(CONFIG_DEBUG_TI81XXUART1)
mov \rp, #UART_OFFSET(TI81XX_UART1_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART2
+#elif defined(CONFIG_DEBUG_TI81XXUART2)
mov \rp, #UART_OFFSET(TI81XX_UART2_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART3
+#elif defined(CONFIG_DEBUG_TI81XXUART3)
mov \rp, #UART_OFFSET(TI81XX_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_AM33XXUART1
+#elif defined(CONFIG_DEBUG_AM33XXUART1)
ldr \rp, =AM33XX_UART1_BASE
and \rp, \rp, #0x00ff
b   97f
-#endif
-#ifdef CONFIG_DEBUG_ZOOM_UART
+#elif defined(CONFIG_DEBUG_ZOOM_UART)
ldr \rp, =ZOOM_UART_BASE
-   str \rp, [\tmp, #0] @ omap_uart_phys
-   ldr \rp, =ZOOM_UART_VIRT
-   str \rp, [\tmp, #4] @ 

[PATCHv2] ARM: debug: uncompress debug support for omap2plus

2014-08-26 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

Since OMAP low-level debug code places data in the .data section,
The symbol DEBUG_UNCOMPRESS was defined with !DEBUG_OMAP2PLUS_UART.
This patch removes the part using data section in debug/omap2plus.S,
so DEBUG_UNCOMPRESS is now available on OMAP system.

Signed-off-by: Sahara keun-o.p...@windriver.com
Tested-by: Afzal Mohammed afzal.mohd...@gmail.com (on am335x beagle
bone white)
---
 arch/arm/Kconfig.debug |3 +-
 arch/arm/include/debug/omap2plus.S |   96 ++--
 2 files changed, 27 insertions(+), 72 deletions(-)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index b11ad54..c0ad3e4 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1220,8 +1220,7 @@ config DEBUG_UART_8250_FLOW_CONTROL
 config DEBUG_UNCOMPRESS
bool
depends on ARCH_MULTIPLATFORM || ARCH_MSM || PLAT_SAMSUNG
-   default y if DEBUG_LL  !DEBUG_OMAP2PLUS_UART  \
-(!DEBUG_TEGRA_UART || !ZBOOT_ROM)
+   default y if DEBUG_LL  (!DEBUG_TEGRA_UART || !ZBOOT_ROM)
help
  This option influences the normal decompressor output for
  multiplatform kernels.  Normally, multiplatform kernels disable
diff --git a/arch/arm/include/debug/omap2plus.S 
b/arch/arm/include/debug/omap2plus.S
index 6d867ae..0b7ec89 100644
--- a/arch/arm/include/debug/omap2plus.S
+++ b/arch/arm/include/debug/omap2plus.S
@@ -58,115 +58,71 @@
 
 #define UART_OFFSET(addr)  ((addr)  0x00ff)
 
-   .pushsection .data
-omap_uart_phys:.word   0
-omap_uart_virt:.word   0
-omap_uart_lsr: .word   0
-   .popsection
-
.macro  addruart, rp, rv, tmp
 
-   /* Use omap_uart_phys/virt if already configured */
-10:adr \rp, 99f@ get effective addr of 99f
-   ldr \rv, [\rp]  @ get absolute addr of 99f
-   sub \rv, \rv, \rp   @ offset between the two
-   ldr \rp, [\rp, #4]  @ abs addr of omap_uart_phys
-   sub \tmp, \rp, \rv  @ make it effective
-   ldr \rp, [\tmp, #0] @ omap_uart_phys
-   ldr \rv, [\tmp, #4] @ omap_uart_virt
-   cmp \rp, #0 @ is port configured?
-   cmpne   \rv, #0
-   bne 100f@ already configured
-
/* Configure the UART offset from the phys/virt base */
-#ifdef CONFIG_DEBUG_OMAP2UART1
+#if defined(CONFIG_DEBUG_OMAP2UART1)
mov \rp, #UART_OFFSET(OMAP2_UART1_BASE) @ omap2/3/4
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP2UART2
+#elif defined(CONFIG_DEBUG_OMAP2UART2)
mov \rp, #UART_OFFSET(OMAP2_UART2_BASE) @ omap2/3/4
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP2UART3
+#elif defined(CONFIG_DEBUG_OMAP2UART3)
mov \rp, #UART_OFFSET(OMAP2_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP3UART3
+#elif defined(CONFIG_DEBUG_OMAP3UART3)
mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
add \rp, \rp, #0x00fb
add \rp, \rp, #0x6000   @ OMAP3_UART3_BASE
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP4UART3
+#elif defined(CONFIG_DEBUG_OMAP4UART3)
mov \rp, #UART_OFFSET(OMAP4_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP3UART4
+#elif defined(CONFIG_DEBUG_OMAP3UART4)
mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
add \rp, \rp, #0x00fb
add \rp, \rp, #0x00028000   @ OMAP3_UART4_BASE
b   98f
-#endif
-#ifdef CONFIG_DEBUG_OMAP4UART4
+#elif defined(CONFIG_DEBUG_OMAP4UART4)
mov \rp, #UART_OFFSET(OMAP4_UART4_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART1
+#elif defined(CONFIG_DEBUG_TI81XXUART1)
mov \rp, #UART_OFFSET(TI81XX_UART1_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART2
+#elif defined(CONFIG_DEBUG_TI81XXUART2)
mov \rp, #UART_OFFSET(TI81XX_UART2_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_TI81XXUART3
+#elif defined(CONFIG_DEBUG_TI81XXUART3)
mov \rp, #UART_OFFSET(TI81XX_UART3_BASE)
b   98f
-#endif
-#ifdef CONFIG_DEBUG_AM33XXUART1
+#elif defined(CONFIG_DEBUG_AM33XXUART1)
ldr \rp, =AM33XX_UART1_BASE
and \rp, \rp, #0x00ff
b   97f
-#endif
-#ifdef CONFIG_DEBUG_ZOOM_UART
+#elif defined(CONFIG_DEBUG_ZOOM_UART)
ldr \rp, =ZOOM_UART_BASE
-   str \rp, [\tmp, #0] @ omap_uart_phys
-   ldr \rp, =ZOOM_UART_VIRT
-   str \rp, [\tmp, #4] @ 

[PATCH] ARM: compressed/head.S: use addruart properly

2014-08-26 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

This patch fixes compile error in compressed/head.S, when DEBUG
is defined. Since addruart macro accepts 3 params, rp, rv, and tmp,
loadsp macro also needs to be fixed. Or you will meet the following
error messages:
Error: ARM register expected -- `mov ,#(51)'
Error: shift expression expected -- `add r3,r3,'

Signed-off-by: Sahara keun-o.p...@windriver.com
---
 arch/arm/boot/compressed/head.S |   22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 413fd94..9f1a6cd 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -24,19 +24,19 @@
 #if defined(CONFIG_DEBUG_ICEDCC)
 
 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c0, c5, 0
.endm
 #elif defined(CONFIG_CPU_XSCALE)
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c8, c0, 0
.endm
 #else
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c1, c0, 0
@@ -52,17 +52,17 @@
.endm
 
 #if defined(CONFIG_ARCH_SA1100)
-   .macro  loadsp, rb, tmp
-   mov \rb, #0x8000@ physical base address
+   .macro  loadsp, rp, rv, tmp
+   mov \rp, #0x8000@ physical base address
 #ifdef CONFIG_DEBUG_LL_SER3
-   add \rb, \rb, #0x0005   @ Ser3
+   add \rp, \rp, #0x0005   @ Ser3
 #else
-   add \rb, \rb, #0x0001   @ Ser1
+   add \rp, \rp, #0x0001   @ Ser1
 #endif
.endm
 #else
-   .macro  loadsp, rb, tmp
-   addruart \rb, \tmp
+   .macro  loadsp, rp, rv, tmp
+   addruart \rp, \rv, \tmp
.endm
 #endif
 #endif
@@ -1209,7 +1209,7 @@ phex: adr r3, phexbuf
b   1b
 
 @ puts corrupts {r0, r1, r2, r3}
-puts:  loadsp  r3, r1
+puts:  loadsp  r3, r2, r1
 1: ldrbr2, [r0], #1
teq r2, #0
moveq   pc, lr
@@ -1225,9 +1225,9 @@ puts: loadsp  r3, r1
mov pc, lr
 @ putc corrupts {r0, r1, r2, r3}
 putc:
+   loadsp  r3, r2, r1
mov r2, r0
mov r0, #0
-   loadsp  r3, r1
b   2b
 
 @ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr}
-- 
1.7.9.5

--
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] earlyprintk: re-enable earlyprintk calling early_param

2014-08-14 Thread kpark3469
From: Sahara 

Although there are many obs_kernel_param and its names are
earlyprintk and also EARLY_PRINTK is also enabled, we could not
see the early_printk output properly until now. This patch
considers earlycon as well as earlyprintk.

Signed-off-by: Sahara 
---
 init/main.c |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/init/main.c b/init/main.c
index bb1aed9..235d248 100644
--- a/init/main.c
+++ b/init/main.c
@@ -426,7 +426,8 @@ static int __init do_early_param(char *param, char *val, 
const char *unused)
for (p = __setup_start; p < __setup_end; p++) {
if ((p->early && parameq(param, p->str)) ||
(strcmp(param, "console") == 0 &&
-strcmp(p->str, "earlycon") == 0)
+((strcmp(p->str, "earlycon") == 0) ||
+(strcmp(p->str, "earlyprintk") == 0)))
) {
if (p->setup_func(val) != 0)
pr_warn("Malformed early option '%s'\n", param);
-- 
1.7.9.5

--
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] earlyprintk: re-enable earlyprintk calling early_param

2014-08-14 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

Although there are many obs_kernel_param and its names are
earlyprintk and also EARLY_PRINTK is also enabled, we could not
see the early_printk output properly until now. This patch
considers earlycon as well as earlyprintk.

Signed-off-by: Sahara keun-o.p...@windriver.com
---
 init/main.c |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/init/main.c b/init/main.c
index bb1aed9..235d248 100644
--- a/init/main.c
+++ b/init/main.c
@@ -426,7 +426,8 @@ static int __init do_early_param(char *param, char *val, 
const char *unused)
for (p = __setup_start; p  __setup_end; p++) {
if ((p-early  parameq(param, p-str)) ||
(strcmp(param, console) == 0 
-strcmp(p-str, earlycon) == 0)
+((strcmp(p-str, earlycon) == 0) ||
+(strcmp(p-str, earlyprintk) == 0)))
) {
if (p-setup_func(val) != 0)
pr_warn(Malformed early option '%s'\n, param);
-- 
1.7.9.5

--
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] ARM: compressed/head.S: use addruart properly

2014-08-13 Thread kpark3469
From: Sahara 

This patch fixes compile error in compressed/head.S, when DEBUG
is defined. Since addruart macro accepts 3 params, rp, rv, and tmp,
loadsp macro also needs to be fixed. Or you will meet the following
error messages:
Error: ARM register expected -- `mov ,#(5<<1)'
Error: shift expression expected -- `add r3,r3,'

Signed-off-by: Sahara 
---
 arch/arm/boot/compressed/head.S |   22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 413fd94..9f1a6cd 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -24,19 +24,19 @@
 #if defined(CONFIG_DEBUG_ICEDCC)
 
 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c0, c5, 0
.endm
 #elif defined(CONFIG_CPU_XSCALE)
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c8, c0, 0
.endm
 #else
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c1, c0, 0
@@ -52,17 +52,17 @@
.endm
 
 #if defined(CONFIG_ARCH_SA1100)
-   .macro  loadsp, rb, tmp
-   mov \rb, #0x8000@ physical base address
+   .macro  loadsp, rp, rv, tmp
+   mov \rp, #0x8000@ physical base address
 #ifdef CONFIG_DEBUG_LL_SER3
-   add \rb, \rb, #0x0005   @ Ser3
+   add \rp, \rp, #0x0005   @ Ser3
 #else
-   add \rb, \rb, #0x0001   @ Ser1
+   add \rp, \rp, #0x0001   @ Ser1
 #endif
.endm
 #else
-   .macro  loadsp, rb, tmp
-   addruart \rb, \tmp
+   .macro  loadsp, rp, rv, tmp
+   addruart \rp, \rv, \tmp
.endm
 #endif
 #endif
@@ -1209,7 +1209,7 @@ phex: adr r3, phexbuf
b   1b
 
 @ puts corrupts {r0, r1, r2, r3}
-puts:  loadsp  r3, r1
+puts:  loadsp  r3, r2, r1
 1: ldrbr2, [r0], #1
teq r2, #0
moveq   pc, lr
@@ -1225,9 +1225,9 @@ puts: loadsp  r3, r1
mov pc, lr
 @ putc corrupts {r0, r1, r2, r3}
 putc:
+   loadsp  r3, r2, r1
mov r2, r0
mov r0, #0
-   loadsp  r3, r1
b   2b
 
 @ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr}
-- 
1.7.9.5

--
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] ARM: compressed/head.S: use addruart properly

2014-08-13 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

This patch fixes compile error in compressed/head.S, when DEBUG
is defined. Since addruart macro accepts 3 params, rp, rv, and tmp,
loadsp macro also needs to be fixed. Or you will meet the following
error messages:
Error: ARM register expected -- `mov ,#(51)'
Error: shift expression expected -- `add r3,r3,'

Signed-off-by: Sahara keun-o.p...@windriver.com
---
 arch/arm/boot/compressed/head.S |   22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 413fd94..9f1a6cd 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -24,19 +24,19 @@
 #if defined(CONFIG_DEBUG_ICEDCC)
 
 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c0, c5, 0
.endm
 #elif defined(CONFIG_CPU_XSCALE)
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c8, c0, 0
.endm
 #else
-   .macro  loadsp, rb, tmp
+   .macro  loadsp, rp, rv, tmp
.endm
.macro  writeb, ch, rb
mcr p14, 0, \ch, c1, c0, 0
@@ -52,17 +52,17 @@
.endm
 
 #if defined(CONFIG_ARCH_SA1100)
-   .macro  loadsp, rb, tmp
-   mov \rb, #0x8000@ physical base address
+   .macro  loadsp, rp, rv, tmp
+   mov \rp, #0x8000@ physical base address
 #ifdef CONFIG_DEBUG_LL_SER3
-   add \rb, \rb, #0x0005   @ Ser3
+   add \rp, \rp, #0x0005   @ Ser3
 #else
-   add \rb, \rb, #0x0001   @ Ser1
+   add \rp, \rp, #0x0001   @ Ser1
 #endif
.endm
 #else
-   .macro  loadsp, rb, tmp
-   addruart \rb, \tmp
+   .macro  loadsp, rp, rv, tmp
+   addruart \rp, \rv, \tmp
.endm
 #endif
 #endif
@@ -1209,7 +1209,7 @@ phex: adr r3, phexbuf
b   1b
 
 @ puts corrupts {r0, r1, r2, r3}
-puts:  loadsp  r3, r1
+puts:  loadsp  r3, r2, r1
 1: ldrbr2, [r0], #1
teq r2, #0
moveq   pc, lr
@@ -1225,9 +1225,9 @@ puts: loadsp  r3, r1
mov pc, lr
 @ putc corrupts {r0, r1, r2, r3}
 putc:
+   loadsp  r3, r2, r1
mov r2, r0
mov r0, #0
-   loadsp  r3, r1
b   2b
 
 @ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr}
-- 
1.7.9.5

--
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] xen/trace: replace old code with __print_symbolic

2013-08-05 Thread kpark3469
From: Sahara 

The advantage of using __print_symbolic() is that it allows both perf
and trace-cmd to read this event properly. Their parsers are not full C
parsers, and when you open code the the processing, they both will fail
to parse how to read the output, and will just default to printing the
fields via their raw numbers.
Another advantage is if the __entry->action is not one of the defined
fields, instead of outputting "??" it will output the number in hex. Say
if __entry->action is 0x123, the __print_symbolic will return "0x123" as
a string and that will be shown to the user, letting you know the actual
value of the field that was unknown.

Signed-off-by: Sahara 
---
 include/trace/events/xen.h |   33 +++--
 1 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h
index d06b6da..8c6f945 100644
--- a/include/trace/events/xen.h
+++ b/include/trace/events/xen.h
@@ -10,6 +10,25 @@
 
 struct multicall_entry;
 
+#define show_paravirt_lazy_mode(val)   \
+   __print_symbolic(val,   \
+   { PARAVIRT_LAZY_NONE,   "LAZY_NONE" },  \
+   { PARAVIRT_LAZY_MMU,"LAZY_MMU" },   \
+   { PARAVIRT_LAZY_CPU,"LAZY_CPU" })
+
+#define show_xen_mc_flush_reason(val)  \
+   __print_symbolic(val,   \
+   { XEN_MC_FL_NONE,   "NONE" },   \
+   { XEN_MC_FL_BATCH,  "BATCH" },  \
+   { XEN_MC_FL_ARGS,   "ARGS" },   \
+   { XEN_MC_FL_CALLBACK,   "CALLBACK" })
+
+#define show_xen_mc_extend_args(val)   \
+   __print_symbolic(val,   \
+   { XEN_MC_XE_OK, "OK" }, \
+   { XEN_MC_XE_BAD_OP, "BAD_OP" }, \
+   { XEN_MC_XE_NO_SPACE,   "NO_SPACE" })
+
 /* Multicalls */
 DECLARE_EVENT_CLASS(xen_mc__batch,
TP_PROTO(enum paravirt_lazy_mode mode),
@@ -18,9 +37,8 @@ DECLARE_EVENT_CLASS(xen_mc__batch,
__field(enum paravirt_lazy_mode, mode)
),
TP_fast_assign(__entry->mode = mode),
-   TP_printk("start batch LAZY_%s",
- (__entry->mode == PARAVIRT_LAZY_MMU) ? "MMU" :
- (__entry->mode == PARAVIRT_LAZY_CPU) ? "CPU" : "NONE")
+   TP_printk("start batch %s",
+ show_paravirt_lazy_mode(__entry->mode)
);
 #define DEFINE_XEN_MC_BATCH(name)  \
DEFINE_EVENT(xen_mc__batch, name,   \
@@ -82,10 +100,7 @@ TRACE_EVENT(xen_mc_flush_reason,
),
TP_fast_assign(__entry->reason = reason),
TP_printk("flush reason %s",
- (__entry->reason == XEN_MC_FL_NONE) ? "NONE" :
- (__entry->reason == XEN_MC_FL_BATCH) ? "BATCH" :
- (__entry->reason == XEN_MC_FL_ARGS) ? "ARGS" :
- (__entry->reason == XEN_MC_FL_CALLBACK) ? "CALLBACK" : 
"??")
+ show_xen_mc_flush_reason(__entry->reason)
);
 
 TRACE_EVENT(xen_mc_flush,
@@ -117,9 +132,7 @@ TRACE_EVENT(xen_mc_extend_args,
TP_printk("extending op %u%s by %zu bytes res %s",
  __entry->op, xen_hypercall_name(__entry->op),
  __entry->args,
- __entry->res == XEN_MC_XE_OK ? "OK" :
- __entry->res == XEN_MC_XE_BAD_OP ? "BAD_OP" :
- __entry->res == XEN_MC_XE_NO_SPACE ? "NO_SPACE" : "???")
+ show_xen_mc_extend_args(__entry->res)
);
 
 /* mmu */
-- 
1.7.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 1/2] PM / QoS: use __print_symbolic with more convenient way

2013-08-05 Thread kpark3469
From: Sahara 

This patch is to prevent the same __print_symbolic functions from
being used repeatedly.

Signed-off-by: Sahara 
---
 include/trace/events/power.h |   43 +
 1 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 8e42410..34efacc 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -182,6 +182,23 @@ DEFINE_EVENT(power_domain, power_domain_target,
 /*
  * The pm qos events are used for pm qos update
  */
+#define show_pm_qos_class(val) \
+   __print_symbolic(val,   \
+   { PM_QOS_CPU_DMA_LATENCY,   "CPU_DMA_LATENCY" },\
+   { PM_QOS_NETWORK_LATENCY,   "NETWORK_LATENCY" },\
+   { PM_QOS_NETWORK_THROUGHPUT,"NETWORK_THROUGHPUT" })
+
+#define show_pm_qos_req_action(val)\
+   __print_symbolic(val,   \
+   { PM_QOS_ADD_REQ,   "ADD_REQ" },\
+   { PM_QOS_UPDATE_REQ,"UPDATE_REQ" }, \
+   { PM_QOS_REMOVE_REQ,"REMOVE_REQ" })
+
+#define show_dev_pm_qos_req_type(val)  \
+   __print_symbolic(val,   \
+   { DEV_PM_QOS_LATENCY,   "DEV_PM_QOS_LATENCY" }, \
+   { DEV_PM_QOS_FLAGS, "DEV_PM_QOS_FLAGS" })
+
 DECLARE_EVENT_CLASS(pm_qos_request,
 
TP_PROTO(int pm_qos_class, s32 value),
@@ -199,11 +216,7 @@ DECLARE_EVENT_CLASS(pm_qos_request,
),
 
TP_printk("pm_qos_class=%s value=%d",
- __print_symbolic(__entry->pm_qos_class,
-   { PM_QOS_CPU_DMA_LATENCY,   "CPU_DMA_LATENCY" },
-   { PM_QOS_NETWORK_LATENCY,   "NETWORK_LATENCY" },
-   { PM_QOS_NETWORK_THROUGHPUT,"NETWORK_THROUGHPUT" }),
- __entry->value)
+ show_pm_qos_class(__entry->pm_qos_class), __entry->value)
 );
 
 DEFINE_EVENT(pm_qos_request, pm_qos_add_request,
@@ -246,10 +259,7 @@ TRACE_EVENT(pm_qos_update_request_timeout,
),
 
TP_printk("pm_qos_class=%s value=%d, timeout_us=%ld",
- __print_symbolic(__entry->pm_qos_class,
-   { PM_QOS_CPU_DMA_LATENCY,   "CPU_DMA_LATENCY" },
-   { PM_QOS_NETWORK_LATENCY,   "NETWORK_LATENCY" },
-   { PM_QOS_NETWORK_THROUGHPUT,"NETWORK_THROUGHPUT" }),
+ show_pm_qos_class(__entry->pm_qos_class),
  __entry->value, __entry->timeout_us)
 );
 
@@ -272,10 +282,7 @@ DECLARE_EVENT_CLASS(pm_qos_update,
),
 
TP_printk("action=%s prev_value=%d curr_value=%d",
- __print_symbolic(__entry->action,
-   { PM_QOS_ADD_REQ,   "ADD_REQ" },
-   { PM_QOS_UPDATE_REQ,"UPDATE_REQ" },
-   { PM_QOS_REMOVE_REQ,"REMOVE_REQ" }),
+ show_pm_qos_req_action(__entry->action),
  __entry->prev_value, __entry->curr_value)
 );
 
@@ -293,10 +300,7 @@ DEFINE_EVENT_PRINT(pm_qos_update, pm_qos_update_flags,
TP_ARGS(action, prev_value, curr_value),
 
TP_printk("action=%s prev_value=0x%x curr_value=0x%x",
- __print_symbolic(__entry->action,
-   { PM_QOS_ADD_REQ,   "ADD_REQ" },
-   { PM_QOS_UPDATE_REQ,"UPDATE_REQ" },
-   { PM_QOS_REMOVE_REQ,"REMOVE_REQ" }),
+ show_pm_qos_req_action(__entry->action),
  __entry->prev_value, __entry->curr_value)
 );
 
@@ -321,10 +325,7 @@ DECLARE_EVENT_CLASS(dev_pm_qos_request,
 
TP_printk("device=%s type=%s new_value=%d",
  __get_str(name),
- __print_symbolic(__entry->type,
-   { DEV_PM_QOS_LATENCY,   "DEV_PM_QOS_LATENCY" },
-   { DEV_PM_QOS_FLAGS, "DEV_PM_QOS_FLAGS" }),
- __entry->new_value)
+ show_dev_pm_qos_req_type(__entry->type), __entry->new_value)
 );
 
 DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_add_request,
-- 
1.7.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 1/2] PM / QoS: use __print_symbolic with more convenient way

2013-08-05 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

This patch is to prevent the same __print_symbolic functions from
being used repeatedly.

Signed-off-by: Sahara keun-o.p...@windriver.com
---
 include/trace/events/power.h |   43 +
 1 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 8e42410..34efacc 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -182,6 +182,23 @@ DEFINE_EVENT(power_domain, power_domain_target,
 /*
  * The pm qos events are used for pm qos update
  */
+#define show_pm_qos_class(val) \
+   __print_symbolic(val,   \
+   { PM_QOS_CPU_DMA_LATENCY,   CPU_DMA_LATENCY },\
+   { PM_QOS_NETWORK_LATENCY,   NETWORK_LATENCY },\
+   { PM_QOS_NETWORK_THROUGHPUT,NETWORK_THROUGHPUT })
+
+#define show_pm_qos_req_action(val)\
+   __print_symbolic(val,   \
+   { PM_QOS_ADD_REQ,   ADD_REQ },\
+   { PM_QOS_UPDATE_REQ,UPDATE_REQ }, \
+   { PM_QOS_REMOVE_REQ,REMOVE_REQ })
+
+#define show_dev_pm_qos_req_type(val)  \
+   __print_symbolic(val,   \
+   { DEV_PM_QOS_LATENCY,   DEV_PM_QOS_LATENCY }, \
+   { DEV_PM_QOS_FLAGS, DEV_PM_QOS_FLAGS })
+
 DECLARE_EVENT_CLASS(pm_qos_request,
 
TP_PROTO(int pm_qos_class, s32 value),
@@ -199,11 +216,7 @@ DECLARE_EVENT_CLASS(pm_qos_request,
),
 
TP_printk(pm_qos_class=%s value=%d,
- __print_symbolic(__entry-pm_qos_class,
-   { PM_QOS_CPU_DMA_LATENCY,   CPU_DMA_LATENCY },
-   { PM_QOS_NETWORK_LATENCY,   NETWORK_LATENCY },
-   { PM_QOS_NETWORK_THROUGHPUT,NETWORK_THROUGHPUT }),
- __entry-value)
+ show_pm_qos_class(__entry-pm_qos_class), __entry-value)
 );
 
 DEFINE_EVENT(pm_qos_request, pm_qos_add_request,
@@ -246,10 +259,7 @@ TRACE_EVENT(pm_qos_update_request_timeout,
),
 
TP_printk(pm_qos_class=%s value=%d, timeout_us=%ld,
- __print_symbolic(__entry-pm_qos_class,
-   { PM_QOS_CPU_DMA_LATENCY,   CPU_DMA_LATENCY },
-   { PM_QOS_NETWORK_LATENCY,   NETWORK_LATENCY },
-   { PM_QOS_NETWORK_THROUGHPUT,NETWORK_THROUGHPUT }),
+ show_pm_qos_class(__entry-pm_qos_class),
  __entry-value, __entry-timeout_us)
 );
 
@@ -272,10 +282,7 @@ DECLARE_EVENT_CLASS(pm_qos_update,
),
 
TP_printk(action=%s prev_value=%d curr_value=%d,
- __print_symbolic(__entry-action,
-   { PM_QOS_ADD_REQ,   ADD_REQ },
-   { PM_QOS_UPDATE_REQ,UPDATE_REQ },
-   { PM_QOS_REMOVE_REQ,REMOVE_REQ }),
+ show_pm_qos_req_action(__entry-action),
  __entry-prev_value, __entry-curr_value)
 );
 
@@ -293,10 +300,7 @@ DEFINE_EVENT_PRINT(pm_qos_update, pm_qos_update_flags,
TP_ARGS(action, prev_value, curr_value),
 
TP_printk(action=%s prev_value=0x%x curr_value=0x%x,
- __print_symbolic(__entry-action,
-   { PM_QOS_ADD_REQ,   ADD_REQ },
-   { PM_QOS_UPDATE_REQ,UPDATE_REQ },
-   { PM_QOS_REMOVE_REQ,REMOVE_REQ }),
+ show_pm_qos_req_action(__entry-action),
  __entry-prev_value, __entry-curr_value)
 );
 
@@ -321,10 +325,7 @@ DECLARE_EVENT_CLASS(dev_pm_qos_request,
 
TP_printk(device=%s type=%s new_value=%d,
  __get_str(name),
- __print_symbolic(__entry-type,
-   { DEV_PM_QOS_LATENCY,   DEV_PM_QOS_LATENCY },
-   { DEV_PM_QOS_FLAGS, DEV_PM_QOS_FLAGS }),
- __entry-new_value)
+ show_dev_pm_qos_req_type(__entry-type), __entry-new_value)
 );
 
 DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_add_request,
-- 
1.7.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 2/2] xen/trace: replace old code with __print_symbolic

2013-08-05 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

The advantage of using __print_symbolic() is that it allows both perf
and trace-cmd to read this event properly. Their parsers are not full C
parsers, and when you open code the the processing, they both will fail
to parse how to read the output, and will just default to printing the
fields via their raw numbers.
Another advantage is if the __entry-action is not one of the defined
fields, instead of outputting ?? it will output the number in hex. Say
if __entry-action is 0x123, the __print_symbolic will return 0x123 as
a string and that will be shown to the user, letting you know the actual
value of the field that was unknown.

Signed-off-by: Sahara keun-o.p...@windriver.com
---
 include/trace/events/xen.h |   33 +++--
 1 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h
index d06b6da..8c6f945 100644
--- a/include/trace/events/xen.h
+++ b/include/trace/events/xen.h
@@ -10,6 +10,25 @@
 
 struct multicall_entry;
 
+#define show_paravirt_lazy_mode(val)   \
+   __print_symbolic(val,   \
+   { PARAVIRT_LAZY_NONE,   LAZY_NONE },  \
+   { PARAVIRT_LAZY_MMU,LAZY_MMU },   \
+   { PARAVIRT_LAZY_CPU,LAZY_CPU })
+
+#define show_xen_mc_flush_reason(val)  \
+   __print_symbolic(val,   \
+   { XEN_MC_FL_NONE,   NONE },   \
+   { XEN_MC_FL_BATCH,  BATCH },  \
+   { XEN_MC_FL_ARGS,   ARGS },   \
+   { XEN_MC_FL_CALLBACK,   CALLBACK })
+
+#define show_xen_mc_extend_args(val)   \
+   __print_symbolic(val,   \
+   { XEN_MC_XE_OK, OK }, \
+   { XEN_MC_XE_BAD_OP, BAD_OP }, \
+   { XEN_MC_XE_NO_SPACE,   NO_SPACE })
+
 /* Multicalls */
 DECLARE_EVENT_CLASS(xen_mc__batch,
TP_PROTO(enum paravirt_lazy_mode mode),
@@ -18,9 +37,8 @@ DECLARE_EVENT_CLASS(xen_mc__batch,
__field(enum paravirt_lazy_mode, mode)
),
TP_fast_assign(__entry-mode = mode),
-   TP_printk(start batch LAZY_%s,
- (__entry-mode == PARAVIRT_LAZY_MMU) ? MMU :
- (__entry-mode == PARAVIRT_LAZY_CPU) ? CPU : NONE)
+   TP_printk(start batch %s,
+ show_paravirt_lazy_mode(__entry-mode)
);
 #define DEFINE_XEN_MC_BATCH(name)  \
DEFINE_EVENT(xen_mc__batch, name,   \
@@ -82,10 +100,7 @@ TRACE_EVENT(xen_mc_flush_reason,
),
TP_fast_assign(__entry-reason = reason),
TP_printk(flush reason %s,
- (__entry-reason == XEN_MC_FL_NONE) ? NONE :
- (__entry-reason == XEN_MC_FL_BATCH) ? BATCH :
- (__entry-reason == XEN_MC_FL_ARGS) ? ARGS :
- (__entry-reason == XEN_MC_FL_CALLBACK) ? CALLBACK : 
??)
+ show_xen_mc_flush_reason(__entry-reason)
);
 
 TRACE_EVENT(xen_mc_flush,
@@ -117,9 +132,7 @@ TRACE_EVENT(xen_mc_extend_args,
TP_printk(extending op %u%s by %zu bytes res %s,
  __entry-op, xen_hypercall_name(__entry-op),
  __entry-args,
- __entry-res == XEN_MC_XE_OK ? OK :
- __entry-res == XEN_MC_XE_BAD_OP ? BAD_OP :
- __entry-res == XEN_MC_XE_NO_SPACE ? NO_SPACE : ???)
+ show_xen_mc_extend_args(__entry-res)
);
 
 /* mmu */
-- 
1.7.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 v3] tracepoints: prevents null probe from being added

2013-04-14 Thread kpark3469
From: Sahara 

Somehow tracepoint_entry_add_probe function allows a null probe function.
And, this may lead to unexpected result since the number of probe
functions in an entry can be counted by checking whether probe is null
or not in for-loop.
This patch prevents the null probe from being added.
In tracepoint_entry_remove_probe function, checking probe parameter
within for-loop is moved out for code efficiency leaving the null probe
feature which removes all probe functions in the entry.

Signed-off-by: Sahara 
Reviewed-by: Steven Rostedt 
Reviewed-by: Mathieu Desnoyers 
---
 kernel/tracepoint.c |   21 +
 1 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 0c05a45..29f2654 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -112,7 +112,8 @@ tracepoint_entry_add_probe(struct tracepoint_entry *entry,
int nr_probes = 0;
struct tracepoint_func *old, *new;
 
-   WARN_ON(!probe);
+   if (WARN_ON(!probe))
+   return ERR_PTR(-EINVAL);
 
debug_print_probes(entry);
old = entry->funcs;
@@ -152,13 +153,18 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
 
debug_print_probes(entry);
/* (N -> M), (N > 1, M >= 0) probes */
-   for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
-   if (!probe ||
-   (old[nr_probes].func == probe &&
-old[nr_probes].data == data))
-   nr_del++;
+   if (probe) {
+   for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
+   if (old[nr_probes].func == probe &&
+old[nr_probes].data == data)
+   nr_del++;
+   }
}
 
+   /*
+* If probe is NULL, then nr_probes = nr_del = 0, and then the
+* entire entry will be removed.
+*/
if (nr_probes - nr_del == 0) {
/* N -> 0, (N > 1) */
entry->funcs = NULL;
@@ -173,8 +179,7 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
if (new == NULL)
return ERR_PTR(-ENOMEM);
for (i = 0; old[i].func; i++)
-   if (probe &&
-   (old[i].func != probe || old[i].data != data))
+   if (old[i].func != probe || old[i].data != data)
new[j++] = old[i];
new[nr_probes - nr_del].func = NULL;
entry->refcount = nr_probes - nr_del;
-- 
1.7.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 v3] tracepoints: prevents null probe from being added

2013-04-14 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

Somehow tracepoint_entry_add_probe function allows a null probe function.
And, this may lead to unexpected result since the number of probe
functions in an entry can be counted by checking whether probe is null
or not in for-loop.
This patch prevents the null probe from being added.
In tracepoint_entry_remove_probe function, checking probe parameter
within for-loop is moved out for code efficiency leaving the null probe
feature which removes all probe functions in the entry.

Signed-off-by: Sahara keun-o.p...@windriver.com
Reviewed-by: Steven Rostedt rost...@goodmis.org
Reviewed-by: Mathieu Desnoyers mathieu.desnoy...@efficios.com
---
 kernel/tracepoint.c |   21 +
 1 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 0c05a45..29f2654 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -112,7 +112,8 @@ tracepoint_entry_add_probe(struct tracepoint_entry *entry,
int nr_probes = 0;
struct tracepoint_func *old, *new;
 
-   WARN_ON(!probe);
+   if (WARN_ON(!probe))
+   return ERR_PTR(-EINVAL);
 
debug_print_probes(entry);
old = entry-funcs;
@@ -152,13 +153,18 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
 
debug_print_probes(entry);
/* (N - M), (N  1, M = 0) probes */
-   for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
-   if (!probe ||
-   (old[nr_probes].func == probe 
-old[nr_probes].data == data))
-   nr_del++;
+   if (probe) {
+   for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
+   if (old[nr_probes].func == probe 
+old[nr_probes].data == data)
+   nr_del++;
+   }
}
 
+   /*
+* If probe is NULL, then nr_probes = nr_del = 0, and then the
+* entire entry will be removed.
+*/
if (nr_probes - nr_del == 0) {
/* N - 0, (N  1) */
entry-funcs = NULL;
@@ -173,8 +179,7 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
if (new == NULL)
return ERR_PTR(-ENOMEM);
for (i = 0; old[i].func; i++)
-   if (probe 
-   (old[i].func != probe || old[i].data != data))
+   if (old[i].func != probe || old[i].data != data)
new[j++] = old[i];
new[nr_probes - nr_del].func = NULL;
entry-refcount = nr_probes - nr_del;
-- 
1.7.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] ptp_pch: eliminate a number of sparse warnings

2013-03-25 Thread kpark3469
From: Sahara 

This fixes a number of sparse warnings like:
  warning: incorrect type in argument 2 (different address spaces)
expected void volatile [noderef] *addr
got unsigned int *

  warning: Using plain integer as NULL pointer

Additionally this fixes a warning from checkpatch.pl like:
  WARNING: sizeof pch_param.station should be sizeof(pch_param.station)

Signed-off-by: Sahara 
---
 drivers/ptp/ptp_pch.c |   27 ++-
 1 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c
index 1367655..d1adb19 100644
--- a/drivers/ptp/ptp_pch.c
+++ b/drivers/ptp/ptp_pch.c
@@ -118,7 +118,7 @@ struct pch_ts_regs {
  * struct pch_dev - Driver private data
  */
 struct pch_dev {
-   struct pch_ts_regs *regs;
+   struct pch_ts_regs __iomem *regs;
struct ptp_clock *ptp_clock;
struct ptp_clock_info caps;
int exts0_enabled;
@@ -154,7 +154,7 @@ static inline void pch_eth_enable_set(struct pch_dev *chip)
iowrite32(val, (>regs->ts_sel));
 }
 
-static u64 pch_systime_read(struct pch_ts_regs *regs)
+static u64 pch_systime_read(struct pch_ts_regs __iomem *regs)
 {
u64 ns;
u32 lo, hi;
@@ -169,7 +169,7 @@ static u64 pch_systime_read(struct pch_ts_regs *regs)
return ns;
 }
 
-static void pch_systime_write(struct pch_ts_regs *regs, u64 ns)
+static void pch_systime_write(struct pch_ts_regs __iomem *regs, u64 ns)
 {
u32 hi, lo;
 
@@ -315,7 +315,7 @@ int pch_set_station_address(u8 *addr, struct pci_dev *pdev)
struct pch_dev *chip = pci_get_drvdata(pdev);
 
/* Verify the parameter */
-   if ((chip->regs == 0) || addr == (u8 *)NULL) {
+   if ((chip->regs == NULL) || addr == (u8 *)NULL) {
dev_err(>dev,
"invalid params returning PCH_INVALIDPARAM\n");
return PCH_INVALIDPARAM;
@@ -361,7 +361,7 @@ EXPORT_SYMBOL(pch_set_station_address);
 static irqreturn_t isr(int irq, void *priv)
 {
struct pch_dev *pch_dev = priv;
-   struct pch_ts_regs *regs = pch_dev->regs;
+   struct pch_ts_regs __iomem *regs = pch_dev->regs;
struct ptp_clock_event event;
u32 ack = 0, lo, hi, val;
 
@@ -415,7 +415,7 @@ static int ptp_pch_adjfreq(struct ptp_clock_info *ptp, s32 
ppb)
u32 diff, addend;
int neg_adj = 0;
struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-   struct pch_ts_regs *regs = pch_dev->regs;
+   struct pch_ts_regs __iomem *regs = pch_dev->regs;
 
if (ppb < 0) {
neg_adj = 1;
@@ -438,7 +438,7 @@ static int ptp_pch_adjtime(struct ptp_clock_info *ptp, s64 
delta)
s64 now;
unsigned long flags;
struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-   struct pch_ts_regs *regs = pch_dev->regs;
+   struct pch_ts_regs __iomem *regs = pch_dev->regs;
 
spin_lock_irqsave(_dev->register_lock, flags);
now = pch_systime_read(regs);
@@ -455,7 +455,7 @@ static int ptp_pch_gettime(struct ptp_clock_info *ptp, 
struct timespec *ts)
u32 remainder;
unsigned long flags;
struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-   struct pch_ts_regs *regs = pch_dev->regs;
+   struct pch_ts_regs __iomem *regs = pch_dev->regs;
 
spin_lock_irqsave(_dev->register_lock, flags);
ns = pch_systime_read(regs);
@@ -472,7 +472,7 @@ static int ptp_pch_settime(struct ptp_clock_info *ptp,
u64 ns;
unsigned long flags;
struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-   struct pch_ts_regs *regs = pch_dev->regs;
+   struct pch_ts_regs __iomem *regs = pch_dev->regs;
 
ns = ts->tv_sec * 10ULL;
ns += ts->tv_nsec;
@@ -567,9 +567,9 @@ static void pch_remove(struct pci_dev *pdev)
free_irq(pdev->irq, chip);
 
/* unmap the virtual IO memory space */
-   if (chip->regs != 0) {
+   if (chip->regs != NULL) {
iounmap(chip->regs);
-   chip->regs = 0;
+   chip->regs = NULL;
}
/* release the reserved IO memory space */
if (chip->mem_base != 0) {
@@ -670,7 +670,7 @@ pch_probe(struct pci_dev *pdev, const struct pci_device_id 
*id)
 err_req_irq:
ptp_clock_unregister(chip->ptp_clock);
iounmap(chip->regs);
-   chip->regs = 0;
+   chip->regs = NULL;
 
 err_ioremap:
release_mem_region(chip->mem_base, chip->mem_size);
@@ -723,7 +723,8 @@ static s32 __init ptp_pch_init(void)
 module_init(ptp_pch_init);
 module_exit(ptp_pch_exit);
 
-module_param_string(station, pch_param.station, sizeof pch_param.station, 
0444);
+module_param_string(station,
+pch_param.station, sizeof(pch_param.station), 0444);
 MODULE_PARM_DESC(station,
 "IEEE 1588 station address to use - column separated hex values");
 
-- 
1.7.1

--
To unsubscribe from this list: send the 

[PATCH] ptp_pch: eliminate a number of sparse warnings

2013-03-25 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

This fixes a number of sparse warnings like:
  warning: incorrect type in argument 2 (different address spaces)
expected void volatile [noderef] asn:2*addr
got unsigned int *noident

  warning: Using plain integer as NULL pointer

Additionally this fixes a warning from checkpatch.pl like:
  WARNING: sizeof pch_param.station should be sizeof(pch_param.station)

Signed-off-by: Sahara keun-o.p...@windriver.com
---
 drivers/ptp/ptp_pch.c |   27 ++-
 1 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c
index 1367655..d1adb19 100644
--- a/drivers/ptp/ptp_pch.c
+++ b/drivers/ptp/ptp_pch.c
@@ -118,7 +118,7 @@ struct pch_ts_regs {
  * struct pch_dev - Driver private data
  */
 struct pch_dev {
-   struct pch_ts_regs *regs;
+   struct pch_ts_regs __iomem *regs;
struct ptp_clock *ptp_clock;
struct ptp_clock_info caps;
int exts0_enabled;
@@ -154,7 +154,7 @@ static inline void pch_eth_enable_set(struct pch_dev *chip)
iowrite32(val, (chip-regs-ts_sel));
 }
 
-static u64 pch_systime_read(struct pch_ts_regs *regs)
+static u64 pch_systime_read(struct pch_ts_regs __iomem *regs)
 {
u64 ns;
u32 lo, hi;
@@ -169,7 +169,7 @@ static u64 pch_systime_read(struct pch_ts_regs *regs)
return ns;
 }
 
-static void pch_systime_write(struct pch_ts_regs *regs, u64 ns)
+static void pch_systime_write(struct pch_ts_regs __iomem *regs, u64 ns)
 {
u32 hi, lo;
 
@@ -315,7 +315,7 @@ int pch_set_station_address(u8 *addr, struct pci_dev *pdev)
struct pch_dev *chip = pci_get_drvdata(pdev);
 
/* Verify the parameter */
-   if ((chip-regs == 0) || addr == (u8 *)NULL) {
+   if ((chip-regs == NULL) || addr == (u8 *)NULL) {
dev_err(pdev-dev,
invalid params returning PCH_INVALIDPARAM\n);
return PCH_INVALIDPARAM;
@@ -361,7 +361,7 @@ EXPORT_SYMBOL(pch_set_station_address);
 static irqreturn_t isr(int irq, void *priv)
 {
struct pch_dev *pch_dev = priv;
-   struct pch_ts_regs *regs = pch_dev-regs;
+   struct pch_ts_regs __iomem *regs = pch_dev-regs;
struct ptp_clock_event event;
u32 ack = 0, lo, hi, val;
 
@@ -415,7 +415,7 @@ static int ptp_pch_adjfreq(struct ptp_clock_info *ptp, s32 
ppb)
u32 diff, addend;
int neg_adj = 0;
struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-   struct pch_ts_regs *regs = pch_dev-regs;
+   struct pch_ts_regs __iomem *regs = pch_dev-regs;
 
if (ppb  0) {
neg_adj = 1;
@@ -438,7 +438,7 @@ static int ptp_pch_adjtime(struct ptp_clock_info *ptp, s64 
delta)
s64 now;
unsigned long flags;
struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-   struct pch_ts_regs *regs = pch_dev-regs;
+   struct pch_ts_regs __iomem *regs = pch_dev-regs;
 
spin_lock_irqsave(pch_dev-register_lock, flags);
now = pch_systime_read(regs);
@@ -455,7 +455,7 @@ static int ptp_pch_gettime(struct ptp_clock_info *ptp, 
struct timespec *ts)
u32 remainder;
unsigned long flags;
struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-   struct pch_ts_regs *regs = pch_dev-regs;
+   struct pch_ts_regs __iomem *regs = pch_dev-regs;
 
spin_lock_irqsave(pch_dev-register_lock, flags);
ns = pch_systime_read(regs);
@@ -472,7 +472,7 @@ static int ptp_pch_settime(struct ptp_clock_info *ptp,
u64 ns;
unsigned long flags;
struct pch_dev *pch_dev = container_of(ptp, struct pch_dev, caps);
-   struct pch_ts_regs *regs = pch_dev-regs;
+   struct pch_ts_regs __iomem *regs = pch_dev-regs;
 
ns = ts-tv_sec * 10ULL;
ns += ts-tv_nsec;
@@ -567,9 +567,9 @@ static void pch_remove(struct pci_dev *pdev)
free_irq(pdev-irq, chip);
 
/* unmap the virtual IO memory space */
-   if (chip-regs != 0) {
+   if (chip-regs != NULL) {
iounmap(chip-regs);
-   chip-regs = 0;
+   chip-regs = NULL;
}
/* release the reserved IO memory space */
if (chip-mem_base != 0) {
@@ -670,7 +670,7 @@ pch_probe(struct pci_dev *pdev, const struct pci_device_id 
*id)
 err_req_irq:
ptp_clock_unregister(chip-ptp_clock);
iounmap(chip-regs);
-   chip-regs = 0;
+   chip-regs = NULL;
 
 err_ioremap:
release_mem_region(chip-mem_base, chip-mem_size);
@@ -723,7 +723,8 @@ static s32 __init ptp_pch_init(void)
 module_init(ptp_pch_init);
 module_exit(ptp_pch_exit);
 
-module_param_string(station, pch_param.station, sizeof pch_param.station, 
0444);
+module_param_string(station,
+pch_param.station, sizeof(pch_param.station), 0444);
 MODULE_PARM_DESC(station,
 IEEE 1588 station address to use - column separated hex values);
 
-- 
1.7.1

--

[PATCH v2] tracepoints: prevents null probe from being added

2013-03-20 Thread kpark3469
From: Sahara 

Somehow tracepoint_entry_add_probe function allows a null probe function.
And, this may lead to unexpected result since the number of probe
functions in an entry can be counted by checking whether probe is null
or not in for-loop.
This patch prevents the null probe from being added.
In tracepoint_entry_remove_probe function, checking probe parameter
within for-loop is moved out for code efficiency leaving the null probe
feature which removes all probe functions in the entry.

Signed-off-by: Sahara 
Reviewed-by: Steven Rostedt 
Reviewed-by: Mathieu Desnoyers 
---
 kernel/tracepoint.c |   18 ++
 1 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 0c05a45..7d69348 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -112,7 +112,8 @@ tracepoint_entry_add_probe(struct tracepoint_entry *entry,
int nr_probes = 0;
struct tracepoint_func *old, *new;
 
-   WARN_ON(!probe);
+   if (WARN_ON(!probe))
+   return ERR_PTR(-EINVAL);
 
debug_print_probes(entry);
old = entry->funcs;
@@ -152,13 +153,15 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
 
debug_print_probes(entry);
/* (N -> M), (N > 1, M >= 0) probes */
-   for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
-   if (!probe ||
-   (old[nr_probes].func == probe &&
-old[nr_probes].data == data))
-   nr_del++;
+   if (probe) {
+   for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
+   if (old[nr_probes].func == probe &&
+old[nr_probes].data == data)
+   nr_del++;
+   }
}
 
+   /* If probe is NULL, all funcs in the entry will be removed. */
if (nr_probes - nr_del == 0) {
/* N -> 0, (N > 1) */
entry->funcs = NULL;
@@ -173,8 +176,7 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
if (new == NULL)
return ERR_PTR(-ENOMEM);
for (i = 0; old[i].func; i++)
-   if (probe &&
-   (old[i].func != probe || old[i].data != data))
+   if (old[i].func != probe || old[i].data != data)
new[j++] = old[i];
new[nr_probes - nr_del].func = NULL;
entry->refcount = nr_probes - nr_del;
-- 
1.7.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] tracepoints: prevents null probe from being added

2013-03-20 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

Somehow tracepoint_entry_add_probe function allows a null probe function.
And, this may lead to unexpected result since the number of probe
functions in an entry can be counted by checking whether probe is null
or not in for-loop.
This patch prevents the null probe from being added.
In tracepoint_entry_remove_probe function, checking probe parameter
within for-loop is moved out for code efficiency leaving the null probe
feature which removes all probe functions in the entry.

Signed-off-by: Sahara keun-o.p...@windriver.com
Reviewed-by: Steven Rostedt rost...@goodmis.org
Reviewed-by: Mathieu Desnoyers mathieu.desnoy...@efficios.com
---
 kernel/tracepoint.c |   18 ++
 1 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 0c05a45..7d69348 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -112,7 +112,8 @@ tracepoint_entry_add_probe(struct tracepoint_entry *entry,
int nr_probes = 0;
struct tracepoint_func *old, *new;
 
-   WARN_ON(!probe);
+   if (WARN_ON(!probe))
+   return ERR_PTR(-EINVAL);
 
debug_print_probes(entry);
old = entry-funcs;
@@ -152,13 +153,15 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
 
debug_print_probes(entry);
/* (N - M), (N  1, M = 0) probes */
-   for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
-   if (!probe ||
-   (old[nr_probes].func == probe 
-old[nr_probes].data == data))
-   nr_del++;
+   if (probe) {
+   for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
+   if (old[nr_probes].func == probe 
+old[nr_probes].data == data)
+   nr_del++;
+   }
}
 
+   /* If probe is NULL, all funcs in the entry will be removed. */
if (nr_probes - nr_del == 0) {
/* N - 0, (N  1) */
entry-funcs = NULL;
@@ -173,8 +176,7 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
if (new == NULL)
return ERR_PTR(-ENOMEM);
for (i = 0; old[i].func; i++)
-   if (probe 
-   (old[i].func != probe || old[i].data != data))
+   if (old[i].func != probe || old[i].data != data)
new[j++] = old[i];
new[nr_probes - nr_del].func = NULL;
entry-refcount = nr_probes - nr_del;
-- 
1.7.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] tracepoints: prevents null probe from being added

2013-03-19 Thread kpark3469
From: Sahara 

Somehow tracepoint_entry_add/remove_probe functions allow a null probe
function. Especially on getting a null probe in remove function, it seems
to be used to remove all probe functions in the entry.
But, the code is not handled as expected. Since the tracepoint_entry
maintains funcs array's last func as NULL in order to mark it as the end
of the array. Also NULL func is used in for-loop to check out the end of
the loop. So if there's NULL func in the entry's funcs, the for-loop
will be abruptly ended in the middle of operation.
Also checking out if probe is null in for-loop is not efficient.

Signed-off-by: Sahara 
---
 kernel/tracepoint.c |   18 --
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 0c05a45..30f427e 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -112,7 +112,10 @@ tracepoint_entry_add_probe(struct tracepoint_entry *entry,
int nr_probes = 0;
struct tracepoint_func *old, *new;
 
-   WARN_ON(!probe);
+   if (unlikely(!probe)) {
+   WARN_ON(!probe);
+   return ERR_PTR(-EINVAL);
+   }
 
debug_print_probes(entry);
old = entry->funcs;
@@ -147,15 +150,19 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
 
old = entry->funcs;
 
+   if (unlikely(!probe)) {
+   WARN_ON(!probe);
+   return ERR_PTR(-EINVAL);
+   }
+
if (!old)
return ERR_PTR(-ENOENT);
 
debug_print_probes(entry);
/* (N -> M), (N > 1, M >= 0) probes */
for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
-   if (!probe ||
-   (old[nr_probes].func == probe &&
-old[nr_probes].data == data))
+   if (old[nr_probes].func == probe &&
+old[nr_probes].data == data)
nr_del++;
}
 
@@ -173,8 +180,7 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
if (new == NULL)
return ERR_PTR(-ENOMEM);
for (i = 0; old[i].func; i++)
-   if (probe &&
-   (old[i].func != probe || old[i].data != data))
+   if (old[i].func != probe || old[i].data != data)
new[j++] = old[i];
new[nr_probes - nr_del].func = NULL;
entry->refcount = nr_probes - nr_del;
-- 
1.7.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] tracepoints: prevents null probe from being added

2013-03-19 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

Somehow tracepoint_entry_add/remove_probe functions allow a null probe
function. Especially on getting a null probe in remove function, it seems
to be used to remove all probe functions in the entry.
But, the code is not handled as expected. Since the tracepoint_entry
maintains funcs array's last func as NULL in order to mark it as the end
of the array. Also NULL func is used in for-loop to check out the end of
the loop. So if there's NULL func in the entry's funcs, the for-loop
will be abruptly ended in the middle of operation.
Also checking out if probe is null in for-loop is not efficient.

Signed-off-by: Sahara keun-o.p...@windriver.com
---
 kernel/tracepoint.c |   18 --
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 0c05a45..30f427e 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -112,7 +112,10 @@ tracepoint_entry_add_probe(struct tracepoint_entry *entry,
int nr_probes = 0;
struct tracepoint_func *old, *new;
 
-   WARN_ON(!probe);
+   if (unlikely(!probe)) {
+   WARN_ON(!probe);
+   return ERR_PTR(-EINVAL);
+   }
 
debug_print_probes(entry);
old = entry-funcs;
@@ -147,15 +150,19 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
 
old = entry-funcs;
 
+   if (unlikely(!probe)) {
+   WARN_ON(!probe);
+   return ERR_PTR(-EINVAL);
+   }
+
if (!old)
return ERR_PTR(-ENOENT);
 
debug_print_probes(entry);
/* (N - M), (N  1, M = 0) probes */
for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
-   if (!probe ||
-   (old[nr_probes].func == probe 
-old[nr_probes].data == data))
+   if (old[nr_probes].func == probe 
+old[nr_probes].data == data)
nr_del++;
}
 
@@ -173,8 +180,7 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
*entry,
if (new == NULL)
return ERR_PTR(-ENOMEM);
for (i = 0; old[i].func; i++)
-   if (probe 
-   (old[i].func != probe || old[i].data != data))
+   if (old[i].func != probe || old[i].data != data)
new[j++] = old[i];
new[nr_probes - nr_del].func = NULL;
entry-refcount = nr_probes - nr_del;
-- 
1.7.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 v3] arm: fix a wrong value returned from CALLER_ADDRn

2013-03-13 Thread kpark3469
From: Sahara 

This makes return_address() return a correct value for CALLER_ADDRn.
To have a correct value from CALLER_ADDRn, we need to fix three points.

* The unwind_frame() does not update frame->lr but frame->pc for backtrace.
So frame->pc is meaningful for backtrace.

* data.level should be adjusted by adding 2 additional iteration levels.
With the current +1 level adjustment, the result of CALLER_ADDR1 will
be the same return address with CALLER_ADDR0.

* The initialization of data.addr to NULL is needed.
When unwind_fame() fails right after data.level reaches zero,
the routine returns data.addr which has uninitialized garbage value.

Signed-off-by: Sahara 
Reviewed-by: Dave Martin 
---
 arch/arm/kernel/return_address.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index 8085417..fafedd8 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -26,7 +26,7 @@ static int save_return_addr(struct stackframe *frame, void *d)
struct return_address_data *data = d;
 
if (!data->level) {
-   data->addr = (void *)frame->lr;
+   data->addr = (void *)frame->pc;
 
return 1;
} else {
@@ -41,7 +41,8 @@ void *return_address(unsigned int level)
struct stackframe frame;
register unsigned long current_sp asm ("sp");
 
-   data.level = level + 1;
+   data.level = level + 2;
+   data.addr = NULL;
 
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.sp = current_sp;
-- 
1.7.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 v3] arm: fix a wrong value returned from CALLER_ADDRn

2013-03-13 Thread kpark3469
From: Sahara keun-o.p...@windriver.com

This makes return_address() return a correct value for CALLER_ADDRn.
To have a correct value from CALLER_ADDRn, we need to fix three points.

* The unwind_frame() does not update frame-lr but frame-pc for backtrace.
So frame-pc is meaningful for backtrace.

* data.level should be adjusted by adding 2 additional iteration levels.
With the current +1 level adjustment, the result of CALLER_ADDR1 will
be the same return address with CALLER_ADDR0.

* The initialization of data.addr to NULL is needed.
When unwind_fame() fails right after data.level reaches zero,
the routine returns data.addr which has uninitialized garbage value.

Signed-off-by: Sahara keun-o.p...@windriver.com
Reviewed-by: Dave Martin dave.mar...@linaro.org
---
 arch/arm/kernel/return_address.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index 8085417..fafedd8 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -26,7 +26,7 @@ static int save_return_addr(struct stackframe *frame, void *d)
struct return_address_data *data = d;
 
if (!data-level) {
-   data-addr = (void *)frame-lr;
+   data-addr = (void *)frame-pc;
 
return 1;
} else {
@@ -41,7 +41,8 @@ void *return_address(unsigned int level)
struct stackframe frame;
register unsigned long current_sp asm (sp);
 
-   data.level = level + 1;
+   data.level = level + 2;
+   data.addr = NULL;
 
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.sp = current_sp;
-- 
1.7.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] arm: fix returning wrong CALLER_ADDRx

2013-01-29 Thread kpark3469
From: sahara 

This makes return_address return correct value for ftrace feature.
unwind_frame does not update frame->lr but frame->pc for backtrace.
And, the initialization for data.addr was missing so that wrong value
returned when unwind_frame failed.

Signed-off-by: Sahara 
Reviewed-by: Dave Martin 
---
 arch/arm/kernel/return_address.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index 8085417..fafedd8 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -26,7 +26,7 @@ static int save_return_addr(struct stackframe *frame, void *d)
struct return_address_data *data = d;
 
if (!data->level) {
-   data->addr = (void *)frame->lr;
+   data->addr = (void *)frame->pc;
 
return 1;
} else {
@@ -41,7 +41,8 @@ void *return_address(unsigned int level)
struct stackframe frame;
register unsigned long current_sp asm ("sp");
 
-   data.level = level + 1;
+   data.level = level + 2;
+   data.addr = NULL;
 
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.sp = current_sp;
-- 
1.7.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] arm: fix returning wrong CALLER_ADDRx

2013-01-29 Thread kpark3469
From: sahara keun-o.p...@windriver.com

This makes return_address return correct value for ftrace feature.
unwind_frame does not update frame-lr but frame-pc for backtrace.
And, the initialization for data.addr was missing so that wrong value
returned when unwind_frame failed.

Signed-off-by: Sahara keun-o.p...@windriver.com
Reviewed-by: Dave Martin dave.mar...@linaro.org
---
 arch/arm/kernel/return_address.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index 8085417..fafedd8 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -26,7 +26,7 @@ static int save_return_addr(struct stackframe *frame, void *d)
struct return_address_data *data = d;
 
if (!data-level) {
-   data-addr = (void *)frame-lr;
+   data-addr = (void *)frame-pc;
 
return 1;
} else {
@@ -41,7 +41,8 @@ void *return_address(unsigned int level)
struct stackframe frame;
register unsigned long current_sp asm (sp);
 
-   data.level = level + 1;
+   data.level = level + 2;
+   data.addr = NULL;
 
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.sp = current_sp;
-- 
1.7.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 1/2] arm: fix returning wrong CALLER_ADDRx

2013-01-03 Thread kpark3469
From: sahara 

This makes return_address return correct value for ftrace feature.
unwind_frame does not update frame->lr but frame->pc for backtrace.
And, the initialization for data.addr was missing so that wrong value
returned when unwind_frame failed.

Signed-off-by: sahara 
---
 arch/arm/kernel/return_address.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index 8085417..fafedd8 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -26,7 +26,7 @@ static int save_return_addr(struct stackframe *frame, void *d)
struct return_address_data *data = d;
 
if (!data->level) {
-   data->addr = (void *)frame->lr;
+   data->addr = (void *)frame->pc;
 
return 1;
} else {
@@ -41,7 +41,8 @@ void *return_address(unsigned int level)
struct stackframe frame;
register unsigned long current_sp asm ("sp");
 
-   data.level = level + 1;
+   data.level = level + 2;
+   data.addr = NULL;
 
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.sp = current_sp;
-- 
1.7.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 2/2] arm: make return_address available for ARM_UNWIND

2013-01-03 Thread kpark3469
From: sahara 

This fixes a warning saying:

warning: #warning "TODO: return_address should use unwind tables"

And, this enables return_address using unwind information. If ARM_UNWIND is
selected, unwind_frame in unwind.c will be called in walk_stackframe.

Signed-off-by: sahara 
---
 arch/arm/include/asm/ftrace.h|6 ++
 arch/arm/kernel/return_address.c |   10 +++---
 arch/arm/kernel/stacktrace.c |3 +++
 3 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index f89515a..3552ad9 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -32,13 +32,11 @@ extern void ftrace_call_old(void);
 
 #ifndef __ASSEMBLY__
 
-#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
+#if defined(CONFIG_FRAME_POINTER) || defined(CONFIG_ARM_UNWIND)
 /*
  * return_address uses walk_stackframe to do it's work.  If both
  * CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=y walk_stackframe uses unwind
- * information.  For this to work in the function tracer many functions would
- * have to be marked with __notrace.  So for now just depend on
- * !CONFIG_ARM_UNWIND.
+ * information.
  */
 
 void *return_address(unsigned int);
diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index fafedd8..f202bc0 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -11,7 +11,7 @@
 #include 
 #include 
 
-#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
+#if defined(CONFIG_FRAME_POINTER) || defined(CONFIG_ARM_UNWIND)
 #include 
 
 #include 
@@ -57,17 +57,13 @@ void *return_address(unsigned int level)
return NULL;
 }
 
-#else /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) */
-
-#if defined(CONFIG_ARM_UNWIND)
-#warning "TODO: return_address should use unwind tables"
-#endif
+#else /* CONFIG_FRAME_POINTER || CONFIG_ARM_UNWIND */
 
 void *return_address(unsigned int level)
 {
return NULL;
 }
 
-#endif /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) / 
else */
+#endif /* CONFIG_FRAME_POINTER || CONFIG_ARM_UNWIND */
 
 EXPORT_SYMBOL_GPL(return_address);
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index 00f79e5..aab144b 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -6,6 +6,9 @@
 
 #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
 /*
+ * If both CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=y walk_stackframe uses
+ * unwind information. So for now just depend on !CONFIG_ARM_UNWIND.
+ *
  * Unwind the current stack frame and store the new register values in the
  * structure passed as argument. Unwinding is equivalent to a function return,
  * hence the new PC value rather than LR should be used for backtrace.
-- 
1.7.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 2/2] arm: make return_address available for ARM_UNWIND

2013-01-03 Thread kpark3469
From: sahara keun-o.p...@windriver.com

This fixes a warning saying:

warning: #warning TODO: return_address should use unwind tables

And, this enables return_address using unwind information. If ARM_UNWIND is
selected, unwind_frame in unwind.c will be called in walk_stackframe.

Signed-off-by: sahara keun-o.p...@windriver.com
---
 arch/arm/include/asm/ftrace.h|6 ++
 arch/arm/kernel/return_address.c |   10 +++---
 arch/arm/kernel/stacktrace.c |3 +++
 3 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index f89515a..3552ad9 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -32,13 +32,11 @@ extern void ftrace_call_old(void);
 
 #ifndef __ASSEMBLY__
 
-#if defined(CONFIG_FRAME_POINTER)  !defined(CONFIG_ARM_UNWIND)
+#if defined(CONFIG_FRAME_POINTER) || defined(CONFIG_ARM_UNWIND)
 /*
  * return_address uses walk_stackframe to do it's work.  If both
  * CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=y walk_stackframe uses unwind
- * information.  For this to work in the function tracer many functions would
- * have to be marked with __notrace.  So for now just depend on
- * !CONFIG_ARM_UNWIND.
+ * information.
  */
 
 void *return_address(unsigned int);
diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index fafedd8..f202bc0 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -11,7 +11,7 @@
 #include linux/export.h
 #include linux/ftrace.h
 
-#if defined(CONFIG_FRAME_POINTER)  !defined(CONFIG_ARM_UNWIND)
+#if defined(CONFIG_FRAME_POINTER) || defined(CONFIG_ARM_UNWIND)
 #include linux/sched.h
 
 #include asm/stacktrace.h
@@ -57,17 +57,13 @@ void *return_address(unsigned int level)
return NULL;
 }
 
-#else /* if defined(CONFIG_FRAME_POINTER)  !defined(CONFIG_ARM_UNWIND) */
-
-#if defined(CONFIG_ARM_UNWIND)
-#warning TODO: return_address should use unwind tables
-#endif
+#else /* CONFIG_FRAME_POINTER || CONFIG_ARM_UNWIND */
 
 void *return_address(unsigned int level)
 {
return NULL;
 }
 
-#endif /* if defined(CONFIG_FRAME_POINTER)  !defined(CONFIG_ARM_UNWIND) / 
else */
+#endif /* CONFIG_FRAME_POINTER || CONFIG_ARM_UNWIND */
 
 EXPORT_SYMBOL_GPL(return_address);
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index 00f79e5..aab144b 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -6,6 +6,9 @@
 
 #if defined(CONFIG_FRAME_POINTER)  !defined(CONFIG_ARM_UNWIND)
 /*
+ * If both CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=y walk_stackframe uses
+ * unwind information. So for now just depend on !CONFIG_ARM_UNWIND.
+ *
  * Unwind the current stack frame and store the new register values in the
  * structure passed as argument. Unwinding is equivalent to a function return,
  * hence the new PC value rather than LR should be used for backtrace.
-- 
1.7.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 1/2] arm: fix returning wrong CALLER_ADDRx

2013-01-03 Thread kpark3469
From: sahara keun-o.p...@windriver.com

This makes return_address return correct value for ftrace feature.
unwind_frame does not update frame-lr but frame-pc for backtrace.
And, the initialization for data.addr was missing so that wrong value
returned when unwind_frame failed.

Signed-off-by: sahara keun-o.p...@windriver.com
---
 arch/arm/kernel/return_address.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index 8085417..fafedd8 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -26,7 +26,7 @@ static int save_return_addr(struct stackframe *frame, void *d)
struct return_address_data *data = d;
 
if (!data-level) {
-   data-addr = (void *)frame-lr;
+   data-addr = (void *)frame-pc;
 
return 1;
} else {
@@ -41,7 +41,8 @@ void *return_address(unsigned int level)
struct stackframe frame;
register unsigned long current_sp asm (sp);
 
-   data.level = level + 1;
+   data.level = level + 2;
+   data.addr = NULL;
 
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.sp = current_sp;
-- 
1.7.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/