Skip to content

Commit 012a224

Browse files
Nico Boehrhcahca
authored andcommitted
s390/uaccess: introduce bit field for OAC specifier
Previously, we've used magic values to specify the OAC (operand-access control) for mvcos. Instead we introduce a bit field for it. When using a bit field, we cannot use an immediate value with K constraint anymore, since GCC older than 10 doesn't recognize the bit field union as a compile time constant. To make things work with older compilers, load the OAC value through a register. Bloat-o-meter reports a slight increase in kernel size with this change: Total: Before=15692135, After=15693015, chg +0.01% Signed-off-by: Nico Boehr <nrb@linux.ibm.com> Co-developed-by: Janis Schoetterl-Glausch <scgl@linux.ibm.com> Signed-off-by: Janis Schoetterl-Glausch <scgl@linux.ibm.com> Link: https://lore.kernel.org/r/20220111100003.743116-1-scgl@linux.ibm.com Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Christian Borntraeger <borntraeger@linux.ibm.com> Cc: Vasily Gorbik <gor@linux.ibm.com> Cc: Sven Schnelle <svens@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
1 parent 745f5d2 commit 012a224

2 files changed

Lines changed: 95 additions & 49 deletions

File tree

arch/s390/include/asm/uaccess.h

Lines changed: 77 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -49,51 +49,85 @@ int __get_user_bad(void) __attribute__((noreturn));
4949

5050
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
5151

52-
#define __put_get_user_asm(to, from, size, insn) \
53-
({ \
54-
int __rc; \
55-
\
56-
asm volatile( \
57-
insn " 0,%[spec]\n" \
58-
"0: mvcos %[_to],%[_from],%[_size]\n" \
59-
"1: xr %[rc],%[rc]\n" \
60-
"2:\n" \
61-
".pushsection .fixup, \"ax\"\n" \
62-
"3: lhi %[rc],%[retval]\n" \
63-
" jg 2b\n" \
64-
".popsection\n" \
65-
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
66-
: [rc] "=&d" (__rc), [_to] "+Q" (*(to)) \
67-
: [_size] "d" (size), [_from] "Q" (*(from)), \
68-
[retval] "K" (-EFAULT), [spec] "K" (0x81UL) \
69-
: "cc", "0"); \
70-
__rc; \
52+
union oac {
53+
unsigned int val;
54+
struct {
55+
struct {
56+
unsigned short key : 4;
57+
unsigned short : 4;
58+
unsigned short as : 2;
59+
unsigned short : 4;
60+
unsigned short k : 1;
61+
unsigned short a : 1;
62+
} oac1;
63+
struct {
64+
unsigned short key : 4;
65+
unsigned short : 4;
66+
unsigned short as : 2;
67+
unsigned short : 4;
68+
unsigned short k : 1;
69+
unsigned short a : 1;
70+
} oac2;
71+
};
72+
};
73+
74+
#define __put_get_user_asm(to, from, size, oac_spec) \
75+
({ \
76+
int __rc; \
77+
\
78+
asm volatile( \
79+
" lr 0,%[spec]\n" \
80+
"0: mvcos %[_to],%[_from],%[_size]\n" \
81+
"1: xr %[rc],%[rc]\n" \
82+
"2:\n" \
83+
".pushsection .fixup, \"ax\"\n" \
84+
"3: lhi %[rc],%[retval]\n" \
85+
" jg 2b\n" \
86+
".popsection\n" \
87+
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
88+
: [rc] "=&d" (__rc), [_to] "+Q" (*(to)) \
89+
: [_size] "d" (size), [_from] "Q" (*(from)), \
90+
[retval] "K" (-EFAULT), [spec] "d" (oac_spec.val) \
91+
: "cc", "0"); \
92+
__rc; \
7193
})
7294

95+
#define __put_user_asm(to, from, size) \
96+
__put_get_user_asm(to, from, size, ((union oac) { \
97+
.oac1.as = PSW_BITS_AS_SECONDARY, \
98+
.oac1.a = 1 \
99+
}))
100+
101+
#define __get_user_asm(to, from, size) \
102+
__put_get_user_asm(to, from, size, ((union oac) { \
103+
.oac2.as = PSW_BITS_AS_SECONDARY, \
104+
.oac2.a = 1 \
105+
})) \
106+
73107
static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
74108
{
75109
int rc;
76110

77111
switch (size) {
78112
case 1:
79-
rc = __put_get_user_asm((unsigned char __user *)ptr,
80-
(unsigned char *)x,
81-
size, "llilh");
113+
rc = __put_user_asm((unsigned char __user *)ptr,
114+
(unsigned char *)x,
115+
size);
82116
break;
83117
case 2:
84-
rc = __put_get_user_asm((unsigned short __user *)ptr,
85-
(unsigned short *)x,
86-
size, "llilh");
118+
rc = __put_user_asm((unsigned short __user *)ptr,
119+
(unsigned short *)x,
120+
size);
87121
break;
88122
case 4:
89-
rc = __put_get_user_asm((unsigned int __user *)ptr,
90-
(unsigned int *)x,
91-
size, "llilh");
123+
rc = __put_user_asm((unsigned int __user *)ptr,
124+
(unsigned int *)x,
125+
size);
92126
break;
93127
case 8:
94-
rc = __put_get_user_asm((unsigned long __user *)ptr,
95-
(unsigned long *)x,
96-
size, "llilh");
128+
rc = __put_user_asm((unsigned long __user *)ptr,
129+
(unsigned long *)x,
130+
size);
97131
break;
98132
default:
99133
__put_user_bad();
@@ -108,24 +142,24 @@ static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsign
108142

109143
switch (size) {
110144
case 1:
111-
rc = __put_get_user_asm((unsigned char *)x,
112-
(unsigned char __user *)ptr,
113-
size, "lghi");
145+
rc = __get_user_asm((unsigned char *)x,
146+
(unsigned char __user *)ptr,
147+
size);
114148
break;
115149
case 2:
116-
rc = __put_get_user_asm((unsigned short *)x,
117-
(unsigned short __user *)ptr,
118-
size, "lghi");
150+
rc = __get_user_asm((unsigned short *)x,
151+
(unsigned short __user *)ptr,
152+
size);
119153
break;
120154
case 4:
121-
rc = __put_get_user_asm((unsigned int *)x,
122-
(unsigned int __user *)ptr,
123-
size, "lghi");
155+
rc = __get_user_asm((unsigned int *)x,
156+
(unsigned int __user *)ptr,
157+
size);
124158
break;
125159
case 8:
126-
rc = __put_get_user_asm((unsigned long *)x,
127-
(unsigned long __user *)ptr,
128-
size, "lghi");
160+
rc = __get_user_asm((unsigned long *)x,
161+
(unsigned long __user *)ptr,
162+
size);
129163
break;
130164
default:
131165
__get_user_bad();

arch/s390/lib/uaccess.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,14 @@ static inline unsigned long copy_from_user_mvcos(void *x, const void __user *ptr
6262
unsigned long size)
6363
{
6464
unsigned long tmp1, tmp2;
65+
union oac spec = {
66+
.oac2.as = PSW_BITS_AS_SECONDARY,
67+
.oac2.a = 1,
68+
};
6569

6670
tmp1 = -4096UL;
6771
asm volatile(
68-
" lghi 0,%[spec]\n"
72+
" lr 0,%[spec]\n"
6973
"0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n"
7074
"6: jz 4f\n"
7175
"1: algr %0,%3\n"
@@ -84,7 +88,7 @@ static inline unsigned long copy_from_user_mvcos(void *x, const void __user *ptr
8488
"5:\n"
8589
EX_TABLE(0b,2b) EX_TABLE(3b,5b) EX_TABLE(6b,2b) EX_TABLE(7b,5b)
8690
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
87-
: [spec] "K" (0x81UL)
91+
: [spec] "d" (spec.val)
8892
: "cc", "memory", "0");
8993
return size;
9094
}
@@ -135,10 +139,14 @@ static inline unsigned long copy_to_user_mvcos(void __user *ptr, const void *x,
135139
unsigned long size)
136140
{
137141
unsigned long tmp1, tmp2;
142+
union oac spec = {
143+
.oac1.as = PSW_BITS_AS_SECONDARY,
144+
.oac1.a = 1,
145+
};
138146

139147
tmp1 = -4096UL;
140148
asm volatile(
141-
" llilh 0,%[spec]\n"
149+
" lr 0,%[spec]\n"
142150
"0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n"
143151
"6: jz 4f\n"
144152
"1: algr %0,%3\n"
@@ -157,7 +165,7 @@ static inline unsigned long copy_to_user_mvcos(void __user *ptr, const void *x,
157165
"5:\n"
158166
EX_TABLE(0b,2b) EX_TABLE(3b,5b) EX_TABLE(6b,2b) EX_TABLE(7b,5b)
159167
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
160-
: [spec] "K" (0x81UL)
168+
: [spec] "d" (spec.val)
161169
: "cc", "memory", "0");
162170
return size;
163171
}
@@ -207,10 +215,14 @@ EXPORT_SYMBOL(raw_copy_to_user);
207215
static inline unsigned long clear_user_mvcos(void __user *to, unsigned long size)
208216
{
209217
unsigned long tmp1, tmp2;
218+
union oac spec = {
219+
.oac1.as = PSW_BITS_AS_SECONDARY,
220+
.oac1.a = 1,
221+
};
210222

211223
tmp1 = -4096UL;
212224
asm volatile(
213-
" llilh 0,%[spec]\n"
225+
" lr 0,%[spec]\n"
214226
"0: .insn ss,0xc80000000000,0(%0,%1),0(%4),0\n"
215227
" jz 4f\n"
216228
"1: algr %0,%2\n"
@@ -228,7 +240,7 @@ static inline unsigned long clear_user_mvcos(void __user *to, unsigned long size
228240
"5:\n"
229241
EX_TABLE(0b,2b) EX_TABLE(3b,5b)
230242
: "+a" (size), "+a" (to), "+a" (tmp1), "=a" (tmp2)
231-
: "a" (empty_zero_page), [spec] "K" (0x81UL)
243+
: "a" (empty_zero_page), [spec] "d" (spec.val)
232244
: "cc", "memory", "0");
233245
return size;
234246
}

0 commit comments

Comments
 (0)