You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6: (27 commits) [S390] Fix checkstack for s390 [S390] fix initialization of stp [S390] 3215: Remove tasklet. [S390] console flush on panic / reboot [S390] introduce dirty bit for kvm live migration [S390] Add ioctl support for EMC Symmetrix Subsystem Control I/O [S390] xpram: per device block request queues. [S390] dasd: fix message flood for unsolicited interrupts [S390] Move private simple udelay function to arch/s390/lib/delay.c. [S390] dcssblk: add >2G DCSSs support and stacked contiguous DCSSs support. [S390] ptrace changes [S390] s390: use sys_pause for 31bit pause entry point [S390] qdio enhanced SIGA (iqdio) support. [S390] cio: fix cio_tpi. [S390] cio: Correct use of ! and & [S390] cio: inline assembly cleanup [S390] bus_id -> dev_set_name() for css and ccw busses [S390] bus_id ->dev_name() conversions in qdio [S390] Use s390_root_dev_* in kvm_virtio. [S390] more bus_id -> dev_name conversions ...
This commit is contained in:
@@ -70,13 +70,19 @@ Command line parameters
|
||||
|
||||
Note: While already known devices can be added to the list of devices to be
|
||||
ignored, there will be no effect on then. However, if such a device
|
||||
disappears and then reappears, it will then be ignored.
|
||||
disappears and then reappears, it will then be ignored. To make
|
||||
known devices go away, you need the "purge" command (see below).
|
||||
|
||||
For example,
|
||||
"echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore"
|
||||
will add 0.0.a000-0.0.accc and 0.0.af00-0.0.afff to the list of ignored
|
||||
devices.
|
||||
|
||||
You can remove already known but now ignored devices via
|
||||
"echo purge > /proc/cio_ignore"
|
||||
All devices ignored but still registered and not online (= not in use)
|
||||
will be deregistered and thus removed from the system.
|
||||
|
||||
The devices can be specified either by bus id (0.x.abcd) or, for 2.4 backward
|
||||
compatibility, by the device number in hexadecimal (0xabcd or abcd). Device
|
||||
numbers given as 0xabcd will be interpreted as 0.0.abcd.
|
||||
@@ -98,8 +104,7 @@ debugfs entries
|
||||
handling).
|
||||
|
||||
- /sys/kernel/debug/s390dbf/cio_msg/sprintf
|
||||
Various debug messages from the common I/O-layer, including messages
|
||||
printed when cio_msg=yes.
|
||||
Various debug messages from the common I/O-layer.
|
||||
|
||||
- /sys/kernel/debug/s390dbf/cio_trace/hex_ascii
|
||||
Logs the calling of functions in the common I/O-layer and, if applicable,
|
||||
|
||||
@@ -74,6 +74,7 @@ config S390
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_KVM if 64BIT
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
|
||||
* Bugreports.to..: <Linux390@de.ibm.com>
|
||||
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
|
||||
* EMC Symmetrix ioctl Copyright EMC Corporation, 2008
|
||||
* Author.........: Nigel Hislop <hislop_nigel@emc.com>
|
||||
*
|
||||
* This file is the interface of the DASD device driver, which is exported to user space
|
||||
* any future changes wrt the API will result in a change of the APIVERSION reported
|
||||
@@ -202,6 +204,16 @@ typedef struct attrib_data_t {
|
||||
#define DASD_SEQ_PRESTAGE 0x4
|
||||
#define DASD_REC_ACCESS 0x5
|
||||
|
||||
/*
|
||||
* Perform EMC Symmetrix I/O
|
||||
*/
|
||||
typedef struct dasd_symmio_parms {
|
||||
unsigned char reserved[8]; /* compat with older releases */
|
||||
unsigned long long psf_data; /* char * cast to u64 */
|
||||
unsigned long long rssd_result; /* char * cast to u64 */
|
||||
int psf_data_len;
|
||||
int rssd_result_len;
|
||||
} __attribute__ ((packed)) dasd_symmio_parms_t;
|
||||
|
||||
/********************************************************************************
|
||||
* SECTION: Definition of IOCTLs
|
||||
@@ -247,6 +259,7 @@ typedef struct attrib_data_t {
|
||||
/* Set Attributes (cache operations) */
|
||||
#define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t)
|
||||
|
||||
#define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t)
|
||||
|
||||
#endif /* DASD_H */
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#define _S390_DELAY_H
|
||||
|
||||
extern void __udelay(unsigned long usecs);
|
||||
extern void udelay_simple(unsigned long usecs);
|
||||
extern void __delay(unsigned long loops);
|
||||
|
||||
#define udelay(n) __udelay(n)
|
||||
|
||||
@@ -281,6 +281,9 @@ extern char empty_zero_page[PAGE_SIZE];
|
||||
#define RCP_GR_BIT 50
|
||||
#define RCP_GC_BIT 49
|
||||
|
||||
/* User dirty bit for KVM's migration feature */
|
||||
#define KVM_UD_BIT 47
|
||||
|
||||
#ifndef __s390x__
|
||||
|
||||
/* Bits in the segment table address-space-control-element */
|
||||
@@ -575,12 +578,16 @@ static inline void ptep_rcp_copy(pte_t *ptep)
|
||||
unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
|
||||
|
||||
skey = page_get_storage_key(page_to_phys(page));
|
||||
if (skey & _PAGE_CHANGED)
|
||||
if (skey & _PAGE_CHANGED) {
|
||||
set_bit_simple(RCP_GC_BIT, pgste);
|
||||
set_bit_simple(KVM_UD_BIT, pgste);
|
||||
}
|
||||
if (skey & _PAGE_REFERENCED)
|
||||
set_bit_simple(RCP_GR_BIT, pgste);
|
||||
if (test_and_clear_bit_simple(RCP_HC_BIT, pgste))
|
||||
if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) {
|
||||
SetPageDirty(page);
|
||||
set_bit_simple(KVM_UD_BIT, pgste);
|
||||
}
|
||||
if (test_and_clear_bit_simple(RCP_HR_BIT, pgste))
|
||||
SetPageReferenced(page);
|
||||
#endif
|
||||
@@ -744,6 +751,40 @@ static inline pte_t pte_mkspecial(pte_t pte)
|
||||
return pte;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PGSTE
|
||||
/*
|
||||
* Get (and clear) the user dirty bit for a PTE.
|
||||
*/
|
||||
static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm,
|
||||
pte_t *ptep)
|
||||
{
|
||||
int dirty;
|
||||
unsigned long *pgste;
|
||||
struct page *page;
|
||||
unsigned int skey;
|
||||
|
||||
if (!mm->context.pgstes)
|
||||
return -EINVAL;
|
||||
rcp_lock(ptep);
|
||||
pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
|
||||
page = virt_to_page(pte_val(*ptep));
|
||||
skey = page_get_storage_key(page_to_phys(page));
|
||||
if (skey & _PAGE_CHANGED) {
|
||||
set_bit_simple(RCP_GC_BIT, pgste);
|
||||
set_bit_simple(KVM_UD_BIT, pgste);
|
||||
}
|
||||
if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) {
|
||||
SetPageDirty(page);
|
||||
set_bit_simple(KVM_UD_BIT, pgste);
|
||||
}
|
||||
dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste);
|
||||
if (skey & _PAGE_CHANGED)
|
||||
page_clear_dirty(page);
|
||||
rcp_unlock(ptep);
|
||||
return dirty;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
|
||||
static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
|
||||
@@ -490,6 +490,7 @@ extern void user_disable_single_step(struct task_struct *);
|
||||
|
||||
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
|
||||
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
|
||||
#define user_stack_pointer(regs)((regs)->gprs[15])
|
||||
#define regs_return_value(regs)((regs)->gprs[2])
|
||||
#define profile_pc(regs) instruction_pointer(regs)
|
||||
extern void show_regs(struct pt_regs * regs);
|
||||
|
||||
@@ -299,7 +299,13 @@ struct qdio_ssqd_desc {
|
||||
u8 mbccnt;
|
||||
u16 qdioac2;
|
||||
u64 sch_token;
|
||||
u64:64;
|
||||
u8 mro;
|
||||
u8 mri;
|
||||
u8:8;
|
||||
u8 sbalic;
|
||||
u16:16;
|
||||
u8:8;
|
||||
u8 mmwc;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* params are: ccw_device, qdio_error, queue_number,
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Access to user system call parameters and results
|
||||
*
|
||||
* Copyright IBM Corp. 2008
|
||||
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (version 2 only)
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_SYSCALL_H
|
||||
#define _ASM_SYSCALL_H 1
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
static inline long syscall_get_nr(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (regs->trap != __LC_SVC_OLD_PSW)
|
||||
return -1;
|
||||
return regs->gprs[2];
|
||||
}
|
||||
|
||||
static inline void syscall_rollback(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs->gprs[2] = regs->orig_gpr2;
|
||||
}
|
||||
|
||||
static inline long syscall_get_error(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0;
|
||||
}
|
||||
|
||||
static inline long syscall_get_return_value(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return regs->gprs[2];
|
||||
}
|
||||
|
||||
static inline void syscall_set_return_value(struct task_struct *task,
|
||||
struct pt_regs *regs,
|
||||
int error, long val)
|
||||
{
|
||||
regs->gprs[2] = error ? -error : val;
|
||||
}
|
||||
|
||||
static inline void syscall_get_arguments(struct task_struct *task,
|
||||
struct pt_regs *regs,
|
||||
unsigned int i, unsigned int n,
|
||||
unsigned long *args)
|
||||
{
|
||||
BUG_ON(i + n > 6);
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (test_tsk_thread_flag(task, TIF_31BIT)) {
|
||||
if (i + n == 6)
|
||||
args[--n] = (u32) regs->args[0];
|
||||
while (n-- > 0)
|
||||
args[n] = (u32) regs->gprs[2 + i + n];
|
||||
}
|
||||
#endif
|
||||
if (i + n == 6)
|
||||
args[--n] = regs->args[0];
|
||||
memcpy(args, ®s->gprs[2 + i], n * sizeof(args[0]));
|
||||
}
|
||||
|
||||
static inline void syscall_set_arguments(struct task_struct *task,
|
||||
struct pt_regs *regs,
|
||||
unsigned int i, unsigned int n,
|
||||
const unsigned long *args)
|
||||
{
|
||||
BUG_ON(i + n > 6);
|
||||
if (i + n == 6)
|
||||
regs->args[0] = args[--n];
|
||||
memcpy(®s->gprs[2 + i], args, n * sizeof(args[0]));
|
||||
}
|
||||
|
||||
#endif /* _ASM_SYSCALL_H */
|
||||
@@ -86,6 +86,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||
* thread information flags bit numbers
|
||||
*/
|
||||
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
|
||||
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
|
||||
#define TIF_SIGPENDING 2 /* signal pending */
|
||||
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
|
||||
#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
|
||||
@@ -100,6 +101,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||
#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */
|
||||
|
||||
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
|
||||
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
|
||||
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
|
||||
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
|
||||
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
|
||||
|
||||
@@ -608,14 +608,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct time
|
||||
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
|
||||
}
|
||||
|
||||
/* These are here just in case some old sparc32 binary calls it. */
|
||||
asmlinkage long sys32_pause(void)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
|
||||
size_t count, u32 poshi, u32 poslo)
|
||||
{
|
||||
|
||||
@@ -206,7 +206,6 @@ long sys32_gettimeofday(struct compat_timeval __user *tv,
|
||||
struct timezone __user *tz);
|
||||
long sys32_settimeofday(struct compat_timeval __user *tv,
|
||||
struct timezone __user *tz);
|
||||
long sys32_pause(void);
|
||||
long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
|
||||
u32 poshi, u32 poslo);
|
||||
long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
|
||||
|
||||
@@ -128,8 +128,6 @@ sys32_alarm_wrapper:
|
||||
llgfr %r2,%r2 # unsigned int
|
||||
jg sys_alarm # branch to system call
|
||||
|
||||
#sys32_pause_wrapper # void
|
||||
|
||||
.globl compat_sys_utime_wrapper
|
||||
compat_sys_utime_wrapper:
|
||||
llgtr %r2,%r2 # char *
|
||||
|
||||
+40
-10
@@ -49,9 +49,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
|
||||
SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
|
||||
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
|
||||
|
||||
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
||||
_TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
|
||||
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
||||
_TIF_MCCK_PENDING)
|
||||
|
||||
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
|
||||
@@ -318,6 +318,8 @@ sysc_work:
|
||||
bo BASED(sysc_reschedule)
|
||||
tm __TI_flags+3(%r9),_TIF_SIGPENDING
|
||||
bnz BASED(sysc_sigpending)
|
||||
tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
|
||||
bnz BASED(sysc_notify_resume)
|
||||
tm __TI_flags+3(%r9),_TIF_RESTART_SVC
|
||||
bo BASED(sysc_restart)
|
||||
tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
|
||||
@@ -355,6 +357,16 @@ sysc_sigpending:
|
||||
bo BASED(sysc_singlestep)
|
||||
b BASED(sysc_work_loop)
|
||||
|
||||
#
|
||||
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
|
||||
#
|
||||
sysc_notify_resume:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
l %r1,BASED(.Ldo_notify_resume)
|
||||
la %r14,BASED(sysc_work_loop)
|
||||
br %r1 # call do_notify_resume
|
||||
|
||||
|
||||
#
|
||||
# _TIF_RESTART_SVC is set, set up registers and restart svc
|
||||
#
|
||||
@@ -378,20 +390,21 @@ sysc_singlestep:
|
||||
br %r1 # branch to do_single_step
|
||||
|
||||
#
|
||||
# call trace before and after sys_call
|
||||
# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
|
||||
# and after the system call
|
||||
#
|
||||
sysc_tracesys:
|
||||
l %r1,BASED(.Ltrace)
|
||||
l %r1,BASED(.Ltrace_entry)
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
la %r3,0
|
||||
srl %r7,2
|
||||
st %r7,SP_R2(%r15)
|
||||
basr %r14,%r1
|
||||
clc SP_R2(4,%r15),BASED(.Lnr_syscalls)
|
||||
cl %r2,BASED(.Lnr_syscalls)
|
||||
bnl BASED(sysc_tracenogo)
|
||||
l %r8,BASED(.Lsysc_table)
|
||||
l %r7,SP_R2(%r15) # strace might have changed the
|
||||
sll %r7,2 # system call
|
||||
lr %r7,%r2
|
||||
sll %r7,2 # *4
|
||||
l %r8,0(%r7,%r8)
|
||||
sysc_tracego:
|
||||
lm %r3,%r6,SP_R3(%r15)
|
||||
@@ -401,9 +414,8 @@ sysc_tracego:
|
||||
sysc_tracenogo:
|
||||
tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
|
||||
bz BASED(sysc_return)
|
||||
l %r1,BASED(.Ltrace)
|
||||
l %r1,BASED(.Ltrace_exit)
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
la %r3,1
|
||||
la %r14,BASED(sysc_return)
|
||||
br %r1
|
||||
|
||||
@@ -666,6 +678,8 @@ io_work_loop:
|
||||
bo BASED(io_reschedule)
|
||||
tm __TI_flags+3(%r9),_TIF_SIGPENDING
|
||||
bnz BASED(io_sigpending)
|
||||
tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
|
||||
bnz BASED(io_notify_resume)
|
||||
b BASED(io_restore)
|
||||
io_work_done:
|
||||
|
||||
@@ -704,6 +718,19 @@ io_sigpending:
|
||||
TRACE_IRQS_OFF
|
||||
b BASED(io_work_loop)
|
||||
|
||||
#
|
||||
# _TIF_SIGPENDING is set, call do_signal
|
||||
#
|
||||
io_notify_resume:
|
||||
TRACE_IRQS_ON
|
||||
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
l %r1,BASED(.Ldo_notify_resume)
|
||||
basr %r14,%r1 # call do_signal
|
||||
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
|
||||
TRACE_IRQS_OFF
|
||||
b BASED(io_work_loop)
|
||||
|
||||
/*
|
||||
* External interrupt handler routine
|
||||
*/
|
||||
@@ -1070,6 +1097,8 @@ cleanup_io_leave_insn:
|
||||
.Ldo_IRQ: .long do_IRQ
|
||||
.Ldo_extint: .long do_extint
|
||||
.Ldo_signal: .long do_signal
|
||||
.Ldo_notify_resume:
|
||||
.long do_notify_resume
|
||||
.Lhandle_per: .long do_single_step
|
||||
.Ldo_execve: .long do_execve
|
||||
.Lexecve_tail: .long execve_tail
|
||||
@@ -1079,7 +1108,8 @@ cleanup_io_leave_insn:
|
||||
.Lpreempt_schedule_irq:
|
||||
.long preempt_schedule_irq
|
||||
#endif
|
||||
.Ltrace: .long syscall_trace
|
||||
.Ltrace_entry: .long do_syscall_trace_enter
|
||||
.Ltrace_exit: .long do_syscall_trace_exit
|
||||
.Lschedtail: .long schedule_tail
|
||||
.Lsysc_table: .long sys_call_table
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
|
||||
+32
-10
@@ -52,9 +52,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
|
||||
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
|
||||
STACK_SIZE = 1 << STACK_SHIFT
|
||||
|
||||
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
||||
_TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
|
||||
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
||||
_TIF_MCCK_PENDING)
|
||||
|
||||
#define BASED(name) name-system_call(%r13)
|
||||
@@ -310,6 +310,8 @@ sysc_work:
|
||||
jo sysc_reschedule
|
||||
tm __TI_flags+7(%r9),_TIF_SIGPENDING
|
||||
jnz sysc_sigpending
|
||||
tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
|
||||
jnz sysc_notify_resume
|
||||
tm __TI_flags+7(%r9),_TIF_RESTART_SVC
|
||||
jo sysc_restart
|
||||
tm __TI_flags+7(%r9),_TIF_SINGLE_STEP
|
||||
@@ -344,6 +346,14 @@ sysc_sigpending:
|
||||
jo sysc_singlestep
|
||||
j sysc_work_loop
|
||||
|
||||
#
|
||||
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
|
||||
#
|
||||
sysc_notify_resume:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
larl %r14,sysc_work_loop
|
||||
jg do_notify_resume # call do_notify_resume
|
||||
|
||||
#
|
||||
# _TIF_RESTART_SVC is set, set up registers and restart svc
|
||||
#
|
||||
@@ -367,20 +377,19 @@ sysc_singlestep:
|
||||
jg do_single_step # branch to do_sigtrap
|
||||
|
||||
#
|
||||
# call syscall_trace before and after system call
|
||||
# special linkage: %r12 contains the return address for trace_svc
|
||||
# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
|
||||
# and after the system call
|
||||
#
|
||||
sysc_tracesys:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
la %r3,0
|
||||
srl %r7,2
|
||||
stg %r7,SP_R2(%r15)
|
||||
brasl %r14,syscall_trace
|
||||
brasl %r14,do_syscall_trace_enter
|
||||
lghi %r0,NR_syscalls
|
||||
clg %r0,SP_R2(%r15)
|
||||
clgr %r0,%r2
|
||||
jnh sysc_tracenogo
|
||||
lg %r7,SP_R2(%r15) # strace might have changed the
|
||||
sll %r7,2 # system call
|
||||
slag %r7,%r2,2 # *4
|
||||
lgf %r8,0(%r7,%r10)
|
||||
sysc_tracego:
|
||||
lmg %r3,%r6,SP_R3(%r15)
|
||||
@@ -391,9 +400,8 @@ sysc_tracenogo:
|
||||
tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
|
||||
jz sysc_return
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
la %r3,1
|
||||
larl %r14,sysc_return # return point is sysc_return
|
||||
jg syscall_trace
|
||||
jg do_syscall_trace_exit
|
||||
|
||||
#
|
||||
# a new process exits the kernel with ret_from_fork
|
||||
@@ -672,6 +680,8 @@ io_work_loop:
|
||||
jo io_reschedule
|
||||
tm __TI_flags+7(%r9),_TIF_SIGPENDING
|
||||
jnz io_sigpending
|
||||
tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
|
||||
jnz io_notify_resume
|
||||
j io_restore
|
||||
io_work_done:
|
||||
|
||||
@@ -712,6 +722,18 @@ io_sigpending:
|
||||
TRACE_IRQS_OFF
|
||||
j io_work_loop
|
||||
|
||||
#
|
||||
# _TIF_NOTIFY_RESUME or is set, call do_notify_resume
|
||||
#
|
||||
io_notify_resume:
|
||||
TRACE_IRQS_ON
|
||||
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
brasl %r14,do_notify_resume # call do_notify_resume
|
||||
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
|
||||
TRACE_IRQS_OFF
|
||||
j io_work_loop
|
||||
|
||||
/*
|
||||
* External interrupt handler routine
|
||||
*/
|
||||
|
||||
+33
-28
@@ -35,6 +35,7 @@
|
||||
#include <linux/signal.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/regset.h>
|
||||
#include <linux/tracehook.h>
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
@@ -639,40 +640,44 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||
}
|
||||
#endif
|
||||
|
||||
asmlinkage void
|
||||
syscall_trace(struct pt_regs *regs, int entryexit)
|
||||
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
if (unlikely(current->audit_context) && entryexit)
|
||||
audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
|
||||
|
||||
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
||||
goto out;
|
||||
if (!(current->ptrace & PT_PTRACED))
|
||||
goto out;
|
||||
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
|
||||
? 0x80 : 0));
|
||||
long ret;
|
||||
|
||||
/*
|
||||
* If the debuffer has set an invalid system call number,
|
||||
* we prepare to skip the system call restart handling.
|
||||
* The sysc_tracesys code in entry.S stored the system
|
||||
* call number to gprs[2].
|
||||
*/
|
||||
if (!entryexit && regs->gprs[2] >= NR_syscalls)
|
||||
ret = regs->gprs[2];
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
|
||||
(tracehook_report_syscall_entry(regs) ||
|
||||
regs->gprs[2] >= NR_syscalls)) {
|
||||
/*
|
||||
* Tracing decided this syscall should not happen or the
|
||||
* debugger stored an invalid system call number. Skip
|
||||
* the system call and the system call restart handling.
|
||||
*/
|
||||
regs->trap = -1;
|
||||
|
||||
/*
|
||||
* this isn't the same as continuing with a signal, but it will do
|
||||
* for normal use. strace only continues with a signal if the
|
||||
* stopping signal is not SIGTRAP. -brl
|
||||
*/
|
||||
if (current->exit_code) {
|
||||
send_sig(current->exit_code, current, 1);
|
||||
current->exit_code = 0;
|
||||
ret = -1;
|
||||
}
|
||||
out:
|
||||
if (unlikely(current->audit_context) && !entryexit)
|
||||
audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
|
||||
regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
|
||||
regs->gprs[4], regs->gprs[5]);
|
||||
|
||||
if (unlikely(current->audit_context))
|
||||
audit_syscall_entry(test_thread_flag(TIF_31BIT) ?
|
||||
AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
|
||||
regs->gprs[2], regs->orig_gpr2,
|
||||
regs->gprs[3], regs->gprs[4],
|
||||
regs->gprs[5]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
|
||||
{
|
||||
if (unlikely(current->audit_context))
|
||||
audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
|
||||
regs->gprs[2]);
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE))
|
||||
tracehook_report_syscall_exit(regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/tracehook.h>
|
||||
#include <asm/ucontext.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/lowcore.h>
|
||||
@@ -507,6 +508,12 @@ void do_signal(struct pt_regs *regs)
|
||||
*/
|
||||
if (current->thread.per_info.single_step)
|
||||
set_thread_flag(TIF_SINGLE_STEP);
|
||||
|
||||
/*
|
||||
* Let tracing know that we've done the handler setup.
|
||||
*/
|
||||
tracehook_signal_handler(signr, &info, &ka, regs,
|
||||
test_thread_flag(TIF_SINGLE_STEP));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -526,3 +533,9 @@ void do_signal(struct pt_regs *regs)
|
||||
set_thread_flag(TIF_RESTART_SVC);
|
||||
}
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs)
|
||||
{
|
||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||
tracehook_notify_resume(regs);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ SYSCALL(sys_stime,sys_ni_syscall,sys32_stime_wrapper) /* 25 old stime syscall *
|
||||
SYSCALL(sys_ptrace,sys_ptrace,sys32_ptrace_wrapper)
|
||||
SYSCALL(sys_alarm,sys_alarm,sys32_alarm_wrapper)
|
||||
NI_SYSCALL /* old fstat syscall */
|
||||
SYSCALL(sys_pause,sys_pause,sys32_pause)
|
||||
SYSCALL(sys_pause,sys_pause,sys_pause)
|
||||
SYSCALL(sys_utime,sys_utime,compat_sys_utime_wrapper) /* 30 */
|
||||
NI_SYSCALL /* old stty syscall */
|
||||
NI_SYSCALL /* old gtty syscall */
|
||||
|
||||
@@ -1356,7 +1356,7 @@ static void __init stp_reset(void)
|
||||
|
||||
stp_page = alloc_bootmem_pages(PAGE_SIZE);
|
||||
rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
|
||||
if (rc == 1)
|
||||
if (rc == 0)
|
||||
set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags);
|
||||
else if (stp_online) {
|
||||
printk(KERN_WARNING "Running on non STP capable machine.\n");
|
||||
|
||||
@@ -92,3 +92,16 @@ out:
|
||||
local_irq_restore(flags);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple udelay variant. To be used on startup and reboot
|
||||
* when the interrupt handler isn't working.
|
||||
*/
|
||||
void udelay_simple(unsigned long usecs)
|
||||
{
|
||||
u64 end;
|
||||
|
||||
end = get_clock() + ((u64) usecs << 12);
|
||||
while (get_clock() < end)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
+215
-42
@@ -43,21 +43,41 @@
|
||||
#define DCSS_FINDSEG 0x0c
|
||||
#define DCSS_LOADNOLY 0x10
|
||||
#define DCSS_SEGEXT 0x18
|
||||
#define DCSS_LOADSHRX 0x20
|
||||
#define DCSS_LOADNSRX 0x24
|
||||
#define DCSS_FINDSEGX 0x2c
|
||||
#define DCSS_SEGEXTX 0x38
|
||||
#define DCSS_FINDSEGA 0x0c
|
||||
|
||||
struct qrange {
|
||||
unsigned int start; // 3byte start address, 1 byte type
|
||||
unsigned int end; // 3byte end address, 1 byte reserved
|
||||
unsigned long start; /* last byte type */
|
||||
unsigned long end; /* last byte reserved */
|
||||
};
|
||||
|
||||
struct qout64 {
|
||||
int segstart;
|
||||
int segend;
|
||||
unsigned long segstart;
|
||||
unsigned long segend;
|
||||
int segcnt;
|
||||
int segrcnt;
|
||||
struct qrange range[6];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
struct qrange_old {
|
||||
unsigned int start; /* last byte type */
|
||||
unsigned int end; /* last byte reserved */
|
||||
};
|
||||
|
||||
/* output area format for the Diag x'64' old subcode x'18' */
|
||||
struct qout64_old {
|
||||
int segstart;
|
||||
int segend;
|
||||
int segcnt;
|
||||
int segrcnt;
|
||||
struct qrange_old range[6];
|
||||
};
|
||||
#endif
|
||||
|
||||
struct qin64 {
|
||||
char qopcode;
|
||||
char rsrv1[3];
|
||||
@@ -86,6 +106,55 @@ static DEFINE_MUTEX(dcss_lock);
|
||||
static LIST_HEAD(dcss_list);
|
||||
static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC",
|
||||
"EW/EN-MIXED" };
|
||||
static int loadshr_scode, loadnsr_scode, findseg_scode;
|
||||
static int segext_scode, purgeseg_scode;
|
||||
static int scode_set;
|
||||
|
||||
/* set correct Diag x'64' subcodes. */
|
||||
static int
|
||||
dcss_set_subcodes(void)
|
||||
{
|
||||
#ifdef CONFIG_64BIT
|
||||
char *name = kmalloc(8 * sizeof(char), GFP_DMA);
|
||||
unsigned long rx, ry;
|
||||
int rc;
|
||||
|
||||
if (name == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rx = (unsigned long) name;
|
||||
ry = DCSS_FINDSEGX;
|
||||
|
||||
strcpy(name, "dummy");
|
||||
asm volatile(
|
||||
" diag %0,%1,0x64\n"
|
||||
"0: ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
" j 2f\n"
|
||||
"1: la %2,3\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b, 1b)
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
|
||||
kfree(name);
|
||||
/* Diag x'64' new subcodes are supported, set to new subcodes */
|
||||
if (rc != 3) {
|
||||
loadshr_scode = DCSS_LOADSHRX;
|
||||
loadnsr_scode = DCSS_LOADNSRX;
|
||||
purgeseg_scode = DCSS_PURGESEG;
|
||||
findseg_scode = DCSS_FINDSEGX;
|
||||
segext_scode = DCSS_SEGEXTX;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/* Diag x'64' new subcodes are not supported, set to old subcodes */
|
||||
loadshr_scode = DCSS_LOADNOLY;
|
||||
loadnsr_scode = DCSS_LOADNSR;
|
||||
purgeseg_scode = DCSS_PURGESEG;
|
||||
findseg_scode = DCSS_FINDSEG;
|
||||
segext_scode = DCSS_SEGEXT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the 8 bytes, ebcdic VM segment name from
|
||||
@@ -135,25 +204,45 @@ segment_by_name (char *name)
|
||||
* Perform a function on a dcss segment.
|
||||
*/
|
||||
static inline int
|
||||
dcss_diag (__u8 func, void *parameter,
|
||||
dcss_diag(int *func, void *parameter,
|
||||
unsigned long *ret1, unsigned long *ret2)
|
||||
{
|
||||
unsigned long rx, ry;
|
||||
int rc;
|
||||
|
||||
if (scode_set == 0) {
|
||||
rc = dcss_set_subcodes();
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
scode_set = 1;
|
||||
}
|
||||
rx = (unsigned long) parameter;
|
||||
ry = (unsigned long) func;
|
||||
asm volatile(
|
||||
ry = (unsigned long) *func;
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
" sam31\n"
|
||||
" diag %0,%1,0x64\n"
|
||||
" sam64\n"
|
||||
/* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */
|
||||
if (*func > DCSS_SEGEXT)
|
||||
asm volatile(
|
||||
" diag %0,%1,0x64\n"
|
||||
" ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
/* 31-bit Diag x'64' old subcode, switch to 31-bit addressing mode */
|
||||
else
|
||||
asm volatile(
|
||||
" sam31\n"
|
||||
" diag %0,%1,0x64\n"
|
||||
" sam64\n"
|
||||
" ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
#else
|
||||
asm volatile(
|
||||
" diag %0,%1,0x64\n"
|
||||
#endif
|
||||
" ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
#endif
|
||||
*ret1 = rx;
|
||||
*ret2 = ry;
|
||||
return rc;
|
||||
@@ -190,14 +279,45 @@ query_segment_type (struct dcss_segment *seg)
|
||||
qin->qoutlen = sizeof(struct qout64);
|
||||
memcpy (qin->qname, seg->dcss_name, 8);
|
||||
|
||||
diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc);
|
||||
diag_cc = dcss_diag(&segext_scode, qin, &dummy, &vmrc);
|
||||
|
||||
if (diag_cc < 0) {
|
||||
rc = diag_cc;
|
||||
goto out_free;
|
||||
}
|
||||
if (diag_cc > 1) {
|
||||
PRINT_WARN ("segment_type: diag returned error %ld\n", vmrc);
|
||||
rc = dcss_diag_translate_rc (vmrc);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
/* Only old format of output area of Diagnose x'64' is supported,
|
||||
copy data for the new format. */
|
||||
if (segext_scode == DCSS_SEGEXT) {
|
||||
struct qout64_old *qout_old;
|
||||
qout_old = kzalloc(sizeof(struct qout64_old), GFP_DMA);
|
||||
if (qout_old == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
memcpy(qout_old, qout, sizeof(struct qout64_old));
|
||||
qout->segstart = (unsigned long) qout_old->segstart;
|
||||
qout->segend = (unsigned long) qout_old->segend;
|
||||
qout->segcnt = qout_old->segcnt;
|
||||
qout->segrcnt = qout_old->segrcnt;
|
||||
|
||||
if (qout->segcnt > 6)
|
||||
qout->segrcnt = 6;
|
||||
for (i = 0; i < qout->segrcnt; i++) {
|
||||
qout->range[i].start =
|
||||
(unsigned long) qout_old->range[i].start;
|
||||
qout->range[i].end =
|
||||
(unsigned long) qout_old->range[i].end;
|
||||
}
|
||||
kfree(qout_old);
|
||||
}
|
||||
#endif
|
||||
if (qout->segcnt > 6) {
|
||||
rc = -ENOTSUPP;
|
||||
goto out_free;
|
||||
@@ -268,6 +388,30 @@ segment_type (char* name)
|
||||
return seg.vm_segtype;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if segment collides with other segments that are currently loaded
|
||||
* returns 1 if this is the case, 0 if no collision was found
|
||||
*/
|
||||
static int
|
||||
segment_overlaps_others (struct dcss_segment *seg)
|
||||
{
|
||||
struct list_head *l;
|
||||
struct dcss_segment *tmp;
|
||||
|
||||
BUG_ON(!mutex_is_locked(&dcss_lock));
|
||||
list_for_each(l, &dcss_list) {
|
||||
tmp = list_entry(l, struct dcss_segment, list);
|
||||
if ((tmp->start_addr >> 20) > (seg->end >> 20))
|
||||
continue;
|
||||
if ((tmp->end >> 20) < (seg->start_addr >> 20))
|
||||
continue;
|
||||
if (seg == tmp)
|
||||
continue;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* real segment loading function, called from segment_load
|
||||
*/
|
||||
@@ -276,7 +420,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
|
||||
{
|
||||
struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment),
|
||||
GFP_DMA);
|
||||
int dcss_command, rc, diag_cc;
|
||||
int rc, diag_cc;
|
||||
unsigned long start_addr, end_addr, dummy;
|
||||
|
||||
if (seg == NULL) {
|
||||
rc = -ENOMEM;
|
||||
@@ -287,6 +432,13 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
|
||||
if (rc < 0)
|
||||
goto out_free;
|
||||
|
||||
if (loadshr_scode == DCSS_LOADSHRX) {
|
||||
if (segment_overlaps_others(seg)) {
|
||||
rc = -EBUSY;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
|
||||
|
||||
if (rc)
|
||||
@@ -316,20 +468,28 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
|
||||
}
|
||||
|
||||
if (do_nonshared)
|
||||
dcss_command = DCSS_LOADNSR;
|
||||
diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name,
|
||||
&start_addr, &end_addr);
|
||||
else
|
||||
dcss_command = DCSS_LOADNOLY;
|
||||
|
||||
diag_cc = dcss_diag(dcss_command, seg->dcss_name,
|
||||
&seg->start_addr, &seg->end);
|
||||
if (diag_cc > 1) {
|
||||
PRINT_WARN ("segment_load: could not load segment %s - "
|
||||
"diag returned error (%ld)\n",name,seg->end);
|
||||
rc = dcss_diag_translate_rc (seg->end);
|
||||
dcss_diag(DCSS_PURGESEG, seg->dcss_name,
|
||||
&seg->start_addr, &seg->end);
|
||||
diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name,
|
||||
&start_addr, &end_addr);
|
||||
if (diag_cc < 0) {
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name,
|
||||
&dummy, &dummy);
|
||||
rc = diag_cc;
|
||||
goto out_resource;
|
||||
}
|
||||
if (diag_cc > 1) {
|
||||
PRINT_WARN ("segment_load: could not load segment %s - "
|
||||
"diag returned error (%ld)\n",
|
||||
name, end_addr);
|
||||
rc = dcss_diag_translate_rc(end_addr);
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name,
|
||||
&dummy, &dummy);
|
||||
goto out_resource;
|
||||
}
|
||||
seg->start_addr = start_addr;
|
||||
seg->end = end_addr;
|
||||
seg->do_nonshared = do_nonshared;
|
||||
atomic_set(&seg->ref_count, 1);
|
||||
list_add(&seg->list, &dcss_list);
|
||||
@@ -423,8 +583,8 @@ int
|
||||
segment_modify_shared (char *name, int do_nonshared)
|
||||
{
|
||||
struct dcss_segment *seg;
|
||||
unsigned long dummy;
|
||||
int dcss_command, rc, diag_cc;
|
||||
unsigned long start_addr, end_addr, dummy;
|
||||
int rc, diag_cc;
|
||||
|
||||
mutex_lock(&dcss_lock);
|
||||
seg = segment_by_name (name);
|
||||
@@ -445,38 +605,51 @@ segment_modify_shared (char *name, int do_nonshared)
|
||||
goto out_unlock;
|
||||
}
|
||||
release_resource(seg->res);
|
||||
if (do_nonshared) {
|
||||
dcss_command = DCSS_LOADNSR;
|
||||
if (do_nonshared)
|
||||
seg->res->flags &= ~IORESOURCE_READONLY;
|
||||
} else {
|
||||
dcss_command = DCSS_LOADNOLY;
|
||||
else
|
||||
if (seg->vm_segtype == SEG_TYPE_SR ||
|
||||
seg->vm_segtype == SEG_TYPE_ER)
|
||||
seg->res->flags |= IORESOURCE_READONLY;
|
||||
}
|
||||
|
||||
if (request_resource(&iomem_resource, seg->res)) {
|
||||
PRINT_WARN("segment_modify_shared: could not reload segment %s"
|
||||
" - overlapping resources\n", name);
|
||||
rc = -EBUSY;
|
||||
kfree(seg->res);
|
||||
goto out_del;
|
||||
goto out_del_mem;
|
||||
}
|
||||
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
|
||||
if (do_nonshared)
|
||||
diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name,
|
||||
&start_addr, &end_addr);
|
||||
else
|
||||
diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name,
|
||||
&start_addr, &end_addr);
|
||||
if (diag_cc < 0) {
|
||||
rc = diag_cc;
|
||||
goto out_del_res;
|
||||
}
|
||||
dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
|
||||
diag_cc = dcss_diag(dcss_command, seg->dcss_name,
|
||||
&seg->start_addr, &seg->end);
|
||||
if (diag_cc > 1) {
|
||||
PRINT_WARN ("segment_modify_shared: could not reload segment %s"
|
||||
" - diag returned error (%ld)\n",name,seg->end);
|
||||
rc = dcss_diag_translate_rc (seg->end);
|
||||
goto out_del;
|
||||
" - diag returned error (%ld)\n",
|
||||
name, end_addr);
|
||||
rc = dcss_diag_translate_rc(end_addr);
|
||||
goto out_del_res;
|
||||
}
|
||||
seg->start_addr = start_addr;
|
||||
seg->end = end_addr;
|
||||
seg->do_nonshared = do_nonshared;
|
||||
rc = 0;
|
||||
goto out_unlock;
|
||||
out_del:
|
||||
out_del_res:
|
||||
release_resource(seg->res);
|
||||
kfree(seg->res);
|
||||
out_del_mem:
|
||||
vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
|
||||
list_del(&seg->list);
|
||||
dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
|
||||
kfree(seg);
|
||||
out_unlock:
|
||||
mutex_unlock(&dcss_lock);
|
||||
@@ -510,7 +683,7 @@ segment_unload(char *name)
|
||||
kfree(seg->res);
|
||||
vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
|
||||
list_del(&seg->list);
|
||||
dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
|
||||
dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
|
||||
kfree(seg);
|
||||
out_unlock:
|
||||
mutex_unlock(&dcss_lock);
|
||||
@@ -545,7 +718,7 @@ segment_save(char *name)
|
||||
endpfn = (seg->end) >> PAGE_SHIFT;
|
||||
sprintf(cmd1, "DEFSEG %s", name);
|
||||
for (i=0; i<seg->segcnt; i++) {
|
||||
sprintf(cmd1+strlen(cmd1), " %X-%X %s",
|
||||
sprintf(cmd1+strlen(cmd1), " %lX-%lX %s",
|
||||
seg->range[i].start >> PAGE_SHIFT,
|
||||
seg->range[i].end >> PAGE_SHIFT,
|
||||
segtype_string[seg->range[i].start & 0xff]);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user