linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] nds32: Unaligned access handler fix
@ 2018-10-18  8:34 Nickhu
  2018-10-18  8:34 ` [PATCH 1/3] nds32: Fix instruction simulator bug for unaligned access handler Nickhu
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Nickhu @ 2018-10-18  8:34 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, deanbo422, zong, ebiederm; +Cc: Nickhu, green.hu

The patches are about unaligned access handler. We fix some
bugs in unaligned access handler and add some kernel configs
for unaligned access handler. Then we add the kernel unaligned
access handled by software in handler.

Nickhu (3):
  nds32: Fix instruction simulator bug for unaligned access handler.
  nds32: Add 'HAVE_EFFICIENT_UNALIGNED_ACCESS' config
  nds32: Add unaligned access in kernel space.

 arch/nds32/Kconfig.cpu    |  3 ++-
 arch/nds32/kernel/traps.c |  4 +++-
 arch/nds32/mm/alignment.c | 43 +++++++++++++++++++++++----------------
 3 files changed, 30 insertions(+), 20 deletions(-)

-- 
2.17.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] nds32: Fix instruction simulator bug for unaligned access handler.
  2018-10-18  8:34 [PATCH 0/3] nds32: Unaligned access handler fix Nickhu
@ 2018-10-18  8:34 ` Nickhu
  2018-10-18  8:34 ` [PATCH 2/3] nds32: Add 'HAVE_EFFICIENT_UNALIGNED_ACCESS' config Nickhu
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Nickhu @ 2018-10-18  8:34 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, deanbo422, zong, ebiederm; +Cc: Nickhu, green.hu

	When emulating the 16 bits instructions, the mapping of general
purpose registers is not the same as 32 bits instructions.

	Example:
		'LWI450 r16, [r15]' 16-bit instruction will be decoded as
'1011010110001110', the target register field is decode as index=12.

    But the index of target register should be 16. So the mapping of
register in unaligned access handler is wrong.

Signed-off-by: Nickhu <nickhu@andestech.com>
---
 arch/nds32/mm/alignment.c | 37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/arch/nds32/mm/alignment.c b/arch/nds32/mm/alignment.c
index e1aed9dc692d..66a556befd05 100644
--- a/arch/nds32/mm/alignment.c
+++ b/arch/nds32/mm/alignment.c
@@ -152,12 +152,16 @@ extern int va_writable(struct pt_regs *regs, unsigned long addr);
 
 int unalign_access_mode = 0, unalign_access_debug = 0;
 
-static inline unsigned long *idx_to_addr(struct pt_regs *regs, int idx)
+static inline unsigned long *idx_to_addr(struct pt_regs *regs, int idx,
+				int idx_mode)
 {
 	/* this should be consistent with ptrace.h */
-	if (idx >= 0 && idx <= 25)	/* R0-R25 */
-		return &regs->uregs[0] + idx;
-	else if (idx >= 28 && idx <= 30)	/* FP, GP, LP */
+	if (idx >= 0 && idx <= 25) {	/* R0-R25 */
+		if (idx_mode == 4 && idx > 11)
+			return &regs->uregs[0] + idx + 4;
+		else
+			return &regs->uregs[0] + idx;
+	} else if (idx >= 28 && idx <= 30)	/* FP, GP, LP */
 		return &regs->fp + (idx - 28);
 	else if (idx == 31)	/* SP */
 		return &regs->sp;
@@ -270,10 +274,10 @@ static inline int do_16(unsigned long inst, struct pt_regs *regs)
 	}
 
 	if (addr_mode == 3) {
-		unaligned_addr = *idx_to_addr(regs, RA3(inst));
+		unaligned_addr = *idx_to_addr(regs, RA3(inst), addr_mode);
 		source_idx = RA3(inst);
 	} else {
-		unaligned_addr = *idx_to_addr(regs, RA5(inst));
+		unaligned_addr = *idx_to_addr(regs, RA5(inst), addr_mode);
 		source_idx = RA5(inst);
 	}
 
@@ -293,16 +297,17 @@ static inline int do_16(unsigned long inst, struct pt_regs *regs)
 			return -EACCES;
 
 		get_data(unaligned_addr, &target_val, len);
-		*idx_to_addr(regs, target_idx) = target_val;
+		*idx_to_addr(regs, target_idx, idx_mode) = target_val;
 	} else {
 		if (!access_ok(VERIFY_WRITE, (void *)unaligned_addr, len))
 			return -EACCES;
-		target_val = *idx_to_addr(regs, target_idx);
+		target_val = *idx_to_addr(regs, target_idx, idx_mode);
 		set_data((void *)unaligned_addr, target_val, len);
 	}
 
 	if (!regular)
-		*idx_to_addr(regs, source_idx) = unaligned_addr + shift;
+		*idx_to_addr(regs, source_idx, idx_mode) =
+			unaligned_addr + shift;
 	regs->ipc += 2;
 
 	return 0;
@@ -312,10 +317,10 @@ static inline int do_16(unsigned long inst, struct pt_regs *regs)
 
 static inline int do_32(unsigned long inst, struct pt_regs *regs)
 {
-	int imm, regular, load, len, sign_ext;
+	int imm, regular, load, len, sign_ext, idx_mode = 5;
 	unsigned long unaligned_addr, target_val, shift;
 
-	unaligned_addr = *idx_to_addr(regs, RA(inst));
+	unaligned_addr = *idx_to_addr(regs, RA(inst), idx_mode);
 
 	switch ((inst >> 25) << 1) {
 
@@ -472,7 +477,7 @@ static inline int do_32(unsigned long inst, struct pt_regs *regs)
 	if (imm)
 		shift = GET_IMMSVAL(IMM(inst)) * len;
 	else
-		shift = *idx_to_addr(regs, RB(inst)) << SV(inst);
+		shift = *idx_to_addr(regs, RB(inst), idx_mode) << SV(inst);
 
 	if (regular)
 		unaligned_addr += shift;
@@ -485,21 +490,21 @@ static inline int do_32(unsigned long inst, struct pt_regs *regs)
 		get_data(unaligned_addr, &target_val, len);
 
 		if (sign_ext)
-			*idx_to_addr(regs, RT(inst)) =
+			*idx_to_addr(regs, RT(inst), idx_mode) =
 			    sign_extend(target_val, len);
 		else
-			*idx_to_addr(regs, RT(inst)) = target_val;
+			*idx_to_addr(regs, RT(inst), idx_mode) = target_val;
 	} else {
 
 		if (!access_ok(VERIFY_WRITE, (void *)unaligned_addr, len))
 			return -EACCES;
 
-		target_val = *idx_to_addr(regs, RT(inst));
+		target_val = *idx_to_addr(regs, RT(inst), idx_mode);
 		set_data((void *)unaligned_addr, target_val, len);
 	}
 
 	if (!regular)
-		*idx_to_addr(regs, RA(inst)) = unaligned_addr + shift;
+		*idx_to_addr(regs, RA(inst), idx_mode) = unaligned_addr + shift;
 
 	regs->ipc += 4;
 
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] nds32: Add 'HAVE_EFFICIENT_UNALIGNED_ACCESS' config
  2018-10-18  8:34 [PATCH 0/3] nds32: Unaligned access handler fix Nickhu
  2018-10-18  8:34 ` [PATCH 1/3] nds32: Fix instruction simulator bug for unaligned access handler Nickhu
@ 2018-10-18  8:34 ` Nickhu
  2018-10-18  8:34 ` [PATCH 3/3] nds32: Add unaligned access in kernel space Nickhu
  2018-10-19  9:25 ` [PATCH 0/3] nds32: Unaligned access handler fix Greentime Hu
  3 siblings, 0 replies; 5+ messages in thread
From: Nickhu @ 2018-10-18  8:34 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, deanbo422, zong, ebiederm; +Cc: Nickhu, green.hu

According to my understanding, this config will optimize the code generate.
When there is an unaligned access happened, the load word instruction
still can be used if there is unaligned access support or the load byte
instruction is used. So this config need unaligned access support.

'HAVE_EFFICIENT_UNALIGNED_ACCESS' and 'HW_SUPPORT_UNALIGNMENT_ACCESS' are
default configs in nds32.

Signed-off-by: Nickhu <nickhu@andestech.com>
---
 arch/nds32/Kconfig.cpu | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/nds32/Kconfig.cpu b/arch/nds32/Kconfig.cpu
index b8c8984d1456..b8eecd0cde6b 100644
--- a/arch/nds32/Kconfig.cpu
+++ b/arch/nds32/Kconfig.cpu
@@ -111,8 +111,9 @@ config ALIGNMENT_TRAP
 
 config HW_SUPPORT_UNALIGNMENT_ACCESS
 	bool "Kernel support unaligned access handling by hw"
+	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	depends on !ALIGNMENT_TRAP
-	default n
+	default y
 	help
 	  Andes processors load/store world/half-word instructions can access
 	  unaligned memory locations without generating the Data Alignment
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] nds32: Add unaligned access in kernel space.
  2018-10-18  8:34 [PATCH 0/3] nds32: Unaligned access handler fix Nickhu
  2018-10-18  8:34 ` [PATCH 1/3] nds32: Fix instruction simulator bug for unaligned access handler Nickhu
  2018-10-18  8:34 ` [PATCH 2/3] nds32: Add 'HAVE_EFFICIENT_UNALIGNED_ACCESS' config Nickhu
@ 2018-10-18  8:34 ` Nickhu
  2018-10-19  9:25 ` [PATCH 0/3] nds32: Unaligned access handler fix Greentime Hu
  3 siblings, 0 replies; 5+ messages in thread
From: Nickhu @ 2018-10-18  8:34 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, deanbo422, zong, ebiederm; +Cc: Nickhu, green.hu

As my colleague has encountered kernel panic when unaligned access
in kernel space. Here is the situation, the structure 'TP_STRUCT__entry':

TP_STRUCT__entry(
                __field(        u32,    tb_id           )
                __field(        int,    err             )
                __field(        int,    oif             )
                __field(        int,    iif             )
                __field(        __u8,   tos             )
                __field(        __u8,   scope           )
                __field(        __u8,   flags           )
                __field(        u8,     proto           )
                __array(        __u8,   src,    4       )
                __array(        __u8,   dst,    4       )
                __array(        __u8,   gw,     4       )
                __array(        __u8,   saddr,  4       )
                __field(        u16,    sport           )
                __field(        u16,    dport           )
                __dynamic_array(char,  name,   IFNAMSIZ )
        )

When he try to access the element in the structure, the kernel panic
happen. Although he has rearrange the order of the structure to fix
the problem, but we cannot ignore the fact that there still need
unaligned access in kernel space. It can help us to avoid kernel panic
when reasonable unaligned address access happen. The users need to have
the knowledge that some unreasonable unaligned address may cause the bug
in kernel.

The config 'HAVE_EFFICIENT_UNALIGNED_ACCESS' must be with the hw
unaligned access config 'HW_SUPPORT_UNALIGNMENT_ACCESS'. In sw
unalinged access handler, the code 'get_inst()' in arch/nds32/mm/
alignment.c:522 would be generate as load word instruction if
'HAVE_EFFICIENT_UNALIGNED_ACCESS' is set. This would cause the kernel
hang in loop if the address of the load word instruction is unaligned.
For example:

	0xbc39e: lwi450 $r0, [$r1], if the $r1 cause unaligned access.
								|
								| unaligned access handler
								v
	arch/nds32/mm/alignment.c:522: get_ints():0xb0874b7e lwi450 $r2, [$3],
	$r3 is the address '0xbc39e', it would cause kernel unaligned access.
								|
								| unaligned access handler
								v
	arch/nds32/mm/alignment.c:522: get_ints():0xb0874b7e lwi450 $r2, [$3],
	$r3 is the address '0xb0874b7e', it would cause kernel unaligned access.

The kernel is hang in the loop.

Signed-off-by: Nickhu <nickhu@andestech.com>
---
 arch/nds32/kernel/traps.c | 4 +++-
 arch/nds32/mm/alignment.c | 6 ++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/nds32/kernel/traps.c b/arch/nds32/kernel/traps.c
index 1496aab48998..dcde7abc5515 100644
--- a/arch/nds32/kernel/traps.c
+++ b/arch/nds32/kernel/traps.c
@@ -331,6 +331,7 @@ void do_revinsn(struct pt_regs *regs)
 #ifdef CONFIG_ALIGNMENT_TRAP
 extern int unalign_access_mode;
 extern int do_unaligned_access(unsigned long addr, struct pt_regs *regs);
+extern int va_kernel_present(unsigned long addr);
 #endif
 void do_dispatch_general(unsigned long entry, unsigned long addr,
 			 unsigned long itype, struct pt_regs *regs,
@@ -341,7 +342,8 @@ void do_dispatch_general(unsigned long entry, unsigned long addr,
 	if (type == ETYPE_ALIGNMENT_CHECK) {
 #ifdef CONFIG_ALIGNMENT_TRAP
 		/* Alignment check */
-		if (user_mode(regs) && unalign_access_mode) {
+		if ((user_mode(regs) && unalign_access_mode) ||
+		    va_kernel_present(addr)) {
 			int ret;
 			ret = do_unaligned_access(addr, regs);
 
diff --git a/arch/nds32/mm/alignment.c b/arch/nds32/mm/alignment.c
index 66a556befd05..2d7a08af6622 100644
--- a/arch/nds32/mm/alignment.c
+++ b/arch/nds32/mm/alignment.c
@@ -524,8 +524,10 @@ int do_unaligned_access(unsigned long addr, struct pt_regs *regs)
 	DEBUG((unalign_access_debug > 0), 1,
 	      "Faulting addr: 0x%08lx, pc: 0x%08lx [inst: 0x%08lx ]\n", addr,
 	      regs->ipc, inst);
-
-	set_fs(USER_DS);
+	if ((user_mode(regs) && unalign_access_mode))
+		set_fs(USER_DS);
+	else if (va_kernel_present(addr))
+		set_fs(KERNEL_DS);
 
 	if (inst & NDS32_16BIT_INSTRUCTION)
 		ret = do_16((inst >> 16) & 0xffff, regs);
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] nds32: Unaligned access handler fix
  2018-10-18  8:34 [PATCH 0/3] nds32: Unaligned access handler fix Nickhu
                   ` (2 preceding siblings ...)
  2018-10-18  8:34 ` [PATCH 3/3] nds32: Add unaligned access in kernel space Nickhu
@ 2018-10-19  9:25 ` Greentime Hu
  3 siblings, 0 replies; 5+ messages in thread
From: Greentime Hu @ 2018-10-19  9:25 UTC (permalink / raw)
  To: Nickhu
  Cc: Greentime, Linux Kernel Mailing List, Arnd Bergmann,
	Vincent Chen, Zong Li, Eric W. Biederman

Nickhu <nickhu@andestech.com> 於 2018年10月18日 週四 下午4:34寫道:
>
> The patches are about unaligned access handler. We fix some
> bugs in unaligned access handler and add some kernel configs
> for unaligned access handler. Then we add the kernel unaligned
> access handled by software in handler.
>
> Nickhu (3):
>   nds32: Fix instruction simulator bug for unaligned access handler.
>   nds32: Add 'HAVE_EFFICIENT_UNALIGNED_ACCESS' config
>   nds32: Add unaligned access in kernel space.
>
>  arch/nds32/Kconfig.cpu    |  3 ++-
>  arch/nds32/kernel/traps.c |  4 +++-
>  arch/nds32/mm/alignment.c | 43 +++++++++++++++++++++++----------------
>  3 files changed, 30 insertions(+), 20 deletions(-)
>

Hi Nick,
Thanks
Acked-by: Greentime Hu <greentime@andestech.com>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-10-19  9:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-18  8:34 [PATCH 0/3] nds32: Unaligned access handler fix Nickhu
2018-10-18  8:34 ` [PATCH 1/3] nds32: Fix instruction simulator bug for unaligned access handler Nickhu
2018-10-18  8:34 ` [PATCH 2/3] nds32: Add 'HAVE_EFFICIENT_UNALIGNED_ACCESS' config Nickhu
2018-10-18  8:34 ` [PATCH 3/3] nds32: Add unaligned access in kernel space Nickhu
2018-10-19  9:25 ` [PATCH 0/3] nds32: Unaligned access handler fix Greentime Hu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).