Skip to content

Commit 70609c1

Browse files
committed
Merge tag 'powerpc-6.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: - Fix 32-bit syscall wrappers with 64-bit arguments of unaligned register-pairs. Notably this broke ftruncate64 & pread/write64, which can lead to file corruption. - Fix lost interrupts when returning to soft-masked context on 64-bit. - Fix build failure when CONFIG_DTL=n. Thanks to Nicholas Piggin, Jason A. Donenfeld, Guenter Roeck, Arnd Bergmann, and Sachin Sant. * tag 'powerpc-6.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/pseries: Fix CONFIG_DTL=n build powerpc/64s/interrupt: Fix lost interrupts when returning to soft-masked context powerpc/32: fix syscall wrappers with 64-bit arguments of unaligned register-pairs
2 parents 2130b87 + 90d5ce8 commit 70609c1

File tree

7 files changed

+149
-91
lines changed

7 files changed

+149
-91
lines changed

arch/powerpc/include/asm/syscalls.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,22 @@ long compat_sys_rt_sigreturn(void);
8989
* responsible for combining parameter pairs.
9090
*/
9191

92+
#ifdef CONFIG_PPC32
93+
long sys_ppc_pread64(unsigned int fd,
94+
char __user *ubuf, compat_size_t count,
95+
u32 reg6, u32 pos1, u32 pos2);
96+
long sys_ppc_pwrite64(unsigned int fd,
97+
const char __user *ubuf, compat_size_t count,
98+
u32 reg6, u32 pos1, u32 pos2);
99+
long sys_ppc_readahead(int fd, u32 r4,
100+
u32 offset1, u32 offset2, u32 count);
101+
long sys_ppc_truncate64(const char __user *path, u32 reg4,
102+
unsigned long len1, unsigned long len2);
103+
long sys_ppc_ftruncate64(unsigned int fd, u32 reg4,
104+
unsigned long len1, unsigned long len2);
105+
long sys_ppc32_fadvise64(int fd, u32 unused, u32 offset1, u32 offset2,
106+
size_t len, int advice);
107+
#endif
92108
#ifdef CONFIG_COMPAT
93109
long compat_sys_mmap2(unsigned long addr, size_t len,
94110
unsigned long prot, unsigned long flags,

arch/powerpc/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ obj-y := cputable.o syscalls.o \
7373
obj-y += ptrace/
7474
obj-$(CONFIG_PPC64) += setup_64.o irq_64.o\
7575
paca.o nvram_64.o note.o
76+
obj-$(CONFIG_PPC32) += sys_ppc32.o
7677
obj-$(CONFIG_COMPAT) += sys_ppc32.o signal_32.o
7778
obj-$(CONFIG_VDSO32) += vdso32_wrapper.o
7879
obj-$(CONFIG_PPC_WATCHDOG) += watchdog.o

arch/powerpc/kernel/interrupt_64.S

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
538538
beq .Lfast_kernel_interrupt_return_\srr\() // EE already disabled
539539
lbz r11,PACAIRQHAPPENED(r13)
540540
andi. r10,r11,PACA_IRQ_MUST_HARD_MASK
541-
beq 1f // No HARD_MASK pending
541+
beq .Lfast_kernel_interrupt_return_\srr\() // No HARD_MASK pending
542542

543543
/* Must clear MSR_EE from _MSR */
544544
#ifdef CONFIG_PPC_BOOK3S
@@ -555,12 +555,23 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
555555
b .Lfast_kernel_interrupt_return_\srr\()
556556

557557
.Linterrupt_return_\srr\()_soft_enabled:
558+
/*
559+
* In the soft-enabled case, need to double-check that we have no
560+
* pending interrupts that might have come in before we reached the
561+
* restart section of code, and restart the exit so those can be
562+
* handled.
563+
*
564+
* If there are none, it is be possible that the interrupt still
565+
* has PACA_IRQ_HARD_DIS set, which needs to be cleared for the
566+
* interrupted context. This clear will not clobber a new pending
567+
* interrupt coming in, because we're in the restart section, so
568+
* such would return to the restart location.
569+
*/
558570
#ifdef CONFIG_PPC_BOOK3S
559571
lbz r11,PACAIRQHAPPENED(r13)
560572
andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
561573
bne- interrupt_return_\srr\()_kernel_restart
562574
#endif
563-
1:
564575
li r11,0
565576
stb r11,PACAIRQHAPPENED(r13) // clear the possible HARD_DIS
566577

arch/powerpc/kernel/sys_ppc32.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
// SPDX-License-Identifier: GPL-2.0-or-later
22
/*
3-
* sys_ppc32.c: Conversion between 32bit and 64bit native syscalls.
3+
* sys_ppc32.c: 32-bit system calls with complex calling conventions.
44
*
55
* Copyright (C) 2001 IBM
66
* Copyright (C) 1997,1998 Jakub Jelinek ([email protected])
77
* Copyright (C) 1997 David S. Miller ([email protected])
88
*
9-
* These routines maintain argument size conversion between 32bit and 64bit
10-
* environment.
9+
* 32-bit system calls with 64-bit arguments pass those in register pairs.
10+
* This must be specially dealt with on 64-bit kernels. The compat_arg_u64_dual
11+
* in generic compat syscalls is not always usable because the register
12+
* pairing is constrained depending on preceding arguments.
13+
*
14+
* An analogous problem exists on 32-bit kernels with ARCH_HAS_SYSCALL_WRAPPER,
15+
* the defined system call functions take the pt_regs as an argument, and there
16+
* is a mapping macro which maps registers to arguments
17+
* (SC_POWERPC_REGS_TO_ARGS) which also does not deal with these 64-bit
18+
* arguments.
19+
*
20+
* This file contains these system calls.
1121
*/
1222

1323
#include <linux/kernel.h>
@@ -47,44 +57,54 @@
4757
#include <asm/syscalls.h>
4858
#include <asm/switch_to.h>
4959

50-
COMPAT_SYSCALL_DEFINE6(ppc_pread64,
60+
#ifdef CONFIG_PPC32
61+
#define PPC32_SYSCALL_DEFINE4 SYSCALL_DEFINE4
62+
#define PPC32_SYSCALL_DEFINE5 SYSCALL_DEFINE5
63+
#define PPC32_SYSCALL_DEFINE6 SYSCALL_DEFINE6
64+
#else
65+
#define PPC32_SYSCALL_DEFINE4 COMPAT_SYSCALL_DEFINE4
66+
#define PPC32_SYSCALL_DEFINE5 COMPAT_SYSCALL_DEFINE5
67+
#define PPC32_SYSCALL_DEFINE6 COMPAT_SYSCALL_DEFINE6
68+
#endif
69+
70+
PPC32_SYSCALL_DEFINE6(ppc_pread64,
5171
unsigned int, fd,
5272
char __user *, ubuf, compat_size_t, count,
5373
u32, reg6, u32, pos1, u32, pos2)
5474
{
5575
return ksys_pread64(fd, ubuf, count, merge_64(pos1, pos2));
5676
}
5777

58-
COMPAT_SYSCALL_DEFINE6(ppc_pwrite64,
78+
PPC32_SYSCALL_DEFINE6(ppc_pwrite64,
5979
unsigned int, fd,
6080
const char __user *, ubuf, compat_size_t, count,
6181
u32, reg6, u32, pos1, u32, pos2)
6282
{
6383
return ksys_pwrite64(fd, ubuf, count, merge_64(pos1, pos2));
6484
}
6585

66-
COMPAT_SYSCALL_DEFINE5(ppc_readahead,
86+
PPC32_SYSCALL_DEFINE5(ppc_readahead,
6787
int, fd, u32, r4,
6888
u32, offset1, u32, offset2, u32, count)
6989
{
7090
return ksys_readahead(fd, merge_64(offset1, offset2), count);
7191
}
7292

73-
COMPAT_SYSCALL_DEFINE4(ppc_truncate64,
93+
PPC32_SYSCALL_DEFINE4(ppc_truncate64,
7494
const char __user *, path, u32, reg4,
7595
unsigned long, len1, unsigned long, len2)
7696
{
7797
return ksys_truncate(path, merge_64(len1, len2));
7898
}
7999

80-
COMPAT_SYSCALL_DEFINE4(ppc_ftruncate64,
100+
PPC32_SYSCALL_DEFINE4(ppc_ftruncate64,
81101
unsigned int, fd, u32, reg4,
82102
unsigned long, len1, unsigned long, len2)
83103
{
84104
return ksys_ftruncate(fd, merge_64(len1, len2));
85105
}
86106

87-
COMPAT_SYSCALL_DEFINE6(ppc32_fadvise64,
107+
PPC32_SYSCALL_DEFINE6(ppc32_fadvise64,
88108
int, fd, u32, unused, u32, offset1, u32, offset2,
89109
size_t, len, int, advice)
90110
{

arch/powerpc/kernel/syscalls/syscall.tbl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,10 @@
228228
176 64 rt_sigtimedwait sys_rt_sigtimedwait
229229
177 nospu rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
230230
178 nospu rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
231-
179 common pread64 sys_pread64 compat_sys_ppc_pread64
232-
180 common pwrite64 sys_pwrite64 compat_sys_ppc_pwrite64
231+
179 32 pread64 sys_ppc_pread64 compat_sys_ppc_pread64
232+
179 64 pread64 sys_pread64
233+
180 32 pwrite64 sys_ppc_pwrite64 compat_sys_ppc_pwrite64
234+
180 64 pwrite64 sys_pwrite64
233235
181 common chown sys_chown
234236
182 common getcwd sys_getcwd
235237
183 common capget sys_capget
@@ -242,10 +244,11 @@
242244
188 common putpmsg sys_ni_syscall
243245
189 nospu vfork sys_vfork
244246
190 common ugetrlimit sys_getrlimit compat_sys_getrlimit
245-
191 common readahead sys_readahead compat_sys_ppc_readahead
247+
191 32 readahead sys_ppc_readahead compat_sys_ppc_readahead
248+
191 64 readahead sys_readahead
246249
192 32 mmap2 sys_mmap2 compat_sys_mmap2
247-
193 32 truncate64 sys_truncate64 compat_sys_ppc_truncate64
248-
194 32 ftruncate64 sys_ftruncate64 compat_sys_ppc_ftruncate64
250+
193 32 truncate64 sys_ppc_truncate64 compat_sys_ppc_truncate64
251+
194 32 ftruncate64 sys_ppc_ftruncate64 compat_sys_ppc_ftruncate64
249252
195 32 stat64 sys_stat64
250253
196 32 lstat64 sys_lstat64
251254
197 32 fstat64 sys_fstat64
@@ -288,7 +291,8 @@
288291
230 common io_submit sys_io_submit compat_sys_io_submit
289292
231 common io_cancel sys_io_cancel
290293
232 nospu set_tid_address sys_set_tid_address
291-
233 common fadvise64 sys_fadvise64 compat_sys_ppc32_fadvise64
294+
233 32 fadvise64 sys_ppc32_fadvise64 compat_sys_ppc32_fadvise64
295+
233 64 fadvise64 sys_fadvise64
292296
234 nospu exit_group sys_exit_group
293297
235 nospu lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
294298
236 common epoll_create sys_epoll_create

arch/powerpc/platforms/pseries/Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \
77
setup.o iommu.o event_sources.o ras.o \
88
firmware.o power.o dlpar.o mobility.o rng.o \
99
pci.o pci_dlpar.o eeh_pseries.o msi.o \
10-
papr_platform_attributes.o
10+
papr_platform_attributes.o dtl.o
1111
obj-$(CONFIG_SMP) += smp.o
1212
obj-$(CONFIG_KEXEC_CORE) += kexec.o
1313
obj-$(CONFIG_PSERIES_ENERGY) += pseries_energy.o
@@ -19,7 +19,6 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
1919
obj-$(CONFIG_HVCS) += hvcserver.o
2020
obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
2121
obj-$(CONFIG_CMM) += cmm.o
22-
obj-$(CONFIG_DTL) += dtl.o
2322
obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o
2423
obj-$(CONFIG_LPARCFG) += lparcfg.o
2524
obj-$(CONFIG_IBMVIO) += vio.o

arch/powerpc/platforms/pseries/dtl.c

Lines changed: 79 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <asm/plpar_wrappers.h>
1919
#include <asm/machdep.h>
2020

21+
#ifdef CONFIG_DTL
2122
struct dtl {
2223
struct dtl_entry *buf;
2324
int cpu;
@@ -57,78 +58,6 @@ static DEFINE_PER_CPU(struct dtl_ring, dtl_rings);
5758

5859
static atomic_t dtl_count;
5960

60-
/*
61-
* Scan the dispatch trace log and count up the stolen time.
62-
* Should be called with interrupts disabled.
63-
*/
64-
static notrace u64 scan_dispatch_log(u64 stop_tb)
65-
{
66-
u64 i = local_paca->dtl_ridx;
67-
struct dtl_entry *dtl = local_paca->dtl_curr;
68-
struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
69-
struct lppaca *vpa = local_paca->lppaca_ptr;
70-
u64 tb_delta;
71-
u64 stolen = 0;
72-
u64 dtb;
73-
74-
if (!dtl)
75-
return 0;
76-
77-
if (i == be64_to_cpu(vpa->dtl_idx))
78-
return 0;
79-
while (i < be64_to_cpu(vpa->dtl_idx)) {
80-
dtb = be64_to_cpu(dtl->timebase);
81-
tb_delta = be32_to_cpu(dtl->enqueue_to_dispatch_time) +
82-
be32_to_cpu(dtl->ready_to_enqueue_time);
83-
barrier();
84-
if (i + N_DISPATCH_LOG < be64_to_cpu(vpa->dtl_idx)) {
85-
/* buffer has overflowed */
86-
i = be64_to_cpu(vpa->dtl_idx) - N_DISPATCH_LOG;
87-
dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
88-
continue;
89-
}
90-
if (dtb > stop_tb)
91-
break;
92-
if (dtl_consumer)
93-
dtl_consumer(dtl, i);
94-
stolen += tb_delta;
95-
++i;
96-
++dtl;
97-
if (dtl == dtl_end)
98-
dtl = local_paca->dispatch_log;
99-
}
100-
local_paca->dtl_ridx = i;
101-
local_paca->dtl_curr = dtl;
102-
return stolen;
103-
}
104-
105-
/*
106-
* Accumulate stolen time by scanning the dispatch trace log.
107-
* Called on entry from user mode.
108-
*/
109-
void notrace pseries_accumulate_stolen_time(void)
110-
{
111-
u64 sst, ust;
112-
struct cpu_accounting_data *acct = &local_paca->accounting;
113-
114-
sst = scan_dispatch_log(acct->starttime_user);
115-
ust = scan_dispatch_log(acct->starttime);
116-
acct->stime -= sst;
117-
acct->utime -= ust;
118-
acct->steal_time += ust + sst;
119-
}
120-
121-
u64 pseries_calculate_stolen_time(u64 stop_tb)
122-
{
123-
if (!firmware_has_feature(FW_FEATURE_SPLPAR))
124-
return 0;
125-
126-
if (get_paca()->dtl_ridx != be64_to_cpu(get_lppaca()->dtl_idx))
127-
return scan_dispatch_log(stop_tb);
128-
129-
return 0;
130-
}
131-
13261
/*
13362
* The cpu accounting code controls the DTL ring buffer, and we get
13463
* given entries as they are processed.
@@ -436,3 +365,81 @@ static int dtl_init(void)
436365
return 0;
437366
}
438367
machine_arch_initcall(pseries, dtl_init);
368+
#endif /* CONFIG_DTL */
369+
370+
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
371+
/*
372+
* Scan the dispatch trace log and count up the stolen time.
373+
* Should be called with interrupts disabled.
374+
*/
375+
static notrace u64 scan_dispatch_log(u64 stop_tb)
376+
{
377+
u64 i = local_paca->dtl_ridx;
378+
struct dtl_entry *dtl = local_paca->dtl_curr;
379+
struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
380+
struct lppaca *vpa = local_paca->lppaca_ptr;
381+
u64 tb_delta;
382+
u64 stolen = 0;
383+
u64 dtb;
384+
385+
if (!dtl)
386+
return 0;
387+
388+
if (i == be64_to_cpu(vpa->dtl_idx))
389+
return 0;
390+
while (i < be64_to_cpu(vpa->dtl_idx)) {
391+
dtb = be64_to_cpu(dtl->timebase);
392+
tb_delta = be32_to_cpu(dtl->enqueue_to_dispatch_time) +
393+
be32_to_cpu(dtl->ready_to_enqueue_time);
394+
barrier();
395+
if (i + N_DISPATCH_LOG < be64_to_cpu(vpa->dtl_idx)) {
396+
/* buffer has overflowed */
397+
i = be64_to_cpu(vpa->dtl_idx) - N_DISPATCH_LOG;
398+
dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
399+
continue;
400+
}
401+
if (dtb > stop_tb)
402+
break;
403+
#ifdef CONFIG_DTL
404+
if (dtl_consumer)
405+
dtl_consumer(dtl, i);
406+
#endif
407+
stolen += tb_delta;
408+
++i;
409+
++dtl;
410+
if (dtl == dtl_end)
411+
dtl = local_paca->dispatch_log;
412+
}
413+
local_paca->dtl_ridx = i;
414+
local_paca->dtl_curr = dtl;
415+
return stolen;
416+
}
417+
418+
/*
419+
* Accumulate stolen time by scanning the dispatch trace log.
420+
* Called on entry from user mode.
421+
*/
422+
void notrace pseries_accumulate_stolen_time(void)
423+
{
424+
u64 sst, ust;
425+
struct cpu_accounting_data *acct = &local_paca->accounting;
426+
427+
sst = scan_dispatch_log(acct->starttime_user);
428+
ust = scan_dispatch_log(acct->starttime);
429+
acct->stime -= sst;
430+
acct->utime -= ust;
431+
acct->steal_time += ust + sst;
432+
}
433+
434+
u64 pseries_calculate_stolen_time(u64 stop_tb)
435+
{
436+
if (!firmware_has_feature(FW_FEATURE_SPLPAR))
437+
return 0;
438+
439+
if (get_paca()->dtl_ridx != be64_to_cpu(get_lppaca()->dtl_idx))
440+
return scan_dispatch_log(stop_tb);
441+
442+
return 0;
443+
}
444+
445+
#endif

0 commit comments

Comments
 (0)