Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 's390-7.0-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

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

+66 -67
+2 -2
arch/s390/include/asm/idle.h
··· 19 19 unsigned long mt_cycles_enter[8]; 20 20 }; 21 21 22 + DECLARE_PER_CPU(struct s390_idle_data, s390_idle); 23 + 22 24 extern struct device_attribute dev_attr_idle_count; 23 25 extern struct device_attribute dev_attr_idle_time_us; 24 - 25 - void psw_idle(struct s390_idle_data *data, unsigned long psw_mask); 26 26 27 27 #endif /* _S390_IDLE_H */
+34
arch/s390/include/asm/vtime.h
··· 2 2 #ifndef _S390_VTIME_H 3 3 #define _S390_VTIME_H 4 4 5 + #include <asm/lowcore.h> 6 + #include <asm/cpu_mf.h> 7 + #include <asm/idle.h> 8 + 9 + DECLARE_PER_CPU(u64, mt_cycles[8]); 10 + 5 11 static inline void update_timer_sys(void) 6 12 { 7 13 struct lowcore *lc = get_lowcore(); ··· 24 18 lc->system_timer += lc->last_update_timer - lc->exit_timer; 25 19 lc->user_timer += lc->exit_timer - lc->mcck_enter_timer; 26 20 lc->last_update_timer = lc->mcck_enter_timer; 21 + } 22 + 23 + static inline void update_timer_idle(void) 24 + { 25 + struct s390_idle_data *idle = this_cpu_ptr(&s390_idle); 26 + struct lowcore *lc = get_lowcore(); 27 + u64 cycles_new[8]; 28 + int i, mtid; 29 + 30 + mtid = smp_cpu_mtid; 31 + if (mtid) { 32 + stcctm(MT_DIAG, mtid, cycles_new); 33 + for (i = 0; i < mtid; i++) 34 + __this_cpu_add(mt_cycles[i], cycles_new[i] - idle->mt_cycles_enter[i]); 35 + } 36 + /* 37 + * This is a bit subtle: Forward last_update_clock so it excludes idle 38 + * time. For correct steal time calculation in do_account_vtime() add 39 + * passed wall time before idle_enter to steal_timer: 40 + * During the passed wall time before idle_enter CPU time may have 41 + * been accounted to system, hardirq, softirq, etc. lowcore fields. 42 + * The accounted CPU times will be subtracted again from steal_timer 43 + * when accumulated steal time is calculated in do_account_vtime(). 44 + */ 45 + lc->steal_timer += idle->clock_idle_enter - lc->last_update_clock; 46 + lc->last_update_clock = lc->int_clock; 47 + lc->system_timer += lc->last_update_timer - idle->timer_idle_enter; 48 + lc->last_update_timer = lc->sys_enter_timer; 27 49 } 28 50 29 51 #endif /* _S390_VTIME_H */
-2
arch/s390/kernel/entry.h
··· 56 56 long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t); 57 57 long sys_s390_sthyi(unsigned long function_code, void __user *buffer, u64 __user *return_code, unsigned long flags); 58 58 59 - DECLARE_PER_CPU(u64, mt_cycles[8]); 60 - 61 59 unsigned long stack_alloc(void); 62 60 void stack_free(unsigned long stack); 63 61
+5 -20
arch/s390/kernel/idle.c
··· 15 15 #include <trace/events/power.h> 16 16 #include <asm/cpu_mf.h> 17 17 #include <asm/cputime.h> 18 + #include <asm/idle.h> 18 19 #include <asm/nmi.h> 19 20 #include <asm/smp.h> 20 - #include "entry.h" 21 21 22 - static DEFINE_PER_CPU(struct s390_idle_data, s390_idle); 22 + DEFINE_PER_CPU(struct s390_idle_data, s390_idle); 23 23 24 24 void account_idle_time_irq(void) 25 25 { 26 26 struct s390_idle_data *idle = this_cpu_ptr(&s390_idle); 27 - struct lowcore *lc = get_lowcore(); 28 27 unsigned long idle_time; 29 - u64 cycles_new[8]; 30 - int i; 31 28 32 - if (smp_cpu_mtid) { 33 - stcctm(MT_DIAG, smp_cpu_mtid, cycles_new); 34 - for (i = 0; i < smp_cpu_mtid; i++) 35 - this_cpu_add(mt_cycles[i], cycles_new[i] - idle->mt_cycles_enter[i]); 36 - } 37 - 38 - idle_time = lc->int_clock - idle->clock_idle_enter; 39 - 40 - lc->steal_timer += idle->clock_idle_enter - lc->last_update_clock; 41 - lc->last_update_clock = lc->int_clock; 42 - 43 - lc->system_timer += lc->last_update_timer - idle->timer_idle_enter; 44 - lc->last_update_timer = lc->sys_enter_timer; 29 + idle_time = get_lowcore()->int_clock - idle->clock_idle_enter; 45 30 46 31 /* Account time spent with enabled wait psw loaded as idle time. */ 47 - WRITE_ONCE(idle->idle_time, READ_ONCE(idle->idle_time) + idle_time); 48 - WRITE_ONCE(idle->idle_count, READ_ONCE(idle->idle_count) + 1); 32 + __atomic64_add(idle_time, &idle->idle_time); 33 + __atomic64_add_const(1, &idle->idle_count); 49 34 account_idle_time(cputime_to_nsecs(idle_time)); 50 35 } 51 36
+1 -1
arch/s390/kernel/ipl.c
··· 2377 2377 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); 2378 2378 } 2379 2379 2380 - void s390_reset_system(void) 2380 + void __no_stack_protector s390_reset_system(void) 2381 2381 { 2382 2382 /* Disable prefixing */ 2383 2383 set_prefix(0);
+12 -8
arch/s390/kernel/irq.c
··· 146 146 struct pt_regs *old_regs = set_irq_regs(regs); 147 147 bool from_idle; 148 148 149 + from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); 150 + if (from_idle) { 151 + update_timer_idle(); 152 + regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); 153 + } 154 + 149 155 irq_enter_rcu(); 150 156 151 157 if (user_mode(regs)) { ··· 160 154 current->thread.last_break = regs->last_break; 161 155 } 162 156 163 - from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); 164 157 if (from_idle) 165 158 account_idle_time_irq(); 166 159 ··· 176 171 177 172 set_irq_regs(old_regs); 178 173 irqentry_exit(regs, state); 179 - 180 - if (from_idle) 181 - regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); 182 174 } 183 175 184 176 void noinstr do_ext_irq(struct pt_regs *regs) ··· 183 181 irqentry_state_t state = irqentry_enter(regs); 184 182 struct pt_regs *old_regs = set_irq_regs(regs); 185 183 bool from_idle; 184 + 185 + from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); 186 + if (from_idle) { 187 + update_timer_idle(); 188 + regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); 189 + } 186 190 187 191 irq_enter_rcu(); 188 192 ··· 202 194 regs->int_parm = get_lowcore()->ext_params; 203 195 regs->int_parm_long = get_lowcore()->ext_params2; 204 196 205 - from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); 206 197 if (from_idle) 207 198 account_idle_time_irq(); 208 199 ··· 210 203 irq_exit_rcu(); 211 204 set_irq_regs(old_regs); 212 205 irqentry_exit(regs, state); 213 - 214 - if (from_idle) 215 - regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); 216 206 } 217 207 218 208 static void show_msi_interrupt(struct seq_file *p, int irq)
+10 -32
arch/s390/kernel/vtime.c
··· 48 48 49 49 static inline int virt_timer_forward(u64 elapsed) 50 50 { 51 - BUG_ON(!irqs_disabled()); 52 - 51 + lockdep_assert_irqs_disabled(); 53 52 if (list_empty(&virt_timer_list)) 54 53 return 0; 55 54 elapsed = atomic64_add_return(elapsed, &virt_timer_elapsed); ··· 136 137 lc->system_timer += timer; 137 138 138 139 /* Update MT utilization calculation */ 139 - if (smp_cpu_mtid && 140 - time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies))) 140 + if (smp_cpu_mtid && time_after64(jiffies_64, __this_cpu_read(mt_scaling_jiffies))) 141 141 update_mt_scaling(); 142 142 143 143 /* Calculate cputime delta */ 144 - user = update_tsk_timer(&tsk->thread.user_timer, 145 - READ_ONCE(lc->user_timer)); 146 - guest = update_tsk_timer(&tsk->thread.guest_timer, 147 - READ_ONCE(lc->guest_timer)); 148 - system = update_tsk_timer(&tsk->thread.system_timer, 149 - READ_ONCE(lc->system_timer)); 150 - hardirq = update_tsk_timer(&tsk->thread.hardirq_timer, 151 - READ_ONCE(lc->hardirq_timer)); 152 - softirq = update_tsk_timer(&tsk->thread.softirq_timer, 153 - READ_ONCE(lc->softirq_timer)); 154 - lc->steal_timer += 155 - clock - user - guest - system - hardirq - softirq; 144 + user = update_tsk_timer(&tsk->thread.user_timer, lc->user_timer); 145 + guest = update_tsk_timer(&tsk->thread.guest_timer, lc->guest_timer); 146 + system = update_tsk_timer(&tsk->thread.system_timer, lc->system_timer); 147 + hardirq = update_tsk_timer(&tsk->thread.hardirq_timer, lc->hardirq_timer); 148 + softirq = update_tsk_timer(&tsk->thread.softirq_timer, lc->softirq_timer); 149 + lc->steal_timer += clock - user - guest - system - hardirq - softirq; 156 150 157 151 /* Push account value */ 158 152 if (user) { ··· 217 225 return timer - lc->last_update_timer; 218 226 } 219 227 220 - /* 221 - * Update process times based on virtual cpu times stored by entry.S 222 - * to the lowcore fields user_timer, system_timer & steal_clock. 223 - */ 224 228 void vtime_account_kernel(struct task_struct *tsk) 225 229 { 226 230 struct lowcore *lc = get_lowcore(); ··· 226 238 lc->guest_timer += delta; 227 239 else 228 240 lc->system_timer += delta; 229 - 230 - virt_timer_forward(delta); 231 241 } 232 242 EXPORT_SYMBOL_GPL(vtime_account_kernel); 233 243 234 244 void vtime_account_softirq(struct task_struct *tsk) 235 245 { 236 - u64 delta = vtime_delta(); 237 - 238 - get_lowcore()->softirq_timer += delta; 239 - 240 - virt_timer_forward(delta); 246 + get_lowcore()->softirq_timer += vtime_delta(); 241 247 } 242 248 243 249 void vtime_account_hardirq(struct task_struct *tsk) 244 250 { 245 - u64 delta = vtime_delta(); 246 - 247 - get_lowcore()->hardirq_timer += delta; 248 - 249 - virt_timer_forward(delta); 251 + get_lowcore()->hardirq_timer += vtime_delta(); 250 252 } 251 253 252 254 /*
+2 -2
arch/s390/mm/pfault.c
··· 62 62 "0: nopr %%r7\n" 63 63 EX_TABLE(0b, 0b) 64 64 : [rc] "+d" (rc) 65 - : [refbk] "a" (&pfault_init_refbk), "m" (pfault_init_refbk) 65 + : [refbk] "a" (virt_to_phys(&pfault_init_refbk)), "m" (pfault_init_refbk) 66 66 : "cc"); 67 67 return rc; 68 68 } ··· 84 84 "0: nopr %%r7\n" 85 85 EX_TABLE(0b, 0b) 86 86 : 87 - : [refbk] "a" (&pfault_fini_refbk), "m" (pfault_fini_refbk) 87 + : [refbk] "a" (virt_to_phys(&pfault_fini_refbk)), "m" (pfault_fini_refbk) 88 88 : "cc"); 89 89 } 90 90