From nobody Tue Apr 7 19:50:53 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 8693BC28D13 for ; Thu, 25 Aug 2022 06:24:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235156AbiHYGYK (ORCPT ); Thu, 25 Aug 2022 02:24:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33828 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230127AbiHYGYI (ORCPT ); Thu, 25 Aug 2022 02:24:08 -0400 Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-eopbgr80044.outbound.protection.outlook.com [40.107.8.44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1839CA00F5 for ; Wed, 24 Aug 2022 23:24:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=C0gm+MJlJ8/JEXp8xK3BKAs/ad/A5ohQrvIXrDPEuY29EEHNkfCHmNpR00MEgmUxzftK2jp8M4Y86NhHD1naHUbmhRpsMXBKeIe/E4mrw0J/amXZgZDFhRgjQyc+CQEP1Bdjp5Tc35xeJVspjYl7TwN+eFVhoXdPWS7nlVdSr6kNWyUF/2iKy9KMwTmJp1Sg0jtN+hAyjkT9UtnufZbsTKigWxpeXxc0sk2Qc5isu0ra+sW7MIhxTweroaIquzSOiuipfQdkeR/VSgsB+1K1ZS5Ke4DMkhqJ/+l6YvIwCzasWWE+Up/8TK0KNC+dpkp98SEgGOPuEzW834zZ1d3pYQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=yinKPj8hAy6AHMAEACuEciP0kQPa8xPbmQ/xVuemKxU=; b=YUoHI/0UkT7x5AVjpsIoWWzhRK4io9kf/dl2kOMVDHlZ23/0zguVkOBi4UkyKk8Eljlw3tQkTZT4IZiaEMBYj++X5Znl/Zs5bt8WYZ6tkDiQ/wuqRUrP0eL9Iv+pYcwZLrZSRQHnVE4DQ6ayurM9WqhbON5xWawfSGwZv2nBknHwzWt9viIK4sJ0OiUJw6aCKEOTjHYR4/iOclypFTmCTxyLAUdtiCAGVY80tD6ArB8hubLpJ1OdHXQDr7zSUc/O6EgSA42LE31UPJg7SZQ3ppEtMsY5YO1iNEDbW5jNph01TrymclxFFpRFrb5cxXrR+vXVfjpGl7XeapMNai3D/A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=sap.com; dmarc=pass action=none header.from=sap.com; dkim=pass header.d=sap.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sap.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=yinKPj8hAy6AHMAEACuEciP0kQPa8xPbmQ/xVuemKxU=; b=Uy2lWwbmINOztgpW+NnGmps/IJXvaMmsPm97isE9oWO0I1fx/ssz4r0L7wLCm5DJfjHYnAMP6BOEat4jRTltgS4PdcyHZQc+IrlRdQfrnfUVX5DqFV87MOV72GEuZah7jAb+TLCfU9OnCIxEWeuhKpIw9iQrkcAnVlvaAFqHkNrKsUN/+jWksI8D2QoJ52yQsA6vX3Ei4IAAXNRMfPQyueA5d2ePNibij7JvRsPqqTlOi+8U0FAmr9CDgMqGIOPiZMn9uK5t94sh22ToCElfJ6N+KayIS/hKxQnTGE4u0UTNL1riJldm+Q3l05N9p7L+Pg9exXp54nygMjYm2UtX2Q== Received: from PAXPR02MB7310.eurprd02.prod.outlook.com (2603:10a6:102:1c5::10) by DB3PR0202MB3484.eurprd02.prod.outlook.com (2603:10a6:8:2::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5566.15; Thu, 25 Aug 2022 06:24:02 +0000 Received: from PAXPR02MB7310.eurprd02.prod.outlook.com ([fe80::25a4:e5d5:aefc:fe46]) by PAXPR02MB7310.eurprd02.prod.outlook.com ([fe80::25a4:e5d5:aefc:fe46%9]) with mapi id 15.20.5566.015; Thu, 25 Aug 2022 06:24:02 +0000 From: "Czerwacki, Eial" To: "linux-kernel@vger.kernel.org" CC: "Arsh, Leonid" , "Twaig, Oren" , SAP vSMP Linux Maintainer , Greg Kroah-Hartman , Arnd Bergmann , Dan Carpenter , Andra Paraschiv , Borislav Petkov , Brijesh Singh , Eric Biggers , Fei Li , Hans de Goede , Jens Axboe , Mauro Carvalho Chehab Subject: [PATCH v2] drivers/virt/vSMP: new driver Thread-Topic: [PATCH v2] drivers/virt/vSMP: new driver Thread-Index: AQHYuErwCwPojP5fak60UhGlJnJEow== Date: Thu, 25 Aug 2022 06:24:02 +0000 Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: msip_labels: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=sap.com; x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 45ee7d60-6b08-4e2f-8bb8-08da86626773 x-ms-traffictypediagnostic: DB3PR0202MB3484:EE_ x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: NZu2X7LbMtoZ24PxIGTsF5a1r0ddInDyaGc2TDAv/Mz4Qxx8rtjP+euCnd4zauEVIPOFh4MAbAMtb5ZBx17ZJRfAW6OxOd9zLPwXahhBEhyHuxj7U4c2mwC1EwBg3/LP2x9nxO8kWfXXmDUrw6X4QDHb/rqL1kEp44ZGhEi5s+zdy4OO1kzI08GXERmHcWFAsulhAiUa39RcKD8lFxc4s5XrWD2A0GL3j/ggVRSg2E9M8Wc3xVnJeAaFx1yyAdAaqrZ1ByA61SHI95b8JGPBQTohyR2FvJYkVWU76ERZYHCfQfqlIImOa/igP9IygbYtw/zcgDlnain0dq3BoLvQVmJktVDox2G3bTlIBJhC3RYgz7gZXyBNENzv3TkNYDkoJUKYnEqreeYZ67VwNcQt3zY0ykD9+/fXnkFD/myCDgN9Zsg2FPzxAUCG79IP/VehyEVXvpaOOtkCzDlVhKRYE5KuLvPqk0YmSgLJgyLfiVE04gF0jXDWUYpFp7xVBG0/XLe09o4JsDhao9B3FJKxQUo7kcLwrmLViQXOfQ6QaOkkeuWvzqDfq8zEwQFwpHKFSczP898ykJ190mM2hfVn7gdil+elPVgUFcPuXfQ0GgPPZZXMD30BpN+WhPFDVwFKguvA6gmWJuZqocUo1HaTErWHL0vQWcs1h9AF5AMaHFvVG23EOLdFQzjZbvVwUqmrfOMlKqbyO08Hl6q/felcERuxpOJP3dxP2cjJMiLrxb0/+XH2JK+nY7QeBw1MrLZjI/8kI18CafJup5qcg99bgQ== x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PAXPR02MB7310.eurprd02.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230016)(4636009)(39860400002)(136003)(396003)(366004)(346002)(376002)(66446008)(186003)(64756008)(4326008)(8936002)(8676002)(38100700002)(66476007)(7416002)(71200400001)(66556008)(5660300002)(30864003)(52536014)(122000001)(76116006)(91956017)(66946007)(54906003)(6916009)(478600001)(33656002)(26005)(316002)(86362001)(41300700001)(82960400001)(9686003)(2906002)(55016003)(83380400001)(38070700005)(6506007)(7696005)(579004);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?Q?p2Vi2KVqzRjRWdpih/bgdvZS7VtNyS+QneM4EI9W4lP9l/HhOQ85aUAFGL?= =?iso-8859-1?Q?pr2BaprG9xEcYNYdvliQEiZBPH0JIQsIgR4sxLBV20IkgIKqVqDHtTgqm7?= =?iso-8859-1?Q?jWeU0hUvr/lSofDsOPLVx1H9W4Sfaqk/4EJ9+qUF0APKIjjJbxUWAmAPRD?= =?iso-8859-1?Q?IPbMQ6M/eJa3a1crGwbcnFjH7/rdyc6/oeyL0/WiwFs8hzOg5cFr22jHRU?= =?iso-8859-1?Q?xvYbivN8lzjyStdA1Dnx+p0WJ6HZ8vmNguHR26qFx4LjXYXDnBg9bgzhIM?= =?iso-8859-1?Q?hm7HUW26aX7U/ieGigBes58rXKz7E6rbsbPYLqpw3hfJLImBdozukzQsGf?= =?iso-8859-1?Q?8TskOMqK6uwZRutZNZB29A5bdHtipgf7fCXJ1pABa8CZzK5Lx1cDCaiYrB?= =?iso-8859-1?Q?+t0Ea4jk4/Do114YRAQTiFghzG8+83LHWvp4P1xpceWrGd1uTYIypOJ2tU?= =?iso-8859-1?Q?e8S4AHNjQ4HoHi/EMCraqPTNDnXIDTbXfUWrVOlCWpzvLNNsclhEWpWP8b?= =?iso-8859-1?Q?k5ExEMOmagBOsuBJqU29rWPNyvu0De0io8ucTignBYmn3B0A2kNNckvdpl?= =?iso-8859-1?Q?EedNxQqEfq+IC40ZsqyYmRWX+V7VCqozMjqTL3kCWDd4sKVrByelUMkRx9?= =?iso-8859-1?Q?pPB2MYjkrEk5/nQBpQEyKTPdCPlW4VllknMJbQ0YnYn7Tm1N4EjpNyq+8W?= =?iso-8859-1?Q?tfcXAMELl0ZB38AkmzbDl/cl6E3WldTj9+07X27OoS29fnmb74P2y7VBd6?= =?iso-8859-1?Q?+K3yvGpvI+bwtV+k95Z8+nQmHpawxZRnwr+Xh91WmpJuDirI45uYSIZ9ld?= =?iso-8859-1?Q?mW/WksVIiHHh27LWy2DxvBfQP0YQXiY41iP4LvNe1kn9a/9n5CSgoOfv+R?= =?iso-8859-1?Q?18DT4/jKKCRh5wpiGO40SRLg/whByVGW2UTstGR6NoL/J+8iGOHPyV1H/0?= =?iso-8859-1?Q?celaSq2CrrN5k4dOlHX+opfgHg8YfPR261YMJIhpEozaEQyIdNfaVzUSpF?= =?iso-8859-1?Q?YvcfkO4ZVTb6O1OMCj9tvNCVZGBUj2+x2rlhmnRCH3qDKjKmF+MErt7uV9?= =?iso-8859-1?Q?5jfKOhVo6EPFXfe3aShAvDiw1Z0KQcVFirSKi18wWNvCjtz4+3rzJWcVl+?= =?iso-8859-1?Q?AWx0FTVQmYQLxlBGu0qSXZUmmcddUE1QDeaM1OKET39x0LDUfBNaz7aZD3?= =?iso-8859-1?Q?itVSE5WhXusLNk8MWode4vx5RDqoJ0Ew4u1wnctUK7vNkDMRrqaCh9W6Li?= =?iso-8859-1?Q?IVNLB41QRhl6k/P95FkdSNUoCwU72WheOFmhqWN4fwIAINHnaJb2M0OqWi?= =?iso-8859-1?Q?ybsUtoOmhSW6IOTlVn97pnewpAc5bWb3uC5t+u8k53DQJurDH1RszmUySh?= =?iso-8859-1?Q?owaR1X1yHUsYrWAWL1qeIXuMT45VEZ6bKSk2XZmr8bbwaVaFrCZrDj2Z3j?= =?iso-8859-1?Q?sldNNTx4+A3hOwZfXQ/kUigjRGECBSDkMUcBAgorAsE1bTKJt5a5b2ejJs?= =?iso-8859-1?Q?IOtntJbhKz5wz+FLWskRm/KVseokt3GDsrPHH//r8tFwlqQULsYMX6jyql?= =?iso-8859-1?Q?ckMvonlQrG4eMZwNc6cOkDtm56YsBeWdmIMCu06+/n8KxXdKph7XtIDo5t?= =?iso-8859-1?Q?I9DVeyumL6kq8XP9jBAlAK3S9hGsDQ9ulk?= Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: sap.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: PAXPR02MB7310.eurprd02.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 45ee7d60-6b08-4e2f-8bb8-08da86626773 X-MS-Exchange-CrossTenant-originalarrivaltime: 25 Aug 2022 06:24:02.6576 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 42f7676c-f455-423c-82f6-dc2d99791af7 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: YP8qDi+C3/Q2zI+xgqc3C4ai1uJWkLmTRDO9iYfx9mrs16jt3XkMU1NbyyRAQCxgQC/KPXXsORcR+RM+7Az+iw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB3PR0202MB3484 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Introducing the vSMP guest driver which allows interaction with the vSMP control device when running a Linux OS atop of the vSMP hypervisor. vSMP is a resource aggregation hypervisor from SAP. The driver comprises of api part which facilitates communication with the hypervisor and version which displays the hypervisor's version. This patch s based on previous patches sent to the staging tree mailing lists Signed-off-by: Eial Czerwacki Acked-by: Leonid Arsh Acked-by: Oren Twaig CC: SAP vSMP Linux Maintainer CC: Greg Kroah-Hartman CC: Arnd Bergmann CC: Dan Carpenter CC: Andra Paraschiv CC: Borislav Petkov CC: Brijesh Singh CC: Eric Biggers CC: Fei Li CC: Hans de Goede CC: Jens Axboe CC: Mauro Carvalho Chehab v1 -> v2: - fix -0 var init in add_sysfs_entries (pointed out by Dan Carpenter) --- Documentation/ABI/stable/sysfs-driver-vsmp | 5 + MAINTAINERS | 6 + drivers/virt/Kconfig | 2 + drivers/virt/Makefile | 2 + drivers/virt/vsmp/Kconfig | 11 + drivers/virt/vsmp/Makefile | 7 + drivers/virt/vsmp/api/api.c | 249 +++++++++++++++++++++ drivers/virt/vsmp/api/api.h | 69 ++++++ drivers/virt/vsmp/include/registers.h | 12 + drivers/virt/vsmp/version/version.c | 118 ++++++++++ drivers/virt/vsmp/version/version.h | 14 ++ drivers/virt/vsmp/vsmp_main.c | 110 +++++++++ 12 files changed, 605 insertions(+) create mode 100644 Documentation/ABI/stable/sysfs-driver-vsmp create mode 100644 drivers/virt/vsmp/Kconfig create mode 100644 drivers/virt/vsmp/Makefile create mode 100644 drivers/virt/vsmp/api/api.c create mode 100644 drivers/virt/vsmp/api/api.h create mode 100644 drivers/virt/vsmp/include/registers.h create mode 100644 drivers/virt/vsmp/version/version.c create mode 100644 drivers/virt/vsmp/version/version.h create mode 100644 drivers/virt/vsmp/vsmp_main.c diff --git a/Documentation/ABI/stable/sysfs-driver-vsmp b/Documentation/ABI= /stable/sysfs-driver-vsmp new file mode 100644 index 000000000000..18a0a62f40ed --- /dev/null +++ b/Documentation/ABI/stable/sysfs-driver-vsmp @@ -0,0 +1,5 @@ +What: /sys/hypervisor/vsmp/version +Date: Aug 2022 +Contact: Eial Czerwacki + linux-vsmp@sap.com +Description: Shows the full version of the vSMP hypervisor diff --git a/MAINTAINERS b/MAINTAINERS index f512b430c7cb..cf74089c4d19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21783,6 +21783,12 @@ F: lib/test_printf.c F: lib/test_scanf.c F: lib/vsprintf.c +VSMP GUEST DRIVER +M: Eial Czerwacki +M: linux-vsmp@sap.com +S: Maintained +F: drivers/virt/vsmp + VT1211 HARDWARE MONITOR DRIVER M: Juerg Haefliger L: linux-hwmon@vger.kernel.org diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig index 87ef258cec64..9f283f476674 100644 --- a/drivers/virt/Kconfig +++ b/drivers/virt/Kconfig @@ -52,4 +52,6 @@ source "drivers/virt/coco/efi_secret/Kconfig" source "drivers/virt/coco/sev-guest/Kconfig" +source "drivers/virt/vsmp/Kconfig" + endif diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile index 093674e05c40..159ba37cb471 100644 --- a/drivers/virt/Makefile +++ b/drivers/virt/Makefile @@ -11,3 +11,5 @@ obj-$(CONFIG_NITRO_ENCLAVES) +=3D nitro_enclaves/ obj-$(CONFIG_ACRN_HSM) +=3D acrn/ obj-$(CONFIG_EFI_SECRET) +=3D coco/efi_secret/ obj-$(CONFIG_SEV_GUEST) +=3D coco/sev-guest/ + +obj-$(CONFIG_VSMP) +=3D vsmp/ diff --git a/drivers/virt/vsmp/Kconfig b/drivers/virt/vsmp/Kconfig new file mode 100644 index 000000000000..4e1d7e0dc746 --- /dev/null +++ b/drivers/virt/vsmp/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +config VSMP + tristate "vSMP Guest Support" + depends on SYS_HYPERVISOR && X86_64 && PCI + help + Support for vSMP Guest Driver. + + This driver allows information gathering of data from the vSMP hypervis= or when + running on top of a vSMP-based hypervisor. + + If unsure, say no. diff --git a/drivers/virt/vsmp/Makefile b/drivers/virt/vsmp/Makefile new file mode 100644 index 000000000000..f637097e19f2 --- /dev/null +++ b/drivers/virt/vsmp/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for vSMP Guest drivers +# + +obj-$(CONFIG_VSMP) =3D vsmp.o +vsmp-y :=3D vsmp_main.o api/api.o version/version.o diff --git a/drivers/virt/vsmp/api/api.c b/drivers/virt/vsmp/api/api.c new file mode 100644 index 000000000000..6e40935907bc --- /dev/null +++ b/drivers/virt/vsmp/api/api.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * vSMP driver api + * (C) Copyright 2022 SAP SE + */ + +#include "api.h" + +static void __iomem *cfg_addr; +static struct kobject *vsmp_sysfs_kobj; +static struct pci_dev *vsmp_dev_obj; + +/* R/W ops handlers */ + +/* + * Init a vsmp firmware operation object + */ +int vsmp_init_op(struct fw_ops *op, ssize_t max_size, + enum vsmp_fw_action action) +{ + op->hwi_block_size =3D max_size; + op->action =3D action; + op->buff_offset =3D op->hwi_block_size; + + op->buff =3D kzalloc(op->hwi_block_size, GFP_KERNEL); + if (!op->buff) + return -ENOMEM; + + vsmp_reset_op(op); + + return 0; +} + +/* + * Release an vsmp firmware operation object + */ +void vsmp_release_op(struct fw_ops *op) +{ + if (!op) { + WARN_ON(!op); + return; + } + + if (!op->buff) { + WARN_ON(!op->buff); + return; + } + + kfree(op->buff); + memset(op, 0, sizeof(*op)); +} + +/* + * Reset a vsmp firmware operation object + */ +void vsmp_reset_op(struct fw_ops *op) +{ + memset(op->buff, 0, op->hwi_block_size); + op->buff_offset =3D op->hwi_block_size; +} + +/* Regs/Buffs R/W handlers */ + +/* + * Read a value from a specific register in the vSMP's device config space + */ +u64 vsmp_read_reg_from_cfg(u64 reg, enum reg_size_type type) +{ + u64 ret_val; + + switch (type) { + case VSMP_CTL_REG_SIZE_8BIT: + ret_val =3D readb(cfg_addr + reg); + break; + + case VSMP_CTL_REG_SIZE_16BIT: + ret_val =3D readw(cfg_addr + reg); + break; + + case VSMP_CTL_REG_SIZE_32BIT: + ret_val =3D readl(cfg_addr + reg); + break; + + case VSMP_CTL_REG_SIZE_64BIT: + ret_val =3D readq(cfg_addr + reg); + break; + + default: + dev_err(get_dev(), "Unsupported reg size type %d.\n", type); + ret_val =3D (u64) -EINVAL; + } + + dev_dbg(get_dev(), "%s: read 0x%llx from reg 0x%llx of %d bits\n", + __func__, ret_val, reg, (type + 1) * 8); + return ret_val; +} + +/* + * Read a buffer from the bar byte by byte for halt on + * null termination. + * Expected buffs are strings. + */ +static ssize_t read_buff_from_bar_in_bytes(char *out, u8 __iomem *buff, ss= ize_t len) +{ + u32 i; + + for (i =3D 0; i < len; i++) { + out[i] =3D ioread8(&buff[i]); + if (!out[i]) + break; + } + + return i; +} + +/* + * Read a buffer from a specific offset in a specific bar, + * maxed to a predefined len size-wise from the vSMP device + */ +int vsmp_read_buff_from_bar(u8 bar, u32 offset, char *out, ssize_t len, + bool halt_on_null) +{ + u8 __iomem *buff; + u64 bar_start =3D pci_resource_start(vsmp_dev_obj, bar); + u32 bar_len =3D pci_resource_len(vsmp_dev_obj, bar); + ssize_t actual_len =3D len; + + /* incase of overflow, warn and use max len possible */ + if ((offset + len) > bar_len) { + WARN_ON((offset + len) > actual_len); + actual_len =3D bar_len - offset; + dev_dbg(get_dev(), "%lu overflows bar len, using %ld len instead\n", + len, actual_len); + } + + buff =3D ioremap(bar_start + offset, actual_len); + if (!buff) + return -ENOMEM; + + if (halt_on_null) + read_buff_from_bar_in_bytes(out, buff, len); + else + memcpy_fromio(out, buff, len); + + iounmap(buff); + + return 0; +} + +/* + * Generic function to read from the bar + */ +ssize_t vsmp_generic_buff_read(struct fw_ops *op, u8 bar, u64 reg, + char *buf, loff_t off, ssize_t count) +{ + ssize_t ret_val =3D 0; + + if (op->buff_offset >=3D op->hwi_block_size) { /* perform H/W op */ + vsmp_reset_op(op); + + ret_val =3D vsmp_read_buff_from_bar(bar, reg, op->buff, op->hwi_block_si= ze, false); + if (ret_val) { + dev_err(get_dev(), "%s operation failed\n", + (op->action =3D=3D FW_READ) ? "read" : "write"); + } + op->buff_offset =3D 0; + } + + if (ret_val) + return ret_val; + + return memory_read_from_buffer(buf, count, &op->buff_offset, op->buff, op= ->hwi_block_size); +} + +/* sysfs handlers */ + +/* + * Register the vSMP sysfs object for user space interaction + */ +int vsmp_register_sysfs_group(const struct bin_attribute *bin_attr) +{ + int error =3D -EINVAL; + + if (vsmp_sysfs_kobj && bin_attr) { + error =3D sysfs_create_bin_file(vsmp_sysfs_kobj, bin_attr); + if (error) + dev_err(get_dev(), "Failed to register sysfs entry (%d)\n", error); + } + + return error; +} + +/* + * Deregister the vSMP sysfs object for user space interaction + */ +void vsmp_deregister_sysfs_group(const struct bin_attribute *bin_attr) +{ + if (vsmp_sysfs_kobj && bin_attr) + sysfs_remove_bin_file(vsmp_sysfs_kobj, bin_attr); +} + +/* Generic functions */ + +/* + * Open the cfg address space of the vSDP device + */ +int open_cfg_addr(struct pci_dev *pdev) +{ + u64 cfg_start; + u32 cfg_len; + + vsmp_dev_obj =3D pdev; + cfg_start =3D pci_resource_start(vsmp_dev_obj, 0); + cfg_len =3D pci_resource_len(vsmp_dev_obj, 0); + + dev_dbg(get_dev(), "Mapping bar 0: [0x%llx,0x%llx]\n", + cfg_start, cfg_start + cfg_len); + + cfg_addr =3D ioremap(cfg_start, cfg_len); + if (!cfg_addr) { + dev_err(get_dev(), "Failed to map vSMP pci controller, exiting.\n"); + return -ENODEV; + } + + return 0; +} + +int init_sysfs(void) +{ + vsmp_sysfs_kobj =3D kobject_create_and_add("vsmp", hypervisor_kobj); + if (!vsmp_sysfs_kobj) { + dev_err(get_dev(), "Failed to create vSMP sysfs entry, exiting.\n"); + return -EINVAL; + } + + return 0; +} + +void cleanup(void) +{ + iounmap(cfg_addr); + kobject_put(vsmp_sysfs_kobj); +} + +const struct device *get_dev(void) +{ + return &vsmp_dev_obj->dev; +} diff --git a/drivers/virt/vsmp/api/api.h b/drivers/virt/vsmp/api/api.h new file mode 100644 index 000000000000..6142e947979f --- /dev/null +++ b/drivers/virt/vsmp/api/api.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * vSMP driver api header + * (C) Copyright 2022 SAP SE + */ + +#ifndef VSMP_API_H +#define VSMP_API_H + +#include + +// R/W ops handlers +#define vsmp_read_reg32_from_cfg(_reg_) \ + ((u32) vsmp_read_reg_from_cfg((_reg_), VSMP_CTL_REG_SIZE_32BIT)) + +enum reg_size_type { + VSMP_CTL_REG_SIZE_8BIT =3D 0, + VSMP_CTL_REG_SIZE_16BIT, + VSMP_CTL_REG_SIZE_32BIT, + VSMP_CTL_REG_SIZE_64BIT +}; + +enum vsmp_fw_action { + FW_READ =3D 0, + FW_WRITE =3D 1 +}; + +struct fw_ops { + enum vsmp_fw_action action; + ssize_t hwi_block_size; + unsigned char *buff; + loff_t buff_offset; + bool in_progress; +}; + +int vsmp_init_op(struct fw_ops *op, ssize_t max_size, + enum vsmp_fw_action action); +void vsmp_release_op(struct fw_ops *op); +void vsmp_reset_op(struct fw_ops *op); + +#define FILE_PREM 0444 + +/* Regs/Buffs R/W handlers */ +#define vsmp_read_reg32_from_cfg(_reg_) \ + ((u32) vsmp_read_reg_from_cfg((_reg_), VSMP_CTL_REG_SIZE_32BIT)) + +u64 vsmp_read_reg_from_cfg(u64 reg, enum reg_size_type type); +ssize_t vsmp_generic_buff_read(struct fw_ops *op, u8 bar, u64 reg, + char *buf, loff_t off, ssize_t count); +int vsmp_read_buff_from_bar(u8 bar, u32 offset, char *out, ssize_t len, + bool halt_on_null); + +typedef int (*sysfs_register_cb)(void); +typedef void (*sysfs_deregister_cb)(void); + +struct sysfs_entry_cbs { + sysfs_register_cb reg_cb; + sysfs_deregister_cb dereg_cb; +}; + +int vsmp_register_sysfs_group(const struct bin_attribute *bin_attr); +void vsmp_deregister_sysfs_group(const struct bin_attribute *bin_attr); + +int open_cfg_addr(struct pci_dev *pdev); +int init_sysfs(void); +void cleanup(void); +const struct device *get_dev(void); +#endif /* VSMP_API_H */ diff --git a/drivers/virt/vsmp/include/registers.h b/drivers/virt/vsmp/incl= ude/registers.h new file mode 100644 index 000000000000..b6458d25e3b7 --- /dev/null +++ b/drivers/virt/vsmp/include/registers.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * vSMP driver registers + * (C) Copyright 2022 SAP SE + */ + +#ifndef VSMP_REGSITERS_H +#define VSMP_REGSITERS_H + +#define VSMP_VERSION_REG 0x0c + +#endif /* VSMP_REGSITERS_H */ diff --git a/drivers/virt/vsmp/version/version.c b/drivers/virt/vsmp/versio= n/version.c new file mode 100644 index 000000000000..d8ad771daf28 --- /dev/null +++ b/drivers/virt/vsmp/version/version.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * vSMP driver version module + * (C) Copyright 2022 SAP SE + */ + +#include +#include + +#include "../api/api.h" +#include "../include/registers.h" + +/* + * This is the maximal possible length of the version which is a text stri= ng + * the real len is usually much smaller, thus the driver uses this once to= read + * the version string and record it's actual len. + * From that point and on, the actual len will be used in each call. + */ +#define VERSION_MAX_LEN (1 << 19) + +static struct fw_ops op; + +static ssize_t version_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + u64 reg_val =3D vsmp_read_reg32_from_cfg(VSMP_VERSION_REG); + ssize_t ret_val; + + if (reg_val < 0) { + dev_err(get_dev(), "Failed to value of reg 0x%x\n", VSMP_VERSION_REG); + return 0; + } + + ret_val =3D vsmp_generic_buff_read(&op, 0, reg_val, buf, off, count); + if (ret_val < 0) { + dev_err(get_dev(), "Failed to read version (%ld)\n", ret_val); + return 0; + } + + buf[ret_val++] =3D '\n'; + + return ret_val; +} + +struct bin_attribute version_raw_attr =3D __BIN_ATTR(version, FILE_PREM, + version_read, NULL, VERSION_MAX_LEN); + +/* + * Retrieve str in order to determine the proper length. + * This is the best way to maintain backwards compatibility with all + * vSMP versions. + */ +static ssize_t get_version_len(void) +{ + ssize_t len =3D 0; + u64 reg_val =3D vsmp_read_reg32_from_cfg(VSMP_VERSION_REG); + char *version_str =3D kzalloc(VERSION_MAX_LEN, GFP_KERNEL); + + if (!version_str) + return len; + + if (vsmp_read_reg32_from_cfg(VSMP_VERSION_REG) < 0) { + kfree(version_str); + dev_err(get_dev(), "Failed to read value of reg 0x%x\n", VSMP_VERSION_RE= G); + return len; + } + + memset(version_str, 0, VERSION_MAX_LEN); + if (vsmp_read_buff_from_bar(0, reg_val, version_str, VERSION_MAX_LEN, tru= e)) { + kfree(version_str); + dev_err(get_dev(), "Failed to read buffer from bar\n"); + return len; + } + + len =3D strlen(version_str); + kfree(version_str); + + return len; +} + +/* + * Register the version sysfs entry + */ +int sysfs_register_version_cb(void) +{ + ssize_t len =3D get_version_len(); + int ret_val; + + if (!len) { + dev_err(get_dev(), "Failed to init vSMP version module\n"); + return -EINVAL; + } + version_raw_attr.size =3D len; + + if (vsmp_init_op(&op, version_raw_attr.size, FW_READ)) { + dev_err(get_dev(), "Failed to init vSMP version op\n"); + return -ENODEV; + } + + ret_val =3D vsmp_register_sysfs_group(&version_raw_attr); + if (ret_val) { + dev_err(get_dev(), "Failed to init vSMP version support\n"); + vsmp_release_op(&op); + } + + return ret_val; +} + +/* + * Deregister the version sysfs entry + */ +void sysfs_deregister_version_cb(void) +{ + vsmp_deregister_sysfs_group(&version_raw_attr); + vsmp_release_op(&op); +} diff --git a/drivers/virt/vsmp/version/version.h b/drivers/virt/vsmp/versio= n/version.h new file mode 100644 index 000000000000..c4430b3065e4 --- /dev/null +++ b/drivers/virt/vsmp/version/version.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * vSMP driver version module header + * (C) Copyright 2022 SAP SE + */ + +#ifndef VSMP_VERSION_COMMON_H +#define VSMP_VERSION_COMMON_H + +int sysfs_register_version_cb(void); +void sysfs_deregister_version_cb(void); + +#endif /* VSMP_VERSION_COMMON_H */ diff --git a/drivers/virt/vsmp/vsmp_main.c b/drivers/virt/vsmp/vsmp_main.c new file mode 100644 index 000000000000..95704bc7a32f --- /dev/null +++ b/drivers/virt/vsmp/vsmp_main.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * vSMP driver main + * (C) Copyright 2022 SAP SE + */ + +#include + +#include "api/api.h" +#include "version/version.h" + +/* modules info */ +#define DEVICE_NAME "vSMP" +#define DRIVER_LICENSE "GPL v2" +#define DRIVER_AUTHOR "Eial Czerwacki " +#define DRIVER_DESC "vSMP hypervisor driver" +#define DRIVER_VERSION "0.1" + +#define PCI_DEVICE_ID_SAP_FLX_VSMP_CTL 0x1011 + +MODULE_LICENSE(DRIVER_LICENSE); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); + +/* Sysfs handlers */ +#define create_entry(_label_) \ + { \ + .reg_cb =3D sysfs_register_ ## _label_ ## _cb, \ + .dereg_cb =3D sysfs_deregister_ ## _label_ ## _cb, \ + } + +static struct sysfs_entry_cbs cbs_arr[] =3D { + create_entry(version), +}; + +static const struct pci_device_id vsmp_pci_table[] =3D { + { PCI_VDEVICE(SCALEMP, PCI_DEVICE_ID_SAP_FLX_VSMP_CTL), 0, }, + { 0, }, /* terminate list */ +}; + +/* + * Init all submodules's sysfs entries + */ +static int add_sysfs_entries(void) +{ + int ret_val =3D 0, i; + + for (i =3D 0; (i < ARRAY_SIZE(cbs_arr) && !ret_val); i++) { + ret_val =3D cbs_arr[i].reg_cb(); + if (ret_val) { + dev_err(get_dev(), "Failed to init sysfs entry %d (%d).\n", + i, ret_val); + } + } + + return ret_val; +} + +/* + * Remove all submodules's sysfs entries + */ +static void remove_sysfs_entries(void) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(cbs_arr); i++) + cbs_arr[i].dereg_cb(); +} + +static int vsmp_pci_probe(struct pci_dev *pci, const struct pci_device_id = *id) +{ + int ret_val; + + ret_val =3D open_cfg_addr(pci); + if (ret_val) { + dev_err(get_dev(), "Failed to open cfg addr\n"); + return ret_val; + } + + if (init_sysfs()) { + dev_err(get_dev(), "Failed to create sysfs folder\n"); + return -ENODEV; + } + + if (add_sysfs_entries()) { + dev_err(get_dev(), "Failed to create sysfs entries\n"); + return -ENODEV; + } + + dev_info(get_dev(), "%s up and running\n", DRIVER_DESC); + + return 0; +} + +static void vsmp_pci_remove(struct pci_dev *pci) +{ + remove_sysfs_entries(); + cleanup(); +} + +static struct pci_driver vsmp_pci_driver =3D { + .name =3D DEVICE_NAME, + .id_table =3D vsmp_pci_table, + .probe =3D vsmp_pci_probe, + .remove =3D vsmp_pci_remove, +}; + +module_pci_driver(vsmp_pci_driver); -- 2.25.1