csky: Support kernel non-aligned access
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>
This commit is contained in:
parent
dc140045c0
commit
c7e6f0e992
@ -5,8 +5,10 @@
|
|||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
|
|
||||||
static int align_enable = 1;
|
static int align_kern_enable = 1;
|
||||||
static int align_count;
|
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)
|
static inline uint32_t get_ptreg(struct pt_regs *regs, uint32_t rx)
|
||||||
{
|
{
|
||||||
@ -32,9 +34,6 @@ static int ldb_asm(uint32_t addr, uint32_t *valp)
|
|||||||
uint32_t val;
|
uint32_t val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!access_ok((void *)addr, 1))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"movi %0, 0\n"
|
"movi %0, 0\n"
|
||||||
"1:\n"
|
"1:\n"
|
||||||
@ -67,9 +66,6 @@ static int stb_asm(uint32_t addr, uint32_t val)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!access_ok((void *)addr, 1))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"movi %0, 0\n"
|
"movi %0, 0\n"
|
||||||
"1:\n"
|
"1:\n"
|
||||||
@ -203,8 +199,6 @@ static int stw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
|
|||||||
if (stb_asm(addr, byte3))
|
if (stb_asm(addr, byte3))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
align_count++;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +220,14 @@ void csky_alignment(struct pt_regs *regs)
|
|||||||
uint32_t addr = 0;
|
uint32_t addr = 0;
|
||||||
|
|
||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
|
goto kernel_area;
|
||||||
|
|
||||||
|
if (!align_usr_enable) {
|
||||||
|
pr_err("%s user disabled.\n", __func__);
|
||||||
goto bad_area;
|
goto bad_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
align_usr_count++;
|
||||||
|
|
||||||
ret = get_user(tmp, (uint16_t *)instruction_pointer(regs));
|
ret = get_user(tmp, (uint16_t *)instruction_pointer(regs));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -234,6 +235,19 @@ void csky_alignment(struct pt_regs *regs)
|
|||||||
goto bad_area;
|
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;
|
opcode = (uint32_t)tmp;
|
||||||
|
|
||||||
rx = opcode & 0xf;
|
rx = opcode & 0xf;
|
||||||
@ -286,18 +300,32 @@ bad_area:
|
|||||||
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);
|
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ctl_table alignment_tbl[4] = {
|
static struct ctl_table alignment_tbl[5] = {
|
||||||
{
|
{
|
||||||
.procname = "enable",
|
.procname = "kernel_enable",
|
||||||
.data = &align_enable,
|
.data = &align_kern_enable,
|
||||||
.maxlen = sizeof(align_enable),
|
.maxlen = sizeof(align_kern_enable),
|
||||||
.mode = 0666,
|
.mode = 0666,
|
||||||
.proc_handler = &proc_dointvec
|
.proc_handler = &proc_dointvec
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.procname = "count",
|
.procname = "user_enable",
|
||||||
.data = &align_count,
|
.data = &align_usr_enable,
|
||||||
.maxlen = sizeof(align_count),
|
.maxlen = sizeof(align_usr_enable),
|
||||||
|
.mode = 0666,
|
||||||
|
.proc_handler = &proc_dointvec
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.procname = "kernel_count",
|
||||||
|
.data = &align_kern_count,
|
||||||
|
.maxlen = sizeof(align_kern_count),
|
||||||
|
.mode = 0666,
|
||||||
|
.proc_handler = &proc_dointvec
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.procname = "user_count",
|
||||||
|
.data = &align_usr_count,
|
||||||
|
.maxlen = sizeof(align_usr_count),
|
||||||
.mode = 0666,
|
.mode = 0666,
|
||||||
.proc_handler = &proc_dointvec
|
.proc_handler = &proc_dointvec
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user