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-5.4-6' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Vasily Gorbik:

- Fix cpu idle time accounting

- Fix stack unwinder case when both pt_regs and sp are specified

- Fix information leak via cmm timeout proc handler

* tag 's390-5.4-6' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/idle: fix cpu idle time calculation
s390/unwind: fix mixing regs and sp
s390/cmm: fix information leak in cmm_timeout_handler()

+42 -18
+1
arch/s390/include/asm/unwind.h
··· 35 35 struct task_struct *task; 36 36 struct pt_regs *regs; 37 37 unsigned long sp, ip; 38 + bool reuse_sp; 38 39 int graph_idx; 39 40 bool reliable; 40 41 bool error;
+22 -7
arch/s390/kernel/idle.c
··· 69 69 static ssize_t show_idle_time(struct device *dev, 70 70 struct device_attribute *attr, char *buf) 71 71 { 72 + unsigned long long now, idle_time, idle_enter, idle_exit, in_idle; 72 73 struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); 73 - unsigned long long now, idle_time, idle_enter, idle_exit; 74 74 unsigned int seq; 75 75 76 76 do { 77 - now = get_tod_clock(); 78 77 seq = read_seqcount_begin(&idle->seqcount); 79 78 idle_time = READ_ONCE(idle->idle_time); 80 79 idle_enter = READ_ONCE(idle->clock_idle_enter); 81 80 idle_exit = READ_ONCE(idle->clock_idle_exit); 82 81 } while (read_seqcount_retry(&idle->seqcount, seq)); 83 - idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0; 82 + in_idle = 0; 83 + now = get_tod_clock(); 84 + if (idle_enter) { 85 + if (idle_exit) { 86 + in_idle = idle_exit - idle_enter; 87 + } else if (now > idle_enter) { 88 + in_idle = now - idle_enter; 89 + } 90 + } 91 + idle_time += in_idle; 84 92 return sprintf(buf, "%llu\n", idle_time >> 12); 85 93 } 86 94 DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL); ··· 96 88 u64 arch_cpu_idle_time(int cpu) 97 89 { 98 90 struct s390_idle_data *idle = &per_cpu(s390_idle, cpu); 99 - unsigned long long now, idle_enter, idle_exit; 91 + unsigned long long now, idle_enter, idle_exit, in_idle; 100 92 unsigned int seq; 101 93 102 94 do { 103 - now = get_tod_clock(); 104 95 seq = read_seqcount_begin(&idle->seqcount); 105 96 idle_enter = READ_ONCE(idle->clock_idle_enter); 106 97 idle_exit = READ_ONCE(idle->clock_idle_exit); 107 98 } while (read_seqcount_retry(&idle->seqcount, seq)); 108 - 109 - return cputime_to_nsecs(idle_enter ? ((idle_exit ?: now) - idle_enter) : 0); 99 + in_idle = 0; 100 + now = get_tod_clock(); 101 + if (idle_enter) { 102 + if (idle_exit) { 103 + in_idle = idle_exit - idle_enter; 104 + } else if (now > idle_enter) { 105 + in_idle = now - idle_enter; 106 + } 107 + } 108 + return cputime_to_nsecs(in_idle); 110 109 } 111 110 112 111 void arch_cpu_idle_enter(void)
+13 -5
arch/s390/kernel/unwind_bc.c
··· 46 46 47 47 regs = state->regs; 48 48 if (unlikely(regs)) { 49 - sp = READ_ONCE_NOCHECK(regs->gprs[15]); 50 - if (unlikely(outside_of_stack(state, sp))) { 51 - if (!update_stack_info(state, sp)) 52 - goto out_err; 49 + if (state->reuse_sp) { 50 + sp = state->sp; 51 + state->reuse_sp = false; 52 + } else { 53 + sp = READ_ONCE_NOCHECK(regs->gprs[15]); 54 + if (unlikely(outside_of_stack(state, sp))) { 55 + if (!update_stack_info(state, sp)) 56 + goto out_err; 57 + } 53 58 } 54 59 sf = (struct stack_frame *) sp; 55 60 ip = READ_ONCE_NOCHECK(sf->gprs[8]); ··· 112 107 { 113 108 struct stack_info *info = &state->stack_info; 114 109 unsigned long *mask = &state->stack_mask; 110 + bool reliable, reuse_sp; 115 111 struct stack_frame *sf; 116 112 unsigned long ip; 117 - bool reliable; 118 113 119 114 memset(state, 0, sizeof(*state)); 120 115 state->task = task; ··· 139 134 if (regs) { 140 135 ip = READ_ONCE_NOCHECK(regs->psw.addr); 141 136 reliable = true; 137 + reuse_sp = true; 142 138 } else { 143 139 sf = (struct stack_frame *) sp; 144 140 ip = READ_ONCE_NOCHECK(sf->gprs[8]); 145 141 reliable = false; 142 + reuse_sp = false; 146 143 } 147 144 148 145 #ifdef CONFIG_FUNCTION_GRAPH_TRACER ··· 158 151 state->sp = sp; 159 152 state->ip = ip; 160 153 state->reliable = reliable; 154 + state->reuse_sp = reuse_sp; 161 155 } 162 156 EXPORT_SYMBOL_GPL(__unwind_start);
+6 -6
arch/s390/mm/cmm.c
··· 298 298 } 299 299 300 300 if (write) { 301 - len = *lenp; 302 - if (copy_from_user(buf, buffer, 303 - len > sizeof(buf) ? sizeof(buf) : len)) 301 + len = min(*lenp, sizeof(buf)); 302 + if (copy_from_user(buf, buffer, len)) 304 303 return -EFAULT; 305 - buf[sizeof(buf) - 1] = '\0'; 304 + buf[len - 1] = '\0'; 306 305 cmm_skip_blanks(buf, &p); 307 306 nr = simple_strtoul(p, &p, 0); 308 307 cmm_skip_blanks(p, &p); 309 308 seconds = simple_strtoul(p, &p, 0); 310 309 cmm_set_timeout(nr, seconds); 310 + *ppos += *lenp; 311 311 } else { 312 312 len = sprintf(buf, "%ld %ld\n", 313 313 cmm_timeout_pages, cmm_timeout_seconds); ··· 315 315 len = *lenp; 316 316 if (copy_to_user(buffer, buf, len)) 317 317 return -EFAULT; 318 + *lenp = len; 319 + *ppos += len; 318 320 } 319 - *lenp = len; 320 - *ppos += len; 321 321 return 0; 322 322 } 323 323