mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 03:27:30 -04:00
s390/irq/idle: Use stcke instead of stckf for time stamps
The upcoming cpu idle time accounting rework involves comparing and subtracting cross cpu time stamps. Time stamps created with the stckf instruction monotonic with respect to the local cpu. For cross cpu monotonic time stamps the slightly slower stcke instruction has to be used [1]. Convert the idle time accounting relevant usages of stckf to stcke. [1] Principles of Operation - Setting and Inspecting the Clock Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Acked-by: Frederic Weisbecker <frederic@kernel.org> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
This commit is contained in:
committed by
Alexander Gordeev
parent
fe47b8b1c0
commit
4fe307f0f5
@@ -11,14 +11,15 @@
|
||||
#include <linux/percpu-defs.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <asm/tod_types.h>
|
||||
|
||||
struct s390_idle_data {
|
||||
bool idle_dyntick;
|
||||
unsigned long idle_count;
|
||||
unsigned long idle_time;
|
||||
unsigned long clock_idle_enter;
|
||||
unsigned long timer_idle_enter;
|
||||
unsigned long mt_cycles_enter[8];
|
||||
union tod_clock clock_idle_enter;
|
||||
};
|
||||
|
||||
DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define _ASM_S390_LOWCORE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/tod_types.h>
|
||||
#include <asm/machine.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/ctlreg.h>
|
||||
@@ -125,8 +126,7 @@ struct lowcore {
|
||||
__u64 avg_steal_timer; /* 0x0300 */
|
||||
__u64 last_update_timer; /* 0x0308 */
|
||||
__u64 last_update_clock; /* 0x0310 */
|
||||
__u64 int_clock; /* 0x0318 */
|
||||
__u8 pad_0x0320[0x0328-0x0320]; /* 0x0320 */
|
||||
union tod_clock int_clock; /* 0x0318 */
|
||||
__u64 clock_comparator; /* 0x0328 */
|
||||
__u8 pad_0x0330[0x0340-0x0330]; /* 0x0330 */
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ static inline void update_timer_idle(void)
|
||||
* The accounted CPU times will be subtracted again from steal_timer
|
||||
* when accumulated steal time is calculated in do_account_vtime().
|
||||
*/
|
||||
lc->steal_timer += idle->clock_idle_enter - lc->last_update_clock;
|
||||
lc->last_update_clock = lc->int_clock;
|
||||
lc->steal_timer += idle->clock_idle_enter.tod - lc->last_update_clock;
|
||||
lc->last_update_clock = lc->int_clock.tod;
|
||||
lc->system_timer += lc->last_update_timer - idle->timer_idle_enter;
|
||||
lc->last_update_timer = lc->sys_enter_timer;
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ SYM_CODE_END(pgm_check_handler)
|
||||
SYM_CODE_START(\name)
|
||||
STMG_LC %r8,%r15,__LC_SAVE_AREA
|
||||
GET_LC %r13
|
||||
stckf __LC_INT_CLOCK(%r13)
|
||||
stcke __LC_INT_CLOCK(%r13)
|
||||
stpt __LC_SYS_ENTER_TIMER(%r13)
|
||||
STBEAR __LC_LAST_BREAK(%r13)
|
||||
BPOFF
|
||||
|
||||
@@ -26,7 +26,7 @@ void account_idle_time_irq(void)
|
||||
struct s390_idle_data *idle = this_cpu_ptr(&s390_idle);
|
||||
unsigned long idle_time;
|
||||
|
||||
idle_time = get_lowcore()->int_clock - idle->clock_idle_enter;
|
||||
idle_time = get_lowcore()->int_clock.tod - idle->clock_idle_enter.tod;
|
||||
|
||||
/* Account time spent with enabled wait psw loaded as idle time. */
|
||||
__atomic64_add(idle_time, &idle->idle_time);
|
||||
@@ -49,7 +49,7 @@ void noinstr arch_cpu_idle(void)
|
||||
set_cpu_flag(CIF_ENABLED_WAIT);
|
||||
if (smp_cpu_mtid)
|
||||
stcctm(MT_DIAG, smp_cpu_mtid, (u64 *)&idle->mt_cycles_enter);
|
||||
idle->clock_idle_enter = get_tod_clock_fast();
|
||||
store_tod_clock_ext(&idle->clock_idle_enter);
|
||||
idle->timer_idle_enter = get_cpu_timer();
|
||||
bpon();
|
||||
__load_psw_mask(psw_mask);
|
||||
|
||||
@@ -103,9 +103,10 @@ static const struct irq_class irqclass_sub_desc[] = {
|
||||
|
||||
static void do_IRQ(struct pt_regs *regs, int irq)
|
||||
{
|
||||
if (tod_after_eq(get_lowcore()->int_clock,
|
||||
get_lowcore()->clock_comparator))
|
||||
/* Serve timer interrupts first. */
|
||||
struct lowcore *lc = get_lowcore();
|
||||
|
||||
/* Serve timer interrupts first */
|
||||
if (tod_after_eq(lc->int_clock.tod, lc->clock_comparator))
|
||||
clock_comparator_work();
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
|
||||
@@ -695,7 +695,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
|
||||
return;
|
||||
|
||||
qdio_deliver_irq(irq_ptr);
|
||||
irq_ptr->last_data_irq_time = get_lowcore()->int_clock;
|
||||
irq_ptr->last_data_irq_time = get_lowcore()->int_clock.tod;
|
||||
}
|
||||
|
||||
static void qdio_handle_activate_check(struct qdio_irq *irq_ptr,
|
||||
|
||||
@@ -99,7 +99,7 @@ static inline u32 clear_shared_ind(void)
|
||||
static void tiqdio_thinint_handler(struct airq_struct *airq,
|
||||
struct tpi_info *tpi_info)
|
||||
{
|
||||
u64 irq_time = get_lowcore()->int_clock;
|
||||
u64 irq_time = get_lowcore()->int_clock.tod;
|
||||
u32 si_used = clear_shared_ind();
|
||||
struct qdio_irq *irq;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user