Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 293930
b: refs/heads/master
c: 4c1051e
h: refs/heads/master
v: v3
  • Loading branch information
Martin Schwidefsky committed Mar 11, 2012
1 parent e8ba274 commit ec580f8
Show file tree
Hide file tree
Showing 14 changed files with 211 additions and 211 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8b646bd759086f6090fe27acf414c0b5faa737f4
refs/heads/master: 4c1051e37a0e2a941115c6fb7ba08c318f25a0f9
9 changes: 1 addition & 8 deletions trunk/arch/s390/include/asm/cputime.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,24 +170,17 @@ struct s390_idle_data {
unsigned int sequence;
unsigned long long idle_count;
unsigned long long idle_enter;
unsigned long long idle_exit;
unsigned long long idle_time;
int nohz_delay;
};

DECLARE_PER_CPU(struct s390_idle_data, s390_idle);

void vtime_start_cpu(__u64 int_clock, __u64 enter_timer);
cputime64_t s390_get_idle_time(int cpu);

#define arch_idle_time(cpu) s390_get_idle_time(cpu)

static inline void s390_idle_check(struct pt_regs *regs, __u64 int_clock,
__u64 enter_timer)
{
if (regs->psw.mask & PSW_MASK_WAIT)
vtime_start_cpu(int_clock, enter_timer);
}

static inline int s390_nohz_delay(int cpu)
{
return __get_cpu_var(s390_idle).nohz_delay != 0;
Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/s390/include/asm/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ struct vtimer_queue {
spinlock_t lock;
__u64 timer; /* last programmed timer */
__u64 elapsed; /* elapsed time of timer expire values */
__u64 idle; /* temp var for idle */
int do_spt; /* =1: reprogram cpu timer in idle */
__u64 idle_enter; /* cpu timer on idle enter */
__u64 idle_exit; /* cpu timer on idle exit */
};

extern void init_virt_timer(struct vtimer_list *timer);
Expand Down
8 changes: 8 additions & 0 deletions trunk/arch/s390/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#include <linux/kbuild.h>
#include <linux/sched.h>
#include <asm/cputime.h>
#include <asm/timer.h>
#include <asm/vdso.h>
#include <asm/pgtable.h>
#include <asm/system.h>
Expand Down Expand Up @@ -70,6 +72,12 @@ int main(void)
DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC);
DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
BLANK();
/* idle data offsets */
DEFINE(__IDLE_ENTER, offsetof(struct s390_idle_data, idle_enter));
DEFINE(__IDLE_EXIT, offsetof(struct s390_idle_data, idle_exit));
/* vtimer queue offsets */
DEFINE(__VQ_IDLE_ENTER, offsetof(struct vtimer_queue, idle_enter));
DEFINE(__VQ_IDLE_EXIT, offsetof(struct vtimer_queue, idle_exit));
/* lowcore offsets */
DEFINE(__LC_EXT_PARAMS, offsetof(struct _lowcore, ext_params));
DEFINE(__LC_EXT_CPU_ADDR, offsetof(struct _lowcore, ext_cpu_addr));
Expand Down
76 changes: 70 additions & 6 deletions trunk/arch/s390/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ STACK_SIZE = 1 << STACK_SHIFT

.macro ADD64 high,low,timer
al \high,\timer
al \low,\timer+4
al \low,4+\timer
brc 12,.+8
ahi \high,1
.endm

.macro SUB64 high,low,timer
sl \high,\timer
sl \low,\timer+4
sl \low,4+\timer
brc 3,.+8
ahi \high,-1
.endm
Expand Down Expand Up @@ -471,7 +471,6 @@ io_tif:
jnz io_work # there is work to do (signals etc.)
io_restore:
mvc __LC_RETURN_PSW(8),__PT_PSW(%r11)
ni __LC_RETURN_PSW+1,0xfd # clean wait state bit
stpt __LC_EXIT_TIMER
lm %r0,%r15,__PT_R0(%r11)
lpsw __LC_RETURN_PSW
Expand Down Expand Up @@ -612,6 +611,26 @@ ext_skip:
basr %r14,%r1 # call do_extint
j io_return

/*
* Load idle PSW. The second "half" of this function is in cleanup_idle.
*/
ENTRY(psw_idle)
st %r4,__SF_EMPTY(%r15)
basr %r1,0
la %r1,psw_idle_lpsw+4-.(%r1)
st %r1,__SF_EMPTY+4(%r15)
oi __SF_EMPTY+4(%r15),0x80
la %r1,.Lvtimer_max-psw_idle_lpsw-4(%r1)
stck __IDLE_ENTER(%r2)
ltr %r5,%r5
stpt __VQ_IDLE_ENTER(%r3)
jz psw_idle_lpsw
spt 0(%r1)
psw_idle_lpsw:
lpsw __SF_EMPTY(%r15)
br %r14
psw_idle_end:

__critical_end:

/*
Expand Down Expand Up @@ -673,7 +692,6 @@ mcck_skip:
TRACE_IRQS_ON
mcck_return:
mvc __LC_RETURN_MCCK_PSW(8),__PT_PSW(%r11) # move return PSW
ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
jno 0f
lm %r0,%r15,__PT_R0(%r11)
Expand Down Expand Up @@ -748,6 +766,8 @@ cleanup_table:
.long io_tif + 0x80000000
.long io_restore + 0x80000000
.long io_done + 0x80000000
.long psw_idle + 0x80000000
.long psw_idle_end + 0x80000000

cleanup_critical:
cl %r9,BASED(cleanup_table) # system_call
Expand All @@ -766,6 +786,10 @@ cleanup_critical:
jl cleanup_io_tif
cl %r9,BASED(cleanup_table+28) # io_done
jl cleanup_io_restore
cl %r9,BASED(cleanup_table+32) # psw_idle
jl 0f
cl %r9,BASED(cleanup_table+36) # psw_idle_end
jl cleanup_idle
0: br %r14

cleanup_system_call:
Expand Down Expand Up @@ -849,19 +873,59 @@ cleanup_io_restore:
jhe 0f
l %r9,12(%r11) # get saved r11 pointer to pt_regs
mvc __LC_RETURN_PSW(8),__PT_PSW(%r9)
ni __LC_RETURN_PSW+1,0xfd # clear wait state bit
mvc 0(32,%r11),__PT_R8(%r9)
lm %r0,%r7,__PT_R0(%r9)
0: lm %r8,%r9,__LC_RETURN_PSW
br %r14
cleanup_io_restore_insn:
.long io_done - 4 + 0x80000000

cleanup_idle:
# copy interrupt clock & cpu timer
mvc __IDLE_EXIT(8,%r2),__LC_INT_CLOCK
mvc __VQ_IDLE_EXIT(8,%r3),__LC_ASYNC_ENTER_TIMER
chi %r11,__LC_SAVE_AREA_ASYNC
je 0f
mvc __IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK
mvc __VQ_IDLE_EXIT(8,%r3),__LC_MCCK_ENTER_TIMER
0: # check if stck has been executed
cl %r9,BASED(cleanup_idle_insn)
jhe 1f
mvc __IDLE_ENTER(8,%r2),__IDLE_EXIT(%r2)
mvc __VQ_IDLE_ENTER(8,%r3),__VQ_IDLE_EXIT(%r3)
j 2f
1: # check if the cpu timer has been reprogrammed
ltr %r5,%r5
jz 2f
spt __VQ_IDLE_ENTER(%r3)
2: # account system time going idle
lm %r9,%r10,__LC_STEAL_TIMER
ADD64 %r9,%r10,__IDLE_ENTER(%r2)
SUB64 %r9,%r10,__LC_LAST_UPDATE_CLOCK
stm %r9,%r10,__LC_STEAL_TIMER
mvc __LC_LAST_UPDATE_CLOCK(8),__IDLE_EXIT(%r2)
lm %r9,%r10,__LC_SYSTEM_TIMER
ADD64 %r9,%r10,__LC_LAST_UPDATE_TIMER
SUB64 %r9,%r10,__VQ_IDLE_ENTER(%r3)
stm %r9,%r10,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__VQ_IDLE_EXIT(%r3)
# prepare return psw
n %r8,BASED(cleanup_idle_wait) # clear wait state bit
l %r9,24(%r11) # return from psw_idle
br %r14
cleanup_idle_insn:
.long psw_idle_lpsw + 0x80000000
cleanup_idle_wait:
.long 0xfffdffff

/*
* Integer constants
*/
.align 4
.Lnr_syscalls: .long NR_syscalls
.Lnr_syscalls:
.long NR_syscalls
.Lvtimer_max:
.quad 0x7fffffffffffffff

/*
* Symbol constants
Expand Down
5 changes: 4 additions & 1 deletion trunk/arch/s390/kernel/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#include <linux/types.h>
#include <linux/signal.h>
#include <asm/ptrace.h>

#include <asm/cputime.h>
#include <asm/timer.h>

extern void (*pgm_check_table[128])(struct pt_regs *);
extern void *restart_stack;
Expand All @@ -16,6 +17,8 @@ void io_int_handler(void);
void mcck_int_handler(void);
void restart_int_handler(void);
void restart_call_handler(void);
void psw_idle(struct s390_idle_data *, struct vtimer_queue *,
unsigned long, int);

asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
Expand Down
65 changes: 62 additions & 3 deletions trunk/arch/s390/kernel/entry64.S
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,6 @@ io_restore:
lg %r14,__LC_VDSO_PER_CPU
lmg %r0,%r10,__PT_R0(%r11)
mvc __LC_RETURN_PSW(16),__PT_PSW(%r11)
ni __LC_RETURN_PSW+1,0xfd # clear wait state bit
stpt __LC_EXIT_TIMER
mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
lmg %r11,%r15,__PT_R11(%r11)
Expand Down Expand Up @@ -631,6 +630,24 @@ ext_skip:
brasl %r14,do_extint
j io_return

/*
* Load idle PSW. The second "half" of this function is in cleanup_idle.
*/
ENTRY(psw_idle)
stg %r4,__SF_EMPTY(%r15)
larl %r1,psw_idle_lpsw+4
stg %r1,__SF_EMPTY+8(%r15)
larl %r1,.Lvtimer_max
stck __IDLE_ENTER(%r2)
ltr %r5,%r5
stpt __VQ_IDLE_ENTER(%r3)
jz psw_idle_lpsw
spt 0(%r1)
psw_idle_lpsw:
lpswe __SF_EMPTY(%r15)
br %r14
psw_idle_end:

__critical_end:

/*
Expand Down Expand Up @@ -696,7 +713,6 @@ mcck_return:
lg %r14,__LC_VDSO_PER_CPU
lmg %r0,%r10,__PT_R0(%r11)
mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW
ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
jno 0f
stpt __LC_EXIT_TIMER
Expand Down Expand Up @@ -770,6 +786,8 @@ cleanup_table:
.quad io_tif
.quad io_restore
.quad io_done
.quad psw_idle
.quad psw_idle_end

cleanup_critical:
clg %r9,BASED(cleanup_table) # system_call
Expand All @@ -788,6 +806,10 @@ cleanup_critical:
jl cleanup_io_tif
clg %r9,BASED(cleanup_table+56) # io_done
jl cleanup_io_restore
clg %r9,BASED(cleanup_table+64) # psw_idle
jl 0f
clg %r9,BASED(cleanup_table+72) # psw_idle_end
jl cleanup_idle
0: br %r14


Expand Down Expand Up @@ -877,14 +899,49 @@ cleanup_io_restore:
je 0f
lg %r9,24(%r11) # get saved r11 pointer to pt_regs
mvc __LC_RETURN_PSW(16),__PT_PSW(%r9)
ni __LC_RETURN_PSW+1,0xfd # clear wait state bit
mvc 0(64,%r11),__PT_R8(%r9)
lmg %r0,%r7,__PT_R0(%r9)
0: lmg %r8,%r9,__LC_RETURN_PSW
br %r14
cleanup_io_restore_insn:
.quad io_done - 4

cleanup_idle:
# copy interrupt clock & cpu timer
mvc __IDLE_EXIT(8,%r2),__LC_INT_CLOCK
mvc __VQ_IDLE_EXIT(8,%r3),__LC_ASYNC_ENTER_TIMER
cghi %r11,__LC_SAVE_AREA_ASYNC
je 0f
mvc __IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK
mvc __VQ_IDLE_EXIT(8,%r3),__LC_MCCK_ENTER_TIMER
0: # check if stck & stpt have been executed
clg %r9,BASED(cleanup_idle_insn)
jhe 1f
mvc __IDLE_ENTER(8,%r2),__IDLE_EXIT(%r2)
mvc __VQ_IDLE_ENTER(8,%r3),__VQ_IDLE_EXIT(%r3)
j 2f
1: # check if the cpu timer has been reprogrammed
ltr %r5,%r5
jz 2f
spt __VQ_IDLE_ENTER(%r3)
2: # account system time going idle
lg %r9,__LC_STEAL_TIMER
alg %r9,__IDLE_ENTER(%r2)
slg %r9,__LC_LAST_UPDATE_CLOCK
stg %r9,__LC_STEAL_TIMER
mvc __LC_LAST_UPDATE_CLOCK(8),__IDLE_EXIT(%r2)
lg %r9,__LC_SYSTEM_TIMER
alg %r9,__LC_LAST_UPDATE_TIMER
slg %r9,__VQ_IDLE_ENTER(%r3)
stg %r9,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__VQ_IDLE_EXIT(%r3)
# prepare return psw
nihh %r8,0xfffd # clear wait state bit
lg %r9,48(%r11) # return from psw_idle
br %r14
cleanup_idle_insn:
.quad psw_idle_lpsw

/*
* Integer constants
*/
Expand All @@ -893,6 +950,8 @@ cleanup_io_restore_insn:
.quad __critical_start
.Lcritical_length:
.quad __critical_end - __critical_start
.Lvtimer_max:
.quad 0x7fffffffffffffff


#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
Expand Down
2 changes: 0 additions & 2 deletions trunk/arch/s390/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,6 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code,

code = (unsigned short) ext_int_code;
old_regs = set_irq_regs(regs);
s390_idle_check(regs, S390_lowcore.int_clock,
S390_lowcore.async_enter_timer);
irq_enter();
if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
/* Serve timer interrupts first. */
Expand Down
2 changes: 0 additions & 2 deletions trunk/arch/s390/kernel/nmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,6 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
int umode;

nmi_enter();
s390_idle_check(regs, S390_lowcore.mcck_clock,
S390_lowcore.mcck_enter_timer);
kstat_cpu(smp_processor_id()).irqs[NMI_NMI]++;
mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
mcck = &__get_cpu_var(cpu_mcck);
Expand Down
7 changes: 1 addition & 6 deletions trunk/arch/s390/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,8 @@ static void default_idle(void)
local_irq_enable();
return;
}
trace_hardirqs_on();
/* Don't trace preempt off for idle. */
stop_critical_timings();
/* Stop virtual timer and halt the cpu. */
/* Halt the cpu and keep track of cpu time accounting. */
vtime_stop_cpu();
/* Reenable preemption tracer. */
start_critical_timings();
}

void cpu_idle(void)
Expand Down
Loading

0 comments on commit ec580f8

Please sign in to comment.