Commit 201795a1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull s390 fixes from Vasily Gorbik:

 - Fix guest pfault init to pass a physical address to DIAG 0x258,
   restoring pfault interrupts and avoiding vCPU stalls during host
   page-in

 - Fix kexec/kdump hangs with stack protector by marking
   s390_reset_system() __no_stack_protector; set_prefix(0) switches
   lowcore and the canary no longer matches

 - Fix idle/vtime cputime accounting (idle-exit ordering, vtimer
   double-forwarding) and small cleanups

* tag 's390-7.0-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/pfault: Fix virtual vs physical address confusion
  s390/kexec: Disable stack protector in s390_reset_system()
  s390/idle: Remove psw_idle() prototype
  s390/vtime: Use lockdep_assert_irqs_disabled() instead of BUG_ON()
  s390/vtime: Use __this_cpu_read() / get rid of READ_ONCE()
  s390/irq/idle: Remove psw bits early
  s390/idle: Inline update_timer_idle()
  s390/idle: Slightly optimize idle time accounting
  s390/idle: Add comment for non obvious code
  s390/vtime: Fix virtual timer forwarding
  s390/idle: Fix cpu idle exit cpu time accounting
parents 4d349ee5 d879ac67
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -19,9 +19,9 @@ struct s390_idle_data {
	unsigned long mt_cycles_enter[8];
};

DECLARE_PER_CPU(struct s390_idle_data, s390_idle);

extern struct device_attribute dev_attr_idle_count;
extern struct device_attribute dev_attr_idle_time_us;

void psw_idle(struct s390_idle_data *data, unsigned long psw_mask);

#endif /* _S390_IDLE_H */
+34 −0
Original line number Diff line number Diff line
@@ -2,6 +2,12 @@
#ifndef _S390_VTIME_H
#define _S390_VTIME_H

#include <asm/lowcore.h>
#include <asm/cpu_mf.h>
#include <asm/idle.h>

DECLARE_PER_CPU(u64, mt_cycles[8]);

static inline void update_timer_sys(void)
{
	struct lowcore *lc = get_lowcore();
@@ -20,4 +26,32 @@ static inline void update_timer_mcck(void)
	lc->last_update_timer = lc->mcck_enter_timer;
}

static inline void update_timer_idle(void)
{
	struct s390_idle_data *idle = this_cpu_ptr(&s390_idle);
	struct lowcore *lc = get_lowcore();
	u64 cycles_new[8];
	int i, mtid;

	mtid = smp_cpu_mtid;
	if (mtid) {
		stcctm(MT_DIAG, mtid, cycles_new);
		for (i = 0; i < mtid; i++)
			__this_cpu_add(mt_cycles[i], cycles_new[i] - idle->mt_cycles_enter[i]);
	}
	/*
	 * This is a bit subtle: Forward last_update_clock so it excludes idle
	 * time. For correct steal time calculation in do_account_vtime() add
	 * passed wall time before idle_enter to steal_timer:
	 * During the passed wall time before idle_enter CPU time may have
	 * been accounted to system, hardirq, softirq, etc. lowcore fields.
	 * 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->system_timer += lc->last_update_timer - idle->timer_idle_enter;
	lc->last_update_timer = lc->sys_enter_timer;
}

#endif /* _S390_VTIME_H */
+0 −2
Original line number Diff line number Diff line
@@ -56,8 +56,6 @@ long sys_s390_pci_mmio_write(unsigned long, const void __user *, size_t);
long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t);
long sys_s390_sthyi(unsigned long function_code, void __user *buffer, u64 __user *return_code, unsigned long flags);

DECLARE_PER_CPU(u64, mt_cycles[8]);

unsigned long stack_alloc(void);
void stack_free(unsigned long stack);

+5 −20
Original line number Diff line number Diff line
@@ -15,37 +15,22 @@
#include <trace/events/power.h>
#include <asm/cpu_mf.h>
#include <asm/cputime.h>
#include <asm/idle.h>
#include <asm/nmi.h>
#include <asm/smp.h>
#include "entry.h"

static DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
DEFINE_PER_CPU(struct s390_idle_data, s390_idle);

void account_idle_time_irq(void)
{
	struct s390_idle_data *idle = this_cpu_ptr(&s390_idle);
	struct lowcore *lc = get_lowcore();
	unsigned long idle_time;
	u64 cycles_new[8];
	int i;

	if (smp_cpu_mtid) {
		stcctm(MT_DIAG, smp_cpu_mtid, cycles_new);
		for (i = 0; i < smp_cpu_mtid; i++)
			this_cpu_add(mt_cycles[i], cycles_new[i] - idle->mt_cycles_enter[i]);
	}

	idle_time = lc->int_clock - idle->clock_idle_enter;

	lc->steal_timer += idle->clock_idle_enter - lc->last_update_clock;
	lc->last_update_clock = lc->int_clock;

	lc->system_timer += lc->last_update_timer - idle->timer_idle_enter;
	lc->last_update_timer = lc->sys_enter_timer;
	idle_time = get_lowcore()->int_clock - idle->clock_idle_enter;

	/* Account time spent with enabled wait psw loaded as idle time. */
	WRITE_ONCE(idle->idle_time, READ_ONCE(idle->idle_time) + idle_time);
	WRITE_ONCE(idle->idle_count, READ_ONCE(idle->idle_count) + 1);
	__atomic64_add(idle_time, &idle->idle_time);
	__atomic64_add_const(1, &idle->idle_count);
	account_idle_time(cputime_to_nsecs(idle_time));
}

+1 −1
Original line number Diff line number Diff line
@@ -2377,7 +2377,7 @@ void __init setup_ipl(void)
	atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
}

void s390_reset_system(void)
void __no_stack_protector s390_reset_system(void)
{
	/* Disable prefixing */
	set_prefix(0);
Loading