Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 125493
b: refs/heads/master
c: 6f43092
h: refs/heads/master
i:
  125491: 50e8331
v: v3
  • Loading branch information
Martin Schwidefsky committed Dec 31, 2008
1 parent f571661 commit 5ee3a31
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 38 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: aa5e97ce4bbc9d5daeec16b1d15bb3f6b7b4f4d4
refs/heads/master: 6f43092441bda528dd38f2dc6c1e2522c5079fb7
3 changes: 1 addition & 2 deletions trunk/arch/s390/include/asm/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

struct s390_idle_data {
spinlock_t lock;
unsigned int in_idle;
unsigned long long idle_count;
unsigned long long idle_enter;
unsigned long long idle_time;
Expand All @@ -26,7 +25,7 @@ void s390_idle_leave(void);

static inline void s390_idle_check(void)
{
if ((&__get_cpu_var(s390_idle))->in_idle)
if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL)
s390_idle_leave();
}

Expand Down
67 changes: 45 additions & 22 deletions trunk/arch/s390/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <linux/utsname.h>
#include <linux/tick.h>
#include <linux/elfcore.h>
#include <linux/kernel_stat.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
Expand Down Expand Up @@ -79,30 +80,19 @@ DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = {
.lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
};

static int s390_idle_enter(void)
void s390_idle_leave(void)
{
struct s390_idle_data *idle;
unsigned long long idle_time;

idle = &__get_cpu_var(s390_idle);
idle_time = S390_lowcore.int_clock - idle->idle_enter;
spin_lock(&idle->lock);
idle->idle_time += idle_time;
idle->idle_enter = 0ULL;
idle->idle_count++;
idle->in_idle = 1;
idle->idle_enter = get_clock();
spin_unlock(&idle->lock);
vtime_stop_cpu_timer();
return NOTIFY_OK;
}

void s390_idle_leave(void)
{
struct s390_idle_data *idle;

vtime_start_cpu_timer();
idle = &__get_cpu_var(s390_idle);
spin_lock(&idle->lock);
idle->idle_time += get_clock() - idle->idle_enter;
idle->in_idle = 0;
spin_unlock(&idle->lock);
}

extern void s390_handle_mcck(void);
Expand All @@ -111,16 +101,16 @@ extern void s390_handle_mcck(void);
*/
static void default_idle(void)
{
struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
unsigned long addr;
psw_t psw;

/* CPU is going idle. */
local_irq_disable();
if (need_resched()) {
local_irq_enable();
return;
}
if (s390_idle_enter() == NOTIFY_BAD) {
local_irq_enable();
return;
}
#ifdef CONFIG_HOTPLUG_CPU
if (cpu_is_offline(smp_processor_id())) {
preempt_enable_no_resched();
Expand All @@ -138,9 +128,42 @@ static void default_idle(void)
trace_hardirqs_on();
/* Don't trace preempt off for idle. */
stop_critical_timings();
vtime_stop_cpu_timer();

/*
* The inline assembly is equivalent to
* idle->idle_enter = get_clock();
* __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
* PSW_MASK_IO | PSW_MASK_EXT);
* The difference is that the inline assembly makes sure that
* the stck instruction is right before the lpsw instruction.
* This is done to increase the precision.
*/

/* Wait for external, I/O or machine check interrupt. */
__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
PSW_MASK_IO | PSW_MASK_EXT);
psw.mask = psw_kernel_bits|PSW_MASK_WAIT|PSW_MASK_IO|PSW_MASK_EXT;
#ifndef __s390x__
asm volatile(
" basr %0,0\n"
"0: ahi %0,1f-0b\n"
" st %0,4(%2)\n"
" stck 0(%3)\n"
" lpsw 0(%2)\n"
"1:"
: "=&d" (addr), "=m" (idle->idle_enter)
: "a" (&psw), "a" (&idle->idle_enter), "m" (psw)
: "memory", "cc");
#else /* __s390x__ */
asm volatile(
" larl %0,1f\n"
" stg %0,8(%2)\n"
" stck 0(%3)\n"
" lpswe 0(%2)\n"
"1:"
: "=&d" (addr), "=m" (idle->idle_enter)
: "a" (&psw), "a" (&idle->idle_enter), "m" (psw)
: "memory", "cc");
#endif /* __s390x__ */
start_critical_timings();
}

Expand Down
25 changes: 13 additions & 12 deletions trunk/arch/s390/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -851,9 +851,11 @@ static ssize_t show_idle_count(struct sys_device *dev,
unsigned long long idle_count;

idle = &per_cpu(s390_idle, dev->id);
spin_lock_irq(&idle->lock);
spin_lock(&idle->lock);
idle_count = idle->idle_count;
spin_unlock_irq(&idle->lock);
if (idle->idle_enter)
idle_count++;
spin_unlock(&idle->lock);
return sprintf(buf, "%llu\n", idle_count);
}
static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
Expand All @@ -862,18 +864,17 @@ static ssize_t show_idle_time(struct sys_device *dev,
struct sysdev_attribute *attr, char *buf)
{
struct s390_idle_data *idle;
unsigned long long new_time;
unsigned long long now, idle_time, idle_enter;

idle = &per_cpu(s390_idle, dev->id);
spin_lock_irq(&idle->lock);
if (idle->in_idle) {
new_time = get_clock();
idle->idle_time += new_time - idle->idle_enter;
idle->idle_enter = new_time;
}
new_time = idle->idle_time;
spin_unlock_irq(&idle->lock);
return sprintf(buf, "%llu\n", new_time >> 12);
spin_lock(&idle->lock);
now = get_clock();
idle_time = idle->idle_time;
idle_enter = idle->idle_enter;
if (idle_enter != 0ULL && idle_enter < now)
idle_time += now - idle_enter;
spin_unlock(&idle->lock);
return sprintf(buf, "%llu\n", idle_time >> 12);
}
static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL);

Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/s390/kernel/vtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ EXPORT_SYMBOL_GPL(account_system_vtime);

static inline void set_vtimer(__u64 expires)
{
struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
__u64 timer;

asm volatile (" STPT %0\n" /* Store current cpu timer value */
Expand All @@ -121,7 +122,7 @@ static inline void set_vtimer(__u64 expires)
S390_lowcore.last_update_timer = expires;

/* store expire time for this CPU timer */
__get_cpu_var(virt_cpu_timer).to_expire = expires;
vq->to_expire = expires;
}

void vtime_start_cpu_timer(void)
Expand Down

0 comments on commit 5ee3a31

Please sign in to comment.