Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
Browse files Browse the repository at this point in the history
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (21 commits)
  [S390] dasd: fix race condition in resume code
  [S390] Add EX_TABLE for addressing exception in usercopy functions.
  [S390] 64-bit register support for 31-bit processes
  [S390] hibernate: Use correct place for CPU address in lowcore
  [S390] pm: ignore time spend in suspended state
  [S390] zcrypt: Improve some comments
  [S390] zcrypt: Fix sparse warning.
  [S390] perf_counter: fix vdso detection
  [S390] ftrace: drop nmi protection
  [S390] compat: fix truncate system call wrapper
  [S390] Provide arch specific mdelay implementation.
  [S390] Fix enabled udelay for short delays.
  [S390] cio: allow setting boxed devices offline
  [S390] cio: make not operational handling consistent
  [S390] cio: make disconnected handling consistent
  [S390] Fix memory leak in /proc/cio_ignore
  [S390] cio: channel path memory leak
  [S390] module: fix memory leak in s390 module loader
  [S390] Enable kmemleak on s390.
  [S390] 3270 console build fix
  ...
  • Loading branch information
torvalds committed Oct 11, 2009
2 parents ef1f7a7 + 6fca97a commit f144c78
Show file tree
Hide file tree
Showing 28 changed files with 282 additions and 82 deletions.
7 changes: 4 additions & 3 deletions arch/s390/include/asm/delay.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
#ifndef _S390_DELAY_H
#define _S390_DELAY_H

extern void __udelay(unsigned long usecs);
extern void udelay_simple(unsigned long usecs);
extern void __udelay(unsigned long long usecs);
extern void udelay_simple(unsigned long long usecs);
extern void __delay(unsigned long loops);

#define udelay(n) __udelay(n)
#define udelay(n) __udelay((unsigned long long) (n))
#define mdelay(n) __udelay((unsigned long long) (n) * 1000)

#endif /* defined(_S390_DELAY_H) */
12 changes: 12 additions & 0 deletions arch/s390/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@
/* Keep this the last entry. */
#define R_390_NUM 61

/* Bits present in AT_HWCAP. */
#define HWCAP_S390_ESAN3 1
#define HWCAP_S390_ZARCH 2
#define HWCAP_S390_STFLE 4
#define HWCAP_S390_MSA 8
#define HWCAP_S390_LDISP 16
#define HWCAP_S390_EIMM 32
#define HWCAP_S390_DFP 64
#define HWCAP_S390_HPAGE 128
#define HWCAP_S390_ETF3EH 256
#define HWCAP_S390_HIGH_GPRS 512

/*
* These are used to set parameters in the core dumps.
*/
Expand Down
4 changes: 4 additions & 0 deletions arch/s390/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ typedef struct
__u32 orig_gpr2;
} s390_compat_regs;

typedef struct
{
__u32 gprs_high[NUM_GPRS];
} s390_compat_regs_high;

#ifdef __KERNEL__

Expand Down
15 changes: 15 additions & 0 deletions arch/s390/include/asm/ucontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@
#ifndef _ASM_S390_UCONTEXT_H
#define _ASM_S390_UCONTEXT_H

#define UC_EXTENDED 0x00000001

#ifndef __s390x__

struct ucontext_extended {
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
_sigregs uc_mcontext;
unsigned long uc_sigmask[2];
unsigned long uc_gprs_high[16];
};

#endif

struct ucontext {
unsigned long uc_flags;
struct ucontext *uc_link;
Expand Down
35 changes: 34 additions & 1 deletion arch/s390/kernel/compat_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ typedef struct
struct sigcontext32 sc;
_sigregs32 sregs;
int signo;
__u32 gprs_high[NUM_GPRS];
__u8 retcode[S390_SYSCALL_SIZE];
} sigframe32;

Expand All @@ -48,6 +49,7 @@ typedef struct
__u8 retcode[S390_SYSCALL_SIZE];
compat_siginfo_t info;
struct ucontext32 uc;
__u32 gprs_high[NUM_GPRS];
} rt_sigframe32;

int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
Expand Down Expand Up @@ -344,6 +346,30 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
return 0;
}

static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
{
__u32 gprs_high[NUM_GPRS];
int i;

for (i = 0; i < NUM_GPRS; i++)
gprs_high[i] = regs->gprs[i] >> 32;

return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high));
}

static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
{
__u32 gprs_high[NUM_GPRS];
int err, i;

err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high));
if (err)
return err;
for (i = 0; i < NUM_GPRS; i++)
*(__u32 *)&regs->gprs[i] = gprs_high[i];
return 0;
}

asmlinkage long sys32_sigreturn(void)
{
struct pt_regs *regs = task_pt_regs(current);
Expand All @@ -363,6 +389,8 @@ asmlinkage long sys32_sigreturn(void)

if (restore_sigregs32(regs, &frame->sregs))
goto badframe;
if (restore_sigregs_gprs_high(regs, frame->gprs_high))
goto badframe;

return regs->gprs[2];

Expand Down Expand Up @@ -394,6 +422,8 @@ asmlinkage long sys32_rt_sigreturn(void)

if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
goto badframe;
if (restore_sigregs_gprs_high(regs, frame->gprs_high))
goto badframe;

err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
st.ss_sp = compat_ptr(ss_sp);
Expand Down Expand Up @@ -474,6 +504,8 @@ static int setup_frame32(int sig, struct k_sigaction *ka,

if (save_sigregs32(regs, &frame->sregs))
goto give_sigsegv;
if (save_sigregs_gprs_high(regs, frame->gprs_high))
goto give_sigsegv;
if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
goto give_sigsegv;

Expand Down Expand Up @@ -529,13 +561,14 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;

/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
err |= __put_user(sas_ss_flags(regs->gprs[15]),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
err |= save_sigregs_gprs_high(regs, frame->gprs_high);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
goto give_sigsegv;
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/compat_wrapper.S
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ sys32_munmap_wrapper:
.globl sys32_truncate_wrapper
sys32_truncate_wrapper:
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # unsigned long
lgfr %r3,%r3 # long
jg sys_truncate # branch to system call

.globl sys32_ftruncate_wrapper
Expand Down
3 changes: 0 additions & 3 deletions arch/s390/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,6 @@ unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent)
{
struct ftrace_graph_ent trace;

/* Nmi's are currently unsupported. */
if (unlikely(in_nmi()))
goto out;
if (unlikely(atomic_read(&current->tracing_graph_pause)))
goto out;
if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
Expand Down
3 changes: 3 additions & 0 deletions arch/s390/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ void *module_alloc(unsigned long size)
/* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region)
{
vfree(mod->arch.syminfo);
mod->arch.syminfo = NULL;
vfree(module_region);
}

Expand Down Expand Up @@ -402,6 +404,7 @@ int module_finalize(const Elf_Ehdr *hdr,
struct module *me)
{
vfree(me->arch.syminfo);
me->arch.syminfo = NULL;
return module_bug_finalize(hdr, sechdrs, me);
}

Expand Down
70 changes: 70 additions & 0 deletions arch/s390/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
enum s390_regset {
REGSET_GENERAL,
REGSET_FP,
REGSET_GENERAL_EXTENDED,
};

static void
Expand Down Expand Up @@ -879,6 +880,67 @@ static int s390_compat_regs_set(struct task_struct *target,
return rc;
}

static int s390_compat_regs_high_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
{
compat_ulong_t *gprs_high;

gprs_high = (compat_ulong_t *)
&task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
if (kbuf) {
compat_ulong_t *k = kbuf;
while (count > 0) {
*k++ = *gprs_high;
gprs_high += 2;
count -= sizeof(*k);
}
} else {
compat_ulong_t __user *u = ubuf;
while (count > 0) {
if (__put_user(*gprs_high, u++))
return -EFAULT;
gprs_high += 2;
count -= sizeof(*u);
}
}
return 0;
}

static int s390_compat_regs_high_set(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
compat_ulong_t *gprs_high;
int rc = 0;

gprs_high = (compat_ulong_t *)
&task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
if (kbuf) {
const compat_ulong_t *k = kbuf;
while (count > 0) {
*gprs_high = *k++;
*gprs_high += 2;
count -= sizeof(*k);
}
} else {
const compat_ulong_t __user *u = ubuf;
while (count > 0 && !rc) {
unsigned long word;
rc = __get_user(word, u++);
if (rc)
break;
*gprs_high = word;
*gprs_high += 2;
count -= sizeof(*u);
}
}

return rc;
}

static const struct user_regset s390_compat_regsets[] = {
[REGSET_GENERAL] = {
.core_note_type = NT_PRSTATUS,
Expand All @@ -896,6 +958,14 @@ static const struct user_regset s390_compat_regsets[] = {
.get = s390_fpregs_get,
.set = s390_fpregs_set,
},
[REGSET_GENERAL_EXTENDED] = {
.core_note_type = NT_PRXSTATUS,
.n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
.size = sizeof(compat_long_t),
.align = sizeof(compat_long_t),
.get = s390_compat_regs_high_get,
.set = s390_compat_regs_high_set,
},
};

static const struct user_regset_view user_s390_compat_view = {
Expand Down
15 changes: 12 additions & 3 deletions arch/s390/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ static void __init setup_hwcaps(void)

if ((facility_list & (1UL << (31 - 22)))
&& (facility_list & (1UL << (31 - 30))))
elf_hwcap |= 1UL << 8;
elf_hwcap |= HWCAP_S390_ETF3EH;

/*
* Check for additional facilities with store-facility-list-extended.
Expand All @@ -748,11 +748,20 @@ static void __init setup_hwcaps(void)
__stfle(&facility_list_extended, 1) > 0) {
if ((facility_list_extended & (1ULL << (63 - 42)))
&& (facility_list_extended & (1ULL << (63 - 44))))
elf_hwcap |= 1UL << 6;
elf_hwcap |= HWCAP_S390_DFP;
}

/*
* Huge page support HWCAP_S390_HPAGE is bit 7.
*/
if (MACHINE_HAS_HPAGE)
elf_hwcap |= 1UL << 7;
elf_hwcap |= HWCAP_S390_HPAGE;

/*
* 64-bit register support for 31-bit processes
* HWCAP_S390_HIGH_GPRS is bit 9.
*/
elf_hwcap |= HWCAP_S390_HIGH_GPRS;

switch (S390_lowcore.cpu_id.machine) {
case 0x9672:
Expand Down
26 changes: 19 additions & 7 deletions arch/s390/kernel/swsusp_asm64.S
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ swsusp_arch_suspend:
lghi %r1,0x1000

/* Save CPU address */
stap __LC_CPU_ADDRESS(%r1)
stap __LC_CPU_ADDRESS(%r0)

/* Store registers */
mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */
Expand All @@ -69,8 +69,21 @@ swsusp_arch_suspend:
stmg %r0,%r15,0x280(%r1) /* store general registers */

stpt 0x328(%r1) /* store timer */
stck __SF_EMPTY(%r15) /* store clock */
stckc 0x330(%r1) /* store clock comparator */

/* Update cputime accounting before going to sleep */
lg %r0,__LC_LAST_UPDATE_TIMER
slg %r0,0x328(%r1)
alg %r0,__LC_SYSTEM_TIMER
stg %r0,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),0x328(%r1)
lg %r0,__LC_LAST_UPDATE_CLOCK
slg %r0,__SF_EMPTY(%r15)
alg %r0,__LC_STEAL_TIMER
stg %r0,__LC_STEAL_TIMER
mvc __LC_LAST_UPDATE_CLOCK(8),__SF_EMPTY(%r15)

/* Activate DAT */
stosm __SF_EMPTY(%r15),0x04

Expand Down Expand Up @@ -159,8 +172,7 @@ pgm_check_entry:
larl %r1,.Lresume_cpu /* Resume CPU address: r2 */
stap 0(%r1)
llgh %r2,0(%r1)
lghi %r3,0x1000
llgh %r1,__LC_CPU_ADDRESS(%r3) /* Suspend CPU address: r1 */
llgh %r1,__LC_CPU_ADDRESS(%r0) /* Suspend CPU address: r1 */
cgr %r1,%r2
je restore_registers /* r1 = r2 -> nothing to do */
larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
Expand Down Expand Up @@ -200,8 +212,11 @@ restart_suspend:

restore_registers:
/* Restore registers */
lghi %r13,0x1000 /* %r1 = pointer to save arae */
lghi %r13,0x1000 /* %r1 = pointer to save area */

/* Ignore time spent in suspended state. */
llgf %r1,0x318(%r13)
stck __LC_LAST_UPDATE_CLOCK(%r1)
spt 0x328(%r13) /* reprogram timer */
//sckc 0x330(%r13) /* set clock comparator */

Expand Down Expand Up @@ -229,9 +244,6 @@ restore_registers:
/* Load old stack */
lg %r15,0x2f8(%r13)

/* Pointer to save area */
lghi %r13,0x1000

/* Restore prefix register */
spx 0x318(%r13)

Expand Down
Loading

0 comments on commit f144c78

Please sign in to comment.