Skip to content

Commit

Permalink
csky: Support kernel non-aligned access
Browse files Browse the repository at this point in the history
We prohibit non-aligned access in kernel mode, but some special NIC
driver needs to support kernel-state unaligned access. For example,
when the bus does not support unaligned access, IP header parsing
will cause non-aligned access and driver does not recopy the skb
buffer to dma for performance reasons.

Added kernel_enable & user_enable to control unaligned access and
added kernel_count  & user_count for statistical unaligned access.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
Cc: Arnd Bergmann <arnd@arndb.de>
  • Loading branch information
Guo Ren committed Aug 20, 2019
1 parent dc14004 commit c7e6f0e
Showing 1 changed file with 45 additions and 17 deletions.
62 changes: 45 additions & 17 deletions arch/csky/abiv1/alignment.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#include <linux/uaccess.h>
#include <linux/ptrace.h>

static int align_enable = 1;
static int align_count;
static int align_kern_enable = 1;
static int align_usr_enable = 1;
static int align_kern_count = 0;
static int align_usr_count = 0;

static inline uint32_t get_ptreg(struct pt_regs *regs, uint32_t rx)
{
Expand All @@ -32,9 +34,6 @@ static int ldb_asm(uint32_t addr, uint32_t *valp)
uint32_t val;
int err;

if (!access_ok((void *)addr, 1))
return 1;

asm volatile (
"movi %0, 0\n"
"1:\n"
Expand Down Expand Up @@ -67,9 +66,6 @@ static int stb_asm(uint32_t addr, uint32_t val)
{
int err;

if (!access_ok((void *)addr, 1))
return 1;

asm volatile (
"movi %0, 0\n"
"1:\n"
Expand Down Expand Up @@ -203,8 +199,6 @@ static int stw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
if (stb_asm(addr, byte3))
return 1;

align_count++;

return 0;
}

Expand All @@ -226,14 +220,34 @@ void csky_alignment(struct pt_regs *regs)
uint32_t addr = 0;

if (!user_mode(regs))
goto kernel_area;

if (!align_usr_enable) {
pr_err("%s user disabled.\n", __func__);
goto bad_area;
}

align_usr_count++;

ret = get_user(tmp, (uint16_t *)instruction_pointer(regs));
if (ret) {
pr_err("%s get_user failed.\n", __func__);
goto bad_area;
}

goto good_area;

kernel_area:
if (!align_kern_enable) {
pr_err("%s kernel disabled.\n", __func__);
goto bad_area;
}

align_kern_count++;

tmp = *(uint16_t *)instruction_pointer(regs);

good_area:
opcode = (uint32_t)tmp;

rx = opcode & 0xf;
Expand Down Expand Up @@ -286,18 +300,32 @@ void csky_alignment(struct pt_regs *regs)
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);
}

static struct ctl_table alignment_tbl[4] = {
static struct ctl_table alignment_tbl[5] = {
{
.procname = "kernel_enable",
.data = &align_kern_enable,
.maxlen = sizeof(align_kern_enable),
.mode = 0666,
.proc_handler = &proc_dointvec
},
{
.procname = "user_enable",
.data = &align_usr_enable,
.maxlen = sizeof(align_usr_enable),
.mode = 0666,
.proc_handler = &proc_dointvec
},
{
.procname = "enable",
.data = &align_enable,
.maxlen = sizeof(align_enable),
.procname = "kernel_count",
.data = &align_kern_count,
.maxlen = sizeof(align_kern_count),
.mode = 0666,
.proc_handler = &proc_dointvec
},
{
.procname = "count",
.data = &align_count,
.maxlen = sizeof(align_count),
.procname = "user_count",
.data = &align_usr_count,
.maxlen = sizeof(align_usr_count),
.mode = 0666,
.proc_handler = &proc_dointvec
},
Expand Down

0 comments on commit c7e6f0e

Please sign in to comment.