Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 fixes from Martin Schwidefsky: "An update for the BFP jit to the latest and greatest, two patches to get kdump working again, the random-abort ptrace extention for transactional execution, the z90crypt module alias for ap and a tiny cleanup" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/zcrypt: Alias for new zcrypt device driver base module s390/kdump: Allow copy_oldmem_page() copy to virtual memory s390/kdump: Disable mmap for s390 s390/bpf,jit: add pkt_type support s390/bpf,jit: address randomize and write protect jit code s390/bpf,jit: use generic jit dumper s390/bpf,jit: call module_free() from any context s390/qdio: remove unused variable s390/ptrace: PTRACE_TE_ABORT_RAND
This commit is contained in:
Коммит
89a8c5940d
|
@ -91,7 +91,15 @@ struct thread_struct {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PER_FLAG_NO_TE 1UL /* Flag to disable transactions. */
|
/* Flag to disable transactions. */
|
||||||
|
#define PER_FLAG_NO_TE 1UL
|
||||||
|
/* Flag to enable random transaction aborts. */
|
||||||
|
#define PER_FLAG_TE_ABORT_RAND 2UL
|
||||||
|
/* Flag to specify random transaction abort mode:
|
||||||
|
* - abort each transaction at a random instruction before TEND if set.
|
||||||
|
* - abort random transactions at a random instruction if cleared.
|
||||||
|
*/
|
||||||
|
#define PER_FLAG_TE_ABORT_RAND_TEND 4UL
|
||||||
|
|
||||||
typedef struct thread_struct thread_struct;
|
typedef struct thread_struct thread_struct;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include <linux/thread_info.h>
|
#include <linux/thread_info.h>
|
||||||
|
|
||||||
extern struct task_struct *__switch_to(void *, void *);
|
extern struct task_struct *__switch_to(void *, void *);
|
||||||
extern void update_per_regs(struct task_struct *task);
|
extern void update_cr_regs(struct task_struct *task);
|
||||||
|
|
||||||
static inline void save_fp_regs(s390_fp_regs *fpregs)
|
static inline void save_fp_regs(s390_fp_regs *fpregs)
|
||||||
{
|
{
|
||||||
|
@ -86,7 +86,7 @@ static inline void restore_access_regs(unsigned int *acrs)
|
||||||
restore_fp_regs(&next->thread.fp_regs); \
|
restore_fp_regs(&next->thread.fp_regs); \
|
||||||
restore_access_regs(&next->thread.acrs[0]); \
|
restore_access_regs(&next->thread.acrs[0]); \
|
||||||
restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \
|
restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \
|
||||||
update_per_regs(next); \
|
update_cr_regs(next); \
|
||||||
} \
|
} \
|
||||||
prev = __switch_to(prev,next); \
|
prev = __switch_to(prev,next); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
|
@ -400,6 +400,7 @@ typedef struct
|
||||||
#define PTRACE_POKE_SYSTEM_CALL 0x5008
|
#define PTRACE_POKE_SYSTEM_CALL 0x5008
|
||||||
#define PTRACE_ENABLE_TE 0x5009
|
#define PTRACE_ENABLE_TE 0x5009
|
||||||
#define PTRACE_DISABLE_TE 0x5010
|
#define PTRACE_DISABLE_TE 0x5010
|
||||||
|
#define PTRACE_TE_ABORT_RAND 0x5011
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PT_PROT definition is loosely based on hppa bsd definition in
|
* PT_PROT definition is loosely based on hppa bsd definition in
|
||||||
|
|
|
@ -21,6 +21,48 @@
|
||||||
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
|
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
|
||||||
#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
|
#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return physical address for virtual address
|
||||||
|
*/
|
||||||
|
static inline void *load_real_addr(void *addr)
|
||||||
|
{
|
||||||
|
unsigned long real_addr;
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
" lra %0,0(%1)\n"
|
||||||
|
" jz 0f\n"
|
||||||
|
" la %0,0\n"
|
||||||
|
"0:"
|
||||||
|
: "=a" (real_addr) : "a" (addr) : "cc");
|
||||||
|
return (void *)real_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy up to one page to vmalloc or real memory
|
||||||
|
*/
|
||||||
|
static ssize_t copy_page_real(void *buf, void *src, size_t csize)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
if (is_vmalloc_addr(buf)) {
|
||||||
|
BUG_ON(csize >= PAGE_SIZE);
|
||||||
|
/* If buf is not page aligned, copy first part */
|
||||||
|
size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize);
|
||||||
|
if (size) {
|
||||||
|
if (memcpy_real(load_real_addr(buf), src, size))
|
||||||
|
return -EFAULT;
|
||||||
|
buf += size;
|
||||||
|
src += size;
|
||||||
|
}
|
||||||
|
/* Copy second part */
|
||||||
|
size = csize - size;
|
||||||
|
return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0;
|
||||||
|
} else {
|
||||||
|
return memcpy_real(buf, src, csize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy one page from "oldmem"
|
* Copy one page from "oldmem"
|
||||||
*
|
*
|
||||||
|
@ -32,6 +74,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
|
||||||
size_t csize, unsigned long offset, int userbuf)
|
size_t csize, unsigned long offset, int userbuf)
|
||||||
{
|
{
|
||||||
unsigned long src;
|
unsigned long src;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!csize)
|
if (!csize)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -43,11 +86,11 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
|
||||||
src < OLDMEM_BASE + OLDMEM_SIZE)
|
src < OLDMEM_BASE + OLDMEM_SIZE)
|
||||||
src -= OLDMEM_BASE;
|
src -= OLDMEM_BASE;
|
||||||
if (userbuf)
|
if (userbuf)
|
||||||
copy_to_user_real((void __force __user *) buf, (void *) src,
|
rc = copy_to_user_real((void __force __user *) buf,
|
||||||
csize);
|
(void *) src, csize);
|
||||||
else
|
else
|
||||||
memcpy_real(buf, (void *) src, csize);
|
rc = copy_page_real(buf, (void *) src, csize);
|
||||||
return csize;
|
return (rc == 0) ? csize : rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -47,7 +47,7 @@ enum s390_regset {
|
||||||
REGSET_GENERAL_EXTENDED,
|
REGSET_GENERAL_EXTENDED,
|
||||||
};
|
};
|
||||||
|
|
||||||
void update_per_regs(struct task_struct *task)
|
void update_cr_regs(struct task_struct *task)
|
||||||
{
|
{
|
||||||
struct pt_regs *regs = task_pt_regs(task);
|
struct pt_regs *regs = task_pt_regs(task);
|
||||||
struct thread_struct *thread = &task->thread;
|
struct thread_struct *thread = &task->thread;
|
||||||
|
@ -56,17 +56,25 @@ void update_per_regs(struct task_struct *task)
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
/* Take care of the enable/disable of transactional execution. */
|
/* Take care of the enable/disable of transactional execution. */
|
||||||
if (MACHINE_HAS_TE) {
|
if (MACHINE_HAS_TE) {
|
||||||
unsigned long cr0, cr0_new;
|
unsigned long cr[3], cr_new[3];
|
||||||
|
|
||||||
__ctl_store(cr0, 0, 0);
|
__ctl_store(cr, 0, 2);
|
||||||
/* set or clear transaction execution bits 8 and 9. */
|
cr_new[1] = cr[1];
|
||||||
|
/* Set or clear transaction execution TXC/PIFO bits 8 and 9. */
|
||||||
if (task->thread.per_flags & PER_FLAG_NO_TE)
|
if (task->thread.per_flags & PER_FLAG_NO_TE)
|
||||||
cr0_new = cr0 & ~(3UL << 54);
|
cr_new[0] = cr[0] & ~(3UL << 54);
|
||||||
else
|
else
|
||||||
cr0_new = cr0 | (3UL << 54);
|
cr_new[0] = cr[0] | (3UL << 54);
|
||||||
/* Only load control register 0 if necessary. */
|
/* Set or clear transaction execution TDC bits 62 and 63. */
|
||||||
if (cr0 != cr0_new)
|
cr_new[2] = cr[2] & ~3UL;
|
||||||
__ctl_load(cr0_new, 0, 0);
|
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
|
||||||
|
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
|
||||||
|
cr_new[2] |= 1UL;
|
||||||
|
else
|
||||||
|
cr_new[2] |= 2UL;
|
||||||
|
}
|
||||||
|
if (memcmp(&cr_new, &cr, sizeof(cr)))
|
||||||
|
__ctl_load(cr_new, 0, 2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Copy user specified PER registers */
|
/* Copy user specified PER registers */
|
||||||
|
@ -100,14 +108,14 @@ void user_enable_single_step(struct task_struct *task)
|
||||||
{
|
{
|
||||||
set_tsk_thread_flag(task, TIF_SINGLE_STEP);
|
set_tsk_thread_flag(task, TIF_SINGLE_STEP);
|
||||||
if (task == current)
|
if (task == current)
|
||||||
update_per_regs(task);
|
update_cr_regs(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
void user_disable_single_step(struct task_struct *task)
|
void user_disable_single_step(struct task_struct *task)
|
||||||
{
|
{
|
||||||
clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
|
clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
|
||||||
if (task == current)
|
if (task == current)
|
||||||
update_per_regs(task);
|
update_cr_regs(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -447,6 +455,26 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||||
if (!MACHINE_HAS_TE)
|
if (!MACHINE_HAS_TE)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
child->thread.per_flags |= PER_FLAG_NO_TE;
|
child->thread.per_flags |= PER_FLAG_NO_TE;
|
||||||
|
child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND;
|
||||||
|
return 0;
|
||||||
|
case PTRACE_TE_ABORT_RAND:
|
||||||
|
if (!MACHINE_HAS_TE || (child->thread.per_flags & PER_FLAG_NO_TE))
|
||||||
|
return -EIO;
|
||||||
|
switch (data) {
|
||||||
|
case 0UL:
|
||||||
|
child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND;
|
||||||
|
break;
|
||||||
|
case 1UL:
|
||||||
|
child->thread.per_flags |= PER_FLAG_TE_ABORT_RAND;
|
||||||
|
child->thread.per_flags |= PER_FLAG_TE_ABORT_RAND_TEND;
|
||||||
|
break;
|
||||||
|
case 2UL:
|
||||||
|
child->thread.per_flags |= PER_FLAG_TE_ABORT_RAND;
|
||||||
|
child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND_TEND;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
/* Removing high order bit from addr (only for 31 bit). */
|
/* Removing high order bit from addr (only for 31 bit). */
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/if_vlan.h>
|
#include <linux/if_vlan.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
|
#include <linux/random.h>
|
||||||
|
#include <linux/init.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/facility.h>
|
#include <asm/facility.h>
|
||||||
|
@ -221,6 +223,37 @@ static void bpf_jit_epilogue(struct bpf_jit *jit)
|
||||||
EMIT2(0x07fe);
|
EMIT2(0x07fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper to find the offset of pkt_type in sk_buff
|
||||||
|
* Make sure its still a 3bit field starting at the MSBs within a byte.
|
||||||
|
*/
|
||||||
|
#define PKT_TYPE_MAX 0xe0
|
||||||
|
static int pkt_type_offset;
|
||||||
|
|
||||||
|
static int __init bpf_pkt_type_offset_init(void)
|
||||||
|
{
|
||||||
|
struct sk_buff skb_probe = {
|
||||||
|
.pkt_type = ~0,
|
||||||
|
};
|
||||||
|
char *ct = (char *)&skb_probe;
|
||||||
|
int off;
|
||||||
|
|
||||||
|
pkt_type_offset = -1;
|
||||||
|
for (off = 0; off < sizeof(struct sk_buff); off++) {
|
||||||
|
if (!ct[off])
|
||||||
|
continue;
|
||||||
|
if (ct[off] == PKT_TYPE_MAX)
|
||||||
|
pkt_type_offset = off;
|
||||||
|
else {
|
||||||
|
/* Found non matching bit pattern, fix needed. */
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
pkt_type_offset = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
device_initcall(bpf_pkt_type_offset_init);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make sure we dont leak kernel information to user
|
* make sure we dont leak kernel information to user
|
||||||
*/
|
*/
|
||||||
|
@ -720,6 +753,16 @@ call_fn: /* lg %r1,<d(function)>(%r13) */
|
||||||
EMIT4_DISP(0x88500000, 12);
|
EMIT4_DISP(0x88500000, 12);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case BPF_S_ANC_PKTTYPE:
|
||||||
|
if (pkt_type_offset < 0)
|
||||||
|
goto out;
|
||||||
|
/* lhi %r5,0 */
|
||||||
|
EMIT4(0xa7580000);
|
||||||
|
/* ic %r5,<d(pkt_type_offset)>(%r2) */
|
||||||
|
EMIT4_DISP(0x43502000, pkt_type_offset);
|
||||||
|
/* srl %r5,5 */
|
||||||
|
EMIT4_DISP(0x88500000, 5);
|
||||||
|
break;
|
||||||
case BPF_S_ANC_CPU: /* A = smp_processor_id() */
|
case BPF_S_ANC_CPU: /* A = smp_processor_id() */
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/* l %r5,<d(cpu_nr)> */
|
/* l %r5,<d(cpu_nr)> */
|
||||||
|
@ -738,8 +781,41 @@ out:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: for security reasons, bpf code will follow a randomly
|
||||||
|
* sized amount of illegal instructions.
|
||||||
|
*/
|
||||||
|
struct bpf_binary_header {
|
||||||
|
unsigned int pages;
|
||||||
|
u8 image[];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct bpf_binary_header *bpf_alloc_binary(unsigned int bpfsize,
|
||||||
|
u8 **image_ptr)
|
||||||
|
{
|
||||||
|
struct bpf_binary_header *header;
|
||||||
|
unsigned int sz, hole;
|
||||||
|
|
||||||
|
/* Most BPF filters are really small, but if some of them fill a page,
|
||||||
|
* allow at least 128 extra bytes for illegal instructions.
|
||||||
|
*/
|
||||||
|
sz = round_up(bpfsize + sizeof(*header) + 128, PAGE_SIZE);
|
||||||
|
header = module_alloc(sz);
|
||||||
|
if (!header)
|
||||||
|
return NULL;
|
||||||
|
memset(header, 0, sz);
|
||||||
|
header->pages = sz / PAGE_SIZE;
|
||||||
|
hole = sz - bpfsize + sizeof(*header);
|
||||||
|
/* Insert random number of illegal instructions before BPF code
|
||||||
|
* and make sure the first instruction starts at an even address.
|
||||||
|
*/
|
||||||
|
*image_ptr = &header->image[(prandom_u32() % hole) & -2];
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
void bpf_jit_compile(struct sk_filter *fp)
|
void bpf_jit_compile(struct sk_filter *fp)
|
||||||
{
|
{
|
||||||
|
struct bpf_binary_header *header = NULL;
|
||||||
unsigned long size, prg_len, lit_len;
|
unsigned long size, prg_len, lit_len;
|
||||||
struct bpf_jit jit, cjit;
|
struct bpf_jit jit, cjit;
|
||||||
unsigned int *addrs;
|
unsigned int *addrs;
|
||||||
|
@ -772,12 +848,11 @@ void bpf_jit_compile(struct sk_filter *fp)
|
||||||
} else if (jit.prg == cjit.prg && jit.lit == cjit.lit) {
|
} else if (jit.prg == cjit.prg && jit.lit == cjit.lit) {
|
||||||
prg_len = jit.prg - jit.start;
|
prg_len = jit.prg - jit.start;
|
||||||
lit_len = jit.lit - jit.mid;
|
lit_len = jit.lit - jit.mid;
|
||||||
size = max_t(unsigned long, prg_len + lit_len,
|
size = prg_len + lit_len;
|
||||||
sizeof(struct work_struct));
|
|
||||||
if (size >= BPF_SIZE_MAX)
|
if (size >= BPF_SIZE_MAX)
|
||||||
goto out;
|
goto out;
|
||||||
jit.start = module_alloc(size);
|
header = bpf_alloc_binary(size, &jit.start);
|
||||||
if (!jit.start)
|
if (!header)
|
||||||
goto out;
|
goto out;
|
||||||
jit.prg = jit.mid = jit.start + prg_len;
|
jit.prg = jit.mid = jit.start + prg_len;
|
||||||
jit.lit = jit.end = jit.start + prg_len + lit_len;
|
jit.lit = jit.end = jit.start + prg_len + lit_len;
|
||||||
|
@ -788,37 +863,25 @@ void bpf_jit_compile(struct sk_filter *fp)
|
||||||
cjit = jit;
|
cjit = jit;
|
||||||
}
|
}
|
||||||
if (bpf_jit_enable > 1) {
|
if (bpf_jit_enable > 1) {
|
||||||
pr_err("flen=%d proglen=%lu pass=%d image=%p\n",
|
bpf_jit_dump(fp->len, jit.end - jit.start, pass, jit.start);
|
||||||
fp->len, jit.end - jit.start, pass, jit.start);
|
if (jit.start)
|
||||||
if (jit.start) {
|
|
||||||
printk(KERN_ERR "JIT code:\n");
|
|
||||||
print_fn_code(jit.start, jit.mid - jit.start);
|
print_fn_code(jit.start, jit.mid - jit.start);
|
||||||
print_hex_dump(KERN_ERR, "JIT literals:\n",
|
|
||||||
DUMP_PREFIX_ADDRESS, 16, 1,
|
|
||||||
jit.mid, jit.end - jit.mid, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (jit.start)
|
if (jit.start) {
|
||||||
|
set_memory_ro((unsigned long)header, header->pages);
|
||||||
fp->bpf_func = (void *) jit.start;
|
fp->bpf_func = (void *) jit.start;
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
kfree(addrs);
|
kfree(addrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jit_free_defer(struct work_struct *arg)
|
|
||||||
{
|
|
||||||
module_free(NULL, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* run from softirq, we must use a work_struct to call
|
|
||||||
* module_free() from process context
|
|
||||||
*/
|
|
||||||
void bpf_jit_free(struct sk_filter *fp)
|
void bpf_jit_free(struct sk_filter *fp)
|
||||||
{
|
{
|
||||||
struct work_struct *work;
|
unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
|
||||||
|
struct bpf_binary_header *header = (void *)addr;
|
||||||
|
|
||||||
if (fp->bpf_func == sk_run_filter)
|
if (fp->bpf_func == sk_run_filter)
|
||||||
return;
|
return;
|
||||||
work = (struct work_struct *)fp->bpf_func;
|
set_memory_rw(addr, header->pages);
|
||||||
INIT_WORK(work, jit_free_defer);
|
module_free(NULL, header);
|
||||||
schedule_work(work);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1497,7 +1497,7 @@ static inline int buf_in_between(int bufnr, int start, int count)
|
||||||
static int handle_inbound(struct qdio_q *q, unsigned int callflags,
|
static int handle_inbound(struct qdio_q *q, unsigned int callflags,
|
||||||
int bufnr, int count)
|
int bufnr, int count)
|
||||||
{
|
{
|
||||||
int used, diff;
|
int diff;
|
||||||
|
|
||||||
qperf_inc(q, inbound_call);
|
qperf_inc(q, inbound_call);
|
||||||
|
|
||||||
|
@ -1530,7 +1530,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
|
||||||
|
|
||||||
set:
|
set:
|
||||||
count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count);
|
count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count);
|
||||||
used = atomic_add_return(count, &q->nr_buf_used) - count;
|
atomic_add(count, &q->nr_buf_used);
|
||||||
|
|
||||||
if (need_siga_in(q))
|
if (need_siga_in(q))
|
||||||
return qdio_siga_input(q);
|
return qdio_siga_input(q);
|
||||||
|
|
|
@ -71,6 +71,7 @@ MODULE_AUTHOR("IBM Corporation");
|
||||||
MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \
|
MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \
|
||||||
"Copyright IBM Corp. 2006, 2012");
|
"Copyright IBM Corp. 2006, 2012");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("z90crypt");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Module parameter
|
* Module parameter
|
||||||
|
|
|
@ -223,7 +223,7 @@ static inline char *alloc_elfnotes_buf(size_t notes_sz)
|
||||||
* regions in the 1st kernel pointed to by PT_LOAD entries) into
|
* regions in the 1st kernel pointed to by PT_LOAD entries) into
|
||||||
* virtually contiguous user-space in ELF layout.
|
* virtually contiguous user-space in ELF layout.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_MMU
|
#if defined(CONFIG_MMU) && !defined(CONFIG_S390)
|
||||||
static int mmap_vmcore(struct file *file, struct vm_area_struct *vma)
|
static int mmap_vmcore(struct file *file, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
size_t size = vma->vm_end - vma->vm_start;
|
size_t size = vma->vm_end - vma->vm_start;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче