From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4CC4C3526F for ; Fri, 11 Feb 2022 18:22:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347765AbiBKSWd (ORCPT ); Fri, 11 Feb 2022 13:22:33 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33038 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233971AbiBKSW2 (ORCPT ); Fri, 11 Feb 2022 13:22:28 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F1164D4A; Fri, 11 Feb 2022 10:22:25 -0800 (PST) Received: from pps.filterd (m0098419.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BGHToL014475; Fri, 11 Feb 2022 18:22:23 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=2o2UZ0ZdzvYVh487Vo5zB5Y9E5/+0N6KuU9B4oTnd4o=; b=YSDxW7RiYIZGiNdY7H4Yek6XQOCz4VH5HDWivgB39LulveOMpMnRNTyAlzCcSRDYzGDv CI1T1Bfc45NDfR4h4gqA23hvziWcy6FQVbnNPLjdFlyR8nadBWO7qscOXwEnXtUv8Vak +Z8nPYVFwzcGIT4Y/tQnOpCWYeAwkNHYlMtZfD8gCQmvnEuACh9lU97Q+xxsbIpCSh2A gftbxM4AotWa0NkWOw0+JIXdu31FR7gQ0T7m2M8NoQGna8Hb2iMSoxabBIDyOwbs9TVl WUoxcIqvE+ThG1zjvE7Yc9UVDd17VdycP+6BWPiOHwY/FiLyECjAPw+qnCkpzPYTwuBw vg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3e5fx3grd0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:23 +0000 Received: from m0098419.ppops.net (m0098419.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BGq18Q001811; Fri, 11 Feb 2022 18:22:23 GMT Received: from ppma03ams.nl.ibm.com (62.31.33a9.ip4.static.sl-reverse.com [169.51.49.98]) by mx0b-001b2d01.pphosted.com with ESMTP id 3e5fx3grch-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:22 +0000 Received: from pps.filterd (ppma03ams.nl.ibm.com [127.0.0.1]) by ppma03ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BID5qD032628; Fri, 11 Feb 2022 18:22:21 GMT Received: from b06cxnps4076.portsmouth.uk.ibm.com (d06relay13.portsmouth.uk.ibm.com [9.149.109.198]) by ppma03ams.nl.ibm.com with ESMTP id 3e1gvac2vy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:21 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIMI0426280360 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:22:18 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E6DCD52050; Fri, 11 Feb 2022 18:22:17 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id 7D40752059; Fri, 11 Feb 2022 18:22:17 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 01/10] s390/uaccess: Add copy_from/to_user_key functions Date: Fri, 11 Feb 2022 19:22:06 +0100 Message-Id: <20220211182215.2730017-2-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-GUID: CeyMA6dqLQ_LA-CxeJEqf5YZfJl-WnYA X-Proofpoint-ORIG-GUID: RbsQg6V1UxQgn6PQgv8nbY8fCj8yKOhO X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 clxscore=1015 bulkscore=0 impostorscore=0 phishscore=0 spamscore=0 suspectscore=0 priorityscore=1501 adultscore=0 malwarescore=0 mlxscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add copy_from/to_user_key functions, which perform storage key checking. These functions can be used by KVM for emulating instructions that need to be key checked. These functions differ from their non _key counterparts in include/linux/uaccess.h only in the additional key argument and must be kept in sync with those. Since the existing uaccess implementation on s390 makes use of move instructions that support having an additional access key supplied, we can implement raw_copy_from/to_user_key by enhancing the existing implementation. Signed-off-by: Janis Schoetterl-Glausch Acked-by: Heiko Carstens Reviewed-by: Christian Borntraeger Acked-by: Janosch Frank Reviewed-by: Claudio Imbrenda --- arch/s390/include/asm/uaccess.h | 22 +++++++++ arch/s390/lib/uaccess.c | 81 +++++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 18 deletions(-) diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uacces= s.h index d74e26b48604..ba1bcb91af95 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -44,6 +44,28 @@ raw_copy_to_user(void __user *to, const void *from, unsi= gned long n); #define INLINE_COPY_TO_USER #endif =20 +unsigned long __must_check +_copy_from_user_key(void *to, const void __user *from, unsigned long n, un= signed long key); + +static __always_inline unsigned long __must_check +copy_from_user_key(void *to, const void __user *from, unsigned long n, uns= igned long key) +{ + if (likely(check_copy_size(to, n, false))) + n =3D _copy_from_user_key(to, from, n, key); + return n; +} + +unsigned long __must_check +_copy_to_user_key(void __user *to, const void *from, unsigned long n, unsi= gned long key); + +static __always_inline unsigned long __must_check +copy_to_user_key(void __user *to, const void *from, unsigned long n, unsig= ned long key) +{ + if (likely(check_copy_size(from, n, true))) + n =3D _copy_to_user_key(to, from, n, key); + return n; +} + int __put_user_bad(void) __attribute__((noreturn)); int __get_user_bad(void) __attribute__((noreturn)); =20 diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c index 8a5d21461889..b709239feb5d 100644 --- a/arch/s390/lib/uaccess.c +++ b/arch/s390/lib/uaccess.c @@ -59,11 +59,13 @@ static inline int copy_with_mvcos(void) #endif =20 static inline unsigned long copy_from_user_mvcos(void *x, const void __use= r *ptr, - unsigned long size) + unsigned long size, unsigned long key) { unsigned long tmp1, tmp2; union oac spec =3D { + .oac2.key =3D key, .oac2.as =3D PSW_BITS_AS_SECONDARY, + .oac2.k =3D 1, .oac2.a =3D 1, }; =20 @@ -94,19 +96,19 @@ static inline unsigned long copy_from_user_mvcos(void *= x, const void __user *ptr } =20 static inline unsigned long copy_from_user_mvcp(void *x, const void __user= *ptr, - unsigned long size) + unsigned long size, unsigned long key) { unsigned long tmp1, tmp2; =20 tmp1 =3D -256UL; asm volatile( " sacf 0\n" - "0: mvcp 0(%0,%2),0(%1),%3\n" + "0: mvcp 0(%0,%2),0(%1),%[key]\n" "7: jz 5f\n" "1: algr %0,%3\n" " la %1,256(%1)\n" " la %2,256(%2)\n" - "2: mvcp 0(%0,%2),0(%1),%3\n" + "2: mvcp 0(%0,%2),0(%1),%[key]\n" "8: jnz 1b\n" " j 5f\n" "3: la %4,255(%1)\n" /* %4 =3D ptr + 255 */ @@ -115,7 +117,7 @@ static inline unsigned long copy_from_user_mvcp(void *x= , const void __user *ptr, " slgr %4,%1\n" " clgr %0,%4\n" /* copy crosses next page boundary? */ " jnh 6f\n" - "4: mvcp 0(%4,%2),0(%1),%3\n" + "4: mvcp 0(%4,%2),0(%1),%[key]\n" "9: slgr %0,%4\n" " j 6f\n" "5: slgr %0,%0\n" @@ -123,24 +125,49 @@ static inline unsigned long copy_from_user_mvcp(void = *x, const void __user *ptr, EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b) EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b) : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=3Da" (tmp2) - : : "cc", "memory"); + : [key] "d" (key << 4) + : "cc", "memory"); return size; } =20 -unsigned long raw_copy_from_user(void *to, const void __user *from, unsign= ed long n) +static unsigned long raw_copy_from_user_key(void *to, const void __user *f= rom, + unsigned long n, unsigned long key) { if (copy_with_mvcos()) - return copy_from_user_mvcos(to, from, n); - return copy_from_user_mvcp(to, from, n); + return copy_from_user_mvcos(to, from, n, key); + return copy_from_user_mvcp(to, from, n, key); +} + +unsigned long raw_copy_from_user(void *to, const void __user *from, unsign= ed long n) +{ + return raw_copy_from_user_key(to, from, n, 0); } EXPORT_SYMBOL(raw_copy_from_user); =20 +unsigned long _copy_from_user_key(void *to, const void __user *from, + unsigned long n, unsigned long key) +{ + unsigned long res =3D n; + + might_fault(); + if (!should_fail_usercopy()) { + instrument_copy_from_user(to, from, n); + res =3D raw_copy_from_user_key(to, from, n, key); + } + if (unlikely(res)) + memset(to + (n - res), 0, res); + return res; +} +EXPORT_SYMBOL(_copy_from_user_key); + static inline unsigned long copy_to_user_mvcos(void __user *ptr, const voi= d *x, - unsigned long size) + unsigned long size, unsigned long key) { unsigned long tmp1, tmp2; union oac spec =3D { + .oac1.key =3D key, .oac1.as =3D PSW_BITS_AS_SECONDARY, + .oac1.k =3D 1, .oac1.a =3D 1, }; =20 @@ -171,19 +198,19 @@ static inline unsigned long copy_to_user_mvcos(void _= _user *ptr, const void *x, } =20 static inline unsigned long copy_to_user_mvcs(void __user *ptr, const void= *x, - unsigned long size) + unsigned long size, unsigned long key) { unsigned long tmp1, tmp2; =20 tmp1 =3D -256UL; asm volatile( " sacf 0\n" - "0: mvcs 0(%0,%1),0(%2),%3\n" + "0: mvcs 0(%0,%1),0(%2),%[key]\n" "7: jz 5f\n" "1: algr %0,%3\n" " la %1,256(%1)\n" " la %2,256(%2)\n" - "2: mvcs 0(%0,%1),0(%2),%3\n" + "2: mvcs 0(%0,%1),0(%2),%[key]\n" "8: jnz 1b\n" " j 5f\n" "3: la %4,255(%1)\n" /* %4 =3D ptr + 255 */ @@ -192,7 +219,7 @@ static inline unsigned long copy_to_user_mvcs(void __us= er *ptr, const void *x, " slgr %4,%1\n" " clgr %0,%4\n" /* copy crosses next page boundary? */ " jnh 6f\n" - "4: mvcs 0(%4,%1),0(%2),%3\n" + "4: mvcs 0(%4,%1),0(%2),%[key]\n" "9: slgr %0,%4\n" " j 6f\n" "5: slgr %0,%0\n" @@ -200,18 +227,36 @@ static inline unsigned long copy_to_user_mvcs(void __= user *ptr, const void *x, EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b) EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b) : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=3Da" (tmp2) - : : "cc", "memory"); + : [key] "d" (key << 4) + : "cc", "memory"); return size; } =20 -unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned= long n) +static unsigned long raw_copy_to_user_key(void __user *to, const void *fro= m, + unsigned long n, unsigned long key) { if (copy_with_mvcos()) - return copy_to_user_mvcos(to, from, n); - return copy_to_user_mvcs(to, from, n); + return copy_to_user_mvcos(to, from, n, key); + return copy_to_user_mvcs(to, from, n, key); +} + +unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned= long n) +{ + return raw_copy_to_user_key(to, from, n, 0); } EXPORT_SYMBOL(raw_copy_to_user); =20 +unsigned long _copy_to_user_key(void __user *to, const void *from, + unsigned long n, unsigned long key) +{ + might_fault(); + if (should_fail_usercopy()) + return n; + instrument_copy_to_user(to, from, n); + return raw_copy_to_user_key(to, from, n, key); +} +EXPORT_SYMBOL(_copy_to_user_key); + static inline unsigned long clear_user_mvcos(void __user *to, unsigned lon= g size) { unsigned long tmp1, tmp2; --=20 2.32.0 From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23DADC433F5 for ; Fri, 11 Feb 2022 18:22:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352713AbiBKSWn (ORCPT ); Fri, 11 Feb 2022 13:22:43 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33056 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351393AbiBKSW2 (ORCPT ); Fri, 11 Feb 2022 13:22:28 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5180213A; Fri, 11 Feb 2022 10:22:26 -0800 (PST) Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BGiCo9019489; Fri, 11 Feb 2022 18:22:24 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=w9/COitnFblZJTuY7BvWW//7i9RNT2wY8ICV2NGSaUo=; b=ayWPHw0gqnHvGckW2tTbzvsBEI6MP2HHNsSvse87laP6Y9FHbn9megCVSzPO5A1mSELN tXdHzOlflOrSv95KbMTtmp6YMCb3FIP6IP8fsoESry34KSttW+7EiMpkOj1N5b5/6RFZ L/cjsBH3/FWUH46Z1/0MrJRDo/SCe1oEIV9y1D3wcXmrZGUDLx7/mTuq7UHN3Y2NRJlr JrWHuCqCa7G3Mjc12kYMpoiXJtmq1AbcggOMkYxfL+vznV6ZHkd9eEUCmWldP60iQKaW VElGSKD7CJuyhppP3DYLJWi0901ow10KWHm2MBopvfabjjqK6gppg0MairL2X0ARi9pZ kA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3e5tf63g13-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:24 +0000 Received: from m0098414.ppops.net (m0098414.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BI6286026990; Fri, 11 Feb 2022 18:22:23 GMT Received: from ppma04ams.nl.ibm.com (63.31.33a9.ip4.static.sl-reverse.com [169.51.49.99]) by mx0b-001b2d01.pphosted.com with ESMTP id 3e5tf63g0k-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:23 +0000 Received: from pps.filterd (ppma04ams.nl.ibm.com [127.0.0.1]) by ppma04ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BICJLp020539; Fri, 11 Feb 2022 18:22:22 GMT Received: from b06cxnps4076.portsmouth.uk.ibm.com (d06relay13.portsmouth.uk.ibm.com [9.149.109.198]) by ppma04ams.nl.ibm.com with ESMTP id 3e1gva44db-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:21 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIMIVg41746798 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:22:18 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5D8BC5204F; Fri, 11 Feb 2022 18:22:18 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id E8BE152063; Fri, 11 Feb 2022 18:22:17 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 02/10] KVM: s390: Honor storage keys when accessing guest memory Date: Fri, 11 Feb 2022 19:22:07 +0100 Message-Id: <20220211182215.2730017-3-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-GUID: 8RCo5Nb15LZsXbmUsQLKAohRZFljF-G8 X-Proofpoint-ORIG-GUID: I0Sh0Vyc_E86TYUeyU4nhsdHkbckGnQA X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 priorityscore=1501 mlxscore=0 suspectscore=0 adultscore=0 impostorscore=0 malwarescore=0 spamscore=0 mlxlogscore=999 bulkscore=0 clxscore=1015 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Storage key checking had not been implemented for instructions emulated by KVM. Implement it by enhancing the functions used for guest access, in particular those making use of access_guest which has been renamed to access_guest_with_key. Accesses via access_guest_real should not be key checked. For actual accesses, key checking is done by copy_from/to_user_key (which internally uses MVCOS/MVCP/MVCS). In cases where accessibility is checked without an actual access, this is performed by getting the storage key and checking if the access key matches. In both cases, if applicable, storage and fetch protection override are honored. Signed-off-by: Janis Schoetterl-Glausch Reviewed-by: Janosch Frank Reviewed-by: Christian Borntraeger Reviewed-by: Claudio Imbrenda --- arch/s390/include/asm/ctl_reg.h | 2 + arch/s390/include/asm/page.h | 2 + arch/s390/kvm/gaccess.c | 187 ++++++++++++++++++++++++++++++-- arch/s390/kvm/gaccess.h | 77 +++++++++++-- arch/s390/kvm/intercept.c | 12 +- arch/s390/kvm/kvm-s390.c | 4 +- 6 files changed, 253 insertions(+), 31 deletions(-) diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_re= g.h index 04dc65f8901d..c800199a376b 100644 --- a/arch/s390/include/asm/ctl_reg.h +++ b/arch/s390/include/asm/ctl_reg.h @@ -12,6 +12,8 @@ =20 #define CR0_CLOCK_COMPARATOR_SIGN BIT(63 - 10) #define CR0_LOW_ADDRESS_PROTECTION BIT(63 - 35) +#define CR0_FETCH_PROTECTION_OVERRIDE BIT(63 - 38) +#define CR0_STORAGE_PROTECTION_OVERRIDE BIT(63 - 39) #define CR0_EMERGENCY_SIGNAL_SUBMASK BIT(63 - 49) #define CR0_EXTERNAL_CALL_SUBMASK BIT(63 - 50) #define CR0_CLOCK_COMPARATOR_SUBMASK BIT(63 - 52) diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index d98d17a36c7b..cfc4d6fb2385 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -20,6 +20,8 @@ #define PAGE_SIZE _PAGE_SIZE #define PAGE_MASK _PAGE_MASK #define PAGE_DEFAULT_ACC 0 +/* storage-protection override */ +#define PAGE_SPO_ACC 9 #define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4) =20 #define HPAGE_SHIFT 20 diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index 4460808c3b9a..7fca0cff4c12 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -10,6 +10,7 @@ #include #include #include +#include =20 #include #include "kvm-s390.h" @@ -794,6 +795,79 @@ static int low_address_protection_enabled(struct kvm_v= cpu *vcpu, return 1; } =20 +static bool fetch_prot_override_applicable(struct kvm_vcpu *vcpu, enum gac= c_mode mode, + union asce asce) +{ + psw_t *psw =3D &vcpu->arch.sie_block->gpsw; + unsigned long override; + + if (mode =3D=3D GACC_FETCH || mode =3D=3D GACC_IFETCH) { + /* check if fetch protection override enabled */ + override =3D vcpu->arch.sie_block->gcr[0]; + override &=3D CR0_FETCH_PROTECTION_OVERRIDE; + /* not applicable if subject to DAT && private space */ + override =3D override && !(psw_bits(*psw).dat && asce.p); + return override; + } + return false; +} + +static bool fetch_prot_override_applies(unsigned long ga, unsigned int len) +{ + return ga < 2048 && ga + len <=3D 2048; +} + +static bool storage_prot_override_applicable(struct kvm_vcpu *vcpu) +{ + /* check if storage protection override enabled */ + return vcpu->arch.sie_block->gcr[0] & CR0_STORAGE_PROTECTION_OVERRIDE; +} + +static bool storage_prot_override_applies(u8 access_control) +{ + /* matches special storage protection override key (9) -> allow */ + return access_control =3D=3D PAGE_SPO_ACC; +} + +static int vcpu_check_access_key(struct kvm_vcpu *vcpu, u8 access_key, + enum gacc_mode mode, union asce asce, gpa_t gpa, + unsigned long ga, unsigned int len) +{ + u8 storage_key, access_control; + unsigned long hva; + int r; + + /* access key 0 matches any storage key -> allow */ + if (access_key =3D=3D 0) + return 0; + /* + * caller needs to ensure that gfn is accessible, so we can + * assume that this cannot fail + */ + hva =3D gfn_to_hva(vcpu->kvm, gpa_to_gfn(gpa)); + mmap_read_lock(current->mm); + r =3D get_guest_storage_key(current->mm, hva, &storage_key); + mmap_read_unlock(current->mm); + if (r) + return r; + access_control =3D FIELD_GET(_PAGE_ACC_BITS, storage_key); + /* access key matches storage key -> allow */ + if (access_control =3D=3D access_key) + return 0; + if (mode =3D=3D GACC_FETCH || mode =3D=3D GACC_IFETCH) { + /* it is a fetch and fetch protection is off -> allow */ + if (!(storage_key & _PAGE_FP_BIT)) + return 0; + if (fetch_prot_override_applicable(vcpu, mode, asce) && + fetch_prot_override_applies(ga, len)) + return 0; + } + if (storage_prot_override_applicable(vcpu) && + storage_prot_override_applies(access_control)) + return 0; + return PGM_PROTECTION; +} + /** * guest_range_to_gpas() - Calculate guest physical addresses of page frag= ments * covering a logical range @@ -804,6 +878,7 @@ static int low_address_protection_enabled(struct kvm_vc= pu *vcpu, * @len: length of range in bytes * @asce: address-space-control element to use for translation * @mode: access mode + * @access_key: access key to mach the range's storage keys against * * Translate a logical range to a series of guest absolute addresses, * such that the concatenation of page fragments starting at each gpa make= up @@ -830,7 +905,8 @@ static int low_address_protection_enabled(struct kvm_vc= pu *vcpu, */ static int guest_range_to_gpas(struct kvm_vcpu *vcpu, unsigned long ga, u8= ar, unsigned long *gpas, unsigned long len, - const union asce asce, enum gacc_mode mode) + const union asce asce, enum gacc_mode mode, + u8 access_key) { psw_t *psw =3D &vcpu->arch.sie_block->gpsw; unsigned int offset =3D offset_in_page(ga); @@ -857,6 +933,10 @@ static int guest_range_to_gpas(struct kvm_vcpu *vcpu, = unsigned long ga, u8 ar, } if (rc) return trans_exc(vcpu, rc, ga, ar, mode, prot); + rc =3D vcpu_check_access_key(vcpu, access_key, mode, asce, gpa, ga, + fragment_len); + if (rc) + return trans_exc(vcpu, rc, ga, ar, mode, PROT_TYPE_KEYC); if (gpas) *gpas++ =3D gpa; offset =3D 0; @@ -880,16 +960,54 @@ static int access_guest_page(struct kvm *kvm, enum ga= cc_mode mode, gpa_t gpa, return rc; } =20 -int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *dat= a, - unsigned long len, enum gacc_mode mode) +static int +access_guest_page_with_key(struct kvm *kvm, enum gacc_mode mode, gpa_t gpa, + void *data, unsigned int len, u8 access_key) +{ + struct kvm_memory_slot *slot; + bool writable; + gfn_t gfn; + hva_t hva; + int rc; + + gfn =3D gpa >> PAGE_SHIFT; + slot =3D gfn_to_memslot(kvm, gfn); + hva =3D gfn_to_hva_memslot_prot(slot, gfn, &writable); + + if (kvm_is_error_hva(hva)) + return PGM_ADDRESSING; + /* + * Check if it's a ro memslot, even tho that can't occur (they're unsuppo= rted). + * Don't try to actually handle that case. + */ + if (!writable && mode =3D=3D GACC_STORE) + return -EOPNOTSUPP; + hva +=3D offset_in_page(gpa); + if (mode =3D=3D GACC_STORE) + rc =3D copy_to_user_key((void __user *)hva, data, len, access_key); + else + rc =3D copy_from_user_key(data, (void __user *)hva, len, access_key); + if (rc) + return PGM_PROTECTION; + if (mode =3D=3D GACC_STORE) + mark_page_dirty_in_slot(kvm, slot, gfn); + return 0; +} + +int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, + void *data, unsigned long len, enum gacc_mode mode, + u8 access_key) { psw_t *psw =3D &vcpu->arch.sie_block->gpsw; unsigned long nr_pages, idx; unsigned long gpa_array[2]; unsigned int fragment_len; unsigned long *gpas; + enum prot_type prot; int need_ipte_lock; union asce asce; + bool try_storage_prot_override; + bool try_fetch_prot_override; int rc; =20 if (!len) @@ -904,16 +1022,47 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned lon= g ga, u8 ar, void *data, gpas =3D vmalloc(array_size(nr_pages, sizeof(unsigned long))); if (!gpas) return -ENOMEM; + try_fetch_prot_override =3D fetch_prot_override_applicable(vcpu, mode, as= ce); + try_storage_prot_override =3D storage_prot_override_applicable(vcpu); need_ipte_lock =3D psw_bits(*psw).dat && !asce.r; if (need_ipte_lock) ipte_lock(vcpu); - rc =3D guest_range_to_gpas(vcpu, ga, ar, gpas, len, asce, mode); - for (idx =3D 0; idx < nr_pages && !rc; idx++) { + /* + * Since we do the access further down ultimately via a move instruction + * that does key checking and returns an error in case of a protection + * violation, we don't need to do the check during address translation. + * Skip it by passing access key 0, which matches any storage key, + * obviating the need for any further checks. As a result the check is + * handled entirely in hardware on access, we only need to take care to + * forego key protection checking if fetch protection override applies or + * retry with the special key 9 in case of storage protection override. + */ + rc =3D guest_range_to_gpas(vcpu, ga, ar, gpas, len, asce, mode, 0); + if (rc) + goto out_unlock; + for (idx =3D 0; idx < nr_pages; idx++) { fragment_len =3D min(PAGE_SIZE - offset_in_page(gpas[idx]), len); - rc =3D access_guest_page(vcpu->kvm, mode, gpas[idx], data, fragment_len); + if (try_fetch_prot_override && fetch_prot_override_applies(ga, fragment_= len)) { + rc =3D access_guest_page(vcpu->kvm, mode, gpas[idx], + data, fragment_len); + } else { + rc =3D access_guest_page_with_key(vcpu->kvm, mode, gpas[idx], + data, fragment_len, access_key); + } + if (rc =3D=3D PGM_PROTECTION && try_storage_prot_override) + rc =3D access_guest_page_with_key(vcpu->kvm, mode, gpas[idx], + data, fragment_len, PAGE_SPO_ACC); + if (rc =3D=3D PGM_PROTECTION) + prot =3D PROT_TYPE_KEYC; + if (rc) + break; len -=3D fragment_len; data +=3D fragment_len; + ga =3D kvm_s390_logical_to_effective(vcpu, ga + fragment_len); } + if (rc > 0) + rc =3D trans_exc(vcpu, rc, ga, ar, mode, prot); +out_unlock: if (need_ipte_lock) ipte_unlock(vcpu); if (nr_pages > ARRAY_SIZE(gpa_array)) @@ -940,12 +1089,13 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigne= d long gra, } =20 /** - * guest_translate_address - translate guest logical into guest absolute a= ddress + * guest_translate_address_with_key - translate guest logical into guest a= bsolute address * @vcpu: virtual cpu * @gva: Guest virtual address * @ar: Access register * @gpa: Guest physical address * @mode: Translation access mode + * @access_key: access key to mach the storage key with * * Parameter semantics are the same as the ones from guest_translate. * The memory contents at the guest address are not changed. @@ -953,8 +1103,9 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned = long gra, * Note: The IPTE lock is not taken during this function, so the caller * has to take care of this. */ -int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 a= r, - unsigned long *gpa, enum gacc_mode mode) +int guest_translate_address_with_key(struct kvm_vcpu *vcpu, unsigned long = gva, u8 ar, + unsigned long *gpa, enum gacc_mode mode, + u8 access_key) { union asce asce; int rc; @@ -963,7 +1114,17 @@ int guest_translate_address(struct kvm_vcpu *vcpu, un= signed long gva, u8 ar, rc =3D get_vcpu_asce(vcpu, &asce, gva, ar, mode); if (rc) return rc; - return guest_range_to_gpas(vcpu, gva, ar, gpa, 1, asce, mode); + return guest_range_to_gpas(vcpu, gva, ar, gpa, 1, asce, mode, + access_key); +} + +int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 a= r, + unsigned long *gpa, enum gacc_mode mode) +{ + u8 access_key =3D psw_bits(vcpu->arch.sie_block->gpsw).key; + + return guest_translate_address_with_key(vcpu, gva, ar, gpa, mode, + access_key); } =20 /** @@ -973,9 +1134,10 @@ int guest_translate_address(struct kvm_vcpu *vcpu, un= signed long gva, u8 ar, * @ar: Access register * @length: Length of test range * @mode: Translation access mode + * @access_key: access key to mach the storage keys with */ int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, - unsigned long length, enum gacc_mode mode) + unsigned long length, enum gacc_mode mode, u8 access_key) { union asce asce; int rc =3D 0; @@ -984,7 +1146,8 @@ int check_gva_range(struct kvm_vcpu *vcpu, unsigned lo= ng gva, u8 ar, if (rc) return rc; ipte_lock(vcpu); - rc =3D guest_range_to_gpas(vcpu, gva, ar, NULL, length, asce, mode); + rc =3D guest_range_to_gpas(vcpu, gva, ar, NULL, length, asce, mode, + access_key); ipte_unlock(vcpu); =20 return rc; diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h index 7c72a5e3449f..e5b2f56e7962 100644 --- a/arch/s390/kvm/gaccess.h +++ b/arch/s390/kvm/gaccess.h @@ -186,24 +186,31 @@ enum gacc_mode { GACC_IFETCH, }; =20 +int guest_translate_address_with_key(struct kvm_vcpu *vcpu, unsigned long = gva, u8 ar, + unsigned long *gpa, enum gacc_mode mode, + u8 access_key); + int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, unsigned long *gpa, enum gacc_mode mode); + int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, - unsigned long length, enum gacc_mode mode); + unsigned long length, enum gacc_mode mode, u8 access_key); =20 -int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *dat= a, - unsigned long len, enum gacc_mode mode); +int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, + void *data, unsigned long len, enum gacc_mode mode, + u8 access_key); =20 int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data, unsigned long len, enum gacc_mode mode); =20 /** - * write_guest - copy data from kernel space to guest space + * write_guest_with_key - copy data from kernel space to guest space * @vcpu: virtual cpu * @ga: guest address * @ar: access register * @data: source address in kernel space * @len: number of bytes to copy + * @access_key: access key the storage key needs to match * * Copy @len bytes from @data (kernel space) to @ga (guest address). * In order to copy data to guest space the PSW of the vcpu is inspected: @@ -214,8 +221,8 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned l= ong gra, * The addressing mode of the PSW is also inspected, so that address wrap * around is taken into account for 24-, 31- and 64-bit addressing mode, * if the to be copied data crosses page boundaries in guest address space. - * In addition also low address and DAT protection are inspected before - * copying any data (key protection is currently not implemented). + * In addition low address, DAT and key protection checks are performed be= fore + * copying any data. * * This function modifies the 'struct kvm_s390_pgm_info pgm' member of @vc= pu. * In case of an access exception (e.g. protection exception) pgm will con= tain @@ -243,10 +250,53 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned= long gra, * if data has been changed in guest space in case of an exception. */ static inline __must_check +int write_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, + void *data, unsigned long len, u8 access_key) +{ + return access_guest_with_key(vcpu, ga, ar, data, len, GACC_STORE, + access_key); +} + +/** + * write_guest - copy data from kernel space to guest space + * @vcpu: virtual cpu + * @ga: guest address + * @ar: access register + * @data: source address in kernel space + * @len: number of bytes to copy + * + * The behaviour of write_guest is identical to write_guest_with_key, exce= pt + * that the PSW access key is used instead of an explicit argument. + */ +static inline __must_check int write_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, unsigned long len) { - return access_guest(vcpu, ga, ar, data, len, GACC_STORE); + u8 access_key =3D psw_bits(vcpu->arch.sie_block->gpsw).key; + + return write_guest_with_key(vcpu, ga, ar, data, len, access_key); +} + +/** + * read_guest_with_key - copy data from guest space to kernel space + * @vcpu: virtual cpu + * @ga: guest address + * @ar: access register + * @data: destination address in kernel space + * @len: number of bytes to copy + * @access_key: access key the storage key needs to match + * + * Copy @len bytes from @ga (guest address) to @data (kernel space). + * + * The behaviour of read_guest_with_key is identical to write_guest_with_k= ey, + * except that data will be copied from guest space to kernel space. + */ +static inline __must_check +int read_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, + void *data, unsigned long len, u8 access_key) +{ + return access_guest_with_key(vcpu, ga, ar, data, len, GACC_FETCH, + access_key); } =20 /** @@ -259,14 +309,16 @@ int write_guest(struct kvm_vcpu *vcpu, unsigned long = ga, u8 ar, void *data, * * Copy @len bytes from @ga (guest address) to @data (kernel space). * - * The behaviour of read_guest is identical to write_guest, except that - * data will be copied from guest space to kernel space. + * The behaviour of read_guest is identical to read_guest_with_key, except + * that the PSW access key is used instead of an explicit argument. */ static inline __must_check int read_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, unsigned long len) { - return access_guest(vcpu, ga, ar, data, len, GACC_FETCH); + u8 access_key =3D psw_bits(vcpu->arch.sie_block->gpsw).key; + + return read_guest_with_key(vcpu, ga, ar, data, len, access_key); } =20 /** @@ -287,7 +339,10 @@ static inline __must_check int read_guest_instr(struct kvm_vcpu *vcpu, unsigned long ga, void *data, unsigned long len) { - return access_guest(vcpu, ga, 0, data, len, GACC_IFETCH); + u8 access_key =3D psw_bits(vcpu->arch.sie_block->gpsw).key; + + return access_guest_with_key(vcpu, ga, 0, data, len, GACC_IFETCH, + access_key); } =20 /** diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index d07ff646d844..8bd42a20d924 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -331,18 +331,18 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu) =20 kvm_s390_get_regs_rre(vcpu, ®1, ®2); =20 - /* Make sure that the source is paged-in */ - rc =3D guest_translate_address(vcpu, vcpu->run->s.regs.gprs[reg2], - reg2, &srcaddr, GACC_FETCH); + /* Ensure that the source is paged-in, no actual access -> no key checkin= g */ + rc =3D guest_translate_address_with_key(vcpu, vcpu->run->s.regs.gprs[reg2= ], + reg2, &srcaddr, GACC_FETCH, 0); if (rc) return kvm_s390_inject_prog_cond(vcpu, rc); rc =3D kvm_arch_fault_in_page(vcpu, srcaddr, 0); if (rc !=3D 0) return rc; =20 - /* Make sure that the destination is paged-in */ - rc =3D guest_translate_address(vcpu, vcpu->run->s.regs.gprs[reg1], - reg1, &dstaddr, GACC_STORE); + /* Ensure that the source is paged-in, no actual access -> no key checkin= g */ + rc =3D guest_translate_address_with_key(vcpu, vcpu->run->s.regs.gprs[reg1= ], + reg1, &dstaddr, GACC_STORE, 0); if (rc) return kvm_s390_inject_prog_cond(vcpu, rc); rc =3D kvm_arch_fault_in_page(vcpu, dstaddr, 1); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 2296b1ff1e02..fdbd6c1dc709 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -4713,7 +4713,7 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vc= pu, case KVM_S390_MEMOP_LOGICAL_READ: if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { r =3D check_gva_range(vcpu, mop->gaddr, mop->ar, - mop->size, GACC_FETCH); + mop->size, GACC_FETCH, 0); break; } r =3D read_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size); @@ -4725,7 +4725,7 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vc= pu, case KVM_S390_MEMOP_LOGICAL_WRITE: if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { r =3D check_gva_range(vcpu, mop->gaddr, mop->ar, - mop->size, GACC_STORE); + mop->size, GACC_STORE, 0); break; } if (copy_from_user(tmpbuf, uaddr, mop->size)) { --=20 2.32.0 From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BBE7BC433FE for ; Fri, 11 Feb 2022 18:22:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352614AbiBKSW3 (ORCPT ); Fri, 11 Feb 2022 13:22:29 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33028 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347765AbiBKSW1 (ORCPT ); Fri, 11 Feb 2022 13:22:27 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F0AC0CFF; Fri, 11 Feb 2022 10:22:25 -0800 (PST) Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BGD8TH000393; Fri, 11 Feb 2022 18:22:25 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=YkaDjfN6fpTsxhXUZebdfTLf6Q+ECbzky4ml3wC9PFQ=; b=bSB1ayWGBeCgDybB97MtQTsm3ITL9ae7GSHR1kYJudYFVo0bEC8Sm8sCoE75GphlxSey P41McrjYrprPxTLwI+2qfbMb+fBBRuBjUp9Ho2+T1CppDYPmD0N5FCjTbK0JYZa0me0P RjUaR6Jdo7zL/mX/ls8rX2vCVYcpZclKHFaWdLXWAVGQsq1wzzOX2Dr7ryYVz/uNTcu4 QdLUERDVIJ4gAgWLDepTZzvETjAK8ikzQdXRsDsRYk3GdtaONZPHbqZ3dv2yhVR5LHJZ VvW8M6jfu0NkSE86ecYeR1CYgvSfcXKU6WBd5/X5Vaiqbbq1NuPe4ZSeGhPKLRfiOsWZ 9w== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5rq56fy0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:24 +0000 Received: from m0098410.ppops.net (m0098410.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BIL8jx003692; Fri, 11 Feb 2022 18:22:24 GMT Received: from ppma06ams.nl.ibm.com (66.31.33a9.ip4.static.sl-reverse.com [169.51.49.102]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5rq56fxa-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:24 +0000 Received: from pps.filterd (ppma06ams.nl.ibm.com [127.0.0.1]) by ppma06ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BICAMe028899; Fri, 11 Feb 2022 18:22:22 GMT Received: from b06cxnps4076.portsmouth.uk.ibm.com (d06relay13.portsmouth.uk.ibm.com [9.149.109.198]) by ppma06ams.nl.ibm.com with ESMTP id 3e1ggkv5rw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:22 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIMI3M19726760 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:22:18 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C87AE5204F; Fri, 11 Feb 2022 18:22:18 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id 5F61452050; Fri, 11 Feb 2022 18:22:18 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 03/10] KVM: s390: handle_tprot: Honor storage keys Date: Fri, 11 Feb 2022 19:22:08 +0100 Message-Id: <20220211182215.2730017-4-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: IX4xPgTYb4S58olRHNcAkkwlLJzsRKHK X-Proofpoint-GUID: OvZgHfuuJqS-j26Ss0niFWKjIjJKNHGP X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 suspectscore=0 bulkscore=0 malwarescore=0 adultscore=0 priorityscore=1501 phishscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Use the access key operand to check for key protection when translating guest addresses. Since the translation code checks for accessing exceptions/error hvas, we can remove the check here and simplify the control flow. Keep checking if the memory is read-only even if such memslots are currently not supported. handle_tprot was the last user of guest_translate_address, so remove it. Signed-off-by: Janis Schoetterl-Glausch Reviewed-by: Janosch Frank Reviewed-by: Claudio Imbrenda --- arch/s390/kvm/gaccess.c | 9 ------ arch/s390/kvm/gaccess.h | 3 -- arch/s390/kvm/priv.c | 66 ++++++++++++++++++++++------------------- 3 files changed, 35 insertions(+), 43 deletions(-) diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index 7fca0cff4c12..37838f637707 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -1118,15 +1118,6 @@ int guest_translate_address_with_key(struct kvm_vcpu= *vcpu, unsigned long gva, u access_key); } =20 -int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 a= r, - unsigned long *gpa, enum gacc_mode mode) -{ - u8 access_key =3D psw_bits(vcpu->arch.sie_block->gpsw).key; - - return guest_translate_address_with_key(vcpu, gva, ar, gpa, mode, - access_key); -} - /** * check_gva_range - test a range of guest virtual addresses for accessibi= lity * @vcpu: virtual cpu diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h index e5b2f56e7962..c5f2e7311b17 100644 --- a/arch/s390/kvm/gaccess.h +++ b/arch/s390/kvm/gaccess.h @@ -190,9 +190,6 @@ int guest_translate_address_with_key(struct kvm_vcpu *v= cpu, unsigned long gva, u unsigned long *gpa, enum gacc_mode mode, u8 access_key); =20 -int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, - u8 ar, unsigned long *gpa, enum gacc_mode mode); - int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, unsigned long length, enum gacc_mode mode, u8 access_key); =20 diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 417154b314a6..30b24c42ef99 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -1443,10 +1443,11 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu) =20 static int handle_tprot(struct kvm_vcpu *vcpu) { - u64 address1, address2; - unsigned long hva, gpa; - int ret =3D 0, cc =3D 0; + u64 address, operand2; + unsigned long gpa; + u8 access_key; bool writable; + int ret, cc; u8 ar; =20 vcpu->stat.instruction_tprot++; @@ -1454,43 +1455,46 @@ static int handle_tprot(struct kvm_vcpu *vcpu) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); =20 - kvm_s390_get_base_disp_sse(vcpu, &address1, &address2, &ar, NULL); + kvm_s390_get_base_disp_sse(vcpu, &address, &operand2, &ar, NULL); + access_key =3D (operand2 & 0xf0) >> 4; =20 - /* we only handle the Linux memory detection case: - * access key =3D=3D 0 - * everything else goes to userspace. */ - if (address2 & 0xf0) - return -EOPNOTSUPP; if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT) ipte_lock(vcpu); - ret =3D guest_translate_address(vcpu, address1, ar, &gpa, GACC_STORE); - if (ret =3D=3D PGM_PROTECTION) { + + ret =3D guest_translate_address_with_key(vcpu, address, ar, &gpa, + GACC_STORE, access_key); + if (ret =3D=3D 0) { + gfn_to_hva_prot(vcpu->kvm, gpa_to_gfn(gpa), &writable); + } else if (ret =3D=3D PGM_PROTECTION) { + writable =3D false; /* Write protected? Try again with read-only... */ - cc =3D 1; - ret =3D guest_translate_address(vcpu, address1, ar, &gpa, - GACC_FETCH); + ret =3D guest_translate_address_with_key(vcpu, address, ar, &gpa, + GACC_FETCH, access_key); } - if (ret) { - if (ret =3D=3D PGM_ADDRESSING || ret =3D=3D PGM_TRANSLATION_SPEC) { - ret =3D kvm_s390_inject_program_int(vcpu, ret); - } else if (ret > 0) { - /* Translation not available */ - kvm_s390_set_psw_cc(vcpu, 3); + if (ret >=3D 0) { + cc =3D -1; + + /* Fetching permitted; storing permitted */ + if (ret =3D=3D 0 && writable) + cc =3D 0; + /* Fetching permitted; storing not permitted */ + else if (ret =3D=3D 0 && !writable) + cc =3D 1; + /* Fetching not permitted; storing not permitted */ + else if (ret =3D=3D PGM_PROTECTION) + cc =3D 2; + /* Translation not available */ + else if (ret !=3D PGM_ADDRESSING && ret !=3D PGM_TRANSLATION_SPEC) + cc =3D 3; + + if (cc !=3D -1) { + kvm_s390_set_psw_cc(vcpu, cc); ret =3D 0; + } else { + ret =3D kvm_s390_inject_program_int(vcpu, ret); } - goto out_unlock; } =20 - hva =3D gfn_to_hva_prot(vcpu->kvm, gpa_to_gfn(gpa), &writable); - if (kvm_is_error_hva(hva)) { - ret =3D kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); - } else { - if (!writable) - cc =3D 1; /* Write not permitted =3D=3D> read-only */ - kvm_s390_set_psw_cc(vcpu, cc); - /* Note: CC2 only occurs for storage keys (not supported yet) */ - } -out_unlock: if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT) ipte_unlock(vcpu); return ret; --=20 2.32.0 From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61A7FC4167E for ; Fri, 11 Feb 2022 18:22:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352655AbiBKSWh (ORCPT ); Fri, 11 Feb 2022 13:22:37 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33040 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347352AbiBKSW2 (ORCPT ); Fri, 11 Feb 2022 13:22:28 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0AE2AD4B; Fri, 11 Feb 2022 10:22:26 -0800 (PST) Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BG7FdC006066; Fri, 11 Feb 2022 18:22:25 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=OiuAH7C13RosG5m5BaiojgfE/FWaUD5nb7GxdoFhOB8=; b=mwuLCNYqavCtI18aYoQfu9Zuf3vtoC8Q6A4y00SCMMBWKoxlZWFsz1TfaTmWEVQGeqgv LpFeXTj4Izoe7meRAIQn7OyMgSDUvdIXRdzrTZLVYs6xotO8jr7HwUH2BDmTLWNmz0VO zDx4OYIBorZ8/LJeIt7qZYgLzFiDhTes3O6ZCB9dmaN8TTY8BnLa+DiJhbw4t2tYxUzP YdnQ5bq1X5GH3Dhi8Ym3H7ItzbsV1u0PRPn4eaXvsJdfNntCgvXMT1WyvIjflDFZ3rvN bMFmLVTsw1uOiJGnFkoWsBV+H39hZQUFhgZwwPaiNmBzIVTNboshWLJ7BsbOhG5Ceu/3 mA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5mrk3hdn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:25 +0000 Received: from m0098396.ppops.net (m0098396.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BI5bk3026068; Fri, 11 Feb 2022 18:22:25 GMT Received: from ppma01fra.de.ibm.com (46.49.7a9f.ip4.static.sl-reverse.com [159.122.73.70]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5mrk3hcx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:24 +0000 Received: from pps.filterd (ppma01fra.de.ibm.com [127.0.0.1]) by ppma01fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BIDaTc000939; Fri, 11 Feb 2022 18:22:22 GMT Received: from b06avi18878370.portsmouth.uk.ibm.com (b06avi18878370.portsmouth.uk.ibm.com [9.149.26.194]) by ppma01fra.de.ibm.com with ESMTP id 3e1gva9htf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:22 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06avi18878370.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIMJrQ21889528 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:22:19 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3F45952050; Fri, 11 Feb 2022 18:22:19 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id CA52452051; Fri, 11 Feb 2022 18:22:18 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 04/10] KVM: s390: selftests: Test TEST PROTECTION emulation Date: Fri, 11 Feb 2022 19:22:09 +0100 Message-Id: <20220211182215.2730017-5-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: 7GiqbC5VG26JgIkBRbJY_mmX12LFaTwT X-Proofpoint-GUID: NFMhRKCoTO6YUr1KsBm6M-EF7vyjU3F- X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 suspectscore=0 priorityscore=1501 adultscore=0 lowpriorityscore=0 malwarescore=0 mlxlogscore=999 clxscore=1015 spamscore=0 phishscore=0 impostorscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Test the emulation of TEST PROTECTION in the presence of storage keys. Emulation only occurs under certain conditions, one of which is the host page being protected. Trigger this by protecting the test pages via mprotect. Signed-off-by: Janis Schoetterl-Glausch Reviewed-by: Janosch Frank --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/s390x/tprot.c | 227 ++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 tools/testing/selftests/kvm/s390x/tprot.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftes= ts/kvm/.gitignore index dce7de7755e6..7903580a48ac 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -8,6 +8,7 @@ /s390x/memop /s390x/resets /s390x/sync_regs_test +/s390x/tprot /x86_64/amx_test /x86_64/cpuid_test /x86_64/cr4_cpuid_sync_test diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests= /kvm/Makefile index 0e4926bc9a58..086f490e808d 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -121,6 +121,7 @@ TEST_GEN_PROGS_aarch64 +=3D kvm_binary_stats_test TEST_GEN_PROGS_s390x =3D s390x/memop TEST_GEN_PROGS_s390x +=3D s390x/resets TEST_GEN_PROGS_s390x +=3D s390x/sync_regs_test +TEST_GEN_PROGS_s390x +=3D s390x/tprot TEST_GEN_PROGS_s390x +=3D demand_paging_test TEST_GEN_PROGS_s390x +=3D dirty_log_test TEST_GEN_PROGS_s390x +=3D kvm_create_max_vcpus diff --git a/tools/testing/selftests/kvm/s390x/tprot.c b/tools/testing/self= tests/kvm/s390x/tprot.c new file mode 100644 index 000000000000..c097b9db495e --- /dev/null +++ b/tools/testing/selftests/kvm/s390x/tprot.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Test TEST PROTECTION emulation. + * + * Copyright IBM Corp. 2021 + */ + +#include +#include "test_util.h" +#include "kvm_util.h" + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define CR0_FETCH_PROTECTION_OVERRIDE (1UL << (63 - 38)) +#define CR0_STORAGE_PROTECTION_OVERRIDE (1UL << (63 - 39)) + +#define VCPU_ID 1 + +static __aligned(PAGE_SIZE) uint8_t pages[2][PAGE_SIZE]; +static uint8_t *const page_store_prot =3D pages[0]; +static uint8_t *const page_fetch_prot =3D pages[1]; + +/* Nonzero return value indicates that address not mapped */ +static int set_storage_key(void *addr, uint8_t key) +{ + int not_mapped =3D 0; + + asm volatile ( + "lra %[addr], 0(0,%[addr])\n" + " jz 0f\n" + " llill %[not_mapped],1\n" + " j 1f\n" + "0: sske %[key], %[addr]\n" + "1:" + : [addr] "+&a" (addr), [not_mapped] "+r" (not_mapped) + : [key] "r" (key) + : "cc" + ); + return -not_mapped; +} + +enum permission { + READ_WRITE =3D 0, + READ =3D 1, + RW_PROTECTED =3D 2, + TRANSL_UNAVAIL =3D 3, +}; + +static enum permission test_protection(void *addr, uint8_t key) +{ + uint64_t mask; + + asm volatile ( + "tprot %[addr], 0(%[key])\n" + " ipm %[mask]\n" + : [mask] "=3Dr" (mask) + : [addr] "Q" (*(char *)addr), + [key] "a" (key) + : "cc" + ); + + return (enum permission)(mask >> 28); +} + +enum stage { + STAGE_END, + STAGE_INIT_SIMPLE, + TEST_SIMPLE, + STAGE_INIT_FETCH_PROT_OVERRIDE, + TEST_FETCH_PROT_OVERRIDE, + TEST_STORAGE_PROT_OVERRIDE, +}; + +struct test { + enum stage stage; + void *addr; + uint8_t key; + enum permission expected; +} tests[] =3D { + /* + * We perform each test in the array by executing TEST PROTECTION on + * the specified addr with the specified key and checking if the returned + * permissions match the expected value. + * Both guest and host cooperate to set up the required test conditions. + * A central condition is that the page targeted by addr has to be DAT + * protected in the host mappings, in order for KVM to emulate the + * TEST PROTECTION instruction. + * Since the page tables are shared, the host uses mprotect to achieve + * this. + * + * Test resulting in RW_PROTECTED/TRANSL_UNAVAIL will be interpreted + * by SIE, not KVM, but there is no harm in testing them also. + * See Enhanced Suppression-on-Protection Facilities in the + * Interpretive-Execution Mode + */ + /* + * guest: set storage key of page_store_prot to 1 + * storage key of page_fetch_prot to 9 and enable + * protection for it + * STAGE_INIT_SIMPLE + * host: write protect both via mprotect + */ + /* access key 0 matches any storage key -> RW */ + { TEST_SIMPLE, page_store_prot, 0x00, READ_WRITE }, + /* access key matches storage key -> RW */ + { TEST_SIMPLE, page_store_prot, 0x10, READ_WRITE }, + /* mismatched keys, but no fetch protection -> RO */ + { TEST_SIMPLE, page_store_prot, 0x20, READ }, + /* access key 0 matches any storage key -> RW */ + { TEST_SIMPLE, page_fetch_prot, 0x00, READ_WRITE }, + /* access key matches storage key -> RW */ + { TEST_SIMPLE, page_fetch_prot, 0x90, READ_WRITE }, + /* mismatched keys, fetch protection -> inaccessible */ + { TEST_SIMPLE, page_fetch_prot, 0x10, RW_PROTECTED }, + /* page 0 not mapped yet -> translation not available */ + { TEST_SIMPLE, (void *)0x00, 0x10, TRANSL_UNAVAIL }, + /* + * host: try to map page 0 + * guest: set storage key of page 0 to 9 and enable fetch protection + * STAGE_INIT_FETCH_PROT_OVERRIDE + * host: write protect page 0 + * enable fetch protection override + */ + /* mismatched keys, fetch protection, but override applies -> RO */ + { TEST_FETCH_PROT_OVERRIDE, (void *)0x00, 0x10, READ }, + /* mismatched keys, fetch protection, override applies to 0-2048 only -> = inaccessible */ + { TEST_FETCH_PROT_OVERRIDE, (void *)2049, 0x10, RW_PROTECTED }, + /* + * host: enable storage protection override + */ + /* mismatched keys, but override applies (storage key 9) -> RW */ + { TEST_STORAGE_PROT_OVERRIDE, page_fetch_prot, 0x10, READ_WRITE }, + /* mismatched keys, no fetch protection, override doesn't apply -> RO */ + { TEST_STORAGE_PROT_OVERRIDE, page_store_prot, 0x20, READ }, + /* mismatched keys, but override applies (storage key 9) -> RW */ + { TEST_STORAGE_PROT_OVERRIDE, (void *)2049, 0x10, READ_WRITE }, + /* end marker */ + { STAGE_END, 0, 0, 0 }, +}; + +static enum stage perform_next_stage(int *i, bool mapped_0) +{ + enum stage stage =3D tests[*i].stage; + enum permission result; + bool skip; + + for (; tests[*i].stage =3D=3D stage; (*i)++) { + /* + * Some fetch protection override tests require that page 0 + * be mapped, however, when the hosts tries to map that page via + * vm_vaddr_alloc, it may happen that some other page gets mapped + * instead. + * In order to skip these tests we detect this inside the guest + */ + skip =3D tests[*i].addr < (void *)4096 && + tests[*i].expected !=3D TRANSL_UNAVAIL && + !mapped_0; + if (!skip) { + result =3D test_protection(tests[*i].addr, tests[*i].key); + GUEST_ASSERT_2(result =3D=3D tests[*i].expected, *i, result); + } + } + return stage; +} + +static void guest_code(void) +{ + bool mapped_0; + int i =3D 0; + + GUEST_ASSERT_EQ(set_storage_key(page_store_prot, 0x10), 0); + GUEST_ASSERT_EQ(set_storage_key(page_fetch_prot, 0x98), 0); + GUEST_SYNC(STAGE_INIT_SIMPLE); + GUEST_SYNC(perform_next_stage(&i, false)); + + /* Fetch-protection override */ + mapped_0 =3D !set_storage_key((void *)0, 0x98); + GUEST_SYNC(STAGE_INIT_FETCH_PROT_OVERRIDE); + GUEST_SYNC(perform_next_stage(&i, mapped_0)); + + /* Storage-protection override */ + GUEST_SYNC(perform_next_stage(&i, mapped_0)); +} + +#define HOST_SYNC(vmp, stage) \ +({ \ + struct kvm_vm *__vm =3D (vmp); \ + struct ucall uc; \ + int __stage =3D (stage); \ + \ + vcpu_run(__vm, VCPU_ID); \ + get_ucall(__vm, VCPU_ID, &uc); \ + if (uc.cmd =3D=3D UCALL_ABORT) { \ + TEST_FAIL("line %lu: %s, hints: %lu, %lu", uc.args[1], \ + (const char *)uc.args[0], uc.args[2], uc.args[3]); \ + } \ + ASSERT_EQ(uc.cmd, UCALL_SYNC); \ + ASSERT_EQ(uc.args[1], __stage); \ +}) + +int main(int argc, char *argv[]) +{ + struct kvm_vm *vm; + struct kvm_run *run; + vm_vaddr_t guest_0_page; + + vm =3D vm_create_default(VCPU_ID, 0, guest_code); + run =3D vcpu_state(vm, VCPU_ID); + + HOST_SYNC(vm, STAGE_INIT_SIMPLE); + mprotect(addr_gva2hva(vm, (vm_vaddr_t)pages), PAGE_SIZE * 2, PROT_READ); + HOST_SYNC(vm, TEST_SIMPLE); + + guest_0_page =3D vm_vaddr_alloc(vm, PAGE_SIZE, 0); + if (guest_0_page !=3D 0) + print_skip("Did not allocate page at 0 for fetch protection override tes= ts"); + HOST_SYNC(vm, STAGE_INIT_FETCH_PROT_OVERRIDE); + if (guest_0_page =3D=3D 0) + mprotect(addr_gva2hva(vm, (vm_vaddr_t)0), PAGE_SIZE, PROT_READ); + run->s.regs.crs[0] |=3D CR0_FETCH_PROTECTION_OVERRIDE; + run->kvm_dirty_regs =3D KVM_SYNC_CRS; + HOST_SYNC(vm, TEST_FETCH_PROT_OVERRIDE); + + run->s.regs.crs[0] |=3D CR0_STORAGE_PROTECTION_OVERRIDE; + run->kvm_dirty_regs =3D KVM_SYNC_CRS; + HOST_SYNC(vm, TEST_STORAGE_PROT_OVERRIDE); +} --=20 2.32.0 From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 14A47C433F5 for ; Fri, 11 Feb 2022 18:22:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352665AbiBKSWk (ORCPT ); Fri, 11 Feb 2022 13:22:40 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33042 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344468AbiBKSW2 (ORCPT ); Fri, 11 Feb 2022 13:22:28 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B0772196; Fri, 11 Feb 2022 10:22:26 -0800 (PST) Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BHSiuL017416; Fri, 11 Feb 2022 18:22:26 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=B3NjpAqJS+7+xYQ3GwJvA+tXJxEEOVApLK2sh4yC31I=; b=r/7LyF+XS+uZPmdjAJG082iYSUknTwXlFQSNF8TifqsdqO5m4D0yOggVKNH2PwcYiJ7N y/vT8OiOcHtM0JKoFOw9feD2RjwPtB+HWxhHIxyXsLR5ZHQ61HaiHvjyyJXoNMsqjieA +1tOBTjjWyvuStVWtUO2SAXBlFjmDVCV5POxBo/c5nyAckFffrMLCguyj0GQ7VBLegOK RVQs6iKENMEkfxyXWJ+tJrZpVTbRz/P7+7l3BO2+UghL0g4DJ928aWPBjwVWuB5+lr/k C7ITNiB1LgMlp32oZS1lJJvPV0olHMzPGsoMPfPvhNV2fvWH+aGdSWvRdPgOaUM8/cfr 1g== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5v7y91n8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:26 +0000 Received: from m0098404.ppops.net (m0098404.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BIFcSc003076; Fri, 11 Feb 2022 18:22:25 GMT Received: from ppma04ams.nl.ibm.com (63.31.33a9.ip4.static.sl-reverse.com [169.51.49.99]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5v7y91mj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:25 +0000 Received: from pps.filterd (ppma04ams.nl.ibm.com [127.0.0.1]) by ppma04ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BICJuV020538; Fri, 11 Feb 2022 18:22:23 GMT Received: from b06avi18878370.portsmouth.uk.ibm.com (b06avi18878370.portsmouth.uk.ibm.com [9.149.26.194]) by ppma04ams.nl.ibm.com with ESMTP id 3e1gva44dd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:22 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06avi18878370.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIMJXn36569528 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:22:19 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id ABCBD5204E; Fri, 11 Feb 2022 18:22:19 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id 428D352054; Fri, 11 Feb 2022 18:22:19 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 05/10] KVM: s390: Add optional storage key checking to MEMOP IOCTL Date: Fri, 11 Feb 2022 19:22:10 +0100 Message-Id: <20220211182215.2730017-6-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: YeDpvl0kUzZjyMZapEtPxvXU1TwduhVy X-Proofpoint-GUID: gVr-8CH-y3PD_ts-obhMapEgqVp2AJgr X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 mlxlogscore=999 priorityscore=1501 lowpriorityscore=0 suspectscore=0 mlxscore=0 phishscore=0 spamscore=0 malwarescore=0 clxscore=1015 bulkscore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" User space needs a mechanism to perform key checked accesses when emulating instructions. The key can be passed as an additional argument. Having an additional argument is flexible, as user space can pass the guest PSW's key, in order to make an access the same way the CPU would, or pass another key if necessary. Signed-off-by: Janis Schoetterl-Glausch Reviewed-by: Claudio Imbrenda Reviewed-by: Christian Borntraeger Reviewed-by: Janosch Frank --- arch/s390/kvm/kvm-s390.c | 31 +++++++++++++++++++++---------- include/uapi/linux/kvm.h | 6 +++++- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index fdbd6c1dc709..c31b40abfa23 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -2359,6 +2359,11 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struc= t kvm_pv_cmd *cmd) return r; } =20 +static bool access_key_invalid(u8 access_key) +{ + return access_key > 0xf; +} + long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -4692,17 +4697,21 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *= vcpu, void *tmpbuf =3D NULL; int r =3D 0; const u64 supported_flags =3D KVM_S390_MEMOP_F_INJECT_EXCEPTION - | KVM_S390_MEMOP_F_CHECK_ONLY; + | KVM_S390_MEMOP_F_CHECK_ONLY + | KVM_S390_MEMOP_F_SKEY_PROTECTION; =20 if (mop->flags & ~supported_flags || mop->ar >=3D NUM_ACRS || !mop->size) return -EINVAL; - if (mop->size > MEM_OP_MAX_SIZE) return -E2BIG; - if (kvm_s390_pv_cpu_is_protected(vcpu)) return -EINVAL; - + if (mop->flags & KVM_S390_MEMOP_F_SKEY_PROTECTION) { + if (access_key_invalid(mop->key)) + return -EINVAL; + } else { + mop->key =3D 0; + } if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) { tmpbuf =3D vmalloc(mop->size); if (!tmpbuf) @@ -4712,11 +4721,12 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *= vcpu, switch (mop->op) { case KVM_S390_MEMOP_LOGICAL_READ: if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { - r =3D check_gva_range(vcpu, mop->gaddr, mop->ar, - mop->size, GACC_FETCH, 0); + r =3D check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size, + GACC_FETCH, mop->key); break; } - r =3D read_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size); + r =3D read_guest_with_key(vcpu, mop->gaddr, mop->ar, tmpbuf, + mop->size, mop->key); if (r =3D=3D 0) { if (copy_to_user(uaddr, tmpbuf, mop->size)) r =3D -EFAULT; @@ -4724,15 +4734,16 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *= vcpu, break; case KVM_S390_MEMOP_LOGICAL_WRITE: if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { - r =3D check_gva_range(vcpu, mop->gaddr, mop->ar, - mop->size, GACC_STORE, 0); + r =3D check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size, + GACC_STORE, mop->key); break; } if (copy_from_user(tmpbuf, uaddr, mop->size)) { r =3D -EFAULT; break; } - r =3D write_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size); + r =3D write_guest_with_key(vcpu, mop->gaddr, mop->ar, tmpbuf, + mop->size, mop->key); break; } =20 diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 5191b57e1562..4566f429db2c 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -562,7 +562,10 @@ struct kvm_s390_mem_op { __u32 op; /* type of operation */ __u64 buf; /* buffer in userspace */ union { - __u8 ar; /* the access register number */ + struct { + __u8 ar; /* the access register number */ + __u8 key; /* access key, ignored if flag unset */ + }; __u32 sida_offset; /* offset into the sida */ __u8 reserved[32]; /* should be set to 0 */ }; @@ -575,6 +578,7 @@ struct kvm_s390_mem_op { /* flags for kvm_s390_mem_op->flags */ #define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) #define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1) +#define KVM_S390_MEMOP_F_SKEY_PROTECTION (1ULL << 2) =20 /* for KVM_INTERRUPT */ struct kvm_interrupt { --=20 2.32.0 From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 91C7EC433EF for ; Fri, 11 Feb 2022 18:22:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346086AbiBKSWs (ORCPT ); Fri, 11 Feb 2022 13:22:48 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351217AbiBKSW2 (ORCPT ); Fri, 11 Feb 2022 13:22:28 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DCA49D43; Fri, 11 Feb 2022 10:22:26 -0800 (PST) Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BGVdvY003447; Fri, 11 Feb 2022 18:22:26 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=kmezqiBmE+coJr9WrGzX+puRpPPxFQD3DqpBEfvNPRc=; b=IvKHJZfaiv+xSmu0jFuU9dZy3L2f85TZHtp5R3ZvkyTQsLrHfKoXd+8zvpqLSD4Pr3zs V4IEUUQlfQ9cRlrcV0D32ptbTwch4D72aYL3CxQGLBr3XqP/xNptq4d9Qb8G7b3hy2Mz RNV+OOAvxH2stivUMJ/j+Uu54bOgzgpk5CV4xeBwX5oZxV4G7zwcPOd4p7T7ww5D/o0Q 6BV7Pv/9foqSg2nCB+VG2skiUprC3q1HaUJ4MbtszwhFiXnDjeM70Q593+bmrR497Xtd brHOM65t5pbUisM7o2vxxL4ddbku6r3zABYBZRYZ/MFJm2j2sQ+yGTyuShi0EsFElDtI 3w== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5ph49fdf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:26 +0000 Received: from m0098409.ppops.net (m0098409.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BGRwpc005498; Fri, 11 Feb 2022 18:22:25 GMT Received: from ppma04fra.de.ibm.com (6a.4a.5195.ip4.static.sl-reverse.com [149.81.74.106]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5ph49fcv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:25 +0000 Received: from pps.filterd (ppma04fra.de.ibm.com [127.0.0.1]) by ppma04fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BICLF6006140; Fri, 11 Feb 2022 18:22:23 GMT Received: from b06avi18626390.portsmouth.uk.ibm.com (b06avi18626390.portsmouth.uk.ibm.com [9.149.26.192]) by ppma04fra.de.ibm.com with ESMTP id 3e2ygr0jxs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:23 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06avi18626390.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIC7QP47579590 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:12:07 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 222CD5204F; Fri, 11 Feb 2022 18:22:20 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id AD10252050; Fri, 11 Feb 2022 18:22:19 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 06/10] KVM: s390: Add vm IOCTL for key checked guest absolute memory access Date: Fri, 11 Feb 2022 19:22:11 +0100 Message-Id: <20220211182215.2730017-7-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: IIPy70TegzO2eo5MlyDgNnJbUCBURDtb X-Proofpoint-GUID: UuA5ye6aKf3S-EF-gncqaZuctU2qNXn_ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxscore=0 lowpriorityscore=0 phishscore=0 mlxlogscore=999 bulkscore=0 priorityscore=1501 impostorscore=0 clxscore=1015 adultscore=0 spamscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Channel I/O honors storage keys and is performed on absolute memory. For I/O emulation user space therefore needs to be able to do key checked accesses. The vm IOCTL supports read/write accesses, as well as checking if an access would succeed. Unlike relying on KVM_S390_GET_SKEYS for key checking would, the vm IOCTL performs the check in lockstep with the read or write, by, ultimately, mapping the access to move instructions that support key protection checking with a supplied key. Fetch and storage protection override are not applicable to absolute accesses and so are not applied as they are when using the vcpu memop. Signed-off-by: Janis Schoetterl-Glausch Reviewed-by: Christian Borntraeger Reviewed-by: Claudio Imbrenda --- arch/s390/kvm/gaccess.c | 72 +++++++++++++++++++++++++++++++++++ arch/s390/kvm/gaccess.h | 6 +++ arch/s390/kvm/kvm-s390.c | 81 ++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 2 + 4 files changed, 161 insertions(+) diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index 37838f637707..d53a183c2005 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -795,6 +795,35 @@ static int low_address_protection_enabled(struct kvm_v= cpu *vcpu, return 1; } =20 +static int vm_check_access_key(struct kvm *kvm, u8 access_key, + enum gacc_mode mode, gpa_t gpa) +{ + u8 storage_key, access_control; + bool fetch_protected; + unsigned long hva; + int r; + + if (access_key =3D=3D 0) + return 0; + + hva =3D gfn_to_hva(kvm, gpa_to_gfn(gpa)); + if (kvm_is_error_hva(hva)) + return PGM_ADDRESSING; + + mmap_read_lock(current->mm); + r =3D get_guest_storage_key(current->mm, hva, &storage_key); + mmap_read_unlock(current->mm); + if (r) + return r; + access_control =3D FIELD_GET(_PAGE_ACC_BITS, storage_key); + if (access_control =3D=3D access_key) + return 0; + fetch_protected =3D storage_key & _PAGE_FP_BIT; + if ((mode =3D=3D GACC_FETCH || mode =3D=3D GACC_IFETCH) && !fetch_protect= ed) + return 0; + return PGM_PROTECTION; +} + static bool fetch_prot_override_applicable(struct kvm_vcpu *vcpu, enum gac= c_mode mode, union asce asce) { @@ -994,6 +1023,26 @@ access_guest_page_with_key(struct kvm *kvm, enum gacc= _mode mode, gpa_t gpa, return 0; } =20 +int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data, + unsigned long len, enum gacc_mode mode, u8 access_key) +{ + int offset =3D offset_in_page(gpa); + int fragment_len; + int rc; + + while (min(PAGE_SIZE - offset, len) > 0) { + fragment_len =3D min(PAGE_SIZE - offset, len); + rc =3D access_guest_page_with_key(kvm, mode, gpa, data, fragment_len, ac= cess_key); + if (rc) + return rc; + offset =3D 0; + len -=3D fragment_len; + data +=3D fragment_len; + gpa +=3D fragment_len; + } + return 0; +} + int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, unsigned long len, enum gacc_mode mode, u8 access_key) @@ -1144,6 +1193,29 @@ int check_gva_range(struct kvm_vcpu *vcpu, unsigned = long gva, u8 ar, return rc; } =20 +/** + * check_gpa_range - test a range of guest physical addresses for accessib= ility + * @kvm: virtual machine instance + * @gpa: guest physical address + * @length: length of test range + * @mode: access mode to test, relevant for storage keys + * @access_key: access key to mach the storage keys with + */ +int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long leng= th, + enum gacc_mode mode, u8 access_key) +{ + unsigned int fragment_len; + int rc =3D 0; + + while (length && !rc) { + fragment_len =3D min(PAGE_SIZE - offset_in_page(gpa), length); + rc =3D vm_check_access_key(kvm, access_key, mode, gpa); + length -=3D fragment_len; + gpa +=3D fragment_len; + } + return rc; +} + /** * kvm_s390_check_low_addr_prot_real - check for low-address protection * @vcpu: virtual cpu diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h index c5f2e7311b17..1124ff282012 100644 --- a/arch/s390/kvm/gaccess.h +++ b/arch/s390/kvm/gaccess.h @@ -193,6 +193,12 @@ int guest_translate_address_with_key(struct kvm_vcpu *= vcpu, unsigned long gva, u int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, unsigned long length, enum gacc_mode mode, u8 access_key); =20 +int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long leng= th, + enum gacc_mode mode, u8 access_key); + +int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data, + unsigned long len, enum gacc_mode mode, u8 access_key); + int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, unsigned long len, enum gacc_mode mode, u8 access_key); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c31b40abfa23..36bc73b5f5de 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -2364,6 +2364,78 @@ static bool access_key_invalid(u8 access_key) return access_key > 0xf; } =20 +static int kvm_s390_vm_mem_op(struct kvm *kvm, struct kvm_s390_mem_op *mop) +{ + void __user *uaddr =3D (void __user *)mop->buf; + u64 supported_flags; + void *tmpbuf =3D NULL; + int r, srcu_idx; + + supported_flags =3D KVM_S390_MEMOP_F_SKEY_PROTECTION + | KVM_S390_MEMOP_F_CHECK_ONLY; + if (mop->flags & ~supported_flags) + return -EINVAL; + if (mop->size > MEM_OP_MAX_SIZE) + return -E2BIG; + if (kvm_s390_pv_is_protected(kvm)) + return -EINVAL; + if (mop->flags & KVM_S390_MEMOP_F_SKEY_PROTECTION) { + if (access_key_invalid(mop->key)) + return -EINVAL; + } else { + mop->key =3D 0; + } + if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) { + tmpbuf =3D vmalloc(mop->size); + if (!tmpbuf) + return -ENOMEM; + } + + srcu_idx =3D srcu_read_lock(&kvm->srcu); + + if (kvm_is_error_gpa(kvm, mop->gaddr)) { + r =3D PGM_ADDRESSING; + goto out_unlock; + } + + switch (mop->op) { + case KVM_S390_MEMOP_ABSOLUTE_READ: { + if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { + r =3D check_gpa_range(kvm, mop->gaddr, mop->size, GACC_FETCH, mop->key); + } else { + r =3D access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf, + mop->size, GACC_FETCH, mop->key); + if (r =3D=3D 0) { + if (copy_to_user(uaddr, tmpbuf, mop->size)) + r =3D -EFAULT; + } + } + break; + } + case KVM_S390_MEMOP_ABSOLUTE_WRITE: { + if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { + r =3D check_gpa_range(kvm, mop->gaddr, mop->size, GACC_STORE, mop->key); + } else { + if (copy_from_user(tmpbuf, uaddr, mop->size)) { + r =3D -EFAULT; + break; + } + r =3D access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf, + mop->size, GACC_STORE, mop->key); + } + break; + } + default: + r =3D -EINVAL; + } + +out_unlock: + srcu_read_unlock(&kvm->srcu, srcu_idx); + + vfree(tmpbuf); + return r; +} + long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -2488,6 +2560,15 @@ long kvm_arch_vm_ioctl(struct file *filp, } break; } + case KVM_S390_MEM_OP: { + struct kvm_s390_mem_op mem_op; + + if (copy_from_user(&mem_op, argp, sizeof(mem_op)) =3D=3D 0) + r =3D kvm_s390_vm_mem_op(kvm, &mem_op); + else + r =3D -EFAULT; + break; + } default: r =3D -ENOTTY; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 4566f429db2c..4bc7623def87 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -575,6 +575,8 @@ struct kvm_s390_mem_op { #define KVM_S390_MEMOP_LOGICAL_WRITE 1 #define KVM_S390_MEMOP_SIDA_READ 2 #define KVM_S390_MEMOP_SIDA_WRITE 3 +#define KVM_S390_MEMOP_ABSOLUTE_READ 4 +#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 /* flags for kvm_s390_mem_op->flags */ #define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) #define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1) --=20 2.32.0 From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24B48C433EF for ; Fri, 11 Feb 2022 18:23:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243192AbiBKSW6 (ORCPT ); Fri, 11 Feb 2022 13:22:58 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33072 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352609AbiBKSW3 (ORCPT ); Fri, 11 Feb 2022 13:22:29 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 29E2F196; Fri, 11 Feb 2022 10:22:28 -0800 (PST) Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BHvJMG001836; Fri, 11 Feb 2022 18:22:26 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=OWnK9tzmWdhK2TZFn9Xq30TFdbZWOX+ioANPcoD0StA=; b=Wwn4ZlrY2UBXUIPLEbghqSjndTQQxJdWgPyI5ecRvbrG/8DDWGP2bDAfm86Tw320U3mS oUbP7omPI0PbLnf4w9e43VJCFEQKxzHXh+cJ9FXL4LMDbd5jq8qBIyzRxHyuP+WN0eFt rIGlXGri5R7rChHdRYEurpvHfIypvGek6x2sAfUplKIV0FrX4ZL9GPTKZEja6ZFjRUfU fucOb6juXPjYOJgwehYGx8o7zzXrUexRp89/yLG1O0zBsLBIVhfANXTylsSQjHmuWckS JzEVeV61p8UQ6irCZrCLgkTy/v1aB7he2L6Z3ULnYDUkD5DGn9nETgNUsnBy/TZR0vKR sQ== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3e5tf63g1x-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:26 +0000 Received: from m0098414.ppops.net (m0098414.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BIEHWt028519; Fri, 11 Feb 2022 18:22:25 GMT Received: from ppma02fra.de.ibm.com (47.49.7a9f.ip4.static.sl-reverse.com [159.122.73.71]) by mx0b-001b2d01.pphosted.com with ESMTP id 3e5tf63g18-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:25 +0000 Received: from pps.filterd (ppma02fra.de.ibm.com [127.0.0.1]) by ppma02fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BICMKB015232; Fri, 11 Feb 2022 18:22:24 GMT Received: from b06avi18626390.portsmouth.uk.ibm.com (b06avi18626390.portsmouth.uk.ibm.com [9.149.26.192]) by ppma02fra.de.ibm.com with ESMTP id 3e1gva9kf6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:24 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06avi18626390.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIC8DN47579594 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:12:08 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8CE545204E; Fri, 11 Feb 2022 18:22:20 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id 23E9452051; Fri, 11 Feb 2022 18:22:20 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 07/10] KVM: s390: Rename existing vcpu memop functions Date: Fri, 11 Feb 2022 19:22:12 +0100 Message-Id: <20220211182215.2730017-8-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-GUID: OYgMrVQch2YcM3fwwDlI_rBzNp6VWrwj X-Proofpoint-ORIG-GUID: V29AmG4DhWyQUo3Uh7Qa4Tx1LRf-SiVw X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 priorityscore=1501 mlxscore=0 suspectscore=0 adultscore=0 impostorscore=0 malwarescore=0 spamscore=0 mlxlogscore=999 bulkscore=0 clxscore=1015 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Makes the naming consistent, now that we also have a vm ioctl. Signed-off-by: Janis Schoetterl-Glausch Reviewed-by: Janosch Frank Reviewed-by: Claudio Imbrenda --- arch/s390/kvm/kvm-s390.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 36bc73b5f5de..773bccdd446c 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -4741,8 +4741,8 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu = *vcpu, return r; } =20 -static long kvm_s390_guest_sida_op(struct kvm_vcpu *vcpu, - struct kvm_s390_mem_op *mop) +static long kvm_s390_vcpu_sida_op(struct kvm_vcpu *vcpu, + struct kvm_s390_mem_op *mop) { void __user *uaddr =3D (void __user *)mop->buf; int r =3D 0; @@ -4771,8 +4771,9 @@ static long kvm_s390_guest_sida_op(struct kvm_vcpu *v= cpu, } return r; } -static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu, - struct kvm_s390_mem_op *mop) + +static long kvm_s390_vcpu_mem_op(struct kvm_vcpu *vcpu, + struct kvm_s390_mem_op *mop) { void __user *uaddr =3D (void __user *)mop->buf; void *tmpbuf =3D NULL; @@ -4835,8 +4836,8 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vc= pu, return r; } =20 -static long kvm_s390_guest_memsida_op(struct kvm_vcpu *vcpu, - struct kvm_s390_mem_op *mop) +static long kvm_s390_vcpu_memsida_op(struct kvm_vcpu *vcpu, + struct kvm_s390_mem_op *mop) { int r, srcu_idx; =20 @@ -4845,12 +4846,12 @@ static long kvm_s390_guest_memsida_op(struct kvm_vc= pu *vcpu, switch (mop->op) { case KVM_S390_MEMOP_LOGICAL_READ: case KVM_S390_MEMOP_LOGICAL_WRITE: - r =3D kvm_s390_guest_mem_op(vcpu, mop); + r =3D kvm_s390_vcpu_mem_op(vcpu, mop); break; case KVM_S390_MEMOP_SIDA_READ: case KVM_S390_MEMOP_SIDA_WRITE: /* we are locked against sida going away by the vcpu->mutex */ - r =3D kvm_s390_guest_sida_op(vcpu, mop); + r =3D kvm_s390_vcpu_sida_op(vcpu, mop); break; default: r =3D -EINVAL; @@ -5013,7 +5014,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, struct kvm_s390_mem_op mem_op; =20 if (copy_from_user(&mem_op, argp, sizeof(mem_op)) =3D=3D 0) - r =3D kvm_s390_guest_memsida_op(vcpu, &mem_op); + r =3D kvm_s390_vcpu_memsida_op(vcpu, &mem_op); else r =3D -EFAULT; break; --=20 2.32.0 From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C01A0C433F5 for ; Fri, 11 Feb 2022 18:22:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352724AbiBKSWv (ORCPT ); Fri, 11 Feb 2022 13:22:51 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33060 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352584AbiBKSW3 (ORCPT ); Fri, 11 Feb 2022 13:22:29 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B971DCD3; Fri, 11 Feb 2022 10:22:27 -0800 (PST) Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BGsvZv010648; Fri, 11 Feb 2022 18:22:27 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=N6mXra5Ie4+ZeBnaR8payp93zxPRlR66EUeezDLCiSs=; b=sBXy5waDnVJRQeiUn+Bu8DJ20pXO/YLlUnBhqpWJtx8oLLFSEEtAY8u+sGonRkiaRCEb lue/WWKa1XYX+ve7gWV7d2zx3A4tSzI3Hxgi5INU17S2PHl8J5ZJui2iLKFIORUpAkBX /CzeoP+nr7e+n3gzwCj+HGRvCsckMcz6LlrcGXLBHwP8f0wJ8q2dOKd1dn2SM03j7u/1 PWmi3pDUQscwYslBg3K8+6sU7Zu3qyZbvYwKz/R6gug3hjlliEJn+T7VJO3RPxQ+RXBY agv++XbMB2Ag3pmYCLMMOjoD3dJf8lc/KcXfxjGrkO6NWYR89rATK/xOHaCG7tZO+VVD Bg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5sk5n5na-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:27 +0000 Received: from m0098393.ppops.net (m0098393.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BIHm4f027653; Fri, 11 Feb 2022 18:22:26 GMT Received: from ppma06ams.nl.ibm.com (66.31.33a9.ip4.static.sl-reverse.com [169.51.49.102]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5sk5n5mp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:26 +0000 Received: from pps.filterd (ppma06ams.nl.ibm.com [127.0.0.1]) by ppma06ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BICAMf028899; Fri, 11 Feb 2022 18:22:24 GMT Received: from b06cxnps3075.portsmouth.uk.ibm.com (d06relay10.portsmouth.uk.ibm.com [9.149.109.195]) by ppma06ams.nl.ibm.com with ESMTP id 3e1ggkv5s4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:24 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIMLg234144614 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:22:21 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0D1895204E; Fri, 11 Feb 2022 18:22:21 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id 8E9AD52057; Fri, 11 Feb 2022 18:22:20 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 08/10] KVM: s390: Add capability for storage key extension of MEM_OP IOCTL Date: Fri, 11 Feb 2022 19:22:13 +0100 Message-Id: <20220211182215.2730017-9-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: M5FY2t2cYJMoF7H3HIXVaxpG_8iuPtdU X-Proofpoint-GUID: 38QdVAVT4jJW02NM1mfQhijb_PPaCDCd X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxscore=0 priorityscore=1501 mlxlogscore=999 suspectscore=0 spamscore=0 adultscore=0 phishscore=0 lowpriorityscore=0 clxscore=1015 impostorscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Availability of the KVM_CAP_S390_MEM_OP_EXTENSION capability signals that: * The vcpu MEM_OP IOCTL supports storage key checking. * The vm MEM_OP IOCTL exists. Signed-off-by: Janis Schoetterl-Glausch Reviewed-by: Janosch Frank Reviewed-by: Christian Borntraeger Reviewed-by: Claudio Imbrenda --- arch/s390/kvm/kvm-s390.c | 1 + include/uapi/linux/kvm.h | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 773bccdd446c..c2c26c2aad64 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -564,6 +564,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long = ext) case KVM_CAP_S390_VCPU_RESETS: case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_S390_DIAG318: + case KVM_CAP_S390_MEM_OP_EXTENSION: r =3D 1; break; case KVM_CAP_SET_GUEST_DEBUG2: diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 4bc7623def87..08756eeea065 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1140,6 +1140,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_VM_GPA_BITS 207 #define KVM_CAP_XSAVE2 208 #define KVM_CAP_SYS_ATTRIBUTES 209 +#define KVM_CAP_S390_MEM_OP_EXTENSION 210 =20 #ifdef KVM_CAP_IRQ_ROUTING =20 --=20 2.32.0 From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4A329C433FE for ; Fri, 11 Feb 2022 18:23:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352739AbiBKSXB (ORCPT ); Fri, 11 Feb 2022 13:23:01 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33074 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230377AbiBKSW3 (ORCPT ); Fri, 11 Feb 2022 13:22:29 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4D44213A; Fri, 11 Feb 2022 10:22:28 -0800 (PST) Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BG8cbw003365; Fri, 11 Feb 2022 18:22:28 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=qxBZfgf8hN2GgRjJ/RSGAwsocPIU9mek478pfm148K8=; b=tEdUQx9fIPnZBdSEQqd7oU/tYCNEtbG2r5jRP125//fiXqNp/kzmzVSW1m6Gh/Fy5mXv CLIxFrkU4YCMFBN66sGJasXDATmUG1XQI4crIW60+J/el6bBM4h1YYmfyq6UEBV/VssZ dbS5u4nVe1ah4MB3tVYSkL8FaVTkkP/RE5auFaQ2fgR1gimwDhkyhQ+LjKLeoOT1/6Xg C+L4QlSIJ9wa8of2gTLKR+1vaV78jPWJG71oIggEXumyHfG+F2dlxUwsCct+qGDP9IMr b6R8PjmWBGpV/k2bha/eVUmRLdMG/8+urtn+3gBVYmIrrwRMooZUYz/BI/JdrQ12cqox 5Q== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5ph49fdy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:27 +0000 Received: from m0098409.ppops.net (m0098409.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BIBmhq009751; Fri, 11 Feb 2022 18:22:27 GMT Received: from ppma03ams.nl.ibm.com (62.31.33a9.ip4.static.sl-reverse.com [169.51.49.98]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5ph49fd7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:27 +0000 Received: from pps.filterd (ppma03ams.nl.ibm.com [127.0.0.1]) by ppma03ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BID40E032607; Fri, 11 Feb 2022 18:22:24 GMT Received: from b06cxnps3075.portsmouth.uk.ibm.com (d06relay10.portsmouth.uk.ibm.com [9.149.109.195]) by ppma03ams.nl.ibm.com with ESMTP id 3e1gvac2wk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:24 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIML0Z43975140 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:22:21 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 77AE652051; Fri, 11 Feb 2022 18:22:21 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id 0EBAB5204F; Fri, 11 Feb 2022 18:22:21 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 09/10] KVM: s390: Update api documentation for memop ioctl Date: Fri, 11 Feb 2022 19:22:14 +0100 Message-Id: <20220211182215.2730017-10-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: DGFcinGbsnvE1FrNkHCpWwObnbuCF2iy X-Proofpoint-GUID: DTY_AMexXPyGorioyxLLVlo6A-07hpA- X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxscore=0 lowpriorityscore=0 phishscore=0 mlxlogscore=825 bulkscore=0 priorityscore=1501 impostorscore=0 clxscore=1015 adultscore=0 spamscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Document all currently existing operations, flags and explain under which circumstances they are available. Document the recently introduced absolute operations and the storage key protection flag, as well as the existing SIDA operations. Signed-off-by: Janis Schoetterl-Glausch Reviewed-by: Janosch Frank Reviewed-by: Claudio Imbrenda --- Documentation/virt/kvm/api.rst | 112 ++++++++++++++++++++++++++------- include/uapi/linux/kvm.h | 2 +- 2 files changed, 91 insertions(+), 23 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index a4267104db50..48f23bb80d7f 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -3683,15 +3683,17 @@ The fields in each entry are defined as follows: 4.89 KVM_S390_MEM_OP -------------------- =20 -:Capability: KVM_CAP_S390_MEM_OP +:Capability: KVM_CAP_S390_MEM_OP, KVM_CAP_S390_PROTECTED, KVM_CAP_S390_MEM= _OP_EXTENSION :Architectures: s390 -:Type: vcpu ioctl +:Type: vm ioctl, vcpu ioctl :Parameters: struct kvm_s390_mem_op (in) :Returns: =3D 0 on success, < 0 on generic error (e.g. -EFAULT or -ENOMEM), > 0 if an exception occurred while walking the page tables =20 -Read or write data from/to the logical (virtual) memory of a VCPU. +Read or write data from/to the VM's memory. +The KVM_CAP_S390_MEM_OP_EXTENSION capability specifies what functionality = is +supported. =20 Parameters are specified via the following structure:: =20 @@ -3701,33 +3703,99 @@ Parameters are specified via the following structur= e:: __u32 size; /* amount of bytes */ __u32 op; /* type of operation */ __u64 buf; /* buffer in userspace */ - __u8 ar; /* the access register number */ - __u8 reserved[31]; /* should be set to 0 */ + union { + struct { + __u8 ar; /* the access register number */ + __u8 key; /* access key, ignored if flag unset */ + }; + __u32 sida_offset; /* offset into the sida */ + __u8 reserved[32]; /* ignored */ + }; }; =20 -The type of operation is specified in the "op" field. It is either -KVM_S390_MEMOP_LOGICAL_READ for reading from logical memory space or -KVM_S390_MEMOP_LOGICAL_WRITE for writing to logical memory space. The -KVM_S390_MEMOP_F_CHECK_ONLY flag can be set in the "flags" field to check -whether the corresponding memory access would create an access exception -(without touching the data in the memory at the destination). In case an -access exception occurred while walking the MMU tables of the guest, the -ioctl returns a positive error number to indicate the type of exception. -This exception is also raised directly at the corresponding VCPU if the -flag KVM_S390_MEMOP_F_INJECT_EXCEPTION is set in the "flags" field. - The start address of the memory region has to be specified in the "gaddr" field, and the length of the region in the "size" field (which must not be 0). The maximum value for "size" can be obtained by checking the KVM_CAP_S390_MEM_OP capability. "buf" is the buffer supplied by the userspace application where the read data should be written to for -KVM_S390_MEMOP_LOGICAL_READ, or where the data that should be written is -stored for a KVM_S390_MEMOP_LOGICAL_WRITE. When KVM_S390_MEMOP_F_CHECK_ONLY -is specified, "buf" is unused and can be NULL. "ar" designates the access -register number to be used; the valid range is 0..15. +a read access, or where the data that should be written is stored for +a write access. The "reserved" field is meant for future extensions. +Reserved and unused values are ignored. Future extension that add members = must +introduce new flags. + +The type of operation is specified in the "op" field. Flags modifying +their behavior can be set in the "flags" field. Undefined flag bits must +be set to 0. + +Possible operations are: + * ``KVM_S390_MEMOP_LOGICAL_READ`` + * ``KVM_S390_MEMOP_LOGICAL_WRITE`` + * ``KVM_S390_MEMOP_ABSOLUTE_READ`` + * ``KVM_S390_MEMOP_ABSOLUTE_WRITE`` + * ``KVM_S390_MEMOP_SIDA_READ`` + * ``KVM_S390_MEMOP_SIDA_WRITE`` + +Logical read/write: +^^^^^^^^^^^^^^^^^^^ + +Access logical memory, i.e. translate the given guest address to an absolu= te +address given the state of the VCPU and use the absolute address as target= of +the access. "ar" designates the access register number to be used; the val= id +range is 0..15. +Logical accesses are permitted for the VCPU ioctl only. +Logical accesses are permitted for non-protected guests only. + +Supported flags: + * ``KVM_S390_MEMOP_F_CHECK_ONLY`` + * ``KVM_S390_MEMOP_F_INJECT_EXCEPTION`` + * ``KVM_S390_MEMOP_F_SKEY_PROTECTION`` + +The KVM_S390_MEMOP_F_CHECK_ONLY flag can be set to check whether the +corresponding memory access would cause an access exception; however, +no actual access to the data in memory at the destination is performed. +In this case, "buf" is unused and can be NULL. + +In case an access exception occurred during the access (or would occur +in case of KVM_S390_MEMOP_F_CHECK_ONLY), the ioctl returns a positive +error number indicating the type of exception. This exception is also +raised directly at the corresponding VCPU if the flag +KVM_S390_MEMOP_F_INJECT_EXCEPTION is set. + +If the KVM_S390_MEMOP_F_SKEY_PROTECTION flag is set, storage key +protection is also in effect and may cause exceptions if accesses are +prohibited given the access key passed in "key". +KVM_S390_MEMOP_F_SKEY_PROTECTION is available if KVM_CAP_S390_MEM_OP_EXTEN= SION +is > 0. + +Absolute read/write: +^^^^^^^^^^^^^^^^^^^^ + +Access absolute memory. This operation is intended to be used with the +KVM_S390_MEMOP_F_SKEY_PROTECTION flag, to allow accessing memory and perfo= rming +the checks required for storage key protection as one operation (as oppose= d to +user space getting the storage keys, performing the checks, and accessing +memory thereafter, which could lead to a delay between check and access). +Absolute accesses are permitted for the VM ioctl if KVM_CAP_S390_MEM_OP_EX= TENSION +is > 0. +Currently absolute accesses are not permitted for VCPU ioctls. +Absolute accesses are permitted for non-protected guests only. + +Supported flags: + * ``KVM_S390_MEMOP_F_CHECK_ONLY`` + * ``KVM_S390_MEMOP_F_SKEY_PROTECTION`` + +The semantics of the flags are as for logical accesses. + +SIDA read/write: +^^^^^^^^^^^^^^^^ + +Access the secure instruction data area which contains memory operands nec= essary +for instruction emulation for protected guests. +SIDA accesses are available if the KVM_CAP_S390_PROTECTED capability is av= ailable. +SIDA accesses are permitted for the VCPU ioctl only. +SIDA accesses are permitted for protected guests only. =20 -The "reserved" field is meant for future extensions. It is not used by -KVM with the currently defined set of flags. +No flags are supported. =20 4.90 KVM_S390_GET_SKEYS ----------------------- diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 08756eeea065..dbc550bbd9fa 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -567,7 +567,7 @@ struct kvm_s390_mem_op { __u8 key; /* access key, ignored if flag unset */ }; __u32 sida_offset; /* offset into the sida */ - __u8 reserved[32]; /* should be set to 0 */ + __u8 reserved[32]; /* ignored */ }; }; /* types for kvm_s390_mem_op->op */ --=20 2.32.0 From nobody Sun Jun 28 05:31:09 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59792C433F5 for ; Fri, 11 Feb 2022 18:23:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352884AbiBKSXI (ORCPT ); Fri, 11 Feb 2022 13:23:08 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:33268 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352664AbiBKSWk (ORCPT ); Fri, 11 Feb 2022 13:22:40 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 83A6713A; Fri, 11 Feb 2022 10:22:29 -0800 (PST) Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21BG9Euh000420; Fri, 11 Feb 2022 18:22:29 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=mqGItTU/1dyFNrzrvn2cBlGISzWXV56J/m32nPA2Dao=; b=PXAU+SOVkozCCgi/NEUwDCULJdchPlTEbn9JMeSkMc3wf6LyT1g/5WqUAWdSTjOcgAv3 Ac1yajYLXN/T8hNWVHB8Oel3qAKGSnWE9/RIIKPReE4SxsKi11gJMflkxpdHdpir8jQN 6cBSWn1kmJRCyoa4sjB4nE8VdmPgEjEi9x+SOFJopTRBTu7nBrTlwOQHtOPWgY+1a3mp EtgasIAoDt9uloyNTisGSKNunY8xfsDyzDByGKL2r9EdSgJoFIhdTCB9GQvAD6v+Pns2 ugww/51M9heIks8fDEnlphl7Q7BrFvfa9BVErnS6eGNn4uZuaSjOhTlNHmYyE2LqFLHs Ug== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5rq56g0e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:28 +0000 Received: from m0098410.ppops.net (m0098410.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 21BI6S6D018384; Fri, 11 Feb 2022 18:22:28 GMT Received: from ppma02fra.de.ibm.com (47.49.7a9f.ip4.static.sl-reverse.com [159.122.73.71]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e5rq56fyg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:27 +0000 Received: from pps.filterd (ppma02fra.de.ibm.com [127.0.0.1]) by ppma02fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21BICLAo015218; Fri, 11 Feb 2022 18:22:25 GMT Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by ppma02fra.de.ibm.com with ESMTP id 3e1gva9kfc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 18:22:25 +0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21BIMMSA34013686 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Feb 2022 18:22:22 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E2DBA5204E; Fri, 11 Feb 2022 18:22:21 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id 79B1C52059; Fri, 11 Feb 2022 18:22:21 +0000 (GMT) From: Janis Schoetterl-Glausch To: Christian Borntraeger , Heiko Carstens , Janosch Frank Cc: Janis Schoetterl-Glausch , Alexander Gordeev , Claudio Imbrenda , David Hildenbrand , Jonathan Corbet , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Paolo Bonzini , Sven Schnelle , Vasily Gorbik Subject: [PATCH v4 10/10] KVM: s390: selftests: Test memops with storage keys Date: Fri, 11 Feb 2022 19:22:15 +0100 Message-Id: <20220211182215.2730017-11-scgl@linux.ibm.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220211182215.2730017-1-scgl@linux.ibm.com> References: <20220211182215.2730017-1-scgl@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: mK7rSgjPVm3hb5Qg05GMKS322IUZLvsB X-Proofpoint-GUID: Akr1e2BPYxamAwKBhC4E4msiiyzVAsos X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-11_05,2022-02-11_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 suspectscore=0 bulkscore=0 malwarescore=0 adultscore=0 priorityscore=1501 phishscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202110098 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Test vm and vcpu memops with storage keys, both successful accesses as well as various exception conditions. Signed-off-by: Janis Schoetterl-Glausch --- tools/testing/selftests/kvm/s390x/memop.c | 558 +++++++++++++++++++--- 1 file changed, 495 insertions(+), 63 deletions(-) diff --git a/tools/testing/selftests/kvm/s390x/memop.c b/tools/testing/self= tests/kvm/s390x/memop.c index 9f49ead380ab..ac08fd5aa746 100644 --- a/tools/testing/selftests/kvm/s390x/memop.c +++ b/tools/testing/selftests/kvm/s390x/memop.c @@ -13,28 +13,304 @@ #include "test_util.h" #include "kvm_util.h" =20 +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE - 1)) +#define CR0_FETCH_PROTECTION_OVERRIDE (1UL << (63 - 38)) +#define CR0_STORAGE_PROTECTION_OVERRIDE (1UL << (63 - 39)) + #define VCPU_ID 1 =20 +const uint64_t last_page_addr =3D UINT64_MAX - PAGE_SIZE + 1; + static uint8_t mem1[65536]; static uint8_t mem2[65536]; =20 +static void set_storage_key_range(void *addr, size_t len, u8 key) +{ + uintptr_t _addr, abs, i; + + _addr =3D (uintptr_t)addr; + for (i =3D _addr & PAGE_MASK; i < _addr + len; i +=3D PAGE_SIZE) { + abs =3D i; + asm volatile ( + "lra %[abs], 0(0,%[abs])\n" + " sske %[key], %[abs]\n" + : [abs] "+&a" (abs) + : [key] "r" (key) + : "cc" + ); + } +} + static void guest_code(void) +{ + /* Set storage key */ + set_storage_key_range(mem1, sizeof(mem1), 0x90); + set_storage_key_range(mem2, sizeof(mem2), 0x90); + GUEST_SYNC(0); + + /* Write, read back, without keys */ + memcpy(mem2, mem1, sizeof(mem2)); + GUEST_SYNC(10); + + /* Write, read back, key 0 */ + memcpy(mem2, mem1, sizeof(mem2)); + GUEST_SYNC(20); + + /* Write, read back, matching key, 1 page */ + memcpy(mem2, mem1, sizeof(mem2)); + GUEST_SYNC(30); + + /* Write, read back, matching key, all pages */ + memcpy(mem2, mem1, sizeof(mem2)); + GUEST_SYNC(40); + + /* Set fetch protection */ + set_storage_key_range(0, 1, 0x18); + GUEST_SYNC(50); + + /* Enable fetch protection override */ + GUEST_SYNC(60); + + /* Enable storage protection override, set fetch protection*/ + set_storage_key_range(mem1, sizeof(mem1), 0x98); + set_storage_key_range(mem2, sizeof(mem2), 0x98); + GUEST_SYNC(70); + + /* Write, read back, mismatching key, + * storage protection override, all pages + */ + memcpy(mem2, mem1, sizeof(mem2)); + GUEST_SYNC(80); + + /* VM memop, write, read back, matching key */ + memcpy(mem2, mem1, sizeof(mem2)); + GUEST_SYNC(90); + + /* VM memop, write, read back, key 0 */ + memcpy(mem2, mem1, sizeof(mem2)); + /* VM memop, fail to read from 0 absolute/virtual, mismatching key, + * fetch protection override does not apply to VM memops + */ + asm volatile ("sske %1,%0\n" + : : "r"(0), "r"(0x18) : "cc" + ); + GUEST_SYNC(100); + + /* Enable AR mode */ + GUEST_SYNC(110); + + /* Disable AR mode */ + GUEST_SYNC(120); +} + +static void reroll_mem1(void) { int i; =20 - for (;;) { - for (i =3D 0; i < sizeof(mem2); i++) - mem2[i] =3D mem1[i]; - GUEST_SYNC(0); - } + for (i =3D 0; i < sizeof(mem1); i++) + mem1[i] =3D rand(); +} + +static int _vcpu_read_guest(struct kvm_vm *vm, void *host_addr, + uintptr_t guest_addr, size_t len) +{ + struct kvm_s390_mem_op ksmo =3D { + .gaddr =3D guest_addr, + .flags =3D 0, + .size =3D len, + .op =3D KVM_S390_MEMOP_LOGICAL_READ, + .buf =3D (uintptr_t)host_addr, + .ar =3D 0, + }; + + return _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); +} + +static void vcpu_read_guest(struct kvm_vm *vm, void *host_addr, + uintptr_t guest_addr, size_t len) +{ + int rv; + + rv =3D _vcpu_read_guest(vm, host_addr, guest_addr, len); + TEST_ASSERT(rv =3D=3D 0, "vcpu memop read failed: reason =3D %d\n", rv); +} + +static int _vcpu_read_guest_key(struct kvm_vm *vm, void *host_addr, + uintptr_t guest_addr, size_t len, u8 access_key) +{ + struct kvm_s390_mem_op ksmo =3D {0}; + + ksmo.gaddr =3D guest_addr; + ksmo.flags =3D KVM_S390_MEMOP_F_SKEY_PROTECTION; + ksmo.size =3D len; + ksmo.op =3D KVM_S390_MEMOP_LOGICAL_READ; + ksmo.buf =3D (uintptr_t)host_addr; + ksmo.ar =3D 0; + ksmo.key =3D access_key; + + return _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); +} + +static void vcpu_read_guest_key(struct kvm_vm *vm, void *host_addr, + uintptr_t guest_addr, size_t len, u8 access_key) +{ + int rv; + + rv =3D _vcpu_read_guest_key(vm, host_addr, guest_addr, len, access_key); + TEST_ASSERT(rv =3D=3D 0, "vcpu memop read failed: reason =3D %d\n", rv); +} + +static int _vcpu_write_guest(struct kvm_vm *vm, uintptr_t guest_addr, + void *host_addr, size_t len) +{ + struct kvm_s390_mem_op ksmo =3D { + .gaddr =3D guest_addr, + .flags =3D 0, + .size =3D len, + .op =3D KVM_S390_MEMOP_LOGICAL_WRITE, + .buf =3D (uintptr_t)host_addr, + .ar =3D 0, + }; + return _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); +} + +static void vcpu_write_guest(struct kvm_vm *vm, uintptr_t guest_addr, + void *host_addr, size_t len) +{ + int rv; + + rv =3D _vcpu_write_guest(vm, guest_addr, host_addr, len); + TEST_ASSERT(rv =3D=3D 0, "vcpu memop write failed: reason =3D %d\n", rv); +} + +static int _vcpu_write_guest_key(struct kvm_vm *vm, uintptr_t guest_addr, + void *host_addr, size_t len, u8 access_key) +{ + struct kvm_s390_mem_op ksmo =3D {0}; + + ksmo.gaddr =3D guest_addr; + ksmo.flags =3D KVM_S390_MEMOP_F_SKEY_PROTECTION; + ksmo.size =3D len; + ksmo.op =3D KVM_S390_MEMOP_LOGICAL_WRITE; + ksmo.buf =3D (uintptr_t)host_addr; + ksmo.ar =3D 0; + ksmo.key =3D access_key; + + return _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); +} + +static void vcpu_write_guest_key(struct kvm_vm *vm, uintptr_t guest_addr, + void *host_addr, size_t len, u8 access_key) +{ + int rv; + + rv =3D _vcpu_write_guest_key(vm, guest_addr, host_addr, len, access_key); + TEST_ASSERT(rv =3D=3D 0, "vcpu memop write failed: reason =3D %d\n", rv); +} + +static int _vm_read_guest_key(struct kvm_vm *vm, void *host_addr, + uintptr_t guest_addr, size_t len, u8 access_key) +{ + struct kvm_s390_mem_op ksmo =3D {0}; + + ksmo.gaddr =3D guest_addr; + ksmo.flags =3D KVM_S390_MEMOP_F_SKEY_PROTECTION; + ksmo.size =3D len; + ksmo.op =3D KVM_S390_MEMOP_ABSOLUTE_READ; + ksmo.buf =3D (uintptr_t)host_addr; + ksmo.key =3D access_key; + + return _vm_ioctl(vm, KVM_S390_MEM_OP, &ksmo); +} + +static void vm_read_guest_key(struct kvm_vm *vm, void *host_addr, + uintptr_t guest_addr, size_t len, u8 access_key) +{ + int rv; + + rv =3D _vm_read_guest_key(vm, host_addr, guest_addr, len, access_key); + TEST_ASSERT(rv =3D=3D 0, "vm memop read failed: reason =3D %d\n", rv); +} + +static int _vm_write_guest_key(struct kvm_vm *vm, uintptr_t guest_addr, + void *host_addr, size_t len, u8 access_key) +{ + struct kvm_s390_mem_op ksmo =3D {0}; + + ksmo.gaddr =3D guest_addr; + ksmo.flags =3D KVM_S390_MEMOP_F_SKEY_PROTECTION; + ksmo.size =3D len; + ksmo.op =3D KVM_S390_MEMOP_ABSOLUTE_WRITE; + ksmo.buf =3D (uintptr_t)host_addr; + ksmo.key =3D access_key; + + return _vm_ioctl(vm, KVM_S390_MEM_OP, &ksmo); +} + +static void vm_write_guest_key(struct kvm_vm *vm, uintptr_t guest_addr, + void *host_addr, size_t len, u8 access_key) +{ + int rv; + + rv =3D _vm_write_guest_key(vm, guest_addr, host_addr, len, access_key); + TEST_ASSERT(rv =3D=3D 0, "vm memop write failed: reason =3D %d\n", rv); } =20 +enum access_mode { + ACCESS_READ, + ACCESS_WRITE +}; + +static int _vm_check_guest_key(struct kvm_vm *vm, enum access_mode mode, + uintptr_t guest_addr, size_t len, u8 access_key) +{ + struct kvm_s390_mem_op ksmo =3D {0}; + + ksmo.gaddr =3D guest_addr; + ksmo.flags =3D KVM_S390_MEMOP_F_CHECK_ONLY | KVM_S390_MEMOP_F_SKEY_PROTEC= TION; + ksmo.size =3D len; + if (mode =3D=3D ACCESS_READ) + ksmo.op =3D KVM_S390_MEMOP_ABSOLUTE_READ; + else + ksmo.op =3D KVM_S390_MEMOP_ABSOLUTE_WRITE; + ksmo.key =3D access_key; + + return _vm_ioctl(vm, KVM_S390_MEM_OP, &ksmo); +} + +static void vm_check_guest_key(struct kvm_vm *vm, enum access_mode mode, + uintptr_t guest_addr, size_t len, u8 access_key) +{ + int rv; + + rv =3D _vm_check_guest_key(vm, mode, guest_addr, len, access_key); + TEST_ASSERT(rv =3D=3D 0, "vm memop write failed: reason =3D %d\n", rv); +} + +#define HOST_SYNC(vmp, stage) \ +({ \ + struct kvm_vm *__vm =3D (vmp); \ + struct ucall uc; \ + int __stage =3D (stage); \ + \ + vcpu_run(__vm, VCPU_ID); \ + get_ucall(__vm, VCPU_ID, &uc); \ + ASSERT_EQ(uc.cmd, UCALL_SYNC); \ + ASSERT_EQ(uc.args[1], __stage); \ +}) \ + int main(int argc, char *argv[]) { struct kvm_vm *vm; struct kvm_run *run; struct kvm_s390_mem_op ksmo; - int rv, i, maxsize; + bool has_skey_ext; + vm_vaddr_t guest_mem1; + vm_vaddr_t guest_mem2; + vm_paddr_t guest_mem1_abs; + int rv, maxsize; =20 setbuf(stdout, NULL); /* Tell stdout not to buffer its content */ =20 @@ -45,67 +321,225 @@ int main(int argc, char *argv[]) } if (maxsize > sizeof(mem1)) maxsize =3D sizeof(mem1); + has_skey_ext =3D kvm_check_cap(KVM_CAP_S390_MEM_OP_EXTENSION); + if (!has_skey_ext) + print_skip("Storage key extension not supported"); =20 /* Create VM */ vm =3D vm_create_default(VCPU_ID, 0, guest_code); run =3D vcpu_state(vm, VCPU_ID); + guest_mem1 =3D (uintptr_t)mem1; + guest_mem2 =3D (uintptr_t)mem2; + guest_mem1_abs =3D addr_gva2gpa(vm, guest_mem1); =20 - for (i =3D 0; i < sizeof(mem1); i++) - mem1[i] =3D i * i + i; + /* Set storage key */ + HOST_SYNC(vm, 0); =20 - /* Set the first array */ - ksmo.gaddr =3D addr_gva2gpa(vm, (uintptr_t)mem1); - ksmo.flags =3D 0; - ksmo.size =3D maxsize; - ksmo.op =3D KVM_S390_MEMOP_LOGICAL_WRITE; - ksmo.buf =3D (uintptr_t)mem1; - ksmo.ar =3D 0; - vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); + /* Write, read back, without keys */ + reroll_mem1(); + vcpu_write_guest(vm, guest_mem1, mem1, maxsize); + HOST_SYNC(vm, 10); // Copy in vm + memset(mem2, 0xaa, sizeof(mem2)); + vcpu_read_guest(vm, mem2, guest_mem2, maxsize); + TEST_ASSERT(!memcmp(mem1, mem2, maxsize), + "Memory contents do not match!"); =20 - /* Let the guest code copy the first array to the second */ - vcpu_run(vm, VCPU_ID); - TEST_ASSERT(run->exit_reason =3D=3D KVM_EXIT_S390_SIEIC, - "Unexpected exit reason: %u (%s)\n", - run->exit_reason, - exit_reason_str(run->exit_reason)); + if (has_skey_ext) { + vm_vaddr_t guest_0_page =3D vm_vaddr_alloc(vm, PAGE_SIZE, 0); + vm_vaddr_t guest_last_page =3D vm_vaddr_alloc(vm, PAGE_SIZE, last_page_a= ddr); + vm_paddr_t guest_mem2_abs =3D addr_gva2gpa(vm, guest_mem2); =20 - memset(mem2, 0xaa, sizeof(mem2)); + /* Write, read back, key 0 */ + reroll_mem1(); + vcpu_write_guest_key(vm, guest_mem1, mem1, maxsize, 0); + HOST_SYNC(vm, 20); // Copy in vm + memset(mem2, 0xaa, sizeof(mem2)); + vcpu_read_guest_key(vm, mem2, guest_mem2, maxsize, 0); + TEST_ASSERT(!memcmp(mem1, mem2, maxsize), + "Memory contents do not match!"); =20 - /* Get the second array */ - ksmo.gaddr =3D (uintptr_t)mem2; - ksmo.flags =3D 0; - ksmo.size =3D maxsize; - ksmo.op =3D KVM_S390_MEMOP_LOGICAL_READ; - ksmo.buf =3D (uintptr_t)mem2; - ksmo.ar =3D 0; - vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); + /* Write, read back, matching key, 1 page */ + reroll_mem1(); + vcpu_write_guest_key(vm, guest_mem1, mem1, PAGE_SIZE, 9); + HOST_SYNC(vm, 30); // Copy in vm + memset(mem2, 0xaa, sizeof(mem2)); + vcpu_read_guest_key(vm, mem2, guest_mem2, PAGE_SIZE, 9); + TEST_ASSERT(!memcmp(mem1, mem2, PAGE_SIZE), + "Memory contents do not match!"); =20 - TEST_ASSERT(!memcmp(mem1, mem2, maxsize), - "Memory contents do not match!"); + /* Write, read back, matching key, all pages */ + reroll_mem1(); + vcpu_write_guest_key(vm, guest_mem1, mem1, maxsize, 9); + HOST_SYNC(vm, 40); // Copy in vm + memset(mem2, 0xaa, sizeof(mem2)); + vcpu_read_guest_key(vm, mem2, guest_mem2, maxsize, 9); + TEST_ASSERT(!memcmp(mem1, mem2, maxsize), + "Memory contents do not match!"); =20 - /* Check error conditions - first bad size: */ - ksmo.gaddr =3D (uintptr_t)mem1; - ksmo.flags =3D 0; - ksmo.size =3D -1; - ksmo.op =3D KVM_S390_MEMOP_LOGICAL_WRITE; - ksmo.buf =3D (uintptr_t)mem1; - ksmo.ar =3D 0; - rv =3D _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); + /* Fail to write, read back old value, mismatching key */ + rv =3D _vcpu_write_guest_key(vm, guest_mem1, mem1, maxsize, 2); + TEST_ASSERT(rv =3D=3D 4, "Store should result in protection exception"); + memset(mem2, 0xaa, sizeof(mem2)); + vcpu_read_guest_key(vm, mem2, guest_mem2, maxsize, 2); + TEST_ASSERT(!memcmp(mem1, mem2, maxsize), + "Memory contents do not match!"); + + /* Set fetch protection */ + HOST_SYNC(vm, 50); + + /* Write without key, read back, matching key, fetch protection */ + reroll_mem1(); + vcpu_write_guest(vm, guest_0_page, mem1, PAGE_SIZE); + memset(mem2, 0xaa, sizeof(mem2)); + /* Lets not copy in the guest, in case guest_0_page !=3D 0 */ + vcpu_read_guest_key(vm, mem2, guest_0_page, PAGE_SIZE, 1); + TEST_ASSERT(!memcmp(mem1, mem2, PAGE_SIZE), + "Memory contents do not match!"); + + /* Fail to read, mismatching key, fetch protection */ + rv =3D _vcpu_read_guest_key(vm, mem2, guest_0_page, PAGE_SIZE, 2); + TEST_ASSERT(rv =3D=3D 4, "Fetch should result in protection exception"); + + /* Enable fetch protection override */ + run->s.regs.crs[0] |=3D CR0_FETCH_PROTECTION_OVERRIDE; + run->kvm_dirty_regs =3D KVM_SYNC_CRS; + HOST_SYNC(vm, 60); + + if (guest_0_page !=3D 0) + print_skip("Did not allocate page at 0 for fetch protection override te= st"); + + /* Write without key, read back, mismatching key, + * fetch protection override, 1 page + */ + if (guest_0_page =3D=3D 0) { + reroll_mem1(); + vcpu_write_guest(vm, guest_0_page, mem1, PAGE_SIZE); + memset(mem2, 0xaa, sizeof(mem2)); + /* Lets not copy in the guest, in case guest_0_page !=3D 0 */ + vcpu_read_guest_key(vm, mem2, guest_0_page, 2048, 2); + TEST_ASSERT(!memcmp(mem1, mem2, 2048), + "Memory contents do not match!"); + } + + /* Fail to read, mismatching key, + * fetch protection override address exceeded, 1 page + */ + if (guest_0_page =3D=3D 0) { + rv =3D _vcpu_read_guest_key(vm, mem2, 0, 2048 + 1, 2); + TEST_ASSERT(rv =3D=3D 4, + "Fetch should result in protection exception"); + } + + if (guest_last_page !=3D last_page_addr) + print_skip("Did not allocate last page for fetch protection override te= st"); + + /* Write without key, read back, mismatching key, + * fetch protection override, 2 pages, last page not fetch protected + */ + reroll_mem1(); + vcpu_write_guest(vm, guest_last_page, mem1, PAGE_SIZE); + vcpu_write_guest(vm, guest_0_page, mem1 + PAGE_SIZE, PAGE_SIZE); + if (guest_0_page =3D=3D 0 && guest_last_page =3D=3D last_page_addr) { + memset(mem2, 0xaa, sizeof(mem2)); + /* Lets not copy in the guest, in case guest_0_page !=3D 0 */ + vcpu_read_guest_key(vm, mem2, last_page_addr, + PAGE_SIZE + 2048, 2); + TEST_ASSERT(!memcmp(mem1, mem2, PAGE_SIZE + 2048), + "Memory contents do not match!"); + } + + /* Fail to read, mismatching key, fetch protection override address + * exceeded, 2 pages, last page not fetch protected + */ + if (guest_0_page =3D=3D 0 && guest_last_page =3D=3D last_page_addr) { + rv =3D _vcpu_read_guest_key(vm, mem2, last_page_addr, + PAGE_SIZE + 2048 + 1, 2); + TEST_ASSERT(rv =3D=3D 4, + "Fetch should result in protection exception"); + } + + /* Enable storage protection override, set fetch protection*/ + run->s.regs.crs[0] |=3D CR0_STORAGE_PROTECTION_OVERRIDE; + run->kvm_dirty_regs =3D KVM_SYNC_CRS; + HOST_SYNC(vm, 70); + + /* Write, read back, mismatching key, + * storage protection override, all pages + */ + reroll_mem1(); + vcpu_write_guest_key(vm, guest_mem1, mem1, maxsize, 2); + HOST_SYNC(vm, 80); // Copy in vm + memset(mem2, 0xaa, sizeof(mem2)); + vcpu_read_guest_key(vm, mem2, guest_mem2, maxsize, 2); + TEST_ASSERT(!memcmp(mem1, mem2, maxsize), + "Memory contents do not match!"); + + /* VM memop, write, read back, matching key */ + reroll_mem1(); + vm_write_guest_key(vm, guest_mem1_abs, mem1, maxsize, 9); + HOST_SYNC(vm, 90); // Copy in vm + memset(mem2, 0xaa, sizeof(mem2)); + vm_read_guest_key(vm, mem2, guest_mem2_abs, maxsize, 9); + TEST_ASSERT(!memcmp(mem1, mem2, maxsize), + "Memory contents do not match!"); + vm_check_guest_key(vm, ACCESS_WRITE, guest_mem1_abs, maxsize, 9); + vm_check_guest_key(vm, ACCESS_READ, guest_mem2_abs, maxsize, 9); + + /* VM memop, write, read back, key 0 */ + reroll_mem1(); + vm_write_guest_key(vm, guest_mem1_abs, mem1, maxsize, 0); + HOST_SYNC(vm, 100); // Copy in vm + memset(mem2, 0xaa, sizeof(mem2)); + vm_read_guest_key(vm, mem2, guest_mem2_abs, maxsize, 0); + TEST_ASSERT(!memcmp(mem1, mem2, maxsize), + "Memory contents do not match!"); + rv =3D _vm_check_guest_key(vm, ACCESS_READ, guest_mem1_abs, maxsize, 9); + TEST_ASSERT(rv =3D=3D 0, "Check should succeed"); + vm_check_guest_key(vm, ACCESS_WRITE, guest_mem1_abs, maxsize, 0); + vm_check_guest_key(vm, ACCESS_READ, guest_mem2_abs, maxsize, 0); + + /* VM memop, fail to write, fail to read, mismatching key, + * storage protection override does not apply to VM memops + */ + rv =3D _vm_write_guest_key(vm, guest_mem1_abs, mem1, maxsize, 2); + TEST_ASSERT(rv =3D=3D 4, "Store should result in protection exception"); + rv =3D _vm_read_guest_key(vm, mem2, guest_mem2_abs, maxsize, 2); + TEST_ASSERT(rv =3D=3D 4, "Fetch should result in protection exception"); + rv =3D _vm_check_guest_key(vm, ACCESS_WRITE, guest_mem1_abs, maxsize, 2); + TEST_ASSERT(rv =3D=3D 4, "Check should indicate protection exception"); + rv =3D _vm_check_guest_key(vm, ACCESS_READ, guest_mem2_abs, maxsize, 2); + TEST_ASSERT(rv =3D=3D 4, "Check should indicate protection exception"); + + /* VM memop, fail to read from 0 absolute/virtual, mismatching key, + * fetch protection override does not apply to VM memops + */ + rv =3D _vm_read_guest_key(vm, mem2, 0, 2048, 2); + TEST_ASSERT(rv !=3D 0, "Fetch should result in exception"); + rv =3D _vm_read_guest_key(vm, mem2, addr_gva2gpa(vm, 0), 2048, 2); + TEST_ASSERT(rv =3D=3D 4, "Fetch should result in protection exception"); + } else { + struct ucall uc; + + do { + vcpu_run(vm, VCPU_ID); + get_ucall(vm, VCPU_ID, &uc); + ASSERT_EQ(uc.cmd, UCALL_SYNC); + } while (uc.args[1] < 100); + } + + /* Check error conditions */ + + /* Bad size: */ + rv =3D _vcpu_write_guest(vm, (uintptr_t)mem1, mem1, -1); TEST_ASSERT(rv =3D=3D -1 && errno =3D=3D E2BIG, "ioctl allows insane size= s"); =20 /* Zero size: */ - ksmo.gaddr =3D (uintptr_t)mem1; - ksmo.flags =3D 0; - ksmo.size =3D 0; - ksmo.op =3D KVM_S390_MEMOP_LOGICAL_WRITE; - ksmo.buf =3D (uintptr_t)mem1; - ksmo.ar =3D 0; - rv =3D _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); + rv =3D _vcpu_write_guest(vm, (uintptr_t)mem1, mem1, 0); TEST_ASSERT(rv =3D=3D -1 && (errno =3D=3D EINVAL || errno =3D=3D ENOMEM), "ioctl allows 0 as size"); =20 /* Bad flags: */ - ksmo.gaddr =3D (uintptr_t)mem1; + ksmo.gaddr =3D guest_mem1; ksmo.flags =3D -1; ksmo.size =3D maxsize; ksmo.op =3D KVM_S390_MEMOP_LOGICAL_WRITE; @@ -115,7 +549,7 @@ int main(int argc, char *argv[]) TEST_ASSERT(rv =3D=3D -1 && errno =3D=3D EINVAL, "ioctl allows all flags"= ); =20 /* Bad operation: */ - ksmo.gaddr =3D (uintptr_t)mem1; + ksmo.gaddr =3D guest_mem1; ksmo.flags =3D 0; ksmo.size =3D maxsize; ksmo.op =3D -1; @@ -135,21 +569,17 @@ int main(int argc, char *argv[]) TEST_ASSERT(rv > 0, "ioctl does not report bad guest memory access"); =20 /* Bad host address: */ - ksmo.gaddr =3D (uintptr_t)mem1; - ksmo.flags =3D 0; - ksmo.size =3D maxsize; - ksmo.op =3D KVM_S390_MEMOP_LOGICAL_WRITE; - ksmo.buf =3D 0; - ksmo.ar =3D 0; - rv =3D _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); + rv =3D _vcpu_write_guest(vm, guest_mem1, 0, maxsize); TEST_ASSERT(rv =3D=3D -1 && errno =3D=3D EFAULT, "ioctl does not report bad host memory address"); =20 - /* Bad access register: */ + /* Enable AR mode */ run->psw_mask &=3D ~(3UL << (63 - 17)); - run->psw_mask |=3D 1UL << (63 - 17); /* Enable AR mode */ - vcpu_run(vm, VCPU_ID); /* To sync new state to SIE block */ - ksmo.gaddr =3D (uintptr_t)mem1; + run->psw_mask |=3D 1UL << (63 - 17); + HOST_SYNC(vm, 110); + + /* Bad access register: */ + ksmo.gaddr =3D guest_mem1; ksmo.flags =3D 0; ksmo.size =3D maxsize; ksmo.op =3D KVM_S390_MEMOP_LOGICAL_WRITE; @@ -157,8 +587,10 @@ int main(int argc, char *argv[]) ksmo.ar =3D 17; rv =3D _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); TEST_ASSERT(rv =3D=3D -1 && errno =3D=3D EINVAL, "ioctl allows ARs > 15"); - run->psw_mask &=3D ~(3UL << (63 - 17)); /* Disable AR mode */ - vcpu_run(vm, VCPU_ID); /* Run to sync new state */ + + /* Disable AR mode */ + run->psw_mask &=3D ~(3UL << (63 - 17)); + HOST_SYNC(vm, 120); =20 kvm_vm_free(vm); =20 --=20 2.32.0