Skip to content

Commit e98e03d

Browse files
committed
Merge tag 's390-5.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull more s390 updates from Vasily Gorbik: - Fix preempt_count initialization. - Rework call_on_stack() macro to add proper type handling and avoid possible register corruption. - More error prone "register asm" removal and fixes. - Fix syscall restarting when multiple signals are coming in. This adds minimalistic trampolines to vdso so we can return from signal without using the stack which requires pgm check handler hacks when NX is enabled. - Remove HAVE_IRQ_EXIT_ON_IRQ_STACK since this is no longer true after switch to generic entry. - Fix protected virtualization secure storage access exception handling. - Make machine check C handler always enter with DAT enabled and move register validation to C code. - Fix tinyconfig boot problem by avoiding MONITOR CALL without CONFIG_BUG. - Increase asm symbols alignment to 16 to make it consistent with compilers. - Enable concurrent access to the CPU Measurement Counter Facility. - Add support for dynamic AP bus size limit and rework ap_dqap to deal with messages greater than recv buffer. * tag 's390-5.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (41 commits) s390: preempt: Fix preempt_count initialization s390/linkage: increase asm symbols alignment to 16 s390: rename CALL_ON_STACK_NORETURN() to call_on_stack_noreturn() s390: add type checking to CALL_ON_STACK_NORETURN() macro s390: remove old CALL_ON_STACK() macro s390/softirq: use call_on_stack() macro s390/lib: use call_on_stack() macro s390/smp: use call_on_stack() macro s390/kexec: use call_on_stack() macro s390/irq: use call_on_stack() macro s390/mm: use call_on_stack() macro s390: introduce proper type handling call_on_stack() macro s390/irq: simplify on_async_stack() s390/irq: inline do_softirq_own_stack() s390/irq: simplify do_softirq_own_stack() s390/ap: get rid of register asm in ap_dqap() s390: rename PIF_SYSCALL_RESTART to PIF_EXECVE_PGSTE_RESTART s390: move restart of execve() syscall s390/signal: remove sigreturn on stack s390/signal: switch to using vdso for sigreturn and syscall restart ...
2 parents 379cf80 + 6a942f5 commit e98e03d

66 files changed

Lines changed: 2110 additions & 1721 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

arch/s390/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ config S390
163163
select HAVE_GCC_PLUGINS
164164
select HAVE_GENERIC_VDSO
165165
select HAVE_IOREMAP_PROT if PCI
166-
select HAVE_IRQ_EXIT_ON_IRQ_STACK
167166
select HAVE_KERNEL_BZIP2
168167
select HAVE_KERNEL_GZIP
169168
select HAVE_KERNEL_LZ4
@@ -438,6 +437,7 @@ config COMPAT
438437
select COMPAT_OLD_SIGACTION
439438
select HAVE_UID16
440439
depends on MULTIUSER
440+
depends on !CC_IS_CLANG
441441
help
442442
Select this option if you want to enable your system kernel to
443443
handle system-calls from ELF binaries for 31 bit ESA. This option

arch/s390/Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,19 @@ archheaders:
166166
archprepare:
167167
$(Q)$(MAKE) $(build)=$(syscalls) kapi
168168
$(Q)$(MAKE) $(build)=$(tools) kapi
169+
ifeq ($(KBUILD_EXTMOD),)
170+
# We need to generate vdso-offsets.h before compiling certain files in kernel/.
171+
# In order to do that, we should use the archprepare target, but we can't since
172+
# asm-offsets.h is included in some files used to generate vdso-offsets.h, and
173+
# asm-offsets.h is built in prepare0, for which archprepare is a dependency.
174+
# Therefore we need to generate the header after prepare0 has been made, hence
175+
# this hack.
176+
prepare: vdso_prepare
177+
vdso_prepare: prepare0
178+
$(Q)$(MAKE) $(build)=arch/s390/kernel/vdso64 include/generated/vdso64-offsets.h
179+
$(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
180+
$(build)=arch/s390/kernel/vdso32 include/generated/vdso32-offsets.h)
181+
endif
169182

170183
# Don't use tabs in echo arguments
171184
define archhelp

arch/s390/boot/startup.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ unsigned long __bootdata_preserved(vmemmap_size);
2323
unsigned long __bootdata_preserved(MODULES_VADDR);
2424
unsigned long __bootdata_preserved(MODULES_END);
2525
unsigned long __bootdata(ident_map_size);
26+
int __bootdata(is_full_image) = 1;
2627

2728
u64 __bootdata_preserved(stfle_fac_list[16]);
2829
u64 __bootdata_preserved(alt_stfle_fac_list[16]);

arch/s390/boot/uv.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void uv_query_info(void)
3636
uv_info.max_sec_stor_addr = ALIGN(uvcb.max_guest_stor_addr, PAGE_SIZE);
3737
uv_info.max_num_sec_conf = uvcb.max_num_sec_conf;
3838
uv_info.max_guest_cpu_id = uvcb.max_guest_cpu_id;
39+
uv_info.uv_feature_indications = uvcb.uv_feature_indications;
3940
}
4041

4142
#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST

arch/s390/include/asm/ap.h

Lines changed: 142 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,20 @@ struct ap_queue_status {
5353
*/
5454
static inline bool ap_instructions_available(void)
5555
{
56-
register unsigned long reg0 asm ("0") = AP_MKQID(0, 0);
57-
register unsigned long reg1 asm ("1") = 0;
58-
register unsigned long reg2 asm ("2") = 0;
56+
unsigned long reg0 = AP_MKQID(0, 0);
57+
unsigned long reg1 = 0;
5958

6059
asm volatile(
61-
" .long 0xb2af0000\n" /* PQAP(TAPQ) */
62-
"0: la %0,1\n"
60+
" lgr 0,%[reg0]\n" /* qid into gr0 */
61+
" lghi 1,0\n" /* 0 into gr1 */
62+
" lghi 2,0\n" /* 0 into gr2 */
63+
" .long 0xb2af0000\n" /* PQAP(TAPQ) */
64+
"0: la %[reg1],1\n" /* 1 into reg1 */
6365
"1:\n"
6466
EX_TABLE(0b, 1b)
65-
: "+d" (reg1), "+d" (reg2)
66-
: "d" (reg0)
67-
: "cc");
67+
: [reg1] "+&d" (reg1)
68+
: [reg0] "d" (reg0)
69+
: "cc", "0", "1", "2");
6870
return reg1 != 0;
6971
}
7072

@@ -77,14 +79,18 @@ static inline bool ap_instructions_available(void)
7779
*/
7880
static inline struct ap_queue_status ap_tapq(ap_qid_t qid, unsigned long *info)
7981
{
80-
register unsigned long reg0 asm ("0") = qid;
81-
register struct ap_queue_status reg1 asm ("1");
82-
register unsigned long reg2 asm ("2");
83-
84-
asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
85-
: "=d" (reg1), "=d" (reg2)
86-
: "d" (reg0)
87-
: "cc");
82+
struct ap_queue_status reg1;
83+
unsigned long reg2;
84+
85+
asm volatile(
86+
" lgr 0,%[qid]\n" /* qid into gr0 */
87+
" lghi 2,0\n" /* 0 into gr2 */
88+
" .long 0xb2af0000\n" /* PQAP(TAPQ) */
89+
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
90+
" lgr %[reg2],2\n" /* gr2 into reg2 */
91+
: [reg1] "=&d" (reg1), [reg2] "=&d" (reg2)
92+
: [qid] "d" (qid)
93+
: "cc", "0", "1", "2");
8894
if (info)
8995
*info = reg2;
9096
return reg1;
@@ -115,14 +121,16 @@ static inline struct ap_queue_status ap_test_queue(ap_qid_t qid,
115121
*/
116122
static inline struct ap_queue_status ap_rapq(ap_qid_t qid)
117123
{
118-
register unsigned long reg0 asm ("0") = qid | (1UL << 24);
119-
register struct ap_queue_status reg1 asm ("1");
124+
unsigned long reg0 = qid | (1UL << 24); /* fc 1UL is RAPQ */
125+
struct ap_queue_status reg1;
120126

121127
asm volatile(
122-
".long 0xb2af0000" /* PQAP(RAPQ) */
123-
: "=d" (reg1)
124-
: "d" (reg0)
125-
: "cc");
128+
" lgr 0,%[reg0]\n" /* qid arg into gr0 */
129+
" .long 0xb2af0000\n" /* PQAP(RAPQ) */
130+
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
131+
: [reg1] "=&d" (reg1)
132+
: [reg0] "d" (reg0)
133+
: "cc", "0", "1");
126134
return reg1;
127135
}
128136

@@ -134,14 +142,16 @@ static inline struct ap_queue_status ap_rapq(ap_qid_t qid)
134142
*/
135143
static inline struct ap_queue_status ap_zapq(ap_qid_t qid)
136144
{
137-
register unsigned long reg0 asm ("0") = qid | (2UL << 24);
138-
register struct ap_queue_status reg1 asm ("1");
145+
unsigned long reg0 = qid | (2UL << 24); /* fc 2UL is ZAPQ */
146+
struct ap_queue_status reg1;
139147

140148
asm volatile(
141-
".long 0xb2af0000" /* PQAP(ZAPQ) */
142-
: "=d" (reg1)
143-
: "d" (reg0)
144-
: "cc");
149+
" lgr 0,%[reg0]\n" /* qid arg into gr0 */
150+
" .long 0xb2af0000\n" /* PQAP(ZAPQ) */
151+
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
152+
: [reg1] "=&d" (reg1)
153+
: [reg0] "d" (reg0)
154+
: "cc", "0", "1");
145155
return reg1;
146156
}
147157

@@ -172,18 +182,20 @@ struct ap_config_info {
172182
*/
173183
static inline int ap_qci(struct ap_config_info *config)
174184
{
175-
register unsigned long reg0 asm ("0") = 4UL << 24;
176-
register unsigned long reg1 asm ("1") = -EOPNOTSUPP;
177-
register struct ap_config_info *reg2 asm ("2") = config;
185+
unsigned long reg0 = 4UL << 24; /* fc 4UL is QCI */
186+
unsigned long reg1 = -EOPNOTSUPP;
187+
struct ap_config_info *reg2 = config;
178188

179189
asm volatile(
180-
".long 0xb2af0000\n" /* PQAP(QCI) */
181-
"0: la %0,0\n"
190+
" lgr 0,%[reg0]\n" /* QCI fc into gr0 */
191+
" lgr 2,%[reg2]\n" /* ptr to config into gr2 */
192+
" .long 0xb2af0000\n" /* PQAP(QCI) */
193+
"0: la %[reg1],0\n" /* good case, QCI fc available */
182194
"1:\n"
183195
EX_TABLE(0b, 1b)
184-
: "+d" (reg1)
185-
: "d" (reg0), "d" (reg2)
186-
: "cc", "memory");
196+
: [reg1] "+&d" (reg1)
197+
: [reg0] "d" (reg0), [reg2] "d" (reg2)
198+
: "cc", "memory", "0", "2");
187199

188200
return reg1;
189201
}
@@ -220,21 +232,25 @@ static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
220232
struct ap_qirq_ctrl qirqctrl,
221233
void *ind)
222234
{
223-
register unsigned long reg0 asm ("0") = qid | (3UL << 24);
224-
register union {
235+
unsigned long reg0 = qid | (3UL << 24); /* fc 3UL is AQIC */
236+
union {
225237
unsigned long value;
226238
struct ap_qirq_ctrl qirqctrl;
227239
struct ap_queue_status status;
228-
} reg1 asm ("1");
229-
register void *reg2 asm ("2") = ind;
240+
} reg1;
241+
void *reg2 = ind;
230242

231243
reg1.qirqctrl = qirqctrl;
232244

233245
asm volatile(
234-
".long 0xb2af0000" /* PQAP(AQIC) */
235-
: "+d" (reg1)
236-
: "d" (reg0), "d" (reg2)
237-
: "cc");
246+
" lgr 0,%[reg0]\n" /* qid param into gr0 */
247+
" lgr 1,%[reg1]\n" /* irq ctrl into gr1 */
248+
" lgr 2,%[reg2]\n" /* ni addr into gr2 */
249+
" .long 0xb2af0000\n" /* PQAP(AQIC) */
250+
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
251+
: [reg1] "+&d" (reg1)
252+
: [reg0] "d" (reg0), [reg2] "d" (reg2)
253+
: "cc", "0", "1", "2");
238254

239255
return reg1.status;
240256
}
@@ -268,21 +284,24 @@ union ap_qact_ap_info {
268284
static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
269285
union ap_qact_ap_info *apinfo)
270286
{
271-
register unsigned long reg0 asm ("0") = qid | (5UL << 24)
272-
| ((ifbit & 0x01) << 22);
273-
register union {
287+
unsigned long reg0 = qid | (5UL << 24) | ((ifbit & 0x01) << 22);
288+
union {
274289
unsigned long value;
275290
struct ap_queue_status status;
276-
} reg1 asm ("1");
277-
register unsigned long reg2 asm ("2");
291+
} reg1;
292+
unsigned long reg2;
278293

279294
reg1.value = apinfo->val;
280295

281296
asm volatile(
282-
".long 0xb2af0000" /* PQAP(QACT) */
283-
: "+d" (reg1), "=d" (reg2)
284-
: "d" (reg0)
285-
: "cc");
297+
" lgr 0,%[reg0]\n" /* qid param into gr0 */
298+
" lgr 1,%[reg1]\n" /* qact in info into gr1 */
299+
" .long 0xb2af0000\n" /* PQAP(QACT) */
300+
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
301+
" lgr %[reg2],2\n" /* qact out info into reg2 */
302+
: [reg1] "+&d" (reg1), [reg2] "=&d" (reg2)
303+
: [reg0] "d" (reg0)
304+
: "cc", "0", "1", "2");
286305
apinfo->val = reg2;
287306
return reg1.status;
288307
}
@@ -303,19 +322,24 @@ static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
303322
unsigned long long psmid,
304323
void *msg, size_t length)
305324
{
306-
register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
307-
register struct ap_queue_status reg1 asm ("1");
308-
register unsigned long reg2 asm ("2") = (unsigned long) msg;
309-
register unsigned long reg3 asm ("3") = (unsigned long) length;
310-
register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
311-
register unsigned long reg5 asm ("5") = psmid & 0xffffffff;
325+
unsigned long reg0 = qid | 0x40000000UL; /* 0x4... is last msg part */
326+
union register_pair nqap_r1, nqap_r2;
327+
struct ap_queue_status reg1;
328+
329+
nqap_r1.even = (unsigned int)(psmid >> 32);
330+
nqap_r1.odd = psmid & 0xffffffff;
331+
nqap_r2.even = (unsigned long)msg;
332+
nqap_r2.odd = (unsigned long)length;
312333

313334
asm volatile (
314-
"0: .long 0xb2ad0042\n" /* NQAP */
315-
" brc 2,0b"
316-
: "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
317-
: "d" (reg4), "d" (reg5)
318-
: "cc", "memory");
335+
" lgr 0,%[reg0]\n" /* qid param in gr0 */
336+
"0: .insn rre,0xb2ad0000,%[nqap_r1],%[nqap_r2]\n"
337+
" brc 2,0b\n" /* handle partial completion */
338+
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
339+
: [reg0] "+&d" (reg0), [reg1] "=&d" (reg1),
340+
[nqap_r2] "+&d" (nqap_r2.pair)
341+
: [nqap_r1] "d" (nqap_r1.pair)
342+
: "cc", "memory", "0", "1");
319343
return reg1;
320344
}
321345

@@ -325,6 +349,8 @@ static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
325349
* @psmid: Pointer to program supplied message identifier
326350
* @msg: The message text
327351
* @length: The message length
352+
* @reslength: Resitual length on return
353+
* @resgr0: input: gr0 value (only used if != 0), output: resitual gr0 content
328354
*
329355
* Returns AP queue status structure.
330356
* Condition code 1 on DQAP means the receive has taken place
@@ -336,27 +362,65 @@ static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
336362
* Note that gpr2 is used by the DQAP instruction to keep track of
337363
* any 'residual' length, in case the instruction gets interrupted.
338364
* Hence it gets zeroed before the instruction.
365+
* If the message does not fit into the buffer, this function will
366+
* return with a truncated message and the reply in the firmware queue
367+
* is not removed. This is indicated to the caller with an
368+
* ap_queue_status response_code value of all bits on (0xFF) and (if
369+
* the reslength ptr is given) the remaining length is stored in
370+
* *reslength and (if the resgr0 ptr is given) the updated gr0 value
371+
* for further processing of this msg entry is stored in *resgr0. The
372+
* caller needs to detect this situation and should invoke ap_dqap
373+
* with a valid resgr0 ptr and a value in there != 0 to indicate that
374+
* *resgr0 is to be used instead of qid to further process this entry.
339375
*/
340376
static inline struct ap_queue_status ap_dqap(ap_qid_t qid,
341377
unsigned long long *psmid,
342-
void *msg, size_t length)
378+
void *msg, size_t length,
379+
size_t *reslength,
380+
unsigned long *resgr0)
343381
{
344-
register unsigned long reg0 asm("0") = qid | 0x80000000UL;
345-
register struct ap_queue_status reg1 asm ("1");
346-
register unsigned long reg2 asm("2") = 0UL;
347-
register unsigned long reg4 asm("4") = (unsigned long) msg;
348-
register unsigned long reg5 asm("5") = (unsigned long) length;
349-
register unsigned long reg6 asm("6") = 0UL;
350-
register unsigned long reg7 asm("7") = 0UL;
382+
unsigned long reg0 = resgr0 && *resgr0 ? *resgr0 : qid | 0x80000000UL;
383+
struct ap_queue_status reg1;
384+
unsigned long reg2;
385+
union register_pair rp1, rp2;
351386

387+
rp1.even = 0UL;
388+
rp1.odd = 0UL;
389+
rp2.even = (unsigned long)msg;
390+
rp2.odd = (unsigned long)length;
352391

353392
asm volatile(
354-
"0: .long 0xb2ae0064\n" /* DQAP */
355-
" brc 6,0b\n"
356-
: "+d" (reg0), "=d" (reg1), "+d" (reg2),
357-
"+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7)
358-
: : "cc", "memory");
359-
*psmid = (((unsigned long long) reg6) << 32) + reg7;
393+
" lgr 0,%[reg0]\n" /* qid param into gr0 */
394+
" lghi 2,0\n" /* 0 into gr2 (res length) */
395+
"0: ltgr %N[rp2],%N[rp2]\n" /* check buf len */
396+
" jz 2f\n" /* go out if buf len is 0 */
397+
"1: .insn rre,0xb2ae0000,%[rp1],%[rp2]\n"
398+
" brc 6,0b\n" /* handle partial complete */
399+
"2: lgr %[reg0],0\n" /* gr0 (qid + info) into reg0 */
400+
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
401+
" lgr %[reg2],2\n" /* gr2 (res length) into reg2 */
402+
: [reg0] "+&d" (reg0), [reg1] "=&d" (reg1), [reg2] "=&d" (reg2),
403+
[rp1] "+&d" (rp1.pair), [rp2] "+&d" (rp2.pair)
404+
:
405+
: "cc", "memory", "0", "1", "2");
406+
407+
if (reslength)
408+
*reslength = reg2;
409+
if (reg2 != 0 && rp2.odd == 0) {
410+
/*
411+
* Partially complete, status in gr1 is not set.
412+
* Signal the caller that this dqap is only partially received
413+
* with a special status response code 0xFF and *resgr0 updated
414+
*/
415+
reg1.response_code = 0xFF;
416+
if (resgr0)
417+
*resgr0 = reg0;
418+
} else {
419+
*psmid = (((unsigned long long)rp1.even) << 32) + rp1.odd;
420+
if (resgr0)
421+
*resgr0 = 0;
422+
}
423+
360424
return reg1;
361425
}
362426

0 commit comments

Comments
 (0)