All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/16] Enable VAS and NX-GZIP support on powerVM
@ 2021-05-21  9:25 ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:25 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


Virtual Accelerator Switchboard (VAS) allows kernel subsystems
and user space processes to directly access the Nest Accelerator
(NX) engines which provides HW compression. The true user mode
VAS/NX support on PowerNV is already included in Linux. Whereas
PowerVM support is available from P10 onwards.

This patch series enables VAS / NX-GZIP on powerVM which allows
the user space to do copy/paste with the same existing interface
that is available on powerNV.

VAS Enablement:
- Get all VAS capabilities using H_QUERY_VAS_CAPABILITIES that are
  available in the hypervisor. These capabilities tells OS which
  type of features (credit types such as Default and Quality of
  Service (QoS)). Also gives specific capabilities for each credit
  type: Maximum window credits, Maximum LPAR credits, Target credits
  in that parition (varies from max LPAR credits based DLPAR
  operation), whether supports user mode COPY/PASTE and etc.
- Register LPAR VAS operations such as open window. get paste
  address and close window with the current VAS user space API.
- Open window operation - Use H_ALLOCATE_VAS_WINDOW HCALL to open
  window and H_MODIFY_VAS_WINDOW HCALL to setup the window with LPAR
  PID and etc.
- mmap to paste address returned in H_ALLOCATE_VAS_WINDOW HCALL
- To close window, H_DEALLOCATE_VAS_WINDOW HCALL is used to close in
  the hypervisor.

NX Enablement:
- Get NX capabilities from the the hypervisor which provides Maximum
  buffer length in a single GZIP request, recommended minimum
  compression / decompression lengths.
- Register to VAS to enable user space VAS API

Main feature differences with powerNV implementation:
- Each VAS window will be configured with a number of credits which
  means that many requests can be issues simultaniously on that
  window. On powerNV, 1K credits are configured per window.
  Whereas on powerVM, the hypervisor allows 1 credit per window
  at present.
- The hypervisor introduced 2 different types of credits: Default -
  Uses normal priority FIFO and Quality of Service (QoS) - Uses high
  priority FIFO. On powerVM, VAS/NX HW resources are shared across
  LPARs. The total number of credits available on a system depends
  on cores configured. We may see more credits are assigned across
  the system than the NX HW resources can handle. So to avoid NX HW
  contention, the hypervisor introduced QoS credits which can be
  configured by system administration with HMC API. Then the total
  number of available default credits on LPAR varies based on QoS
  credits configured.
- On powerNV, windows are allocated on a specific VAS instance
  and the user space can select VAS instance with the open window
  ioctl. Since VAS instances can be shared across partitions on
  powerVM, the hypervisor manages window allocations on different
  VAS instances. So H_ALLOCATE_VAS_WINDOW allows to select by domain
  indentifiers (H_HOME_NODE_ASSOCIATIVITY values by cpu). By default
  the hypervisor selects VAS instance closer to CPU resources that the
  parition uses. So vas_id in ioctl interface is ignored on powerVM
  except vas_id=-1 which is used to allocate window based on CPU that
  the process is executing. This option is needed for process affinity
  to NUMA node.

  The existing applications that linked with libnxz should work as
  long as the job request length is restricted to
  req_max_processed_len.

  Tested the following patches on P10 successfully with test cases
  given: https://github.com/libnxz/power-gzip

  Note: The hypervisor supports user mode NX from p10 onwards. Linux
        supports user mode VAS/NX on P10 only with radix page tables.

Patches 1- 5:   Move the code that is needed for both powerNV and
                powerVM to powerpc book3s platform directory
Patch 6:        Modify vas-window struct to support both and the
                related changes.
Patch 7:        Define HCALL and the related VAS/NXGZIP specific
                structs.
Patch 8:        Define QoS credit flag in window open ioctl
Patch 9:        Implement Allocate, Modify and Deallocate HCALLs
Patch 10:        Retrieve VAS capabilities from the hypervisor
Patch 11;       Implement window operations and integrate with API
Patch 12:       Setup IRQ and NX fault handling
Patch 13 - 14:  Make the code common to add NX-GZIP enablement
Patch 15:       Get NX capabilities from the hypervisor
patch 16;       Add sysfs interface to expose NX capabilities

Changes in V2:
  - Rebase on 5.12-rc6
  - Moved VAS Kconfig changes to arch/powerpc/platform as suggested
    by Christophe Leroy
  - build fix with allyesconfig (reported by kernel test build)

Changes in V3:
  - Rebase on 5.12-rc7
  - Moved vas-api.c and VAS Kconfig changes to
    arch/powerpc/platform/book3s as Michael Ellerman suggested

Changes in V4:
  - Rebase on 5.13-rc2
  - Changes based on review comments from Nicholas Piggin
    - Add seperate patch to define user window operations
    - Drop "sysfs interface to export VAS capabilities" patch
      This interface is mainly needed for DLPAR operations
      and this patch will be included when DLPAR/LPM support
      is added.
    - Other cleanup changes

Haren Myneni (16):
  powerpc/vas: Move VAS API to book3s common platform
  powerpc/powernv/vas: Rename register/unregister functions
  powerpc/vas: Add platform specific user window operations
  powerpc/vas: Create take/drop pid and mm reference functions
  powerpc/vas: Move update_csb/dump_crb to common book3s platform
  powerpc/vas:  Define and use common vas_window struct
  powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
  powerpc/vas: Define QoS credit flag to allocate window
  powerpc/pseries/vas: Add HCALL wrappers for VAS handling
  powerpc/pseries/vas: Implement getting capabilities from hypervisor
  powerpc/pseries/vas: Integrate API with open/close windows
  powerpc/pseries/vas: Setup IRQ and fault handling
  crypto/nx: Rename nx-842-pseries file name to nx-common-pseries
  crypto/nx: Register and unregister VAS interface
  crypto/nx: Get NX capabilities for GZIP coprocessor type
  crypto/nx: Add sysfs interface to export NX capabilities

 arch/powerpc/include/asm/hvcall.h             |   7 +
 arch/powerpc/include/asm/vas.h                | 135 +++-
 arch/powerpc/include/uapi/asm/vas-api.h       |   6 +-
 arch/powerpc/platforms/Kconfig                |   1 +
 arch/powerpc/platforms/Makefile               |   1 +
 arch/powerpc/platforms/book3s/Kconfig         |  15 +
 arch/powerpc/platforms/book3s/Makefile        |   2 +
 arch/powerpc/platforms/book3s/vas-api.c       | 484 +++++++++++++
 arch/powerpc/platforms/powernv/Kconfig        |  14 -
 arch/powerpc/platforms/powernv/Makefile       |   2 +-
 arch/powerpc/platforms/powernv/vas-api.c      | 278 --------
 arch/powerpc/platforms/powernv/vas-debug.c    |  12 +-
 arch/powerpc/platforms/powernv/vas-fault.c    | 155 +---
 arch/powerpc/platforms/powernv/vas-trace.h    |   6 +-
 arch/powerpc/platforms/powernv/vas-window.c   | 246 ++++---
 arch/powerpc/platforms/powernv/vas.h          |  42 +-
 arch/powerpc/platforms/pseries/Makefile       |   1 +
 arch/powerpc/platforms/pseries/vas.c          | 672 ++++++++++++++++++
 arch/powerpc/platforms/pseries/vas.h          | 110 +++
 drivers/crypto/nx/Kconfig                     |   1 +
 drivers/crypto/nx/Makefile                    |   2 +-
 drivers/crypto/nx/nx-common-powernv.c         |   6 +-
 .../{nx-842-pseries.c => nx-common-pseries.c} | 141 ++++
 23 files changed, 1738 insertions(+), 601 deletions(-)
 create mode 100644 arch/powerpc/platforms/book3s/Kconfig
 create mode 100644 arch/powerpc/platforms/book3s/Makefile
 create mode 100644 arch/powerpc/platforms/book3s/vas-api.c
 delete mode 100644 arch/powerpc/platforms/powernv/vas-api.c
 create mode 100644 arch/powerpc/platforms/pseries/vas.c
 create mode 100644 arch/powerpc/platforms/pseries/vas.h
 rename drivers/crypto/nx/{nx-842-pseries.c => nx-common-pseries.c} (90%)

-- 
2.18.2



^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v4 00/16] Enable VAS and NX-GZIP support on powerVM
@ 2021-05-21  9:25 ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:25 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


Virtual Accelerator Switchboard (VAS) allows kernel subsystems
and user space processes to directly access the Nest Accelerator
(NX) engines which provides HW compression. The true user mode
VAS/NX support on PowerNV is already included in Linux. Whereas
PowerVM support is available from P10 onwards.

This patch series enables VAS / NX-GZIP on powerVM which allows
the user space to do copy/paste with the same existing interface
that is available on powerNV.

VAS Enablement:
- Get all VAS capabilities using H_QUERY_VAS_CAPABILITIES that are
  available in the hypervisor. These capabilities tells OS which
  type of features (credit types such as Default and Quality of
  Service (QoS)). Also gives specific capabilities for each credit
  type: Maximum window credits, Maximum LPAR credits, Target credits
  in that parition (varies from max LPAR credits based DLPAR
  operation), whether supports user mode COPY/PASTE and etc.
- Register LPAR VAS operations such as open window. get paste
  address and close window with the current VAS user space API.
- Open window operation - Use H_ALLOCATE_VAS_WINDOW HCALL to open
  window and H_MODIFY_VAS_WINDOW HCALL to setup the window with LPAR
  PID and etc.
- mmap to paste address returned in H_ALLOCATE_VAS_WINDOW HCALL
- To close window, H_DEALLOCATE_VAS_WINDOW HCALL is used to close in
  the hypervisor.

NX Enablement:
- Get NX capabilities from the the hypervisor which provides Maximum
  buffer length in a single GZIP request, recommended minimum
  compression / decompression lengths.
- Register to VAS to enable user space VAS API

Main feature differences with powerNV implementation:
- Each VAS window will be configured with a number of credits which
  means that many requests can be issues simultaniously on that
  window. On powerNV, 1K credits are configured per window.
  Whereas on powerVM, the hypervisor allows 1 credit per window
  at present.
- The hypervisor introduced 2 different types of credits: Default -
  Uses normal priority FIFO and Quality of Service (QoS) - Uses high
  priority FIFO. On powerVM, VAS/NX HW resources are shared across
  LPARs. The total number of credits available on a system depends
  on cores configured. We may see more credits are assigned across
  the system than the NX HW resources can handle. So to avoid NX HW
  contention, the hypervisor introduced QoS credits which can be
  configured by system administration with HMC API. Then the total
  number of available default credits on LPAR varies based on QoS
  credits configured.
- On powerNV, windows are allocated on a specific VAS instance
  and the user space can select VAS instance with the open window
  ioctl. Since VAS instances can be shared across partitions on
  powerVM, the hypervisor manages window allocations on different
  VAS instances. So H_ALLOCATE_VAS_WINDOW allows to select by domain
  indentifiers (H_HOME_NODE_ASSOCIATIVITY values by cpu). By default
  the hypervisor selects VAS instance closer to CPU resources that the
  parition uses. So vas_id in ioctl interface is ignored on powerVM
  except vas_id=-1 which is used to allocate window based on CPU that
  the process is executing. This option is needed for process affinity
  to NUMA node.

  The existing applications that linked with libnxz should work as
  long as the job request length is restricted to
  req_max_processed_len.

  Tested the following patches on P10 successfully with test cases
  given: https://github.com/libnxz/power-gzip

  Note: The hypervisor supports user mode NX from p10 onwards. Linux
        supports user mode VAS/NX on P10 only with radix page tables.

Patches 1- 5:   Move the code that is needed for both powerNV and
                powerVM to powerpc book3s platform directory
Patch 6:        Modify vas-window struct to support both and the
                related changes.
Patch 7:        Define HCALL and the related VAS/NXGZIP specific
                structs.
Patch 8:        Define QoS credit flag in window open ioctl
Patch 9:        Implement Allocate, Modify and Deallocate HCALLs
Patch 10:        Retrieve VAS capabilities from the hypervisor
Patch 11;       Implement window operations and integrate with API
Patch 12:       Setup IRQ and NX fault handling
Patch 13 - 14:  Make the code common to add NX-GZIP enablement
Patch 15:       Get NX capabilities from the hypervisor
patch 16;       Add sysfs interface to expose NX capabilities

Changes in V2:
  - Rebase on 5.12-rc6
  - Moved VAS Kconfig changes to arch/powerpc/platform as suggested
    by Christophe Leroy
  - build fix with allyesconfig (reported by kernel test build)

Changes in V3:
  - Rebase on 5.12-rc7
  - Moved vas-api.c and VAS Kconfig changes to
    arch/powerpc/platform/book3s as Michael Ellerman suggested

Changes in V4:
  - Rebase on 5.13-rc2
  - Changes based on review comments from Nicholas Piggin
    - Add seperate patch to define user window operations
    - Drop "sysfs interface to export VAS capabilities" patch
      This interface is mainly needed for DLPAR operations
      and this patch will be included when DLPAR/LPM support
      is added.
    - Other cleanup changes

Haren Myneni (16):
  powerpc/vas: Move VAS API to book3s common platform
  powerpc/powernv/vas: Rename register/unregister functions
  powerpc/vas: Add platform specific user window operations
  powerpc/vas: Create take/drop pid and mm reference functions
  powerpc/vas: Move update_csb/dump_crb to common book3s platform
  powerpc/vas:  Define and use common vas_window struct
  powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
  powerpc/vas: Define QoS credit flag to allocate window
  powerpc/pseries/vas: Add HCALL wrappers for VAS handling
  powerpc/pseries/vas: Implement getting capabilities from hypervisor
  powerpc/pseries/vas: Integrate API with open/close windows
  powerpc/pseries/vas: Setup IRQ and fault handling
  crypto/nx: Rename nx-842-pseries file name to nx-common-pseries
  crypto/nx: Register and unregister VAS interface
  crypto/nx: Get NX capabilities for GZIP coprocessor type
  crypto/nx: Add sysfs interface to export NX capabilities

 arch/powerpc/include/asm/hvcall.h             |   7 +
 arch/powerpc/include/asm/vas.h                | 135 +++-
 arch/powerpc/include/uapi/asm/vas-api.h       |   6 +-
 arch/powerpc/platforms/Kconfig                |   1 +
 arch/powerpc/platforms/Makefile               |   1 +
 arch/powerpc/platforms/book3s/Kconfig         |  15 +
 arch/powerpc/platforms/book3s/Makefile        |   2 +
 arch/powerpc/platforms/book3s/vas-api.c       | 484 +++++++++++++
 arch/powerpc/platforms/powernv/Kconfig        |  14 -
 arch/powerpc/platforms/powernv/Makefile       |   2 +-
 arch/powerpc/platforms/powernv/vas-api.c      | 278 --------
 arch/powerpc/platforms/powernv/vas-debug.c    |  12 +-
 arch/powerpc/platforms/powernv/vas-fault.c    | 155 +---
 arch/powerpc/platforms/powernv/vas-trace.h    |   6 +-
 arch/powerpc/platforms/powernv/vas-window.c   | 246 ++++---
 arch/powerpc/platforms/powernv/vas.h          |  42 +-
 arch/powerpc/platforms/pseries/Makefile       |   1 +
 arch/powerpc/platforms/pseries/vas.c          | 672 ++++++++++++++++++
 arch/powerpc/platforms/pseries/vas.h          | 110 +++
 drivers/crypto/nx/Kconfig                     |   1 +
 drivers/crypto/nx/Makefile                    |   2 +-
 drivers/crypto/nx/nx-common-powernv.c         |   6 +-
 .../{nx-842-pseries.c => nx-common-pseries.c} | 141 ++++
 23 files changed, 1738 insertions(+), 601 deletions(-)
 create mode 100644 arch/powerpc/platforms/book3s/Kconfig
 create mode 100644 arch/powerpc/platforms/book3s/Makefile
 create mode 100644 arch/powerpc/platforms/book3s/vas-api.c
 delete mode 100644 arch/powerpc/platforms/powernv/vas-api.c
 create mode 100644 arch/powerpc/platforms/pseries/vas.c
 create mode 100644 arch/powerpc/platforms/pseries/vas.h
 rename drivers/crypto/nx/{nx-842-pseries.c => nx-common-pseries.c} (90%)

-- 
2.18.2



^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v4 01/16] powerpc/vas: Move VAS API to book3s common platform
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:28   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:28 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu


Using the same /dev/crypto/nx-gzip interface for both powerNV and
pseries. So this patch creates platforms/book3s/ and moves VAS API
to that directory. The actual functionality is not changed.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h                    |  3 +++
 arch/powerpc/platforms/Kconfig                    |  1 +
 arch/powerpc/platforms/Makefile                   |  1 +
 arch/powerpc/platforms/book3s/Kconfig             | 15 +++++++++++++++
 arch/powerpc/platforms/book3s/Makefile            |  2 ++
 .../platforms/{powernv => book3s}/vas-api.c       |  2 +-
 arch/powerpc/platforms/powernv/Kconfig            | 14 --------------
 arch/powerpc/platforms/powernv/Makefile           |  2 +-
 8 files changed, 24 insertions(+), 16 deletions(-)
 create mode 100644 arch/powerpc/platforms/book3s/Kconfig
 create mode 100644 arch/powerpc/platforms/book3s/Makefile
 rename arch/powerpc/platforms/{powernv => book3s}/vas-api.c (99%)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index e33f80b0ea81..3be76e813e2d 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -162,6 +162,9 @@ int vas_copy_crb(void *crb, int offset);
  */
 int vas_paste_crb(struct vas_window *win, int offset, bool re);
 
+void vas_win_paste_addr(struct vas_window *window, u64 *addr,
+			int *len);
+
 /*
  * Register / unregister coprocessor type to VAS API which will be exported
  * to user space. Applications can use this API to open / close window
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 7a5e8f4541e3..594544a65b02 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -20,6 +20,7 @@ source "arch/powerpc/platforms/embedded6xx/Kconfig"
 source "arch/powerpc/platforms/44x/Kconfig"
 source "arch/powerpc/platforms/40x/Kconfig"
 source "arch/powerpc/platforms/amigaone/Kconfig"
+source "arch/powerpc/platforms/book3s/Kconfig"
 
 config KVM_GUEST
 	bool "KVM Guest support"
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 143d4417f6cc..0e75d7df387b 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_PPC_CELL)		+= cell/
 obj-$(CONFIG_PPC_PS3)		+= ps3/
 obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
 obj-$(CONFIG_AMIGAONE)		+= amigaone/
+obj-$(CONFIG_PPC_BOOK3S)	+= book3s/
diff --git a/arch/powerpc/platforms/book3s/Kconfig b/arch/powerpc/platforms/book3s/Kconfig
new file mode 100644
index 000000000000..bed21449e8e5
--- /dev/null
+++ b/arch/powerpc/platforms/book3s/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+config PPC_VAS
+	bool "IBM Virtual Accelerator Switchboard (VAS)"
+	depends on (PPC_POWERNV || PPC_PSERIES) && PPC_64K_PAGES
+	default y
+	help
+	  This enables support for IBM Virtual Accelerator Switchboard (VAS).
+
+	  VAS allows accelerators in co-processors like NX-GZIP and NX-842
+	  to be accessible to kernel subsystems and user processes.
+	  VAS adapters are found in POWER9 and later based systems.
+	  The user mode NX-GZIP support is added on P9 for powerNV and on
+	  P10 for powerVM.
+
+	  If unsure, say "N".
diff --git a/arch/powerpc/platforms/book3s/Makefile b/arch/powerpc/platforms/book3s/Makefile
new file mode 100644
index 000000000000..e790f1910f61
--- /dev/null
+++ b/arch/powerpc/platforms/book3s/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_PPC_VAS)	+= vas-api.o
diff --git a/arch/powerpc/platforms/powernv/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
similarity index 99%
rename from arch/powerpc/platforms/powernv/vas-api.c
rename to arch/powerpc/platforms/book3s/vas-api.c
index 98ed5d8c5441..cfc9d7dd65ab 100644
--- a/arch/powerpc/platforms/powernv/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -10,9 +10,9 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/io.h>
 #include <asm/vas.h>
 #include <uapi/asm/vas-api.h>
-#include "vas.h"
 
 /*
  * The driver creates the device node that can be used as follows:
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
index 619b093a0657..043eefbbdd28 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -33,20 +33,6 @@ config PPC_MEMTRACE
 	  Enabling this option allows for runtime allocation of memory (RAM)
 	  for hardware tracing.
 
-config PPC_VAS
-	bool "IBM Virtual Accelerator Switchboard (VAS)"
-	depends on PPC_POWERNV && PPC_64K_PAGES
-	default y
-	help
-	  This enables support for IBM Virtual Accelerator Switchboard (VAS).
-
-	  VAS allows accelerators in co-processors like NX-GZIP and NX-842
-	  to be accessible to kernel subsystems and user processes.
-
-	  VAS adapters are found in POWER9 based systems.
-
-	  If unsure, say N.
-
 config SCOM_DEBUGFS
 	bool "Expose SCOM controllers via debugfs"
 	depends on DEBUG_FS
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index be2546b96816..dc7b37c23b60 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_MEMORY_FAILURE)	+= opal-memory-errors.o
 obj-$(CONFIG_OPAL_PRD)	+= opal-prd.o
 obj-$(CONFIG_PERF_EVENTS) += opal-imc.o
 obj-$(CONFIG_PPC_MEMTRACE)	+= memtrace.o
-obj-$(CONFIG_PPC_VAS)	+= vas.o vas-window.o vas-debug.o vas-fault.o vas-api.o
+obj-$(CONFIG_PPC_VAS)	+= vas.o vas-window.o vas-debug.o vas-fault.o
 obj-$(CONFIG_OCXL_BASE)	+= ocxl.o
 obj-$(CONFIG_SCOM_DEBUGFS) += opal-xscom.o
 obj-$(CONFIG_PPC_SECURE_BOOT) += opal-secvar.o
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 01/16] powerpc/vas: Move VAS API to book3s common platform
@ 2021-05-21  9:28   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:28 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


Using the same /dev/crypto/nx-gzip interface for both powerNV and
pseries. So this patch creates platforms/book3s/ and moves VAS API
to that directory. The actual functionality is not changed.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h                    |  3 +++
 arch/powerpc/platforms/Kconfig                    |  1 +
 arch/powerpc/platforms/Makefile                   |  1 +
 arch/powerpc/platforms/book3s/Kconfig             | 15 +++++++++++++++
 arch/powerpc/platforms/book3s/Makefile            |  2 ++
 .../platforms/{powernv => book3s}/vas-api.c       |  2 +-
 arch/powerpc/platforms/powernv/Kconfig            | 14 --------------
 arch/powerpc/platforms/powernv/Makefile           |  2 +-
 8 files changed, 24 insertions(+), 16 deletions(-)
 create mode 100644 arch/powerpc/platforms/book3s/Kconfig
 create mode 100644 arch/powerpc/platforms/book3s/Makefile
 rename arch/powerpc/platforms/{powernv => book3s}/vas-api.c (99%)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index e33f80b0ea81..3be76e813e2d 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -162,6 +162,9 @@ int vas_copy_crb(void *crb, int offset);
  */
 int vas_paste_crb(struct vas_window *win, int offset, bool re);
 
+void vas_win_paste_addr(struct vas_window *window, u64 *addr,
+			int *len);
+
 /*
  * Register / unregister coprocessor type to VAS API which will be exported
  * to user space. Applications can use this API to open / close window
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 7a5e8f4541e3..594544a65b02 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -20,6 +20,7 @@ source "arch/powerpc/platforms/embedded6xx/Kconfig"
 source "arch/powerpc/platforms/44x/Kconfig"
 source "arch/powerpc/platforms/40x/Kconfig"
 source "arch/powerpc/platforms/amigaone/Kconfig"
+source "arch/powerpc/platforms/book3s/Kconfig"
 
 config KVM_GUEST
 	bool "KVM Guest support"
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 143d4417f6cc..0e75d7df387b 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_PPC_CELL)		+= cell/
 obj-$(CONFIG_PPC_PS3)		+= ps3/
 obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
 obj-$(CONFIG_AMIGAONE)		+= amigaone/
+obj-$(CONFIG_PPC_BOOK3S)	+= book3s/
diff --git a/arch/powerpc/platforms/book3s/Kconfig b/arch/powerpc/platforms/book3s/Kconfig
new file mode 100644
index 000000000000..bed21449e8e5
--- /dev/null
+++ b/arch/powerpc/platforms/book3s/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+config PPC_VAS
+	bool "IBM Virtual Accelerator Switchboard (VAS)"
+	depends on (PPC_POWERNV || PPC_PSERIES) && PPC_64K_PAGES
+	default y
+	help
+	  This enables support for IBM Virtual Accelerator Switchboard (VAS).
+
+	  VAS allows accelerators in co-processors like NX-GZIP and NX-842
+	  to be accessible to kernel subsystems and user processes.
+	  VAS adapters are found in POWER9 and later based systems.
+	  The user mode NX-GZIP support is added on P9 for powerNV and on
+	  P10 for powerVM.
+
+	  If unsure, say "N".
diff --git a/arch/powerpc/platforms/book3s/Makefile b/arch/powerpc/platforms/book3s/Makefile
new file mode 100644
index 000000000000..e790f1910f61
--- /dev/null
+++ b/arch/powerpc/platforms/book3s/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_PPC_VAS)	+= vas-api.o
diff --git a/arch/powerpc/platforms/powernv/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
similarity index 99%
rename from arch/powerpc/platforms/powernv/vas-api.c
rename to arch/powerpc/platforms/book3s/vas-api.c
index 98ed5d8c5441..cfc9d7dd65ab 100644
--- a/arch/powerpc/platforms/powernv/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -10,9 +10,9 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/io.h>
 #include <asm/vas.h>
 #include <uapi/asm/vas-api.h>
-#include "vas.h"
 
 /*
  * The driver creates the device node that can be used as follows:
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
index 619b093a0657..043eefbbdd28 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -33,20 +33,6 @@ config PPC_MEMTRACE
 	  Enabling this option allows for runtime allocation of memory (RAM)
 	  for hardware tracing.
 
-config PPC_VAS
-	bool "IBM Virtual Accelerator Switchboard (VAS)"
-	depends on PPC_POWERNV && PPC_64K_PAGES
-	default y
-	help
-	  This enables support for IBM Virtual Accelerator Switchboard (VAS).
-
-	  VAS allows accelerators in co-processors like NX-GZIP and NX-842
-	  to be accessible to kernel subsystems and user processes.
-
-	  VAS adapters are found in POWER9 based systems.
-
-	  If unsure, say N.
-
 config SCOM_DEBUGFS
 	bool "Expose SCOM controllers via debugfs"
 	depends on DEBUG_FS
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index be2546b96816..dc7b37c23b60 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_MEMORY_FAILURE)	+= opal-memory-errors.o
 obj-$(CONFIG_OPAL_PRD)	+= opal-prd.o
 obj-$(CONFIG_PERF_EVENTS) += opal-imc.o
 obj-$(CONFIG_PPC_MEMTRACE)	+= memtrace.o
-obj-$(CONFIG_PPC_VAS)	+= vas.o vas-window.o vas-debug.o vas-fault.o vas-api.o
+obj-$(CONFIG_PPC_VAS)	+= vas.o vas-window.o vas-debug.o vas-fault.o
 obj-$(CONFIG_OCXL_BASE)	+= ocxl.o
 obj-$(CONFIG_SCOM_DEBUGFS) += opal-xscom.o
 obj-$(CONFIG_PPC_SECURE_BOOT) += opal-secvar.o
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 02/16] powerpc/powernv/vas: Rename register/unregister functions
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:29   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:29 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


powerNV and pseries drivers register / unregister to the corresponding
platform specific VAS separately. Then these VAS functions call the
common API with the specific window operations. So rename powerNV VAS
API register/unregister functions.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/vas.h              |  3 +++
 arch/powerpc/platforms/book3s/vas-api.c     |  2 --
 arch/powerpc/platforms/powernv/vas-window.c | 18 ++++++++++++++++++
 drivers/crypto/nx/nx-common-powernv.c       |  6 +++---
 4 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 3be76e813e2d..6076adf9ab4f 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -164,6 +164,9 @@ int vas_paste_crb(struct vas_window *win, int offset, bool re);
 
 void vas_win_paste_addr(struct vas_window *window, u64 *addr,
 			int *len);
+int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
+			     const char *name);
+void vas_unregister_api_powernv(void);
 
 /*
  * Register / unregister coprocessor type to VAS API which will be exported
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index cfc9d7dd65ab..72c126d87216 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -262,7 +262,6 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
 	unregister_chrdev_region(coproc_device.devt, 1);
 	return rc;
 }
-EXPORT_SYMBOL_GPL(vas_register_coproc_api);
 
 void vas_unregister_coproc_api(void)
 {
@@ -275,4 +274,3 @@ void vas_unregister_coproc_api(void)
 	class_destroy(coproc_device.class);
 	unregister_chrdev_region(coproc_device.devt, 1);
 }
-EXPORT_SYMBOL_GPL(vas_unregister_coproc_api);
diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
index 5f5fe63a3d1c..2fc0fbc4a3d1 100644
--- a/arch/powerpc/platforms/powernv/vas-window.c
+++ b/arch/powerpc/platforms/powernv/vas-window.c
@@ -1441,3 +1441,21 @@ struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
 
 	return window;
 }
+
+/*
+ * Supporting only nx-gzip coprocessor type now, but this API code
+ * extended to other coprocessor types later.
+ */
+int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
+			     const char *name)
+{
+
+	return vas_register_coproc_api(mod, cop_type, name);
+}
+EXPORT_SYMBOL_GPL(vas_register_api_powernv);
+
+void vas_unregister_api_powernv(void)
+{
+	vas_unregister_coproc_api();
+}
+EXPORT_SYMBOL_GPL(vas_unregister_api_powernv);
diff --git a/drivers/crypto/nx/nx-common-powernv.c b/drivers/crypto/nx/nx-common-powernv.c
index 446f611726df..3b159f2fae17 100644
--- a/drivers/crypto/nx/nx-common-powernv.c
+++ b/drivers/crypto/nx/nx-common-powernv.c
@@ -1092,8 +1092,8 @@ static __init int nx_compress_powernv_init(void)
 		 * normal FIFO priority is assigned for userspace.
 		 * 842 compression is supported only in kernel.
 		 */
-		ret = vas_register_coproc_api(THIS_MODULE, VAS_COP_TYPE_GZIP,
-						"nx-gzip");
+		ret = vas_register_api_powernv(THIS_MODULE, VAS_COP_TYPE_GZIP,
+					       "nx-gzip");
 
 		/*
 		 * GZIP is not supported in kernel right now.
@@ -1129,7 +1129,7 @@ static void __exit nx_compress_powernv_exit(void)
 	 * use. So delete this API use for GZIP engine.
 	 */
 	if (!nx842_ct)
-		vas_unregister_coproc_api();
+		vas_unregister_api_powernv();
 
 	crypto_unregister_alg(&nx842_powernv_alg);
 
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 02/16] powerpc/powernv/vas: Rename register/unregister functions
@ 2021-05-21  9:29   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:29 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


powerNV and pseries drivers register / unregister to the corresponding
platform specific VAS separately. Then these VAS functions call the
common API with the specific window operations. So rename powerNV VAS
API register/unregister functions.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/vas.h              |  3 +++
 arch/powerpc/platforms/book3s/vas-api.c     |  2 --
 arch/powerpc/platforms/powernv/vas-window.c | 18 ++++++++++++++++++
 drivers/crypto/nx/nx-common-powernv.c       |  6 +++---
 4 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 3be76e813e2d..6076adf9ab4f 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -164,6 +164,9 @@ int vas_paste_crb(struct vas_window *win, int offset, bool re);
 
 void vas_win_paste_addr(struct vas_window *window, u64 *addr,
 			int *len);
+int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
+			     const char *name);
+void vas_unregister_api_powernv(void);
 
 /*
  * Register / unregister coprocessor type to VAS API which will be exported
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index cfc9d7dd65ab..72c126d87216 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -262,7 +262,6 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
 	unregister_chrdev_region(coproc_device.devt, 1);
 	return rc;
 }
-EXPORT_SYMBOL_GPL(vas_register_coproc_api);
 
 void vas_unregister_coproc_api(void)
 {
@@ -275,4 +274,3 @@ void vas_unregister_coproc_api(void)
 	class_destroy(coproc_device.class);
 	unregister_chrdev_region(coproc_device.devt, 1);
 }
-EXPORT_SYMBOL_GPL(vas_unregister_coproc_api);
diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
index 5f5fe63a3d1c..2fc0fbc4a3d1 100644
--- a/arch/powerpc/platforms/powernv/vas-window.c
+++ b/arch/powerpc/platforms/powernv/vas-window.c
@@ -1441,3 +1441,21 @@ struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
 
 	return window;
 }
+
+/*
+ * Supporting only nx-gzip coprocessor type now, but this API code
+ * extended to other coprocessor types later.
+ */
+int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
+			     const char *name)
+{
+
+	return vas_register_coproc_api(mod, cop_type, name);
+}
+EXPORT_SYMBOL_GPL(vas_register_api_powernv);
+
+void vas_unregister_api_powernv(void)
+{
+	vas_unregister_coproc_api();
+}
+EXPORT_SYMBOL_GPL(vas_unregister_api_powernv);
diff --git a/drivers/crypto/nx/nx-common-powernv.c b/drivers/crypto/nx/nx-common-powernv.c
index 446f611726df..3b159f2fae17 100644
--- a/drivers/crypto/nx/nx-common-powernv.c
+++ b/drivers/crypto/nx/nx-common-powernv.c
@@ -1092,8 +1092,8 @@ static __init int nx_compress_powernv_init(void)
 		 * normal FIFO priority is assigned for userspace.
 		 * 842 compression is supported only in kernel.
 		 */
-		ret = vas_register_coproc_api(THIS_MODULE, VAS_COP_TYPE_GZIP,
-						"nx-gzip");
+		ret = vas_register_api_powernv(THIS_MODULE, VAS_COP_TYPE_GZIP,
+					       "nx-gzip");
 
 		/*
 		 * GZIP is not supported in kernel right now.
@@ -1129,7 +1129,7 @@ static void __exit nx_compress_powernv_exit(void)
 	 * use. So delete this API use for GZIP engine.
 	 */
 	if (!nx842_ct)
-		vas_unregister_coproc_api();
+		vas_unregister_api_powernv();
 
 	crypto_unregister_alg(&nx842_powernv_alg);
 
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 03/16] powerpc/vas: Add platform specific user window operations
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:30   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:30 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


PowerNV uses registers to open/close VAS windows, and getting the
paste address. Whereas the hypervisor calls are used on PowerVM.

This patch adds the platform specific user space window operations
and register with the common VAS user space interface.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h              | 14 +++++-
 arch/powerpc/platforms/book3s/vas-api.c     | 52 ++++++++++++---------
 arch/powerpc/platforms/powernv/vas-window.c | 46 +++++++++++++++++-
 3 files changed, 89 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 6076adf9ab4f..668303198772 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -5,6 +5,7 @@
 
 #ifndef _ASM_POWERPC_VAS_H
 #define _ASM_POWERPC_VAS_H
+#include <uapi/asm/vas-api.h>
 
 struct vas_window;
 
@@ -48,6 +49,16 @@ enum vas_cop_type {
 	VAS_COP_TYPE_MAX,
 };
 
+/*
+ * User space window operations used for powernv and powerVM
+ */
+struct vas_user_win_ops {
+	struct vas_window * (*open_win)(struct vas_tx_win_open_attr *,
+				enum vas_cop_type);
+	u64 (*paste_addr)(void *);
+	int (*close_win)(void *);
+};
+
 /*
  * Receive window attributes specified by the (in-kernel) owner of window.
  */
@@ -177,7 +188,8 @@ void vas_unregister_api_powernv(void);
  * used for others in future.
  */
 int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
-				const char *name);
+			    const char *name,
+			    struct vas_user_win_ops *vops);
 void vas_unregister_coproc_api(void);
 
 #endif /* __ASM_POWERPC_VAS_H */
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index 72c126d87216..6c39320bfb9b 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -42,6 +42,7 @@ static struct coproc_dev {
 	dev_t devt;
 	struct class *class;
 	enum vas_cop_type cop_type;
+	struct vas_user_win_ops *vops;
 } coproc_device;
 
 struct coproc_instance {
@@ -72,11 +73,10 @@ static int coproc_open(struct inode *inode, struct file *fp)
 static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
 {
 	void __user *uptr = (void __user *)arg;
-	struct vas_tx_win_attr txattr = {};
 	struct vas_tx_win_open_attr uattr;
 	struct coproc_instance *cp_inst;
 	struct vas_window *txwin;
-	int rc, vasid;
+	int rc;
 
 	cp_inst = fp->private_data;
 
@@ -93,27 +93,20 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
 	}
 
 	if (uattr.version != 1) {
-		pr_err("Invalid version\n");
+		pr_err("Invalid window open API version\n");
 		return -EINVAL;
 	}
 
-	vasid = uattr.vas_id;
-
-	vas_init_tx_win_attr(&txattr, cp_inst->coproc->cop_type);
-
-	txattr.lpid = mfspr(SPRN_LPID);
-	txattr.pidr = mfspr(SPRN_PID);
-	txattr.user_win = true;
-	txattr.rsvd_txbuf_count = false;
-	txattr.pswid = false;
-
-	pr_devel("Pid %d: Opening txwin, PIDR %ld\n", txattr.pidr,
-				mfspr(SPRN_PID));
+	if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->open_win) {
+		pr_err("VAS API is not registered\n");
+		return -EACCES;
+	}
 
-	txwin = vas_tx_win_open(vasid, cp_inst->coproc->cop_type, &txattr);
+	txwin = cp_inst->coproc->vops->open_win(&uattr,
+						cp_inst->coproc->cop_type);
 	if (IS_ERR(txwin)) {
-		pr_err("%s() vas_tx_win_open() failed, %ld\n", __func__,
-					PTR_ERR(txwin));
+		pr_err("%s() VAS window open failed, %ld\n", __func__,
+				PTR_ERR(txwin));
 		return PTR_ERR(txwin);
 	}
 
@@ -125,9 +118,15 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
 static int coproc_release(struct inode *inode, struct file *fp)
 {
 	struct coproc_instance *cp_inst = fp->private_data;
+	int rc;
 
 	if (cp_inst->txwin) {
-		vas_win_close(cp_inst->txwin);
+		if (cp_inst->coproc->vops &&
+			cp_inst->coproc->vops->close_win) {
+			rc = cp_inst->coproc->vops->close_win(cp_inst->txwin);
+			if (rc)
+				return rc;
+		}
 		cp_inst->txwin = NULL;
 	}
 
@@ -168,7 +167,17 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
 		return -EINVAL;
 	}
 
-	vas_win_paste_addr(txwin, &paste_addr, NULL);
+	if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->paste_addr) {
+		pr_err("%s(): VAS API is not registered\n", __func__);
+		return -EACCES;
+	}
+
+	paste_addr = cp_inst->coproc->vops->paste_addr(txwin);
+	if (!paste_addr) {
+		pr_err("%s(): Window paste address failed\n", __func__);
+		return -EINVAL;
+	}
+
 	pfn = paste_addr >> PAGE_SHIFT;
 
 	/* flags, page_prot from cxl_mmap(), except we want cachable */
@@ -208,7 +217,7 @@ static struct file_operations coproc_fops = {
  * extended to other coprocessor types later.
  */
 int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
-				const char *name)
+			    const char *name, struct vas_user_win_ops *vops)
 {
 	int rc = -EINVAL;
 	dev_t devno;
@@ -230,6 +239,7 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
 	}
 	coproc_device.class->devnode = coproc_devnode;
 	coproc_device.cop_type = cop_type;
+	coproc_device.vops = vops;
 
 	coproc_fops.owner = mod;
 	cdev_init(&coproc_device.cdev, &coproc_fops);
diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
index 2fc0fbc4a3d1..3ccd3edcaf1a 100644
--- a/arch/powerpc/platforms/powernv/vas-window.c
+++ b/arch/powerpc/platforms/powernv/vas-window.c
@@ -16,6 +16,7 @@
 #include <linux/mmu_context.h>
 #include <asm/switch_to.h>
 #include <asm/ppc-opcode.h>
+#include <asm/vas.h>
 #include "vas.h"
 #include "copy-paste.h"
 
@@ -1442,6 +1443,49 @@ struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
 	return window;
 }
 
+static struct vas_window *vas_user_win_open(struct vas_tx_win_open_attr *uattr,
+				enum vas_cop_type cop_type)
+{
+	struct vas_tx_win_attr txattr = {};
+
+	vas_init_tx_win_attr(&txattr, cop_type);
+
+	txattr.lpid = mfspr(SPRN_LPID);
+	txattr.pidr = mfspr(SPRN_PID);
+	txattr.user_win = true;
+	txattr.rsvd_txbuf_count = false;
+	txattr.pswid = false;
+
+	pr_devel("Pid %d: Opening txwin, PIDR %ld\n", txattr.pidr,
+				mfspr(SPRN_PID));
+
+	return vas_tx_win_open(uattr->vas_id, cop_type, &txattr);
+}
+
+static u64 vas_user_win_paste_addr(void *addr)
+{
+	u64 paste_addr;
+
+	vas_win_paste_addr((struct vas_window *)addr, &paste_addr, NULL);
+
+	return paste_addr;
+}
+
+static int vas_user_win_close(void *addr)
+{
+	struct vas_window *txwin = addr;
+
+	vas_win_close(txwin);
+
+	return 0;
+}
+
+static struct vas_user_win_ops vops =  {
+	.open_win	=	vas_user_win_open,
+	.paste_addr	=	vas_user_win_paste_addr,
+	.close_win	=	vas_user_win_close,
+};
+
 /*
  * Supporting only nx-gzip coprocessor type now, but this API code
  * extended to other coprocessor types later.
@@ -1450,7 +1494,7 @@ int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
 			     const char *name)
 {
 
-	return vas_register_coproc_api(mod, cop_type, name);
+	return vas_register_coproc_api(mod, cop_type, name, &vops);
 }
 EXPORT_SYMBOL_GPL(vas_register_api_powernv);
 
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 03/16] powerpc/vas: Add platform specific user window operations
@ 2021-05-21  9:30   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:30 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


PowerNV uses registers to open/close VAS windows, and getting the
paste address. Whereas the hypervisor calls are used on PowerVM.

This patch adds the platform specific user space window operations
and register with the common VAS user space interface.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h              | 14 +++++-
 arch/powerpc/platforms/book3s/vas-api.c     | 52 ++++++++++++---------
 arch/powerpc/platforms/powernv/vas-window.c | 46 +++++++++++++++++-
 3 files changed, 89 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 6076adf9ab4f..668303198772 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -5,6 +5,7 @@
 
 #ifndef _ASM_POWERPC_VAS_H
 #define _ASM_POWERPC_VAS_H
+#include <uapi/asm/vas-api.h>
 
 struct vas_window;
 
@@ -48,6 +49,16 @@ enum vas_cop_type {
 	VAS_COP_TYPE_MAX,
 };
 
+/*
+ * User space window operations used for powernv and powerVM
+ */
+struct vas_user_win_ops {
+	struct vas_window * (*open_win)(struct vas_tx_win_open_attr *,
+				enum vas_cop_type);
+	u64 (*paste_addr)(void *);
+	int (*close_win)(void *);
+};
+
 /*
  * Receive window attributes specified by the (in-kernel) owner of window.
  */
@@ -177,7 +188,8 @@ void vas_unregister_api_powernv(void);
  * used for others in future.
  */
 int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
-				const char *name);
+			    const char *name,
+			    struct vas_user_win_ops *vops);
 void vas_unregister_coproc_api(void);
 
 #endif /* __ASM_POWERPC_VAS_H */
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index 72c126d87216..6c39320bfb9b 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -42,6 +42,7 @@ static struct coproc_dev {
 	dev_t devt;
 	struct class *class;
 	enum vas_cop_type cop_type;
+	struct vas_user_win_ops *vops;
 } coproc_device;
 
 struct coproc_instance {
@@ -72,11 +73,10 @@ static int coproc_open(struct inode *inode, struct file *fp)
 static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
 {
 	void __user *uptr = (void __user *)arg;
-	struct vas_tx_win_attr txattr = {};
 	struct vas_tx_win_open_attr uattr;
 	struct coproc_instance *cp_inst;
 	struct vas_window *txwin;
-	int rc, vasid;
+	int rc;
 
 	cp_inst = fp->private_data;
 
@@ -93,27 +93,20 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
 	}
 
 	if (uattr.version != 1) {
-		pr_err("Invalid version\n");
+		pr_err("Invalid window open API version\n");
 		return -EINVAL;
 	}
 
-	vasid = uattr.vas_id;
-
-	vas_init_tx_win_attr(&txattr, cp_inst->coproc->cop_type);
-
-	txattr.lpid = mfspr(SPRN_LPID);
-	txattr.pidr = mfspr(SPRN_PID);
-	txattr.user_win = true;
-	txattr.rsvd_txbuf_count = false;
-	txattr.pswid = false;
-
-	pr_devel("Pid %d: Opening txwin, PIDR %ld\n", txattr.pidr,
-				mfspr(SPRN_PID));
+	if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->open_win) {
+		pr_err("VAS API is not registered\n");
+		return -EACCES;
+	}
 
-	txwin = vas_tx_win_open(vasid, cp_inst->coproc->cop_type, &txattr);
+	txwin = cp_inst->coproc->vops->open_win(&uattr,
+						cp_inst->coproc->cop_type);
 	if (IS_ERR(txwin)) {
-		pr_err("%s() vas_tx_win_open() failed, %ld\n", __func__,
-					PTR_ERR(txwin));
+		pr_err("%s() VAS window open failed, %ld\n", __func__,
+				PTR_ERR(txwin));
 		return PTR_ERR(txwin);
 	}
 
@@ -125,9 +118,15 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
 static int coproc_release(struct inode *inode, struct file *fp)
 {
 	struct coproc_instance *cp_inst = fp->private_data;
+	int rc;
 
 	if (cp_inst->txwin) {
-		vas_win_close(cp_inst->txwin);
+		if (cp_inst->coproc->vops &&
+			cp_inst->coproc->vops->close_win) {
+			rc = cp_inst->coproc->vops->close_win(cp_inst->txwin);
+			if (rc)
+				return rc;
+		}
 		cp_inst->txwin = NULL;
 	}
 
@@ -168,7 +167,17 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
 		return -EINVAL;
 	}
 
-	vas_win_paste_addr(txwin, &paste_addr, NULL);
+	if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->paste_addr) {
+		pr_err("%s(): VAS API is not registered\n", __func__);
+		return -EACCES;
+	}
+
+	paste_addr = cp_inst->coproc->vops->paste_addr(txwin);
+	if (!paste_addr) {
+		pr_err("%s(): Window paste address failed\n", __func__);
+		return -EINVAL;
+	}
+
 	pfn = paste_addr >> PAGE_SHIFT;
 
 	/* flags, page_prot from cxl_mmap(), except we want cachable */
@@ -208,7 +217,7 @@ static struct file_operations coproc_fops = {
  * extended to other coprocessor types later.
  */
 int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
-				const char *name)
+			    const char *name, struct vas_user_win_ops *vops)
 {
 	int rc = -EINVAL;
 	dev_t devno;
@@ -230,6 +239,7 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
 	}
 	coproc_device.class->devnode = coproc_devnode;
 	coproc_device.cop_type = cop_type;
+	coproc_device.vops = vops;
 
 	coproc_fops.owner = mod;
 	cdev_init(&coproc_device.cdev, &coproc_fops);
diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
index 2fc0fbc4a3d1..3ccd3edcaf1a 100644
--- a/arch/powerpc/platforms/powernv/vas-window.c
+++ b/arch/powerpc/platforms/powernv/vas-window.c
@@ -16,6 +16,7 @@
 #include <linux/mmu_context.h>
 #include <asm/switch_to.h>
 #include <asm/ppc-opcode.h>
+#include <asm/vas.h>
 #include "vas.h"
 #include "copy-paste.h"
 
@@ -1442,6 +1443,49 @@ struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
 	return window;
 }
 
+static struct vas_window *vas_user_win_open(struct vas_tx_win_open_attr *uattr,
+				enum vas_cop_type cop_type)
+{
+	struct vas_tx_win_attr txattr = {};
+
+	vas_init_tx_win_attr(&txattr, cop_type);
+
+	txattr.lpid = mfspr(SPRN_LPID);
+	txattr.pidr = mfspr(SPRN_PID);
+	txattr.user_win = true;
+	txattr.rsvd_txbuf_count = false;
+	txattr.pswid = false;
+
+	pr_devel("Pid %d: Opening txwin, PIDR %ld\n", txattr.pidr,
+				mfspr(SPRN_PID));
+
+	return vas_tx_win_open(uattr->vas_id, cop_type, &txattr);
+}
+
+static u64 vas_user_win_paste_addr(void *addr)
+{
+	u64 paste_addr;
+
+	vas_win_paste_addr((struct vas_window *)addr, &paste_addr, NULL);
+
+	return paste_addr;
+}
+
+static int vas_user_win_close(void *addr)
+{
+	struct vas_window *txwin = addr;
+
+	vas_win_close(txwin);
+
+	return 0;
+}
+
+static struct vas_user_win_ops vops =  {
+	.open_win	=	vas_user_win_open,
+	.paste_addr	=	vas_user_win_paste_addr,
+	.close_win	=	vas_user_win_close,
+};
+
 /*
  * Supporting only nx-gzip coprocessor type now, but this API code
  * extended to other coprocessor types later.
@@ -1450,7 +1494,7 @@ int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
 			     const char *name)
 {
 
-	return vas_register_coproc_api(mod, cop_type, name);
+	return vas_register_coproc_api(mod, cop_type, name, &vops);
 }
 EXPORT_SYMBOL_GPL(vas_register_api_powernv);
 
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:31   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:31 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


Take pid and mm references when each window opens and drops during
close. This functionality is needed for powerNV and pseries. So
this patch defines the existing code as functions in common book3s
platform vas-api.c

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h              | 25 +++++++++
 arch/powerpc/platforms/book3s/vas-api.c     | 51 ++++++++++++++++++
 arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
 arch/powerpc/platforms/powernv/vas-window.c | 57 ++-------------------
 arch/powerpc/platforms/powernv/vas.h        |  6 +--
 5 files changed, 88 insertions(+), 61 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 668303198772..3f2b02461a76 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -5,6 +5,9 @@
 
 #ifndef _ASM_POWERPC_VAS_H
 #define _ASM_POWERPC_VAS_H
+#include <linux/sched/mm.h>
+#include <linux/mmu_context.h>
+#include <asm/icswx.h>
 #include <uapi/asm/vas-api.h>
 
 struct vas_window;
@@ -49,6 +52,17 @@ enum vas_cop_type {
 	VAS_COP_TYPE_MAX,
 };
 
+/*
+ * User space VAS windows are opened by tasks and take references
+ * to pid and mm until windows are closed.
+ * Stores pid, mm, and tgid for each window.
+ */
+struct vas_user_win_ref {
+	struct pid *pid;	/* PID of owner */
+	struct pid *tgid;	/* Thread group ID of owner */
+	struct mm_struct *mm;	/* Linux process mm_struct */
+};
+
 /*
  * User space window operations used for powernv and powerVM
  */
@@ -59,6 +73,16 @@ struct vas_user_win_ops {
 	int (*close_win)(void *);
 };
 
+static inline void vas_drop_reference_pid_mm(struct vas_user_win_ref *ref)
+{
+	/* Drop references to pid and mm */
+	put_pid(ref->pid);
+	if (ref->mm) {
+		mm_context_remove_vas_window(ref->mm);
+		mmdrop(ref->mm);
+	}
+}
+
 /*
  * Receive window attributes specified by the (in-kernel) owner of window.
  */
@@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
 			    struct vas_user_win_ops *vops);
 void vas_unregister_coproc_api(void);
 
+int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
 #endif /* __ASM_POWERPC_VAS_H */
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index 6c39320bfb9b..a0141bfb2e4b 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev, umode_t *mode)
 	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
 }
 
+/*
+ * Take reference to pid and mm
+ */
+int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
+{
+	/*
+	 * Window opened by a child thread may not be closed when
+	 * it exits. So take reference to its pid and release it
+	 * when the window is free by parent thread.
+	 * Acquire a reference to the task's pid to make sure
+	 * pid will not be re-used - needed only for multithread
+	 * applications.
+	 */
+	task_ref->pid = get_task_pid(current, PIDTYPE_PID);
+	/*
+	 * Acquire a reference to the task's mm.
+	 */
+	task_ref->mm = get_task_mm(current);
+	if (!task_ref->mm) {
+		put_pid(task_ref->pid);
+		pr_err("VAS: pid(%d): mm_struct is not found\n",
+				current->pid);
+		return -EPERM;
+	}
+
+	mmgrab(task_ref->mm);
+	mmput(task_ref->mm);
+	mm_context_add_vas_window(task_ref->mm);
+	/*
+	 * Process closes window during exit. In the case of
+	 * multithread application, the child thread can open
+	 * window and can exit without closing it. Expects parent
+	 * thread to use and close the window. So do not need
+	 * to take pid reference for parent thread.
+	 */
+	task_ref->tgid = find_get_pid(task_tgid_vnr(current));
+	/*
+	 * Even a process that has no foreign real address mapping can
+	 * use an unpaired COPY instruction (to no real effect). Issue
+	 * CP_ABORT to clear any pending COPY and prevent a covert
+	 * channel.
+	 *
+	 * __switch_to() will issue CP_ABORT on future context switches
+	 * if process / thread has any open VAS window (Use
+	 * current->mm->context.vas_windows).
+	 */
+	asm volatile(PPC_CP_ABORT);
+
+	return 0;
+}
+
 static int coproc_open(struct inode *inode, struct file *fp)
 {
 	struct coproc_instance *cp_inst;
diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index 3d21fce254b7..ac3a71ec3bd5 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -73,7 +73,7 @@ static void update_csb(struct vas_window *window,
 	 * NX user space windows can not be opened for task->mm=NULL
 	 * and faults will not be generated for kernel requests.
 	 */
-	if (WARN_ON_ONCE(!window->mm || !window->user_win))
+	if (WARN_ON_ONCE(!window->task_ref.mm || !window->user_win))
 		return;
 
 	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
@@ -92,7 +92,7 @@ static void update_csb(struct vas_window *window,
 	csb.address = crb->stamp.nx.fault_storage_addr;
 	csb.flags = 0;
 
-	pid = window->pid;
+	pid = window->task_ref.pid;
 	tsk = get_pid_task(pid, PIDTYPE_PID);
 	/*
 	 * Process closes send window after all pending NX requests are
@@ -111,7 +111,7 @@ static void update_csb(struct vas_window *window,
 	 * a window and exits without closing it.
 	 */
 	if (!tsk) {
-		pid = window->tgid;
+		pid = window->task_ref.tgid;
 		tsk = get_pid_task(pid, PIDTYPE_PID);
 		/*
 		 * Parent thread (tgid) will be closing window when it
@@ -127,7 +127,7 @@ static void update_csb(struct vas_window *window,
 		return;
 	}
 
-	kthread_use_mm(window->mm);
+	kthread_use_mm(window->task_ref.mm);
 	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
 	/*
 	 * User space polls on csb.flags (first byte). So add barrier
@@ -139,7 +139,7 @@ static void update_csb(struct vas_window *window,
 		smp_mb();
 		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
 	}
-	kthread_unuse_mm(window->mm);
+	kthread_unuse_mm(window->task_ref.mm);
 	put_task_struct(tsk);
 
 	/* Success */
diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
index 3ccd3edcaf1a..ffd619e5a218 100644
--- a/arch/powerpc/platforms/powernv/vas-window.c
+++ b/arch/powerpc/platforms/powernv/vas-window.c
@@ -1065,51 +1065,9 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
 			rc = -ENODEV;
 			goto free_window;
 		}
-
-		/*
-		 * Window opened by a child thread may not be closed when
-		 * it exits. So take reference to its pid and release it
-		 * when the window is free by parent thread.
-		 * Acquire a reference to the task's pid to make sure
-		 * pid will not be re-used - needed only for multithread
-		 * applications.
-		 */
-		txwin->pid = get_task_pid(current, PIDTYPE_PID);
-		/*
-		 * Acquire a reference to the task's mm.
-		 */
-		txwin->mm = get_task_mm(current);
-
-		if (!txwin->mm) {
-			put_pid(txwin->pid);
-			pr_err("VAS: pid(%d): mm_struct is not found\n",
-					current->pid);
-			rc = -EPERM;
+		rc = vas_reference_pid_mm(&txwin->task_ref);
+		if (rc)
 			goto free_window;
-		}
-
-		mmgrab(txwin->mm);
-		mmput(txwin->mm);
-		mm_context_add_vas_window(txwin->mm);
-		/*
-		 * Process closes window during exit. In the case of
-		 * multithread application, the child thread can open
-		 * window and can exit without closing it. Expects parent
-		 * thread to use and close the window. So do not need
-		 * to take pid reference for parent thread.
-		 */
-		txwin->tgid = find_get_pid(task_tgid_vnr(current));
-		/*
-		 * Even a process that has no foreign real address mapping can
-		 * use an unpaired COPY instruction (to no real effect). Issue
-		 * CP_ABORT to clear any pending COPY and prevent a covert
-		 * channel.
-		 *
-		 * __switch_to() will issue CP_ABORT on future context switches
-		 * if process / thread has any open VAS window (Use
-		 * current->mm->context.vas_windows).
-		 */
-		asm volatile(PPC_CP_ABORT);
 	}
 
 	set_vinst_win(vinst, txwin);
@@ -1339,14 +1297,9 @@ int vas_win_close(struct vas_window *window)
 
 	/* if send window, drop reference to matching receive window */
 	if (window->tx_win) {
-		if (window->user_win) {
-			/* Drop references to pid and mm */
-			put_pid(window->pid);
-			if (window->mm) {
-				mm_context_remove_vas_window(window->mm);
-				mmdrop(window->mm);
-			}
-		}
+		if (window->user_win)
+			vas_drop_reference_pid_mm(&window->task_ref);
+
 		put_rx_win(window->rxwin);
 	}
 
diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
index c7db3190baca..f354dd5c51bd 100644
--- a/arch/powerpc/platforms/powernv/vas.h
+++ b/arch/powerpc/platforms/powernv/vas.h
@@ -357,11 +357,9 @@ struct vas_window {
 	bool user_win;		/* True if user space window */
 	void *hvwc_map;		/* HV window context */
 	void *uwc_map;		/* OS/User window context */
-	struct pid *pid;	/* Linux process id of owner */
-	struct pid *tgid;	/* Thread group ID of owner */
-	struct mm_struct *mm;	/* Linux process mm_struct */
 	int wcreds_max;		/* Window credits */
 
+	struct vas_user_win_ref task_ref;
 	char *dbgname;
 	struct dentry *dbgdir;
 
@@ -443,7 +441,7 @@ extern void vas_win_paste_addr(struct vas_window *window, u64 *addr,
 
 static inline int vas_window_pid(struct vas_window *window)
 {
-	return pid_vnr(window->pid);
+	return pid_vnr(window->task_ref.pid);
 }
 
 static inline void vas_log_write(struct vas_window *win, char *name,
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
@ 2021-05-21  9:31   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:31 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


Take pid and mm references when each window opens and drops during
close. This functionality is needed for powerNV and pseries. So
this patch defines the existing code as functions in common book3s
platform vas-api.c

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h              | 25 +++++++++
 arch/powerpc/platforms/book3s/vas-api.c     | 51 ++++++++++++++++++
 arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
 arch/powerpc/platforms/powernv/vas-window.c | 57 ++-------------------
 arch/powerpc/platforms/powernv/vas.h        |  6 +--
 5 files changed, 88 insertions(+), 61 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 668303198772..3f2b02461a76 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -5,6 +5,9 @@
 
 #ifndef _ASM_POWERPC_VAS_H
 #define _ASM_POWERPC_VAS_H
+#include <linux/sched/mm.h>
+#include <linux/mmu_context.h>
+#include <asm/icswx.h>
 #include <uapi/asm/vas-api.h>
 
 struct vas_window;
@@ -49,6 +52,17 @@ enum vas_cop_type {
 	VAS_COP_TYPE_MAX,
 };
 
+/*
+ * User space VAS windows are opened by tasks and take references
+ * to pid and mm until windows are closed.
+ * Stores pid, mm, and tgid for each window.
+ */
+struct vas_user_win_ref {
+	struct pid *pid;	/* PID of owner */
+	struct pid *tgid;	/* Thread group ID of owner */
+	struct mm_struct *mm;	/* Linux process mm_struct */
+};
+
 /*
  * User space window operations used for powernv and powerVM
  */
@@ -59,6 +73,16 @@ struct vas_user_win_ops {
 	int (*close_win)(void *);
 };
 
+static inline void vas_drop_reference_pid_mm(struct vas_user_win_ref *ref)
+{
+	/* Drop references to pid and mm */
+	put_pid(ref->pid);
+	if (ref->mm) {
+		mm_context_remove_vas_window(ref->mm);
+		mmdrop(ref->mm);
+	}
+}
+
 /*
  * Receive window attributes specified by the (in-kernel) owner of window.
  */
@@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
 			    struct vas_user_win_ops *vops);
 void vas_unregister_coproc_api(void);
 
+int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
 #endif /* __ASM_POWERPC_VAS_H */
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index 6c39320bfb9b..a0141bfb2e4b 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev, umode_t *mode)
 	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
 }
 
+/*
+ * Take reference to pid and mm
+ */
+int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
+{
+	/*
+	 * Window opened by a child thread may not be closed when
+	 * it exits. So take reference to its pid and release it
+	 * when the window is free by parent thread.
+	 * Acquire a reference to the task's pid to make sure
+	 * pid will not be re-used - needed only for multithread
+	 * applications.
+	 */
+	task_ref->pid = get_task_pid(current, PIDTYPE_PID);
+	/*
+	 * Acquire a reference to the task's mm.
+	 */
+	task_ref->mm = get_task_mm(current);
+	if (!task_ref->mm) {
+		put_pid(task_ref->pid);
+		pr_err("VAS: pid(%d): mm_struct is not found\n",
+				current->pid);
+		return -EPERM;
+	}
+
+	mmgrab(task_ref->mm);
+	mmput(task_ref->mm);
+	mm_context_add_vas_window(task_ref->mm);
+	/*
+	 * Process closes window during exit. In the case of
+	 * multithread application, the child thread can open
+	 * window and can exit without closing it. Expects parent
+	 * thread to use and close the window. So do not need
+	 * to take pid reference for parent thread.
+	 */
+	task_ref->tgid = find_get_pid(task_tgid_vnr(current));
+	/*
+	 * Even a process that has no foreign real address mapping can
+	 * use an unpaired COPY instruction (to no real effect). Issue
+	 * CP_ABORT to clear any pending COPY and prevent a covert
+	 * channel.
+	 *
+	 * __switch_to() will issue CP_ABORT on future context switches
+	 * if process / thread has any open VAS window (Use
+	 * current->mm->context.vas_windows).
+	 */
+	asm volatile(PPC_CP_ABORT);
+
+	return 0;
+}
+
 static int coproc_open(struct inode *inode, struct file *fp)
 {
 	struct coproc_instance *cp_inst;
diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index 3d21fce254b7..ac3a71ec3bd5 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -73,7 +73,7 @@ static void update_csb(struct vas_window *window,
 	 * NX user space windows can not be opened for task->mm=NULL
 	 * and faults will not be generated for kernel requests.
 	 */
-	if (WARN_ON_ONCE(!window->mm || !window->user_win))
+	if (WARN_ON_ONCE(!window->task_ref.mm || !window->user_win))
 		return;
 
 	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
@@ -92,7 +92,7 @@ static void update_csb(struct vas_window *window,
 	csb.address = crb->stamp.nx.fault_storage_addr;
 	csb.flags = 0;
 
-	pid = window->pid;
+	pid = window->task_ref.pid;
 	tsk = get_pid_task(pid, PIDTYPE_PID);
 	/*
 	 * Process closes send window after all pending NX requests are
@@ -111,7 +111,7 @@ static void update_csb(struct vas_window *window,
 	 * a window and exits without closing it.
 	 */
 	if (!tsk) {
-		pid = window->tgid;
+		pid = window->task_ref.tgid;
 		tsk = get_pid_task(pid, PIDTYPE_PID);
 		/*
 		 * Parent thread (tgid) will be closing window when it
@@ -127,7 +127,7 @@ static void update_csb(struct vas_window *window,
 		return;
 	}
 
-	kthread_use_mm(window->mm);
+	kthread_use_mm(window->task_ref.mm);
 	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
 	/*
 	 * User space polls on csb.flags (first byte). So add barrier
@@ -139,7 +139,7 @@ static void update_csb(struct vas_window *window,
 		smp_mb();
 		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
 	}
-	kthread_unuse_mm(window->mm);
+	kthread_unuse_mm(window->task_ref.mm);
 	put_task_struct(tsk);
 
 	/* Success */
diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
index 3ccd3edcaf1a..ffd619e5a218 100644
--- a/arch/powerpc/platforms/powernv/vas-window.c
+++ b/arch/powerpc/platforms/powernv/vas-window.c
@@ -1065,51 +1065,9 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
 			rc = -ENODEV;
 			goto free_window;
 		}
-
-		/*
-		 * Window opened by a child thread may not be closed when
-		 * it exits. So take reference to its pid and release it
-		 * when the window is free by parent thread.
-		 * Acquire a reference to the task's pid to make sure
-		 * pid will not be re-used - needed only for multithread
-		 * applications.
-		 */
-		txwin->pid = get_task_pid(current, PIDTYPE_PID);
-		/*
-		 * Acquire a reference to the task's mm.
-		 */
-		txwin->mm = get_task_mm(current);
-
-		if (!txwin->mm) {
-			put_pid(txwin->pid);
-			pr_err("VAS: pid(%d): mm_struct is not found\n",
-					current->pid);
-			rc = -EPERM;
+		rc = vas_reference_pid_mm(&txwin->task_ref);
+		if (rc)
 			goto free_window;
-		}
-
-		mmgrab(txwin->mm);
-		mmput(txwin->mm);
-		mm_context_add_vas_window(txwin->mm);
-		/*
-		 * Process closes window during exit. In the case of
-		 * multithread application, the child thread can open
-		 * window and can exit without closing it. Expects parent
-		 * thread to use and close the window. So do not need
-		 * to take pid reference for parent thread.
-		 */
-		txwin->tgid = find_get_pid(task_tgid_vnr(current));
-		/*
-		 * Even a process that has no foreign real address mapping can
-		 * use an unpaired COPY instruction (to no real effect). Issue
-		 * CP_ABORT to clear any pending COPY and prevent a covert
-		 * channel.
-		 *
-		 * __switch_to() will issue CP_ABORT on future context switches
-		 * if process / thread has any open VAS window (Use
-		 * current->mm->context.vas_windows).
-		 */
-		asm volatile(PPC_CP_ABORT);
 	}
 
 	set_vinst_win(vinst, txwin);
@@ -1339,14 +1297,9 @@ int vas_win_close(struct vas_window *window)
 
 	/* if send window, drop reference to matching receive window */
 	if (window->tx_win) {
-		if (window->user_win) {
-			/* Drop references to pid and mm */
-			put_pid(window->pid);
-			if (window->mm) {
-				mm_context_remove_vas_window(window->mm);
-				mmdrop(window->mm);
-			}
-		}
+		if (window->user_win)
+			vas_drop_reference_pid_mm(&window->task_ref);
+
 		put_rx_win(window->rxwin);
 	}
 
diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
index c7db3190baca..f354dd5c51bd 100644
--- a/arch/powerpc/platforms/powernv/vas.h
+++ b/arch/powerpc/platforms/powernv/vas.h
@@ -357,11 +357,9 @@ struct vas_window {
 	bool user_win;		/* True if user space window */
 	void *hvwc_map;		/* HV window context */
 	void *uwc_map;		/* OS/User window context */
-	struct pid *pid;	/* Linux process id of owner */
-	struct pid *tgid;	/* Thread group ID of owner */
-	struct mm_struct *mm;	/* Linux process mm_struct */
 	int wcreds_max;		/* Window credits */
 
+	struct vas_user_win_ref task_ref;
 	char *dbgname;
 	struct dentry *dbgdir;
 
@@ -443,7 +441,7 @@ extern void vas_win_paste_addr(struct vas_window *window, u64 *addr,
 
 static inline int vas_window_pid(struct vas_window *window)
 {
-	return pid_vnr(window->pid);
+	return pid_vnr(window->task_ref.pid);
 }
 
 static inline void vas_log_write(struct vas_window *win, char *name,
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 05/16] powerpc/vas: Move update_csb/dump_crb to common book3s platform
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:32   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:32 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


If a coprocessor encounters an error translating an address, the
VAS will cause an interrupt in the host. The kernel processes
the fault by updating CSB. This functionality is same for both
powerNV and pseries. So this patch moves these functions to
common vas-api.c and the actual functionality is not changed.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/vas.h             |   3 +
 arch/powerpc/platforms/book3s/vas-api.c    | 147 +++++++++++++++++++
 arch/powerpc/platforms/powernv/vas-fault.c | 155 ++-------------------
 3 files changed, 159 insertions(+), 146 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 3f2b02461a76..2c1040f399d9 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -217,4 +217,7 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
 void vas_unregister_coproc_api(void);
 
 int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
+void vas_update_csb(struct coprocessor_request_block *crb,
+		    struct vas_user_win_ref *task_ref);
+void vas_dump_crb(struct coprocessor_request_block *crb);
 #endif /* __ASM_POWERPC_VAS_H */
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index a0141bfb2e4b..992b45795a05 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -10,6 +10,9 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/kthread.h>
+#include <linux/sched/signal.h>
+#include <linux/mmu_context.h>
 #include <linux/io.h>
 #include <asm/vas.h>
 #include <uapi/asm/vas-api.h>
@@ -106,6 +109,150 @@ int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
 	return 0;
 }
 
+/*
+ * Update the CSB to indicate a translation error.
+ *
+ * User space will be polling on CSB after the request is issued.
+ * If NX can handle the request without any issues, it updates CSB.
+ * Whereas if NX encounters page fault, the kernel will handle the
+ * fault and update CSB with translation error.
+ *
+ * If we are unable to update the CSB means copy_to_user failed due to
+ * invalid csb_addr, send a signal to the process.
+ */
+void vas_update_csb(struct coprocessor_request_block *crb,
+		    struct vas_user_win_ref *task_ref)
+{
+	struct coprocessor_status_block csb;
+	struct kernel_siginfo info;
+	struct task_struct *tsk;
+	void __user *csb_addr;
+	struct pid *pid;
+	int rc;
+
+	/*
+	 * NX user space windows can not be opened for task->mm=NULL
+	 * and faults will not be generated for kernel requests.
+	 */
+	if (WARN_ON_ONCE(!task_ref->mm))
+		return;
+
+	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
+
+	memset(&csb, 0, sizeof(csb));
+	csb.cc = CSB_CC_FAULT_ADDRESS;
+	csb.ce = CSB_CE_TERMINATION;
+	csb.cs = 0;
+	csb.count = 0;
+
+	/*
+	 * NX operates and returns in BE format as defined CRB struct.
+	 * So saves fault_storage_addr in BE as NX pastes in FIFO and
+	 * expects user space to convert to CPU format.
+	 */
+	csb.address = crb->stamp.nx.fault_storage_addr;
+	csb.flags = 0;
+
+	pid = task_ref->pid;
+	tsk = get_pid_task(pid, PIDTYPE_PID);
+	/*
+	 * Process closes send window after all pending NX requests are
+	 * completed. In multi-thread applications, a child thread can
+	 * open a window and can exit without closing it. May be some
+	 * requests are pending or this window can be used by other
+	 * threads later. We should handle faults if NX encounters
+	 * pages faults on these requests. Update CSB with translation
+	 * error and fault address. If csb_addr passed by user space is
+	 * invalid, send SEGV signal to pid saved in window. If the
+	 * child thread is not running, send the signal to tgid.
+	 * Parent thread (tgid) will close this window upon its exit.
+	 *
+	 * pid and mm references are taken when window is opened by
+	 * process (pid). So tgid is used only when child thread opens
+	 * a window and exits without closing it.
+	 */
+	if (!tsk) {
+		pid = task_ref->tgid;
+		tsk = get_pid_task(pid, PIDTYPE_PID);
+		/*
+		 * Parent thread (tgid) will be closing window when it
+		 * exits. So should not get here.
+		 */
+		if (WARN_ON_ONCE(!tsk))
+			return;
+	}
+
+	/* Return if the task is exiting. */
+	if (tsk->flags & PF_EXITING) {
+		put_task_struct(tsk);
+		return;
+	}
+
+	kthread_use_mm(task_ref->mm);
+	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
+	/*
+	 * User space polls on csb.flags (first byte). So add barrier
+	 * then copy first byte with csb flags update.
+	 */
+	if (!rc) {
+		csb.flags = CSB_V;
+		/* Make sure update to csb.flags is visible now */
+		smp_mb();
+		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
+	}
+	kthread_unuse_mm(task_ref->mm);
+	put_task_struct(tsk);
+
+	/* Success */
+	if (!rc)
+		return;
+
+
+	pr_debug("Invalid CSB address 0x%p signalling pid(%d)\n",
+			csb_addr, pid_vnr(pid));
+
+	clear_siginfo(&info);
+	info.si_signo = SIGSEGV;
+	info.si_errno = EFAULT;
+	info.si_code = SEGV_MAPERR;
+	info.si_addr = csb_addr;
+	/*
+	 * process will be polling on csb.flags after request is sent to
+	 * NX. So generally CSB update should not fail except when an
+	 * application passes invalid csb_addr. So an error message will
+	 * be displayed and leave it to user space whether to ignore or
+	 * handle this signal.
+	 */
+	rcu_read_lock();
+	rc = kill_pid_info(SIGSEGV, &info, pid);
+	rcu_read_unlock();
+
+	pr_devel("%s(): pid %d kill_proc_info() rc %d\n", __func__,
+			pid_vnr(pid), rc);
+}
+
+void vas_dump_crb(struct coprocessor_request_block *crb)
+{
+	struct data_descriptor_entry *dde;
+	struct nx_fault_stamp *nx;
+
+	dde = &crb->source;
+	pr_devel("SrcDDE: addr 0x%llx, len %d, count %d, idx %d, flags %d\n",
+		be64_to_cpu(dde->address), be32_to_cpu(dde->length),
+		dde->count, dde->index, dde->flags);
+
+	dde = &crb->target;
+	pr_devel("TgtDDE: addr 0x%llx, len %d, count %d, idx %d, flags %d\n",
+		be64_to_cpu(dde->address), be32_to_cpu(dde->length),
+		dde->count, dde->index, dde->flags);
+
+	nx = &crb->stamp.nx;
+	pr_devel("NX Stamp: PSWID 0x%x, FSA 0x%llx, flags 0x%x, FS 0x%x\n",
+		be32_to_cpu(nx->pswid),
+		be64_to_cpu(crb->stamp.nx.fault_storage_addr),
+		nx->flags, nx->fault_status);
+}
+
 static int coproc_open(struct inode *inode, struct file *fp)
 {
 	struct coproc_instance *cp_inst;
diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index ac3a71ec3bd5..2729ac541fb3 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -26,150 +26,6 @@
  */
 #define VAS_FAULT_WIN_FIFO_SIZE	(4 << 20)
 
-static void dump_crb(struct coprocessor_request_block *crb)
-{
-	struct data_descriptor_entry *dde;
-	struct nx_fault_stamp *nx;
-
-	dde = &crb->source;
-	pr_devel("SrcDDE: addr 0x%llx, len %d, count %d, idx %d, flags %d\n",
-		be64_to_cpu(dde->address), be32_to_cpu(dde->length),
-		dde->count, dde->index, dde->flags);
-
-	dde = &crb->target;
-	pr_devel("TgtDDE: addr 0x%llx, len %d, count %d, idx %d, flags %d\n",
-		be64_to_cpu(dde->address), be32_to_cpu(dde->length),
-		dde->count, dde->index, dde->flags);
-
-	nx = &crb->stamp.nx;
-	pr_devel("NX Stamp: PSWID 0x%x, FSA 0x%llx, flags 0x%x, FS 0x%x\n",
-		be32_to_cpu(nx->pswid),
-		be64_to_cpu(crb->stamp.nx.fault_storage_addr),
-		nx->flags, nx->fault_status);
-}
-
-/*
- * Update the CSB to indicate a translation error.
- *
- * User space will be polling on CSB after the request is issued.
- * If NX can handle the request without any issues, it updates CSB.
- * Whereas if NX encounters page fault, the kernel will handle the
- * fault and update CSB with translation error.
- *
- * If we are unable to update the CSB means copy_to_user failed due to
- * invalid csb_addr, send a signal to the process.
- */
-static void update_csb(struct vas_window *window,
-			struct coprocessor_request_block *crb)
-{
-	struct coprocessor_status_block csb;
-	struct kernel_siginfo info;
-	struct task_struct *tsk;
-	void __user *csb_addr;
-	struct pid *pid;
-	int rc;
-
-	/*
-	 * NX user space windows can not be opened for task->mm=NULL
-	 * and faults will not be generated for kernel requests.
-	 */
-	if (WARN_ON_ONCE(!window->task_ref.mm || !window->user_win))
-		return;
-
-	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
-
-	memset(&csb, 0, sizeof(csb));
-	csb.cc = CSB_CC_FAULT_ADDRESS;
-	csb.ce = CSB_CE_TERMINATION;
-	csb.cs = 0;
-	csb.count = 0;
-
-	/*
-	 * NX operates and returns in BE format as defined CRB struct.
-	 * So saves fault_storage_addr in BE as NX pastes in FIFO and
-	 * expects user space to convert to CPU format.
-	 */
-	csb.address = crb->stamp.nx.fault_storage_addr;
-	csb.flags = 0;
-
-	pid = window->task_ref.pid;
-	tsk = get_pid_task(pid, PIDTYPE_PID);
-	/*
-	 * Process closes send window after all pending NX requests are
-	 * completed. In multi-thread applications, a child thread can
-	 * open a window and can exit without closing it. May be some
-	 * requests are pending or this window can be used by other
-	 * threads later. We should handle faults if NX encounters
-	 * pages faults on these requests. Update CSB with translation
-	 * error and fault address. If csb_addr passed by user space is
-	 * invalid, send SEGV signal to pid saved in window. If the
-	 * child thread is not running, send the signal to tgid.
-	 * Parent thread (tgid) will close this window upon its exit.
-	 *
-	 * pid and mm references are taken when window is opened by
-	 * process (pid). So tgid is used only when child thread opens
-	 * a window and exits without closing it.
-	 */
-	if (!tsk) {
-		pid = window->task_ref.tgid;
-		tsk = get_pid_task(pid, PIDTYPE_PID);
-		/*
-		 * Parent thread (tgid) will be closing window when it
-		 * exits. So should not get here.
-		 */
-		if (WARN_ON_ONCE(!tsk))
-			return;
-	}
-
-	/* Return if the task is exiting. */
-	if (tsk->flags & PF_EXITING) {
-		put_task_struct(tsk);
-		return;
-	}
-
-	kthread_use_mm(window->task_ref.mm);
-	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
-	/*
-	 * User space polls on csb.flags (first byte). So add barrier
-	 * then copy first byte with csb flags update.
-	 */
-	if (!rc) {
-		csb.flags = CSB_V;
-		/* Make sure update to csb.flags is visible now */
-		smp_mb();
-		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
-	}
-	kthread_unuse_mm(window->task_ref.mm);
-	put_task_struct(tsk);
-
-	/* Success */
-	if (!rc)
-		return;
-
-	pr_debug("Invalid CSB address 0x%p signalling pid(%d)\n",
-			csb_addr, pid_vnr(pid));
-
-	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = EFAULT;
-	info.si_code = SEGV_MAPERR;
-	info.si_addr = csb_addr;
-
-	/*
-	 * process will be polling on csb.flags after request is sent to
-	 * NX. So generally CSB update should not fail except when an
-	 * application passes invalid csb_addr. So an error message will
-	 * be displayed and leave it to user space whether to ignore or
-	 * handle this signal.
-	 */
-	rcu_read_lock();
-	rc = kill_pid_info(SIGSEGV, &info, pid);
-	rcu_read_unlock();
-
-	pr_devel("%s(): pid %d kill_proc_info() rc %d\n", __func__,
-			pid_vnr(pid), rc);
-}
-
 static void dump_fifo(struct vas_instance *vinst, void *entry)
 {
 	unsigned long *end = vinst->fault_fifo + vinst->fault_fifo_size;
@@ -272,7 +128,7 @@ irqreturn_t vas_fault_thread_fn(int irq, void *data)
 				vinst->vas_id, vinst->fault_fifo, fifo,
 				vinst->fault_crbs);
 
-		dump_crb(crb);
+		vas_dump_crb(crb);
 		window = vas_pswid_to_window(vinst,
 				be32_to_cpu(crb->stamp.nx.pswid));
 
@@ -293,7 +149,14 @@ irqreturn_t vas_fault_thread_fn(int irq, void *data)
 
 			WARN_ON_ONCE(1);
 		} else {
-			update_csb(window, crb);
+			/*
+			 * NX sees faults only with user space windows.
+			 */
+			if (window->user_win)
+				vas_update_csb(crb, &window->task_ref);
+			else
+				WARN_ON_ONCE(!window->user_win);
+
 			/*
 			 * Return credit for send window after processing
 			 * fault CRB.
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 05/16] powerpc/vas: Move update_csb/dump_crb to common book3s platform
@ 2021-05-21  9:32   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:32 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


If a coprocessor encounters an error translating an address, the
VAS will cause an interrupt in the host. The kernel processes
the fault by updating CSB. This functionality is same for both
powerNV and pseries. So this patch moves these functions to
common vas-api.c and the actual functionality is not changed.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/vas.h             |   3 +
 arch/powerpc/platforms/book3s/vas-api.c    | 147 +++++++++++++++++++
 arch/powerpc/platforms/powernv/vas-fault.c | 155 ++-------------------
 3 files changed, 159 insertions(+), 146 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 3f2b02461a76..2c1040f399d9 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -217,4 +217,7 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
 void vas_unregister_coproc_api(void);
 
 int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
+void vas_update_csb(struct coprocessor_request_block *crb,
+		    struct vas_user_win_ref *task_ref);
+void vas_dump_crb(struct coprocessor_request_block *crb);
 #endif /* __ASM_POWERPC_VAS_H */
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index a0141bfb2e4b..992b45795a05 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -10,6 +10,9 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/kthread.h>
+#include <linux/sched/signal.h>
+#include <linux/mmu_context.h>
 #include <linux/io.h>
 #include <asm/vas.h>
 #include <uapi/asm/vas-api.h>
@@ -106,6 +109,150 @@ int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
 	return 0;
 }
 
+/*
+ * Update the CSB to indicate a translation error.
+ *
+ * User space will be polling on CSB after the request is issued.
+ * If NX can handle the request without any issues, it updates CSB.
+ * Whereas if NX encounters page fault, the kernel will handle the
+ * fault and update CSB with translation error.
+ *
+ * If we are unable to update the CSB means copy_to_user failed due to
+ * invalid csb_addr, send a signal to the process.
+ */
+void vas_update_csb(struct coprocessor_request_block *crb,
+		    struct vas_user_win_ref *task_ref)
+{
+	struct coprocessor_status_block csb;
+	struct kernel_siginfo info;
+	struct task_struct *tsk;
+	void __user *csb_addr;
+	struct pid *pid;
+	int rc;
+
+	/*
+	 * NX user space windows can not be opened for task->mm=NULL
+	 * and faults will not be generated for kernel requests.
+	 */
+	if (WARN_ON_ONCE(!task_ref->mm))
+		return;
+
+	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
+
+	memset(&csb, 0, sizeof(csb));
+	csb.cc = CSB_CC_FAULT_ADDRESS;
+	csb.ce = CSB_CE_TERMINATION;
+	csb.cs = 0;
+	csb.count = 0;
+
+	/*
+	 * NX operates and returns in BE format as defined CRB struct.
+	 * So saves fault_storage_addr in BE as NX pastes in FIFO and
+	 * expects user space to convert to CPU format.
+	 */
+	csb.address = crb->stamp.nx.fault_storage_addr;
+	csb.flags = 0;
+
+	pid = task_ref->pid;
+	tsk = get_pid_task(pid, PIDTYPE_PID);
+	/*
+	 * Process closes send window after all pending NX requests are
+	 * completed. In multi-thread applications, a child thread can
+	 * open a window and can exit without closing it. May be some
+	 * requests are pending or this window can be used by other
+	 * threads later. We should handle faults if NX encounters
+	 * pages faults on these requests. Update CSB with translation
+	 * error and fault address. If csb_addr passed by user space is
+	 * invalid, send SEGV signal to pid saved in window. If the
+	 * child thread is not running, send the signal to tgid.
+	 * Parent thread (tgid) will close this window upon its exit.
+	 *
+	 * pid and mm references are taken when window is opened by
+	 * process (pid). So tgid is used only when child thread opens
+	 * a window and exits without closing it.
+	 */
+	if (!tsk) {
+		pid = task_ref->tgid;
+		tsk = get_pid_task(pid, PIDTYPE_PID);
+		/*
+		 * Parent thread (tgid) will be closing window when it
+		 * exits. So should not get here.
+		 */
+		if (WARN_ON_ONCE(!tsk))
+			return;
+	}
+
+	/* Return if the task is exiting. */
+	if (tsk->flags & PF_EXITING) {
+		put_task_struct(tsk);
+		return;
+	}
+
+	kthread_use_mm(task_ref->mm);
+	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
+	/*
+	 * User space polls on csb.flags (first byte). So add barrier
+	 * then copy first byte with csb flags update.
+	 */
+	if (!rc) {
+		csb.flags = CSB_V;
+		/* Make sure update to csb.flags is visible now */
+		smp_mb();
+		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
+	}
+	kthread_unuse_mm(task_ref->mm);
+	put_task_struct(tsk);
+
+	/* Success */
+	if (!rc)
+		return;
+
+
+	pr_debug("Invalid CSB address 0x%p signalling pid(%d)\n",
+			csb_addr, pid_vnr(pid));
+
+	clear_siginfo(&info);
+	info.si_signo = SIGSEGV;
+	info.si_errno = EFAULT;
+	info.si_code = SEGV_MAPERR;
+	info.si_addr = csb_addr;
+	/*
+	 * process will be polling on csb.flags after request is sent to
+	 * NX. So generally CSB update should not fail except when an
+	 * application passes invalid csb_addr. So an error message will
+	 * be displayed and leave it to user space whether to ignore or
+	 * handle this signal.
+	 */
+	rcu_read_lock();
+	rc = kill_pid_info(SIGSEGV, &info, pid);
+	rcu_read_unlock();
+
+	pr_devel("%s(): pid %d kill_proc_info() rc %d\n", __func__,
+			pid_vnr(pid), rc);
+}
+
+void vas_dump_crb(struct coprocessor_request_block *crb)
+{
+	struct data_descriptor_entry *dde;
+	struct nx_fault_stamp *nx;
+
+	dde = &crb->source;
+	pr_devel("SrcDDE: addr 0x%llx, len %d, count %d, idx %d, flags %d\n",
+		be64_to_cpu(dde->address), be32_to_cpu(dde->length),
+		dde->count, dde->index, dde->flags);
+
+	dde = &crb->target;
+	pr_devel("TgtDDE: addr 0x%llx, len %d, count %d, idx %d, flags %d\n",
+		be64_to_cpu(dde->address), be32_to_cpu(dde->length),
+		dde->count, dde->index, dde->flags);
+
+	nx = &crb->stamp.nx;
+	pr_devel("NX Stamp: PSWID 0x%x, FSA 0x%llx, flags 0x%x, FS 0x%x\n",
+		be32_to_cpu(nx->pswid),
+		be64_to_cpu(crb->stamp.nx.fault_storage_addr),
+		nx->flags, nx->fault_status);
+}
+
 static int coproc_open(struct inode *inode, struct file *fp)
 {
 	struct coproc_instance *cp_inst;
diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index ac3a71ec3bd5..2729ac541fb3 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -26,150 +26,6 @@
  */
 #define VAS_FAULT_WIN_FIFO_SIZE	(4 << 20)
 
-static void dump_crb(struct coprocessor_request_block *crb)
-{
-	struct data_descriptor_entry *dde;
-	struct nx_fault_stamp *nx;
-
-	dde = &crb->source;
-	pr_devel("SrcDDE: addr 0x%llx, len %d, count %d, idx %d, flags %d\n",
-		be64_to_cpu(dde->address), be32_to_cpu(dde->length),
-		dde->count, dde->index, dde->flags);
-
-	dde = &crb->target;
-	pr_devel("TgtDDE: addr 0x%llx, len %d, count %d, idx %d, flags %d\n",
-		be64_to_cpu(dde->address), be32_to_cpu(dde->length),
-		dde->count, dde->index, dde->flags);
-
-	nx = &crb->stamp.nx;
-	pr_devel("NX Stamp: PSWID 0x%x, FSA 0x%llx, flags 0x%x, FS 0x%x\n",
-		be32_to_cpu(nx->pswid),
-		be64_to_cpu(crb->stamp.nx.fault_storage_addr),
-		nx->flags, nx->fault_status);
-}
-
-/*
- * Update the CSB to indicate a translation error.
- *
- * User space will be polling on CSB after the request is issued.
- * If NX can handle the request without any issues, it updates CSB.
- * Whereas if NX encounters page fault, the kernel will handle the
- * fault and update CSB with translation error.
- *
- * If we are unable to update the CSB means copy_to_user failed due to
- * invalid csb_addr, send a signal to the process.
- */
-static void update_csb(struct vas_window *window,
-			struct coprocessor_request_block *crb)
-{
-	struct coprocessor_status_block csb;
-	struct kernel_siginfo info;
-	struct task_struct *tsk;
-	void __user *csb_addr;
-	struct pid *pid;
-	int rc;
-
-	/*
-	 * NX user space windows can not be opened for task->mm=NULL
-	 * and faults will not be generated for kernel requests.
-	 */
-	if (WARN_ON_ONCE(!window->task_ref.mm || !window->user_win))
-		return;
-
-	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
-
-	memset(&csb, 0, sizeof(csb));
-	csb.cc = CSB_CC_FAULT_ADDRESS;
-	csb.ce = CSB_CE_TERMINATION;
-	csb.cs = 0;
-	csb.count = 0;
-
-	/*
-	 * NX operates and returns in BE format as defined CRB struct.
-	 * So saves fault_storage_addr in BE as NX pastes in FIFO and
-	 * expects user space to convert to CPU format.
-	 */
-	csb.address = crb->stamp.nx.fault_storage_addr;
-	csb.flags = 0;
-
-	pid = window->task_ref.pid;
-	tsk = get_pid_task(pid, PIDTYPE_PID);
-	/*
-	 * Process closes send window after all pending NX requests are
-	 * completed. In multi-thread applications, a child thread can
-	 * open a window and can exit without closing it. May be some
-	 * requests are pending or this window can be used by other
-	 * threads later. We should handle faults if NX encounters
-	 * pages faults on these requests. Update CSB with translation
-	 * error and fault address. If csb_addr passed by user space is
-	 * invalid, send SEGV signal to pid saved in window. If the
-	 * child thread is not running, send the signal to tgid.
-	 * Parent thread (tgid) will close this window upon its exit.
-	 *
-	 * pid and mm references are taken when window is opened by
-	 * process (pid). So tgid is used only when child thread opens
-	 * a window and exits without closing it.
-	 */
-	if (!tsk) {
-		pid = window->task_ref.tgid;
-		tsk = get_pid_task(pid, PIDTYPE_PID);
-		/*
-		 * Parent thread (tgid) will be closing window when it
-		 * exits. So should not get here.
-		 */
-		if (WARN_ON_ONCE(!tsk))
-			return;
-	}
-
-	/* Return if the task is exiting. */
-	if (tsk->flags & PF_EXITING) {
-		put_task_struct(tsk);
-		return;
-	}
-
-	kthread_use_mm(window->task_ref.mm);
-	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
-	/*
-	 * User space polls on csb.flags (first byte). So add barrier
-	 * then copy first byte with csb flags update.
-	 */
-	if (!rc) {
-		csb.flags = CSB_V;
-		/* Make sure update to csb.flags is visible now */
-		smp_mb();
-		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
-	}
-	kthread_unuse_mm(window->task_ref.mm);
-	put_task_struct(tsk);
-
-	/* Success */
-	if (!rc)
-		return;
-
-	pr_debug("Invalid CSB address 0x%p signalling pid(%d)\n",
-			csb_addr, pid_vnr(pid));
-
-	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = EFAULT;
-	info.si_code = SEGV_MAPERR;
-	info.si_addr = csb_addr;
-
-	/*
-	 * process will be polling on csb.flags after request is sent to
-	 * NX. So generally CSB update should not fail except when an
-	 * application passes invalid csb_addr. So an error message will
-	 * be displayed and leave it to user space whether to ignore or
-	 * handle this signal.
-	 */
-	rcu_read_lock();
-	rc = kill_pid_info(SIGSEGV, &info, pid);
-	rcu_read_unlock();
-
-	pr_devel("%s(): pid %d kill_proc_info() rc %d\n", __func__,
-			pid_vnr(pid), rc);
-}
-
 static void dump_fifo(struct vas_instance *vinst, void *entry)
 {
 	unsigned long *end = vinst->fault_fifo + vinst->fault_fifo_size;
@@ -272,7 +128,7 @@ irqreturn_t vas_fault_thread_fn(int irq, void *data)
 				vinst->vas_id, vinst->fault_fifo, fifo,
 				vinst->fault_crbs);
 
-		dump_crb(crb);
+		vas_dump_crb(crb);
 		window = vas_pswid_to_window(vinst,
 				be32_to_cpu(crb->stamp.nx.pswid));
 
@@ -293,7 +149,14 @@ irqreturn_t vas_fault_thread_fn(int irq, void *data)
 
 			WARN_ON_ONCE(1);
 		} else {
-			update_csb(window, crb);
+			/*
+			 * NX sees faults only with user space windows.
+			 */
+			if (window->user_win)
+				vas_update_csb(crb, &window->task_ref);
+			else
+				WARN_ON_ONCE(!window->user_win);
+
 			/*
 			 * Return credit for send window after processing
 			 * fault CRB.
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:33   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:33 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


Same vas_window struct is used on powerNV and pseries. So this patch
changes in struct vas_window to support both platforms and also the
corresponding modifications in powerNV vas code.

On powerNV, vas_window is used for both TX and RX windows, whereas
only for TX windows on powerVM. So some elements are specific to
these platforms.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h              |  50 +++++++-
 arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
 arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
 arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
 arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++---------
 arch/powerpc/platforms/powernv/vas.h        |  38 +-----
 6 files changed, 135 insertions(+), 104 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 2c1040f399d9..49bfb5be896d 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -10,8 +10,6 @@
 #include <asm/icswx.h>
 #include <uapi/asm/vas-api.h>
 
-struct vas_window;
-
 /*
  * Min and max FIFO sizes are based on Version 1.05 Section 3.1.4.25
  * (Local FIFO Size Register) of the VAS workbook.
@@ -63,6 +61,54 @@ struct vas_user_win_ref {
 	struct mm_struct *mm;	/* Linux process mm_struct */
 };
 
+/*
+ * In-kernel state a VAS window. One per window.
+ * powerVM: Used only for Tx windows.
+ * powerNV: Used for both Tx and Rx windows.
+ */
+struct vas_window {
+	u32 winid;
+	u32 wcreds_max;	/* Window credits */
+	enum vas_cop_type cop;
+	struct vas_user_win_ref task_ref;
+	char *dbgname;
+	struct dentry *dbgdir;
+	union {
+		/* powerNV specific data */
+		struct {
+			void *vinst;	/* points to VAS instance */
+			bool tx_win;	/* True if send window */
+			bool nx_win;	/* True if NX window */
+			bool user_win;	/* True if user space window */
+			void *hvwc_map;	/* HV window context */
+			void *uwc_map;	/* OS/User window context */
+
+			/* Fields applicable only to send windows */
+			void *paste_kaddr;
+			char *paste_addr_name;
+			struct vas_window *rxwin;
+
+			atomic_t num_txwins;	/* Only for receive windows */
+		} pnv;
+		struct {
+			u64 win_addr;	/* Physical paste address */
+			u8 win_type;	/* QoS or Default window */
+			u8 status;
+			u32 complete_irq;	/* Completion interrupt */
+			u32 fault_irq;	/* Fault interrupt */
+			u64 domain[6];	/* Associativity domain Ids */
+					/* this window is allocated */
+			u64 util;
+
+			/* List of windows opened which is used for LPM */
+			struct list_head win_list;
+			u64 flags;
+			char *name;
+			int fault_virq;
+		} lpar;
+	};
+};
+
 /*
  * User space window operations used for powernv and powerVM
  */
diff --git a/arch/powerpc/platforms/powernv/vas-debug.c b/arch/powerpc/platforms/powernv/vas-debug.c
index 41fa90d2f4ab..80f735449ab8 100644
--- a/arch/powerpc/platforms/powernv/vas-debug.c
+++ b/arch/powerpc/platforms/powernv/vas-debug.c
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <asm/vas.h>
 #include "vas.h"
 
 static struct dentry *vas_debugfs;
@@ -33,11 +34,11 @@ static int info_show(struct seq_file *s, void *private)
 	mutex_lock(&vas_mutex);
 
 	/* ensure window is not unmapped */
-	if (!window->hvwc_map)
+	if (!window->pnv.hvwc_map)
 		goto unlock;
 
 	seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop),
-					window->tx_win ? "Send" : "Receive");
+				window->pnv.tx_win ? "Send" : "Receive");
 	seq_printf(s, "Pid : %d\n", vas_window_pid(window));
 
 unlock:
@@ -60,7 +61,7 @@ static int hvwc_show(struct seq_file *s, void *private)
 	mutex_lock(&vas_mutex);
 
 	/* ensure window is not unmapped */
-	if (!window->hvwc_map)
+	if (!window->pnv.hvwc_map)
 		goto unlock;
 
 	print_reg(s, window, VREG(LPID));
@@ -115,9 +116,10 @@ void vas_window_free_dbgdir(struct vas_window *window)
 
 void vas_window_init_dbgdir(struct vas_window *window)
 {
+	struct vas_instance *vinst = window->pnv.vinst;
 	struct dentry *d;
 
-	if (!window->vinst->dbgdir)
+	if (!vinst->dbgdir)
 		return;
 
 	window->dbgname = kzalloc(16, GFP_KERNEL);
@@ -126,7 +128,7 @@ void vas_window_init_dbgdir(struct vas_window *window)
 
 	snprintf(window->dbgname, 16, "w%d", window->winid);
 
-	d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir);
+	d = debugfs_create_dir(window->dbgname, vinst->dbgdir);
 	window->dbgdir = d;
 
 	debugfs_create_file("info", 0444, d, window, &info_fops);
diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index 2729ac541fb3..faaf5b110645 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -152,10 +152,10 @@ irqreturn_t vas_fault_thread_fn(int irq, void *data)
 			/*
 			 * NX sees faults only with user space windows.
 			 */
-			if (window->user_win)
+			if (window->pnv.user_win)
 				vas_update_csb(crb, &window->task_ref);
 			else
-				WARN_ON_ONCE(!window->user_win);
+				WARN_ON_ONCE(!window->pnv.user_win);
 
 			/*
 			 * Return credit for send window after processing
diff --git a/arch/powerpc/platforms/powernv/vas-trace.h b/arch/powerpc/platforms/powernv/vas-trace.h
index a449b9f0c12e..843aae37c07a 100644
--- a/arch/powerpc/platforms/powernv/vas-trace.h
+++ b/arch/powerpc/platforms/powernv/vas-trace.h
@@ -95,9 +95,11 @@ TRACE_EVENT(	vas_paste_crb,
 
 		TP_fast_assign(
 			__entry->pid = tsk->pid;
-			__entry->vasid = win->vinst->vas_id;
+			__entry->vasid =
+				((struct vas_instance *)win->pnv.vinst)->vas_id;
 			__entry->winid = win->winid;
-			__entry->paste_kaddr = (unsigned long)win->paste_kaddr
+			__entry->paste_kaddr =
+				(unsigned long)win->pnv.paste_kaddr;
 		),
 
 		TP_printk("pid=%d, vasid=%d, winid=%d, paste_kaddr=0x%016lx\n",
diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
index ffd619e5a218..6ce8ee4b3371 100644
--- a/arch/powerpc/platforms/powernv/vas-window.c
+++ b/arch/powerpc/platforms/powernv/vas-window.c
@@ -31,9 +31,10 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr, int *len)
 {
 	int winid;
 	u64 base, shift;
+	struct vas_instance *vinst = window->pnv.vinst;
 
-	base = window->vinst->paste_base_addr;
-	shift = window->vinst->paste_win_id_shift;
+	base = vinst->paste_base_addr;
+	shift = vinst->paste_win_id_shift;
 	winid = window->winid;
 
 	*addr  = base + (winid << shift);
@@ -46,9 +47,10 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr, int *len)
 static inline void get_hvwc_mmio_bar(struct vas_window *window,
 			u64 *start, int *len)
 {
+	struct vas_instance *vinst = window->pnv.vinst;
 	u64 pbaddr;
 
-	pbaddr = window->vinst->hvwc_bar_start;
+	pbaddr = vinst->hvwc_bar_start;
 	*start = pbaddr + window->winid * VAS_HVWC_SIZE;
 	*len = VAS_HVWC_SIZE;
 }
@@ -56,9 +58,10 @@ static inline void get_hvwc_mmio_bar(struct vas_window *window,
 static inline void get_uwc_mmio_bar(struct vas_window *window,
 			u64 *start, int *len)
 {
+	struct vas_instance *vinst = window->pnv.vinst;
 	u64 pbaddr;
 
-	pbaddr = window->vinst->uwc_bar_start;
+	pbaddr = vinst->uwc_bar_start;
 	*start = pbaddr + window->winid * VAS_UWC_SIZE;
 	*len = VAS_UWC_SIZE;
 }
@@ -74,13 +77,14 @@ static void *map_paste_region(struct vas_window *txwin)
 	void *map;
 	char *name;
 	u64 start;
+	struct vas_instance *vinst = txwin->pnv.vinst;
 
-	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", txwin->vinst->vas_id,
+	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", vinst->vas_id,
 				txwin->winid);
 	if (!name)
 		goto free_name;
 
-	txwin->paste_addr_name = name;
+	txwin->pnv.paste_addr_name = name;
 	vas_win_paste_addr(txwin, &start, &len);
 
 	if (!request_mem_region(start, len, name)) {
@@ -138,12 +142,12 @@ static void unmap_paste_region(struct vas_window *window)
 	int len;
 	u64 busaddr_start;
 
-	if (window->paste_kaddr) {
+	if (window->pnv.paste_kaddr) {
 		vas_win_paste_addr(window, &busaddr_start, &len);
-		unmap_region(window->paste_kaddr, busaddr_start, len);
-		window->paste_kaddr = NULL;
-		kfree(window->paste_addr_name);
-		window->paste_addr_name = NULL;
+		unmap_region(window->pnv.paste_kaddr, busaddr_start, len);
+		window->pnv.paste_kaddr = NULL;
+		kfree(window->pnv.paste_addr_name);
+		window->pnv.paste_addr_name = NULL;
 	}
 }
 
@@ -163,11 +167,11 @@ static void unmap_winctx_mmio_bars(struct vas_window *window)
 
 	mutex_lock(&vas_mutex);
 
-	hvwc_map = window->hvwc_map;
-	window->hvwc_map = NULL;
+	hvwc_map = window->pnv.hvwc_map;
+	window->pnv.hvwc_map = NULL;
 
-	uwc_map = window->uwc_map;
-	window->uwc_map = NULL;
+	uwc_map = window->pnv.uwc_map;
+	window->pnv.uwc_map = NULL;
 
 	mutex_unlock(&vas_mutex);
 
@@ -193,12 +197,12 @@ static int map_winctx_mmio_bars(struct vas_window *window)
 	u64 start;
 
 	get_hvwc_mmio_bar(window, &start, &len);
-	window->hvwc_map = map_mmio_region("HVWCM_Window", start, len);
+	window->pnv.hvwc_map = map_mmio_region("HVWCM_Window", start, len);
 
 	get_uwc_mmio_bar(window, &start, &len);
-	window->uwc_map = map_mmio_region("UWCM_Window", start, len);
+	window->pnv.uwc_map = map_mmio_region("UWCM_Window", start, len);
 
-	if (!window->hvwc_map || !window->uwc_map) {
+	if (!window->pnv.hvwc_map || !window->pnv.uwc_map) {
 		unmap_winctx_mmio_bars(window);
 		return -1;
 	}
@@ -523,7 +527,7 @@ static int vas_assign_window_id(struct ida *ida)
 static void vas_window_free(struct vas_window *window)
 {
 	int winid = window->winid;
-	struct vas_instance *vinst = window->vinst;
+	struct vas_instance *vinst = window->pnv.vinst;
 
 	unmap_winctx_mmio_bars(window);
 
@@ -547,7 +551,7 @@ static struct vas_window *vas_window_alloc(struct vas_instance *vinst)
 	if (!window)
 		goto out_free;
 
-	window->vinst = vinst;
+	window->pnv.vinst = vinst;
 	window->winid = winid;
 
 	if (map_winctx_mmio_bars(window))
@@ -566,9 +570,9 @@ static struct vas_window *vas_window_alloc(struct vas_instance *vinst)
 static void put_rx_win(struct vas_window *rxwin)
 {
 	/* Better not be a send window! */
-	WARN_ON_ONCE(rxwin->tx_win);
+	WARN_ON_ONCE(rxwin->pnv.tx_win);
 
-	atomic_dec(&rxwin->num_txwins);
+	atomic_dec(&rxwin->pnv.num_txwins);
 }
 
 /*
@@ -591,7 +595,7 @@ static struct vas_window *get_user_rxwin(struct vas_instance *vinst, u32 pswid)
 
 	rxwin = vinst->windows[winid];
 
-	if (!rxwin || rxwin->tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
+	if (!rxwin || rxwin->pnv.tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
 		return ERR_PTR(-EINVAL);
 
 	return rxwin;
@@ -616,7 +620,7 @@ static struct vas_window *get_vinst_rxwin(struct vas_instance *vinst,
 		rxwin = vinst->rxwin[cop] ?: ERR_PTR(-EINVAL);
 
 	if (!IS_ERR(rxwin))
-		atomic_inc(&rxwin->num_txwins);
+		atomic_inc(&rxwin->pnv.num_txwins);
 
 	mutex_unlock(&vinst->mutex);
 
@@ -649,7 +653,7 @@ static void set_vinst_win(struct vas_instance *vinst,
 	 * There should only be one receive window for a coprocessor type
 	 * unless its a user (FTW) window.
 	 */
-	if (!window->user_win && !window->tx_win) {
+	if (!window->pnv.user_win && !window->pnv.tx_win) {
 		WARN_ON_ONCE(vinst->rxwin[window->cop]);
 		vinst->rxwin[window->cop] = window;
 	}
@@ -667,11 +671,11 @@ static void set_vinst_win(struct vas_instance *vinst,
 static void clear_vinst_win(struct vas_window *window)
 {
 	int id = window->winid;
-	struct vas_instance *vinst = window->vinst;
+	struct vas_instance *vinst = window->pnv.vinst;
 
 	mutex_lock(&vinst->mutex);
 
-	if (!window->user_win && !window->tx_win) {
+	if (!window->pnv.user_win && !window->pnv.tx_win) {
 		WARN_ON_ONCE(!vinst->rxwin[window->cop]);
 		vinst->rxwin[window->cop] = NULL;
 	}
@@ -686,6 +690,8 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin,
 			struct vas_rx_win_attr *rxattr,
 			struct vas_winctx *winctx)
 {
+	struct vas_instance *vinst;
+
 	/*
 	 * We first zero (memset()) all fields and only set non-zero fields.
 	 * Following fields are 0/false but maybe deserve a comment:
@@ -750,8 +756,9 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin,
 
 	winctx->min_scope = VAS_SCOPE_LOCAL;
 	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
-	if (rxwin->vinst->virq)
-		winctx->irq_port = rxwin->vinst->irq_port;
+	vinst = rxwin->pnv.vinst;
+	if (vinst->virq)
+		winctx->irq_port = vinst->irq_port;
 }
 
 static bool rx_win_args_valid(enum vas_cop_type cop,
@@ -874,9 +881,9 @@ struct vas_window *vas_rx_win_open(int vasid, enum vas_cop_type cop,
 		return rxwin;
 	}
 
-	rxwin->tx_win = false;
-	rxwin->nx_win = rxattr->nx_win;
-	rxwin->user_win = rxattr->user_win;
+	rxwin->pnv.tx_win = false;
+	rxwin->pnv.nx_win = rxattr->nx_win;
+	rxwin->pnv.user_win = rxattr->user_win;
 	rxwin->cop = cop;
 	rxwin->wcreds_max = rxattr->wcreds_max;
 
@@ -910,6 +917,8 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
 			struct vas_tx_win_attr *txattr,
 			struct vas_winctx *winctx)
 {
+	struct vas_instance *vinst = txwin->pnv.vinst;
+
 	/*
 	 * We first zero all fields and only set non-zero ones. Following
 	 * are some fields set to 0/false for the stated reason:
@@ -930,7 +939,7 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
 	winctx->wcreds_max = txwin->wcreds_max;
 
 	winctx->user_win = txattr->user_win;
-	winctx->nx_win = txwin->rxwin->nx_win;
+	winctx->nx_win = txwin->pnv.rxwin->pnv.nx_win;
 	winctx->pin_win = txattr->pin_win;
 	winctx->rej_no_credit = txattr->rej_no_credit;
 	winctx->rsvd_txbuf_enable = txattr->rsvd_txbuf_enable;
@@ -947,23 +956,23 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
 
 	winctx->lpid = txattr->lpid;
 	winctx->pidr = txattr->pidr;
-	winctx->rx_win_id = txwin->rxwin->winid;
+	winctx->rx_win_id = txwin->pnv.rxwin->winid;
 	/*
 	 * IRQ and fault window setup is successful. Set fault window
 	 * for the send window so that ready to handle faults.
 	 */
-	if (txwin->vinst->virq)
-		winctx->fault_win_id = txwin->vinst->fault_win->winid;
+	if (vinst->virq)
+		winctx->fault_win_id = vinst->fault_win->winid;
 
 	winctx->dma_type = VAS_DMA_TYPE_INJECT;
 	winctx->tc_mode = txattr->tc_mode;
 	winctx->min_scope = VAS_SCOPE_LOCAL;
 	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
-	if (txwin->vinst->virq)
-		winctx->irq_port = txwin->vinst->irq_port;
+	if (vinst->virq)
+		winctx->irq_port = vinst->irq_port;
 
 	winctx->pswid = txattr->pswid ? txattr->pswid :
-			encode_pswid(txwin->vinst->vas_id, txwin->winid);
+			encode_pswid(vinst->vas_id, txwin->winid);
 }
 
 static bool tx_win_args_valid(enum vas_cop_type cop,
@@ -1031,10 +1040,10 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
 	}
 
 	txwin->cop = cop;
-	txwin->tx_win = 1;
-	txwin->rxwin = rxwin;
-	txwin->nx_win = txwin->rxwin->nx_win;
-	txwin->user_win = attr->user_win;
+	txwin->pnv.tx_win = 1;
+	txwin->pnv.rxwin = rxwin;
+	txwin->pnv.nx_win = txwin->pnv.rxwin->pnv.nx_win;
+	txwin->pnv.user_win = attr->user_win;
 	txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT;
 
 	init_winctx_for_txwin(txwin, attr, &winctx);
@@ -1049,10 +1058,10 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
 	 * NOTE: If kernel ever resubmits a user CRB after handling a page
 	 *	 fault, we will need to map this into kernel as well.
 	 */
-	if (!txwin->user_win) {
-		txwin->paste_kaddr = map_paste_region(txwin);
-		if (IS_ERR(txwin->paste_kaddr)) {
-			rc = PTR_ERR(txwin->paste_kaddr);
+	if (!txwin->pnv.user_win) {
+		txwin->pnv.paste_kaddr = map_paste_region(txwin);
+		if (IS_ERR(txwin->pnv.paste_kaddr)) {
+			rc = PTR_ERR(txwin->pnv.paste_kaddr);
 			goto free_window;
 		}
 	} else {
@@ -1104,9 +1113,9 @@ int vas_paste_crb(struct vas_window *txwin, int offset, bool re)
 	 * report-enable flag is set for NX windows. Ensure software
 	 * complies too.
 	 */
-	WARN_ON_ONCE(txwin->nx_win && !re);
+	WARN_ON_ONCE(txwin->pnv.nx_win && !re);
 
-	addr = txwin->paste_kaddr;
+	addr = txwin->pnv.paste_kaddr;
 	if (re) {
 		/*
 		 * Set the REPORT_ENABLE bit (equivalent to writing
@@ -1153,7 +1162,7 @@ static void poll_window_credits(struct vas_window *window)
 	int count = 0;
 
 	val = read_hvwc_reg(window, VREG(WINCTL));
-	if (window->tx_win)
+	if (window->pnv.tx_win)
 		mode = GET_FIELD(VAS_WINCTL_TX_WCRED_MODE, val);
 	else
 		mode = GET_FIELD(VAS_WINCTL_RX_WCRED_MODE, val);
@@ -1161,7 +1170,7 @@ static void poll_window_credits(struct vas_window *window)
 	if (!mode)
 		return;
 retry:
-	if (window->tx_win) {
+	if (window->pnv.tx_win) {
 		val = read_hvwc_reg(window, VREG(TX_WCRED));
 		creds = GET_FIELD(VAS_TX_WCRED, val);
 	} else {
@@ -1277,7 +1286,7 @@ int vas_win_close(struct vas_window *window)
 	if (!window)
 		return 0;
 
-	if (!window->tx_win && atomic_read(&window->num_txwins) != 0) {
+	if (!window->pnv.tx_win && atomic_read(&window->pnv.num_txwins) != 0) {
 		pr_devel("Attempting to close an active Rx window!\n");
 		WARN_ON_ONCE(1);
 		return -EBUSY;
@@ -1296,11 +1305,11 @@ int vas_win_close(struct vas_window *window)
 	poll_window_castout(window);
 
 	/* if send window, drop reference to matching receive window */
-	if (window->tx_win) {
-		if (window->user_win)
+	if (window->pnv.tx_win) {
+		if (window->pnv.user_win)
 			vas_drop_reference_pid_mm(&window->task_ref);
 
-		put_rx_win(window->rxwin);
+		put_rx_win(window->pnv.rxwin);
 	}
 
 	vas_window_free(window);
@@ -1384,12 +1393,12 @@ struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
 	 * since their CRBs are ignored (not queued on FIFO or processed
 	 * by NX).
 	 */
-	if (!window->tx_win || !window->user_win || !window->nx_win ||
-			window->cop == VAS_COP_TYPE_FAULT ||
-			window->cop == VAS_COP_TYPE_FTW) {
+	if (!window->pnv.tx_win || !window->pnv.user_win ||
+		!window->pnv.nx_win || window->cop == VAS_COP_TYPE_FAULT ||
+		window->cop == VAS_COP_TYPE_FTW) {
 		pr_err("PSWID decode: id %d, tx %d, user %d, nx %d, cop %d\n",
-			winid, window->tx_win, window->user_win,
-			window->nx_win, window->cop);
+			winid, window->pnv.tx_win, window->pnv.user_win,
+			window->pnv.nx_win, window->cop);
 		WARN_ON(1);
 	}
 
diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
index f354dd5c51bd..f2d9daff3d82 100644
--- a/arch/powerpc/platforms/powernv/vas.h
+++ b/arch/powerpc/platforms/powernv/vas.h
@@ -345,34 +345,6 @@ struct vas_instance {
 	struct dentry *dbgdir;
 };
 
-/*
- * In-kernel state a VAS window. One per window.
- */
-struct vas_window {
-	/* Fields common to send and receive windows */
-	struct vas_instance *vinst;
-	int winid;
-	bool tx_win;		/* True if send window */
-	bool nx_win;		/* True if NX window */
-	bool user_win;		/* True if user space window */
-	void *hvwc_map;		/* HV window context */
-	void *uwc_map;		/* OS/User window context */
-	int wcreds_max;		/* Window credits */
-
-	struct vas_user_win_ref task_ref;
-	char *dbgname;
-	struct dentry *dbgdir;
-
-	/* Fields applicable only to send windows */
-	void *paste_kaddr;
-	char *paste_addr_name;
-	struct vas_window *rxwin;
-
-	/* Feilds applicable only to receive windows */
-	enum vas_cop_type cop;
-	atomic_t num_txwins;
-};
-
 /*
  * Container for the hardware state of a window. One per-window.
  *
@@ -449,8 +421,8 @@ static inline void vas_log_write(struct vas_window *win, char *name,
 {
 	if (val)
 		pr_debug("%swin #%d: %s reg %p, val 0x%016llx\n",
-				win->tx_win ? "Tx" : "Rx", win->winid, name,
-				regptr, val);
+				win->pnv.tx_win ? "Tx" : "Rx", win->winid,
+				name, regptr, val);
 }
 
 static inline void write_uwc_reg(struct vas_window *win, char *name,
@@ -458,7 +430,7 @@ static inline void write_uwc_reg(struct vas_window *win, char *name,
 {
 	void *regptr;
 
-	regptr = win->uwc_map + reg;
+	regptr = win->pnv.uwc_map + reg;
 	vas_log_write(win, name, regptr, val);
 
 	out_be64(regptr, val);
@@ -469,7 +441,7 @@ static inline void write_hvwc_reg(struct vas_window *win, char *name,
 {
 	void *regptr;
 
-	regptr = win->hvwc_map + reg;
+	regptr = win->pnv.hvwc_map + reg;
 	vas_log_write(win, name, regptr, val);
 
 	out_be64(regptr, val);
@@ -478,7 +450,7 @@ static inline void write_hvwc_reg(struct vas_window *win, char *name,
 static inline u64 read_hvwc_reg(struct vas_window *win,
 			char *name __maybe_unused, s32 reg)
 {
-	return in_be64(win->hvwc_map+reg);
+	return in_be64(win->pnv.hvwc_map + reg);
 }
 
 /*
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
@ 2021-05-21  9:33   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:33 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


Same vas_window struct is used on powerNV and pseries. So this patch
changes in struct vas_window to support both platforms and also the
corresponding modifications in powerNV vas code.

On powerNV, vas_window is used for both TX and RX windows, whereas
only for TX windows on powerVM. So some elements are specific to
these platforms.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h              |  50 +++++++-
 arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
 arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
 arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
 arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++---------
 arch/powerpc/platforms/powernv/vas.h        |  38 +-----
 6 files changed, 135 insertions(+), 104 deletions(-)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 2c1040f399d9..49bfb5be896d 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -10,8 +10,6 @@
 #include <asm/icswx.h>
 #include <uapi/asm/vas-api.h>
 
-struct vas_window;
-
 /*
  * Min and max FIFO sizes are based on Version 1.05 Section 3.1.4.25
  * (Local FIFO Size Register) of the VAS workbook.
@@ -63,6 +61,54 @@ struct vas_user_win_ref {
 	struct mm_struct *mm;	/* Linux process mm_struct */
 };
 
+/*
+ * In-kernel state a VAS window. One per window.
+ * powerVM: Used only for Tx windows.
+ * powerNV: Used for both Tx and Rx windows.
+ */
+struct vas_window {
+	u32 winid;
+	u32 wcreds_max;	/* Window credits */
+	enum vas_cop_type cop;
+	struct vas_user_win_ref task_ref;
+	char *dbgname;
+	struct dentry *dbgdir;
+	union {
+		/* powerNV specific data */
+		struct {
+			void *vinst;	/* points to VAS instance */
+			bool tx_win;	/* True if send window */
+			bool nx_win;	/* True if NX window */
+			bool user_win;	/* True if user space window */
+			void *hvwc_map;	/* HV window context */
+			void *uwc_map;	/* OS/User window context */
+
+			/* Fields applicable only to send windows */
+			void *paste_kaddr;
+			char *paste_addr_name;
+			struct vas_window *rxwin;
+
+			atomic_t num_txwins;	/* Only for receive windows */
+		} pnv;
+		struct {
+			u64 win_addr;	/* Physical paste address */
+			u8 win_type;	/* QoS or Default window */
+			u8 status;
+			u32 complete_irq;	/* Completion interrupt */
+			u32 fault_irq;	/* Fault interrupt */
+			u64 domain[6];	/* Associativity domain Ids */
+					/* this window is allocated */
+			u64 util;
+
+			/* List of windows opened which is used for LPM */
+			struct list_head win_list;
+			u64 flags;
+			char *name;
+			int fault_virq;
+		} lpar;
+	};
+};
+
 /*
  * User space window operations used for powernv and powerVM
  */
diff --git a/arch/powerpc/platforms/powernv/vas-debug.c b/arch/powerpc/platforms/powernv/vas-debug.c
index 41fa90d2f4ab..80f735449ab8 100644
--- a/arch/powerpc/platforms/powernv/vas-debug.c
+++ b/arch/powerpc/platforms/powernv/vas-debug.c
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <asm/vas.h>
 #include "vas.h"
 
 static struct dentry *vas_debugfs;
@@ -33,11 +34,11 @@ static int info_show(struct seq_file *s, void *private)
 	mutex_lock(&vas_mutex);
 
 	/* ensure window is not unmapped */
-	if (!window->hvwc_map)
+	if (!window->pnv.hvwc_map)
 		goto unlock;
 
 	seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop),
-					window->tx_win ? "Send" : "Receive");
+				window->pnv.tx_win ? "Send" : "Receive");
 	seq_printf(s, "Pid : %d\n", vas_window_pid(window));
 
 unlock:
@@ -60,7 +61,7 @@ static int hvwc_show(struct seq_file *s, void *private)
 	mutex_lock(&vas_mutex);
 
 	/* ensure window is not unmapped */
-	if (!window->hvwc_map)
+	if (!window->pnv.hvwc_map)
 		goto unlock;
 
 	print_reg(s, window, VREG(LPID));
@@ -115,9 +116,10 @@ void vas_window_free_dbgdir(struct vas_window *window)
 
 void vas_window_init_dbgdir(struct vas_window *window)
 {
+	struct vas_instance *vinst = window->pnv.vinst;
 	struct dentry *d;
 
-	if (!window->vinst->dbgdir)
+	if (!vinst->dbgdir)
 		return;
 
 	window->dbgname = kzalloc(16, GFP_KERNEL);
@@ -126,7 +128,7 @@ void vas_window_init_dbgdir(struct vas_window *window)
 
 	snprintf(window->dbgname, 16, "w%d", window->winid);
 
-	d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir);
+	d = debugfs_create_dir(window->dbgname, vinst->dbgdir);
 	window->dbgdir = d;
 
 	debugfs_create_file("info", 0444, d, window, &info_fops);
diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index 2729ac541fb3..faaf5b110645 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -152,10 +152,10 @@ irqreturn_t vas_fault_thread_fn(int irq, void *data)
 			/*
 			 * NX sees faults only with user space windows.
 			 */
-			if (window->user_win)
+			if (window->pnv.user_win)
 				vas_update_csb(crb, &window->task_ref);
 			else
-				WARN_ON_ONCE(!window->user_win);
+				WARN_ON_ONCE(!window->pnv.user_win);
 
 			/*
 			 * Return credit for send window after processing
diff --git a/arch/powerpc/platforms/powernv/vas-trace.h b/arch/powerpc/platforms/powernv/vas-trace.h
index a449b9f0c12e..843aae37c07a 100644
--- a/arch/powerpc/platforms/powernv/vas-trace.h
+++ b/arch/powerpc/platforms/powernv/vas-trace.h
@@ -95,9 +95,11 @@ TRACE_EVENT(	vas_paste_crb,
 
 		TP_fast_assign(
 			__entry->pid = tsk->pid;
-			__entry->vasid = win->vinst->vas_id;
+			__entry->vasid =
+				((struct vas_instance *)win->pnv.vinst)->vas_id;
 			__entry->winid = win->winid;
-			__entry->paste_kaddr = (unsigned long)win->paste_kaddr
+			__entry->paste_kaddr =
+				(unsigned long)win->pnv.paste_kaddr;
 		),
 
 		TP_printk("pid=%d, vasid=%d, winid=%d, paste_kaddr=0x%016lx\n",
diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
index ffd619e5a218..6ce8ee4b3371 100644
--- a/arch/powerpc/platforms/powernv/vas-window.c
+++ b/arch/powerpc/platforms/powernv/vas-window.c
@@ -31,9 +31,10 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr, int *len)
 {
 	int winid;
 	u64 base, shift;
+	struct vas_instance *vinst = window->pnv.vinst;
 
-	base = window->vinst->paste_base_addr;
-	shift = window->vinst->paste_win_id_shift;
+	base = vinst->paste_base_addr;
+	shift = vinst->paste_win_id_shift;
 	winid = window->winid;
 
 	*addr  = base + (winid << shift);
@@ -46,9 +47,10 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr, int *len)
 static inline void get_hvwc_mmio_bar(struct vas_window *window,
 			u64 *start, int *len)
 {
+	struct vas_instance *vinst = window->pnv.vinst;
 	u64 pbaddr;
 
-	pbaddr = window->vinst->hvwc_bar_start;
+	pbaddr = vinst->hvwc_bar_start;
 	*start = pbaddr + window->winid * VAS_HVWC_SIZE;
 	*len = VAS_HVWC_SIZE;
 }
@@ -56,9 +58,10 @@ static inline void get_hvwc_mmio_bar(struct vas_window *window,
 static inline void get_uwc_mmio_bar(struct vas_window *window,
 			u64 *start, int *len)
 {
+	struct vas_instance *vinst = window->pnv.vinst;
 	u64 pbaddr;
 
-	pbaddr = window->vinst->uwc_bar_start;
+	pbaddr = vinst->uwc_bar_start;
 	*start = pbaddr + window->winid * VAS_UWC_SIZE;
 	*len = VAS_UWC_SIZE;
 }
@@ -74,13 +77,14 @@ static void *map_paste_region(struct vas_window *txwin)
 	void *map;
 	char *name;
 	u64 start;
+	struct vas_instance *vinst = txwin->pnv.vinst;
 
-	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", txwin->vinst->vas_id,
+	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", vinst->vas_id,
 				txwin->winid);
 	if (!name)
 		goto free_name;
 
-	txwin->paste_addr_name = name;
+	txwin->pnv.paste_addr_name = name;
 	vas_win_paste_addr(txwin, &start, &len);
 
 	if (!request_mem_region(start, len, name)) {
@@ -138,12 +142,12 @@ static void unmap_paste_region(struct vas_window *window)
 	int len;
 	u64 busaddr_start;
 
-	if (window->paste_kaddr) {
+	if (window->pnv.paste_kaddr) {
 		vas_win_paste_addr(window, &busaddr_start, &len);
-		unmap_region(window->paste_kaddr, busaddr_start, len);
-		window->paste_kaddr = NULL;
-		kfree(window->paste_addr_name);
-		window->paste_addr_name = NULL;
+		unmap_region(window->pnv.paste_kaddr, busaddr_start, len);
+		window->pnv.paste_kaddr = NULL;
+		kfree(window->pnv.paste_addr_name);
+		window->pnv.paste_addr_name = NULL;
 	}
 }
 
@@ -163,11 +167,11 @@ static void unmap_winctx_mmio_bars(struct vas_window *window)
 
 	mutex_lock(&vas_mutex);
 
-	hvwc_map = window->hvwc_map;
-	window->hvwc_map = NULL;
+	hvwc_map = window->pnv.hvwc_map;
+	window->pnv.hvwc_map = NULL;
 
-	uwc_map = window->uwc_map;
-	window->uwc_map = NULL;
+	uwc_map = window->pnv.uwc_map;
+	window->pnv.uwc_map = NULL;
 
 	mutex_unlock(&vas_mutex);
 
@@ -193,12 +197,12 @@ static int map_winctx_mmio_bars(struct vas_window *window)
 	u64 start;
 
 	get_hvwc_mmio_bar(window, &start, &len);
-	window->hvwc_map = map_mmio_region("HVWCM_Window", start, len);
+	window->pnv.hvwc_map = map_mmio_region("HVWCM_Window", start, len);
 
 	get_uwc_mmio_bar(window, &start, &len);
-	window->uwc_map = map_mmio_region("UWCM_Window", start, len);
+	window->pnv.uwc_map = map_mmio_region("UWCM_Window", start, len);
 
-	if (!window->hvwc_map || !window->uwc_map) {
+	if (!window->pnv.hvwc_map || !window->pnv.uwc_map) {
 		unmap_winctx_mmio_bars(window);
 		return -1;
 	}
@@ -523,7 +527,7 @@ static int vas_assign_window_id(struct ida *ida)
 static void vas_window_free(struct vas_window *window)
 {
 	int winid = window->winid;
-	struct vas_instance *vinst = window->vinst;
+	struct vas_instance *vinst = window->pnv.vinst;
 
 	unmap_winctx_mmio_bars(window);
 
@@ -547,7 +551,7 @@ static struct vas_window *vas_window_alloc(struct vas_instance *vinst)
 	if (!window)
 		goto out_free;
 
-	window->vinst = vinst;
+	window->pnv.vinst = vinst;
 	window->winid = winid;
 
 	if (map_winctx_mmio_bars(window))
@@ -566,9 +570,9 @@ static struct vas_window *vas_window_alloc(struct vas_instance *vinst)
 static void put_rx_win(struct vas_window *rxwin)
 {
 	/* Better not be a send window! */
-	WARN_ON_ONCE(rxwin->tx_win);
+	WARN_ON_ONCE(rxwin->pnv.tx_win);
 
-	atomic_dec(&rxwin->num_txwins);
+	atomic_dec(&rxwin->pnv.num_txwins);
 }
 
 /*
@@ -591,7 +595,7 @@ static struct vas_window *get_user_rxwin(struct vas_instance *vinst, u32 pswid)
 
 	rxwin = vinst->windows[winid];
 
-	if (!rxwin || rxwin->tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
+	if (!rxwin || rxwin->pnv.tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
 		return ERR_PTR(-EINVAL);
 
 	return rxwin;
@@ -616,7 +620,7 @@ static struct vas_window *get_vinst_rxwin(struct vas_instance *vinst,
 		rxwin = vinst->rxwin[cop] ?: ERR_PTR(-EINVAL);
 
 	if (!IS_ERR(rxwin))
-		atomic_inc(&rxwin->num_txwins);
+		atomic_inc(&rxwin->pnv.num_txwins);
 
 	mutex_unlock(&vinst->mutex);
 
@@ -649,7 +653,7 @@ static void set_vinst_win(struct vas_instance *vinst,
 	 * There should only be one receive window for a coprocessor type
 	 * unless its a user (FTW) window.
 	 */
-	if (!window->user_win && !window->tx_win) {
+	if (!window->pnv.user_win && !window->pnv.tx_win) {
 		WARN_ON_ONCE(vinst->rxwin[window->cop]);
 		vinst->rxwin[window->cop] = window;
 	}
@@ -667,11 +671,11 @@ static void set_vinst_win(struct vas_instance *vinst,
 static void clear_vinst_win(struct vas_window *window)
 {
 	int id = window->winid;
-	struct vas_instance *vinst = window->vinst;
+	struct vas_instance *vinst = window->pnv.vinst;
 
 	mutex_lock(&vinst->mutex);
 
-	if (!window->user_win && !window->tx_win) {
+	if (!window->pnv.user_win && !window->pnv.tx_win) {
 		WARN_ON_ONCE(!vinst->rxwin[window->cop]);
 		vinst->rxwin[window->cop] = NULL;
 	}
@@ -686,6 +690,8 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin,
 			struct vas_rx_win_attr *rxattr,
 			struct vas_winctx *winctx)
 {
+	struct vas_instance *vinst;
+
 	/*
 	 * We first zero (memset()) all fields and only set non-zero fields.
 	 * Following fields are 0/false but maybe deserve a comment:
@@ -750,8 +756,9 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin,
 
 	winctx->min_scope = VAS_SCOPE_LOCAL;
 	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
-	if (rxwin->vinst->virq)
-		winctx->irq_port = rxwin->vinst->irq_port;
+	vinst = rxwin->pnv.vinst;
+	if (vinst->virq)
+		winctx->irq_port = vinst->irq_port;
 }
 
 static bool rx_win_args_valid(enum vas_cop_type cop,
@@ -874,9 +881,9 @@ struct vas_window *vas_rx_win_open(int vasid, enum vas_cop_type cop,
 		return rxwin;
 	}
 
-	rxwin->tx_win = false;
-	rxwin->nx_win = rxattr->nx_win;
-	rxwin->user_win = rxattr->user_win;
+	rxwin->pnv.tx_win = false;
+	rxwin->pnv.nx_win = rxattr->nx_win;
+	rxwin->pnv.user_win = rxattr->user_win;
 	rxwin->cop = cop;
 	rxwin->wcreds_max = rxattr->wcreds_max;
 
@@ -910,6 +917,8 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
 			struct vas_tx_win_attr *txattr,
 			struct vas_winctx *winctx)
 {
+	struct vas_instance *vinst = txwin->pnv.vinst;
+
 	/*
 	 * We first zero all fields and only set non-zero ones. Following
 	 * are some fields set to 0/false for the stated reason:
@@ -930,7 +939,7 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
 	winctx->wcreds_max = txwin->wcreds_max;
 
 	winctx->user_win = txattr->user_win;
-	winctx->nx_win = txwin->rxwin->nx_win;
+	winctx->nx_win = txwin->pnv.rxwin->pnv.nx_win;
 	winctx->pin_win = txattr->pin_win;
 	winctx->rej_no_credit = txattr->rej_no_credit;
 	winctx->rsvd_txbuf_enable = txattr->rsvd_txbuf_enable;
@@ -947,23 +956,23 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
 
 	winctx->lpid = txattr->lpid;
 	winctx->pidr = txattr->pidr;
-	winctx->rx_win_id = txwin->rxwin->winid;
+	winctx->rx_win_id = txwin->pnv.rxwin->winid;
 	/*
 	 * IRQ and fault window setup is successful. Set fault window
 	 * for the send window so that ready to handle faults.
 	 */
-	if (txwin->vinst->virq)
-		winctx->fault_win_id = txwin->vinst->fault_win->winid;
+	if (vinst->virq)
+		winctx->fault_win_id = vinst->fault_win->winid;
 
 	winctx->dma_type = VAS_DMA_TYPE_INJECT;
 	winctx->tc_mode = txattr->tc_mode;
 	winctx->min_scope = VAS_SCOPE_LOCAL;
 	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
-	if (txwin->vinst->virq)
-		winctx->irq_port = txwin->vinst->irq_port;
+	if (vinst->virq)
+		winctx->irq_port = vinst->irq_port;
 
 	winctx->pswid = txattr->pswid ? txattr->pswid :
-			encode_pswid(txwin->vinst->vas_id, txwin->winid);
+			encode_pswid(vinst->vas_id, txwin->winid);
 }
 
 static bool tx_win_args_valid(enum vas_cop_type cop,
@@ -1031,10 +1040,10 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
 	}
 
 	txwin->cop = cop;
-	txwin->tx_win = 1;
-	txwin->rxwin = rxwin;
-	txwin->nx_win = txwin->rxwin->nx_win;
-	txwin->user_win = attr->user_win;
+	txwin->pnv.tx_win = 1;
+	txwin->pnv.rxwin = rxwin;
+	txwin->pnv.nx_win = txwin->pnv.rxwin->pnv.nx_win;
+	txwin->pnv.user_win = attr->user_win;
 	txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT;
 
 	init_winctx_for_txwin(txwin, attr, &winctx);
@@ -1049,10 +1058,10 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
 	 * NOTE: If kernel ever resubmits a user CRB after handling a page
 	 *	 fault, we will need to map this into kernel as well.
 	 */
-	if (!txwin->user_win) {
-		txwin->paste_kaddr = map_paste_region(txwin);
-		if (IS_ERR(txwin->paste_kaddr)) {
-			rc = PTR_ERR(txwin->paste_kaddr);
+	if (!txwin->pnv.user_win) {
+		txwin->pnv.paste_kaddr = map_paste_region(txwin);
+		if (IS_ERR(txwin->pnv.paste_kaddr)) {
+			rc = PTR_ERR(txwin->pnv.paste_kaddr);
 			goto free_window;
 		}
 	} else {
@@ -1104,9 +1113,9 @@ int vas_paste_crb(struct vas_window *txwin, int offset, bool re)
 	 * report-enable flag is set for NX windows. Ensure software
 	 * complies too.
 	 */
-	WARN_ON_ONCE(txwin->nx_win && !re);
+	WARN_ON_ONCE(txwin->pnv.nx_win && !re);
 
-	addr = txwin->paste_kaddr;
+	addr = txwin->pnv.paste_kaddr;
 	if (re) {
 		/*
 		 * Set the REPORT_ENABLE bit (equivalent to writing
@@ -1153,7 +1162,7 @@ static void poll_window_credits(struct vas_window *window)
 	int count = 0;
 
 	val = read_hvwc_reg(window, VREG(WINCTL));
-	if (window->tx_win)
+	if (window->pnv.tx_win)
 		mode = GET_FIELD(VAS_WINCTL_TX_WCRED_MODE, val);
 	else
 		mode = GET_FIELD(VAS_WINCTL_RX_WCRED_MODE, val);
@@ -1161,7 +1170,7 @@ static void poll_window_credits(struct vas_window *window)
 	if (!mode)
 		return;
 retry:
-	if (window->tx_win) {
+	if (window->pnv.tx_win) {
 		val = read_hvwc_reg(window, VREG(TX_WCRED));
 		creds = GET_FIELD(VAS_TX_WCRED, val);
 	} else {
@@ -1277,7 +1286,7 @@ int vas_win_close(struct vas_window *window)
 	if (!window)
 		return 0;
 
-	if (!window->tx_win && atomic_read(&window->num_txwins) != 0) {
+	if (!window->pnv.tx_win && atomic_read(&window->pnv.num_txwins) != 0) {
 		pr_devel("Attempting to close an active Rx window!\n");
 		WARN_ON_ONCE(1);
 		return -EBUSY;
@@ -1296,11 +1305,11 @@ int vas_win_close(struct vas_window *window)
 	poll_window_castout(window);
 
 	/* if send window, drop reference to matching receive window */
-	if (window->tx_win) {
-		if (window->user_win)
+	if (window->pnv.tx_win) {
+		if (window->pnv.user_win)
 			vas_drop_reference_pid_mm(&window->task_ref);
 
-		put_rx_win(window->rxwin);
+		put_rx_win(window->pnv.rxwin);
 	}
 
 	vas_window_free(window);
@@ -1384,12 +1393,12 @@ struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
 	 * since their CRBs are ignored (not queued on FIFO or processed
 	 * by NX).
 	 */
-	if (!window->tx_win || !window->user_win || !window->nx_win ||
-			window->cop == VAS_COP_TYPE_FAULT ||
-			window->cop == VAS_COP_TYPE_FTW) {
+	if (!window->pnv.tx_win || !window->pnv.user_win ||
+		!window->pnv.nx_win || window->cop == VAS_COP_TYPE_FAULT ||
+		window->cop == VAS_COP_TYPE_FTW) {
 		pr_err("PSWID decode: id %d, tx %d, user %d, nx %d, cop %d\n",
-			winid, window->tx_win, window->user_win,
-			window->nx_win, window->cop);
+			winid, window->pnv.tx_win, window->pnv.user_win,
+			window->pnv.nx_win, window->cop);
 		WARN_ON(1);
 	}
 
diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
index f354dd5c51bd..f2d9daff3d82 100644
--- a/arch/powerpc/platforms/powernv/vas.h
+++ b/arch/powerpc/platforms/powernv/vas.h
@@ -345,34 +345,6 @@ struct vas_instance {
 	struct dentry *dbgdir;
 };
 
-/*
- * In-kernel state a VAS window. One per window.
- */
-struct vas_window {
-	/* Fields common to send and receive windows */
-	struct vas_instance *vinst;
-	int winid;
-	bool tx_win;		/* True if send window */
-	bool nx_win;		/* True if NX window */
-	bool user_win;		/* True if user space window */
-	void *hvwc_map;		/* HV window context */
-	void *uwc_map;		/* OS/User window context */
-	int wcreds_max;		/* Window credits */
-
-	struct vas_user_win_ref task_ref;
-	char *dbgname;
-	struct dentry *dbgdir;
-
-	/* Fields applicable only to send windows */
-	void *paste_kaddr;
-	char *paste_addr_name;
-	struct vas_window *rxwin;
-
-	/* Feilds applicable only to receive windows */
-	enum vas_cop_type cop;
-	atomic_t num_txwins;
-};
-
 /*
  * Container for the hardware state of a window. One per-window.
  *
@@ -449,8 +421,8 @@ static inline void vas_log_write(struct vas_window *win, char *name,
 {
 	if (val)
 		pr_debug("%swin #%d: %s reg %p, val 0x%016llx\n",
-				win->tx_win ? "Tx" : "Rx", win->winid, name,
-				regptr, val);
+				win->pnv.tx_win ? "Tx" : "Rx", win->winid,
+				name, regptr, val);
 }
 
 static inline void write_uwc_reg(struct vas_window *win, char *name,
@@ -458,7 +430,7 @@ static inline void write_uwc_reg(struct vas_window *win, char *name,
 {
 	void *regptr;
 
-	regptr = win->uwc_map + reg;
+	regptr = win->pnv.uwc_map + reg;
 	vas_log_write(win, name, regptr, val);
 
 	out_be64(regptr, val);
@@ -469,7 +441,7 @@ static inline void write_hvwc_reg(struct vas_window *win, char *name,
 {
 	void *regptr;
 
-	regptr = win->hvwc_map + reg;
+	regptr = win->pnv.hvwc_map + reg;
 	vas_log_write(win, name, regptr, val);
 
 	out_be64(regptr, val);
@@ -478,7 +450,7 @@ static inline void write_hvwc_reg(struct vas_window *win, char *name,
 static inline u64 read_hvwc_reg(struct vas_window *win,
 			char *name __maybe_unused, s32 reg)
 {
-	return in_be64(win->hvwc_map+reg);
+	return in_be64(win->pnv.hvwc_map + reg);
 }
 
 /*
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 07/16] powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:34   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:34 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


This patch adds HCALLs and other definitions. Also define structs
that are used in VAS implementation on powerVM.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/hvcall.h    |   7 ++
 arch/powerpc/include/asm/vas.h       |  32 ++++++++
 arch/powerpc/platforms/pseries/vas.h | 110 +++++++++++++++++++++++++++
 3 files changed, 149 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/vas.h

diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index e3b29eda8074..7c3418d1b5e9 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -294,6 +294,13 @@
 #define H_RESIZE_HPT_COMMIT	0x370
 #define H_REGISTER_PROC_TBL	0x37C
 #define H_SIGNAL_SYS_RESET	0x380
+#define H_ALLOCATE_VAS_WINDOW	0x388
+#define H_MODIFY_VAS_WINDOW	0x38C
+#define H_DEALLOCATE_VAS_WINDOW	0x390
+#define H_QUERY_VAS_WINDOW	0x394
+#define H_QUERY_VAS_CAPABILITIES	0x398
+#define H_QUERY_NX_CAPABILITIES	0x39C
+#define H_GET_NX_FAULT		0x3A0
 #define H_INT_GET_SOURCE_INFO   0x3A8
 #define H_INT_SET_SOURCE_CONFIG 0x3AC
 #define H_INT_GET_SOURCE_CONFIG 0x3B0
diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 49bfb5be896d..371f62d99174 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -181,6 +181,7 @@ struct vas_tx_win_attr {
 	bool rx_win_ord_mode;
 };
 
+#ifdef CONFIG_PPC_POWERNV
 /*
  * Helper to map a chip id to VAS id.
  * For POWER9, this is a 1:1 mapping. In the future this maybe a 1:N
@@ -248,6 +249,37 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr,
 int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
 			     const char *name);
 void vas_unregister_api_powernv(void);
+#endif
+
+#ifdef CONFIG_PPC_PSERIES
+
+/* VAS Capabilities */
+#define VAS_GZIP_QOS_FEAT	0x1
+#define VAS_GZIP_DEF_FEAT	0x2
+#define VAS_GZIP_QOS_FEAT_BIT	PPC_BIT(VAS_GZIP_QOS_FEAT) /* Bit 1 */
+#define VAS_GZIP_DEF_FEAT_BIT	PPC_BIT(VAS_GZIP_DEF_FEAT) /* Bit 2 */
+
+/* NX Capabilities */
+#define VAS_NX_GZIP_FEAT	0x1
+#define VAS_NX_GZIP_FEAT_BIT	PPC_BIT(VAS_NX_GZIP_FEAT) /* Bit 1 */
+#define VAS_DESCR_LEN		8
+
+/*
+ * These structs are used to retrieve overall VAS capabilities that
+ * the hypervisor provides.
+ */
+struct hv_vas_all_caps {
+	__be64  descriptor;
+	__be64  feat_type;
+} __packed __aligned(0x1000);
+
+struct vas_all_caps {
+	char	name[VAS_DESCR_LEN + 1];
+	u64     descriptor;
+	u64     feat_type;
+};
+
+#endif
 
 /*
  * Register / unregister coprocessor type to VAS API which will be exported
diff --git a/arch/powerpc/platforms/pseries/vas.h b/arch/powerpc/platforms/pseries/vas.h
new file mode 100644
index 000000000000..033667921d36
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/vas.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright 2020-21 IBM Corp.
+ */
+
+#ifndef _VAS_H
+#define _VAS_H
+#include <asm/vas.h>
+#include <linux/mutex.h>
+#include <linux/stringify.h>
+
+/*
+ * VAS window modify flags
+ */
+#define	VAS_MOD_WIN_CLOSE	PPC_BIT(0)
+#define	VAS_MOD_WIN_JOBS_KILL	PPC_BIT(1)
+#define	VAS_MOD_WIN_DR		PPC_BIT(3)
+#define	VAS_MOD_WIN_PR		PPC_BIT(4)
+#define	VAS_MOD_WIN_SF		PPC_BIT(5)
+#define	VAS_MOD_WIN_TA		PPC_BIT(6)
+#define	VAS_MOD_WIN_FLAGS	(VAS_MOD_WIN_JOBS_KILL | VAS_MOD_WIN_DR | \
+				VAS_MOD_WIN_PR | VAS_MOD_WIN_SF)
+
+#define	VAS_WIN_ACTIVE		0x0
+#define	VAS_WIN_CLOSED		0x1
+#define	VAS_WIN_INACTIVE	0x2	/* Inactive due to HW failure */
+/* Process of being modified, deallocated, or quiesced */
+#define	VAS_WIN_MOD_IN_PROCESS	0x3
+
+#define	VAS_COPY_PASTE_USER_MODE	0x00000001
+#define	VAS_COP_OP_USER_MODE		0x00000010
+
+/*
+ * Co-processor feature - GZIP QoS windows or GZIP default windows
+ */
+enum vas_cop_feat_type {
+	VAS_GZIP_QOS_FEAT_TYPE,
+	VAS_GZIP_DEF_FEAT_TYPE,
+	VAS_MAX_FEAT_TYPE,
+};
+
+/*
+ * Use to get feature specific capabilities from the
+ * hypervisor.
+ */
+struct hv_vas_ct_caps {
+	__be64	descriptor;
+	u8	win_type;		/* Default or QoS type */
+	u8	user_mode;
+	__be16	max_lpar_creds;
+	__be16	max_win_creds;
+	union {
+		__be16	reserved;
+		__be16	def_lpar_creds; /* Used for default capabilities */
+	};
+	__be16	target_lpar_creds;
+} __packed __aligned(0x1000);
+
+/*
+ * Feature specific (QoS or default) capabilities.
+ */
+struct vas_ct_caps {
+	char		name[VAS_DESCR_LEN + 1];
+	u64		descriptor;
+	u8		win_type;	/* Default or QoS type */
+	u8		user_mode;	/* User mode copy/paste or COP HCALL */
+	u16		max_lpar_creds;	/* Max credits available in LPAR */
+	/* Max credits can be assigned per window */
+	u16		max_win_creds;
+	union {
+		u16	reserved;	/* Used for QoS credit type */
+		u16	def_lpar_creds; /* Used for default credit type */
+	};
+	/* Total LPAR available credits. Can be different from max LPAR */
+	/* credits due to DLPAR operation */
+	atomic_t	target_lpar_creds;
+	atomic_t	used_lpar_creds; /* Used credits so far */
+	u16		avail_lpar_creds; /* Remaining available credits */
+};
+
+/*
+ * Feature (QoS or Default) specific to store capabilities and
+ * the list of open windows.
+ */
+struct vas_caps {
+	struct vas_ct_caps caps;
+	struct list_head list;	/* List of open windows */
+};
+
+/*
+ * To get window information from the hypervisor.
+ */
+struct hv_vas_win_lpar {
+	__be16	version;
+	u8	win_type;
+	u8	status;
+	__be16	credits;	/* No of credits assigned to this window */
+	__be16	reserved;
+	__be32	pid;		/* LPAR Process ID */
+	__be32	tid;		/* LPAR Thread ID */
+	__be64	win_addr;	/* Paste address */
+	__be32	interrupt;	/* Interrupt when NX request completes */
+	__be32	fault;		/* Interrupt when NX sees fault */
+	/* Associativity Domain Identifiers as returned in */
+	/* H_HOME_NODE_ASSOCIATIVITY */
+	__be64	domain[6];
+	__be64	win_util;	/* Number of bytes processed */
+} __packed __aligned(0x1000);
+
+#endif /* _VAS_H */
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 07/16] powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
@ 2021-05-21  9:34   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:34 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


This patch adds HCALLs and other definitions. Also define structs
that are used in VAS implementation on powerVM.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/hvcall.h    |   7 ++
 arch/powerpc/include/asm/vas.h       |  32 ++++++++
 arch/powerpc/platforms/pseries/vas.h | 110 +++++++++++++++++++++++++++
 3 files changed, 149 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/vas.h

diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index e3b29eda8074..7c3418d1b5e9 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -294,6 +294,13 @@
 #define H_RESIZE_HPT_COMMIT	0x370
 #define H_REGISTER_PROC_TBL	0x37C
 #define H_SIGNAL_SYS_RESET	0x380
+#define H_ALLOCATE_VAS_WINDOW	0x388
+#define H_MODIFY_VAS_WINDOW	0x38C
+#define H_DEALLOCATE_VAS_WINDOW	0x390
+#define H_QUERY_VAS_WINDOW	0x394
+#define H_QUERY_VAS_CAPABILITIES	0x398
+#define H_QUERY_NX_CAPABILITIES	0x39C
+#define H_GET_NX_FAULT		0x3A0
 #define H_INT_GET_SOURCE_INFO   0x3A8
 #define H_INT_SET_SOURCE_CONFIG 0x3AC
 #define H_INT_GET_SOURCE_CONFIG 0x3B0
diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 49bfb5be896d..371f62d99174 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -181,6 +181,7 @@ struct vas_tx_win_attr {
 	bool rx_win_ord_mode;
 };
 
+#ifdef CONFIG_PPC_POWERNV
 /*
  * Helper to map a chip id to VAS id.
  * For POWER9, this is a 1:1 mapping. In the future this maybe a 1:N
@@ -248,6 +249,37 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr,
 int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
 			     const char *name);
 void vas_unregister_api_powernv(void);
+#endif
+
+#ifdef CONFIG_PPC_PSERIES
+
+/* VAS Capabilities */
+#define VAS_GZIP_QOS_FEAT	0x1
+#define VAS_GZIP_DEF_FEAT	0x2
+#define VAS_GZIP_QOS_FEAT_BIT	PPC_BIT(VAS_GZIP_QOS_FEAT) /* Bit 1 */
+#define VAS_GZIP_DEF_FEAT_BIT	PPC_BIT(VAS_GZIP_DEF_FEAT) /* Bit 2 */
+
+/* NX Capabilities */
+#define VAS_NX_GZIP_FEAT	0x1
+#define VAS_NX_GZIP_FEAT_BIT	PPC_BIT(VAS_NX_GZIP_FEAT) /* Bit 1 */
+#define VAS_DESCR_LEN		8
+
+/*
+ * These structs are used to retrieve overall VAS capabilities that
+ * the hypervisor provides.
+ */
+struct hv_vas_all_caps {
+	__be64  descriptor;
+	__be64  feat_type;
+} __packed __aligned(0x1000);
+
+struct vas_all_caps {
+	char	name[VAS_DESCR_LEN + 1];
+	u64     descriptor;
+	u64     feat_type;
+};
+
+#endif
 
 /*
  * Register / unregister coprocessor type to VAS API which will be exported
diff --git a/arch/powerpc/platforms/pseries/vas.h b/arch/powerpc/platforms/pseries/vas.h
new file mode 100644
index 000000000000..033667921d36
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/vas.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright 2020-21 IBM Corp.
+ */
+
+#ifndef _VAS_H
+#define _VAS_H
+#include <asm/vas.h>
+#include <linux/mutex.h>
+#include <linux/stringify.h>
+
+/*
+ * VAS window modify flags
+ */
+#define	VAS_MOD_WIN_CLOSE	PPC_BIT(0)
+#define	VAS_MOD_WIN_JOBS_KILL	PPC_BIT(1)
+#define	VAS_MOD_WIN_DR		PPC_BIT(3)
+#define	VAS_MOD_WIN_PR		PPC_BIT(4)
+#define	VAS_MOD_WIN_SF		PPC_BIT(5)
+#define	VAS_MOD_WIN_TA		PPC_BIT(6)
+#define	VAS_MOD_WIN_FLAGS	(VAS_MOD_WIN_JOBS_KILL | VAS_MOD_WIN_DR | \
+				VAS_MOD_WIN_PR | VAS_MOD_WIN_SF)
+
+#define	VAS_WIN_ACTIVE		0x0
+#define	VAS_WIN_CLOSED		0x1
+#define	VAS_WIN_INACTIVE	0x2	/* Inactive due to HW failure */
+/* Process of being modified, deallocated, or quiesced */
+#define	VAS_WIN_MOD_IN_PROCESS	0x3
+
+#define	VAS_COPY_PASTE_USER_MODE	0x00000001
+#define	VAS_COP_OP_USER_MODE		0x00000010
+
+/*
+ * Co-processor feature - GZIP QoS windows or GZIP default windows
+ */
+enum vas_cop_feat_type {
+	VAS_GZIP_QOS_FEAT_TYPE,
+	VAS_GZIP_DEF_FEAT_TYPE,
+	VAS_MAX_FEAT_TYPE,
+};
+
+/*
+ * Use to get feature specific capabilities from the
+ * hypervisor.
+ */
+struct hv_vas_ct_caps {
+	__be64	descriptor;
+	u8	win_type;		/* Default or QoS type */
+	u8	user_mode;
+	__be16	max_lpar_creds;
+	__be16	max_win_creds;
+	union {
+		__be16	reserved;
+		__be16	def_lpar_creds; /* Used for default capabilities */
+	};
+	__be16	target_lpar_creds;
+} __packed __aligned(0x1000);
+
+/*
+ * Feature specific (QoS or default) capabilities.
+ */
+struct vas_ct_caps {
+	char		name[VAS_DESCR_LEN + 1];
+	u64		descriptor;
+	u8		win_type;	/* Default or QoS type */
+	u8		user_mode;	/* User mode copy/paste or COP HCALL */
+	u16		max_lpar_creds;	/* Max credits available in LPAR */
+	/* Max credits can be assigned per window */
+	u16		max_win_creds;
+	union {
+		u16	reserved;	/* Used for QoS credit type */
+		u16	def_lpar_creds; /* Used for default credit type */
+	};
+	/* Total LPAR available credits. Can be different from max LPAR */
+	/* credits due to DLPAR operation */
+	atomic_t	target_lpar_creds;
+	atomic_t	used_lpar_creds; /* Used credits so far */
+	u16		avail_lpar_creds; /* Remaining available credits */
+};
+
+/*
+ * Feature (QoS or Default) specific to store capabilities and
+ * the list of open windows.
+ */
+struct vas_caps {
+	struct vas_ct_caps caps;
+	struct list_head list;	/* List of open windows */
+};
+
+/*
+ * To get window information from the hypervisor.
+ */
+struct hv_vas_win_lpar {
+	__be16	version;
+	u8	win_type;
+	u8	status;
+	__be16	credits;	/* No of credits assigned to this window */
+	__be16	reserved;
+	__be32	pid;		/* LPAR Process ID */
+	__be32	tid;		/* LPAR Thread ID */
+	__be64	win_addr;	/* Paste address */
+	__be32	interrupt;	/* Interrupt when NX request completes */
+	__be32	fault;		/* Interrupt when NX sees fault */
+	/* Associativity Domain Identifiers as returned in */
+	/* H_HOME_NODE_ASSOCIATIVITY */
+	__be64	domain[6];
+	__be64	win_util;	/* Number of bytes processed */
+} __packed __aligned(0x1000);
+
+#endif /* _VAS_H */
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 08/16] powerpc/vas: Define QoS credit flag to allocate window
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:34   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:34 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


PowerVM introduces two different type of credits: Default and Quality
of service (QoS).

The total number of default credits available on each LPAR depends
on CPU resources configured. But these credits can be shared or
over-committed across LPARs in shared mode which can result in
paste command failure (RMA_busy). To avoid NX HW contention, the
hypervisor ntroduces QoS credit type which makes sure guaranteed
access to NX esources. The system admins can assign QoS credits
or each LPAR via HMC.

Default credit type is used to allocate a VAS window by default as
on PowerVM implementation. But the process can pass
VAS_TX_WIN_FLAG_QOS_CREDIT flag with VAS_TX_WIN_OPEN ioctl to open
QoS type window.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/uapi/asm/vas-api.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/uapi/asm/vas-api.h b/arch/powerpc/include/uapi/asm/vas-api.h
index ebd4b2424785..7c81301ecdba 100644
--- a/arch/powerpc/include/uapi/asm/vas-api.h
+++ b/arch/powerpc/include/uapi/asm/vas-api.h
@@ -13,11 +13,15 @@
 #define VAS_MAGIC	'v'
 #define VAS_TX_WIN_OPEN	_IOW(VAS_MAGIC, 0x20, struct vas_tx_win_open_attr)
 
+/* Flags to VAS TX open window ioctl */
+/* To allocate a window with QoS credit, otherwise use default credit */
+#define VAS_TX_WIN_FLAG_QOS_CREDIT	0x0000000000000001
+
 struct vas_tx_win_open_attr {
 	__u32	version;
 	__s16	vas_id;	/* specific instance of vas or -1 for default */
 	__u16	reserved1;
-	__u64	flags;	/* Future use */
+	__u64	flags;
 	__u64	reserved2[6];
 };
 
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 08/16] powerpc/vas: Define QoS credit flag to allocate window
@ 2021-05-21  9:34   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:34 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


PowerVM introduces two different type of credits: Default and Quality
of service (QoS).

The total number of default credits available on each LPAR depends
on CPU resources configured. But these credits can be shared or
over-committed across LPARs in shared mode which can result in
paste command failure (RMA_busy). To avoid NX HW contention, the
hypervisor ntroduces QoS credit type which makes sure guaranteed
access to NX esources. The system admins can assign QoS credits
or each LPAR via HMC.

Default credit type is used to allocate a VAS window by default as
on PowerVM implementation. But the process can pass
VAS_TX_WIN_FLAG_QOS_CREDIT flag with VAS_TX_WIN_OPEN ioctl to open
QoS type window.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/uapi/asm/vas-api.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/uapi/asm/vas-api.h b/arch/powerpc/include/uapi/asm/vas-api.h
index ebd4b2424785..7c81301ecdba 100644
--- a/arch/powerpc/include/uapi/asm/vas-api.h
+++ b/arch/powerpc/include/uapi/asm/vas-api.h
@@ -13,11 +13,15 @@
 #define VAS_MAGIC	'v'
 #define VAS_TX_WIN_OPEN	_IOW(VAS_MAGIC, 0x20, struct vas_tx_win_open_attr)
 
+/* Flags to VAS TX open window ioctl */
+/* To allocate a window with QoS credit, otherwise use default credit */
+#define VAS_TX_WIN_FLAG_QOS_CREDIT	0x0000000000000001
+
 struct vas_tx_win_open_attr {
 	__u32	version;
 	__s16	vas_id;	/* specific instance of vas or -1 for default */
 	__u16	reserved1;
-	__u64	flags;	/* Future use */
+	__u64	flags;
 	__u64	reserved2[6];
 };
 
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 09/16] powerpc/pseries/vas: Add HCALL wrappers for VAS handling
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:35   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:35 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


This patch adds the following HCALL wrapper functions to allocate,
modify and deallocate VAS windows, and retrieve VAS capabilities.

H_ALLOCATE_VAS_WINDOW: Allocate VAS window
H_DEALLOCATE_VAS_WINDOW: Close VAS window
H_MODIFY_VAS_WINDOW: Setup window before using
H_QUERY_VAS_CAPABILITIES: Get VAS capabilities

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/platforms/pseries/vas.c | 217 +++++++++++++++++++++++++++
 1 file changed, 217 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/vas.c

diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
new file mode 100644
index 000000000000..06960151477c
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2020-21 IBM Corp.
+ */
+
+#define pr_fmt(fmt) "vas: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/sched/mm.h>
+#include <linux/mmu_context.h>
+#include <asm/hvcall.h>
+#include <asm/hvconsole.h>
+#include <asm/machdep.h>
+#include <asm/plpar_wrappers.h>
+#include <asm/vas.h>
+#include "vas.h"
+
+#define	VAS_INVALID_WIN_ADDRESS	0xFFFFFFFFFFFFFFFFul
+#define	VAS_DEFAULT_DOMAIN_ID	0xFFFFFFFFFFFFFFFFul
+/* Authority Mask Register (AMR) value is not supported in */
+/* linux implementation. So pass '0' to modify window HCALL */
+#define	VAS_AMR_VALUE	0
+/* phyp allows one credit per window right now */
+#define DEF_WIN_CREDS		1
+
+static int64_t hcall_return_busy_check(int64_t rc)
+{
+	/* Check if we are stalled for some time */
+	if (H_IS_LONG_BUSY(rc)) {
+		msleep(get_longbusy_msecs(rc));
+		rc = H_BUSY;
+	} else if (rc == H_BUSY) {
+		cond_resched();
+	}
+
+	return rc;
+}
+
+/*
+ * Allocate VAS window HCALL
+ */
+static int plpar_vas_allocate_window(struct vas_window *win, u64 *domain,
+				     u8 wintype, u16 credits)
+{
+	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
+	int64_t rc;
+
+	do {
+		rc = plpar_hcall9(H_ALLOCATE_VAS_WINDOW, retbuf, wintype,
+				  credits, domain[0], domain[1], domain[2],
+				  domain[3], domain[4], domain[5]);
+
+		rc = hcall_return_busy_check(rc);
+	} while (rc == H_BUSY);
+
+	switch (rc) {
+	case H_SUCCESS:
+		win->winid = retbuf[0];
+		win->lpar.win_addr = retbuf[1];
+		win->lpar.complete_irq = retbuf[2];
+		win->lpar.fault_irq = retbuf[3];
+		if (win->lpar.win_addr == VAS_INVALID_WIN_ADDRESS) {
+			pr_err("HCALL(%x): COPY/PASTE is not supported\n",
+				H_ALLOCATE_VAS_WINDOW);
+			return -ENOTSUPP;
+		}
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%x): Invalid window type (%u)\n",
+			H_ALLOCATE_VAS_WINDOW, wintype);
+		return -EINVAL;
+	case H_P2:
+		pr_err("HCALL(%x): Credits(%u) exceed maximum window credits\n",
+			H_ALLOCATE_VAS_WINDOW, credits);
+		return -EINVAL;
+	case H_COP_HW:
+		pr_err("HCALL(%x): User-mode COPY/PASTE is not supported\n",
+			H_ALLOCATE_VAS_WINDOW);
+		return -ENOTSUPP;
+	case H_RESOURCE:
+		pr_err("HCALL(%x): LPAR credit limit exceeds window limit\n",
+			H_ALLOCATE_VAS_WINDOW);
+		return -EPERM;
+	case H_CONSTRAINED:
+		pr_err("HCALL(%x): Credits (%u) are not available\n",
+			H_ALLOCATE_VAS_WINDOW, credits);
+		return -EPERM;
+	default:
+		pr_err("HCALL(%x): Unexpected error %lld\n",
+			H_ALLOCATE_VAS_WINDOW, rc);
+		return -EIO;
+	}
+}
+
+/*
+ * Deallocate VAS window HCALL.
+ */
+static int plpar_vas_deallocate_window(u64 winid)
+{
+	int64_t rc;
+
+	do {
+		rc = plpar_hcall_norets(H_DEALLOCATE_VAS_WINDOW, winid);
+
+		rc = hcall_return_busy_check(rc);
+	} while (rc == H_BUSY);
+
+	switch (rc) {
+	case H_SUCCESS:
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%x): Invalid window ID %llu\n",
+			H_DEALLOCATE_VAS_WINDOW, winid);
+		return -EINVAL;
+	case H_STATE:
+		pr_err("HCALL(%x): Window(%llu): Invalid page table entries\n",
+			H_DEALLOCATE_VAS_WINDOW, winid);
+		return -EPERM;
+	default:
+		pr_err("HCALL(%x): Unexpected error %lld for window(%llu)\n",
+			H_DEALLOCATE_VAS_WINDOW, rc, winid);
+		return -EIO;
+	}
+}
+
+/*
+ * Modify VAS window.
+ * After the window is opened with allocate window HCALL, configure it
+ * with flags and LPAR PID before using.
+ */
+static int plpar_vas_modify_window(struct vas_window *win)
+{
+	int64_t rc;
+	u32 lpid = mfspr(SPRN_PID);
+
+	/*
+	 * AMR value is not supported in Linux implementation
+	 * phyp ignores it if 0 is passed.
+	 */
+	do {
+		rc = plpar_hcall_norets(H_MODIFY_VAS_WINDOW, win->winid,
+					lpid, 0, VAS_MOD_WIN_FLAGS,
+					VAS_AMR_VALUE);
+
+		rc = hcall_return_busy_check(rc);
+	} while (rc == H_BUSY);
+
+	switch (rc) {
+	case H_SUCCESS:
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%x): Invalid window ID %u\n",
+			H_MODIFY_VAS_WINDOW, win->winid);
+		return -EINVAL;
+	case H_P2:
+		pr_err("HCALL(%x): Window(%d): Invalid LPAR Process ID %u\n",
+			H_MODIFY_VAS_WINDOW, lpid, win->winid);
+		return -EINVAL;
+	case H_P3:
+		/* LPAR thread ID is deprecated on P10 */
+		pr_err("HCALL(%x): Invalid LPAR Thread ID for window(%u)\n",
+			H_MODIFY_VAS_WINDOW, win->winid);
+		return -EINVAL;
+	case H_STATE:
+		pr_err("HCALL(%x): Jobs in progress, Can't modify window(%u)\n",
+			H_MODIFY_VAS_WINDOW, win->winid);
+		return -EBUSY;
+	default:
+		pr_err("HCALL(%x): Unexpected error %lld for window(%u)\n",
+			H_MODIFY_VAS_WINDOW, rc, win->winid);
+		return -EIO;
+	}
+}
+
+/*
+ * This HCALL is used to determine the capabilities that pHyp provides.
+ * @hcall: H_QUERY_VAS_CAPABILITIES or H_QUERY_NX_CAPABILITIES
+ * @query_type: If 0 is passed, phyp returns the overall capabilities
+ *		which provides all feature(s) that are available. Then
+ *		query phyp to get the corresponding capabilities for
+ *		the specific feature.
+ *		Example: H_QUERY_VAS_CAPABILITIES provides VAS GZIP QoS
+ *			and VAS GZIP Default capabilities.
+ *			H_QUERY_NX_CAPABILITIES provides NX GZIP
+ *			capabilities.
+ * @result: Return buffer to save capabilities.
+ */
+int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
+					u64 result)
+{
+	int64_t rc;
+
+	rc = plpar_hcall_norets(hcall, query_type, result);
+
+	switch (rc) {
+	case H_SUCCESS:
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%llx): Invalid query type %u\n", hcall,
+			query_type);
+		return -EINVAL;
+	case H_PRIVILEGE:
+		pr_err("HCALL(%llx): Invalid result buffer 0x%llx\n",
+			hcall, result);
+		return -EACCES;
+	default:
+		pr_err("HCALL(%llx): Unexpected error %lld\n", hcall, rc);
+		return -EIO;
+	}
+}
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 09/16] powerpc/pseries/vas: Add HCALL wrappers for VAS handling
@ 2021-05-21  9:35   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:35 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


This patch adds the following HCALL wrapper functions to allocate,
modify and deallocate VAS windows, and retrieve VAS capabilities.

H_ALLOCATE_VAS_WINDOW: Allocate VAS window
H_DEALLOCATE_VAS_WINDOW: Close VAS window
H_MODIFY_VAS_WINDOW: Setup window before using
H_QUERY_VAS_CAPABILITIES: Get VAS capabilities

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/platforms/pseries/vas.c | 217 +++++++++++++++++++++++++++
 1 file changed, 217 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/vas.c

diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
new file mode 100644
index 000000000000..06960151477c
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2020-21 IBM Corp.
+ */
+
+#define pr_fmt(fmt) "vas: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/sched/mm.h>
+#include <linux/mmu_context.h>
+#include <asm/hvcall.h>
+#include <asm/hvconsole.h>
+#include <asm/machdep.h>
+#include <asm/plpar_wrappers.h>
+#include <asm/vas.h>
+#include "vas.h"
+
+#define	VAS_INVALID_WIN_ADDRESS	0xFFFFFFFFFFFFFFFFul
+#define	VAS_DEFAULT_DOMAIN_ID	0xFFFFFFFFFFFFFFFFul
+/* Authority Mask Register (AMR) value is not supported in */
+/* linux implementation. So pass '0' to modify window HCALL */
+#define	VAS_AMR_VALUE	0
+/* phyp allows one credit per window right now */
+#define DEF_WIN_CREDS		1
+
+static int64_t hcall_return_busy_check(int64_t rc)
+{
+	/* Check if we are stalled for some time */
+	if (H_IS_LONG_BUSY(rc)) {
+		msleep(get_longbusy_msecs(rc));
+		rc = H_BUSY;
+	} else if (rc == H_BUSY) {
+		cond_resched();
+	}
+
+	return rc;
+}
+
+/*
+ * Allocate VAS window HCALL
+ */
+static int plpar_vas_allocate_window(struct vas_window *win, u64 *domain,
+				     u8 wintype, u16 credits)
+{
+	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
+	int64_t rc;
+
+	do {
+		rc = plpar_hcall9(H_ALLOCATE_VAS_WINDOW, retbuf, wintype,
+				  credits, domain[0], domain[1], domain[2],
+				  domain[3], domain[4], domain[5]);
+
+		rc = hcall_return_busy_check(rc);
+	} while (rc == H_BUSY);
+
+	switch (rc) {
+	case H_SUCCESS:
+		win->winid = retbuf[0];
+		win->lpar.win_addr = retbuf[1];
+		win->lpar.complete_irq = retbuf[2];
+		win->lpar.fault_irq = retbuf[3];
+		if (win->lpar.win_addr == VAS_INVALID_WIN_ADDRESS) {
+			pr_err("HCALL(%x): COPY/PASTE is not supported\n",
+				H_ALLOCATE_VAS_WINDOW);
+			return -ENOTSUPP;
+		}
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%x): Invalid window type (%u)\n",
+			H_ALLOCATE_VAS_WINDOW, wintype);
+		return -EINVAL;
+	case H_P2:
+		pr_err("HCALL(%x): Credits(%u) exceed maximum window credits\n",
+			H_ALLOCATE_VAS_WINDOW, credits);
+		return -EINVAL;
+	case H_COP_HW:
+		pr_err("HCALL(%x): User-mode COPY/PASTE is not supported\n",
+			H_ALLOCATE_VAS_WINDOW);
+		return -ENOTSUPP;
+	case H_RESOURCE:
+		pr_err("HCALL(%x): LPAR credit limit exceeds window limit\n",
+			H_ALLOCATE_VAS_WINDOW);
+		return -EPERM;
+	case H_CONSTRAINED:
+		pr_err("HCALL(%x): Credits (%u) are not available\n",
+			H_ALLOCATE_VAS_WINDOW, credits);
+		return -EPERM;
+	default:
+		pr_err("HCALL(%x): Unexpected error %lld\n",
+			H_ALLOCATE_VAS_WINDOW, rc);
+		return -EIO;
+	}
+}
+
+/*
+ * Deallocate VAS window HCALL.
+ */
+static int plpar_vas_deallocate_window(u64 winid)
+{
+	int64_t rc;
+
+	do {
+		rc = plpar_hcall_norets(H_DEALLOCATE_VAS_WINDOW, winid);
+
+		rc = hcall_return_busy_check(rc);
+	} while (rc == H_BUSY);
+
+	switch (rc) {
+	case H_SUCCESS:
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%x): Invalid window ID %llu\n",
+			H_DEALLOCATE_VAS_WINDOW, winid);
+		return -EINVAL;
+	case H_STATE:
+		pr_err("HCALL(%x): Window(%llu): Invalid page table entries\n",
+			H_DEALLOCATE_VAS_WINDOW, winid);
+		return -EPERM;
+	default:
+		pr_err("HCALL(%x): Unexpected error %lld for window(%llu)\n",
+			H_DEALLOCATE_VAS_WINDOW, rc, winid);
+		return -EIO;
+	}
+}
+
+/*
+ * Modify VAS window.
+ * After the window is opened with allocate window HCALL, configure it
+ * with flags and LPAR PID before using.
+ */
+static int plpar_vas_modify_window(struct vas_window *win)
+{
+	int64_t rc;
+	u32 lpid = mfspr(SPRN_PID);
+
+	/*
+	 * AMR value is not supported in Linux implementation
+	 * phyp ignores it if 0 is passed.
+	 */
+	do {
+		rc = plpar_hcall_norets(H_MODIFY_VAS_WINDOW, win->winid,
+					lpid, 0, VAS_MOD_WIN_FLAGS,
+					VAS_AMR_VALUE);
+
+		rc = hcall_return_busy_check(rc);
+	} while (rc == H_BUSY);
+
+	switch (rc) {
+	case H_SUCCESS:
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%x): Invalid window ID %u\n",
+			H_MODIFY_VAS_WINDOW, win->winid);
+		return -EINVAL;
+	case H_P2:
+		pr_err("HCALL(%x): Window(%d): Invalid LPAR Process ID %u\n",
+			H_MODIFY_VAS_WINDOW, lpid, win->winid);
+		return -EINVAL;
+	case H_P3:
+		/* LPAR thread ID is deprecated on P10 */
+		pr_err("HCALL(%x): Invalid LPAR Thread ID for window(%u)\n",
+			H_MODIFY_VAS_WINDOW, win->winid);
+		return -EINVAL;
+	case H_STATE:
+		pr_err("HCALL(%x): Jobs in progress, Can't modify window(%u)\n",
+			H_MODIFY_VAS_WINDOW, win->winid);
+		return -EBUSY;
+	default:
+		pr_err("HCALL(%x): Unexpected error %lld for window(%u)\n",
+			H_MODIFY_VAS_WINDOW, rc, win->winid);
+		return -EIO;
+	}
+}
+
+/*
+ * This HCALL is used to determine the capabilities that pHyp provides.
+ * @hcall: H_QUERY_VAS_CAPABILITIES or H_QUERY_NX_CAPABILITIES
+ * @query_type: If 0 is passed, phyp returns the overall capabilities
+ *		which provides all feature(s) that are available. Then
+ *		query phyp to get the corresponding capabilities for
+ *		the specific feature.
+ *		Example: H_QUERY_VAS_CAPABILITIES provides VAS GZIP QoS
+ *			and VAS GZIP Default capabilities.
+ *			H_QUERY_NX_CAPABILITIES provides NX GZIP
+ *			capabilities.
+ * @result: Return buffer to save capabilities.
+ */
+int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
+					u64 result)
+{
+	int64_t rc;
+
+	rc = plpar_hcall_norets(hcall, query_type, result);
+
+	switch (rc) {
+	case H_SUCCESS:
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%llx): Invalid query type %u\n", hcall,
+			query_type);
+		return -EINVAL;
+	case H_PRIVILEGE:
+		pr_err("HCALL(%llx): Invalid result buffer 0x%llx\n",
+			hcall, result);
+		return -EACCES;
+	default:
+		pr_err("HCALL(%llx): Unexpected error %lld\n", hcall, rc);
+		return -EIO;
+	}
+}
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 10/16] powerpc/pseries/vas: Implement getting capabilities from hypervisor
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:38   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:38 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


The hypervisor provides VAS capabilities for GZIP default and QoS
features. These capabilities gives information for the specific
features such as total number of credits available in LPAR,
maximum credits allowed per window, maximum credits allowed in
LPAR, whether usermode copy/paste is supported, and etc.

This patch adds the following:
- Retrieve all features that are provided by hypervisor using
  H_QUERY_VAS_CAPABILITIES hcall with 0 as feature type.
- Retrieve capabilities for the specific feature using the same
  hcall and the feature type (1 for QoS and 2 for default type).

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/vas.c | 127 +++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
index 06960151477c..9976f6b614b9 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -30,6 +30,13 @@
 /* phyp allows one credit per window right now */
 #define DEF_WIN_CREDS		1
 
+static struct vas_all_caps caps_all;
+static bool copypaste_feat;
+
+static struct vas_caps vascaps[VAS_MAX_FEAT_TYPE];
+
+static DEFINE_MUTEX(vas_pseries_mutex);
+
 static int64_t hcall_return_busy_check(int64_t rc)
 {
 	/* Check if we are stalled for some time */
@@ -215,3 +222,123 @@ int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
 		return -EIO;
 	}
 }
+
+/*
+ * Get the specific capabilities based on the feature type.
+ * Right now supports GZIP default and GZIP QoS capabilities.
+ */
+static int get_vas_capabilities(u8 feat, enum vas_cop_feat_type type,
+				struct hv_vas_ct_caps *hv_caps)
+{
+	struct vas_ct_caps *caps;
+	struct vas_caps *vcaps;
+	int rc = 0;
+
+	vcaps = &vascaps[type];
+	memset(vcaps, 0, sizeof(*vcaps));
+	INIT_LIST_HEAD(&vcaps->list);
+
+	caps = &vcaps->caps;
+
+	rc = plpar_vas_query_capabilities(H_QUERY_VAS_CAPABILITIES, feat,
+					  (u64)virt_to_phys(hv_caps));
+	if (rc)
+		return rc;
+
+	caps->user_mode = hv_caps->user_mode;
+	if (!(caps->user_mode & VAS_COPY_PASTE_USER_MODE)) {
+		pr_err("User space COPY/PASTE is not supported\n");
+		return -ENOTSUPP;
+	}
+
+	snprintf(caps->name, VAS_DESCR_LEN + 1, "%.8s",
+		 (char *)&hv_caps->descriptor);
+	caps->descriptor = be64_to_cpu(hv_caps->descriptor);
+	caps->win_type = hv_caps->win_type;
+	if (caps->win_type >= VAS_MAX_FEAT_TYPE) {
+		pr_err("Unsupported window type %u\n", caps->win_type);
+		return -EINVAL;
+	}
+	caps->max_lpar_creds = be16_to_cpu(hv_caps->max_lpar_creds);
+	caps->max_win_creds = be16_to_cpu(hv_caps->max_win_creds);
+	atomic_set(&caps->target_lpar_creds,
+		   be16_to_cpu(hv_caps->target_lpar_creds));
+	if (feat == VAS_GZIP_DEF_FEAT) {
+		caps->def_lpar_creds = be16_to_cpu(hv_caps->def_lpar_creds);
+
+		if (caps->max_win_creds < DEF_WIN_CREDS) {
+			pr_err("Window creds(%u) > max allowed window creds(%u)\n",
+			       DEF_WIN_CREDS, caps->max_win_creds);
+			return -EINVAL;
+		}
+	}
+
+	copypaste_feat = true;
+
+	return 0;
+}
+
+static int __init pseries_vas_init(void)
+{
+	struct hv_vas_ct_caps *hv_ct_caps;
+	struct hv_vas_all_caps *hv_caps;
+	int rc;
+
+	/*
+	 * Linux supports user space COPY/PASTE only with Radix
+	 */
+	if (!radix_enabled()) {
+		pr_err("API is supported only with radix page tables\n");
+		return -ENOTSUPP;
+	}
+
+	hv_caps = kmalloc(sizeof(*hv_caps), GFP_KERNEL);
+	if (!hv_caps)
+		return -ENOMEM;
+	/*
+	 * Get VAS overall capabilities by passing 0 to feature type.
+	 */
+	rc = plpar_vas_query_capabilities(H_QUERY_VAS_CAPABILITIES, 0,
+					  (u64)virt_to_phys(hv_caps));
+	if (rc)
+		goto out;
+
+	snprintf(caps_all.name, VAS_DESCR_LEN, "%.7s",
+		 (char *)&hv_caps->descriptor);
+	caps_all.descriptor = be64_to_cpu(hv_caps->descriptor);
+	caps_all.feat_type = be64_to_cpu(hv_caps->feat_type);
+
+	hv_ct_caps = kmalloc(sizeof(*hv_ct_caps), GFP_KERNEL);
+	if (!hv_ct_caps) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	/*
+	 * QOS capabilities available
+	 */
+	if (caps_all.feat_type & VAS_GZIP_QOS_FEAT_BIT) {
+		rc = get_vas_capabilities(VAS_GZIP_QOS_FEAT,
+					  VAS_GZIP_QOS_FEAT_TYPE, hv_ct_caps);
+
+		if (rc)
+			goto out_ct;
+	}
+	/*
+	 * Default capabilities available
+	 */
+	if (caps_all.feat_type & VAS_GZIP_DEF_FEAT_BIT) {
+		rc = get_vas_capabilities(VAS_GZIP_DEF_FEAT,
+					  VAS_GZIP_DEF_FEAT_TYPE, hv_ct_caps);
+		if (rc)
+			goto out_ct;
+	}
+
+	pr_info("GZIP feature is available\n");
+
+out_ct:
+	kfree(hv_ct_caps);
+out:
+	kfree(hv_caps);
+	return rc;
+}
+machine_device_initcall(pseries, pseries_vas_init);
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 10/16] powerpc/pseries/vas: Implement getting capabilities from hypervisor
@ 2021-05-21  9:38   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:38 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


The hypervisor provides VAS capabilities for GZIP default and QoS
features. These capabilities gives information for the specific
features such as total number of credits available in LPAR,
maximum credits allowed per window, maximum credits allowed in
LPAR, whether usermode copy/paste is supported, and etc.

This patch adds the following:
- Retrieve all features that are provided by hypervisor using
  H_QUERY_VAS_CAPABILITIES hcall with 0 as feature type.
- Retrieve capabilities for the specific feature using the same
  hcall and the feature type (1 for QoS and 2 for default type).

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/vas.c | 127 +++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
index 06960151477c..9976f6b614b9 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -30,6 +30,13 @@
 /* phyp allows one credit per window right now */
 #define DEF_WIN_CREDS		1
 
+static struct vas_all_caps caps_all;
+static bool copypaste_feat;
+
+static struct vas_caps vascaps[VAS_MAX_FEAT_TYPE];
+
+static DEFINE_MUTEX(vas_pseries_mutex);
+
 static int64_t hcall_return_busy_check(int64_t rc)
 {
 	/* Check if we are stalled for some time */
@@ -215,3 +222,123 @@ int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
 		return -EIO;
 	}
 }
+
+/*
+ * Get the specific capabilities based on the feature type.
+ * Right now supports GZIP default and GZIP QoS capabilities.
+ */
+static int get_vas_capabilities(u8 feat, enum vas_cop_feat_type type,
+				struct hv_vas_ct_caps *hv_caps)
+{
+	struct vas_ct_caps *caps;
+	struct vas_caps *vcaps;
+	int rc = 0;
+
+	vcaps = &vascaps[type];
+	memset(vcaps, 0, sizeof(*vcaps));
+	INIT_LIST_HEAD(&vcaps->list);
+
+	caps = &vcaps->caps;
+
+	rc = plpar_vas_query_capabilities(H_QUERY_VAS_CAPABILITIES, feat,
+					  (u64)virt_to_phys(hv_caps));
+	if (rc)
+		return rc;
+
+	caps->user_mode = hv_caps->user_mode;
+	if (!(caps->user_mode & VAS_COPY_PASTE_USER_MODE)) {
+		pr_err("User space COPY/PASTE is not supported\n");
+		return -ENOTSUPP;
+	}
+
+	snprintf(caps->name, VAS_DESCR_LEN + 1, "%.8s",
+		 (char *)&hv_caps->descriptor);
+	caps->descriptor = be64_to_cpu(hv_caps->descriptor);
+	caps->win_type = hv_caps->win_type;
+	if (caps->win_type >= VAS_MAX_FEAT_TYPE) {
+		pr_err("Unsupported window type %u\n", caps->win_type);
+		return -EINVAL;
+	}
+	caps->max_lpar_creds = be16_to_cpu(hv_caps->max_lpar_creds);
+	caps->max_win_creds = be16_to_cpu(hv_caps->max_win_creds);
+	atomic_set(&caps->target_lpar_creds,
+		   be16_to_cpu(hv_caps->target_lpar_creds));
+	if (feat == VAS_GZIP_DEF_FEAT) {
+		caps->def_lpar_creds = be16_to_cpu(hv_caps->def_lpar_creds);
+
+		if (caps->max_win_creds < DEF_WIN_CREDS) {
+			pr_err("Window creds(%u) > max allowed window creds(%u)\n",
+			       DEF_WIN_CREDS, caps->max_win_creds);
+			return -EINVAL;
+		}
+	}
+
+	copypaste_feat = true;
+
+	return 0;
+}
+
+static int __init pseries_vas_init(void)
+{
+	struct hv_vas_ct_caps *hv_ct_caps;
+	struct hv_vas_all_caps *hv_caps;
+	int rc;
+
+	/*
+	 * Linux supports user space COPY/PASTE only with Radix
+	 */
+	if (!radix_enabled()) {
+		pr_err("API is supported only with radix page tables\n");
+		return -ENOTSUPP;
+	}
+
+	hv_caps = kmalloc(sizeof(*hv_caps), GFP_KERNEL);
+	if (!hv_caps)
+		return -ENOMEM;
+	/*
+	 * Get VAS overall capabilities by passing 0 to feature type.
+	 */
+	rc = plpar_vas_query_capabilities(H_QUERY_VAS_CAPABILITIES, 0,
+					  (u64)virt_to_phys(hv_caps));
+	if (rc)
+		goto out;
+
+	snprintf(caps_all.name, VAS_DESCR_LEN, "%.7s",
+		 (char *)&hv_caps->descriptor);
+	caps_all.descriptor = be64_to_cpu(hv_caps->descriptor);
+	caps_all.feat_type = be64_to_cpu(hv_caps->feat_type);
+
+	hv_ct_caps = kmalloc(sizeof(*hv_ct_caps), GFP_KERNEL);
+	if (!hv_ct_caps) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	/*
+	 * QOS capabilities available
+	 */
+	if (caps_all.feat_type & VAS_GZIP_QOS_FEAT_BIT) {
+		rc = get_vas_capabilities(VAS_GZIP_QOS_FEAT,
+					  VAS_GZIP_QOS_FEAT_TYPE, hv_ct_caps);
+
+		if (rc)
+			goto out_ct;
+	}
+	/*
+	 * Default capabilities available
+	 */
+	if (caps_all.feat_type & VAS_GZIP_DEF_FEAT_BIT) {
+		rc = get_vas_capabilities(VAS_GZIP_DEF_FEAT,
+					  VAS_GZIP_DEF_FEAT_TYPE, hv_ct_caps);
+		if (rc)
+			goto out_ct;
+	}
+
+	pr_info("GZIP feature is available\n");
+
+out_ct:
+	kfree(hv_ct_caps);
+out:
+	kfree(hv_caps);
+	return rc;
+}
+machine_device_initcall(pseries, pseries_vas_init);
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 11/16] powerpc/pseries/vas: Integrate API with open/close windows
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:39   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:39 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


This patch adds VAS window allocatioa/close with the corresponding
HCALLs. Also changes to integrate with the existing user space VAS
API and provide register/unregister functions to NX pseries driver.

The driver register function is used to create the user space
interface (/dev/crypto/nx-gzip) and unregister to remove this entry.

The user space process opens this device node and makes an ioctl
to allocate VAS window. The close interface is used to deallocate
window.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h          |   5 +
 arch/powerpc/platforms/pseries/Makefile |   1 +
 arch/powerpc/platforms/pseries/vas.c    | 217 ++++++++++++++++++++++++
 3 files changed, 223 insertions(+)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 371f62d99174..d38372bcb3f8 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -279,6 +279,11 @@ struct vas_all_caps {
 	u64     feat_type;
 };
 
+int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
+				 u64 result);
+int vas_register_api_pseries(struct module *mod,
+			     enum vas_cop_type cop_type, const char *name);
+void vas_unregister_api_pseries(void);
 #endif
 
 /*
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index c8a2b0b05ac0..4cda0ef87be0 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_PPC_SVM)		+= svm.o
 obj-$(CONFIG_FA_DUMP)		+= rtas-fadump.o
 
 obj-$(CONFIG_SUSPEND)		+= suspend.o
+obj-$(CONFIG_PPC_VAS)		+= vas.o
diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
index 9976f6b614b9..ef0c455f6e93 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -222,6 +222,223 @@ int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
 		return -EIO;
 	}
 }
+EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
+
+/*
+ * Allocate window and setup IRQ mapping.
+ */
+static int allocate_setup_window(struct vas_window *txwin,
+				 u64 *domain, u8 wintype)
+{
+	int rc;
+
+	rc = plpar_vas_allocate_window(txwin, domain, wintype, DEF_WIN_CREDS);
+	if (rc)
+		return rc;
+
+	txwin->wcreds_max = DEF_WIN_CREDS;
+
+	return 0;
+}
+
+static struct vas_window *vas_allocate_window(struct vas_tx_win_open_attr *uattr,
+					      enum vas_cop_type cop_type)
+{
+	long domain[PLPAR_HCALL9_BUFSIZE] = {VAS_DEFAULT_DOMAIN_ID};
+	struct vas_ct_caps *ct_caps;
+	struct vas_caps *caps;
+	struct vas_window *txwin;
+	int rc;
+
+	txwin = kzalloc(sizeof(*txwin), GFP_KERNEL);
+	if (!txwin)
+		return ERR_PTR(-ENOMEM);
+
+	/*
+	 * A VAS window can have many credits which means that many
+	 * requests can be issued simultaneously. But phyp restricts
+	 * one credit per window.
+	 * phyp introduces 2 different types of credits:
+	 * Default credit type (Uses normal priority FIFO):
+	 *	A limited number of credits are assigned to partitions
+	 *	based on processor entitlement. But these credits may be
+	 *	over-committed on a system depends on whether the CPUs
+	 *	are in shared or dedicated modes - that is, more requests
+	 *	may be issued across the system than NX can service at
+	 *	once which can result in paste command failure (RMA_busy).
+	 *	Then the process has to resend requests or fall-back to
+	 *	SW compression.
+	 * Quality of Service (QoS) credit type (Uses high priority FIFO):
+	 *	To avoid NX HW contention, the system admins can assign
+	 *	QoS credits for each LPAR so that this partition is
+	 *	guaranteed access to NX resources. These credits are
+	 *	assigned to partitions via the HMC.
+	 *	Refer PAPR for more information.
+	 *
+	 * Allocate window with QoS credits if user requested. Otherwise
+	 * default credits are used.
+	 */
+	if (uattr->flags & VAS_TX_WIN_FLAG_QOS_CREDIT)
+		caps = &vascaps[VAS_GZIP_QOS_FEAT_TYPE];
+	else
+		caps = &vascaps[VAS_GZIP_DEF_FEAT_TYPE];
+
+	ct_caps = &caps->caps;
+
+	if (atomic_inc_return(&ct_caps->used_lpar_creds) >
+			atomic_read(&ct_caps->target_lpar_creds)) {
+		pr_err("Credits are not available to allocate window\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * The user space is requesting to allocate a window on a VAS
+	 * instance (or chip) where the process is executing.
+	 * On powerVM, domain values are passed to pHyp to select chip /
+	 * VAS instance. Useful if the process is affinity to NUMA node.
+	 * pHyp selects VAS instance if VAS_DEFAULT_DOMAIN_ID (-1) is
+	 * passed for domain values.
+	 */
+	if (uattr->vas_id == -1) {
+		/*
+		 * To allocate VAS window, pass same domain values returned
+		 * from this HCALL.
+		 */
+		rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, domain,
+				  VPHN_FLAG_VCPU, smp_processor_id());
+		if (rc != H_SUCCESS) {
+			pr_err("HCALL(%x): failed with ret(%d)\n",
+			       H_HOME_NODE_ASSOCIATIVITY, rc);
+			goto out;
+		}
+	}
+
+	/*
+	 * Allocate / Deallocate window HCALLs and setup / free IRQs
+	 * have to be protected with mutex.
+	 * Open VAS window: Allocate window HCALL and setup IRQ
+	 * Close VAS window: Deallocate window HCALL and free IRQ
+	 *	The hypervisor waits until all NX requests are
+	 *	completed before closing the window. So expects OS
+	 *	to handle NX faults, means IRQ can be freed only
+	 *	after the deallocate window HCALL is returned.
+	 * So once the window is closed with deallocate HCALL before
+	 * the IRQ is freed, it can be assigned to new allocate
+	 * HCALL with the same fault IRQ by the hypervisor. It can
+	 * result in setup IRQ fail for the new window since the
+	 * same fault IRQ is not freed by the OS.
+	 */
+	mutex_lock(&vas_pseries_mutex);
+	rc = allocate_setup_window(txwin, (u64 *)&domain[0],
+				   ct_caps->win_type);
+	mutex_unlock(&vas_pseries_mutex);
+	if (rc)
+		goto out;
+
+	/*
+	 * Modify window and it is ready to use.
+	 */
+	rc = plpar_vas_modify_window(txwin);
+	if (!rc)
+		rc = vas_reference_pid_mm(&txwin->task_ref);
+	if (rc)
+		goto out_free;
+
+	txwin->lpar.win_type = ct_caps->win_type;
+	mutex_lock(&vas_pseries_mutex);
+	list_add(&txwin->lpar.win_list, &caps->list);
+	mutex_unlock(&vas_pseries_mutex);
+
+	return txwin;
+
+out_free:
+	plpar_vas_deallocate_window(txwin->winid);
+out:
+	atomic_dec(&ct_caps->used_lpar_creds);
+	kfree(txwin);
+	return ERR_PTR(rc);
+}
+
+static u64 vas_paste_address(void *addr)
+{
+	struct vas_window *win = addr;
+
+	return win->lpar.win_addr;
+}
+
+static int deallocate_free_window(struct vas_window *win)
+{
+	int rc = 0;
+
+	rc = plpar_vas_deallocate_window(win->winid);
+
+	return rc;
+}
+
+static int vas_deallocate_window(void *addr)
+{
+	struct vas_window *win = (struct vas_window *)addr;
+	struct vas_ct_caps *caps;
+	int rc = 0;
+
+	if (!win)
+		return -EINVAL;
+
+	/* Should not happen */
+	if (win->lpar.win_type >= VAS_MAX_FEAT_TYPE) {
+		pr_err("Window (%u): Invalid window type %u\n",
+				win->winid, win->lpar.win_type);
+		return -EINVAL;
+	}
+
+	caps = &vascaps[win->lpar.win_type].caps;
+	mutex_lock(&vas_pseries_mutex);
+	rc = deallocate_free_window(win);
+	if (rc) {
+		mutex_unlock(&vas_pseries_mutex);
+		return rc;
+	}
+
+	list_del(&win->lpar.win_list);
+	atomic_dec(&caps->used_lpar_creds);
+	mutex_unlock(&vas_pseries_mutex);
+
+	vas_drop_reference_pid_mm(&win->task_ref);
+
+	kfree(win);
+	return 0;
+}
+
+static struct vas_user_win_ops vops_pseries = {
+	.open_win	= vas_allocate_window,	/* Open and configure window */
+	.paste_addr	= vas_paste_address,	/* To do copy/paste */
+	.close_win	= vas_deallocate_window, /* Close window */
+};
+
+/*
+ * Supporting only nx-gzip coprocessor type now, but this API code
+ * extended to other coprocessor types later.
+ */
+int vas_register_api_pseries(struct module *mod, enum vas_cop_type cop_type,
+			     const char *name)
+{
+	int rc;
+
+	if (!copypaste_feat)
+		return -ENOTSUPP;
+
+	rc = vas_register_coproc_api(mod, cop_type, name, &vops_pseries);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(vas_register_api_pseries);
+
+void vas_unregister_api_pseries(void)
+{
+	vas_unregister_coproc_api();
+}
+EXPORT_SYMBOL_GPL(vas_unregister_api_pseries);
 
 /*
  * Get the specific capabilities based on the feature type.
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 11/16] powerpc/pseries/vas: Integrate API with open/close windows
@ 2021-05-21  9:39   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:39 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


This patch adds VAS window allocatioa/close with the corresponding
HCALLs. Also changes to integrate with the existing user space VAS
API and provide register/unregister functions to NX pseries driver.

The driver register function is used to create the user space
interface (/dev/crypto/nx-gzip) and unregister to remove this entry.

The user space process opens this device node and makes an ioctl
to allocate VAS window. The close interface is used to deallocate
window.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/include/asm/vas.h          |   5 +
 arch/powerpc/platforms/pseries/Makefile |   1 +
 arch/powerpc/platforms/pseries/vas.c    | 217 ++++++++++++++++++++++++
 3 files changed, 223 insertions(+)

diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
index 371f62d99174..d38372bcb3f8 100644
--- a/arch/powerpc/include/asm/vas.h
+++ b/arch/powerpc/include/asm/vas.h
@@ -279,6 +279,11 @@ struct vas_all_caps {
 	u64     feat_type;
 };
 
+int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
+				 u64 result);
+int vas_register_api_pseries(struct module *mod,
+			     enum vas_cop_type cop_type, const char *name);
+void vas_unregister_api_pseries(void);
 #endif
 
 /*
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index c8a2b0b05ac0..4cda0ef87be0 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_PPC_SVM)		+= svm.o
 obj-$(CONFIG_FA_DUMP)		+= rtas-fadump.o
 
 obj-$(CONFIG_SUSPEND)		+= suspend.o
+obj-$(CONFIG_PPC_VAS)		+= vas.o
diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
index 9976f6b614b9..ef0c455f6e93 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -222,6 +222,223 @@ int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
 		return -EIO;
 	}
 }
+EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
+
+/*
+ * Allocate window and setup IRQ mapping.
+ */
+static int allocate_setup_window(struct vas_window *txwin,
+				 u64 *domain, u8 wintype)
+{
+	int rc;
+
+	rc = plpar_vas_allocate_window(txwin, domain, wintype, DEF_WIN_CREDS);
+	if (rc)
+		return rc;
+
+	txwin->wcreds_max = DEF_WIN_CREDS;
+
+	return 0;
+}
+
+static struct vas_window *vas_allocate_window(struct vas_tx_win_open_attr *uattr,
+					      enum vas_cop_type cop_type)
+{
+	long domain[PLPAR_HCALL9_BUFSIZE] = {VAS_DEFAULT_DOMAIN_ID};
+	struct vas_ct_caps *ct_caps;
+	struct vas_caps *caps;
+	struct vas_window *txwin;
+	int rc;
+
+	txwin = kzalloc(sizeof(*txwin), GFP_KERNEL);
+	if (!txwin)
+		return ERR_PTR(-ENOMEM);
+
+	/*
+	 * A VAS window can have many credits which means that many
+	 * requests can be issued simultaneously. But phyp restricts
+	 * one credit per window.
+	 * phyp introduces 2 different types of credits:
+	 * Default credit type (Uses normal priority FIFO):
+	 *	A limited number of credits are assigned to partitions
+	 *	based on processor entitlement. But these credits may be
+	 *	over-committed on a system depends on whether the CPUs
+	 *	are in shared or dedicated modes - that is, more requests
+	 *	may be issued across the system than NX can service at
+	 *	once which can result in paste command failure (RMA_busy).
+	 *	Then the process has to resend requests or fall-back to
+	 *	SW compression.
+	 * Quality of Service (QoS) credit type (Uses high priority FIFO):
+	 *	To avoid NX HW contention, the system admins can assign
+	 *	QoS credits for each LPAR so that this partition is
+	 *	guaranteed access to NX resources. These credits are
+	 *	assigned to partitions via the HMC.
+	 *	Refer PAPR for more information.
+	 *
+	 * Allocate window with QoS credits if user requested. Otherwise
+	 * default credits are used.
+	 */
+	if (uattr->flags & VAS_TX_WIN_FLAG_QOS_CREDIT)
+		caps = &vascaps[VAS_GZIP_QOS_FEAT_TYPE];
+	else
+		caps = &vascaps[VAS_GZIP_DEF_FEAT_TYPE];
+
+	ct_caps = &caps->caps;
+
+	if (atomic_inc_return(&ct_caps->used_lpar_creds) >
+			atomic_read(&ct_caps->target_lpar_creds)) {
+		pr_err("Credits are not available to allocate window\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * The user space is requesting to allocate a window on a VAS
+	 * instance (or chip) where the process is executing.
+	 * On powerVM, domain values are passed to pHyp to select chip /
+	 * VAS instance. Useful if the process is affinity to NUMA node.
+	 * pHyp selects VAS instance if VAS_DEFAULT_DOMAIN_ID (-1) is
+	 * passed for domain values.
+	 */
+	if (uattr->vas_id == -1) {
+		/*
+		 * To allocate VAS window, pass same domain values returned
+		 * from this HCALL.
+		 */
+		rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, domain,
+				  VPHN_FLAG_VCPU, smp_processor_id());
+		if (rc != H_SUCCESS) {
+			pr_err("HCALL(%x): failed with ret(%d)\n",
+			       H_HOME_NODE_ASSOCIATIVITY, rc);
+			goto out;
+		}
+	}
+
+	/*
+	 * Allocate / Deallocate window HCALLs and setup / free IRQs
+	 * have to be protected with mutex.
+	 * Open VAS window: Allocate window HCALL and setup IRQ
+	 * Close VAS window: Deallocate window HCALL and free IRQ
+	 *	The hypervisor waits until all NX requests are
+	 *	completed before closing the window. So expects OS
+	 *	to handle NX faults, means IRQ can be freed only
+	 *	after the deallocate window HCALL is returned.
+	 * So once the window is closed with deallocate HCALL before
+	 * the IRQ is freed, it can be assigned to new allocate
+	 * HCALL with the same fault IRQ by the hypervisor. It can
+	 * result in setup IRQ fail for the new window since the
+	 * same fault IRQ is not freed by the OS.
+	 */
+	mutex_lock(&vas_pseries_mutex);
+	rc = allocate_setup_window(txwin, (u64 *)&domain[0],
+				   ct_caps->win_type);
+	mutex_unlock(&vas_pseries_mutex);
+	if (rc)
+		goto out;
+
+	/*
+	 * Modify window and it is ready to use.
+	 */
+	rc = plpar_vas_modify_window(txwin);
+	if (!rc)
+		rc = vas_reference_pid_mm(&txwin->task_ref);
+	if (rc)
+		goto out_free;
+
+	txwin->lpar.win_type = ct_caps->win_type;
+	mutex_lock(&vas_pseries_mutex);
+	list_add(&txwin->lpar.win_list, &caps->list);
+	mutex_unlock(&vas_pseries_mutex);
+
+	return txwin;
+
+out_free:
+	plpar_vas_deallocate_window(txwin->winid);
+out:
+	atomic_dec(&ct_caps->used_lpar_creds);
+	kfree(txwin);
+	return ERR_PTR(rc);
+}
+
+static u64 vas_paste_address(void *addr)
+{
+	struct vas_window *win = addr;
+
+	return win->lpar.win_addr;
+}
+
+static int deallocate_free_window(struct vas_window *win)
+{
+	int rc = 0;
+
+	rc = plpar_vas_deallocate_window(win->winid);
+
+	return rc;
+}
+
+static int vas_deallocate_window(void *addr)
+{
+	struct vas_window *win = (struct vas_window *)addr;
+	struct vas_ct_caps *caps;
+	int rc = 0;
+
+	if (!win)
+		return -EINVAL;
+
+	/* Should not happen */
+	if (win->lpar.win_type >= VAS_MAX_FEAT_TYPE) {
+		pr_err("Window (%u): Invalid window type %u\n",
+				win->winid, win->lpar.win_type);
+		return -EINVAL;
+	}
+
+	caps = &vascaps[win->lpar.win_type].caps;
+	mutex_lock(&vas_pseries_mutex);
+	rc = deallocate_free_window(win);
+	if (rc) {
+		mutex_unlock(&vas_pseries_mutex);
+		return rc;
+	}
+
+	list_del(&win->lpar.win_list);
+	atomic_dec(&caps->used_lpar_creds);
+	mutex_unlock(&vas_pseries_mutex);
+
+	vas_drop_reference_pid_mm(&win->task_ref);
+
+	kfree(win);
+	return 0;
+}
+
+static struct vas_user_win_ops vops_pseries = {
+	.open_win	= vas_allocate_window,	/* Open and configure window */
+	.paste_addr	= vas_paste_address,	/* To do copy/paste */
+	.close_win	= vas_deallocate_window, /* Close window */
+};
+
+/*
+ * Supporting only nx-gzip coprocessor type now, but this API code
+ * extended to other coprocessor types later.
+ */
+int vas_register_api_pseries(struct module *mod, enum vas_cop_type cop_type,
+			     const char *name)
+{
+	int rc;
+
+	if (!copypaste_feat)
+		return -ENOTSUPP;
+
+	rc = vas_register_coproc_api(mod, cop_type, name, &vops_pseries);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(vas_register_api_pseries);
+
+void vas_unregister_api_pseries(void)
+{
+	vas_unregister_coproc_api();
+}
+EXPORT_SYMBOL_GPL(vas_unregister_api_pseries);
 
 /*
  * Get the specific capabilities based on the feature type.
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 12/16] powerpc/pseries/vas: Setup IRQ and fault handling
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:39   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:39 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


NX generates an interrupt when sees a fault on the user space
buffer and the hypervisor forwards that interrupt to OS. Then
the kernel handles the interrupt by issuing H_GET_NX_FAULT hcall
to retrieve the fault CRB information.

This patch also adds changes to setup and free IRQ per each
window and also handles the fault by updating the CSB.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/vas.c | 111 +++++++++++++++++++++++++++
 1 file changed, 111 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
index ef0c455f6e93..31dc17573f50 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -224,6 +224,62 @@ int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
 }
 EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
 
+/*
+ * HCALL to get fault CRB from pHyp.
+ */
+static int plpar_get_nx_fault(u32 winid, u64 buffer)
+{
+	int64_t rc;
+
+	rc = plpar_hcall_norets(H_GET_NX_FAULT, winid, buffer);
+
+	switch (rc) {
+	case H_SUCCESS:
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%x): Invalid window ID %u\n", H_GET_NX_FAULT,
+		       winid);
+		return -EINVAL;
+	case H_STATE:
+		pr_err("HCALL(%x): No outstanding faults for window ID %u\n",
+		       H_GET_NX_FAULT, winid);
+		return -EINVAL;
+	case H_PRIVILEGE:
+		pr_err("HCALL(%x): Window(%u): Invalid fault buffer 0x%llx\n",
+		       H_GET_NX_FAULT, winid, buffer);
+		return -EACCES;
+	default:
+		pr_err("HCALL(%x): Unexpected error %lld for window(%u)\n",
+		       H_GET_NX_FAULT, rc, winid);
+		return -EIO;
+	}
+}
+
+/*
+ * Handle the fault interrupt.
+ * When the fault interrupt is received for each window, query pHyp to get
+ * the fault CRB on the specific fault. Then process the CRB by updating
+ * CSB or send signal if the user space CSB is invalid.
+ * Note: pHyp forwards an interrupt for each fault request. So one fault
+ *	CRB to process for each H_GET_NX_FAULT HCALL.
+ */
+irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
+{
+	struct vas_window *txwin = data;
+	struct coprocessor_request_block crb;
+	struct vas_user_win_ref *tsk_ref;
+	int rc;
+
+	rc = plpar_get_nx_fault(txwin->winid, (u64)virt_to_phys(&crb));
+	if (!rc) {
+		tsk_ref = &txwin->task_ref;
+		vas_dump_crb(&crb);
+		vas_update_csb(&crb, tsk_ref);
+	}
+
+	return IRQ_HANDLED;
+}
+
 /*
  * Allocate window and setup IRQ mapping.
  */
@@ -235,10 +291,51 @@ static int allocate_setup_window(struct vas_window *txwin,
 	rc = plpar_vas_allocate_window(txwin, domain, wintype, DEF_WIN_CREDS);
 	if (rc)
 		return rc;
+	/*
+	 * On powerVM, pHyp setup and forwards the fault interrupt per
+	 * window. So the IRQ setup and fault handling will be done for
+	 * each open window separately.
+	 */
+	txwin->lpar.fault_virq = irq_create_mapping(NULL,
+						    txwin->lpar.fault_irq);
+	if (!txwin->lpar.fault_virq) {
+		pr_err("Failed irq mapping %d\n", txwin->lpar.fault_irq);
+		rc = -EINVAL;
+		goto out_win;
+	}
+
+	txwin->lpar.name = kasprintf(GFP_KERNEL, "vas-win-%d", txwin->winid);
+	if (!txwin->lpar.name) {
+		rc = -ENOMEM;
+		goto out_irq;
+	}
+
+	rc = request_threaded_irq(txwin->lpar.fault_virq, NULL,
+				  pseries_vas_fault_thread_fn, IRQF_ONESHOT,
+				  txwin->lpar.name, txwin);
+	if (rc) {
+		pr_err("VAS-Window[%d]: Request IRQ(%u) failed with %d\n",
+		       txwin->winid, txwin->lpar.fault_virq, rc);
+		goto out_free;
+	}
 
 	txwin->wcreds_max = DEF_WIN_CREDS;
 
 	return 0;
+out_free:
+	kfree(txwin->lpar.name);
+out_irq:
+	irq_dispose_mapping(txwin->lpar.fault_virq);
+out_win:
+	plpar_vas_deallocate_window(txwin->winid);
+	return rc;
+}
+
+static inline void free_irq_setup(struct vas_window *txwin)
+{
+	free_irq(txwin->lpar.fault_virq, txwin);
+	irq_dispose_mapping(txwin->lpar.fault_virq);
+	kfree(txwin->lpar.name);
 }
 
 static struct vas_window *vas_allocate_window(struct vas_tx_win_open_attr *uattr,
@@ -353,6 +450,11 @@ static struct vas_window *vas_allocate_window(struct vas_tx_win_open_attr *uattr
 	return txwin;
 
 out_free:
+	/*
+	 * Window is not operational. Free IRQ before closing
+	 * window so that do not have to hold mutex.
+	 */
+	free_irq_setup(txwin);
 	plpar_vas_deallocate_window(txwin->winid);
 out:
 	atomic_dec(&ct_caps->used_lpar_creds);
@@ -371,7 +473,16 @@ static int deallocate_free_window(struct vas_window *win)
 {
 	int rc = 0;
 
+	/*
+	 * Free IRQ after executing H_DEALLOCATE_VAS_WINDOW HCALL
+	 * to close the window. pHyp waits for all requests including
+	 * faults are processed before closing the window - Means all
+	 * credits are returned. In the case of fault request, credit
+	 * is returned after OS issues H_GET_NX_FAULT HCALL.
+	 */
 	rc = plpar_vas_deallocate_window(win->winid);
+	if (!rc)
+		free_irq_setup(win);
 
 	return rc;
 }
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 12/16] powerpc/pseries/vas: Setup IRQ and fault handling
@ 2021-05-21  9:39   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:39 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


NX generates an interrupt when sees a fault on the user space
buffer and the hypervisor forwards that interrupt to OS. Then
the kernel handles the interrupt by issuing H_GET_NX_FAULT hcall
to retrieve the fault CRB information.

This patch also adds changes to setup and free IRQ per each
window and also handles the fault by updating the CSB.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/vas.c | 111 +++++++++++++++++++++++++++
 1 file changed, 111 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
index ef0c455f6e93..31dc17573f50 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -224,6 +224,62 @@ int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
 }
 EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
 
+/*
+ * HCALL to get fault CRB from pHyp.
+ */
+static int plpar_get_nx_fault(u32 winid, u64 buffer)
+{
+	int64_t rc;
+
+	rc = plpar_hcall_norets(H_GET_NX_FAULT, winid, buffer);
+
+	switch (rc) {
+	case H_SUCCESS:
+		return 0;
+	case H_PARAMETER:
+		pr_err("HCALL(%x): Invalid window ID %u\n", H_GET_NX_FAULT,
+		       winid);
+		return -EINVAL;
+	case H_STATE:
+		pr_err("HCALL(%x): No outstanding faults for window ID %u\n",
+		       H_GET_NX_FAULT, winid);
+		return -EINVAL;
+	case H_PRIVILEGE:
+		pr_err("HCALL(%x): Window(%u): Invalid fault buffer 0x%llx\n",
+		       H_GET_NX_FAULT, winid, buffer);
+		return -EACCES;
+	default:
+		pr_err("HCALL(%x): Unexpected error %lld for window(%u)\n",
+		       H_GET_NX_FAULT, rc, winid);
+		return -EIO;
+	}
+}
+
+/*
+ * Handle the fault interrupt.
+ * When the fault interrupt is received for each window, query pHyp to get
+ * the fault CRB on the specific fault. Then process the CRB by updating
+ * CSB or send signal if the user space CSB is invalid.
+ * Note: pHyp forwards an interrupt for each fault request. So one fault
+ *	CRB to process for each H_GET_NX_FAULT HCALL.
+ */
+irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
+{
+	struct vas_window *txwin = data;
+	struct coprocessor_request_block crb;
+	struct vas_user_win_ref *tsk_ref;
+	int rc;
+
+	rc = plpar_get_nx_fault(txwin->winid, (u64)virt_to_phys(&crb));
+	if (!rc) {
+		tsk_ref = &txwin->task_ref;
+		vas_dump_crb(&crb);
+		vas_update_csb(&crb, tsk_ref);
+	}
+
+	return IRQ_HANDLED;
+}
+
 /*
  * Allocate window and setup IRQ mapping.
  */
@@ -235,10 +291,51 @@ static int allocate_setup_window(struct vas_window *txwin,
 	rc = plpar_vas_allocate_window(txwin, domain, wintype, DEF_WIN_CREDS);
 	if (rc)
 		return rc;
+	/*
+	 * On powerVM, pHyp setup and forwards the fault interrupt per
+	 * window. So the IRQ setup and fault handling will be done for
+	 * each open window separately.
+	 */
+	txwin->lpar.fault_virq = irq_create_mapping(NULL,
+						    txwin->lpar.fault_irq);
+	if (!txwin->lpar.fault_virq) {
+		pr_err("Failed irq mapping %d\n", txwin->lpar.fault_irq);
+		rc = -EINVAL;
+		goto out_win;
+	}
+
+	txwin->lpar.name = kasprintf(GFP_KERNEL, "vas-win-%d", txwin->winid);
+	if (!txwin->lpar.name) {
+		rc = -ENOMEM;
+		goto out_irq;
+	}
+
+	rc = request_threaded_irq(txwin->lpar.fault_virq, NULL,
+				  pseries_vas_fault_thread_fn, IRQF_ONESHOT,
+				  txwin->lpar.name, txwin);
+	if (rc) {
+		pr_err("VAS-Window[%d]: Request IRQ(%u) failed with %d\n",
+		       txwin->winid, txwin->lpar.fault_virq, rc);
+		goto out_free;
+	}
 
 	txwin->wcreds_max = DEF_WIN_CREDS;
 
 	return 0;
+out_free:
+	kfree(txwin->lpar.name);
+out_irq:
+	irq_dispose_mapping(txwin->lpar.fault_virq);
+out_win:
+	plpar_vas_deallocate_window(txwin->winid);
+	return rc;
+}
+
+static inline void free_irq_setup(struct vas_window *txwin)
+{
+	free_irq(txwin->lpar.fault_virq, txwin);
+	irq_dispose_mapping(txwin->lpar.fault_virq);
+	kfree(txwin->lpar.name);
 }
 
 static struct vas_window *vas_allocate_window(struct vas_tx_win_open_attr *uattr,
@@ -353,6 +450,11 @@ static struct vas_window *vas_allocate_window(struct vas_tx_win_open_attr *uattr
 	return txwin;
 
 out_free:
+	/*
+	 * Window is not operational. Free IRQ before closing
+	 * window so that do not have to hold mutex.
+	 */
+	free_irq_setup(txwin);
 	plpar_vas_deallocate_window(txwin->winid);
 out:
 	atomic_dec(&ct_caps->used_lpar_creds);
@@ -371,7 +473,16 @@ static int deallocate_free_window(struct vas_window *win)
 {
 	int rc = 0;
 
+	/*
+	 * Free IRQ after executing H_DEALLOCATE_VAS_WINDOW HCALL
+	 * to close the window. pHyp waits for all requests including
+	 * faults are processed before closing the window - Means all
+	 * credits are returned. In the case of fault request, credit
+	 * is returned after OS issues H_GET_NX_FAULT HCALL.
+	 */
 	rc = plpar_vas_deallocate_window(win->winid);
+	if (!rc)
+		free_irq_setup(win);
 
 	return rc;
 }
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 13/16] crypto/nx: Rename nx-842-pseries file name to nx-common-pseries
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:40   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:40 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


Rename nx-842-pseries.c to nx-common-pseries.c to add code for new
GZIP compression type. The actual functionality is not changed in
this patch.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 drivers/crypto/nx/Makefile                                  | 2 +-
 drivers/crypto/nx/{nx-842-pseries.c => nx-common-pseries.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/crypto/nx/{nx-842-pseries.c => nx-common-pseries.c} (100%)

diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile
index bc89a20e5d9d..d00181a26dd6 100644
--- a/drivers/crypto/nx/Makefile
+++ b/drivers/crypto/nx/Makefile
@@ -14,5 +14,5 @@ nx-crypto-objs := nx.o \
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o nx-compress.o
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o nx-compress.o
 nx-compress-objs := nx-842.o
-nx-compress-pseries-objs := nx-842-pseries.o
+nx-compress-pseries-objs := nx-common-pseries.o
 nx-compress-powernv-objs := nx-common-powernv.o
diff --git a/drivers/crypto/nx/nx-842-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
similarity index 100%
rename from drivers/crypto/nx/nx-842-pseries.c
rename to drivers/crypto/nx/nx-common-pseries.c
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 13/16] crypto/nx: Rename nx-842-pseries file name to nx-common-pseries
@ 2021-05-21  9:40   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:40 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


Rename nx-842-pseries.c to nx-common-pseries.c to add code for new
GZIP compression type. The actual functionality is not changed in
this patch.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 drivers/crypto/nx/Makefile                                  | 2 +-
 drivers/crypto/nx/{nx-842-pseries.c => nx-common-pseries.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/crypto/nx/{nx-842-pseries.c => nx-common-pseries.c} (100%)

diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile
index bc89a20e5d9d..d00181a26dd6 100644
--- a/drivers/crypto/nx/Makefile
+++ b/drivers/crypto/nx/Makefile
@@ -14,5 +14,5 @@ nx-crypto-objs := nx.o \
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o nx-compress.o
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o nx-compress.o
 nx-compress-objs := nx-842.o
-nx-compress-pseries-objs := nx-842-pseries.o
+nx-compress-pseries-objs := nx-common-pseries.o
 nx-compress-powernv-objs := nx-common-powernv.o
diff --git a/drivers/crypto/nx/nx-842-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
similarity index 100%
rename from drivers/crypto/nx/nx-842-pseries.c
rename to drivers/crypto/nx/nx-common-pseries.c
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 14/16] crypto/nx: Register and unregister VAS interface
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:41   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:41 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


Changes to create /dev/crypto/nx-gzip interface with VAS register
and to remove this interface with VAS unregister.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 drivers/crypto/nx/Kconfig             | 1 +
 drivers/crypto/nx/nx-common-pseries.c | 9 +++++++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/crypto/nx/Kconfig b/drivers/crypto/nx/Kconfig
index 23e3d0160e67..2a35e0e785bd 100644
--- a/drivers/crypto/nx/Kconfig
+++ b/drivers/crypto/nx/Kconfig
@@ -29,6 +29,7 @@ if CRYPTO_DEV_NX_COMPRESS
 config CRYPTO_DEV_NX_COMPRESS_PSERIES
 	tristate "Compression acceleration support on pSeries platform"
 	depends on PPC_PSERIES && IBMVIO
+	depends on PPC_VAS
 	default y
 	help
 	  Support for PowerPC Nest (NX) compression acceleration. This
diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
index cc8dd3072b8b..9a40fca8a9e6 100644
--- a/drivers/crypto/nx/nx-common-pseries.c
+++ b/drivers/crypto/nx/nx-common-pseries.c
@@ -9,6 +9,7 @@
  */
 
 #include <asm/vio.h>
+#include <asm/vas.h>
 
 #include "nx-842.h"
 #include "nx_csbcpb.h" /* struct nx_csbcpb */
@@ -1101,6 +1102,12 @@ static int __init nx842_pseries_init(void)
 		return ret;
 	}
 
+	ret = vas_register_api_pseries(THIS_MODULE, VAS_COP_TYPE_GZIP,
+				       "nx-gzip");
+
+	if (ret)
+		pr_err("NX-GZIP is not supported. Returned=%d\n", ret);
+
 	return 0;
 }
 
@@ -1111,6 +1118,8 @@ static void __exit nx842_pseries_exit(void)
 	struct nx842_devdata *old_devdata;
 	unsigned long flags;
 
+	vas_unregister_api_pseries();
+
 	crypto_unregister_alg(&nx842_pseries_alg);
 
 	spin_lock_irqsave(&devdata_mutex, flags);
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 14/16] crypto/nx: Register and unregister VAS interface
@ 2021-05-21  9:41   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:41 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


Changes to create /dev/crypto/nx-gzip interface with VAS register
and to remove this interface with VAS unregister.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 drivers/crypto/nx/Kconfig             | 1 +
 drivers/crypto/nx/nx-common-pseries.c | 9 +++++++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/crypto/nx/Kconfig b/drivers/crypto/nx/Kconfig
index 23e3d0160e67..2a35e0e785bd 100644
--- a/drivers/crypto/nx/Kconfig
+++ b/drivers/crypto/nx/Kconfig
@@ -29,6 +29,7 @@ if CRYPTO_DEV_NX_COMPRESS
 config CRYPTO_DEV_NX_COMPRESS_PSERIES
 	tristate "Compression acceleration support on pSeries platform"
 	depends on PPC_PSERIES && IBMVIO
+	depends on PPC_VAS
 	default y
 	help
 	  Support for PowerPC Nest (NX) compression acceleration. This
diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
index cc8dd3072b8b..9a40fca8a9e6 100644
--- a/drivers/crypto/nx/nx-common-pseries.c
+++ b/drivers/crypto/nx/nx-common-pseries.c
@@ -9,6 +9,7 @@
  */
 
 #include <asm/vio.h>
+#include <asm/vas.h>
 
 #include "nx-842.h"
 #include "nx_csbcpb.h" /* struct nx_csbcpb */
@@ -1101,6 +1102,12 @@ static int __init nx842_pseries_init(void)
 		return ret;
 	}
 
+	ret = vas_register_api_pseries(THIS_MODULE, VAS_COP_TYPE_GZIP,
+				       "nx-gzip");
+
+	if (ret)
+		pr_err("NX-GZIP is not supported. Returned=%d\n", ret);
+
 	return 0;
 }
 
@@ -1111,6 +1118,8 @@ static void __exit nx842_pseries_exit(void)
 	struct nx842_devdata *old_devdata;
 	unsigned long flags;
 
+	vas_unregister_api_pseries();
+
 	crypto_unregister_alg(&nx842_pseries_alg);
 
 	spin_lock_irqsave(&devdata_mutex, flags);
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 15/16] crypto/nx: Get NX capabilities for GZIP coprocessor type
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:41   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:41 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


The hypervisor provides different capabilities that it supports
to define the user space NX request. These capabilities are
recommended minimum compression / decompression lengths and the
maximum request buffer size in bytes.

Changes to get NX overall capabilities which points to the
specific features that the hypervisor supports. Then retrieve
the capabilities for the specific feature (available only
for NXGZIP).

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 drivers/crypto/nx/nx-common-pseries.c | 89 +++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
index 9a40fca8a9e6..4a7278464156 100644
--- a/drivers/crypto/nx/nx-common-pseries.c
+++ b/drivers/crypto/nx/nx-common-pseries.c
@@ -9,6 +9,7 @@
  */
 
 #include <asm/vio.h>
+#include <asm/hvcall.h>
 #include <asm/vas.h>
 
 #include "nx-842.h"
@@ -20,6 +21,30 @@ MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors");
 MODULE_ALIAS_CRYPTO("842");
 MODULE_ALIAS_CRYPTO("842-nx");
 
+/*
+ * Coprocessor type specific capabilities from the hypervisor.
+ */
+struct hv_nx_ct_caps {
+	__be64	descriptor;
+	__be64	req_max_processed_len;	/* Max bytes in one GZIP request */
+	__be64	min_compress_len;	/* Min compression size in bytes */
+	__be64	min_decompress_len;	/* Min decompression size in bytes */
+} __packed __aligned(0x1000);
+
+/*
+ * Coprocessor type specific capabilities.
+ */
+struct nx_ct_caps {
+	char	name[VAS_DESCR_LEN + 1];
+	u64	descriptor;
+	u64	req_max_processed_len;	/* Max bytes in one GZIP request */
+	u64	min_compress_len;	/* Min compression in bytes */
+	u64	min_decompress_len;	/* Min decompression in bytes */
+};
+
+static u64 caps_feat;
+static struct nx_ct_caps nx_ct_caps;
+
 static struct nx842_constraints nx842_pseries_constraints = {
 	.alignment =	DDE_BUFFER_ALIGN,
 	.multiple =	DDE_BUFFER_LAST_MULT,
@@ -1066,6 +1091,66 @@ static void nx842_remove(struct vio_dev *viodev)
 	kfree(old_devdata);
 }
 
+/*
+ * Get NX capabilities from the hypervisor.
+ * Only NXGZIP capabilities are provided by the hypersvisor right
+ * now and these values are available to user space with sysfs.
+ */
+static void __init nxct_get_capabilities(void)
+{
+	struct hv_vas_all_caps *hv_caps;
+	struct hv_nx_ct_caps *hv_nxc;
+	int rc;
+
+	hv_caps = kmalloc(sizeof(*hv_caps), GFP_KERNEL);
+	if (!hv_caps)
+		return;
+	/*
+	 * Get NX overall capabilities with feature type=0
+	 */
+	rc = plpar_vas_query_capabilities(H_QUERY_NX_CAPABILITIES, 0,
+					  (u64)virt_to_phys(hv_caps));
+	if (rc)
+		goto out;
+
+	caps_feat = be64_to_cpu(hv_caps->feat_type);
+	/*
+	 * NX-GZIP feature available
+	 */
+	if (caps_feat & VAS_NX_GZIP_FEAT_BIT) {
+		hv_nxc = kmalloc(sizeof(*hv_nxc), GFP_KERNEL);
+		if (!hv_nxc)
+			goto out;
+		/*
+		 * Get capabilities for NX-GZIP feature
+		 */
+		rc = plpar_vas_query_capabilities(H_QUERY_NX_CAPABILITIES,
+						  VAS_NX_GZIP_FEAT,
+						  (u64)virt_to_phys(hv_nxc));
+	} else {
+		pr_err("NX-GZIP feature is not available\n");
+		rc = -EINVAL;
+	}
+
+	if (!rc) {
+		snprintf(nx_ct_caps.name, VAS_DESCR_LEN + 1, "%.8s",
+			 (char *)&hv_nxc->descriptor);
+		nx_ct_caps.descriptor = be64_to_cpu(hv_nxc->descriptor);
+		nx_ct_caps.req_max_processed_len =
+				be64_to_cpu(hv_nxc->req_max_processed_len);
+		nx_ct_caps.min_compress_len =
+				be64_to_cpu(hv_nxc->min_compress_len);
+		nx_ct_caps.min_decompress_len =
+				be64_to_cpu(hv_nxc->min_decompress_len);
+	} else {
+		caps_feat = 0;
+	}
+
+	kfree(hv_nxc);
+out:
+	kfree(hv_caps);
+}
+
 static const struct vio_device_id nx842_vio_driver_ids[] = {
 	{"ibm,compression-v1", "ibm,compression"},
 	{"", ""},
@@ -1093,6 +1178,10 @@ static int __init nx842_pseries_init(void)
 		return -ENOMEM;
 
 	RCU_INIT_POINTER(devdata, new_devdata);
+	/*
+	 * Get NX capabilities from the hypervisor.
+	 */
+	nxct_get_capabilities();
 
 	ret = vio_register_driver(&nx842_vio_driver);
 	if (ret) {
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 15/16] crypto/nx: Get NX capabilities for GZIP coprocessor type
@ 2021-05-21  9:41   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:41 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


The hypervisor provides different capabilities that it supports
to define the user space NX request. These capabilities are
recommended minimum compression / decompression lengths and the
maximum request buffer size in bytes.

Changes to get NX overall capabilities which points to the
specific features that the hypervisor supports. Then retrieve
the capabilities for the specific feature (available only
for NXGZIP).

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 drivers/crypto/nx/nx-common-pseries.c | 89 +++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
index 9a40fca8a9e6..4a7278464156 100644
--- a/drivers/crypto/nx/nx-common-pseries.c
+++ b/drivers/crypto/nx/nx-common-pseries.c
@@ -9,6 +9,7 @@
  */
 
 #include <asm/vio.h>
+#include <asm/hvcall.h>
 #include <asm/vas.h>
 
 #include "nx-842.h"
@@ -20,6 +21,30 @@ MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors");
 MODULE_ALIAS_CRYPTO("842");
 MODULE_ALIAS_CRYPTO("842-nx");
 
+/*
+ * Coprocessor type specific capabilities from the hypervisor.
+ */
+struct hv_nx_ct_caps {
+	__be64	descriptor;
+	__be64	req_max_processed_len;	/* Max bytes in one GZIP request */
+	__be64	min_compress_len;	/* Min compression size in bytes */
+	__be64	min_decompress_len;	/* Min decompression size in bytes */
+} __packed __aligned(0x1000);
+
+/*
+ * Coprocessor type specific capabilities.
+ */
+struct nx_ct_caps {
+	char	name[VAS_DESCR_LEN + 1];
+	u64	descriptor;
+	u64	req_max_processed_len;	/* Max bytes in one GZIP request */
+	u64	min_compress_len;	/* Min compression in bytes */
+	u64	min_decompress_len;	/* Min decompression in bytes */
+};
+
+static u64 caps_feat;
+static struct nx_ct_caps nx_ct_caps;
+
 static struct nx842_constraints nx842_pseries_constraints = {
 	.alignment =	DDE_BUFFER_ALIGN,
 	.multiple =	DDE_BUFFER_LAST_MULT,
@@ -1066,6 +1091,66 @@ static void nx842_remove(struct vio_dev *viodev)
 	kfree(old_devdata);
 }
 
+/*
+ * Get NX capabilities from the hypervisor.
+ * Only NXGZIP capabilities are provided by the hypersvisor right
+ * now and these values are available to user space with sysfs.
+ */
+static void __init nxct_get_capabilities(void)
+{
+	struct hv_vas_all_caps *hv_caps;
+	struct hv_nx_ct_caps *hv_nxc;
+	int rc;
+
+	hv_caps = kmalloc(sizeof(*hv_caps), GFP_KERNEL);
+	if (!hv_caps)
+		return;
+	/*
+	 * Get NX overall capabilities with feature type=0
+	 */
+	rc = plpar_vas_query_capabilities(H_QUERY_NX_CAPABILITIES, 0,
+					  (u64)virt_to_phys(hv_caps));
+	if (rc)
+		goto out;
+
+	caps_feat = be64_to_cpu(hv_caps->feat_type);
+	/*
+	 * NX-GZIP feature available
+	 */
+	if (caps_feat & VAS_NX_GZIP_FEAT_BIT) {
+		hv_nxc = kmalloc(sizeof(*hv_nxc), GFP_KERNEL);
+		if (!hv_nxc)
+			goto out;
+		/*
+		 * Get capabilities for NX-GZIP feature
+		 */
+		rc = plpar_vas_query_capabilities(H_QUERY_NX_CAPABILITIES,
+						  VAS_NX_GZIP_FEAT,
+						  (u64)virt_to_phys(hv_nxc));
+	} else {
+		pr_err("NX-GZIP feature is not available\n");
+		rc = -EINVAL;
+	}
+
+	if (!rc) {
+		snprintf(nx_ct_caps.name, VAS_DESCR_LEN + 1, "%.8s",
+			 (char *)&hv_nxc->descriptor);
+		nx_ct_caps.descriptor = be64_to_cpu(hv_nxc->descriptor);
+		nx_ct_caps.req_max_processed_len =
+				be64_to_cpu(hv_nxc->req_max_processed_len);
+		nx_ct_caps.min_compress_len =
+				be64_to_cpu(hv_nxc->min_compress_len);
+		nx_ct_caps.min_decompress_len =
+				be64_to_cpu(hv_nxc->min_decompress_len);
+	} else {
+		caps_feat = 0;
+	}
+
+	kfree(hv_nxc);
+out:
+	kfree(hv_caps);
+}
+
 static const struct vio_device_id nx842_vio_driver_ids[] = {
 	{"ibm,compression-v1", "ibm,compression"},
 	{"", ""},
@@ -1093,6 +1178,10 @@ static int __init nx842_pseries_init(void)
 		return -ENOMEM;
 
 	RCU_INIT_POINTER(devdata, new_devdata);
+	/*
+	 * Get NX capabilities from the hypervisor.
+	 */
+	nxct_get_capabilities();
 
 	ret = vio_register_driver(&nx842_vio_driver);
 	if (ret) {
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
  2021-05-21  9:25 ` Haren Myneni
@ 2021-05-21  9:42   ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:42 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin; +Cc: hbabu, haren


Changes to export the following NXGZIP capabilities through sysfs:

/sys/devices/vio/ibm,compression-v1/NxGzCaps:
min_compress_len  /*Recommended minimum compress length in bytes*/
min_decompress_len /*Recommended minimum decompress length in bytes*/
req_max_processed_len /* Maximum number of bytes processed in one
			request */

NX will return RMA_Reject if the request buffer size is greater
than req_max_processed_len.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 drivers/crypto/nx/nx-common-pseries.c | 43 +++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
index 4a7278464156..121718a337fd 100644
--- a/drivers/crypto/nx/nx-common-pseries.c
+++ b/drivers/crypto/nx/nx-common-pseries.c
@@ -968,6 +968,36 @@ static struct attribute_group nx842_attribute_group = {
 	.attrs = nx842_sysfs_entries,
 };
 
+#define	nxct_caps_read(_name)						\
+static ssize_t nxct_##_name##_show(struct device *dev,			\
+			struct device_attribute *attr, char *buf)	\
+{									\
+	return sprintf(buf, "%lld\n", nx_ct_caps._name);		\
+}
+
+#define NXCT_ATTR_RO(_name)						\
+	nxct_caps_read(_name);						\
+	static struct device_attribute dev_attr_##_name = __ATTR(_name,	\
+						0444,			\
+						nxct_##_name##_show,	\
+						NULL);
+
+NXCT_ATTR_RO(req_max_processed_len);
+NXCT_ATTR_RO(min_compress_len);
+NXCT_ATTR_RO(min_decompress_len);
+
+static struct attribute *nxct_caps_sysfs_entries[] = {
+	&dev_attr_req_max_processed_len.attr,
+	&dev_attr_min_compress_len.attr,
+	&dev_attr_min_decompress_len.attr,
+	NULL,
+};
+
+static struct attribute_group nxct_caps_attr_group = {
+	.name	=	nx_ct_caps.name,
+	.attrs	=	nxct_caps_sysfs_entries,
+};
+
 static struct nx842_driver nx842_pseries_driver = {
 	.name =		KBUILD_MODNAME,
 	.owner =	THIS_MODULE,
@@ -1057,6 +1087,16 @@ static int nx842_probe(struct vio_dev *viodev,
 		goto error;
 	}
 
+	if (caps_feat) {
+		if (sysfs_create_group(&viodev->dev.kobj,
+					&nxct_caps_attr_group)) {
+			dev_err(&viodev->dev,
+				"Could not create sysfs NX capability entries\n");
+			ret = -1;
+			goto error;
+		}
+	}
+
 	return 0;
 
 error_unlock:
@@ -1076,6 +1116,9 @@ static void nx842_remove(struct vio_dev *viodev)
 	pr_info("Removing IBM Power 842 compression device\n");
 	sysfs_remove_group(&viodev->dev.kobj, &nx842_attribute_group);
 
+	if (caps_feat)
+		sysfs_remove_group(&viodev->dev.kobj, &nxct_caps_attr_group);
+
 	crypto_unregister_alg(&nx842_pseries_alg);
 
 	spin_lock_irqsave(&devdata_mutex, flags);
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
@ 2021-05-21  9:42   ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-05-21  9:42 UTC (permalink / raw)
  To: linuxppc-dev, linux-crypto, mpe, herbert, npiggin


Changes to export the following NXGZIP capabilities through sysfs:

/sys/devices/vio/ibm,compression-v1/NxGzCaps:
min_compress_len  /*Recommended minimum compress length in bytes*/
min_decompress_len /*Recommended minimum decompress length in bytes*/
req_max_processed_len /* Maximum number of bytes processed in one
			request */

NX will return RMA_Reject if the request buffer size is greater
than req_max_processed_len.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 drivers/crypto/nx/nx-common-pseries.c | 43 +++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
index 4a7278464156..121718a337fd 100644
--- a/drivers/crypto/nx/nx-common-pseries.c
+++ b/drivers/crypto/nx/nx-common-pseries.c
@@ -968,6 +968,36 @@ static struct attribute_group nx842_attribute_group = {
 	.attrs = nx842_sysfs_entries,
 };
 
+#define	nxct_caps_read(_name)						\
+static ssize_t nxct_##_name##_show(struct device *dev,			\
+			struct device_attribute *attr, char *buf)	\
+{									\
+	return sprintf(buf, "%lld\n", nx_ct_caps._name);		\
+}
+
+#define NXCT_ATTR_RO(_name)						\
+	nxct_caps_read(_name);						\
+	static struct device_attribute dev_attr_##_name = __ATTR(_name,	\
+						0444,			\
+						nxct_##_name##_show,	\
+						NULL);
+
+NXCT_ATTR_RO(req_max_processed_len);
+NXCT_ATTR_RO(min_compress_len);
+NXCT_ATTR_RO(min_decompress_len);
+
+static struct attribute *nxct_caps_sysfs_entries[] = {
+	&dev_attr_req_max_processed_len.attr,
+	&dev_attr_min_compress_len.attr,
+	&dev_attr_min_decompress_len.attr,
+	NULL,
+};
+
+static struct attribute_group nxct_caps_attr_group = {
+	.name	=	nx_ct_caps.name,
+	.attrs	=	nxct_caps_sysfs_entries,
+};
+
 static struct nx842_driver nx842_pseries_driver = {
 	.name =		KBUILD_MODNAME,
 	.owner =	THIS_MODULE,
@@ -1057,6 +1087,16 @@ static int nx842_probe(struct vio_dev *viodev,
 		goto error;
 	}
 
+	if (caps_feat) {
+		if (sysfs_create_group(&viodev->dev.kobj,
+					&nxct_caps_attr_group)) {
+			dev_err(&viodev->dev,
+				"Could not create sysfs NX capability entries\n");
+			ret = -1;
+			goto error;
+		}
+	}
+
 	return 0;
 
 error_unlock:
@@ -1076,6 +1116,9 @@ static void nx842_remove(struct vio_dev *viodev)
 	pr_info("Removing IBM Power 842 compression device\n");
 	sysfs_remove_group(&viodev->dev.kobj, &nx842_attribute_group);
 
+	if (caps_feat)
+		sysfs_remove_group(&viodev->dev.kobj, &nxct_caps_attr_group);
+
 	crypto_unregister_alg(&nx842_pseries_alg);
 
 	spin_lock_irqsave(&devdata_mutex, flags);
-- 
2.18.2



^ permalink raw reply related	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 01/16] powerpc/vas: Move VAS API to book3s common platform
  2021-05-21  9:28   ` Haren Myneni
@ 2021-06-03  3:32     ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  3:32 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: hbabu

Excerpts from Haren Myneni's message of May 21, 2021 7:28 pm:
> 
> Using the same /dev/crypto/nx-gzip interface for both powerNV and
> pseries. So this patch creates platforms/book3s/ and moves VAS API
> to that directory. The actual functionality is not changed.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/vas.h                    |  3 +++
>  arch/powerpc/platforms/Kconfig                    |  1 +
>  arch/powerpc/platforms/Makefile                   |  1 +
>  arch/powerpc/platforms/book3s/Kconfig             | 15 +++++++++++++++
>  arch/powerpc/platforms/book3s/Makefile            |  2 ++

If Michael is happy with the new directory structure then fine by me.

>  .../platforms/{powernv => book3s}/vas-api.c       |  2 +-
>  arch/powerpc/platforms/powernv/Kconfig            | 14 --------------
>  arch/powerpc/platforms/powernv/Makefile           |  2 +-
>  8 files changed, 24 insertions(+), 16 deletions(-)
>  create mode 100644 arch/powerpc/platforms/book3s/Kconfig
>  create mode 100644 arch/powerpc/platforms/book3s/Makefile
>  rename arch/powerpc/platforms/{powernv => book3s}/vas-api.c (99%)
> 
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index e33f80b0ea81..3be76e813e2d 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -162,6 +162,9 @@ int vas_copy_crb(void *crb, int offset);
>   */
>  int vas_paste_crb(struct vas_window *win, int offset, bool re);
>  
> +void vas_win_paste_addr(struct vas_window *window, u64 *addr,
> +			int *len);
> +
>  /*
>   * Register / unregister coprocessor type to VAS API which will be exported
>   * to user space. Applications can use this API to open / close window

If you do this, then the prototype should be removed from 
arch/powerpc/platforms/powernv/vas.h

> diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
> index 7a5e8f4541e3..594544a65b02 100644
> --- a/arch/powerpc/platforms/Kconfig
> +++ b/arch/powerpc/platforms/Kconfig
> @@ -20,6 +20,7 @@ source "arch/powerpc/platforms/embedded6xx/Kconfig"
>  source "arch/powerpc/platforms/44x/Kconfig"
>  source "arch/powerpc/platforms/40x/Kconfig"
>  source "arch/powerpc/platforms/amigaone/Kconfig"
> +source "arch/powerpc/platforms/book3s/Kconfig"
>  
>  config KVM_GUEST
>  	bool "KVM Guest support"
> diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
> index 143d4417f6cc..0e75d7df387b 100644
> --- a/arch/powerpc/platforms/Makefile
> +++ b/arch/powerpc/platforms/Makefile
> @@ -22,3 +22,4 @@ obj-$(CONFIG_PPC_CELL)		+= cell/
>  obj-$(CONFIG_PPC_PS3)		+= ps3/
>  obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
>  obj-$(CONFIG_AMIGAONE)		+= amigaone/
> +obj-$(CONFIG_PPC_BOOK3S)	+= book3s/
> diff --git a/arch/powerpc/platforms/book3s/Kconfig b/arch/powerpc/platforms/book3s/Kconfig
> new file mode 100644
> index 000000000000..bed21449e8e5
> --- /dev/null
> +++ b/arch/powerpc/platforms/book3s/Kconfig
> @@ -0,0 +1,15 @@
> +# SPDX-License-Identifier: GPL-2.0
> +config PPC_VAS
> +	bool "IBM Virtual Accelerator Switchboard (VAS)"
> +	depends on (PPC_POWERNV || PPC_PSERIES) && PPC_64K_PAGES
> +	default y
> +	help
> +	  This enables support for IBM Virtual Accelerator Switchboard (VAS).
> +
> +	  VAS allows accelerators in co-processors like NX-GZIP and NX-842
> +	  to be accessible to kernel subsystems and user processes.
> +	  VAS adapters are found in POWER9 and later based systems.
> +	  The user mode NX-GZIP support is added on P9 for powerNV and on
> +	  P10 for powerVM.

The changelog has changed. The last sentence is difficult to understand 
(also please consistently capitalise PowerNV and PowerVM). Is it 
supposed to say that PPC_VAS will provide user-mode NX-GZIP support on 
P9 PowerNV systems and P10 PowerVM systems? If you respin the patch for
the prototype...

  This enables support for IBM Virtual Accelerator Switchboard (VAS).

  VAS devices are found in POWER9-based and later systems, they provide
  access to accelerator coprocessors such as NX-GZIP and NX-842. This
  driver allows the kernel to use NX-GZIP and NX-842 accelerators, and
  user-mode APIs for the NX-GZIP accelerator on POWER9 PowerNV and
  POWER10 PowerVM platforms. <here is a userspace library you can use>
  etc

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 01/16] powerpc/vas: Move VAS API to book3s common platform
@ 2021-06-03  3:32     ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  3:32 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of May 21, 2021 7:28 pm:
> 
> Using the same /dev/crypto/nx-gzip interface for both powerNV and
> pseries. So this patch creates platforms/book3s/ and moves VAS API
> to that directory. The actual functionality is not changed.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/vas.h                    |  3 +++
>  arch/powerpc/platforms/Kconfig                    |  1 +
>  arch/powerpc/platforms/Makefile                   |  1 +
>  arch/powerpc/platforms/book3s/Kconfig             | 15 +++++++++++++++
>  arch/powerpc/platforms/book3s/Makefile            |  2 ++

If Michael is happy with the new directory structure then fine by me.

>  .../platforms/{powernv => book3s}/vas-api.c       |  2 +-
>  arch/powerpc/platforms/powernv/Kconfig            | 14 --------------
>  arch/powerpc/platforms/powernv/Makefile           |  2 +-
>  8 files changed, 24 insertions(+), 16 deletions(-)
>  create mode 100644 arch/powerpc/platforms/book3s/Kconfig
>  create mode 100644 arch/powerpc/platforms/book3s/Makefile
>  rename arch/powerpc/platforms/{powernv => book3s}/vas-api.c (99%)
> 
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index e33f80b0ea81..3be76e813e2d 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -162,6 +162,9 @@ int vas_copy_crb(void *crb, int offset);
>   */
>  int vas_paste_crb(struct vas_window *win, int offset, bool re);
>  
> +void vas_win_paste_addr(struct vas_window *window, u64 *addr,
> +			int *len);
> +
>  /*
>   * Register / unregister coprocessor type to VAS API which will be exported
>   * to user space. Applications can use this API to open / close window

If you do this, then the prototype should be removed from 
arch/powerpc/platforms/powernv/vas.h

> diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
> index 7a5e8f4541e3..594544a65b02 100644
> --- a/arch/powerpc/platforms/Kconfig
> +++ b/arch/powerpc/platforms/Kconfig
> @@ -20,6 +20,7 @@ source "arch/powerpc/platforms/embedded6xx/Kconfig"
>  source "arch/powerpc/platforms/44x/Kconfig"
>  source "arch/powerpc/platforms/40x/Kconfig"
>  source "arch/powerpc/platforms/amigaone/Kconfig"
> +source "arch/powerpc/platforms/book3s/Kconfig"
>  
>  config KVM_GUEST
>  	bool "KVM Guest support"
> diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
> index 143d4417f6cc..0e75d7df387b 100644
> --- a/arch/powerpc/platforms/Makefile
> +++ b/arch/powerpc/platforms/Makefile
> @@ -22,3 +22,4 @@ obj-$(CONFIG_PPC_CELL)		+= cell/
>  obj-$(CONFIG_PPC_PS3)		+= ps3/
>  obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
>  obj-$(CONFIG_AMIGAONE)		+= amigaone/
> +obj-$(CONFIG_PPC_BOOK3S)	+= book3s/
> diff --git a/arch/powerpc/platforms/book3s/Kconfig b/arch/powerpc/platforms/book3s/Kconfig
> new file mode 100644
> index 000000000000..bed21449e8e5
> --- /dev/null
> +++ b/arch/powerpc/platforms/book3s/Kconfig
> @@ -0,0 +1,15 @@
> +# SPDX-License-Identifier: GPL-2.0
> +config PPC_VAS
> +	bool "IBM Virtual Accelerator Switchboard (VAS)"
> +	depends on (PPC_POWERNV || PPC_PSERIES) && PPC_64K_PAGES
> +	default y
> +	help
> +	  This enables support for IBM Virtual Accelerator Switchboard (VAS).
> +
> +	  VAS allows accelerators in co-processors like NX-GZIP and NX-842
> +	  to be accessible to kernel subsystems and user processes.
> +	  VAS adapters are found in POWER9 and later based systems.
> +	  The user mode NX-GZIP support is added on P9 for powerNV and on
> +	  P10 for powerVM.

The changelog has changed. The last sentence is difficult to understand 
(also please consistently capitalise PowerNV and PowerVM). Is it 
supposed to say that PPC_VAS will provide user-mode NX-GZIP support on 
P9 PowerNV systems and P10 PowerVM systems? If you respin the patch for
the prototype...

  This enables support for IBM Virtual Accelerator Switchboard (VAS).

  VAS devices are found in POWER9-based and later systems, they provide
  access to accelerator coprocessors such as NX-GZIP and NX-842. This
  driver allows the kernel to use NX-GZIP and NX-842 accelerators, and
  user-mode APIs for the NX-GZIP accelerator on POWER9 PowerNV and
  POWER10 PowerVM platforms. <here is a userspace library you can use>
  etc

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 03/16] powerpc/vas: Add platform specific user window operations
  2021-05-21  9:30   ` Haren Myneni
@ 2021-06-03  4:05     ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:05 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of May 21, 2021 7:30 pm:
> 
> PowerNV uses registers to open/close VAS windows, and getting the
> paste address. Whereas the hypervisor calls are used on PowerVM.
> 
> This patch adds the platform specific user space window operations
> and register with the common VAS user space interface.

Basic idea makes sense. I don't understand this code in detail though.
A couple of things,

> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/vas.h              | 14 +++++-
>  arch/powerpc/platforms/book3s/vas-api.c     | 52 ++++++++++++---------
>  arch/powerpc/platforms/powernv/vas-window.c | 46 +++++++++++++++++-
>  3 files changed, 89 insertions(+), 23 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index 6076adf9ab4f..668303198772 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -5,6 +5,7 @@
>  
>  #ifndef _ASM_POWERPC_VAS_H
>  #define _ASM_POWERPC_VAS_H
> +#include <uapi/asm/vas-api.h>
>  
>  struct vas_window;
>  
> @@ -48,6 +49,16 @@ enum vas_cop_type {
>  	VAS_COP_TYPE_MAX,
>  };
>  
> +/*
> + * User space window operations used for powernv and powerVM
> + */
> +struct vas_user_win_ops {
> +	struct vas_window * (*open_win)(struct vas_tx_win_open_attr *,
> +				enum vas_cop_type);
> +	u64 (*paste_addr)(void *);
> +	int (*close_win)(void *);

Without looking further into the series, why do these two take void * 
when the first returns a vas_window * which appears to be the required
argument to these?

> +static struct vas_user_win_ops vops =  {
> +	.open_win	=	vas_user_win_open,
> +	.paste_addr	=	vas_user_win_paste_addr,
> +	.close_win	=	vas_user_win_close,
> +};

const?

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 03/16] powerpc/vas: Add platform specific user window operations
@ 2021-06-03  4:05     ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:05 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of May 21, 2021 7:30 pm:
> 
> PowerNV uses registers to open/close VAS windows, and getting the
> paste address. Whereas the hypervisor calls are used on PowerVM.
> 
> This patch adds the platform specific user space window operations
> and register with the common VAS user space interface.

Basic idea makes sense. I don't understand this code in detail though.
A couple of things,

> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/vas.h              | 14 +++++-
>  arch/powerpc/platforms/book3s/vas-api.c     | 52 ++++++++++++---------
>  arch/powerpc/platforms/powernv/vas-window.c | 46 +++++++++++++++++-
>  3 files changed, 89 insertions(+), 23 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index 6076adf9ab4f..668303198772 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -5,6 +5,7 @@
>  
>  #ifndef _ASM_POWERPC_VAS_H
>  #define _ASM_POWERPC_VAS_H
> +#include <uapi/asm/vas-api.h>
>  
>  struct vas_window;
>  
> @@ -48,6 +49,16 @@ enum vas_cop_type {
>  	VAS_COP_TYPE_MAX,
>  };
>  
> +/*
> + * User space window operations used for powernv and powerVM
> + */
> +struct vas_user_win_ops {
> +	struct vas_window * (*open_win)(struct vas_tx_win_open_attr *,
> +				enum vas_cop_type);
> +	u64 (*paste_addr)(void *);
> +	int (*close_win)(void *);

Without looking further into the series, why do these two take void * 
when the first returns a vas_window * which appears to be the required
argument to these?

> +static struct vas_user_win_ops vops =  {
> +	.open_win	=	vas_user_win_open,
> +	.paste_addr	=	vas_user_win_paste_addr,
> +	.close_win	=	vas_user_win_close,
> +};

const?

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
  2021-05-21  9:31   ` Haren Myneni
@ 2021-06-03  4:21     ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:21 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of May 21, 2021 7:31 pm:
> 
> Take pid and mm references when each window opens and drops during
> close. This functionality is needed for powerNV and pseries. So
> this patch defines the existing code as functions in common book3s
> platform vas-api.c
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>

Seems like a good idea to put these into their own helper functions.

> ---
>  arch/powerpc/include/asm/vas.h              | 25 +++++++++
>  arch/powerpc/platforms/book3s/vas-api.c     | 51 ++++++++++++++++++
>  arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
>  arch/powerpc/platforms/powernv/vas-window.c | 57 ++-------------------
>  arch/powerpc/platforms/powernv/vas.h        |  6 +--
>  5 files changed, 88 insertions(+), 61 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index 668303198772..3f2b02461a76 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -5,6 +5,9 @@
>  
>  #ifndef _ASM_POWERPC_VAS_H
>  #define _ASM_POWERPC_VAS_H
> +#include <linux/sched/mm.h>
> +#include <linux/mmu_context.h>
> +#include <asm/icswx.h>
>  #include <uapi/asm/vas-api.h>
>  
>  struct vas_window;
> @@ -49,6 +52,17 @@ enum vas_cop_type {
>  	VAS_COP_TYPE_MAX,
>  };
>  
> +/*
> + * User space VAS windows are opened by tasks and take references
> + * to pid and mm until windows are closed.
> + * Stores pid, mm, and tgid for each window.
> + */
> +struct vas_user_win_ref {
> +	struct pid *pid;	/* PID of owner */
> +	struct pid *tgid;	/* Thread group ID of owner */
> +	struct mm_struct *mm;	/* Linux process mm_struct */
> +};
> +
>  /*
>   * User space window operations used for powernv and powerVM
>   */
> @@ -59,6 +73,16 @@ struct vas_user_win_ops {
>  	int (*close_win)(void *);
>  };
>  
> +static inline void vas_drop_reference_pid_mm(struct vas_user_win_ref *ref)
> +{
> +	/* Drop references to pid and mm */
> +	put_pid(ref->pid);
> +	if (ref->mm) {
> +		mm_context_remove_vas_window(ref->mm);
> +		mmdrop(ref->mm);
> +	}
> +}

You don't have to make up a new name for such a thing because you 
already have one

put_vas_user_win_ref(struct vas_user_win_ref *ref)


> +
>  /*
>   * Receive window attributes specified by the (in-kernel) owner of window.
>   */
> @@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
>  			    struct vas_user_win_ops *vops);
>  void vas_unregister_coproc_api(void);
>  
> +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
>  #endif /* __ASM_POWERPC_VAS_H */
> diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
> index 6c39320bfb9b..a0141bfb2e4b 100644
> --- a/arch/powerpc/platforms/book3s/vas-api.c
> +++ b/arch/powerpc/platforms/book3s/vas-api.c
> @@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev, umode_t *mode)
>  	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
>  }
>  
> +/*
> + * Take reference to pid and mm
> + */
> +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
> +{

So this is quite different from a typical refcount object in that it's 
opening it for access as well. I would split it in two functions, one
matching put_vas_user_win_ref() and appearing in the same place in code,
which is up to about mmput and another function that adds the window and
does the CP_ABORT etc... hmm, where do you release tgid?

Thanks,
Nick

> +	/*
> +	 * Window opened by a child thread may not be closed when
> +	 * it exits. So take reference to its pid and release it
> +	 * when the window is free by parent thread.
> +	 * Acquire a reference to the task's pid to make sure
> +	 * pid will not be re-used - needed only for multithread
> +	 * applications.
> +	 */
> +	task_ref->pid = get_task_pid(current, PIDTYPE_PID);
> +	/*
> +	 * Acquire a reference to the task's mm.
> +	 */
> +	task_ref->mm = get_task_mm(current);
> +	if (!task_ref->mm) {
> +		put_pid(task_ref->pid);
> +		pr_err("VAS: pid(%d): mm_struct is not found\n",
> +				current->pid);
> +		return -EPERM;
> +	}
> +
> +	mmgrab(task_ref->mm);
> +	mmput(task_ref->mm);
> +	mm_context_add_vas_window(task_ref->mm);
> +	/*
> +	 * Process closes window during exit. In the case of
> +	 * multithread application, the child thread can open
> +	 * window and can exit without closing it. Expects parent
> +	 * thread to use and close the window. So do not need
> +	 * to take pid reference for parent thread.
> +	 */
> +	task_ref->tgid = find_get_pid(task_tgid_vnr(current));
> +	/*
> +	 * Even a process that has no foreign real address mapping can
> +	 * use an unpaired COPY instruction (to no real effect). Issue
> +	 * CP_ABORT to clear any pending COPY and prevent a covert
> +	 * channel.
> +	 *
> +	 * __switch_to() will issue CP_ABORT on future context switches
> +	 * if process / thread has any open VAS window (Use
> +	 * current->mm->context.vas_windows).
> +	 */
> +	asm volatile(PPC_CP_ABORT);
> +
> +	return 0;
> +}
> +
>  static int coproc_open(struct inode *inode, struct file *fp)
>  {
>  	struct coproc_instance *cp_inst;
> diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> index 3d21fce254b7..ac3a71ec3bd5 100644
> --- a/arch/powerpc/platforms/powernv/vas-fault.c
> +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> @@ -73,7 +73,7 @@ static void update_csb(struct vas_window *window,
>  	 * NX user space windows can not be opened for task->mm=NULL
>  	 * and faults will not be generated for kernel requests.
>  	 */
> -	if (WARN_ON_ONCE(!window->mm || !window->user_win))
> +	if (WARN_ON_ONCE(!window->task_ref.mm || !window->user_win))
>  		return;
>  
>  	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
> @@ -92,7 +92,7 @@ static void update_csb(struct vas_window *window,
>  	csb.address = crb->stamp.nx.fault_storage_addr;
>  	csb.flags = 0;
>  
> -	pid = window->pid;
> +	pid = window->task_ref.pid;
>  	tsk = get_pid_task(pid, PIDTYPE_PID);
>  	/*
>  	 * Process closes send window after all pending NX requests are
> @@ -111,7 +111,7 @@ static void update_csb(struct vas_window *window,
>  	 * a window and exits without closing it.
>  	 */
>  	if (!tsk) {
> -		pid = window->tgid;
> +		pid = window->task_ref.tgid;
>  		tsk = get_pid_task(pid, PIDTYPE_PID);
>  		/*
>  		 * Parent thread (tgid) will be closing window when it
> @@ -127,7 +127,7 @@ static void update_csb(struct vas_window *window,
>  		return;
>  	}
>  
> -	kthread_use_mm(window->mm);
> +	kthread_use_mm(window->task_ref.mm);
>  	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
>  	/*
>  	 * User space polls on csb.flags (first byte). So add barrier
> @@ -139,7 +139,7 @@ static void update_csb(struct vas_window *window,
>  		smp_mb();
>  		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
>  	}
> -	kthread_unuse_mm(window->mm);
> +	kthread_unuse_mm(window->task_ref.mm);
>  	put_task_struct(tsk);
>  
>  	/* Success */
> diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
> index 3ccd3edcaf1a..ffd619e5a218 100644
> --- a/arch/powerpc/platforms/powernv/vas-window.c
> +++ b/arch/powerpc/platforms/powernv/vas-window.c
> @@ -1065,51 +1065,9 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
>  			rc = -ENODEV;
>  			goto free_window;
>  		}
> -
> -		/*
> -		 * Window opened by a child thread may not be closed when
> -		 * it exits. So take reference to its pid and release it
> -		 * when the window is free by parent thread.
> -		 * Acquire a reference to the task's pid to make sure
> -		 * pid will not be re-used - needed only for multithread
> -		 * applications.
> -		 */
> -		txwin->pid = get_task_pid(current, PIDTYPE_PID);
> -		/*
> -		 * Acquire a reference to the task's mm.
> -		 */
> -		txwin->mm = get_task_mm(current);
> -
> -		if (!txwin->mm) {
> -			put_pid(txwin->pid);
> -			pr_err("VAS: pid(%d): mm_struct is not found\n",
> -					current->pid);
> -			rc = -EPERM;
> +		rc = vas_reference_pid_mm(&txwin->task_ref);
> +		if (rc)
>  			goto free_window;
> -		}
> -
> -		mmgrab(txwin->mm);
> -		mmput(txwin->mm);
> -		mm_context_add_vas_window(txwin->mm);
> -		/*
> -		 * Process closes window during exit. In the case of
> -		 * multithread application, the child thread can open
> -		 * window and can exit without closing it. Expects parent
> -		 * thread to use and close the window. So do not need
> -		 * to take pid reference for parent thread.
> -		 */
> -		txwin->tgid = find_get_pid(task_tgid_vnr(current));
> -		/*
> -		 * Even a process that has no foreign real address mapping can
> -		 * use an unpaired COPY instruction (to no real effect). Issue
> -		 * CP_ABORT to clear any pending COPY and prevent a covert
> -		 * channel.
> -		 *
> -		 * __switch_to() will issue CP_ABORT on future context switches
> -		 * if process / thread has any open VAS window (Use
> -		 * current->mm->context.vas_windows).
> -		 */
> -		asm volatile(PPC_CP_ABORT);
>  	}
>  
>  	set_vinst_win(vinst, txwin);
> @@ -1339,14 +1297,9 @@ int vas_win_close(struct vas_window *window)
>  
>  	/* if send window, drop reference to matching receive window */
>  	if (window->tx_win) {
> -		if (window->user_win) {
> -			/* Drop references to pid and mm */
> -			put_pid(window->pid);
> -			if (window->mm) {
> -				mm_context_remove_vas_window(window->mm);
> -				mmdrop(window->mm);
> -			}
> -		}
> +		if (window->user_win)
> +			vas_drop_reference_pid_mm(&window->task_ref);
> +
>  		put_rx_win(window->rxwin);
>  	}
>  
> diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
> index c7db3190baca..f354dd5c51bd 100644
> --- a/arch/powerpc/platforms/powernv/vas.h
> +++ b/arch/powerpc/platforms/powernv/vas.h
> @@ -357,11 +357,9 @@ struct vas_window {
>  	bool user_win;		/* True if user space window */
>  	void *hvwc_map;		/* HV window context */
>  	void *uwc_map;		/* OS/User window context */
> -	struct pid *pid;	/* Linux process id of owner */
> -	struct pid *tgid;	/* Thread group ID of owner */
> -	struct mm_struct *mm;	/* Linux process mm_struct */
>  	int wcreds_max;		/* Window credits */
>  
> +	struct vas_user_win_ref task_ref;
>  	char *dbgname;
>  	struct dentry *dbgdir;
>  
> @@ -443,7 +441,7 @@ extern void vas_win_paste_addr(struct vas_window *window, u64 *addr,
>  
>  static inline int vas_window_pid(struct vas_window *window)
>  {
> -	return pid_vnr(window->pid);
> +	return pid_vnr(window->task_ref.pid);
>  }
>  
>  static inline void vas_log_write(struct vas_window *win, char *name,
> -- 
> 2.18.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
@ 2021-06-03  4:21     ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:21 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of May 21, 2021 7:31 pm:
> 
> Take pid and mm references when each window opens and drops during
> close. This functionality is needed for powerNV and pseries. So
> this patch defines the existing code as functions in common book3s
> platform vas-api.c
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>

Seems like a good idea to put these into their own helper functions.

> ---
>  arch/powerpc/include/asm/vas.h              | 25 +++++++++
>  arch/powerpc/platforms/book3s/vas-api.c     | 51 ++++++++++++++++++
>  arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
>  arch/powerpc/platforms/powernv/vas-window.c | 57 ++-------------------
>  arch/powerpc/platforms/powernv/vas.h        |  6 +--
>  5 files changed, 88 insertions(+), 61 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index 668303198772..3f2b02461a76 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -5,6 +5,9 @@
>  
>  #ifndef _ASM_POWERPC_VAS_H
>  #define _ASM_POWERPC_VAS_H
> +#include <linux/sched/mm.h>
> +#include <linux/mmu_context.h>
> +#include <asm/icswx.h>
>  #include <uapi/asm/vas-api.h>
>  
>  struct vas_window;
> @@ -49,6 +52,17 @@ enum vas_cop_type {
>  	VAS_COP_TYPE_MAX,
>  };
>  
> +/*
> + * User space VAS windows are opened by tasks and take references
> + * to pid and mm until windows are closed.
> + * Stores pid, mm, and tgid for each window.
> + */
> +struct vas_user_win_ref {
> +	struct pid *pid;	/* PID of owner */
> +	struct pid *tgid;	/* Thread group ID of owner */
> +	struct mm_struct *mm;	/* Linux process mm_struct */
> +};
> +
>  /*
>   * User space window operations used for powernv and powerVM
>   */
> @@ -59,6 +73,16 @@ struct vas_user_win_ops {
>  	int (*close_win)(void *);
>  };
>  
> +static inline void vas_drop_reference_pid_mm(struct vas_user_win_ref *ref)
> +{
> +	/* Drop references to pid and mm */
> +	put_pid(ref->pid);
> +	if (ref->mm) {
> +		mm_context_remove_vas_window(ref->mm);
> +		mmdrop(ref->mm);
> +	}
> +}

You don't have to make up a new name for such a thing because you 
already have one

put_vas_user_win_ref(struct vas_user_win_ref *ref)


> +
>  /*
>   * Receive window attributes specified by the (in-kernel) owner of window.
>   */
> @@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type,
>  			    struct vas_user_win_ops *vops);
>  void vas_unregister_coproc_api(void);
>  
> +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
>  #endif /* __ASM_POWERPC_VAS_H */
> diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
> index 6c39320bfb9b..a0141bfb2e4b 100644
> --- a/arch/powerpc/platforms/book3s/vas-api.c
> +++ b/arch/powerpc/platforms/book3s/vas-api.c
> @@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev, umode_t *mode)
>  	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
>  }
>  
> +/*
> + * Take reference to pid and mm
> + */
> +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
> +{

So this is quite different from a typical refcount object in that it's 
opening it for access as well. I would split it in two functions, one
matching put_vas_user_win_ref() and appearing in the same place in code,
which is up to about mmput and another function that adds the window and
does the CP_ABORT etc... hmm, where do you release tgid?

Thanks,
Nick

> +	/*
> +	 * Window opened by a child thread may not be closed when
> +	 * it exits. So take reference to its pid and release it
> +	 * when the window is free by parent thread.
> +	 * Acquire a reference to the task's pid to make sure
> +	 * pid will not be re-used - needed only for multithread
> +	 * applications.
> +	 */
> +	task_ref->pid = get_task_pid(current, PIDTYPE_PID);
> +	/*
> +	 * Acquire a reference to the task's mm.
> +	 */
> +	task_ref->mm = get_task_mm(current);
> +	if (!task_ref->mm) {
> +		put_pid(task_ref->pid);
> +		pr_err("VAS: pid(%d): mm_struct is not found\n",
> +				current->pid);
> +		return -EPERM;
> +	}
> +
> +	mmgrab(task_ref->mm);
> +	mmput(task_ref->mm);
> +	mm_context_add_vas_window(task_ref->mm);
> +	/*
> +	 * Process closes window during exit. In the case of
> +	 * multithread application, the child thread can open
> +	 * window and can exit without closing it. Expects parent
> +	 * thread to use and close the window. So do not need
> +	 * to take pid reference for parent thread.
> +	 */
> +	task_ref->tgid = find_get_pid(task_tgid_vnr(current));
> +	/*
> +	 * Even a process that has no foreign real address mapping can
> +	 * use an unpaired COPY instruction (to no real effect). Issue
> +	 * CP_ABORT to clear any pending COPY and prevent a covert
> +	 * channel.
> +	 *
> +	 * __switch_to() will issue CP_ABORT on future context switches
> +	 * if process / thread has any open VAS window (Use
> +	 * current->mm->context.vas_windows).
> +	 */
> +	asm volatile(PPC_CP_ABORT);
> +
> +	return 0;
> +}
> +
>  static int coproc_open(struct inode *inode, struct file *fp)
>  {
>  	struct coproc_instance *cp_inst;
> diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> index 3d21fce254b7..ac3a71ec3bd5 100644
> --- a/arch/powerpc/platforms/powernv/vas-fault.c
> +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> @@ -73,7 +73,7 @@ static void update_csb(struct vas_window *window,
>  	 * NX user space windows can not be opened for task->mm=NULL
>  	 * and faults will not be generated for kernel requests.
>  	 */
> -	if (WARN_ON_ONCE(!window->mm || !window->user_win))
> +	if (WARN_ON_ONCE(!window->task_ref.mm || !window->user_win))
>  		return;
>  
>  	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
> @@ -92,7 +92,7 @@ static void update_csb(struct vas_window *window,
>  	csb.address = crb->stamp.nx.fault_storage_addr;
>  	csb.flags = 0;
>  
> -	pid = window->pid;
> +	pid = window->task_ref.pid;
>  	tsk = get_pid_task(pid, PIDTYPE_PID);
>  	/*
>  	 * Process closes send window after all pending NX requests are
> @@ -111,7 +111,7 @@ static void update_csb(struct vas_window *window,
>  	 * a window and exits without closing it.
>  	 */
>  	if (!tsk) {
> -		pid = window->tgid;
> +		pid = window->task_ref.tgid;
>  		tsk = get_pid_task(pid, PIDTYPE_PID);
>  		/*
>  		 * Parent thread (tgid) will be closing window when it
> @@ -127,7 +127,7 @@ static void update_csb(struct vas_window *window,
>  		return;
>  	}
>  
> -	kthread_use_mm(window->mm);
> +	kthread_use_mm(window->task_ref.mm);
>  	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
>  	/*
>  	 * User space polls on csb.flags (first byte). So add barrier
> @@ -139,7 +139,7 @@ static void update_csb(struct vas_window *window,
>  		smp_mb();
>  		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
>  	}
> -	kthread_unuse_mm(window->mm);
> +	kthread_unuse_mm(window->task_ref.mm);
>  	put_task_struct(tsk);
>  
>  	/* Success */
> diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
> index 3ccd3edcaf1a..ffd619e5a218 100644
> --- a/arch/powerpc/platforms/powernv/vas-window.c
> +++ b/arch/powerpc/platforms/powernv/vas-window.c
> @@ -1065,51 +1065,9 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
>  			rc = -ENODEV;
>  			goto free_window;
>  		}
> -
> -		/*
> -		 * Window opened by a child thread may not be closed when
> -		 * it exits. So take reference to its pid and release it
> -		 * when the window is free by parent thread.
> -		 * Acquire a reference to the task's pid to make sure
> -		 * pid will not be re-used - needed only for multithread
> -		 * applications.
> -		 */
> -		txwin->pid = get_task_pid(current, PIDTYPE_PID);
> -		/*
> -		 * Acquire a reference to the task's mm.
> -		 */
> -		txwin->mm = get_task_mm(current);
> -
> -		if (!txwin->mm) {
> -			put_pid(txwin->pid);
> -			pr_err("VAS: pid(%d): mm_struct is not found\n",
> -					current->pid);
> -			rc = -EPERM;
> +		rc = vas_reference_pid_mm(&txwin->task_ref);
> +		if (rc)
>  			goto free_window;
> -		}
> -
> -		mmgrab(txwin->mm);
> -		mmput(txwin->mm);
> -		mm_context_add_vas_window(txwin->mm);
> -		/*
> -		 * Process closes window during exit. In the case of
> -		 * multithread application, the child thread can open
> -		 * window and can exit without closing it. Expects parent
> -		 * thread to use and close the window. So do not need
> -		 * to take pid reference for parent thread.
> -		 */
> -		txwin->tgid = find_get_pid(task_tgid_vnr(current));
> -		/*
> -		 * Even a process that has no foreign real address mapping can
> -		 * use an unpaired COPY instruction (to no real effect). Issue
> -		 * CP_ABORT to clear any pending COPY and prevent a covert
> -		 * channel.
> -		 *
> -		 * __switch_to() will issue CP_ABORT on future context switches
> -		 * if process / thread has any open VAS window (Use
> -		 * current->mm->context.vas_windows).
> -		 */
> -		asm volatile(PPC_CP_ABORT);
>  	}
>  
>  	set_vinst_win(vinst, txwin);
> @@ -1339,14 +1297,9 @@ int vas_win_close(struct vas_window *window)
>  
>  	/* if send window, drop reference to matching receive window */
>  	if (window->tx_win) {
> -		if (window->user_win) {
> -			/* Drop references to pid and mm */
> -			put_pid(window->pid);
> -			if (window->mm) {
> -				mm_context_remove_vas_window(window->mm);
> -				mmdrop(window->mm);
> -			}
> -		}
> +		if (window->user_win)
> +			vas_drop_reference_pid_mm(&window->task_ref);
> +
>  		put_rx_win(window->rxwin);
>  	}
>  
> diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
> index c7db3190baca..f354dd5c51bd 100644
> --- a/arch/powerpc/platforms/powernv/vas.h
> +++ b/arch/powerpc/platforms/powernv/vas.h
> @@ -357,11 +357,9 @@ struct vas_window {
>  	bool user_win;		/* True if user space window */
>  	void *hvwc_map;		/* HV window context */
>  	void *uwc_map;		/* OS/User window context */
> -	struct pid *pid;	/* Linux process id of owner */
> -	struct pid *tgid;	/* Thread group ID of owner */
> -	struct mm_struct *mm;	/* Linux process mm_struct */
>  	int wcreds_max;		/* Window credits */
>  
> +	struct vas_user_win_ref task_ref;
>  	char *dbgname;
>  	struct dentry *dbgdir;
>  
> @@ -443,7 +441,7 @@ extern void vas_win_paste_addr(struct vas_window *window, u64 *addr,
>  
>  static inline int vas_window_pid(struct vas_window *window)
>  {
> -	return pid_vnr(window->pid);
> +	return pid_vnr(window->task_ref.pid);
>  }
>  
>  static inline void vas_log_write(struct vas_window *win, char *name,
> -- 
> 2.18.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 05/16] powerpc/vas: Move update_csb/dump_crb to common book3s platform
  2021-05-21  9:32   ` Haren Myneni
@ 2021-06-03  4:26     ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:26 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of May 21, 2021 7:32 pm:
> +
> +	pid = task_ref->pid;
> +	tsk = get_pid_task(pid, PIDTYPE_PID);
> +	/*
> +	 * Process closes send window after all pending NX requests are
> +	 * completed. In multi-thread applications, a child thread can
> +	 * open a window and can exit without closing it. May be some
> +	 * requests are pending or this window can be used by other
> +	 * threads later. We should handle faults if NX encounters
> +	 * pages faults on these requests. Update CSB with translation
> +	 * error and fault address. If csb_addr passed by user space is
> +	 * invalid, send SEGV signal to pid saved in window. If the
> +	 * child thread is not running, send the signal to tgid.
> +	 * Parent thread (tgid) will close this window upon its exit.
> +	 *
> +	 * pid and mm references are taken when window is opened by
> +	 * process (pid). So tgid is used only when child thread opens
> +	 * a window and exits without closing it.
> +	 */
> +	if (!tsk) {
> +		pid = task_ref->tgid;
> +		tsk = get_pid_task(pid, PIDTYPE_PID);
> +		/*
> +		 * Parent thread (tgid) will be closing window when it
> +		 * exits. So should not get here.
> +		 */
> +		if (WARN_ON_ONCE(!tsk))
> +			return;
> +	}
> +
> +	/* Return if the task is exiting. */
> +	if (tsk->flags & PF_EXITING) {
> +		put_task_struct(tsk);
> +		return;
> +	}

Just as an aside, I know this is existing code, after this series it 
might be good to think about factoring out this above chunk of code 
(possibly +/- the kthread_use_mm() bit), and put it together with the 
rest of the task/mm refcounting stuff.

Thanks,
Nick

> +
> +	kthread_use_mm(task_ref->mm);
> +	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
> +	/*
> +	 * User space polls on csb.flags (first byte). So add barrier
> +	 * then copy first byte with csb flags update.
> +	 */
> +	if (!rc) {
> +		csb.flags = CSB_V;
> +		/* Make sure update to csb.flags is visible now */
> +		smp_mb();
> +		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
> +	}
> +	kthread_unuse_mm(task_ref->mm);
> +	put_task_struct(tsk);
> +

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 05/16] powerpc/vas: Move update_csb/dump_crb to common book3s platform
@ 2021-06-03  4:26     ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:26 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of May 21, 2021 7:32 pm:
> +
> +	pid = task_ref->pid;
> +	tsk = get_pid_task(pid, PIDTYPE_PID);
> +	/*
> +	 * Process closes send window after all pending NX requests are
> +	 * completed. In multi-thread applications, a child thread can
> +	 * open a window and can exit without closing it. May be some
> +	 * requests are pending or this window can be used by other
> +	 * threads later. We should handle faults if NX encounters
> +	 * pages faults on these requests. Update CSB with translation
> +	 * error and fault address. If csb_addr passed by user space is
> +	 * invalid, send SEGV signal to pid saved in window. If the
> +	 * child thread is not running, send the signal to tgid.
> +	 * Parent thread (tgid) will close this window upon its exit.
> +	 *
> +	 * pid and mm references are taken when window is opened by
> +	 * process (pid). So tgid is used only when child thread opens
> +	 * a window and exits without closing it.
> +	 */
> +	if (!tsk) {
> +		pid = task_ref->tgid;
> +		tsk = get_pid_task(pid, PIDTYPE_PID);
> +		/*
> +		 * Parent thread (tgid) will be closing window when it
> +		 * exits. So should not get here.
> +		 */
> +		if (WARN_ON_ONCE(!tsk))
> +			return;
> +	}
> +
> +	/* Return if the task is exiting. */
> +	if (tsk->flags & PF_EXITING) {
> +		put_task_struct(tsk);
> +		return;
> +	}

Just as an aside, I know this is existing code, after this series it 
might be good to think about factoring out this above chunk of code 
(possibly +/- the kthread_use_mm() bit), and put it together with the 
rest of the task/mm refcounting stuff.

Thanks,
Nick

> +
> +	kthread_use_mm(task_ref->mm);
> +	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
> +	/*
> +	 * User space polls on csb.flags (first byte). So add barrier
> +	 * then copy first byte with csb flags update.
> +	 */
> +	if (!rc) {
> +		csb.flags = CSB_V;
> +		/* Make sure update to csb.flags is visible now */
> +		smp_mb();
> +		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
> +	}
> +	kthread_unuse_mm(task_ref->mm);
> +	put_task_struct(tsk);
> +

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
  2021-05-21  9:33   ` Haren Myneni
@ 2021-06-03  4:38     ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:38 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of May 21, 2021 7:33 pm:
> 
> Same vas_window struct is used on powerNV and pseries. So this patch
> changes in struct vas_window to support both platforms and also the
> corresponding modifications in powerNV vas code.
> 
> On powerNV, vas_window is used for both TX and RX windows, whereas
> only for TX windows on powerVM. So some elements are specific to
> these platforms.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/vas.h              |  50 +++++++-
>  arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
>  arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
>  arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
>  arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++---------
>  arch/powerpc/platforms/powernv/vas.h        |  38 +-----
>  6 files changed, 135 insertions(+), 104 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index 2c1040f399d9..49bfb5be896d 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -10,8 +10,6 @@
>  #include <asm/icswx.h>
>  #include <uapi/asm/vas-api.h>
>  
> -struct vas_window;
> -
>  /*
>   * Min and max FIFO sizes are based on Version 1.05 Section 3.1.4.25
>   * (Local FIFO Size Register) of the VAS workbook.
> @@ -63,6 +61,54 @@ struct vas_user_win_ref {
>  	struct mm_struct *mm;	/* Linux process mm_struct */
>  };
>  
> +/*
> + * In-kernel state a VAS window. One per window.
> + * powerVM: Used only for Tx windows.
> + * powerNV: Used for both Tx and Rx windows.
> + */
> +struct vas_window {
> +	u32 winid;
> +	u32 wcreds_max;	/* Window credits */
> +	enum vas_cop_type cop;
> +	struct vas_user_win_ref task_ref;
> +	char *dbgname;
> +	struct dentry *dbgdir;
> +	union {
> +		/* powerNV specific data */
> +		struct {
> +			void *vinst;	/* points to VAS instance */
> +			bool tx_win;	/* True if send window */
> +			bool nx_win;	/* True if NX window */
> +			bool user_win;	/* True if user space window */
> +			void *hvwc_map;	/* HV window context */
> +			void *uwc_map;	/* OS/User window context */
> +
> +			/* Fields applicable only to send windows */
> +			void *paste_kaddr;
> +			char *paste_addr_name;
> +			struct vas_window *rxwin;
> +
> +			atomic_t num_txwins;	/* Only for receive windows */
> +		} pnv;
> +		struct {
> +			u64 win_addr;	/* Physical paste address */
> +			u8 win_type;	/* QoS or Default window */
> +			u8 status;
> +			u32 complete_irq;	/* Completion interrupt */
> +			u32 fault_irq;	/* Fault interrupt */
> +			u64 domain[6];	/* Associativity domain Ids */
> +					/* this window is allocated */
> +			u64 util;
> +
> +			/* List of windows opened which is used for LPM */
> +			struct list_head win_list;
> +			u64 flags;
> +			char *name;
> +			int fault_virq;
> +		} lpar;
> +	};
> +};

The more typical way to do code like this is have the common bit as its 
own struct, and then have the users embed it into their own structs.


struct vas_window {
	u32 winid;
	u32 wcreds_max;	/* Window credits */
	enum vas_cop_type cop;
	struct vas_user_win_ref task_ref;
	char *dbgname;
	struct dentry *dbgdir;
};

struct pnv_vas_window {
	struct vas_window vas_window;

	void *vinst;	/* points to VAS instance */
	bool tx_win;	/* True if send window */
	bool nx_win;	/* True if NX window */
	bool user_win;	/* True if user space window */
	void *hvwc_map;	/* HV window context */
	void *uwc_map;	/* OS/User window context */

	/* Fields applicable only to send windows */
	void *paste_kaddr;
	char *paste_addr_name;
	struct vas_window *rxwin;

	atomic_t num_txwins;	/* Only for receive windows */
};

Which helps reusability / avoids churn (don't have to update the same 
structure to add new functionality), slightly helps naming and union 
size mismatches, helps with type checking, etc.

Maybe not a great benefit for your code as is which may not grow more
users, but unless there are some good reasons for the unions I would 
really consider changing to this style.

Thanks,
Nick

> +		struct {
> +			u64 win_addr;	/* Physical paste address */
> +			u8 win_type;	/* QoS or Default window */
> +			u8 status;
> +			u32 complete_irq;	/* Completion interrupt */
> +			u32 fault_irq;	/* Fault interrupt */
> +			u64 domain[6];	/* Associativity domain Ids */
> +					/* this window is allocated */
> +			u64 util;
> +
> +			/* List of windows opened which is used for LPM */
> +			struct list_head win_list;
> +			u64 flags;
> +			char *name;
> +			int fault_virq;
> +		} lpar;
> +	};
> +};

> +
>  /*
>   * User space window operations used for powernv and powerVM
>   */
> diff --git a/arch/powerpc/platforms/powernv/vas-debug.c b/arch/powerpc/platforms/powernv/vas-debug.c
> index 41fa90d2f4ab..80f735449ab8 100644
> --- a/arch/powerpc/platforms/powernv/vas-debug.c
> +++ b/arch/powerpc/platforms/powernv/vas-debug.c
> @@ -9,6 +9,7 @@
>  #include <linux/slab.h>
>  #include <linux/debugfs.h>
>  #include <linux/seq_file.h>
> +#include <asm/vas.h>
>  #include "vas.h"
>  
>  static struct dentry *vas_debugfs;
> @@ -33,11 +34,11 @@ static int info_show(struct seq_file *s, void *private)
>  	mutex_lock(&vas_mutex);
>  
>  	/* ensure window is not unmapped */
> -	if (!window->hvwc_map)
> +	if (!window->pnv.hvwc_map)
>  		goto unlock;
>  
>  	seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop),
> -					window->tx_win ? "Send" : "Receive");
> +				window->pnv.tx_win ? "Send" : "Receive");
>  	seq_printf(s, "Pid : %d\n", vas_window_pid(window));
>  
>  unlock:
> @@ -60,7 +61,7 @@ static int hvwc_show(struct seq_file *s, void *private)
>  	mutex_lock(&vas_mutex);
>  
>  	/* ensure window is not unmapped */
> -	if (!window->hvwc_map)
> +	if (!window->pnv.hvwc_map)
>  		goto unlock;
>  
>  	print_reg(s, window, VREG(LPID));
> @@ -115,9 +116,10 @@ void vas_window_free_dbgdir(struct vas_window *window)
>  
>  void vas_window_init_dbgdir(struct vas_window *window)
>  {
> +	struct vas_instance *vinst = window->pnv.vinst;
>  	struct dentry *d;
>  
> -	if (!window->vinst->dbgdir)
> +	if (!vinst->dbgdir)
>  		return;
>  
>  	window->dbgname = kzalloc(16, GFP_KERNEL);
> @@ -126,7 +128,7 @@ void vas_window_init_dbgdir(struct vas_window *window)
>  
>  	snprintf(window->dbgname, 16, "w%d", window->winid);
>  
> -	d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir);
> +	d = debugfs_create_dir(window->dbgname, vinst->dbgdir);
>  	window->dbgdir = d;
>  
>  	debugfs_create_file("info", 0444, d, window, &info_fops);
> diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> index 2729ac541fb3..faaf5b110645 100644
> --- a/arch/powerpc/platforms/powernv/vas-fault.c
> +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> @@ -152,10 +152,10 @@ irqreturn_t vas_fault_thread_fn(int irq, void *data)
>  			/*
>  			 * NX sees faults only with user space windows.
>  			 */
> -			if (window->user_win)
> +			if (window->pnv.user_win)
>  				vas_update_csb(crb, &window->task_ref);
>  			else
> -				WARN_ON_ONCE(!window->user_win);
> +				WARN_ON_ONCE(!window->pnv.user_win);
>  
>  			/*
>  			 * Return credit for send window after processing
> diff --git a/arch/powerpc/platforms/powernv/vas-trace.h b/arch/powerpc/platforms/powernv/vas-trace.h
> index a449b9f0c12e..843aae37c07a 100644
> --- a/arch/powerpc/platforms/powernv/vas-trace.h
> +++ b/arch/powerpc/platforms/powernv/vas-trace.h
> @@ -95,9 +95,11 @@ TRACE_EVENT(	vas_paste_crb,
>  
>  		TP_fast_assign(
>  			__entry->pid = tsk->pid;
> -			__entry->vasid = win->vinst->vas_id;
> +			__entry->vasid =
> +				((struct vas_instance *)win->pnv.vinst)->vas_id;
>  			__entry->winid = win->winid;
> -			__entry->paste_kaddr = (unsigned long)win->paste_kaddr
> +			__entry->paste_kaddr =
> +				(unsigned long)win->pnv.paste_kaddr;
>  		),
>  
>  		TP_printk("pid=%d, vasid=%d, winid=%d, paste_kaddr=0x%016lx\n",
> diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
> index ffd619e5a218..6ce8ee4b3371 100644
> --- a/arch/powerpc/platforms/powernv/vas-window.c
> +++ b/arch/powerpc/platforms/powernv/vas-window.c
> @@ -31,9 +31,10 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr, int *len)
>  {
>  	int winid;
>  	u64 base, shift;
> +	struct vas_instance *vinst = window->pnv.vinst;
>  
> -	base = window->vinst->paste_base_addr;
> -	shift = window->vinst->paste_win_id_shift;
> +	base = vinst->paste_base_addr;
> +	shift = vinst->paste_win_id_shift;
>  	winid = window->winid;
>  
>  	*addr  = base + (winid << shift);
> @@ -46,9 +47,10 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr, int *len)
>  static inline void get_hvwc_mmio_bar(struct vas_window *window,
>  			u64 *start, int *len)
>  {
> +	struct vas_instance *vinst = window->pnv.vinst;
>  	u64 pbaddr;
>  
> -	pbaddr = window->vinst->hvwc_bar_start;
> +	pbaddr = vinst->hvwc_bar_start;
>  	*start = pbaddr + window->winid * VAS_HVWC_SIZE;
>  	*len = VAS_HVWC_SIZE;
>  }
> @@ -56,9 +58,10 @@ static inline void get_hvwc_mmio_bar(struct vas_window *window,
>  static inline void get_uwc_mmio_bar(struct vas_window *window,
>  			u64 *start, int *len)
>  {
> +	struct vas_instance *vinst = window->pnv.vinst;
>  	u64 pbaddr;
>  
> -	pbaddr = window->vinst->uwc_bar_start;
> +	pbaddr = vinst->uwc_bar_start;
>  	*start = pbaddr + window->winid * VAS_UWC_SIZE;
>  	*len = VAS_UWC_SIZE;
>  }
> @@ -74,13 +77,14 @@ static void *map_paste_region(struct vas_window *txwin)
>  	void *map;
>  	char *name;
>  	u64 start;
> +	struct vas_instance *vinst = txwin->pnv.vinst;
>  
> -	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", txwin->vinst->vas_id,
> +	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", vinst->vas_id,
>  				txwin->winid);
>  	if (!name)
>  		goto free_name;
>  
> -	txwin->paste_addr_name = name;
> +	txwin->pnv.paste_addr_name = name;
>  	vas_win_paste_addr(txwin, &start, &len);
>  
>  	if (!request_mem_region(start, len, name)) {
> @@ -138,12 +142,12 @@ static void unmap_paste_region(struct vas_window *window)
>  	int len;
>  	u64 busaddr_start;
>  
> -	if (window->paste_kaddr) {
> +	if (window->pnv.paste_kaddr) {
>  		vas_win_paste_addr(window, &busaddr_start, &len);
> -		unmap_region(window->paste_kaddr, busaddr_start, len);
> -		window->paste_kaddr = NULL;
> -		kfree(window->paste_addr_name);
> -		window->paste_addr_name = NULL;
> +		unmap_region(window->pnv.paste_kaddr, busaddr_start, len);
> +		window->pnv.paste_kaddr = NULL;
> +		kfree(window->pnv.paste_addr_name);
> +		window->pnv.paste_addr_name = NULL;
>  	}
>  }
>  
> @@ -163,11 +167,11 @@ static void unmap_winctx_mmio_bars(struct vas_window *window)
>  
>  	mutex_lock(&vas_mutex);
>  
> -	hvwc_map = window->hvwc_map;
> -	window->hvwc_map = NULL;
> +	hvwc_map = window->pnv.hvwc_map;
> +	window->pnv.hvwc_map = NULL;
>  
> -	uwc_map = window->uwc_map;
> -	window->uwc_map = NULL;
> +	uwc_map = window->pnv.uwc_map;
> +	window->pnv.uwc_map = NULL;
>  
>  	mutex_unlock(&vas_mutex);
>  
> @@ -193,12 +197,12 @@ static int map_winctx_mmio_bars(struct vas_window *window)
>  	u64 start;
>  
>  	get_hvwc_mmio_bar(window, &start, &len);
> -	window->hvwc_map = map_mmio_region("HVWCM_Window", start, len);
> +	window->pnv.hvwc_map = map_mmio_region("HVWCM_Window", start, len);
>  
>  	get_uwc_mmio_bar(window, &start, &len);
> -	window->uwc_map = map_mmio_region("UWCM_Window", start, len);
> +	window->pnv.uwc_map = map_mmio_region("UWCM_Window", start, len);
>  
> -	if (!window->hvwc_map || !window->uwc_map) {
> +	if (!window->pnv.hvwc_map || !window->pnv.uwc_map) {
>  		unmap_winctx_mmio_bars(window);
>  		return -1;
>  	}
> @@ -523,7 +527,7 @@ static int vas_assign_window_id(struct ida *ida)
>  static void vas_window_free(struct vas_window *window)
>  {
>  	int winid = window->winid;
> -	struct vas_instance *vinst = window->vinst;
> +	struct vas_instance *vinst = window->pnv.vinst;
>  
>  	unmap_winctx_mmio_bars(window);
>  
> @@ -547,7 +551,7 @@ static struct vas_window *vas_window_alloc(struct vas_instance *vinst)
>  	if (!window)
>  		goto out_free;
>  
> -	window->vinst = vinst;
> +	window->pnv.vinst = vinst;
>  	window->winid = winid;
>  
>  	if (map_winctx_mmio_bars(window))
> @@ -566,9 +570,9 @@ static struct vas_window *vas_window_alloc(struct vas_instance *vinst)
>  static void put_rx_win(struct vas_window *rxwin)
>  {
>  	/* Better not be a send window! */
> -	WARN_ON_ONCE(rxwin->tx_win);
> +	WARN_ON_ONCE(rxwin->pnv.tx_win);
>  
> -	atomic_dec(&rxwin->num_txwins);
> +	atomic_dec(&rxwin->pnv.num_txwins);
>  }
>  
>  /*
> @@ -591,7 +595,7 @@ static struct vas_window *get_user_rxwin(struct vas_instance *vinst, u32 pswid)
>  
>  	rxwin = vinst->windows[winid];
>  
> -	if (!rxwin || rxwin->tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
> +	if (!rxwin || rxwin->pnv.tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
>  		return ERR_PTR(-EINVAL);
>  
>  	return rxwin;
> @@ -616,7 +620,7 @@ static struct vas_window *get_vinst_rxwin(struct vas_instance *vinst,
>  		rxwin = vinst->rxwin[cop] ?: ERR_PTR(-EINVAL);
>  
>  	if (!IS_ERR(rxwin))
> -		atomic_inc(&rxwin->num_txwins);
> +		atomic_inc(&rxwin->pnv.num_txwins);
>  
>  	mutex_unlock(&vinst->mutex);
>  
> @@ -649,7 +653,7 @@ static void set_vinst_win(struct vas_instance *vinst,
>  	 * There should only be one receive window for a coprocessor type
>  	 * unless its a user (FTW) window.
>  	 */
> -	if (!window->user_win && !window->tx_win) {
> +	if (!window->pnv.user_win && !window->pnv.tx_win) {
>  		WARN_ON_ONCE(vinst->rxwin[window->cop]);
>  		vinst->rxwin[window->cop] = window;
>  	}
> @@ -667,11 +671,11 @@ static void set_vinst_win(struct vas_instance *vinst,
>  static void clear_vinst_win(struct vas_window *window)
>  {
>  	int id = window->winid;
> -	struct vas_instance *vinst = window->vinst;
> +	struct vas_instance *vinst = window->pnv.vinst;
>  
>  	mutex_lock(&vinst->mutex);
>  
> -	if (!window->user_win && !window->tx_win) {
> +	if (!window->pnv.user_win && !window->pnv.tx_win) {
>  		WARN_ON_ONCE(!vinst->rxwin[window->cop]);
>  		vinst->rxwin[window->cop] = NULL;
>  	}
> @@ -686,6 +690,8 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin,
>  			struct vas_rx_win_attr *rxattr,
>  			struct vas_winctx *winctx)
>  {
> +	struct vas_instance *vinst;
> +
>  	/*
>  	 * We first zero (memset()) all fields and only set non-zero fields.
>  	 * Following fields are 0/false but maybe deserve a comment:
> @@ -750,8 +756,9 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin,
>  
>  	winctx->min_scope = VAS_SCOPE_LOCAL;
>  	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
> -	if (rxwin->vinst->virq)
> -		winctx->irq_port = rxwin->vinst->irq_port;
> +	vinst = rxwin->pnv.vinst;
> +	if (vinst->virq)
> +		winctx->irq_port = vinst->irq_port;
>  }
>  
>  static bool rx_win_args_valid(enum vas_cop_type cop,
> @@ -874,9 +881,9 @@ struct vas_window *vas_rx_win_open(int vasid, enum vas_cop_type cop,
>  		return rxwin;
>  	}
>  
> -	rxwin->tx_win = false;
> -	rxwin->nx_win = rxattr->nx_win;
> -	rxwin->user_win = rxattr->user_win;
> +	rxwin->pnv.tx_win = false;
> +	rxwin->pnv.nx_win = rxattr->nx_win;
> +	rxwin->pnv.user_win = rxattr->user_win;
>  	rxwin->cop = cop;
>  	rxwin->wcreds_max = rxattr->wcreds_max;
>  
> @@ -910,6 +917,8 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
>  			struct vas_tx_win_attr *txattr,
>  			struct vas_winctx *winctx)
>  {
> +	struct vas_instance *vinst = txwin->pnv.vinst;
> +
>  	/*
>  	 * We first zero all fields and only set non-zero ones. Following
>  	 * are some fields set to 0/false for the stated reason:
> @@ -930,7 +939,7 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
>  	winctx->wcreds_max = txwin->wcreds_max;
>  
>  	winctx->user_win = txattr->user_win;
> -	winctx->nx_win = txwin->rxwin->nx_win;
> +	winctx->nx_win = txwin->pnv.rxwin->pnv.nx_win;
>  	winctx->pin_win = txattr->pin_win;
>  	winctx->rej_no_credit = txattr->rej_no_credit;
>  	winctx->rsvd_txbuf_enable = txattr->rsvd_txbuf_enable;
> @@ -947,23 +956,23 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
>  
>  	winctx->lpid = txattr->lpid;
>  	winctx->pidr = txattr->pidr;
> -	winctx->rx_win_id = txwin->rxwin->winid;
> +	winctx->rx_win_id = txwin->pnv.rxwin->winid;
>  	/*
>  	 * IRQ and fault window setup is successful. Set fault window
>  	 * for the send window so that ready to handle faults.
>  	 */
> -	if (txwin->vinst->virq)
> -		winctx->fault_win_id = txwin->vinst->fault_win->winid;
> +	if (vinst->virq)
> +		winctx->fault_win_id = vinst->fault_win->winid;
>  
>  	winctx->dma_type = VAS_DMA_TYPE_INJECT;
>  	winctx->tc_mode = txattr->tc_mode;
>  	winctx->min_scope = VAS_SCOPE_LOCAL;
>  	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
> -	if (txwin->vinst->virq)
> -		winctx->irq_port = txwin->vinst->irq_port;
> +	if (vinst->virq)
> +		winctx->irq_port = vinst->irq_port;
>  
>  	winctx->pswid = txattr->pswid ? txattr->pswid :
> -			encode_pswid(txwin->vinst->vas_id, txwin->winid);
> +			encode_pswid(vinst->vas_id, txwin->winid);
>  }
>  
>  static bool tx_win_args_valid(enum vas_cop_type cop,
> @@ -1031,10 +1040,10 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
>  	}
>  
>  	txwin->cop = cop;
> -	txwin->tx_win = 1;
> -	txwin->rxwin = rxwin;
> -	txwin->nx_win = txwin->rxwin->nx_win;
> -	txwin->user_win = attr->user_win;
> +	txwin->pnv.tx_win = 1;
> +	txwin->pnv.rxwin = rxwin;
> +	txwin->pnv.nx_win = txwin->pnv.rxwin->pnv.nx_win;
> +	txwin->pnv.user_win = attr->user_win;
>  	txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT;
>  
>  	init_winctx_for_txwin(txwin, attr, &winctx);
> @@ -1049,10 +1058,10 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
>  	 * NOTE: If kernel ever resubmits a user CRB after handling a page
>  	 *	 fault, we will need to map this into kernel as well.
>  	 */
> -	if (!txwin->user_win) {
> -		txwin->paste_kaddr = map_paste_region(txwin);
> -		if (IS_ERR(txwin->paste_kaddr)) {
> -			rc = PTR_ERR(txwin->paste_kaddr);
> +	if (!txwin->pnv.user_win) {
> +		txwin->pnv.paste_kaddr = map_paste_region(txwin);
> +		if (IS_ERR(txwin->pnv.paste_kaddr)) {
> +			rc = PTR_ERR(txwin->pnv.paste_kaddr);
>  			goto free_window;
>  		}
>  	} else {
> @@ -1104,9 +1113,9 @@ int vas_paste_crb(struct vas_window *txwin, int offset, bool re)
>  	 * report-enable flag is set for NX windows. Ensure software
>  	 * complies too.
>  	 */
> -	WARN_ON_ONCE(txwin->nx_win && !re);
> +	WARN_ON_ONCE(txwin->pnv.nx_win && !re);
>  
> -	addr = txwin->paste_kaddr;
> +	addr = txwin->pnv.paste_kaddr;
>  	if (re) {
>  		/*
>  		 * Set the REPORT_ENABLE bit (equivalent to writing
> @@ -1153,7 +1162,7 @@ static void poll_window_credits(struct vas_window *window)
>  	int count = 0;
>  
>  	val = read_hvwc_reg(window, VREG(WINCTL));
> -	if (window->tx_win)
> +	if (window->pnv.tx_win)
>  		mode = GET_FIELD(VAS_WINCTL_TX_WCRED_MODE, val);
>  	else
>  		mode = GET_FIELD(VAS_WINCTL_RX_WCRED_MODE, val);
> @@ -1161,7 +1170,7 @@ static void poll_window_credits(struct vas_window *window)
>  	if (!mode)
>  		return;
>  retry:
> -	if (window->tx_win) {
> +	if (window->pnv.tx_win) {
>  		val = read_hvwc_reg(window, VREG(TX_WCRED));
>  		creds = GET_FIELD(VAS_TX_WCRED, val);
>  	} else {
> @@ -1277,7 +1286,7 @@ int vas_win_close(struct vas_window *window)
>  	if (!window)
>  		return 0;
>  
> -	if (!window->tx_win && atomic_read(&window->num_txwins) != 0) {
> +	if (!window->pnv.tx_win && atomic_read(&window->pnv.num_txwins) != 0) {
>  		pr_devel("Attempting to close an active Rx window!\n");
>  		WARN_ON_ONCE(1);
>  		return -EBUSY;
> @@ -1296,11 +1305,11 @@ int vas_win_close(struct vas_window *window)
>  	poll_window_castout(window);
>  
>  	/* if send window, drop reference to matching receive window */
> -	if (window->tx_win) {
> -		if (window->user_win)
> +	if (window->pnv.tx_win) {
> +		if (window->pnv.user_win)
>  			vas_drop_reference_pid_mm(&window->task_ref);
>  
> -		put_rx_win(window->rxwin);
> +		put_rx_win(window->pnv.rxwin);
>  	}
>  
>  	vas_window_free(window);
> @@ -1384,12 +1393,12 @@ struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
>  	 * since their CRBs are ignored (not queued on FIFO or processed
>  	 * by NX).
>  	 */
> -	if (!window->tx_win || !window->user_win || !window->nx_win ||
> -			window->cop == VAS_COP_TYPE_FAULT ||
> -			window->cop == VAS_COP_TYPE_FTW) {
> +	if (!window->pnv.tx_win || !window->pnv.user_win ||
> +		!window->pnv.nx_win || window->cop == VAS_COP_TYPE_FAULT ||
> +		window->cop == VAS_COP_TYPE_FTW) {
>  		pr_err("PSWID decode: id %d, tx %d, user %d, nx %d, cop %d\n",
> -			winid, window->tx_win, window->user_win,
> -			window->nx_win, window->cop);
> +			winid, window->pnv.tx_win, window->pnv.user_win,
> +			window->pnv.nx_win, window->cop);
>  		WARN_ON(1);
>  	}
>  
> diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
> index f354dd5c51bd..f2d9daff3d82 100644
> --- a/arch/powerpc/platforms/powernv/vas.h
> +++ b/arch/powerpc/platforms/powernv/vas.h
> @@ -345,34 +345,6 @@ struct vas_instance {
>  	struct dentry *dbgdir;
>  };
>  
> -/*
> - * In-kernel state a VAS window. One per window.
> - */
> -struct vas_window {
> -	/* Fields common to send and receive windows */
> -	struct vas_instance *vinst;
> -	int winid;
> -	bool tx_win;		/* True if send window */
> -	bool nx_win;		/* True if NX window */
> -	bool user_win;		/* True if user space window */
> -	void *hvwc_map;		/* HV window context */
> -	void *uwc_map;		/* OS/User window context */
> -	int wcreds_max;		/* Window credits */
> -
> -	struct vas_user_win_ref task_ref;
> -	char *dbgname;
> -	struct dentry *dbgdir;
> -
> -	/* Fields applicable only to send windows */
> -	void *paste_kaddr;
> -	char *paste_addr_name;
> -	struct vas_window *rxwin;
> -
> -	/* Feilds applicable only to receive windows */
> -	enum vas_cop_type cop;
> -	atomic_t num_txwins;
> -};
> -
>  /*
>   * Container for the hardware state of a window. One per-window.
>   *
> @@ -449,8 +421,8 @@ static inline void vas_log_write(struct vas_window *win, char *name,
>  {
>  	if (val)
>  		pr_debug("%swin #%d: %s reg %p, val 0x%016llx\n",
> -				win->tx_win ? "Tx" : "Rx", win->winid, name,
> -				regptr, val);
> +				win->pnv.tx_win ? "Tx" : "Rx", win->winid,
> +				name, regptr, val);
>  }
>  
>  static inline void write_uwc_reg(struct vas_window *win, char *name,
> @@ -458,7 +430,7 @@ static inline void write_uwc_reg(struct vas_window *win, char *name,
>  {
>  	void *regptr;
>  
> -	regptr = win->uwc_map + reg;
> +	regptr = win->pnv.uwc_map + reg;
>  	vas_log_write(win, name, regptr, val);
>  
>  	out_be64(regptr, val);
> @@ -469,7 +441,7 @@ static inline void write_hvwc_reg(struct vas_window *win, char *name,
>  {
>  	void *regptr;
>  
> -	regptr = win->hvwc_map + reg;
> +	regptr = win->pnv.hvwc_map + reg;
>  	vas_log_write(win, name, regptr, val);
>  
>  	out_be64(regptr, val);
> @@ -478,7 +450,7 @@ static inline void write_hvwc_reg(struct vas_window *win, char *name,
>  static inline u64 read_hvwc_reg(struct vas_window *win,
>  			char *name __maybe_unused, s32 reg)
>  {
> -	return in_be64(win->hvwc_map+reg);
> +	return in_be64(win->pnv.hvwc_map + reg);
>  }
>  
>  /*
> -- 
> 2.18.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
@ 2021-06-03  4:38     ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:38 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of May 21, 2021 7:33 pm:
> 
> Same vas_window struct is used on powerNV and pseries. So this patch
> changes in struct vas_window to support both platforms and also the
> corresponding modifications in powerNV vas code.
> 
> On powerNV, vas_window is used for both TX and RX windows, whereas
> only for TX windows on powerVM. So some elements are specific to
> these platforms.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/vas.h              |  50 +++++++-
>  arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
>  arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
>  arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
>  arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++---------
>  arch/powerpc/platforms/powernv/vas.h        |  38 +-----
>  6 files changed, 135 insertions(+), 104 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index 2c1040f399d9..49bfb5be896d 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -10,8 +10,6 @@
>  #include <asm/icswx.h>
>  #include <uapi/asm/vas-api.h>
>  
> -struct vas_window;
> -
>  /*
>   * Min and max FIFO sizes are based on Version 1.05 Section 3.1.4.25
>   * (Local FIFO Size Register) of the VAS workbook.
> @@ -63,6 +61,54 @@ struct vas_user_win_ref {
>  	struct mm_struct *mm;	/* Linux process mm_struct */
>  };
>  
> +/*
> + * In-kernel state a VAS window. One per window.
> + * powerVM: Used only for Tx windows.
> + * powerNV: Used for both Tx and Rx windows.
> + */
> +struct vas_window {
> +	u32 winid;
> +	u32 wcreds_max;	/* Window credits */
> +	enum vas_cop_type cop;
> +	struct vas_user_win_ref task_ref;
> +	char *dbgname;
> +	struct dentry *dbgdir;
> +	union {
> +		/* powerNV specific data */
> +		struct {
> +			void *vinst;	/* points to VAS instance */
> +			bool tx_win;	/* True if send window */
> +			bool nx_win;	/* True if NX window */
> +			bool user_win;	/* True if user space window */
> +			void *hvwc_map;	/* HV window context */
> +			void *uwc_map;	/* OS/User window context */
> +
> +			/* Fields applicable only to send windows */
> +			void *paste_kaddr;
> +			char *paste_addr_name;
> +			struct vas_window *rxwin;
> +
> +			atomic_t num_txwins;	/* Only for receive windows */
> +		} pnv;
> +		struct {
> +			u64 win_addr;	/* Physical paste address */
> +			u8 win_type;	/* QoS or Default window */
> +			u8 status;
> +			u32 complete_irq;	/* Completion interrupt */
> +			u32 fault_irq;	/* Fault interrupt */
> +			u64 domain[6];	/* Associativity domain Ids */
> +					/* this window is allocated */
> +			u64 util;
> +
> +			/* List of windows opened which is used for LPM */
> +			struct list_head win_list;
> +			u64 flags;
> +			char *name;
> +			int fault_virq;
> +		} lpar;
> +	};
> +};

The more typical way to do code like this is have the common bit as its 
own struct, and then have the users embed it into their own structs.


struct vas_window {
	u32 winid;
	u32 wcreds_max;	/* Window credits */
	enum vas_cop_type cop;
	struct vas_user_win_ref task_ref;
	char *dbgname;
	struct dentry *dbgdir;
};

struct pnv_vas_window {
	struct vas_window vas_window;

	void *vinst;	/* points to VAS instance */
	bool tx_win;	/* True if send window */
	bool nx_win;	/* True if NX window */
	bool user_win;	/* True if user space window */
	void *hvwc_map;	/* HV window context */
	void *uwc_map;	/* OS/User window context */

	/* Fields applicable only to send windows */
	void *paste_kaddr;
	char *paste_addr_name;
	struct vas_window *rxwin;

	atomic_t num_txwins;	/* Only for receive windows */
};

Which helps reusability / avoids churn (don't have to update the same 
structure to add new functionality), slightly helps naming and union 
size mismatches, helps with type checking, etc.

Maybe not a great benefit for your code as is which may not grow more
users, but unless there are some good reasons for the unions I would 
really consider changing to this style.

Thanks,
Nick

> +		struct {
> +			u64 win_addr;	/* Physical paste address */
> +			u8 win_type;	/* QoS or Default window */
> +			u8 status;
> +			u32 complete_irq;	/* Completion interrupt */
> +			u32 fault_irq;	/* Fault interrupt */
> +			u64 domain[6];	/* Associativity domain Ids */
> +					/* this window is allocated */
> +			u64 util;
> +
> +			/* List of windows opened which is used for LPM */
> +			struct list_head win_list;
> +			u64 flags;
> +			char *name;
> +			int fault_virq;
> +		} lpar;
> +	};
> +};

> +
>  /*
>   * User space window operations used for powernv and powerVM
>   */
> diff --git a/arch/powerpc/platforms/powernv/vas-debug.c b/arch/powerpc/platforms/powernv/vas-debug.c
> index 41fa90d2f4ab..80f735449ab8 100644
> --- a/arch/powerpc/platforms/powernv/vas-debug.c
> +++ b/arch/powerpc/platforms/powernv/vas-debug.c
> @@ -9,6 +9,7 @@
>  #include <linux/slab.h>
>  #include <linux/debugfs.h>
>  #include <linux/seq_file.h>
> +#include <asm/vas.h>
>  #include "vas.h"
>  
>  static struct dentry *vas_debugfs;
> @@ -33,11 +34,11 @@ static int info_show(struct seq_file *s, void *private)
>  	mutex_lock(&vas_mutex);
>  
>  	/* ensure window is not unmapped */
> -	if (!window->hvwc_map)
> +	if (!window->pnv.hvwc_map)
>  		goto unlock;
>  
>  	seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop),
> -					window->tx_win ? "Send" : "Receive");
> +				window->pnv.tx_win ? "Send" : "Receive");
>  	seq_printf(s, "Pid : %d\n", vas_window_pid(window));
>  
>  unlock:
> @@ -60,7 +61,7 @@ static int hvwc_show(struct seq_file *s, void *private)
>  	mutex_lock(&vas_mutex);
>  
>  	/* ensure window is not unmapped */
> -	if (!window->hvwc_map)
> +	if (!window->pnv.hvwc_map)
>  		goto unlock;
>  
>  	print_reg(s, window, VREG(LPID));
> @@ -115,9 +116,10 @@ void vas_window_free_dbgdir(struct vas_window *window)
>  
>  void vas_window_init_dbgdir(struct vas_window *window)
>  {
> +	struct vas_instance *vinst = window->pnv.vinst;
>  	struct dentry *d;
>  
> -	if (!window->vinst->dbgdir)
> +	if (!vinst->dbgdir)
>  		return;
>  
>  	window->dbgname = kzalloc(16, GFP_KERNEL);
> @@ -126,7 +128,7 @@ void vas_window_init_dbgdir(struct vas_window *window)
>  
>  	snprintf(window->dbgname, 16, "w%d", window->winid);
>  
> -	d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir);
> +	d = debugfs_create_dir(window->dbgname, vinst->dbgdir);
>  	window->dbgdir = d;
>  
>  	debugfs_create_file("info", 0444, d, window, &info_fops);
> diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> index 2729ac541fb3..faaf5b110645 100644
> --- a/arch/powerpc/platforms/powernv/vas-fault.c
> +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> @@ -152,10 +152,10 @@ irqreturn_t vas_fault_thread_fn(int irq, void *data)
>  			/*
>  			 * NX sees faults only with user space windows.
>  			 */
> -			if (window->user_win)
> +			if (window->pnv.user_win)
>  				vas_update_csb(crb, &window->task_ref);
>  			else
> -				WARN_ON_ONCE(!window->user_win);
> +				WARN_ON_ONCE(!window->pnv.user_win);
>  
>  			/*
>  			 * Return credit for send window after processing
> diff --git a/arch/powerpc/platforms/powernv/vas-trace.h b/arch/powerpc/platforms/powernv/vas-trace.h
> index a449b9f0c12e..843aae37c07a 100644
> --- a/arch/powerpc/platforms/powernv/vas-trace.h
> +++ b/arch/powerpc/platforms/powernv/vas-trace.h
> @@ -95,9 +95,11 @@ TRACE_EVENT(	vas_paste_crb,
>  
>  		TP_fast_assign(
>  			__entry->pid = tsk->pid;
> -			__entry->vasid = win->vinst->vas_id;
> +			__entry->vasid =
> +				((struct vas_instance *)win->pnv.vinst)->vas_id;
>  			__entry->winid = win->winid;
> -			__entry->paste_kaddr = (unsigned long)win->paste_kaddr
> +			__entry->paste_kaddr =
> +				(unsigned long)win->pnv.paste_kaddr;
>  		),
>  
>  		TP_printk("pid=%d, vasid=%d, winid=%d, paste_kaddr=0x%016lx\n",
> diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
> index ffd619e5a218..6ce8ee4b3371 100644
> --- a/arch/powerpc/platforms/powernv/vas-window.c
> +++ b/arch/powerpc/platforms/powernv/vas-window.c
> @@ -31,9 +31,10 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr, int *len)
>  {
>  	int winid;
>  	u64 base, shift;
> +	struct vas_instance *vinst = window->pnv.vinst;
>  
> -	base = window->vinst->paste_base_addr;
> -	shift = window->vinst->paste_win_id_shift;
> +	base = vinst->paste_base_addr;
> +	shift = vinst->paste_win_id_shift;
>  	winid = window->winid;
>  
>  	*addr  = base + (winid << shift);
> @@ -46,9 +47,10 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr, int *len)
>  static inline void get_hvwc_mmio_bar(struct vas_window *window,
>  			u64 *start, int *len)
>  {
> +	struct vas_instance *vinst = window->pnv.vinst;
>  	u64 pbaddr;
>  
> -	pbaddr = window->vinst->hvwc_bar_start;
> +	pbaddr = vinst->hvwc_bar_start;
>  	*start = pbaddr + window->winid * VAS_HVWC_SIZE;
>  	*len = VAS_HVWC_SIZE;
>  }
> @@ -56,9 +58,10 @@ static inline void get_hvwc_mmio_bar(struct vas_window *window,
>  static inline void get_uwc_mmio_bar(struct vas_window *window,
>  			u64 *start, int *len)
>  {
> +	struct vas_instance *vinst = window->pnv.vinst;
>  	u64 pbaddr;
>  
> -	pbaddr = window->vinst->uwc_bar_start;
> +	pbaddr = vinst->uwc_bar_start;
>  	*start = pbaddr + window->winid * VAS_UWC_SIZE;
>  	*len = VAS_UWC_SIZE;
>  }
> @@ -74,13 +77,14 @@ static void *map_paste_region(struct vas_window *txwin)
>  	void *map;
>  	char *name;
>  	u64 start;
> +	struct vas_instance *vinst = txwin->pnv.vinst;
>  
> -	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", txwin->vinst->vas_id,
> +	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", vinst->vas_id,
>  				txwin->winid);
>  	if (!name)
>  		goto free_name;
>  
> -	txwin->paste_addr_name = name;
> +	txwin->pnv.paste_addr_name = name;
>  	vas_win_paste_addr(txwin, &start, &len);
>  
>  	if (!request_mem_region(start, len, name)) {
> @@ -138,12 +142,12 @@ static void unmap_paste_region(struct vas_window *window)
>  	int len;
>  	u64 busaddr_start;
>  
> -	if (window->paste_kaddr) {
> +	if (window->pnv.paste_kaddr) {
>  		vas_win_paste_addr(window, &busaddr_start, &len);
> -		unmap_region(window->paste_kaddr, busaddr_start, len);
> -		window->paste_kaddr = NULL;
> -		kfree(window->paste_addr_name);
> -		window->paste_addr_name = NULL;
> +		unmap_region(window->pnv.paste_kaddr, busaddr_start, len);
> +		window->pnv.paste_kaddr = NULL;
> +		kfree(window->pnv.paste_addr_name);
> +		window->pnv.paste_addr_name = NULL;
>  	}
>  }
>  
> @@ -163,11 +167,11 @@ static void unmap_winctx_mmio_bars(struct vas_window *window)
>  
>  	mutex_lock(&vas_mutex);
>  
> -	hvwc_map = window->hvwc_map;
> -	window->hvwc_map = NULL;
> +	hvwc_map = window->pnv.hvwc_map;
> +	window->pnv.hvwc_map = NULL;
>  
> -	uwc_map = window->uwc_map;
> -	window->uwc_map = NULL;
> +	uwc_map = window->pnv.uwc_map;
> +	window->pnv.uwc_map = NULL;
>  
>  	mutex_unlock(&vas_mutex);
>  
> @@ -193,12 +197,12 @@ static int map_winctx_mmio_bars(struct vas_window *window)
>  	u64 start;
>  
>  	get_hvwc_mmio_bar(window, &start, &len);
> -	window->hvwc_map = map_mmio_region("HVWCM_Window", start, len);
> +	window->pnv.hvwc_map = map_mmio_region("HVWCM_Window", start, len);
>  
>  	get_uwc_mmio_bar(window, &start, &len);
> -	window->uwc_map = map_mmio_region("UWCM_Window", start, len);
> +	window->pnv.uwc_map = map_mmio_region("UWCM_Window", start, len);
>  
> -	if (!window->hvwc_map || !window->uwc_map) {
> +	if (!window->pnv.hvwc_map || !window->pnv.uwc_map) {
>  		unmap_winctx_mmio_bars(window);
>  		return -1;
>  	}
> @@ -523,7 +527,7 @@ static int vas_assign_window_id(struct ida *ida)
>  static void vas_window_free(struct vas_window *window)
>  {
>  	int winid = window->winid;
> -	struct vas_instance *vinst = window->vinst;
> +	struct vas_instance *vinst = window->pnv.vinst;
>  
>  	unmap_winctx_mmio_bars(window);
>  
> @@ -547,7 +551,7 @@ static struct vas_window *vas_window_alloc(struct vas_instance *vinst)
>  	if (!window)
>  		goto out_free;
>  
> -	window->vinst = vinst;
> +	window->pnv.vinst = vinst;
>  	window->winid = winid;
>  
>  	if (map_winctx_mmio_bars(window))
> @@ -566,9 +570,9 @@ static struct vas_window *vas_window_alloc(struct vas_instance *vinst)
>  static void put_rx_win(struct vas_window *rxwin)
>  {
>  	/* Better not be a send window! */
> -	WARN_ON_ONCE(rxwin->tx_win);
> +	WARN_ON_ONCE(rxwin->pnv.tx_win);
>  
> -	atomic_dec(&rxwin->num_txwins);
> +	atomic_dec(&rxwin->pnv.num_txwins);
>  }
>  
>  /*
> @@ -591,7 +595,7 @@ static struct vas_window *get_user_rxwin(struct vas_instance *vinst, u32 pswid)
>  
>  	rxwin = vinst->windows[winid];
>  
> -	if (!rxwin || rxwin->tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
> +	if (!rxwin || rxwin->pnv.tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
>  		return ERR_PTR(-EINVAL);
>  
>  	return rxwin;
> @@ -616,7 +620,7 @@ static struct vas_window *get_vinst_rxwin(struct vas_instance *vinst,
>  		rxwin = vinst->rxwin[cop] ?: ERR_PTR(-EINVAL);
>  
>  	if (!IS_ERR(rxwin))
> -		atomic_inc(&rxwin->num_txwins);
> +		atomic_inc(&rxwin->pnv.num_txwins);
>  
>  	mutex_unlock(&vinst->mutex);
>  
> @@ -649,7 +653,7 @@ static void set_vinst_win(struct vas_instance *vinst,
>  	 * There should only be one receive window for a coprocessor type
>  	 * unless its a user (FTW) window.
>  	 */
> -	if (!window->user_win && !window->tx_win) {
> +	if (!window->pnv.user_win && !window->pnv.tx_win) {
>  		WARN_ON_ONCE(vinst->rxwin[window->cop]);
>  		vinst->rxwin[window->cop] = window;
>  	}
> @@ -667,11 +671,11 @@ static void set_vinst_win(struct vas_instance *vinst,
>  static void clear_vinst_win(struct vas_window *window)
>  {
>  	int id = window->winid;
> -	struct vas_instance *vinst = window->vinst;
> +	struct vas_instance *vinst = window->pnv.vinst;
>  
>  	mutex_lock(&vinst->mutex);
>  
> -	if (!window->user_win && !window->tx_win) {
> +	if (!window->pnv.user_win && !window->pnv.tx_win) {
>  		WARN_ON_ONCE(!vinst->rxwin[window->cop]);
>  		vinst->rxwin[window->cop] = NULL;
>  	}
> @@ -686,6 +690,8 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin,
>  			struct vas_rx_win_attr *rxattr,
>  			struct vas_winctx *winctx)
>  {
> +	struct vas_instance *vinst;
> +
>  	/*
>  	 * We first zero (memset()) all fields and only set non-zero fields.
>  	 * Following fields are 0/false but maybe deserve a comment:
> @@ -750,8 +756,9 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin,
>  
>  	winctx->min_scope = VAS_SCOPE_LOCAL;
>  	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
> -	if (rxwin->vinst->virq)
> -		winctx->irq_port = rxwin->vinst->irq_port;
> +	vinst = rxwin->pnv.vinst;
> +	if (vinst->virq)
> +		winctx->irq_port = vinst->irq_port;
>  }
>  
>  static bool rx_win_args_valid(enum vas_cop_type cop,
> @@ -874,9 +881,9 @@ struct vas_window *vas_rx_win_open(int vasid, enum vas_cop_type cop,
>  		return rxwin;
>  	}
>  
> -	rxwin->tx_win = false;
> -	rxwin->nx_win = rxattr->nx_win;
> -	rxwin->user_win = rxattr->user_win;
> +	rxwin->pnv.tx_win = false;
> +	rxwin->pnv.nx_win = rxattr->nx_win;
> +	rxwin->pnv.user_win = rxattr->user_win;
>  	rxwin->cop = cop;
>  	rxwin->wcreds_max = rxattr->wcreds_max;
>  
> @@ -910,6 +917,8 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
>  			struct vas_tx_win_attr *txattr,
>  			struct vas_winctx *winctx)
>  {
> +	struct vas_instance *vinst = txwin->pnv.vinst;
> +
>  	/*
>  	 * We first zero all fields and only set non-zero ones. Following
>  	 * are some fields set to 0/false for the stated reason:
> @@ -930,7 +939,7 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
>  	winctx->wcreds_max = txwin->wcreds_max;
>  
>  	winctx->user_win = txattr->user_win;
> -	winctx->nx_win = txwin->rxwin->nx_win;
> +	winctx->nx_win = txwin->pnv.rxwin->pnv.nx_win;
>  	winctx->pin_win = txattr->pin_win;
>  	winctx->rej_no_credit = txattr->rej_no_credit;
>  	winctx->rsvd_txbuf_enable = txattr->rsvd_txbuf_enable;
> @@ -947,23 +956,23 @@ static void init_winctx_for_txwin(struct vas_window *txwin,
>  
>  	winctx->lpid = txattr->lpid;
>  	winctx->pidr = txattr->pidr;
> -	winctx->rx_win_id = txwin->rxwin->winid;
> +	winctx->rx_win_id = txwin->pnv.rxwin->winid;
>  	/*
>  	 * IRQ and fault window setup is successful. Set fault window
>  	 * for the send window so that ready to handle faults.
>  	 */
> -	if (txwin->vinst->virq)
> -		winctx->fault_win_id = txwin->vinst->fault_win->winid;
> +	if (vinst->virq)
> +		winctx->fault_win_id = vinst->fault_win->winid;
>  
>  	winctx->dma_type = VAS_DMA_TYPE_INJECT;
>  	winctx->tc_mode = txattr->tc_mode;
>  	winctx->min_scope = VAS_SCOPE_LOCAL;
>  	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
> -	if (txwin->vinst->virq)
> -		winctx->irq_port = txwin->vinst->irq_port;
> +	if (vinst->virq)
> +		winctx->irq_port = vinst->irq_port;
>  
>  	winctx->pswid = txattr->pswid ? txattr->pswid :
> -			encode_pswid(txwin->vinst->vas_id, txwin->winid);
> +			encode_pswid(vinst->vas_id, txwin->winid);
>  }
>  
>  static bool tx_win_args_valid(enum vas_cop_type cop,
> @@ -1031,10 +1040,10 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
>  	}
>  
>  	txwin->cop = cop;
> -	txwin->tx_win = 1;
> -	txwin->rxwin = rxwin;
> -	txwin->nx_win = txwin->rxwin->nx_win;
> -	txwin->user_win = attr->user_win;
> +	txwin->pnv.tx_win = 1;
> +	txwin->pnv.rxwin = rxwin;
> +	txwin->pnv.nx_win = txwin->pnv.rxwin->pnv.nx_win;
> +	txwin->pnv.user_win = attr->user_win;
>  	txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT;
>  
>  	init_winctx_for_txwin(txwin, attr, &winctx);
> @@ -1049,10 +1058,10 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop,
>  	 * NOTE: If kernel ever resubmits a user CRB after handling a page
>  	 *	 fault, we will need to map this into kernel as well.
>  	 */
> -	if (!txwin->user_win) {
> -		txwin->paste_kaddr = map_paste_region(txwin);
> -		if (IS_ERR(txwin->paste_kaddr)) {
> -			rc = PTR_ERR(txwin->paste_kaddr);
> +	if (!txwin->pnv.user_win) {
> +		txwin->pnv.paste_kaddr = map_paste_region(txwin);
> +		if (IS_ERR(txwin->pnv.paste_kaddr)) {
> +			rc = PTR_ERR(txwin->pnv.paste_kaddr);
>  			goto free_window;
>  		}
>  	} else {
> @@ -1104,9 +1113,9 @@ int vas_paste_crb(struct vas_window *txwin, int offset, bool re)
>  	 * report-enable flag is set for NX windows. Ensure software
>  	 * complies too.
>  	 */
> -	WARN_ON_ONCE(txwin->nx_win && !re);
> +	WARN_ON_ONCE(txwin->pnv.nx_win && !re);
>  
> -	addr = txwin->paste_kaddr;
> +	addr = txwin->pnv.paste_kaddr;
>  	if (re) {
>  		/*
>  		 * Set the REPORT_ENABLE bit (equivalent to writing
> @@ -1153,7 +1162,7 @@ static void poll_window_credits(struct vas_window *window)
>  	int count = 0;
>  
>  	val = read_hvwc_reg(window, VREG(WINCTL));
> -	if (window->tx_win)
> +	if (window->pnv.tx_win)
>  		mode = GET_FIELD(VAS_WINCTL_TX_WCRED_MODE, val);
>  	else
>  		mode = GET_FIELD(VAS_WINCTL_RX_WCRED_MODE, val);
> @@ -1161,7 +1170,7 @@ static void poll_window_credits(struct vas_window *window)
>  	if (!mode)
>  		return;
>  retry:
> -	if (window->tx_win) {
> +	if (window->pnv.tx_win) {
>  		val = read_hvwc_reg(window, VREG(TX_WCRED));
>  		creds = GET_FIELD(VAS_TX_WCRED, val);
>  	} else {
> @@ -1277,7 +1286,7 @@ int vas_win_close(struct vas_window *window)
>  	if (!window)
>  		return 0;
>  
> -	if (!window->tx_win && atomic_read(&window->num_txwins) != 0) {
> +	if (!window->pnv.tx_win && atomic_read(&window->pnv.num_txwins) != 0) {
>  		pr_devel("Attempting to close an active Rx window!\n");
>  		WARN_ON_ONCE(1);
>  		return -EBUSY;
> @@ -1296,11 +1305,11 @@ int vas_win_close(struct vas_window *window)
>  	poll_window_castout(window);
>  
>  	/* if send window, drop reference to matching receive window */
> -	if (window->tx_win) {
> -		if (window->user_win)
> +	if (window->pnv.tx_win) {
> +		if (window->pnv.user_win)
>  			vas_drop_reference_pid_mm(&window->task_ref);
>  
> -		put_rx_win(window->rxwin);
> +		put_rx_win(window->pnv.rxwin);
>  	}
>  
>  	vas_window_free(window);
> @@ -1384,12 +1393,12 @@ struct vas_window *vas_pswid_to_window(struct vas_instance *vinst,
>  	 * since their CRBs are ignored (not queued on FIFO or processed
>  	 * by NX).
>  	 */
> -	if (!window->tx_win || !window->user_win || !window->nx_win ||
> -			window->cop == VAS_COP_TYPE_FAULT ||
> -			window->cop == VAS_COP_TYPE_FTW) {
> +	if (!window->pnv.tx_win || !window->pnv.user_win ||
> +		!window->pnv.nx_win || window->cop == VAS_COP_TYPE_FAULT ||
> +		window->cop == VAS_COP_TYPE_FTW) {
>  		pr_err("PSWID decode: id %d, tx %d, user %d, nx %d, cop %d\n",
> -			winid, window->tx_win, window->user_win,
> -			window->nx_win, window->cop);
> +			winid, window->pnv.tx_win, window->pnv.user_win,
> +			window->pnv.nx_win, window->cop);
>  		WARN_ON(1);
>  	}
>  
> diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
> index f354dd5c51bd..f2d9daff3d82 100644
> --- a/arch/powerpc/platforms/powernv/vas.h
> +++ b/arch/powerpc/platforms/powernv/vas.h
> @@ -345,34 +345,6 @@ struct vas_instance {
>  	struct dentry *dbgdir;
>  };
>  
> -/*
> - * In-kernel state a VAS window. One per window.
> - */
> -struct vas_window {
> -	/* Fields common to send and receive windows */
> -	struct vas_instance *vinst;
> -	int winid;
> -	bool tx_win;		/* True if send window */
> -	bool nx_win;		/* True if NX window */
> -	bool user_win;		/* True if user space window */
> -	void *hvwc_map;		/* HV window context */
> -	void *uwc_map;		/* OS/User window context */
> -	int wcreds_max;		/* Window credits */
> -
> -	struct vas_user_win_ref task_ref;
> -	char *dbgname;
> -	struct dentry *dbgdir;
> -
> -	/* Fields applicable only to send windows */
> -	void *paste_kaddr;
> -	char *paste_addr_name;
> -	struct vas_window *rxwin;
> -
> -	/* Feilds applicable only to receive windows */
> -	enum vas_cop_type cop;
> -	atomic_t num_txwins;
> -};
> -
>  /*
>   * Container for the hardware state of a window. One per-window.
>   *
> @@ -449,8 +421,8 @@ static inline void vas_log_write(struct vas_window *win, char *name,
>  {
>  	if (val)
>  		pr_debug("%swin #%d: %s reg %p, val 0x%016llx\n",
> -				win->tx_win ? "Tx" : "Rx", win->winid, name,
> -				regptr, val);
> +				win->pnv.tx_win ? "Tx" : "Rx", win->winid,
> +				name, regptr, val);
>  }
>  
>  static inline void write_uwc_reg(struct vas_window *win, char *name,
> @@ -458,7 +430,7 @@ static inline void write_uwc_reg(struct vas_window *win, char *name,
>  {
>  	void *regptr;
>  
> -	regptr = win->uwc_map + reg;
> +	regptr = win->pnv.uwc_map + reg;
>  	vas_log_write(win, name, regptr, val);
>  
>  	out_be64(regptr, val);
> @@ -469,7 +441,7 @@ static inline void write_hvwc_reg(struct vas_window *win, char *name,
>  {
>  	void *regptr;
>  
> -	regptr = win->hvwc_map + reg;
> +	regptr = win->pnv.hvwc_map + reg;
>  	vas_log_write(win, name, regptr, val);
>  
>  	out_be64(regptr, val);
> @@ -478,7 +450,7 @@ static inline void write_hvwc_reg(struct vas_window *win, char *name,
>  static inline u64 read_hvwc_reg(struct vas_window *win,
>  			char *name __maybe_unused, s32 reg)
>  {
> -	return in_be64(win->hvwc_map+reg);
> +	return in_be64(win->pnv.hvwc_map + reg);
>  }
>  
>  /*
> -- 
> 2.18.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 07/16] powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
  2021-05-21  9:34   ` Haren Myneni
@ 2021-06-03  4:47     ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:47 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of May 21, 2021 7:34 pm:
> 
> This patch adds HCALLs and other definitions. Also define structs
> that are used in VAS implementation on powerVM.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/hvcall.h    |   7 ++
>  arch/powerpc/include/asm/vas.h       |  32 ++++++++
>  arch/powerpc/platforms/pseries/vas.h | 110 +++++++++++++++++++++++++++
>  3 files changed, 149 insertions(+)
>  create mode 100644 arch/powerpc/platforms/pseries/vas.h
> 
> diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
> index e3b29eda8074..7c3418d1b5e9 100644
> --- a/arch/powerpc/include/asm/hvcall.h
> +++ b/arch/powerpc/include/asm/hvcall.h
> @@ -294,6 +294,13 @@
>  #define H_RESIZE_HPT_COMMIT	0x370
>  #define H_REGISTER_PROC_TBL	0x37C
>  #define H_SIGNAL_SYS_RESET	0x380
> +#define H_ALLOCATE_VAS_WINDOW	0x388
> +#define H_MODIFY_VAS_WINDOW	0x38C
> +#define H_DEALLOCATE_VAS_WINDOW	0x390
> +#define H_QUERY_VAS_WINDOW	0x394
> +#define H_QUERY_VAS_CAPABILITIES	0x398
> +#define H_QUERY_NX_CAPABILITIES	0x39C
> +#define H_GET_NX_FAULT		0x3A0
>  #define H_INT_GET_SOURCE_INFO   0x3A8
>  #define H_INT_SET_SOURCE_CONFIG 0x3AC
>  #define H_INT_GET_SOURCE_CONFIG 0x3B0
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index 49bfb5be896d..371f62d99174 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -181,6 +181,7 @@ struct vas_tx_win_attr {
>  	bool rx_win_ord_mode;
>  };
>  
> +#ifdef CONFIG_PPC_POWERNV
>  /*
>   * Helper to map a chip id to VAS id.
>   * For POWER9, this is a 1:1 mapping. In the future this maybe a 1:N
> @@ -248,6 +249,37 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr,
>  int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
>  			     const char *name);
>  void vas_unregister_api_powernv(void);
> +#endif
> +
> +#ifdef CONFIG_PPC_PSERIES
> +
> +/* VAS Capabilities */
> +#define VAS_GZIP_QOS_FEAT	0x1
> +#define VAS_GZIP_DEF_FEAT	0x2
> +#define VAS_GZIP_QOS_FEAT_BIT	PPC_BIT(VAS_GZIP_QOS_FEAT) /* Bit 1 */
> +#define VAS_GZIP_DEF_FEAT_BIT	PPC_BIT(VAS_GZIP_DEF_FEAT) /* Bit 2 */
> +
> +/* NX Capabilities */
> +#define VAS_NX_GZIP_FEAT	0x1
> +#define VAS_NX_GZIP_FEAT_BIT	PPC_BIT(VAS_NX_GZIP_FEAT) /* Bit 1 */
> +#define VAS_DESCR_LEN		8
> +
> +/*
> + * These structs are used to retrieve overall VAS capabilities that
> + * the hypervisor provides.
> + */
> +struct hv_vas_all_caps {

...

> +
> +/*
> + * Use to get feature specific capabilities from the
> + * hypervisor.
> + */
> +struct hv_vas_ct_caps {

...

> +/*
> + * To get window information from the hypervisor.
> + */
> +struct hv_vas_win_lpar {

Are any of these names coming from PAPR? If not, then typically we don't 
use hv_ kind of prefixes for something we got from the hypervisor, but
rather something that's hypervisor privileged or specific information
about the hypervisor perhaps (which is not the same as what the 
hypervisor may or may not advertise to the guest).

So if these are all capabilities and features the hypervisor advertises 
to the LPAR, I think the hv_ should be dropped.

Otherwise seems okay. I would be careful of the "lpar" name. I think 
it's okay in this situation where the hypervisor advertises features to 
the partition, but in other parts of the vas code you call it pseries_
but you also have some lpar_ bits. So aside from interacting with PAPR
APIs, it would be safe to consistently use pseries for your driver and
type names.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 07/16] powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
@ 2021-06-03  4:47     ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:47 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of May 21, 2021 7:34 pm:
> 
> This patch adds HCALLs and other definitions. Also define structs
> that are used in VAS implementation on powerVM.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/hvcall.h    |   7 ++
>  arch/powerpc/include/asm/vas.h       |  32 ++++++++
>  arch/powerpc/platforms/pseries/vas.h | 110 +++++++++++++++++++++++++++
>  3 files changed, 149 insertions(+)
>  create mode 100644 arch/powerpc/platforms/pseries/vas.h
> 
> diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
> index e3b29eda8074..7c3418d1b5e9 100644
> --- a/arch/powerpc/include/asm/hvcall.h
> +++ b/arch/powerpc/include/asm/hvcall.h
> @@ -294,6 +294,13 @@
>  #define H_RESIZE_HPT_COMMIT	0x370
>  #define H_REGISTER_PROC_TBL	0x37C
>  #define H_SIGNAL_SYS_RESET	0x380
> +#define H_ALLOCATE_VAS_WINDOW	0x388
> +#define H_MODIFY_VAS_WINDOW	0x38C
> +#define H_DEALLOCATE_VAS_WINDOW	0x390
> +#define H_QUERY_VAS_WINDOW	0x394
> +#define H_QUERY_VAS_CAPABILITIES	0x398
> +#define H_QUERY_NX_CAPABILITIES	0x39C
> +#define H_GET_NX_FAULT		0x3A0
>  #define H_INT_GET_SOURCE_INFO   0x3A8
>  #define H_INT_SET_SOURCE_CONFIG 0x3AC
>  #define H_INT_GET_SOURCE_CONFIG 0x3B0
> diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h
> index 49bfb5be896d..371f62d99174 100644
> --- a/arch/powerpc/include/asm/vas.h
> +++ b/arch/powerpc/include/asm/vas.h
> @@ -181,6 +181,7 @@ struct vas_tx_win_attr {
>  	bool rx_win_ord_mode;
>  };
>  
> +#ifdef CONFIG_PPC_POWERNV
>  /*
>   * Helper to map a chip id to VAS id.
>   * For POWER9, this is a 1:1 mapping. In the future this maybe a 1:N
> @@ -248,6 +249,37 @@ void vas_win_paste_addr(struct vas_window *window, u64 *addr,
>  int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type,
>  			     const char *name);
>  void vas_unregister_api_powernv(void);
> +#endif
> +
> +#ifdef CONFIG_PPC_PSERIES
> +
> +/* VAS Capabilities */
> +#define VAS_GZIP_QOS_FEAT	0x1
> +#define VAS_GZIP_DEF_FEAT	0x2
> +#define VAS_GZIP_QOS_FEAT_BIT	PPC_BIT(VAS_GZIP_QOS_FEAT) /* Bit 1 */
> +#define VAS_GZIP_DEF_FEAT_BIT	PPC_BIT(VAS_GZIP_DEF_FEAT) /* Bit 2 */
> +
> +/* NX Capabilities */
> +#define VAS_NX_GZIP_FEAT	0x1
> +#define VAS_NX_GZIP_FEAT_BIT	PPC_BIT(VAS_NX_GZIP_FEAT) /* Bit 1 */
> +#define VAS_DESCR_LEN		8
> +
> +/*
> + * These structs are used to retrieve overall VAS capabilities that
> + * the hypervisor provides.
> + */
> +struct hv_vas_all_caps {

...

> +
> +/*
> + * Use to get feature specific capabilities from the
> + * hypervisor.
> + */
> +struct hv_vas_ct_caps {

...

> +/*
> + * To get window information from the hypervisor.
> + */
> +struct hv_vas_win_lpar {

Are any of these names coming from PAPR? If not, then typically we don't 
use hv_ kind of prefixes for something we got from the hypervisor, but
rather something that's hypervisor privileged or specific information
about the hypervisor perhaps (which is not the same as what the 
hypervisor may or may not advertise to the guest).

So if these are all capabilities and features the hypervisor advertises 
to the LPAR, I think the hv_ should be dropped.

Otherwise seems okay. I would be careful of the "lpar" name. I think 
it's okay in this situation where the hypervisor advertises features to 
the partition, but in other parts of the vas code you call it pseries_
but you also have some lpar_ bits. So aside from interacting with PAPR
APIs, it would be safe to consistently use pseries for your driver and
type names.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
  2021-05-21  9:42   ` Haren Myneni
@ 2021-06-03  4:57     ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:57 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of May 21, 2021 7:42 pm:
> 
> Changes to export the following NXGZIP capabilities through sysfs:
> 
> /sys/devices/vio/ibm,compression-v1/NxGzCaps:

Where's the horrible camel case name coming from? PowerVM?

Thanks,
Nick

> min_compress_len  /*Recommended minimum compress length in bytes*/
> min_decompress_len /*Recommended minimum decompress length in bytes*/
> req_max_processed_len /* Maximum number of bytes processed in one
> 			request */
> 
> NX will return RMA_Reject if the request buffer size is greater
> than req_max_processed_len.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
> ---
>  drivers/crypto/nx/nx-common-pseries.c | 43 +++++++++++++++++++++++++++
>  1 file changed, 43 insertions(+)
> 
> diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
> index 4a7278464156..121718a337fd 100644
> --- a/drivers/crypto/nx/nx-common-pseries.c
> +++ b/drivers/crypto/nx/nx-common-pseries.c
> @@ -968,6 +968,36 @@ static struct attribute_group nx842_attribute_group = {
>  	.attrs = nx842_sysfs_entries,
>  };
>  
> +#define	nxct_caps_read(_name)						\
> +static ssize_t nxct_##_name##_show(struct device *dev,			\
> +			struct device_attribute *attr, char *buf)	\
> +{									\
> +	return sprintf(buf, "%lld\n", nx_ct_caps._name);		\
> +}
> +
> +#define NXCT_ATTR_RO(_name)						\
> +	nxct_caps_read(_name);						\
> +	static struct device_attribute dev_attr_##_name = __ATTR(_name,	\
> +						0444,			\
> +						nxct_##_name##_show,	\
> +						NULL);
> +
> +NXCT_ATTR_RO(req_max_processed_len);
> +NXCT_ATTR_RO(min_compress_len);
> +NXCT_ATTR_RO(min_decompress_len);
> +
> +static struct attribute *nxct_caps_sysfs_entries[] = {
> +	&dev_attr_req_max_processed_len.attr,
> +	&dev_attr_min_compress_len.attr,
> +	&dev_attr_min_decompress_len.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group nxct_caps_attr_group = {
> +	.name	=	nx_ct_caps.name,
> +	.attrs	=	nxct_caps_sysfs_entries,
> +};
> +
>  static struct nx842_driver nx842_pseries_driver = {
>  	.name =		KBUILD_MODNAME,
>  	.owner =	THIS_MODULE,
> @@ -1057,6 +1087,16 @@ static int nx842_probe(struct vio_dev *viodev,
>  		goto error;
>  	}
>  
> +	if (caps_feat) {
> +		if (sysfs_create_group(&viodev->dev.kobj,
> +					&nxct_caps_attr_group)) {
> +			dev_err(&viodev->dev,
> +				"Could not create sysfs NX capability entries\n");
> +			ret = -1;
> +			goto error;
> +		}
> +	}
> +
>  	return 0;
>  
>  error_unlock:
> @@ -1076,6 +1116,9 @@ static void nx842_remove(struct vio_dev *viodev)
>  	pr_info("Removing IBM Power 842 compression device\n");
>  	sysfs_remove_group(&viodev->dev.kobj, &nx842_attribute_group);
>  
> +	if (caps_feat)
> +		sysfs_remove_group(&viodev->dev.kobj, &nxct_caps_attr_group);
> +
>  	crypto_unregister_alg(&nx842_pseries_alg);
>  
>  	spin_lock_irqsave(&devdata_mutex, flags);
> -- 
> 2.18.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
@ 2021-06-03  4:57     ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:57 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of May 21, 2021 7:42 pm:
> 
> Changes to export the following NXGZIP capabilities through sysfs:
> 
> /sys/devices/vio/ibm,compression-v1/NxGzCaps:

Where's the horrible camel case name coming from? PowerVM?

Thanks,
Nick

> min_compress_len  /*Recommended minimum compress length in bytes*/
> min_decompress_len /*Recommended minimum decompress length in bytes*/
> req_max_processed_len /* Maximum number of bytes processed in one
> 			request */
> 
> NX will return RMA_Reject if the request buffer size is greater
> than req_max_processed_len.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
> ---
>  drivers/crypto/nx/nx-common-pseries.c | 43 +++++++++++++++++++++++++++
>  1 file changed, 43 insertions(+)
> 
> diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
> index 4a7278464156..121718a337fd 100644
> --- a/drivers/crypto/nx/nx-common-pseries.c
> +++ b/drivers/crypto/nx/nx-common-pseries.c
> @@ -968,6 +968,36 @@ static struct attribute_group nx842_attribute_group = {
>  	.attrs = nx842_sysfs_entries,
>  };
>  
> +#define	nxct_caps_read(_name)						\
> +static ssize_t nxct_##_name##_show(struct device *dev,			\
> +			struct device_attribute *attr, char *buf)	\
> +{									\
> +	return sprintf(buf, "%lld\n", nx_ct_caps._name);		\
> +}
> +
> +#define NXCT_ATTR_RO(_name)						\
> +	nxct_caps_read(_name);						\
> +	static struct device_attribute dev_attr_##_name = __ATTR(_name,	\
> +						0444,			\
> +						nxct_##_name##_show,	\
> +						NULL);
> +
> +NXCT_ATTR_RO(req_max_processed_len);
> +NXCT_ATTR_RO(min_compress_len);
> +NXCT_ATTR_RO(min_decompress_len);
> +
> +static struct attribute *nxct_caps_sysfs_entries[] = {
> +	&dev_attr_req_max_processed_len.attr,
> +	&dev_attr_min_compress_len.attr,
> +	&dev_attr_min_decompress_len.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group nxct_caps_attr_group = {
> +	.name	=	nx_ct_caps.name,
> +	.attrs	=	nxct_caps_sysfs_entries,
> +};
> +
>  static struct nx842_driver nx842_pseries_driver = {
>  	.name =		KBUILD_MODNAME,
>  	.owner =	THIS_MODULE,
> @@ -1057,6 +1087,16 @@ static int nx842_probe(struct vio_dev *viodev,
>  		goto error;
>  	}
>  
> +	if (caps_feat) {
> +		if (sysfs_create_group(&viodev->dev.kobj,
> +					&nxct_caps_attr_group)) {
> +			dev_err(&viodev->dev,
> +				"Could not create sysfs NX capability entries\n");
> +			ret = -1;
> +			goto error;
> +		}
> +	}
> +
>  	return 0;
>  
>  error_unlock:
> @@ -1076,6 +1116,9 @@ static void nx842_remove(struct vio_dev *viodev)
>  	pr_info("Removing IBM Power 842 compression device\n");
>  	sysfs_remove_group(&viodev->dev.kobj, &nx842_attribute_group);
>  
> +	if (caps_feat)
> +		sysfs_remove_group(&viodev->dev.kobj, &nxct_caps_attr_group);
> +
>  	crypto_unregister_alg(&nx842_pseries_alg);
>  
>  	spin_lock_irqsave(&devdata_mutex, flags);
> -- 
> 2.18.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 14/16] crypto/nx: Register and unregister VAS interface
  2021-05-21  9:41   ` Haren Myneni
@ 2021-06-03  4:59     ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:59 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of May 21, 2021 7:41 pm:
> 
> Changes to create /dev/crypto/nx-gzip interface with VAS register
> and to remove this interface with VAS unregister.
> 

Could you include why the change is done, or what goes wrong without it?

Thanks,
Nick

> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
> ---
>  drivers/crypto/nx/Kconfig             | 1 +
>  drivers/crypto/nx/nx-common-pseries.c | 9 +++++++++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/drivers/crypto/nx/Kconfig b/drivers/crypto/nx/Kconfig
> index 23e3d0160e67..2a35e0e785bd 100644
> --- a/drivers/crypto/nx/Kconfig
> +++ b/drivers/crypto/nx/Kconfig
> @@ -29,6 +29,7 @@ if CRYPTO_DEV_NX_COMPRESS
>  config CRYPTO_DEV_NX_COMPRESS_PSERIES
>  	tristate "Compression acceleration support on pSeries platform"
>  	depends on PPC_PSERIES && IBMVIO
> +	depends on PPC_VAS
>  	default y
>  	help
>  	  Support for PowerPC Nest (NX) compression acceleration. This
> diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
> index cc8dd3072b8b..9a40fca8a9e6 100644
> --- a/drivers/crypto/nx/nx-common-pseries.c
> +++ b/drivers/crypto/nx/nx-common-pseries.c
> @@ -9,6 +9,7 @@
>   */
>  
>  #include <asm/vio.h>
> +#include <asm/vas.h>
>  
>  #include "nx-842.h"
>  #include "nx_csbcpb.h" /* struct nx_csbcpb */
> @@ -1101,6 +1102,12 @@ static int __init nx842_pseries_init(void)
>  		return ret;
>  	}
>  
> +	ret = vas_register_api_pseries(THIS_MODULE, VAS_COP_TYPE_GZIP,
> +				       "nx-gzip");
> +
> +	if (ret)
> +		pr_err("NX-GZIP is not supported. Returned=%d\n", ret);
> +
>  	return 0;
>  }
>  
> @@ -1111,6 +1118,8 @@ static void __exit nx842_pseries_exit(void)
>  	struct nx842_devdata *old_devdata;
>  	unsigned long flags;
>  
> +	vas_unregister_api_pseries();
> +
>  	crypto_unregister_alg(&nx842_pseries_alg);
>  
>  	spin_lock_irqsave(&devdata_mutex, flags);
> -- 
> 2.18.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 14/16] crypto/nx: Register and unregister VAS interface
@ 2021-06-03  4:59     ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  4:59 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of May 21, 2021 7:41 pm:
> 
> Changes to create /dev/crypto/nx-gzip interface with VAS register
> and to remove this interface with VAS unregister.
> 

Could you include why the change is done, or what goes wrong without it?

Thanks,
Nick

> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
> ---
>  drivers/crypto/nx/Kconfig             | 1 +
>  drivers/crypto/nx/nx-common-pseries.c | 9 +++++++++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/drivers/crypto/nx/Kconfig b/drivers/crypto/nx/Kconfig
> index 23e3d0160e67..2a35e0e785bd 100644
> --- a/drivers/crypto/nx/Kconfig
> +++ b/drivers/crypto/nx/Kconfig
> @@ -29,6 +29,7 @@ if CRYPTO_DEV_NX_COMPRESS
>  config CRYPTO_DEV_NX_COMPRESS_PSERIES
>  	tristate "Compression acceleration support on pSeries platform"
>  	depends on PPC_PSERIES && IBMVIO
> +	depends on PPC_VAS
>  	default y
>  	help
>  	  Support for PowerPC Nest (NX) compression acceleration. This
> diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
> index cc8dd3072b8b..9a40fca8a9e6 100644
> --- a/drivers/crypto/nx/nx-common-pseries.c
> +++ b/drivers/crypto/nx/nx-common-pseries.c
> @@ -9,6 +9,7 @@
>   */
>  
>  #include <asm/vio.h>
> +#include <asm/vas.h>
>  
>  #include "nx-842.h"
>  #include "nx_csbcpb.h" /* struct nx_csbcpb */
> @@ -1101,6 +1102,12 @@ static int __init nx842_pseries_init(void)
>  		return ret;
>  	}
>  
> +	ret = vas_register_api_pseries(THIS_MODULE, VAS_COP_TYPE_GZIP,
> +				       "nx-gzip");
> +
> +	if (ret)
> +		pr_err("NX-GZIP is not supported. Returned=%d\n", ret);
> +
>  	return 0;
>  }
>  
> @@ -1111,6 +1118,8 @@ static void __exit nx842_pseries_exit(void)
>  	struct nx842_devdata *old_devdata;
>  	unsigned long flags;
>  
> +	vas_unregister_api_pseries();
> +
>  	crypto_unregister_alg(&nx842_pseries_alg);
>  
>  	spin_lock_irqsave(&devdata_mutex, flags);
> -- 
> 2.18.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 12/16] powerpc/pseries/vas: Setup IRQ and fault handling
  2021-05-21  9:39   ` Haren Myneni
@ 2021-06-03  5:48     ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  5:48 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of May 21, 2021 7:39 pm:
> 
> NX generates an interrupt when sees a fault on the user space
> buffer and the hypervisor forwards that interrupt to OS. Then
> the kernel handles the interrupt by issuing H_GET_NX_FAULT hcall
> to retrieve the fault CRB information.
> 
> This patch also adds changes to setup and free IRQ per each
> window and also handles the fault by updating the CSB.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/platforms/pseries/vas.c | 111 +++++++++++++++++++++++++++
>  1 file changed, 111 insertions(+)
> 
> diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
> index ef0c455f6e93..31dc17573f50 100644
> --- a/arch/powerpc/platforms/pseries/vas.c
> +++ b/arch/powerpc/platforms/pseries/vas.c
> @@ -224,6 +224,62 @@ int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
>  }
>  EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
>  
> +/*
> + * HCALL to get fault CRB from pHyp.
> + */
> +static int plpar_get_nx_fault(u32 winid, u64 buffer)
> +{
> +	int64_t rc;
> +
> +	rc = plpar_hcall_norets(H_GET_NX_FAULT, winid, buffer);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%x): Invalid window ID %u\n", H_GET_NX_FAULT,
> +		       winid);
> +		return -EINVAL;
> +	case H_STATE:
> +		pr_err("HCALL(%x): No outstanding faults for window ID %u\n",
> +		       H_GET_NX_FAULT, winid);
> +		return -EINVAL;
> +	case H_PRIVILEGE:
> +		pr_err("HCALL(%x): Window(%u): Invalid fault buffer 0x%llx\n",
> +		       H_GET_NX_FAULT, winid, buffer);
> +		return -EACCES;
> +	default:
> +		pr_err("HCALL(%x): Unexpected error %lld for window(%u)\n",
> +		       H_GET_NX_FAULT, rc, winid);
> +		return -EIO;
> +	}
> +}

Out of curiosity, you get one of these errors and it just drops the
interrupt on the floor. Then what happens, I assume everything
stops. Should it put some error in the csb, or signal the process or
something? Or is there nothing very sane that can be done?

> +
> +/*
> + * Handle the fault interrupt.
> + * When the fault interrupt is received for each window, query pHyp to get
> + * the fault CRB on the specific fault. Then process the CRB by updating
> + * CSB or send signal if the user space CSB is invalid.
> + * Note: pHyp forwards an interrupt for each fault request. So one fault
> + *	CRB to process for each H_GET_NX_FAULT HCALL.
> + */
> +irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
> +{
> +	struct vas_window *txwin = data;
> +	struct coprocessor_request_block crb;
> +	struct vas_user_win_ref *tsk_ref;
> +	int rc;
> +
> +	rc = plpar_get_nx_fault(txwin->winid, (u64)virt_to_phys(&crb));
> +	if (!rc) {
> +		tsk_ref = &txwin->task_ref;
> +		vas_dump_crb(&crb);

This (and existing powernv vas code) is printk()ing a lot of lines per 
fault. This should be pretty normal operation I think? It should avoid
filling the kernel logs, if so. Particularly if it can be triggered by 
userspace.

I know it's existing code, so could be fixed separately from the series.


> +		vas_update_csb(&crb, tsk_ref);

> +	}

> +
> +	return IRQ_HANDLED;
> +}
> +

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 12/16] powerpc/pseries/vas: Setup IRQ and fault handling
@ 2021-06-03  5:48     ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-03  5:48 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of May 21, 2021 7:39 pm:
> 
> NX generates an interrupt when sees a fault on the user space
> buffer and the hypervisor forwards that interrupt to OS. Then
> the kernel handles the interrupt by issuing H_GET_NX_FAULT hcall
> to retrieve the fault CRB information.
> 
> This patch also adds changes to setup and free IRQ per each
> window and also handles the fault by updating the CSB.
> 
> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> ---
>  arch/powerpc/platforms/pseries/vas.c | 111 +++++++++++++++++++++++++++
>  1 file changed, 111 insertions(+)
> 
> diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
> index ef0c455f6e93..31dc17573f50 100644
> --- a/arch/powerpc/platforms/pseries/vas.c
> +++ b/arch/powerpc/platforms/pseries/vas.c
> @@ -224,6 +224,62 @@ int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
>  }
>  EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
>  
> +/*
> + * HCALL to get fault CRB from pHyp.
> + */
> +static int plpar_get_nx_fault(u32 winid, u64 buffer)
> +{
> +	int64_t rc;
> +
> +	rc = plpar_hcall_norets(H_GET_NX_FAULT, winid, buffer);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%x): Invalid window ID %u\n", H_GET_NX_FAULT,
> +		       winid);
> +		return -EINVAL;
> +	case H_STATE:
> +		pr_err("HCALL(%x): No outstanding faults for window ID %u\n",
> +		       H_GET_NX_FAULT, winid);
> +		return -EINVAL;
> +	case H_PRIVILEGE:
> +		pr_err("HCALL(%x): Window(%u): Invalid fault buffer 0x%llx\n",
> +		       H_GET_NX_FAULT, winid, buffer);
> +		return -EACCES;
> +	default:
> +		pr_err("HCALL(%x): Unexpected error %lld for window(%u)\n",
> +		       H_GET_NX_FAULT, rc, winid);
> +		return -EIO;
> +	}
> +}

Out of curiosity, you get one of these errors and it just drops the
interrupt on the floor. Then what happens, I assume everything
stops. Should it put some error in the csb, or signal the process or
something? Or is there nothing very sane that can be done?

> +
> +/*
> + * Handle the fault interrupt.
> + * When the fault interrupt is received for each window, query pHyp to get
> + * the fault CRB on the specific fault. Then process the CRB by updating
> + * CSB or send signal if the user space CSB is invalid.
> + * Note: pHyp forwards an interrupt for each fault request. So one fault
> + *	CRB to process for each H_GET_NX_FAULT HCALL.
> + */
> +irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
> +{
> +	struct vas_window *txwin = data;
> +	struct coprocessor_request_block crb;
> +	struct vas_user_win_ref *tsk_ref;
> +	int rc;
> +
> +	rc = plpar_get_nx_fault(txwin->winid, (u64)virt_to_phys(&crb));
> +	if (!rc) {
> +		tsk_ref = &txwin->task_ref;
> +		vas_dump_crb(&crb);

This (and existing powernv vas code) is printk()ing a lot of lines per 
fault. This should be pretty normal operation I think? It should avoid
filling the kernel logs, if so. Particularly if it can be triggered by 
userspace.

I know it's existing code, so could be fixed separately from the series.


> +		vas_update_csb(&crb, tsk_ref);

> +	}

> +
> +	return IRQ_HANDLED;
> +}
> +

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 01/16] powerpc/vas: Move VAS API to book3s common platform
  2021-06-03  3:32     ` Nicholas Piggin
@ 2021-06-03 20:23       ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-03 20:23 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: hbabu

On Thu, 2021-06-03 at 13:32 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:28 pm:
> > Using the same /dev/crypto/nx-gzip interface for both powerNV and
> > pseries. So this patch creates platforms/book3s/ and moves VAS API
> > to that directory. The actual functionality is not changed.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/include/asm/vas.h                    |  3 +++
> >  arch/powerpc/platforms/Kconfig                    |  1 +
> >  arch/powerpc/platforms/Makefile                   |  1 +
> >  arch/powerpc/platforms/book3s/Kconfig             | 15
> > +++++++++++++++
> >  arch/powerpc/platforms/book3s/Makefile            |  2 ++
> 
> If Michael is happy with the new directory structure then fine by me.
> 
> >  .../platforms/{powernv => book3s}/vas-api.c       |  2 +-
> >  arch/powerpc/platforms/powernv/Kconfig            | 14 ---------
> > -----
> >  arch/powerpc/platforms/powernv/Makefile           |  2 +-
> >  8 files changed, 24 insertions(+), 16 deletions(-)
> >  create mode 100644 arch/powerpc/platforms/book3s/Kconfig
> >  create mode 100644 arch/powerpc/platforms/book3s/Makefile
> >  rename arch/powerpc/platforms/{powernv => book3s}/vas-api.c (99%)
> > 
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index e33f80b0ea81..3be76e813e2d 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -162,6 +162,9 @@ int vas_copy_crb(void *crb, int offset);
> >   */
> >  int vas_paste_crb(struct vas_window *win, int offset, bool re);
> >  
> > +void vas_win_paste_addr(struct vas_window *window, u64 *addr,
> > +			int *len);
> > +
> >  /*
> >   * Register / unregister coprocessor type to VAS API which will be
> > exported
> >   * to user space. Applications can use this API to open / close
> > window
> 
> If you do this, then the prototype should be removed from 
> arch/powerpc/platforms/powernv/vas.h

Thanks for your review comments.

vas_win_paste_addr() should be PowerNV specific, so will remove from
include/asm/vas.h


> 
> > diff --git a/arch/powerpc/platforms/Kconfig
> > b/arch/powerpc/platforms/Kconfig
> > index 7a5e8f4541e3..594544a65b02 100644
> > --- a/arch/powerpc/platforms/Kconfig
> > +++ b/arch/powerpc/platforms/Kconfig
> > @@ -20,6 +20,7 @@ source
> > "arch/powerpc/platforms/embedded6xx/Kconfig"
> >  source "arch/powerpc/platforms/44x/Kconfig"
> >  source "arch/powerpc/platforms/40x/Kconfig"
> >  source "arch/powerpc/platforms/amigaone/Kconfig"
> > +source "arch/powerpc/platforms/book3s/Kconfig"
> >  
> >  config KVM_GUEST
> >  	bool "KVM Guest support"
> > diff --git a/arch/powerpc/platforms/Makefile
> > b/arch/powerpc/platforms/Makefile
> > index 143d4417f6cc..0e75d7df387b 100644
> > --- a/arch/powerpc/platforms/Makefile
> > +++ b/arch/powerpc/platforms/Makefile
> > @@ -22,3 +22,4 @@ obj-$(CONFIG_PPC_CELL)		+= cell/
> >  obj-$(CONFIG_PPC_PS3)		+= ps3/
> >  obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
> >  obj-$(CONFIG_AMIGAONE)		+= amigaone/
> > +obj-$(CONFIG_PPC_BOOK3S)	+= book3s/
> > diff --git a/arch/powerpc/platforms/book3s/Kconfig
> > b/arch/powerpc/platforms/book3s/Kconfig
> > new file mode 100644
> > index 000000000000..bed21449e8e5
> > --- /dev/null
> > +++ b/arch/powerpc/platforms/book3s/Kconfig
> > @@ -0,0 +1,15 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +config PPC_VAS
> > +	bool "IBM Virtual Accelerator Switchboard (VAS)"
> > +	depends on (PPC_POWERNV || PPC_PSERIES) && PPC_64K_PAGES
> > +	default y
> > +	help
> > +	  This enables support for IBM Virtual Accelerator Switchboard
> > (VAS).
> > +
> > +	  VAS allows accelerators in co-processors like NX-GZIP and NX-
> > 842
> > +	  to be accessible to kernel subsystems and user processes.
> > +	  VAS adapters are found in POWER9 and later based systems.
> > +	  The user mode NX-GZIP support is added on P9 for powerNV and
> > on
> > +	  P10 for powerVM.
> 
> The changelog has changed. The last sentence is difficult to
> understand 
> (also please consistently capitalise PowerNV and PowerVM). Is it 
> supposed to say that PPC_VAS will provide user-mode NX-GZIP support
> on 
> P9 PowerNV systems and P10 PowerVM systems? If you respin the patch
> for
> the prototype...
> 
>   This enables support for IBM Virtual Accelerator Switchboard (VAS).
> 
>   VAS devices are found in POWER9-based and later systems, they
> provide
>   access to accelerator coprocessors such as NX-GZIP and NX-842. This
>   driver allows the kernel to use NX-GZIP and NX-842 accelerators,
> and
>   user-mode APIs for the NX-GZIP accelerator on POWER9 PowerNV and
>   POWER10 PowerVM platforms. <here is a userspace library you can
> use>
>   etc
> 
> Thanks,
> Nick


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 01/16] powerpc/vas: Move VAS API to book3s common platform
@ 2021-06-03 20:23       ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-03 20:23 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe

On Thu, 2021-06-03 at 13:32 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:28 pm:
> > Using the same /dev/crypto/nx-gzip interface for both powerNV and
> > pseries. So this patch creates platforms/book3s/ and moves VAS API
> > to that directory. The actual functionality is not changed.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/include/asm/vas.h                    |  3 +++
> >  arch/powerpc/platforms/Kconfig                    |  1 +
> >  arch/powerpc/platforms/Makefile                   |  1 +
> >  arch/powerpc/platforms/book3s/Kconfig             | 15
> > +++++++++++++++
> >  arch/powerpc/platforms/book3s/Makefile            |  2 ++
> 
> If Michael is happy with the new directory structure then fine by me.
> 
> >  .../platforms/{powernv => book3s}/vas-api.c       |  2 +-
> >  arch/powerpc/platforms/powernv/Kconfig            | 14 ---------
> > -----
> >  arch/powerpc/platforms/powernv/Makefile           |  2 +-
> >  8 files changed, 24 insertions(+), 16 deletions(-)
> >  create mode 100644 arch/powerpc/platforms/book3s/Kconfig
> >  create mode 100644 arch/powerpc/platforms/book3s/Makefile
> >  rename arch/powerpc/platforms/{powernv => book3s}/vas-api.c (99%)
> > 
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index e33f80b0ea81..3be76e813e2d 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -162,6 +162,9 @@ int vas_copy_crb(void *crb, int offset);
> >   */
> >  int vas_paste_crb(struct vas_window *win, int offset, bool re);
> >  
> > +void vas_win_paste_addr(struct vas_window *window, u64 *addr,
> > +			int *len);
> > +
> >  /*
> >   * Register / unregister coprocessor type to VAS API which will be
> > exported
> >   * to user space. Applications can use this API to open / close
> > window
> 
> If you do this, then the prototype should be removed from 
> arch/powerpc/platforms/powernv/vas.h

Thanks for your review comments.

vas_win_paste_addr() should be PowerNV specific, so will remove from
include/asm/vas.h


> 
> > diff --git a/arch/powerpc/platforms/Kconfig
> > b/arch/powerpc/platforms/Kconfig
> > index 7a5e8f4541e3..594544a65b02 100644
> > --- a/arch/powerpc/platforms/Kconfig
> > +++ b/arch/powerpc/platforms/Kconfig
> > @@ -20,6 +20,7 @@ source
> > "arch/powerpc/platforms/embedded6xx/Kconfig"
> >  source "arch/powerpc/platforms/44x/Kconfig"
> >  source "arch/powerpc/platforms/40x/Kconfig"
> >  source "arch/powerpc/platforms/amigaone/Kconfig"
> > +source "arch/powerpc/platforms/book3s/Kconfig"
> >  
> >  config KVM_GUEST
> >  	bool "KVM Guest support"
> > diff --git a/arch/powerpc/platforms/Makefile
> > b/arch/powerpc/platforms/Makefile
> > index 143d4417f6cc..0e75d7df387b 100644
> > --- a/arch/powerpc/platforms/Makefile
> > +++ b/arch/powerpc/platforms/Makefile
> > @@ -22,3 +22,4 @@ obj-$(CONFIG_PPC_CELL)		+= cell/
> >  obj-$(CONFIG_PPC_PS3)		+= ps3/
> >  obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
> >  obj-$(CONFIG_AMIGAONE)		+= amigaone/
> > +obj-$(CONFIG_PPC_BOOK3S)	+= book3s/
> > diff --git a/arch/powerpc/platforms/book3s/Kconfig
> > b/arch/powerpc/platforms/book3s/Kconfig
> > new file mode 100644
> > index 000000000000..bed21449e8e5
> > --- /dev/null
> > +++ b/arch/powerpc/platforms/book3s/Kconfig
> > @@ -0,0 +1,15 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +config PPC_VAS
> > +	bool "IBM Virtual Accelerator Switchboard (VAS)"
> > +	depends on (PPC_POWERNV || PPC_PSERIES) && PPC_64K_PAGES
> > +	default y
> > +	help
> > +	  This enables support for IBM Virtual Accelerator Switchboard
> > (VAS).
> > +
> > +	  VAS allows accelerators in co-processors like NX-GZIP and NX-
> > 842
> > +	  to be accessible to kernel subsystems and user processes.
> > +	  VAS adapters are found in POWER9 and later based systems.
> > +	  The user mode NX-GZIP support is added on P9 for powerNV and
> > on
> > +	  P10 for powerVM.
> 
> The changelog has changed. The last sentence is difficult to
> understand 
> (also please consistently capitalise PowerNV and PowerVM). Is it 
> supposed to say that PPC_VAS will provide user-mode NX-GZIP support
> on 
> P9 PowerNV systems and P10 PowerVM systems? If you respin the patch
> for
> the prototype...
> 
>   This enables support for IBM Virtual Accelerator Switchboard (VAS).
> 
>   VAS devices are found in POWER9-based and later systems, they
> provide
>   access to accelerator coprocessors such as NX-GZIP and NX-842. This
>   driver allows the kernel to use NX-GZIP and NX-842 accelerators,
> and
>   user-mode APIs for the NX-GZIP accelerator on POWER9 PowerNV and
>   POWER10 PowerVM platforms. <here is a userspace library you can
> use>
>   etc
> 
> Thanks,
> Nick


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 03/16] powerpc/vas: Add platform specific user window operations
  2021-06-03  4:05     ` Nicholas Piggin
@ 2021-06-03 20:25       ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-03 20:25 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

On Thu, 2021-06-03 at 14:05 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:30 pm:
> > PowerNV uses registers to open/close VAS windows, and getting the
> > paste address. Whereas the hypervisor calls are used on PowerVM.
> > 
> > This patch adds the platform specific user space window operations
> > and register with the common VAS user space interface.
> 
> Basic idea makes sense. I don't understand this code in detail
> though.
> A couple of things,
> 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/include/asm/vas.h              | 14 +++++-
> >  arch/powerpc/platforms/book3s/vas-api.c     | 52 ++++++++++++-----
> > ----
> >  arch/powerpc/platforms/powernv/vas-window.c | 46
> > +++++++++++++++++-
> >  3 files changed, 89 insertions(+), 23 deletions(-)
> > 
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index 6076adf9ab4f..668303198772 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -5,6 +5,7 @@
> >  
> >  #ifndef _ASM_POWERPC_VAS_H
> >  #define _ASM_POWERPC_VAS_H
> > +#include <uapi/asm/vas-api.h>
> >  
> >  struct vas_window;
> >  
> > @@ -48,6 +49,16 @@ enum vas_cop_type {
> >  	VAS_COP_TYPE_MAX,
> >  };
> >  
> > +/*
> > + * User space window operations used for powernv and powerVM
> > + */
> > +struct vas_user_win_ops {
> > +	struct vas_window * (*open_win)(struct vas_tx_win_open_attr *,
> > +				enum vas_cop_type);
> > +	u64 (*paste_addr)(void *);
> > +	int (*close_win)(void *);
> 
> Without looking further into the series, why do these two take void
> * 
> when the first returns a vas_window * which appears to be the
> required
> argument to these?

Yes, vas_window * should be passed instead of void * for paste_addr() /
close_win()

> 
> > +static struct vas_user_win_ops vops =  {
> > +	.open_win	=	vas_user_win_open,
> > +	.paste_addr	=	vas_user_win_paste_addr,
> > +	.close_win	=	vas_user_win_close,
> > +};
> 
> const?
> 
> Thanks,
> Nick


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 03/16] powerpc/vas: Add platform specific user window operations
@ 2021-06-03 20:25       ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-03 20:25 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe

On Thu, 2021-06-03 at 14:05 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:30 pm:
> > PowerNV uses registers to open/close VAS windows, and getting the
> > paste address. Whereas the hypervisor calls are used on PowerVM.
> > 
> > This patch adds the platform specific user space window operations
> > and register with the common VAS user space interface.
> 
> Basic idea makes sense. I don't understand this code in detail
> though.
> A couple of things,
> 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/include/asm/vas.h              | 14 +++++-
> >  arch/powerpc/platforms/book3s/vas-api.c     | 52 ++++++++++++-----
> > ----
> >  arch/powerpc/platforms/powernv/vas-window.c | 46
> > +++++++++++++++++-
> >  3 files changed, 89 insertions(+), 23 deletions(-)
> > 
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index 6076adf9ab4f..668303198772 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -5,6 +5,7 @@
> >  
> >  #ifndef _ASM_POWERPC_VAS_H
> >  #define _ASM_POWERPC_VAS_H
> > +#include <uapi/asm/vas-api.h>
> >  
> >  struct vas_window;
> >  
> > @@ -48,6 +49,16 @@ enum vas_cop_type {
> >  	VAS_COP_TYPE_MAX,
> >  };
> >  
> > +/*
> > + * User space window operations used for powernv and powerVM
> > + */
> > +struct vas_user_win_ops {
> > +	struct vas_window * (*open_win)(struct vas_tx_win_open_attr *,
> > +				enum vas_cop_type);
> > +	u64 (*paste_addr)(void *);
> > +	int (*close_win)(void *);
> 
> Without looking further into the series, why do these two take void
> * 
> when the first returns a vas_window * which appears to be the
> required
> argument to these?

Yes, vas_window * should be passed instead of void * for paste_addr() /
close_win()

> 
> > +static struct vas_user_win_ops vops =  {
> > +	.open_win	=	vas_user_win_open,
> > +	.paste_addr	=	vas_user_win_paste_addr,
> > +	.close_win	=	vas_user_win_close,
> > +};
> 
> const?
> 
> Thanks,
> Nick


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
  2021-06-03  4:57     ` Nicholas Piggin
@ 2021-06-04  1:02       ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  1:02 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

On Thu, 2021-06-03 at 14:57 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:42 pm:
> > Changes to export the following NXGZIP capabilities through sysfs:
> > 
> > /sys/devices/vio/ibm,compression-v1/NxGzCaps:
> 
> Where's the horrible camel case name coming from? PowerVM?

Yes, pHyp provides the capabalities string.

Capability Description Descriptor Value Descriptor ascii Value
Overall NX Capabilities 0x4E78204361707320 “Nx Caps ”
NX GZIP Capabilities 0x4E78477A43617073 “NxGzCaps”


> 
> Thanks,
> Nick
> 
> > min_compress_len  /*Recommended minimum compress length in bytes*/
> > min_decompress_len /*Recommended minimum decompress length in
> > bytes*/
> > req_max_processed_len /* Maximum number of bytes processed in one
> > 			request */
> > 
> > NX will return RMA_Reject if the request buffer size is greater
> > than req_max_processed_len.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
> > ---
> >  drivers/crypto/nx/nx-common-pseries.c | 43
> > +++++++++++++++++++++++++++
> >  1 file changed, 43 insertions(+)
> > 
> > diff --git a/drivers/crypto/nx/nx-common-pseries.c
> > b/drivers/crypto/nx/nx-common-pseries.c
> > index 4a7278464156..121718a337fd 100644
> > --- a/drivers/crypto/nx/nx-common-pseries.c
> > +++ b/drivers/crypto/nx/nx-common-pseries.c
> > @@ -968,6 +968,36 @@ static struct attribute_group
> > nx842_attribute_group = {
> >  	.attrs = nx842_sysfs_entries,
> >  };
> >  
> > +#define	nxct_caps_read(_name)					
> > 	\
> > +static ssize_t nxct_##_name##_show(struct device *dev,		
> > 	\
> > +			struct device_attribute *attr, char *buf)	\
> > +{									
> > \
> > +	return sprintf(buf, "%lld\n", nx_ct_caps._name);		\
> > +}
> > +
> > +#define NXCT_ATTR_RO(_name)					
> > 	\
> > +	nxct_caps_read(_name);						
> > \
> > +	static struct device_attribute dev_attr_##_name = __ATTR(_name,
> > 	\
> > +						0444,			
> > \
> > +						nxct_##_name##_show,	
> > \
> > +						NULL);
> > +
> > +NXCT_ATTR_RO(req_max_processed_len);
> > +NXCT_ATTR_RO(min_compress_len);
> > +NXCT_ATTR_RO(min_decompress_len);
> > +
> > +static struct attribute *nxct_caps_sysfs_entries[] = {
> > +	&dev_attr_req_max_processed_len.attr,
> > +	&dev_attr_min_compress_len.attr,
> > +	&dev_attr_min_decompress_len.attr,
> > +	NULL,
> > +};
> > +
> > +static struct attribute_group nxct_caps_attr_group = {
> > +	.name	=	nx_ct_caps.name,
> > +	.attrs	=	nxct_caps_sysfs_entries,
> > +};
> > +
> >  static struct nx842_driver nx842_pseries_driver = {
> >  	.name =		KBUILD_MODNAME,
> >  	.owner =	THIS_MODULE,
> > @@ -1057,6 +1087,16 @@ static int nx842_probe(struct vio_dev
> > *viodev,
> >  		goto error;
> >  	}
> >  
> > +	if (caps_feat) {
> > +		if (sysfs_create_group(&viodev->dev.kobj,
> > +					&nxct_caps_attr_group)) {
> > +			dev_err(&viodev->dev,
> > +				"Could not create sysfs NX capability
> > entries\n");
> > +			ret = -1;
> > +			goto error;
> > +		}
> > +	}
> > +
> >  	return 0;
> >  
> >  error_unlock:
> > @@ -1076,6 +1116,9 @@ static void nx842_remove(struct vio_dev
> > *viodev)
> >  	pr_info("Removing IBM Power 842 compression device\n");
> >  	sysfs_remove_group(&viodev->dev.kobj, &nx842_attribute_group);
> >  
> > +	if (caps_feat)
> > +		sysfs_remove_group(&viodev->dev.kobj,
> > &nxct_caps_attr_group);
> > +
> >  	crypto_unregister_alg(&nx842_pseries_alg);
> >  
> >  	spin_lock_irqsave(&devdata_mutex, flags);
> > -- 
> > 2.18.2
> > 
> > 
> > 


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
@ 2021-06-04  1:02       ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  1:02 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe

On Thu, 2021-06-03 at 14:57 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:42 pm:
> > Changes to export the following NXGZIP capabilities through sysfs:
> > 
> > /sys/devices/vio/ibm,compression-v1/NxGzCaps:
> 
> Where's the horrible camel case name coming from? PowerVM?

Yes, pHyp provides the capabalities string.

Capability Description Descriptor Value Descriptor ascii Value
Overall NX Capabilities 0x4E78204361707320 “Nx Caps ”
NX GZIP Capabilities 0x4E78477A43617073 “NxGzCaps”


> 
> Thanks,
> Nick
> 
> > min_compress_len  /*Recommended minimum compress length in bytes*/
> > min_decompress_len /*Recommended minimum decompress length in
> > bytes*/
> > req_max_processed_len /* Maximum number of bytes processed in one
> > 			request */
> > 
> > NX will return RMA_Reject if the request buffer size is greater
> > than req_max_processed_len.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
> > ---
> >  drivers/crypto/nx/nx-common-pseries.c | 43
> > +++++++++++++++++++++++++++
> >  1 file changed, 43 insertions(+)
> > 
> > diff --git a/drivers/crypto/nx/nx-common-pseries.c
> > b/drivers/crypto/nx/nx-common-pseries.c
> > index 4a7278464156..121718a337fd 100644
> > --- a/drivers/crypto/nx/nx-common-pseries.c
> > +++ b/drivers/crypto/nx/nx-common-pseries.c
> > @@ -968,6 +968,36 @@ static struct attribute_group
> > nx842_attribute_group = {
> >  	.attrs = nx842_sysfs_entries,
> >  };
> >  
> > +#define	nxct_caps_read(_name)					
> > 	\
> > +static ssize_t nxct_##_name##_show(struct device *dev,		
> > 	\
> > +			struct device_attribute *attr, char *buf)	\
> > +{									
> > \
> > +	return sprintf(buf, "%lld\n", nx_ct_caps._name);		\
> > +}
> > +
> > +#define NXCT_ATTR_RO(_name)					
> > 	\
> > +	nxct_caps_read(_name);						
> > \
> > +	static struct device_attribute dev_attr_##_name = __ATTR(_name,
> > 	\
> > +						0444,			
> > \
> > +						nxct_##_name##_show,	
> > \
> > +						NULL);
> > +
> > +NXCT_ATTR_RO(req_max_processed_len);
> > +NXCT_ATTR_RO(min_compress_len);
> > +NXCT_ATTR_RO(min_decompress_len);
> > +
> > +static struct attribute *nxct_caps_sysfs_entries[] = {
> > +	&dev_attr_req_max_processed_len.attr,
> > +	&dev_attr_min_compress_len.attr,
> > +	&dev_attr_min_decompress_len.attr,
> > +	NULL,
> > +};
> > +
> > +static struct attribute_group nxct_caps_attr_group = {
> > +	.name	=	nx_ct_caps.name,
> > +	.attrs	=	nxct_caps_sysfs_entries,
> > +};
> > +
> >  static struct nx842_driver nx842_pseries_driver = {
> >  	.name =		KBUILD_MODNAME,
> >  	.owner =	THIS_MODULE,
> > @@ -1057,6 +1087,16 @@ static int nx842_probe(struct vio_dev
> > *viodev,
> >  		goto error;
> >  	}
> >  
> > +	if (caps_feat) {
> > +		if (sysfs_create_group(&viodev->dev.kobj,
> > +					&nxct_caps_attr_group)) {
> > +			dev_err(&viodev->dev,
> > +				"Could not create sysfs NX capability
> > entries\n");
> > +			ret = -1;
> > +			goto error;
> > +		}
> > +	}
> > +
> >  	return 0;
> >  
> >  error_unlock:
> > @@ -1076,6 +1116,9 @@ static void nx842_remove(struct vio_dev
> > *viodev)
> >  	pr_info("Removing IBM Power 842 compression device\n");
> >  	sysfs_remove_group(&viodev->dev.kobj, &nx842_attribute_group);
> >  
> > +	if (caps_feat)
> > +		sysfs_remove_group(&viodev->dev.kobj,
> > &nxct_caps_attr_group);
> > +
> >  	crypto_unregister_alg(&nx842_pseries_alg);
> >  
> >  	spin_lock_irqsave(&devdata_mutex, flags);
> > -- 
> > 2.18.2
> > 
> > 
> > 


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 12/16] powerpc/pseries/vas: Setup IRQ and fault handling
  2021-06-03  5:48     ` Nicholas Piggin
@ 2021-06-04  1:19       ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  1:19 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

On Thu, 2021-06-03 at 15:48 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:39 pm:
> > NX generates an interrupt when sees a fault on the user space
> > buffer and the hypervisor forwards that interrupt to OS. Then
> > the kernel handles the interrupt by issuing H_GET_NX_FAULT hcall
> > to retrieve the fault CRB information.
> > 
> > This patch also adds changes to setup and free IRQ per each
> > window and also handles the fault by updating the CSB.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/platforms/pseries/vas.c | 111
> > +++++++++++++++++++++++++++
> >  1 file changed, 111 insertions(+)
> > 
> > diff --git a/arch/powerpc/platforms/pseries/vas.c
> > b/arch/powerpc/platforms/pseries/vas.c
> > index ef0c455f6e93..31dc17573f50 100644
> > --- a/arch/powerpc/platforms/pseries/vas.c
> > +++ b/arch/powerpc/platforms/pseries/vas.c
> > @@ -224,6 +224,62 @@ int plpar_vas_query_capabilities(const u64
> > hcall, u8 query_type,
> >  }
> >  EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
> >  
> > +/*
> > + * HCALL to get fault CRB from pHyp.
> > + */
> > +static int plpar_get_nx_fault(u32 winid, u64 buffer)
> > +{
> > +	int64_t rc;
> > +
> > +	rc = plpar_hcall_norets(H_GET_NX_FAULT, winid, buffer);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%x): Invalid window ID %u\n",
> > H_GET_NX_FAULT,
> > +		       winid);
> > +		return -EINVAL;
> > +	case H_STATE:
> > +		pr_err("HCALL(%x): No outstanding faults for window ID
> > %u\n",
> > +		       H_GET_NX_FAULT, winid);
> > +		return -EINVAL;
> > +	case H_PRIVILEGE:
> > +		pr_err("HCALL(%x): Window(%u): Invalid fault buffer
> > 0x%llx\n",
> > +		       H_GET_NX_FAULT, winid, buffer);
> > +		return -EACCES;
> > +	default:
> > +		pr_err("HCALL(%x): Unexpected error %lld for
> > window(%u)\n",
> > +		       H_GET_NX_FAULT, rc, winid);
> > +		return -EIO;
> > +	}
> > +}
> 
> Out of curiosity, you get one of these errors and it just drops the
> interrupt on the floor. Then what happens, I assume everything
> stops. Should it put some error in the csb, or signal the process or
> something? Or is there nothing very sane that can be done?

The user space polls on CSB with timout interval. If the kernel or NX
does not return, the request will be timeout.

The hypervisor returns the credit after H_GET_NX_FAULT HCALL is
successful. Also one credit is assigned for each window. So in this
case, the error is coming from the hypervisor and the application can
not issue another request on the same window. 

> 
> > +
> > +/*
> > + * Handle the fault interrupt.
> > + * When the fault interrupt is received for each window, query
> > pHyp to get
> > + * the fault CRB on the specific fault. Then process the CRB by
> > updating
> > + * CSB or send signal if the user space CSB is invalid.
> > + * Note: pHyp forwards an interrupt for each fault request. So one
> > fault
> > + *	CRB to process for each H_GET_NX_FAULT HCALL.
> > + */
> > +irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
> > +{
> > +	struct vas_window *txwin = data;
> > +	struct coprocessor_request_block crb;
> > +	struct vas_user_win_ref *tsk_ref;
> > +	int rc;
> > +
> > +	rc = plpar_get_nx_fault(txwin->winid, (u64)virt_to_phys(&crb));
> > +	if (!rc) {
> > +		tsk_ref = &txwin->task_ref;
> > +		vas_dump_crb(&crb);
> 
> This (and existing powernv vas code) is printk()ing a lot of lines
> per 
> fault. This should be pretty normal operation I think? It should
> avoid
> filling the kernel logs, if so. Particularly if it can be triggered
> by 
> userspace.
> 
> I know it's existing code, so could be fixed separately from the
> series.

printk messages are only if HCALL returns failure or kernel issue (ex:
not valid window and etc on powerNV). These errors should not be
depending on the iser space requests. So generally we should not get
these errors.  

> 
> 
> > +		vas_update_csb(&crb, tsk_ref);
> > +	}
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 12/16] powerpc/pseries/vas: Setup IRQ and fault handling
@ 2021-06-04  1:19       ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  1:19 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe

On Thu, 2021-06-03 at 15:48 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:39 pm:
> > NX generates an interrupt when sees a fault on the user space
> > buffer and the hypervisor forwards that interrupt to OS. Then
> > the kernel handles the interrupt by issuing H_GET_NX_FAULT hcall
> > to retrieve the fault CRB information.
> > 
> > This patch also adds changes to setup and free IRQ per each
> > window and also handles the fault by updating the CSB.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/platforms/pseries/vas.c | 111
> > +++++++++++++++++++++++++++
> >  1 file changed, 111 insertions(+)
> > 
> > diff --git a/arch/powerpc/platforms/pseries/vas.c
> > b/arch/powerpc/platforms/pseries/vas.c
> > index ef0c455f6e93..31dc17573f50 100644
> > --- a/arch/powerpc/platforms/pseries/vas.c
> > +++ b/arch/powerpc/platforms/pseries/vas.c
> > @@ -224,6 +224,62 @@ int plpar_vas_query_capabilities(const u64
> > hcall, u8 query_type,
> >  }
> >  EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
> >  
> > +/*
> > + * HCALL to get fault CRB from pHyp.
> > + */
> > +static int plpar_get_nx_fault(u32 winid, u64 buffer)
> > +{
> > +	int64_t rc;
> > +
> > +	rc = plpar_hcall_norets(H_GET_NX_FAULT, winid, buffer);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%x): Invalid window ID %u\n",
> > H_GET_NX_FAULT,
> > +		       winid);
> > +		return -EINVAL;
> > +	case H_STATE:
> > +		pr_err("HCALL(%x): No outstanding faults for window ID
> > %u\n",
> > +		       H_GET_NX_FAULT, winid);
> > +		return -EINVAL;
> > +	case H_PRIVILEGE:
> > +		pr_err("HCALL(%x): Window(%u): Invalid fault buffer
> > 0x%llx\n",
> > +		       H_GET_NX_FAULT, winid, buffer);
> > +		return -EACCES;
> > +	default:
> > +		pr_err("HCALL(%x): Unexpected error %lld for
> > window(%u)\n",
> > +		       H_GET_NX_FAULT, rc, winid);
> > +		return -EIO;
> > +	}
> > +}
> 
> Out of curiosity, you get one of these errors and it just drops the
> interrupt on the floor. Then what happens, I assume everything
> stops. Should it put some error in the csb, or signal the process or
> something? Or is there nothing very sane that can be done?

The user space polls on CSB with timout interval. If the kernel or NX
does not return, the request will be timeout.

The hypervisor returns the credit after H_GET_NX_FAULT HCALL is
successful. Also one credit is assigned for each window. So in this
case, the error is coming from the hypervisor and the application can
not issue another request on the same window. 

> 
> > +
> > +/*
> > + * Handle the fault interrupt.
> > + * When the fault interrupt is received for each window, query
> > pHyp to get
> > + * the fault CRB on the specific fault. Then process the CRB by
> > updating
> > + * CSB or send signal if the user space CSB is invalid.
> > + * Note: pHyp forwards an interrupt for each fault request. So one
> > fault
> > + *	CRB to process for each H_GET_NX_FAULT HCALL.
> > + */
> > +irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
> > +{
> > +	struct vas_window *txwin = data;
> > +	struct coprocessor_request_block crb;
> > +	struct vas_user_win_ref *tsk_ref;
> > +	int rc;
> > +
> > +	rc = plpar_get_nx_fault(txwin->winid, (u64)virt_to_phys(&crb));
> > +	if (!rc) {
> > +		tsk_ref = &txwin->task_ref;
> > +		vas_dump_crb(&crb);
> 
> This (and existing powernv vas code) is printk()ing a lot of lines
> per 
> fault. This should be pretty normal operation I think? It should
> avoid
> filling the kernel logs, if so. Particularly if it can be triggered
> by 
> userspace.
> 
> I know it's existing code, so could be fixed separately from the
> series.

printk messages are only if HCALL returns failure or kernel issue (ex:
not valid window and etc on powerNV). These errors should not be
depending on the iser space requests. So generally we should not get
these errors.  

> 
> 
> > +		vas_update_csb(&crb, tsk_ref);
> > +	}
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 07/16] powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
  2021-06-03  4:47     ` Nicholas Piggin
@ 2021-06-04  1:30       ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  1:30 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

On Thu, 2021-06-03 at 14:47 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:34 pm:
> > This patch adds HCALLs and other definitions. Also define structs
> > that are used in VAS implementation on powerVM.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/include/asm/hvcall.h    |   7 ++
> >  arch/powerpc/include/asm/vas.h       |  32 ++++++++
> >  arch/powerpc/platforms/pseries/vas.h | 110
> > +++++++++++++++++++++++++++
> >  3 files changed, 149 insertions(+)
> >  create mode 100644 arch/powerpc/platforms/pseries/vas.h
> > 
> > diff --git a/arch/powerpc/include/asm/hvcall.h
> > b/arch/powerpc/include/asm/hvcall.h
> > index e3b29eda8074..7c3418d1b5e9 100644
> > --- a/arch/powerpc/include/asm/hvcall.h
> > +++ b/arch/powerpc/include/asm/hvcall.h
> > @@ -294,6 +294,13 @@
> >  #define H_RESIZE_HPT_COMMIT	0x370
> >  #define H_REGISTER_PROC_TBL	0x37C
> >  #define H_SIGNAL_SYS_RESET	0x380
> > +#define H_ALLOCATE_VAS_WINDOW	0x388
> > +#define H_MODIFY_VAS_WINDOW	0x38C
> > +#define H_DEALLOCATE_VAS_WINDOW	0x390
> > +#define H_QUERY_VAS_WINDOW	0x394
> > +#define H_QUERY_VAS_CAPABILITIES	0x398
> > +#define H_QUERY_NX_CAPABILITIES	0x39C
> > +#define H_GET_NX_FAULT		0x3A0
> >  #define H_INT_GET_SOURCE_INFO   0x3A8
> >  #define H_INT_SET_SOURCE_CONFIG 0x3AC
> >  #define H_INT_GET_SOURCE_CONFIG 0x3B0
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index 49bfb5be896d..371f62d99174 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -181,6 +181,7 @@ struct vas_tx_win_attr {
> >  	bool rx_win_ord_mode;
> >  };
> >  
> > +#ifdef CONFIG_PPC_POWERNV
> >  /*
> >   * Helper to map a chip id to VAS id.
> >   * For POWER9, this is a 1:1 mapping. In the future this maybe a
> > 1:N
> > @@ -248,6 +249,37 @@ void vas_win_paste_addr(struct vas_window
> > *window, u64 *addr,
> >  int vas_register_api_powernv(struct module *mod, enum vas_cop_type
> > cop_type,
> >  			     const char *name);
> >  void vas_unregister_api_powernv(void);
> > +#endif
> > +
> > +#ifdef CONFIG_PPC_PSERIES
> > +
> > +/* VAS Capabilities */
> > +#define VAS_GZIP_QOS_FEAT	0x1
> > +#define VAS_GZIP_DEF_FEAT	0x2
> > +#define VAS_GZIP_QOS_FEAT_BIT	PPC_BIT(VAS_GZIP_QOS_FEAT) /*
> > Bit 1 */
> > +#define VAS_GZIP_DEF_FEAT_BIT	PPC_BIT(VAS_GZIP_DEF_FEAT) /*
> > Bit 2 */
> > +
> > +/* NX Capabilities */
> > +#define VAS_NX_GZIP_FEAT	0x1
> > +#define VAS_NX_GZIP_FEAT_BIT	PPC_BIT(VAS_NX_GZIP_FEAT) /*
> > Bit 1 */
> > +#define VAS_DESCR_LEN		8
> > +
> > +/*
> > + * These structs are used to retrieve overall VAS capabilities
> > that
> > + * the hypervisor provides.
> > + */
> > +struct hv_vas_all_caps {
> 
> ...
> 
> > +
> > +/*
> > + * Use to get feature specific capabilities from the
> > + * hypervisor.
> > + */
> > +struct hv_vas_ct_caps {
> 
> ...
> 
> > +/*
> > + * To get window information from the hypervisor.
> > + */
> > +struct hv_vas_win_lpar {
> 
> Are any of these names coming from PAPR? If not, then typically we
> don't 
> use hv_ kind of prefixes for something we got from the hypervisor,
> but
> rather something that's hypervisor privileged or specific information
> about the hypervisor perhaps (which is not the same as what the 
> hypervisor may or may not advertise to the guest).
> 
> So if these are all capabilities and features the hypervisor
> advertises 
> to the LPAR, I think the hv_ should be dropped.

The hypervisor advertises the available capabalities and the LPAR
passes buffer to HCALLs to retrieve these capabilties / features (in
BE). 

I was using *_be in the previous version. So can I use like 'struct
vas_ct_caps_be'  

> 
> Otherwise seems okay. I would be careful of the "lpar" name. I think 
> it's okay in this situation where the hypervisor advertises features
> to 
> the partition, but in other parts of the vas code you call it
> pseries_
> but you also have some lpar_ bits. So aside from interacting with
> PAPR
> APIs, it would be safe to consistently use pseries for your driver
> and
> type names.

I can use 'struct hv_vas_win_pseries' or 'struct vas_win_pseries_be'

> 
> Thanks,
> Nick


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 07/16] powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
@ 2021-06-04  1:30       ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  1:30 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe

On Thu, 2021-06-03 at 14:47 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:34 pm:
> > This patch adds HCALLs and other definitions. Also define structs
> > that are used in VAS implementation on powerVM.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/include/asm/hvcall.h    |   7 ++
> >  arch/powerpc/include/asm/vas.h       |  32 ++++++++
> >  arch/powerpc/platforms/pseries/vas.h | 110
> > +++++++++++++++++++++++++++
> >  3 files changed, 149 insertions(+)
> >  create mode 100644 arch/powerpc/platforms/pseries/vas.h
> > 
> > diff --git a/arch/powerpc/include/asm/hvcall.h
> > b/arch/powerpc/include/asm/hvcall.h
> > index e3b29eda8074..7c3418d1b5e9 100644
> > --- a/arch/powerpc/include/asm/hvcall.h
> > +++ b/arch/powerpc/include/asm/hvcall.h
> > @@ -294,6 +294,13 @@
> >  #define H_RESIZE_HPT_COMMIT	0x370
> >  #define H_REGISTER_PROC_TBL	0x37C
> >  #define H_SIGNAL_SYS_RESET	0x380
> > +#define H_ALLOCATE_VAS_WINDOW	0x388
> > +#define H_MODIFY_VAS_WINDOW	0x38C
> > +#define H_DEALLOCATE_VAS_WINDOW	0x390
> > +#define H_QUERY_VAS_WINDOW	0x394
> > +#define H_QUERY_VAS_CAPABILITIES	0x398
> > +#define H_QUERY_NX_CAPABILITIES	0x39C
> > +#define H_GET_NX_FAULT		0x3A0
> >  #define H_INT_GET_SOURCE_INFO   0x3A8
> >  #define H_INT_SET_SOURCE_CONFIG 0x3AC
> >  #define H_INT_GET_SOURCE_CONFIG 0x3B0
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index 49bfb5be896d..371f62d99174 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -181,6 +181,7 @@ struct vas_tx_win_attr {
> >  	bool rx_win_ord_mode;
> >  };
> >  
> > +#ifdef CONFIG_PPC_POWERNV
> >  /*
> >   * Helper to map a chip id to VAS id.
> >   * For POWER9, this is a 1:1 mapping. In the future this maybe a
> > 1:N
> > @@ -248,6 +249,37 @@ void vas_win_paste_addr(struct vas_window
> > *window, u64 *addr,
> >  int vas_register_api_powernv(struct module *mod, enum vas_cop_type
> > cop_type,
> >  			     const char *name);
> >  void vas_unregister_api_powernv(void);
> > +#endif
> > +
> > +#ifdef CONFIG_PPC_PSERIES
> > +
> > +/* VAS Capabilities */
> > +#define VAS_GZIP_QOS_FEAT	0x1
> > +#define VAS_GZIP_DEF_FEAT	0x2
> > +#define VAS_GZIP_QOS_FEAT_BIT	PPC_BIT(VAS_GZIP_QOS_FEAT) /*
> > Bit 1 */
> > +#define VAS_GZIP_DEF_FEAT_BIT	PPC_BIT(VAS_GZIP_DEF_FEAT) /*
> > Bit 2 */
> > +
> > +/* NX Capabilities */
> > +#define VAS_NX_GZIP_FEAT	0x1
> > +#define VAS_NX_GZIP_FEAT_BIT	PPC_BIT(VAS_NX_GZIP_FEAT) /*
> > Bit 1 */
> > +#define VAS_DESCR_LEN		8
> > +
> > +/*
> > + * These structs are used to retrieve overall VAS capabilities
> > that
> > + * the hypervisor provides.
> > + */
> > +struct hv_vas_all_caps {
> 
> ...
> 
> > +
> > +/*
> > + * Use to get feature specific capabilities from the
> > + * hypervisor.
> > + */
> > +struct hv_vas_ct_caps {
> 
> ...
> 
> > +/*
> > + * To get window information from the hypervisor.
> > + */
> > +struct hv_vas_win_lpar {
> 
> Are any of these names coming from PAPR? If not, then typically we
> don't 
> use hv_ kind of prefixes for something we got from the hypervisor,
> but
> rather something that's hypervisor privileged or specific information
> about the hypervisor perhaps (which is not the same as what the 
> hypervisor may or may not advertise to the guest).
> 
> So if these are all capabilities and features the hypervisor
> advertises 
> to the LPAR, I think the hv_ should be dropped.

The hypervisor advertises the available capabalities and the LPAR
passes buffer to HCALLs to retrieve these capabilties / features (in
BE). 

I was using *_be in the previous version. So can I use like 'struct
vas_ct_caps_be'  

> 
> Otherwise seems okay. I would be careful of the "lpar" name. I think 
> it's okay in this situation where the hypervisor advertises features
> to 
> the partition, but in other parts of the vas code you call it
> pseries_
> but you also have some lpar_ bits. So aside from interacting with
> PAPR
> APIs, it would be safe to consistently use pseries for your driver
> and
> type names.

I can use 'struct hv_vas_win_pseries' or 'struct vas_win_pseries_be'

> 
> Thanks,
> Nick


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
  2021-06-03  4:21     ` Nicholas Piggin
@ 2021-06-04  4:08       ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  4:08 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

On Thu, 2021-06-03 at 14:21 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:31 pm:
> > Take pid and mm references when each window opens and drops during
> > close. This functionality is needed for powerNV and pseries. So
> > this patch defines the existing code as functions in common book3s
> > platform vas-api.c
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> 
> Seems like a good idea to put these into their own helper functions.
> 
> > ---
> >  arch/powerpc/include/asm/vas.h              | 25 +++++++++
> >  arch/powerpc/platforms/book3s/vas-api.c     | 51
> > ++++++++++++++++++
> >  arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
> >  arch/powerpc/platforms/powernv/vas-window.c | 57 ++---------------
> > ----
> >  arch/powerpc/platforms/powernv/vas.h        |  6 +--
> >  5 files changed, 88 insertions(+), 61 deletions(-)
> > 
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index 668303198772..3f2b02461a76 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -5,6 +5,9 @@
> >  
> >  #ifndef _ASM_POWERPC_VAS_H
> >  #define _ASM_POWERPC_VAS_H
> > +#include <linux/sched/mm.h>
> > +#include <linux/mmu_context.h>
> > +#include <asm/icswx.h>
> >  #include <uapi/asm/vas-api.h>
> >  
> >  struct vas_window;
> > @@ -49,6 +52,17 @@ enum vas_cop_type {
> >  	VAS_COP_TYPE_MAX,
> >  };
> >  
> > +/*
> > + * User space VAS windows are opened by tasks and take references
> > + * to pid and mm until windows are closed.
> > + * Stores pid, mm, and tgid for each window.
> > + */
> > +struct vas_user_win_ref {
> > +	struct pid *pid;	/* PID of owner */
> > +	struct pid *tgid;	/* Thread group ID of owner */
> > +	struct mm_struct *mm;	/* Linux process mm_struct */
> > +};
> > +
> >  /*
> >   * User space window operations used for powernv and powerVM
> >   */
> > @@ -59,6 +73,16 @@ struct vas_user_win_ops {
> >  	int (*close_win)(void *);
> >  };
> >  
> > +static inline void vas_drop_reference_pid_mm(struct
> > vas_user_win_ref *ref)
> > +{
> > +	/* Drop references to pid and mm */
> > +	put_pid(ref->pid);
> > +	if (ref->mm) {
> > +		mm_context_remove_vas_window(ref->mm);
> > +		mmdrop(ref->mm);
> > +	}
> > +}
> 
> You don't have to make up a new name for such a thing because you 
> already have one
> 
> put_vas_user_win_ref(struct vas_user_win_ref *ref)
> 
> 
> > +
> >  /*
> >   * Receive window attributes specified by the (in-kernel) owner of
> > window.
> >   */
> > @@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod,
> > enum vas_cop_type cop_type,
> >  			    struct vas_user_win_ops *vops);
> >  void vas_unregister_coproc_api(void);
> >  
> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
> >  #endif /* __ASM_POWERPC_VAS_H */
> > diff --git a/arch/powerpc/platforms/book3s/vas-api.c
> > b/arch/powerpc/platforms/book3s/vas-api.c
> > index 6c39320bfb9b..a0141bfb2e4b 100644
> > --- a/arch/powerpc/platforms/book3s/vas-api.c
> > +++ b/arch/powerpc/platforms/book3s/vas-api.c
> > @@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev,
> > umode_t *mode)
> >  	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
> >  }
> >  
> > +/*
> > + * Take reference to pid and mm
> > + */
> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
> > +{
> 
> So this is quite different from a typical refcount object in that
> it's 
> opening it for access as well. I would split it in two functions, one
> matching put_vas_user_win_ref() and appearing in the same place in
> code,
> which is up to about mmput and another function that adds the window
> and
> does the CP_ABORT etc... hmm, where do you release tgid?

Basically copied the existing code in to these functions
(vas_reference_pid_mm/vas_drop_reference_pid_mm) so that useful for
both platforms. 

mm_context_add/remove_vas_window() is also like taking reference. So
instead of adding 2 seperate functions, how about naming
get/put_vas_user_win_ref() 

Regarding tgid, the reference is taking only with pid, but not tgid.
pid reuse can happen only in the case of multithread applications when
the child that opened VAS window exits. But these windows will be
closed when tgid exists. So do not need tgid reference.
  
Thanks
Haren


> 
> Thanks,
> Nick
> 
> > +	/*
> > +	 * Window opened by a child thread may not be closed when
> > +	 * it exits. So take reference to its pid and release it
> > +	 * when the window is free by parent thread.
> > +	 * Acquire a reference to the task's pid to make sure
> > +	 * pid will not be re-used - needed only for multithread
> > +	 * applications.
> > +	 */
> > +	task_ref->pid = get_task_pid(current, PIDTYPE_PID);
> > +	/*
> > +	 * Acquire a reference to the task's mm.
> > +	 */
> > +	task_ref->mm = get_task_mm(current);
> > +	if (!task_ref->mm) {
> > +		put_pid(task_ref->pid);
> > +		pr_err("VAS: pid(%d): mm_struct is not found\n",
> > +				current->pid);
> > +		return -EPERM;
> > +	}
> > +
> > +	mmgrab(task_ref->mm);
> > +	mmput(task_ref->mm);
> > +	mm_context_add_vas_window(task_ref->mm);
> > +	/*
> > +	 * Process closes window during exit. In the case of
> > +	 * multithread application, the child thread can open
> > +	 * window and can exit without closing it. Expects parent
> > +	 * thread to use and close the window. So do not need
> > +	 * to take pid reference for parent thread.
> > +	 */
> > +	task_ref->tgid = find_get_pid(task_tgid_vnr(current));
> > +	/*
> > +	 * Even a process that has no foreign real address mapping can
> > +	 * use an unpaired COPY instruction (to no real effect). Issue
> > +	 * CP_ABORT to clear any pending COPY and prevent a covert
> > +	 * channel.
> > +	 *
> > +	 * __switch_to() will issue CP_ABORT on future context switches
> > +	 * if process / thread has any open VAS window (Use
> > +	 * current->mm->context.vas_windows).
> > +	 */
> > +	asm volatile(PPC_CP_ABORT);
> > +
> > +	return 0;
> > +}
> > +
> >  static int coproc_open(struct inode *inode, struct file *fp)
> >  {
> >  	struct coproc_instance *cp_inst;
> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c
> > b/arch/powerpc/platforms/powernv/vas-fault.c
> > index 3d21fce254b7..ac3a71ec3bd5 100644
> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > @@ -73,7 +73,7 @@ static void update_csb(struct vas_window *window,
> >  	 * NX user space windows can not be opened for task->mm=NULL
> >  	 * and faults will not be generated for kernel requests.
> >  	 */
> > -	if (WARN_ON_ONCE(!window->mm || !window->user_win))
> > +	if (WARN_ON_ONCE(!window->task_ref.mm || !window->user_win))
> >  		return;
> >  
> >  	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
> > @@ -92,7 +92,7 @@ static void update_csb(struct vas_window *window,
> >  	csb.address = crb->stamp.nx.fault_storage_addr;
> >  	csb.flags = 0;
> >  
> > -	pid = window->pid;
> > +	pid = window->task_ref.pid;
> >  	tsk = get_pid_task(pid, PIDTYPE_PID);
> >  	/*
> >  	 * Process closes send window after all pending NX requests are
> > @@ -111,7 +111,7 @@ static void update_csb(struct vas_window
> > *window,
> >  	 * a window and exits without closing it.
> >  	 */
> >  	if (!tsk) {
> > -		pid = window->tgid;
> > +		pid = window->task_ref.tgid;
> >  		tsk = get_pid_task(pid, PIDTYPE_PID);
> >  		/*
> >  		 * Parent thread (tgid) will be closing window when it
> > @@ -127,7 +127,7 @@ static void update_csb(struct vas_window
> > *window,
> >  		return;
> >  	}
> >  
> > -	kthread_use_mm(window->mm);
> > +	kthread_use_mm(window->task_ref.mm);
> >  	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
> >  	/*
> >  	 * User space polls on csb.flags (first byte). So add barrier
> > @@ -139,7 +139,7 @@ static void update_csb(struct vas_window
> > *window,
> >  		smp_mb();
> >  		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
> >  	}
> > -	kthread_unuse_mm(window->mm);
> > +	kthread_unuse_mm(window->task_ref.mm);
> >  	put_task_struct(tsk);
> >  
> >  	/* Success */
> > diff --git a/arch/powerpc/platforms/powernv/vas-window.c
> > b/arch/powerpc/platforms/powernv/vas-window.c
> > index 3ccd3edcaf1a..ffd619e5a218 100644
> > --- a/arch/powerpc/platforms/powernv/vas-window.c
> > +++ b/arch/powerpc/platforms/powernv/vas-window.c
> > @@ -1065,51 +1065,9 @@ struct vas_window *vas_tx_win_open(int
> > vasid, enum vas_cop_type cop,
> >  			rc = -ENODEV;
> >  			goto free_window;
> >  		}
> > -
> > -		/*
> > -		 * Window opened by a child thread may not be closed
> > when
> > -		 * it exits. So take reference to its pid and release
> > it
> > -		 * when the window is free by parent thread.
> > -		 * Acquire a reference to the task's pid to make sure
> > -		 * pid will not be re-used - needed only for
> > multithread
> > -		 * applications.
> > -		 */
> > -		txwin->pid = get_task_pid(current, PIDTYPE_PID);
> > -		/*
> > -		 * Acquire a reference to the task's mm.
> > -		 */
> > -		txwin->mm = get_task_mm(current);
> > -
> > -		if (!txwin->mm) {
> > -			put_pid(txwin->pid);
> > -			pr_err("VAS: pid(%d): mm_struct is not
> > found\n",
> > -					current->pid);
> > -			rc = -EPERM;
> > +		rc = vas_reference_pid_mm(&txwin->task_ref);
> > +		if (rc)
> >  			goto free_window;
> > -		}
> > -
> > -		mmgrab(txwin->mm);
> > -		mmput(txwin->mm);
> > -		mm_context_add_vas_window(txwin->mm);
> > -		/*
> > -		 * Process closes window during exit. In the case of
> > -		 * multithread application, the child thread can open
> > -		 * window and can exit without closing it. Expects
> > parent
> > -		 * thread to use and close the window. So do not need
> > -		 * to take pid reference for parent thread.
> > -		 */
> > -		txwin->tgid = find_get_pid(task_tgid_vnr(current));
> > -		/*
> > -		 * Even a process that has no foreign real address
> > mapping can
> > -		 * use an unpaired COPY instruction (to no real
> > effect). Issue
> > -		 * CP_ABORT to clear any pending COPY and prevent a
> > covert
> > -		 * channel.
> > -		 *
> > -		 * __switch_to() will issue CP_ABORT on future context
> > switches
> > -		 * if process / thread has any open VAS window (Use
> > -		 * current->mm->context.vas_windows).
> > -		 */
> > -		asm volatile(PPC_CP_ABORT);
> >  	}
> >  
> >  	set_vinst_win(vinst, txwin);
> > @@ -1339,14 +1297,9 @@ int vas_win_close(struct vas_window *window)
> >  
> >  	/* if send window, drop reference to matching receive window */
> >  	if (window->tx_win) {
> > -		if (window->user_win) {
> > -			/* Drop references to pid and mm */
> > -			put_pid(window->pid);
> > -			if (window->mm) {
> > -				mm_context_remove_vas_window(window-
> > >mm);
> > -				mmdrop(window->mm);
> > -			}
> > -		}
> > +		if (window->user_win)
> > +			vas_drop_reference_pid_mm(&window->task_ref);
> > +
> >  		put_rx_win(window->rxwin);
> >  	}
> >  
> > diff --git a/arch/powerpc/platforms/powernv/vas.h
> > b/arch/powerpc/platforms/powernv/vas.h
> > index c7db3190baca..f354dd5c51bd 100644
> > --- a/arch/powerpc/platforms/powernv/vas.h
> > +++ b/arch/powerpc/platforms/powernv/vas.h
> > @@ -357,11 +357,9 @@ struct vas_window {
> >  	bool user_win;		/* True if user space window */
> >  	void *hvwc_map;		/* HV window context */
> >  	void *uwc_map;		/* OS/User window context */
> > -	struct pid *pid;	/* Linux process id of owner */
> > -	struct pid *tgid;	/* Thread group ID of owner */
> > -	struct mm_struct *mm;	/* Linux process mm_struct */
> >  	int wcreds_max;		/* Window credits */
> >  
> > +	struct vas_user_win_ref task_ref;
> >  	char *dbgname;
> >  	struct dentry *dbgdir;
> >  
> > @@ -443,7 +441,7 @@ extern void vas_win_paste_addr(struct
> > vas_window *window, u64 *addr,
> >  
> >  static inline int vas_window_pid(struct vas_window *window)
> >  {
> > -	return pid_vnr(window->pid);
> > +	return pid_vnr(window->task_ref.pid);
> >  }
> >  
> >  static inline void vas_log_write(struct vas_window *win, char
> > *name,
> > -- 
> > 2.18.2
> > 
> > 
> > 


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
@ 2021-06-04  4:08       ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  4:08 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe

On Thu, 2021-06-03 at 14:21 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:31 pm:
> > Take pid and mm references when each window opens and drops during
> > close. This functionality is needed for powerNV and pseries. So
> > this patch defines the existing code as functions in common book3s
> > platform vas-api.c
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> 
> Seems like a good idea to put these into their own helper functions.
> 
> > ---
> >  arch/powerpc/include/asm/vas.h              | 25 +++++++++
> >  arch/powerpc/platforms/book3s/vas-api.c     | 51
> > ++++++++++++++++++
> >  arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
> >  arch/powerpc/platforms/powernv/vas-window.c | 57 ++---------------
> > ----
> >  arch/powerpc/platforms/powernv/vas.h        |  6 +--
> >  5 files changed, 88 insertions(+), 61 deletions(-)
> > 
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index 668303198772..3f2b02461a76 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -5,6 +5,9 @@
> >  
> >  #ifndef _ASM_POWERPC_VAS_H
> >  #define _ASM_POWERPC_VAS_H
> > +#include <linux/sched/mm.h>
> > +#include <linux/mmu_context.h>
> > +#include <asm/icswx.h>
> >  #include <uapi/asm/vas-api.h>
> >  
> >  struct vas_window;
> > @@ -49,6 +52,17 @@ enum vas_cop_type {
> >  	VAS_COP_TYPE_MAX,
> >  };
> >  
> > +/*
> > + * User space VAS windows are opened by tasks and take references
> > + * to pid and mm until windows are closed.
> > + * Stores pid, mm, and tgid for each window.
> > + */
> > +struct vas_user_win_ref {
> > +	struct pid *pid;	/* PID of owner */
> > +	struct pid *tgid;	/* Thread group ID of owner */
> > +	struct mm_struct *mm;	/* Linux process mm_struct */
> > +};
> > +
> >  /*
> >   * User space window operations used for powernv and powerVM
> >   */
> > @@ -59,6 +73,16 @@ struct vas_user_win_ops {
> >  	int (*close_win)(void *);
> >  };
> >  
> > +static inline void vas_drop_reference_pid_mm(struct
> > vas_user_win_ref *ref)
> > +{
> > +	/* Drop references to pid and mm */
> > +	put_pid(ref->pid);
> > +	if (ref->mm) {
> > +		mm_context_remove_vas_window(ref->mm);
> > +		mmdrop(ref->mm);
> > +	}
> > +}
> 
> You don't have to make up a new name for such a thing because you 
> already have one
> 
> put_vas_user_win_ref(struct vas_user_win_ref *ref)
> 
> 
> > +
> >  /*
> >   * Receive window attributes specified by the (in-kernel) owner of
> > window.
> >   */
> > @@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod,
> > enum vas_cop_type cop_type,
> >  			    struct vas_user_win_ops *vops);
> >  void vas_unregister_coproc_api(void);
> >  
> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
> >  #endif /* __ASM_POWERPC_VAS_H */
> > diff --git a/arch/powerpc/platforms/book3s/vas-api.c
> > b/arch/powerpc/platforms/book3s/vas-api.c
> > index 6c39320bfb9b..a0141bfb2e4b 100644
> > --- a/arch/powerpc/platforms/book3s/vas-api.c
> > +++ b/arch/powerpc/platforms/book3s/vas-api.c
> > @@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev,
> > umode_t *mode)
> >  	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
> >  }
> >  
> > +/*
> > + * Take reference to pid and mm
> > + */
> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
> > +{
> 
> So this is quite different from a typical refcount object in that
> it's 
> opening it for access as well. I would split it in two functions, one
> matching put_vas_user_win_ref() and appearing in the same place in
> code,
> which is up to about mmput and another function that adds the window
> and
> does the CP_ABORT etc... hmm, where do you release tgid?

Basically copied the existing code in to these functions
(vas_reference_pid_mm/vas_drop_reference_pid_mm) so that useful for
both platforms. 

mm_context_add/remove_vas_window() is also like taking reference. So
instead of adding 2 seperate functions, how about naming
get/put_vas_user_win_ref() 

Regarding tgid, the reference is taking only with pid, but not tgid.
pid reuse can happen only in the case of multithread applications when
the child that opened VAS window exits. But these windows will be
closed when tgid exists. So do not need tgid reference.
  
Thanks
Haren


> 
> Thanks,
> Nick
> 
> > +	/*
> > +	 * Window opened by a child thread may not be closed when
> > +	 * it exits. So take reference to its pid and release it
> > +	 * when the window is free by parent thread.
> > +	 * Acquire a reference to the task's pid to make sure
> > +	 * pid will not be re-used - needed only for multithread
> > +	 * applications.
> > +	 */
> > +	task_ref->pid = get_task_pid(current, PIDTYPE_PID);
> > +	/*
> > +	 * Acquire a reference to the task's mm.
> > +	 */
> > +	task_ref->mm = get_task_mm(current);
> > +	if (!task_ref->mm) {
> > +		put_pid(task_ref->pid);
> > +		pr_err("VAS: pid(%d): mm_struct is not found\n",
> > +				current->pid);
> > +		return -EPERM;
> > +	}
> > +
> > +	mmgrab(task_ref->mm);
> > +	mmput(task_ref->mm);
> > +	mm_context_add_vas_window(task_ref->mm);
> > +	/*
> > +	 * Process closes window during exit. In the case of
> > +	 * multithread application, the child thread can open
> > +	 * window and can exit without closing it. Expects parent
> > +	 * thread to use and close the window. So do not need
> > +	 * to take pid reference for parent thread.
> > +	 */
> > +	task_ref->tgid = find_get_pid(task_tgid_vnr(current));
> > +	/*
> > +	 * Even a process that has no foreign real address mapping can
> > +	 * use an unpaired COPY instruction (to no real effect). Issue
> > +	 * CP_ABORT to clear any pending COPY and prevent a covert
> > +	 * channel.
> > +	 *
> > +	 * __switch_to() will issue CP_ABORT on future context switches
> > +	 * if process / thread has any open VAS window (Use
> > +	 * current->mm->context.vas_windows).
> > +	 */
> > +	asm volatile(PPC_CP_ABORT);
> > +
> > +	return 0;
> > +}
> > +
> >  static int coproc_open(struct inode *inode, struct file *fp)
> >  {
> >  	struct coproc_instance *cp_inst;
> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c
> > b/arch/powerpc/platforms/powernv/vas-fault.c
> > index 3d21fce254b7..ac3a71ec3bd5 100644
> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > @@ -73,7 +73,7 @@ static void update_csb(struct vas_window *window,
> >  	 * NX user space windows can not be opened for task->mm=NULL
> >  	 * and faults will not be generated for kernel requests.
> >  	 */
> > -	if (WARN_ON_ONCE(!window->mm || !window->user_win))
> > +	if (WARN_ON_ONCE(!window->task_ref.mm || !window->user_win))
> >  		return;
> >  
> >  	csb_addr = (void __user *)be64_to_cpu(crb->csb_addr);
> > @@ -92,7 +92,7 @@ static void update_csb(struct vas_window *window,
> >  	csb.address = crb->stamp.nx.fault_storage_addr;
> >  	csb.flags = 0;
> >  
> > -	pid = window->pid;
> > +	pid = window->task_ref.pid;
> >  	tsk = get_pid_task(pid, PIDTYPE_PID);
> >  	/*
> >  	 * Process closes send window after all pending NX requests are
> > @@ -111,7 +111,7 @@ static void update_csb(struct vas_window
> > *window,
> >  	 * a window and exits without closing it.
> >  	 */
> >  	if (!tsk) {
> > -		pid = window->tgid;
> > +		pid = window->task_ref.tgid;
> >  		tsk = get_pid_task(pid, PIDTYPE_PID);
> >  		/*
> >  		 * Parent thread (tgid) will be closing window when it
> > @@ -127,7 +127,7 @@ static void update_csb(struct vas_window
> > *window,
> >  		return;
> >  	}
> >  
> > -	kthread_use_mm(window->mm);
> > +	kthread_use_mm(window->task_ref.mm);
> >  	rc = copy_to_user(csb_addr, &csb, sizeof(csb));
> >  	/*
> >  	 * User space polls on csb.flags (first byte). So add barrier
> > @@ -139,7 +139,7 @@ static void update_csb(struct vas_window
> > *window,
> >  		smp_mb();
> >  		rc = copy_to_user(csb_addr, &csb, sizeof(u8));
> >  	}
> > -	kthread_unuse_mm(window->mm);
> > +	kthread_unuse_mm(window->task_ref.mm);
> >  	put_task_struct(tsk);
> >  
> >  	/* Success */
> > diff --git a/arch/powerpc/platforms/powernv/vas-window.c
> > b/arch/powerpc/platforms/powernv/vas-window.c
> > index 3ccd3edcaf1a..ffd619e5a218 100644
> > --- a/arch/powerpc/platforms/powernv/vas-window.c
> > +++ b/arch/powerpc/platforms/powernv/vas-window.c
> > @@ -1065,51 +1065,9 @@ struct vas_window *vas_tx_win_open(int
> > vasid, enum vas_cop_type cop,
> >  			rc = -ENODEV;
> >  			goto free_window;
> >  		}
> > -
> > -		/*
> > -		 * Window opened by a child thread may not be closed
> > when
> > -		 * it exits. So take reference to its pid and release
> > it
> > -		 * when the window is free by parent thread.
> > -		 * Acquire a reference to the task's pid to make sure
> > -		 * pid will not be re-used - needed only for
> > multithread
> > -		 * applications.
> > -		 */
> > -		txwin->pid = get_task_pid(current, PIDTYPE_PID);
> > -		/*
> > -		 * Acquire a reference to the task's mm.
> > -		 */
> > -		txwin->mm = get_task_mm(current);
> > -
> > -		if (!txwin->mm) {
> > -			put_pid(txwin->pid);
> > -			pr_err("VAS: pid(%d): mm_struct is not
> > found\n",
> > -					current->pid);
> > -			rc = -EPERM;
> > +		rc = vas_reference_pid_mm(&txwin->task_ref);
> > +		if (rc)
> >  			goto free_window;
> > -		}
> > -
> > -		mmgrab(txwin->mm);
> > -		mmput(txwin->mm);
> > -		mm_context_add_vas_window(txwin->mm);
> > -		/*
> > -		 * Process closes window during exit. In the case of
> > -		 * multithread application, the child thread can open
> > -		 * window and can exit without closing it. Expects
> > parent
> > -		 * thread to use and close the window. So do not need
> > -		 * to take pid reference for parent thread.
> > -		 */
> > -		txwin->tgid = find_get_pid(task_tgid_vnr(current));
> > -		/*
> > -		 * Even a process that has no foreign real address
> > mapping can
> > -		 * use an unpaired COPY instruction (to no real
> > effect). Issue
> > -		 * CP_ABORT to clear any pending COPY and prevent a
> > covert
> > -		 * channel.
> > -		 *
> > -		 * __switch_to() will issue CP_ABORT on future context
> > switches
> > -		 * if process / thread has any open VAS window (Use
> > -		 * current->mm->context.vas_windows).
> > -		 */
> > -		asm volatile(PPC_CP_ABORT);
> >  	}
> >  
> >  	set_vinst_win(vinst, txwin);
> > @@ -1339,14 +1297,9 @@ int vas_win_close(struct vas_window *window)
> >  
> >  	/* if send window, drop reference to matching receive window */
> >  	if (window->tx_win) {
> > -		if (window->user_win) {
> > -			/* Drop references to pid and mm */
> > -			put_pid(window->pid);
> > -			if (window->mm) {
> > -				mm_context_remove_vas_window(window-
> > >mm);
> > -				mmdrop(window->mm);
> > -			}
> > -		}
> > +		if (window->user_win)
> > +			vas_drop_reference_pid_mm(&window->task_ref);
> > +
> >  		put_rx_win(window->rxwin);
> >  	}
> >  
> > diff --git a/arch/powerpc/platforms/powernv/vas.h
> > b/arch/powerpc/platforms/powernv/vas.h
> > index c7db3190baca..f354dd5c51bd 100644
> > --- a/arch/powerpc/platforms/powernv/vas.h
> > +++ b/arch/powerpc/platforms/powernv/vas.h
> > @@ -357,11 +357,9 @@ struct vas_window {
> >  	bool user_win;		/* True if user space window */
> >  	void *hvwc_map;		/* HV window context */
> >  	void *uwc_map;		/* OS/User window context */
> > -	struct pid *pid;	/* Linux process id of owner */
> > -	struct pid *tgid;	/* Thread group ID of owner */
> > -	struct mm_struct *mm;	/* Linux process mm_struct */
> >  	int wcreds_max;		/* Window credits */
> >  
> > +	struct vas_user_win_ref task_ref;
> >  	char *dbgname;
> >  	struct dentry *dbgdir;
> >  
> > @@ -443,7 +441,7 @@ extern void vas_win_paste_addr(struct
> > vas_window *window, u64 *addr,
> >  
> >  static inline int vas_window_pid(struct vas_window *window)
> >  {
> > -	return pid_vnr(window->pid);
> > +	return pid_vnr(window->task_ref.pid);
> >  }
> >  
> >  static inline void vas_log_write(struct vas_window *win, char
> > *name,
> > -- 
> > 2.18.2
> > 
> > 
> > 


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
  2021-06-03  4:38     ` Nicholas Piggin
@ 2021-06-04  4:35       ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  4:35 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

On Thu, 2021-06-03 at 14:38 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:33 pm:
> > Same vas_window struct is used on powerNV and pseries. So this
> > patch
> > changes in struct vas_window to support both platforms and also the
> > corresponding modifications in powerNV vas code.
> > 
> > On powerNV, vas_window is used for both TX and RX windows, whereas
> > only for TX windows on powerVM. So some elements are specific to
> > these platforms.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/include/asm/vas.h              |  50 +++++++-
> >  arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
> >  arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
> >  arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
> >  arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++-----
> > ----
> >  arch/powerpc/platforms/powernv/vas.h        |  38 +-----
> >  6 files changed, 135 insertions(+), 104 deletions(-)
> > 
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index 2c1040f399d9..49bfb5be896d 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -10,8 +10,6 @@
> >  #include <asm/icswx.h>
> >  #include <uapi/asm/vas-api.h>
> >  
> > -struct vas_window;
> > -
> >  /*
> >   * Min and max FIFO sizes are based on Version 1.05 Section
> > 3.1.4.25
> >   * (Local FIFO Size Register) of the VAS workbook.
> > @@ -63,6 +61,54 @@ struct vas_user_win_ref {
> >  	struct mm_struct *mm;	/* Linux process mm_struct */
> >  };
> >  
> > +/*
> > + * In-kernel state a VAS window. One per window.
> > + * powerVM: Used only for Tx windows.
> > + * powerNV: Used for both Tx and Rx windows.
> > + */
> > +struct vas_window {
> > +	u32 winid;
> > +	u32 wcreds_max;	/* Window credits */
> > +	enum vas_cop_type cop;
> > +	struct vas_user_win_ref task_ref;
> > +	char *dbgname;
> > +	struct dentry *dbgdir;
> > +	union {
> > +		/* powerNV specific data */
> > +		struct {
> > +			void *vinst;	/* points to VAS instance
> > */
> > +			bool tx_win;	/* True if send window */
> > +			bool nx_win;	/* True if NX window */
> > +			bool user_win;	/* True if user space
> > window */
> > +			void *hvwc_map;	/* HV window context */
> > +			void *uwc_map;	/* OS/User window context
> > */
> > +
> > +			/* Fields applicable only to send windows */
> > +			void *paste_kaddr;
> > +			char *paste_addr_name;
> > +			struct vas_window *rxwin;
> > +
> > +			atomic_t num_txwins;	/* Only for receive
> > windows */
> > +		} pnv;
> > +		struct {
> > +			u64 win_addr;	/* Physical paste address
> > */
> > +			u8 win_type;	/* QoS or Default window */
> > +			u8 status;
> > +			u32 complete_irq;	/* Completion interrupt */
> > +			u32 fault_irq;	/* Fault interrupt */
> > +			u64 domain[6];	/* Associativity domain Ids
> > */
> > +					/* this window is allocated */
> > +			u64 util;
> > +
> > +			/* List of windows opened which is used for LPM
> > */
> > +			struct list_head win_list;
> > +			u64 flags;
> > +			char *name;
> > +			int fault_virq;
> > +		} lpar;
> > +	};
> > +};
> 
> The more typical way to do code like this is have the common bit as
> its 
> own struct, and then have the users embed it into their own structs.
> 
> 
> struct vas_window {
> 	u32 winid;
> 	u32 wcreds_max;	/* Window credits */
> 	enum vas_cop_type cop;
> 	struct vas_user_win_ref task_ref;
> 	char *dbgname;
> 	struct dentry *dbgdir;
> };
> 
> struct pnv_vas_window {
> 	struct vas_window vas_window;
> 
> 	void *vinst;	/* points to VAS instance */
> 	bool tx_win;	/* True if send window */
> 	bool nx_win;	/* True if NX window */
> 	bool user_win;	/* True if user space window */
> 	void *hvwc_map;	/* HV window context */
> 	void *uwc_map;	/* OS/User window context */
> 
> 	/* Fields applicable only to send windows */
> 	void *paste_kaddr;
> 	char *paste_addr_name;
> 	struct vas_window *rxwin;
> 
> 	atomic_t num_txwins;	/* Only for receive windows */
> };
> 
> Which helps reusability / avoids churn (don't have to update the
> same 
> structure to add new functionality), slightly helps naming and union 
> size mismatches, helps with type checking, etc.
> 
> Maybe not a great benefit for your code as is which may not grow more
> users, but unless there are some good reasons for the unions I would 
> really consider changing to this style.

Defined platform specific data as union for the following reasons:
- vas_window address is saved for each file descriptor (fp-
>private_data). If we define separate structs for PowerNV and PowerVM,
'struct vas_window' has to be the first element which can add
confusion.
- vas-window is also used in the PowerNV driver. since exposed this
struct to the driver, thought clean way of exposing common vas-window. 
- Not wasting much memory on PowerNV. Max may be around 20 bytes /
window. 

Thanks
Haren
> 
> Thanks,
> Nick
> 
> > +		struct {
> > +			u64 win_addr;	/* Physical paste address
> > */
> > +			u8 win_type;	/* QoS or Default window */
> > +			u8 status;
> > +			u32 complete_irq;	/* Completion interrupt */
> > +			u32 fault_irq;	/* Fault interrupt */
> > +			u64 domain[6];	/* Associativity domain Ids
> > */
> > +					/* this window is allocated */
> > +			u64 util;
> > +
> > +			/* List of windows opened which is used for LPM
> > */
> > +			struct list_head win_list;
> > +			u64 flags;
> > +			char *name;
> > +			int fault_virq;
> > +		} lpar;
> > +	};
> > +};
> > +
> >  /*
> >   * User space window operations used for powernv and powerVM
> >   */
> > diff --git a/arch/powerpc/platforms/powernv/vas-debug.c
> > b/arch/powerpc/platforms/powernv/vas-debug.c
> > index 41fa90d2f4ab..80f735449ab8 100644
> > --- a/arch/powerpc/platforms/powernv/vas-debug.c
> > +++ b/arch/powerpc/platforms/powernv/vas-debug.c
> > @@ -9,6 +9,7 @@
> >  #include <linux/slab.h>
> >  #include <linux/debugfs.h>
> >  #include <linux/seq_file.h>
> > +#include <asm/vas.h>
> >  #include "vas.h"
> >  
> >  static struct dentry *vas_debugfs;
> > @@ -33,11 +34,11 @@ static int info_show(struct seq_file *s, void
> > *private)
> >  	mutex_lock(&vas_mutex);
> >  
> >  	/* ensure window is not unmapped */
> > -	if (!window->hvwc_map)
> > +	if (!window->pnv.hvwc_map)
> >  		goto unlock;
> >  
> >  	seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop),
> > -					window->tx_win ? "Send" :
> > "Receive");
> > +				window->pnv.tx_win ? "Send" :
> > "Receive");
> >  	seq_printf(s, "Pid : %d\n", vas_window_pid(window));
> >  
> >  unlock:
> > @@ -60,7 +61,7 @@ static int hvwc_show(struct seq_file *s, void
> > *private)
> >  	mutex_lock(&vas_mutex);
> >  
> >  	/* ensure window is not unmapped */
> > -	if (!window->hvwc_map)
> > +	if (!window->pnv.hvwc_map)
> >  		goto unlock;
> >  
> >  	print_reg(s, window, VREG(LPID));
> > @@ -115,9 +116,10 @@ void vas_window_free_dbgdir(struct vas_window
> > *window)
> >  
> >  void vas_window_init_dbgdir(struct vas_window *window)
> >  {
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  	struct dentry *d;
> >  
> > -	if (!window->vinst->dbgdir)
> > +	if (!vinst->dbgdir)
> >  		return;
> >  
> >  	window->dbgname = kzalloc(16, GFP_KERNEL);
> > @@ -126,7 +128,7 @@ void vas_window_init_dbgdir(struct vas_window
> > *window)
> >  
> >  	snprintf(window->dbgname, 16, "w%d", window->winid);
> >  
> > -	d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir);
> > +	d = debugfs_create_dir(window->dbgname, vinst->dbgdir);
> >  	window->dbgdir = d;
> >  
> >  	debugfs_create_file("info", 0444, d, window, &info_fops);
> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c
> > b/arch/powerpc/platforms/powernv/vas-fault.c
> > index 2729ac541fb3..faaf5b110645 100644
> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > @@ -152,10 +152,10 @@ irqreturn_t vas_fault_thread_fn(int irq, void
> > *data)
> >  			/*
> >  			 * NX sees faults only with user space windows.
> >  			 */
> > -			if (window->user_win)
> > +			if (window->pnv.user_win)
> >  				vas_update_csb(crb, &window->task_ref);
> >  			else
> > -				WARN_ON_ONCE(!window->user_win);
> > +				WARN_ON_ONCE(!window->pnv.user_win);
> >  
> >  			/*
> >  			 * Return credit for send window after
> > processing
> > diff --git a/arch/powerpc/platforms/powernv/vas-trace.h
> > b/arch/powerpc/platforms/powernv/vas-trace.h
> > index a449b9f0c12e..843aae37c07a 100644
> > --- a/arch/powerpc/platforms/powernv/vas-trace.h
> > +++ b/arch/powerpc/platforms/powernv/vas-trace.h
> > @@ -95,9 +95,11 @@ TRACE_EVENT(	vas_paste_crb,
> >  
> >  		TP_fast_assign(
> >  			__entry->pid = tsk->pid;
> > -			__entry->vasid = win->vinst->vas_id;
> > +			__entry->vasid =
> > +				((struct vas_instance *)win-
> > >pnv.vinst)->vas_id;
> >  			__entry->winid = win->winid;
> > -			__entry->paste_kaddr = (unsigned long)win-
> > >paste_kaddr
> > +			__entry->paste_kaddr =
> > +				(unsigned long)win->pnv.paste_kaddr;
> >  		),
> >  
> >  		TP_printk("pid=%d, vasid=%d, winid=%d,
> > paste_kaddr=0x%016lx\n",
> > diff --git a/arch/powerpc/platforms/powernv/vas-window.c
> > b/arch/powerpc/platforms/powernv/vas-window.c
> > index ffd619e5a218..6ce8ee4b3371 100644
> > --- a/arch/powerpc/platforms/powernv/vas-window.c
> > +++ b/arch/powerpc/platforms/powernv/vas-window.c
> > @@ -31,9 +31,10 @@ void vas_win_paste_addr(struct vas_window
> > *window, u64 *addr, int *len)
> >  {
> >  	int winid;
> >  	u64 base, shift;
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  
> > -	base = window->vinst->paste_base_addr;
> > -	shift = window->vinst->paste_win_id_shift;
> > +	base = vinst->paste_base_addr;
> > +	shift = vinst->paste_win_id_shift;
> >  	winid = window->winid;
> >  
> >  	*addr  = base + (winid << shift);
> > @@ -46,9 +47,10 @@ void vas_win_paste_addr(struct vas_window
> > *window, u64 *addr, int *len)
> >  static inline void get_hvwc_mmio_bar(struct vas_window *window,
> >  			u64 *start, int *len)
> >  {
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  	u64 pbaddr;
> >  
> > -	pbaddr = window->vinst->hvwc_bar_start;
> > +	pbaddr = vinst->hvwc_bar_start;
> >  	*start = pbaddr + window->winid * VAS_HVWC_SIZE;
> >  	*len = VAS_HVWC_SIZE;
> >  }
> > @@ -56,9 +58,10 @@ static inline void get_hvwc_mmio_bar(struct
> > vas_window *window,
> >  static inline void get_uwc_mmio_bar(struct vas_window *window,
> >  			u64 *start, int *len)
> >  {
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  	u64 pbaddr;
> >  
> > -	pbaddr = window->vinst->uwc_bar_start;
> > +	pbaddr = vinst->uwc_bar_start;
> >  	*start = pbaddr + window->winid * VAS_UWC_SIZE;
> >  	*len = VAS_UWC_SIZE;
> >  }
> > @@ -74,13 +77,14 @@ static void *map_paste_region(struct vas_window
> > *txwin)
> >  	void *map;
> >  	char *name;
> >  	u64 start;
> > +	struct vas_instance *vinst = txwin->pnv.vinst;
> >  
> > -	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", txwin->vinst-
> > >vas_id,
> > +	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", vinst->vas_id,
> >  				txwin->winid);
> >  	if (!name)
> >  		goto free_name;
> >  
> > -	txwin->paste_addr_name = name;
> > +	txwin->pnv.paste_addr_name = name;
> >  	vas_win_paste_addr(txwin, &start, &len);
> >  
> >  	if (!request_mem_region(start, len, name)) {
> > @@ -138,12 +142,12 @@ static void unmap_paste_region(struct
> > vas_window *window)
> >  	int len;
> >  	u64 busaddr_start;
> >  
> > -	if (window->paste_kaddr) {
> > +	if (window->pnv.paste_kaddr) {
> >  		vas_win_paste_addr(window, &busaddr_start, &len);
> > -		unmap_region(window->paste_kaddr, busaddr_start, len);
> > -		window->paste_kaddr = NULL;
> > -		kfree(window->paste_addr_name);
> > -		window->paste_addr_name = NULL;
> > +		unmap_region(window->pnv.paste_kaddr, busaddr_start,
> > len);
> > +		window->pnv.paste_kaddr = NULL;
> > +		kfree(window->pnv.paste_addr_name);
> > +		window->pnv.paste_addr_name = NULL;
> >  	}
> >  }
> >  
> > @@ -163,11 +167,11 @@ static void unmap_winctx_mmio_bars(struct
> > vas_window *window)
> >  
> >  	mutex_lock(&vas_mutex);
> >  
> > -	hvwc_map = window->hvwc_map;
> > -	window->hvwc_map = NULL;
> > +	hvwc_map = window->pnv.hvwc_map;
> > +	window->pnv.hvwc_map = NULL;
> >  
> > -	uwc_map = window->uwc_map;
> > -	window->uwc_map = NULL;
> > +	uwc_map = window->pnv.uwc_map;
> > +	window->pnv.uwc_map = NULL;
> >  
> >  	mutex_unlock(&vas_mutex);
> >  
> > @@ -193,12 +197,12 @@ static int map_winctx_mmio_bars(struct
> > vas_window *window)
> >  	u64 start;
> >  
> >  	get_hvwc_mmio_bar(window, &start, &len);
> > -	window->hvwc_map = map_mmio_region("HVWCM_Window", start, len);
> > +	window->pnv.hvwc_map = map_mmio_region("HVWCM_Window", start,
> > len);
> >  
> >  	get_uwc_mmio_bar(window, &start, &len);
> > -	window->uwc_map = map_mmio_region("UWCM_Window", start, len);
> > +	window->pnv.uwc_map = map_mmio_region("UWCM_Window", start,
> > len);
> >  
> > -	if (!window->hvwc_map || !window->uwc_map) {
> > +	if (!window->pnv.hvwc_map || !window->pnv.uwc_map) {
> >  		unmap_winctx_mmio_bars(window);
> >  		return -1;
> >  	}
> > @@ -523,7 +527,7 @@ static int vas_assign_window_id(struct ida
> > *ida)
> >  static void vas_window_free(struct vas_window *window)
> >  {
> >  	int winid = window->winid;
> > -	struct vas_instance *vinst = window->vinst;
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  
> >  	unmap_winctx_mmio_bars(window);
> >  
> > @@ -547,7 +551,7 @@ static struct vas_window
> > *vas_window_alloc(struct vas_instance *vinst)
> >  	if (!window)
> >  		goto out_free;
> >  
> > -	window->vinst = vinst;
> > +	window->pnv.vinst = vinst;
> >  	window->winid = winid;
> >  
> >  	if (map_winctx_mmio_bars(window))
> > @@ -566,9 +570,9 @@ static struct vas_window
> > *vas_window_alloc(struct vas_instance *vinst)
> >  static void put_rx_win(struct vas_window *rxwin)
> >  {
> >  	/* Better not be a send window! */
> > -	WARN_ON_ONCE(rxwin->tx_win);
> > +	WARN_ON_ONCE(rxwin->pnv.tx_win);
> >  
> > -	atomic_dec(&rxwin->num_txwins);
> > +	atomic_dec(&rxwin->pnv.num_txwins);
> >  }
> >  
> >  /*
> > @@ -591,7 +595,7 @@ static struct vas_window *get_user_rxwin(struct
> > vas_instance *vinst, u32 pswid)
> >  
> >  	rxwin = vinst->windows[winid];
> >  
> > -	if (!rxwin || rxwin->tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
> > +	if (!rxwin || rxwin->pnv.tx_win || rxwin->cop !=
> > VAS_COP_TYPE_FTW)
> >  		return ERR_PTR(-EINVAL);
> >  
> >  	return rxwin;
> > @@ -616,7 +620,7 @@ static struct vas_window
> > *get_vinst_rxwin(struct vas_instance *vinst,
> >  		rxwin = vinst->rxwin[cop] ?: ERR_PTR(-EINVAL);
> >  
> >  	if (!IS_ERR(rxwin))
> > -		atomic_inc(&rxwin->num_txwins);
> > +		atomic_inc(&rxwin->pnv.num_txwins);
> >  
> >  	mutex_unlock(&vinst->mutex);
> >  
> > @@ -649,7 +653,7 @@ static void set_vinst_win(struct vas_instance
> > *vinst,
> >  	 * There should only be one receive window for a coprocessor
> > type
> >  	 * unless its a user (FTW) window.
> >  	 */
> > -	if (!window->user_win && !window->tx_win) {
> > +	if (!window->pnv.user_win && !window->pnv.tx_win) {
> >  		WARN_ON_ONCE(vinst->rxwin[window->cop]);
> >  		vinst->rxwin[window->cop] = window;
> >  	}
> > @@ -667,11 +671,11 @@ static void set_vinst_win(struct vas_instance
> > *vinst,
> >  static void clear_vinst_win(struct vas_window *window)
> >  {
> >  	int id = window->winid;
> > -	struct vas_instance *vinst = window->vinst;
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  
> >  	mutex_lock(&vinst->mutex);
> >  
> > -	if (!window->user_win && !window->tx_win) {
> > +	if (!window->pnv.user_win && !window->pnv.tx_win) {
> >  		WARN_ON_ONCE(!vinst->rxwin[window->cop]);
> >  		vinst->rxwin[window->cop] = NULL;
> >  	}
> > @@ -686,6 +690,8 @@ static void init_winctx_for_rxwin(struct
> > vas_window *rxwin,
> >  			struct vas_rx_win_attr *rxattr,
> >  			struct vas_winctx *winctx)
> >  {
> > +	struct vas_instance *vinst;
> > +
> >  	/*
> >  	 * We first zero (memset()) all fields and only set non-zero
> > fields.
> >  	 * Following fields are 0/false but maybe deserve a comment:
> > @@ -750,8 +756,9 @@ static void init_winctx_for_rxwin(struct
> > vas_window *rxwin,
> >  
> >  	winctx->min_scope = VAS_SCOPE_LOCAL;
> >  	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
> > -	if (rxwin->vinst->virq)
> > -		winctx->irq_port = rxwin->vinst->irq_port;
> > +	vinst = rxwin->pnv.vinst;
> > +	if (vinst->virq)
> > +		winctx->irq_port = vinst->irq_port;
> >  }
> >  
> >  static bool rx_win_args_valid(enum vas_cop_type cop,
> > @@ -874,9 +881,9 @@ struct vas_window *vas_rx_win_open(int vasid,
> > enum vas_cop_type cop,
> >  		return rxwin;
> >  	}
> >  
> > -	rxwin->tx_win = false;
> > -	rxwin->nx_win = rxattr->nx_win;
> > -	rxwin->user_win = rxattr->user_win;
> > +	rxwin->pnv.tx_win = false;
> > +	rxwin->pnv.nx_win = rxattr->nx_win;
> > +	rxwin->pnv.user_win = rxattr->user_win;
> >  	rxwin->cop = cop;
> >  	rxwin->wcreds_max = rxattr->wcreds_max;
> >  
> > @@ -910,6 +917,8 @@ static void init_winctx_for_txwin(struct
> > vas_window *txwin,
> >  			struct vas_tx_win_attr *txattr,
> >  			struct vas_winctx *winctx)
> >  {
> > +	struct vas_instance *vinst = txwin->pnv.vinst;
> > +
> >  	/*
> >  	 * We first zero all fields and only set non-zero ones.
> > Following
> >  	 * are some fields set to 0/false for the stated reason:
> > @@ -930,7 +939,7 @@ static void init_winctx_for_txwin(struct
> > vas_window *txwin,
> >  	winctx->wcreds_max = txwin->wcreds_max;
> >  
> >  	winctx->user_win = txattr->user_win;
> > -	winctx->nx_win = txwin->rxwin->nx_win;
> > +	winctx->nx_win = txwin->pnv.rxwin->pnv.nx_win;
> >  	winctx->pin_win = txattr->pin_win;
> >  	winctx->rej_no_credit = txattr->rej_no_credit;
> >  	winctx->rsvd_txbuf_enable = txattr->rsvd_txbuf_enable;
> > @@ -947,23 +956,23 @@ static void init_winctx_for_txwin(struct
> > vas_window *txwin,
> >  
> >  	winctx->lpid = txattr->lpid;
> >  	winctx->pidr = txattr->pidr;
> > -	winctx->rx_win_id = txwin->rxwin->winid;
> > +	winctx->rx_win_id = txwin->pnv.rxwin->winid;
> >  	/*
> >  	 * IRQ and fault window setup is successful. Set fault window
> >  	 * for the send window so that ready to handle faults.
> >  	 */
> > -	if (txwin->vinst->virq)
> > -		winctx->fault_win_id = txwin->vinst->fault_win->winid;
> > +	if (vinst->virq)
> > +		winctx->fault_win_id = vinst->fault_win->winid;
> >  
> >  	winctx->dma_type = VAS_DMA_TYPE_INJECT;
> >  	winctx->tc_mode = txattr->tc_mode;
> >  	winctx->min_scope = VAS_SCOPE_LOCAL;
> >  	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
> > -	if (txwin->vinst->virq)
> > -		winctx->irq_port = txwin->vinst->irq_port;
> > +	if (vinst->virq)
> > +		winctx->irq_port = vinst->irq_port;
> >  
> >  	winctx->pswid = txattr->pswid ? txattr->pswid :
> > -			encode_pswid(txwin->vinst->vas_id, txwin-
> > >winid);
> > +			encode_pswid(vinst->vas_id, txwin->winid);
> >  }
> >  
> >  static bool tx_win_args_valid(enum vas_cop_type cop,
> > @@ -1031,10 +1040,10 @@ struct vas_window *vas_tx_win_open(int
> > vasid, enum vas_cop_type cop,
> >  	}
> >  
> >  	txwin->cop = cop;
> > -	txwin->tx_win = 1;
> > -	txwin->rxwin = rxwin;
> > -	txwin->nx_win = txwin->rxwin->nx_win;
> > -	txwin->user_win = attr->user_win;
> > +	txwin->pnv.tx_win = 1;
> > +	txwin->pnv.rxwin = rxwin;
> > +	txwin->pnv.nx_win = txwin->pnv.rxwin->pnv.nx_win;
> > +	txwin->pnv.user_win = attr->user_win;
> >  	txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT;
> >  
> >  	init_winctx_for_txwin(txwin, attr, &winctx);
> > @@ -1049,10 +1058,10 @@ struct vas_window *vas_tx_win_open(int
> > vasid, enum vas_cop_type cop,
> >  	 * NOTE: If kernel ever resubmits a user CRB after handling a
> > page
> >  	 *	 fault, we will need to map this into kernel as well.
> >  	 */
> > -	if (!txwin->user_win) {
> > -		txwin->paste_kaddr = map_paste_region(txwin);
> > -		if (IS_ERR(txwin->paste_kaddr)) {
> > -			rc = PTR_ERR(txwin->paste_kaddr);
> > +	if (!txwin->pnv.user_win) {
> > +		txwin->pnv.paste_kaddr = map_paste_region(txwin);
> > +		if (IS_ERR(txwin->pnv.paste_kaddr)) {
> > +			rc = PTR_ERR(txwin->pnv.paste_kaddr);
> >  			goto free_window;
> >  		}
> >  	} else {
> > @@ -1104,9 +1113,9 @@ int vas_paste_crb(struct vas_window *txwin,
> > int offset, bool re)
> >  	 * report-enable flag is set for NX windows. Ensure software
> >  	 * complies too.
> >  	 */
> > -	WARN_ON_ONCE(txwin->nx_win && !re);
> > +	WARN_ON_ONCE(txwin->pnv.nx_win && !re);
> >  
> > -	addr = txwin->paste_kaddr;
> > +	addr = txwin->pnv.paste_kaddr;
> >  	if (re) {
> >  		/*
> >  		 * Set the REPORT_ENABLE bit (equivalent to writing
> > @@ -1153,7 +1162,7 @@ static void poll_window_credits(struct
> > vas_window *window)
> >  	int count = 0;
> >  
> >  	val = read_hvwc_reg(window, VREG(WINCTL));
> > -	if (window->tx_win)
> > +	if (window->pnv.tx_win)
> >  		mode = GET_FIELD(VAS_WINCTL_TX_WCRED_MODE, val);
> >  	else
> >  		mode = GET_FIELD(VAS_WINCTL_RX_WCRED_MODE, val);
> > @@ -1161,7 +1170,7 @@ static void poll_window_credits(struct
> > vas_window *window)
> >  	if (!mode)
> >  		return;
> >  retry:
> > -	if (window->tx_win) {
> > +	if (window->pnv.tx_win) {
> >  		val = read_hvwc_reg(window, VREG(TX_WCRED));
> >  		creds = GET_FIELD(VAS_TX_WCRED, val);
> >  	} else {
> > @@ -1277,7 +1286,7 @@ int vas_win_close(struct vas_window *window)
> >  	if (!window)
> >  		return 0;
> >  
> > -	if (!window->tx_win && atomic_read(&window->num_txwins) != 0) {
> > +	if (!window->pnv.tx_win && atomic_read(&window->pnv.num_txwins) 
> > != 0) {
> >  		pr_devel("Attempting to close an active Rx window!\n");
> >  		WARN_ON_ONCE(1);
> >  		return -EBUSY;
> > @@ -1296,11 +1305,11 @@ int vas_win_close(struct vas_window
> > *window)
> >  	poll_window_castout(window);
> >  
> >  	/* if send window, drop reference to matching receive window */
> > -	if (window->tx_win) {
> > -		if (window->user_win)
> > +	if (window->pnv.tx_win) {
> > +		if (window->pnv.user_win)
> >  			vas_drop_reference_pid_mm(&window->task_ref);
> >  
> > -		put_rx_win(window->rxwin);
> > +		put_rx_win(window->pnv.rxwin);
> >  	}
> >  
> >  	vas_window_free(window);
> > @@ -1384,12 +1393,12 @@ struct vas_window
> > *vas_pswid_to_window(struct vas_instance *vinst,
> >  	 * since their CRBs are ignored (not queued on FIFO or
> > processed
> >  	 * by NX).
> >  	 */
> > -	if (!window->tx_win || !window->user_win || !window->nx_win ||
> > -			window->cop == VAS_COP_TYPE_FAULT ||
> > -			window->cop == VAS_COP_TYPE_FTW) {
> > +	if (!window->pnv.tx_win || !window->pnv.user_win ||
> > +		!window->pnv.nx_win || window->cop ==
> > VAS_COP_TYPE_FAULT ||
> > +		window->cop == VAS_COP_TYPE_FTW) {
> >  		pr_err("PSWID decode: id %d, tx %d, user %d, nx %d, cop
> > %d\n",
> > -			winid, window->tx_win, window->user_win,
> > -			window->nx_win, window->cop);
> > +			winid, window->pnv.tx_win, window-
> > >pnv.user_win,
> > +			window->pnv.nx_win, window->cop);
> >  		WARN_ON(1);
> >  	}
> >  
> > diff --git a/arch/powerpc/platforms/powernv/vas.h
> > b/arch/powerpc/platforms/powernv/vas.h
> > index f354dd5c51bd..f2d9daff3d82 100644
> > --- a/arch/powerpc/platforms/powernv/vas.h
> > +++ b/arch/powerpc/platforms/powernv/vas.h
> > @@ -345,34 +345,6 @@ struct vas_instance {
> >  	struct dentry *dbgdir;
> >  };
> >  
> > -/*
> > - * In-kernel state a VAS window. One per window.
> > - */
> > -struct vas_window {
> > -	/* Fields common to send and receive windows */
> > -	struct vas_instance *vinst;
> > -	int winid;
> > -	bool tx_win;		/* True if send window */
> > -	bool nx_win;		/* True if NX window */
> > -	bool user_win;		/* True if user space window */
> > -	void *hvwc_map;		/* HV window context */
> > -	void *uwc_map;		/* OS/User window context */
> > -	int wcreds_max;		/* Window credits */
> > -
> > -	struct vas_user_win_ref task_ref;
> > -	char *dbgname;
> > -	struct dentry *dbgdir;
> > -
> > -	/* Fields applicable only to send windows */
> > -	void *paste_kaddr;
> > -	char *paste_addr_name;
> > -	struct vas_window *rxwin;
> > -
> > -	/* Feilds applicable only to receive windows */
> > -	enum vas_cop_type cop;
> > -	atomic_t num_txwins;
> > -};
> > -
> >  /*
> >   * Container for the hardware state of a window. One per-window.
> >   *
> > @@ -449,8 +421,8 @@ static inline void vas_log_write(struct
> > vas_window *win, char *name,
> >  {
> >  	if (val)
> >  		pr_debug("%swin #%d: %s reg %p, val 0x%016llx\n",
> > -				win->tx_win ? "Tx" : "Rx", win->winid,
> > name,
> > -				regptr, val);
> > +				win->pnv.tx_win ? "Tx" : "Rx", win-
> > >winid,
> > +				name, regptr, val);
> >  }
> >  
> >  static inline void write_uwc_reg(struct vas_window *win, char
> > *name,
> > @@ -458,7 +430,7 @@ static inline void write_uwc_reg(struct
> > vas_window *win, char *name,
> >  {
> >  	void *regptr;
> >  
> > -	regptr = win->uwc_map + reg;
> > +	regptr = win->pnv.uwc_map + reg;
> >  	vas_log_write(win, name, regptr, val);
> >  
> >  	out_be64(regptr, val);
> > @@ -469,7 +441,7 @@ static inline void write_hvwc_reg(struct
> > vas_window *win, char *name,
> >  {
> >  	void *regptr;
> >  
> > -	regptr = win->hvwc_map + reg;
> > +	regptr = win->pnv.hvwc_map + reg;
> >  	vas_log_write(win, name, regptr, val);
> >  
> >  	out_be64(regptr, val);
> > @@ -478,7 +450,7 @@ static inline void write_hvwc_reg(struct
> > vas_window *win, char *name,
> >  static inline u64 read_hvwc_reg(struct vas_window *win,
> >  			char *name __maybe_unused, s32 reg)
> >  {
> > -	return in_be64(win->hvwc_map+reg);
> > +	return in_be64(win->pnv.hvwc_map + reg);
> >  }
> >  
> >  /*
> > -- 
> > 2.18.2
> > 
> > 
> > 


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
@ 2021-06-04  4:35       ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04  4:35 UTC (permalink / raw)
  To: Nicholas Piggin, herbert, linux-crypto, linuxppc-dev, mpe

On Thu, 2021-06-03 at 14:38 +1000, Nicholas Piggin wrote:
> Excerpts from Haren Myneni's message of May 21, 2021 7:33 pm:
> > Same vas_window struct is used on powerNV and pseries. So this
> > patch
> > changes in struct vas_window to support both platforms and also the
> > corresponding modifications in powerNV vas code.
> > 
> > On powerNV, vas_window is used for both TX and RX windows, whereas
> > only for TX windows on powerVM. So some elements are specific to
> > these platforms.
> > 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > ---
> >  arch/powerpc/include/asm/vas.h              |  50 +++++++-
> >  arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
> >  arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
> >  arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
> >  arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++-----
> > ----
> >  arch/powerpc/platforms/powernv/vas.h        |  38 +-----
> >  6 files changed, 135 insertions(+), 104 deletions(-)
> > 
> > diff --git a/arch/powerpc/include/asm/vas.h
> > b/arch/powerpc/include/asm/vas.h
> > index 2c1040f399d9..49bfb5be896d 100644
> > --- a/arch/powerpc/include/asm/vas.h
> > +++ b/arch/powerpc/include/asm/vas.h
> > @@ -10,8 +10,6 @@
> >  #include <asm/icswx.h>
> >  #include <uapi/asm/vas-api.h>
> >  
> > -struct vas_window;
> > -
> >  /*
> >   * Min and max FIFO sizes are based on Version 1.05 Section
> > 3.1.4.25
> >   * (Local FIFO Size Register) of the VAS workbook.
> > @@ -63,6 +61,54 @@ struct vas_user_win_ref {
> >  	struct mm_struct *mm;	/* Linux process mm_struct */
> >  };
> >  
> > +/*
> > + * In-kernel state a VAS window. One per window.
> > + * powerVM: Used only for Tx windows.
> > + * powerNV: Used for both Tx and Rx windows.
> > + */
> > +struct vas_window {
> > +	u32 winid;
> > +	u32 wcreds_max;	/* Window credits */
> > +	enum vas_cop_type cop;
> > +	struct vas_user_win_ref task_ref;
> > +	char *dbgname;
> > +	struct dentry *dbgdir;
> > +	union {
> > +		/* powerNV specific data */
> > +		struct {
> > +			void *vinst;	/* points to VAS instance
> > */
> > +			bool tx_win;	/* True if send window */
> > +			bool nx_win;	/* True if NX window */
> > +			bool user_win;	/* True if user space
> > window */
> > +			void *hvwc_map;	/* HV window context */
> > +			void *uwc_map;	/* OS/User window context
> > */
> > +
> > +			/* Fields applicable only to send windows */
> > +			void *paste_kaddr;
> > +			char *paste_addr_name;
> > +			struct vas_window *rxwin;
> > +
> > +			atomic_t num_txwins;	/* Only for receive
> > windows */
> > +		} pnv;
> > +		struct {
> > +			u64 win_addr;	/* Physical paste address
> > */
> > +			u8 win_type;	/* QoS or Default window */
> > +			u8 status;
> > +			u32 complete_irq;	/* Completion interrupt */
> > +			u32 fault_irq;	/* Fault interrupt */
> > +			u64 domain[6];	/* Associativity domain Ids
> > */
> > +					/* this window is allocated */
> > +			u64 util;
> > +
> > +			/* List of windows opened which is used for LPM
> > */
> > +			struct list_head win_list;
> > +			u64 flags;
> > +			char *name;
> > +			int fault_virq;
> > +		} lpar;
> > +	};
> > +};
> 
> The more typical way to do code like this is have the common bit as
> its 
> own struct, and then have the users embed it into their own structs.
> 
> 
> struct vas_window {
> 	u32 winid;
> 	u32 wcreds_max;	/* Window credits */
> 	enum vas_cop_type cop;
> 	struct vas_user_win_ref task_ref;
> 	char *dbgname;
> 	struct dentry *dbgdir;
> };
> 
> struct pnv_vas_window {
> 	struct vas_window vas_window;
> 
> 	void *vinst;	/* points to VAS instance */
> 	bool tx_win;	/* True if send window */
> 	bool nx_win;	/* True if NX window */
> 	bool user_win;	/* True if user space window */
> 	void *hvwc_map;	/* HV window context */
> 	void *uwc_map;	/* OS/User window context */
> 
> 	/* Fields applicable only to send windows */
> 	void *paste_kaddr;
> 	char *paste_addr_name;
> 	struct vas_window *rxwin;
> 
> 	atomic_t num_txwins;	/* Only for receive windows */
> };
> 
> Which helps reusability / avoids churn (don't have to update the
> same 
> structure to add new functionality), slightly helps naming and union 
> size mismatches, helps with type checking, etc.
> 
> Maybe not a great benefit for your code as is which may not grow more
> users, but unless there are some good reasons for the unions I would 
> really consider changing to this style.

Defined platform specific data as union for the following reasons:
- vas_window address is saved for each file descriptor (fp-
>private_data). If we define separate structs for PowerNV and PowerVM,
'struct vas_window' has to be the first element which can add
confusion.
- vas-window is also used in the PowerNV driver. since exposed this
struct to the driver, thought clean way of exposing common vas-window. 
- Not wasting much memory on PowerNV. Max may be around 20 bytes /
window. 

Thanks
Haren
> 
> Thanks,
> Nick
> 
> > +		struct {
> > +			u64 win_addr;	/* Physical paste address
> > */
> > +			u8 win_type;	/* QoS or Default window */
> > +			u8 status;
> > +			u32 complete_irq;	/* Completion interrupt */
> > +			u32 fault_irq;	/* Fault interrupt */
> > +			u64 domain[6];	/* Associativity domain Ids
> > */
> > +					/* this window is allocated */
> > +			u64 util;
> > +
> > +			/* List of windows opened which is used for LPM
> > */
> > +			struct list_head win_list;
> > +			u64 flags;
> > +			char *name;
> > +			int fault_virq;
> > +		} lpar;
> > +	};
> > +};
> > +
> >  /*
> >   * User space window operations used for powernv and powerVM
> >   */
> > diff --git a/arch/powerpc/platforms/powernv/vas-debug.c
> > b/arch/powerpc/platforms/powernv/vas-debug.c
> > index 41fa90d2f4ab..80f735449ab8 100644
> > --- a/arch/powerpc/platforms/powernv/vas-debug.c
> > +++ b/arch/powerpc/platforms/powernv/vas-debug.c
> > @@ -9,6 +9,7 @@
> >  #include <linux/slab.h>
> >  #include <linux/debugfs.h>
> >  #include <linux/seq_file.h>
> > +#include <asm/vas.h>
> >  #include "vas.h"
> >  
> >  static struct dentry *vas_debugfs;
> > @@ -33,11 +34,11 @@ static int info_show(struct seq_file *s, void
> > *private)
> >  	mutex_lock(&vas_mutex);
> >  
> >  	/* ensure window is not unmapped */
> > -	if (!window->hvwc_map)
> > +	if (!window->pnv.hvwc_map)
> >  		goto unlock;
> >  
> >  	seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop),
> > -					window->tx_win ? "Send" :
> > "Receive");
> > +				window->pnv.tx_win ? "Send" :
> > "Receive");
> >  	seq_printf(s, "Pid : %d\n", vas_window_pid(window));
> >  
> >  unlock:
> > @@ -60,7 +61,7 @@ static int hvwc_show(struct seq_file *s, void
> > *private)
> >  	mutex_lock(&vas_mutex);
> >  
> >  	/* ensure window is not unmapped */
> > -	if (!window->hvwc_map)
> > +	if (!window->pnv.hvwc_map)
> >  		goto unlock;
> >  
> >  	print_reg(s, window, VREG(LPID));
> > @@ -115,9 +116,10 @@ void vas_window_free_dbgdir(struct vas_window
> > *window)
> >  
> >  void vas_window_init_dbgdir(struct vas_window *window)
> >  {
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  	struct dentry *d;
> >  
> > -	if (!window->vinst->dbgdir)
> > +	if (!vinst->dbgdir)
> >  		return;
> >  
> >  	window->dbgname = kzalloc(16, GFP_KERNEL);
> > @@ -126,7 +128,7 @@ void vas_window_init_dbgdir(struct vas_window
> > *window)
> >  
> >  	snprintf(window->dbgname, 16, "w%d", window->winid);
> >  
> > -	d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir);
> > +	d = debugfs_create_dir(window->dbgname, vinst->dbgdir);
> >  	window->dbgdir = d;
> >  
> >  	debugfs_create_file("info", 0444, d, window, &info_fops);
> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c
> > b/arch/powerpc/platforms/powernv/vas-fault.c
> > index 2729ac541fb3..faaf5b110645 100644
> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > @@ -152,10 +152,10 @@ irqreturn_t vas_fault_thread_fn(int irq, void
> > *data)
> >  			/*
> >  			 * NX sees faults only with user space windows.
> >  			 */
> > -			if (window->user_win)
> > +			if (window->pnv.user_win)
> >  				vas_update_csb(crb, &window->task_ref);
> >  			else
> > -				WARN_ON_ONCE(!window->user_win);
> > +				WARN_ON_ONCE(!window->pnv.user_win);
> >  
> >  			/*
> >  			 * Return credit for send window after
> > processing
> > diff --git a/arch/powerpc/platforms/powernv/vas-trace.h
> > b/arch/powerpc/platforms/powernv/vas-trace.h
> > index a449b9f0c12e..843aae37c07a 100644
> > --- a/arch/powerpc/platforms/powernv/vas-trace.h
> > +++ b/arch/powerpc/platforms/powernv/vas-trace.h
> > @@ -95,9 +95,11 @@ TRACE_EVENT(	vas_paste_crb,
> >  
> >  		TP_fast_assign(
> >  			__entry->pid = tsk->pid;
> > -			__entry->vasid = win->vinst->vas_id;
> > +			__entry->vasid =
> > +				((struct vas_instance *)win-
> > >pnv.vinst)->vas_id;
> >  			__entry->winid = win->winid;
> > -			__entry->paste_kaddr = (unsigned long)win-
> > >paste_kaddr
> > +			__entry->paste_kaddr =
> > +				(unsigned long)win->pnv.paste_kaddr;
> >  		),
> >  
> >  		TP_printk("pid=%d, vasid=%d, winid=%d,
> > paste_kaddr=0x%016lx\n",
> > diff --git a/arch/powerpc/platforms/powernv/vas-window.c
> > b/arch/powerpc/platforms/powernv/vas-window.c
> > index ffd619e5a218..6ce8ee4b3371 100644
> > --- a/arch/powerpc/platforms/powernv/vas-window.c
> > +++ b/arch/powerpc/platforms/powernv/vas-window.c
> > @@ -31,9 +31,10 @@ void vas_win_paste_addr(struct vas_window
> > *window, u64 *addr, int *len)
> >  {
> >  	int winid;
> >  	u64 base, shift;
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  
> > -	base = window->vinst->paste_base_addr;
> > -	shift = window->vinst->paste_win_id_shift;
> > +	base = vinst->paste_base_addr;
> > +	shift = vinst->paste_win_id_shift;
> >  	winid = window->winid;
> >  
> >  	*addr  = base + (winid << shift);
> > @@ -46,9 +47,10 @@ void vas_win_paste_addr(struct vas_window
> > *window, u64 *addr, int *len)
> >  static inline void get_hvwc_mmio_bar(struct vas_window *window,
> >  			u64 *start, int *len)
> >  {
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  	u64 pbaddr;
> >  
> > -	pbaddr = window->vinst->hvwc_bar_start;
> > +	pbaddr = vinst->hvwc_bar_start;
> >  	*start = pbaddr + window->winid * VAS_HVWC_SIZE;
> >  	*len = VAS_HVWC_SIZE;
> >  }
> > @@ -56,9 +58,10 @@ static inline void get_hvwc_mmio_bar(struct
> > vas_window *window,
> >  static inline void get_uwc_mmio_bar(struct vas_window *window,
> >  			u64 *start, int *len)
> >  {
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  	u64 pbaddr;
> >  
> > -	pbaddr = window->vinst->uwc_bar_start;
> > +	pbaddr = vinst->uwc_bar_start;
> >  	*start = pbaddr + window->winid * VAS_UWC_SIZE;
> >  	*len = VAS_UWC_SIZE;
> >  }
> > @@ -74,13 +77,14 @@ static void *map_paste_region(struct vas_window
> > *txwin)
> >  	void *map;
> >  	char *name;
> >  	u64 start;
> > +	struct vas_instance *vinst = txwin->pnv.vinst;
> >  
> > -	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", txwin->vinst-
> > >vas_id,
> > +	name = kasprintf(GFP_KERNEL, "window-v%d-w%d", vinst->vas_id,
> >  				txwin->winid);
> >  	if (!name)
> >  		goto free_name;
> >  
> > -	txwin->paste_addr_name = name;
> > +	txwin->pnv.paste_addr_name = name;
> >  	vas_win_paste_addr(txwin, &start, &len);
> >  
> >  	if (!request_mem_region(start, len, name)) {
> > @@ -138,12 +142,12 @@ static void unmap_paste_region(struct
> > vas_window *window)
> >  	int len;
> >  	u64 busaddr_start;
> >  
> > -	if (window->paste_kaddr) {
> > +	if (window->pnv.paste_kaddr) {
> >  		vas_win_paste_addr(window, &busaddr_start, &len);
> > -		unmap_region(window->paste_kaddr, busaddr_start, len);
> > -		window->paste_kaddr = NULL;
> > -		kfree(window->paste_addr_name);
> > -		window->paste_addr_name = NULL;
> > +		unmap_region(window->pnv.paste_kaddr, busaddr_start,
> > len);
> > +		window->pnv.paste_kaddr = NULL;
> > +		kfree(window->pnv.paste_addr_name);
> > +		window->pnv.paste_addr_name = NULL;
> >  	}
> >  }
> >  
> > @@ -163,11 +167,11 @@ static void unmap_winctx_mmio_bars(struct
> > vas_window *window)
> >  
> >  	mutex_lock(&vas_mutex);
> >  
> > -	hvwc_map = window->hvwc_map;
> > -	window->hvwc_map = NULL;
> > +	hvwc_map = window->pnv.hvwc_map;
> > +	window->pnv.hvwc_map = NULL;
> >  
> > -	uwc_map = window->uwc_map;
> > -	window->uwc_map = NULL;
> > +	uwc_map = window->pnv.uwc_map;
> > +	window->pnv.uwc_map = NULL;
> >  
> >  	mutex_unlock(&vas_mutex);
> >  
> > @@ -193,12 +197,12 @@ static int map_winctx_mmio_bars(struct
> > vas_window *window)
> >  	u64 start;
> >  
> >  	get_hvwc_mmio_bar(window, &start, &len);
> > -	window->hvwc_map = map_mmio_region("HVWCM_Window", start, len);
> > +	window->pnv.hvwc_map = map_mmio_region("HVWCM_Window", start,
> > len);
> >  
> >  	get_uwc_mmio_bar(window, &start, &len);
> > -	window->uwc_map = map_mmio_region("UWCM_Window", start, len);
> > +	window->pnv.uwc_map = map_mmio_region("UWCM_Window", start,
> > len);
> >  
> > -	if (!window->hvwc_map || !window->uwc_map) {
> > +	if (!window->pnv.hvwc_map || !window->pnv.uwc_map) {
> >  		unmap_winctx_mmio_bars(window);
> >  		return -1;
> >  	}
> > @@ -523,7 +527,7 @@ static int vas_assign_window_id(struct ida
> > *ida)
> >  static void vas_window_free(struct vas_window *window)
> >  {
> >  	int winid = window->winid;
> > -	struct vas_instance *vinst = window->vinst;
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  
> >  	unmap_winctx_mmio_bars(window);
> >  
> > @@ -547,7 +551,7 @@ static struct vas_window
> > *vas_window_alloc(struct vas_instance *vinst)
> >  	if (!window)
> >  		goto out_free;
> >  
> > -	window->vinst = vinst;
> > +	window->pnv.vinst = vinst;
> >  	window->winid = winid;
> >  
> >  	if (map_winctx_mmio_bars(window))
> > @@ -566,9 +570,9 @@ static struct vas_window
> > *vas_window_alloc(struct vas_instance *vinst)
> >  static void put_rx_win(struct vas_window *rxwin)
> >  {
> >  	/* Better not be a send window! */
> > -	WARN_ON_ONCE(rxwin->tx_win);
> > +	WARN_ON_ONCE(rxwin->pnv.tx_win);
> >  
> > -	atomic_dec(&rxwin->num_txwins);
> > +	atomic_dec(&rxwin->pnv.num_txwins);
> >  }
> >  
> >  /*
> > @@ -591,7 +595,7 @@ static struct vas_window *get_user_rxwin(struct
> > vas_instance *vinst, u32 pswid)
> >  
> >  	rxwin = vinst->windows[winid];
> >  
> > -	if (!rxwin || rxwin->tx_win || rxwin->cop != VAS_COP_TYPE_FTW)
> > +	if (!rxwin || rxwin->pnv.tx_win || rxwin->cop !=
> > VAS_COP_TYPE_FTW)
> >  		return ERR_PTR(-EINVAL);
> >  
> >  	return rxwin;
> > @@ -616,7 +620,7 @@ static struct vas_window
> > *get_vinst_rxwin(struct vas_instance *vinst,
> >  		rxwin = vinst->rxwin[cop] ?: ERR_PTR(-EINVAL);
> >  
> >  	if (!IS_ERR(rxwin))
> > -		atomic_inc(&rxwin->num_txwins);
> > +		atomic_inc(&rxwin->pnv.num_txwins);
> >  
> >  	mutex_unlock(&vinst->mutex);
> >  
> > @@ -649,7 +653,7 @@ static void set_vinst_win(struct vas_instance
> > *vinst,
> >  	 * There should only be one receive window for a coprocessor
> > type
> >  	 * unless its a user (FTW) window.
> >  	 */
> > -	if (!window->user_win && !window->tx_win) {
> > +	if (!window->pnv.user_win && !window->pnv.tx_win) {
> >  		WARN_ON_ONCE(vinst->rxwin[window->cop]);
> >  		vinst->rxwin[window->cop] = window;
> >  	}
> > @@ -667,11 +671,11 @@ static void set_vinst_win(struct vas_instance
> > *vinst,
> >  static void clear_vinst_win(struct vas_window *window)
> >  {
> >  	int id = window->winid;
> > -	struct vas_instance *vinst = window->vinst;
> > +	struct vas_instance *vinst = window->pnv.vinst;
> >  
> >  	mutex_lock(&vinst->mutex);
> >  
> > -	if (!window->user_win && !window->tx_win) {
> > +	if (!window->pnv.user_win && !window->pnv.tx_win) {
> >  		WARN_ON_ONCE(!vinst->rxwin[window->cop]);
> >  		vinst->rxwin[window->cop] = NULL;
> >  	}
> > @@ -686,6 +690,8 @@ static void init_winctx_for_rxwin(struct
> > vas_window *rxwin,
> >  			struct vas_rx_win_attr *rxattr,
> >  			struct vas_winctx *winctx)
> >  {
> > +	struct vas_instance *vinst;
> > +
> >  	/*
> >  	 * We first zero (memset()) all fields and only set non-zero
> > fields.
> >  	 * Following fields are 0/false but maybe deserve a comment:
> > @@ -750,8 +756,9 @@ static void init_winctx_for_rxwin(struct
> > vas_window *rxwin,
> >  
> >  	winctx->min_scope = VAS_SCOPE_LOCAL;
> >  	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
> > -	if (rxwin->vinst->virq)
> > -		winctx->irq_port = rxwin->vinst->irq_port;
> > +	vinst = rxwin->pnv.vinst;
> > +	if (vinst->virq)
> > +		winctx->irq_port = vinst->irq_port;
> >  }
> >  
> >  static bool rx_win_args_valid(enum vas_cop_type cop,
> > @@ -874,9 +881,9 @@ struct vas_window *vas_rx_win_open(int vasid,
> > enum vas_cop_type cop,
> >  		return rxwin;
> >  	}
> >  
> > -	rxwin->tx_win = false;
> > -	rxwin->nx_win = rxattr->nx_win;
> > -	rxwin->user_win = rxattr->user_win;
> > +	rxwin->pnv.tx_win = false;
> > +	rxwin->pnv.nx_win = rxattr->nx_win;
> > +	rxwin->pnv.user_win = rxattr->user_win;
> >  	rxwin->cop = cop;
> >  	rxwin->wcreds_max = rxattr->wcreds_max;
> >  
> > @@ -910,6 +917,8 @@ static void init_winctx_for_txwin(struct
> > vas_window *txwin,
> >  			struct vas_tx_win_attr *txattr,
> >  			struct vas_winctx *winctx)
> >  {
> > +	struct vas_instance *vinst = txwin->pnv.vinst;
> > +
> >  	/*
> >  	 * We first zero all fields and only set non-zero ones.
> > Following
> >  	 * are some fields set to 0/false for the stated reason:
> > @@ -930,7 +939,7 @@ static void init_winctx_for_txwin(struct
> > vas_window *txwin,
> >  	winctx->wcreds_max = txwin->wcreds_max;
> >  
> >  	winctx->user_win = txattr->user_win;
> > -	winctx->nx_win = txwin->rxwin->nx_win;
> > +	winctx->nx_win = txwin->pnv.rxwin->pnv.nx_win;
> >  	winctx->pin_win = txattr->pin_win;
> >  	winctx->rej_no_credit = txattr->rej_no_credit;
> >  	winctx->rsvd_txbuf_enable = txattr->rsvd_txbuf_enable;
> > @@ -947,23 +956,23 @@ static void init_winctx_for_txwin(struct
> > vas_window *txwin,
> >  
> >  	winctx->lpid = txattr->lpid;
> >  	winctx->pidr = txattr->pidr;
> > -	winctx->rx_win_id = txwin->rxwin->winid;
> > +	winctx->rx_win_id = txwin->pnv.rxwin->winid;
> >  	/*
> >  	 * IRQ and fault window setup is successful. Set fault window
> >  	 * for the send window so that ready to handle faults.
> >  	 */
> > -	if (txwin->vinst->virq)
> > -		winctx->fault_win_id = txwin->vinst->fault_win->winid;
> > +	if (vinst->virq)
> > +		winctx->fault_win_id = vinst->fault_win->winid;
> >  
> >  	winctx->dma_type = VAS_DMA_TYPE_INJECT;
> >  	winctx->tc_mode = txattr->tc_mode;
> >  	winctx->min_scope = VAS_SCOPE_LOCAL;
> >  	winctx->max_scope = VAS_SCOPE_VECTORED_GROUP;
> > -	if (txwin->vinst->virq)
> > -		winctx->irq_port = txwin->vinst->irq_port;
> > +	if (vinst->virq)
> > +		winctx->irq_port = vinst->irq_port;
> >  
> >  	winctx->pswid = txattr->pswid ? txattr->pswid :
> > -			encode_pswid(txwin->vinst->vas_id, txwin-
> > >winid);
> > +			encode_pswid(vinst->vas_id, txwin->winid);
> >  }
> >  
> >  static bool tx_win_args_valid(enum vas_cop_type cop,
> > @@ -1031,10 +1040,10 @@ struct vas_window *vas_tx_win_open(int
> > vasid, enum vas_cop_type cop,
> >  	}
> >  
> >  	txwin->cop = cop;
> > -	txwin->tx_win = 1;
> > -	txwin->rxwin = rxwin;
> > -	txwin->nx_win = txwin->rxwin->nx_win;
> > -	txwin->user_win = attr->user_win;
> > +	txwin->pnv.tx_win = 1;
> > +	txwin->pnv.rxwin = rxwin;
> > +	txwin->pnv.nx_win = txwin->pnv.rxwin->pnv.nx_win;
> > +	txwin->pnv.user_win = attr->user_win;
> >  	txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT;
> >  
> >  	init_winctx_for_txwin(txwin, attr, &winctx);
> > @@ -1049,10 +1058,10 @@ struct vas_window *vas_tx_win_open(int
> > vasid, enum vas_cop_type cop,
> >  	 * NOTE: If kernel ever resubmits a user CRB after handling a
> > page
> >  	 *	 fault, we will need to map this into kernel as well.
> >  	 */
> > -	if (!txwin->user_win) {
> > -		txwin->paste_kaddr = map_paste_region(txwin);
> > -		if (IS_ERR(txwin->paste_kaddr)) {
> > -			rc = PTR_ERR(txwin->paste_kaddr);
> > +	if (!txwin->pnv.user_win) {
> > +		txwin->pnv.paste_kaddr = map_paste_region(txwin);
> > +		if (IS_ERR(txwin->pnv.paste_kaddr)) {
> > +			rc = PTR_ERR(txwin->pnv.paste_kaddr);
> >  			goto free_window;
> >  		}
> >  	} else {
> > @@ -1104,9 +1113,9 @@ int vas_paste_crb(struct vas_window *txwin,
> > int offset, bool re)
> >  	 * report-enable flag is set for NX windows. Ensure software
> >  	 * complies too.
> >  	 */
> > -	WARN_ON_ONCE(txwin->nx_win && !re);
> > +	WARN_ON_ONCE(txwin->pnv.nx_win && !re);
> >  
> > -	addr = txwin->paste_kaddr;
> > +	addr = txwin->pnv.paste_kaddr;
> >  	if (re) {
> >  		/*
> >  		 * Set the REPORT_ENABLE bit (equivalent to writing
> > @@ -1153,7 +1162,7 @@ static void poll_window_credits(struct
> > vas_window *window)
> >  	int count = 0;
> >  
> >  	val = read_hvwc_reg(window, VREG(WINCTL));
> > -	if (window->tx_win)
> > +	if (window->pnv.tx_win)
> >  		mode = GET_FIELD(VAS_WINCTL_TX_WCRED_MODE, val);
> >  	else
> >  		mode = GET_FIELD(VAS_WINCTL_RX_WCRED_MODE, val);
> > @@ -1161,7 +1170,7 @@ static void poll_window_credits(struct
> > vas_window *window)
> >  	if (!mode)
> >  		return;
> >  retry:
> > -	if (window->tx_win) {
> > +	if (window->pnv.tx_win) {
> >  		val = read_hvwc_reg(window, VREG(TX_WCRED));
> >  		creds = GET_FIELD(VAS_TX_WCRED, val);
> >  	} else {
> > @@ -1277,7 +1286,7 @@ int vas_win_close(struct vas_window *window)
> >  	if (!window)
> >  		return 0;
> >  
> > -	if (!window->tx_win && atomic_read(&window->num_txwins) != 0) {
> > +	if (!window->pnv.tx_win && atomic_read(&window->pnv.num_txwins) 
> > != 0) {
> >  		pr_devel("Attempting to close an active Rx window!\n");
> >  		WARN_ON_ONCE(1);
> >  		return -EBUSY;
> > @@ -1296,11 +1305,11 @@ int vas_win_close(struct vas_window
> > *window)
> >  	poll_window_castout(window);
> >  
> >  	/* if send window, drop reference to matching receive window */
> > -	if (window->tx_win) {
> > -		if (window->user_win)
> > +	if (window->pnv.tx_win) {
> > +		if (window->pnv.user_win)
> >  			vas_drop_reference_pid_mm(&window->task_ref);
> >  
> > -		put_rx_win(window->rxwin);
> > +		put_rx_win(window->pnv.rxwin);
> >  	}
> >  
> >  	vas_window_free(window);
> > @@ -1384,12 +1393,12 @@ struct vas_window
> > *vas_pswid_to_window(struct vas_instance *vinst,
> >  	 * since their CRBs are ignored (not queued on FIFO or
> > processed
> >  	 * by NX).
> >  	 */
> > -	if (!window->tx_win || !window->user_win || !window->nx_win ||
> > -			window->cop == VAS_COP_TYPE_FAULT ||
> > -			window->cop == VAS_COP_TYPE_FTW) {
> > +	if (!window->pnv.tx_win || !window->pnv.user_win ||
> > +		!window->pnv.nx_win || window->cop ==
> > VAS_COP_TYPE_FAULT ||
> > +		window->cop == VAS_COP_TYPE_FTW) {
> >  		pr_err("PSWID decode: id %d, tx %d, user %d, nx %d, cop
> > %d\n",
> > -			winid, window->tx_win, window->user_win,
> > -			window->nx_win, window->cop);
> > +			winid, window->pnv.tx_win, window-
> > >pnv.user_win,
> > +			window->pnv.nx_win, window->cop);
> >  		WARN_ON(1);
> >  	}
> >  
> > diff --git a/arch/powerpc/platforms/powernv/vas.h
> > b/arch/powerpc/platforms/powernv/vas.h
> > index f354dd5c51bd..f2d9daff3d82 100644
> > --- a/arch/powerpc/platforms/powernv/vas.h
> > +++ b/arch/powerpc/platforms/powernv/vas.h
> > @@ -345,34 +345,6 @@ struct vas_instance {
> >  	struct dentry *dbgdir;
> >  };
> >  
> > -/*
> > - * In-kernel state a VAS window. One per window.
> > - */
> > -struct vas_window {
> > -	/* Fields common to send and receive windows */
> > -	struct vas_instance *vinst;
> > -	int winid;
> > -	bool tx_win;		/* True if send window */
> > -	bool nx_win;		/* True if NX window */
> > -	bool user_win;		/* True if user space window */
> > -	void *hvwc_map;		/* HV window context */
> > -	void *uwc_map;		/* OS/User window context */
> > -	int wcreds_max;		/* Window credits */
> > -
> > -	struct vas_user_win_ref task_ref;
> > -	char *dbgname;
> > -	struct dentry *dbgdir;
> > -
> > -	/* Fields applicable only to send windows */
> > -	void *paste_kaddr;
> > -	char *paste_addr_name;
> > -	struct vas_window *rxwin;
> > -
> > -	/* Feilds applicable only to receive windows */
> > -	enum vas_cop_type cop;
> > -	atomic_t num_txwins;
> > -};
> > -
> >  /*
> >   * Container for the hardware state of a window. One per-window.
> >   *
> > @@ -449,8 +421,8 @@ static inline void vas_log_write(struct
> > vas_window *win, char *name,
> >  {
> >  	if (val)
> >  		pr_debug("%swin #%d: %s reg %p, val 0x%016llx\n",
> > -				win->tx_win ? "Tx" : "Rx", win->winid,
> > name,
> > -				regptr, val);
> > +				win->pnv.tx_win ? "Tx" : "Rx", win-
> > >winid,
> > +				name, regptr, val);
> >  }
> >  
> >  static inline void write_uwc_reg(struct vas_window *win, char
> > *name,
> > @@ -458,7 +430,7 @@ static inline void write_uwc_reg(struct
> > vas_window *win, char *name,
> >  {
> >  	void *regptr;
> >  
> > -	regptr = win->uwc_map + reg;
> > +	regptr = win->pnv.uwc_map + reg;
> >  	vas_log_write(win, name, regptr, val);
> >  
> >  	out_be64(regptr, val);
> > @@ -469,7 +441,7 @@ static inline void write_hvwc_reg(struct
> > vas_window *win, char *name,
> >  {
> >  	void *regptr;
> >  
> > -	regptr = win->hvwc_map + reg;
> > +	regptr = win->pnv.hvwc_map + reg;
> >  	vas_log_write(win, name, regptr, val);
> >  
> >  	out_be64(regptr, val);
> > @@ -478,7 +450,7 @@ static inline void write_hvwc_reg(struct
> > vas_window *win, char *name,
> >  static inline u64 read_hvwc_reg(struct vas_window *win,
> >  			char *name __maybe_unused, s32 reg)
> >  {
> > -	return in_be64(win->hvwc_map+reg);
> > +	return in_be64(win->pnv.hvwc_map + reg);
> >  }
> >  
> >  /*
> > -- 
> > 2.18.2
> > 
> > 
> > 


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
  2021-06-04  4:35       ` Haren Myneni
@ 2021-06-04 11:52         ` Michael Ellerman
  -1 siblings, 0 replies; 86+ messages in thread
From: Michael Ellerman @ 2021-06-04 11:52 UTC (permalink / raw)
  To: Haren Myneni, Nicholas Piggin, herbert, linux-crypto, linuxppc-dev
  Cc: haren, hbabu

Haren Myneni <haren@linux.ibm.com> writes:
> On Thu, 2021-06-03 at 14:38 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:33 pm:
>> > Same vas_window struct is used on powerNV and pseries. So this
>> > patch
>> > changes in struct vas_window to support both platforms and also the
>> > corresponding modifications in powerNV vas code.
>> > 
>> > On powerNV, vas_window is used for both TX and RX windows, whereas
>> > only for TX windows on powerVM. So some elements are specific to
>> > these platforms.
>> > 
>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>> > ---
>> >  arch/powerpc/include/asm/vas.h              |  50 +++++++-
>> >  arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
>> >  arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
>> >  arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
>> >  arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++-----
>> > ----
>> >  arch/powerpc/platforms/powernv/vas.h        |  38 +-----
>> >  6 files changed, 135 insertions(+), 104 deletions(-)
>> > 
>> > diff --git a/arch/powerpc/include/asm/vas.h
>> > b/arch/powerpc/include/asm/vas.h
>> > index 2c1040f399d9..49bfb5be896d 100644
>> > --- a/arch/powerpc/include/asm/vas.h
>> > +++ b/arch/powerpc/include/asm/vas.h
>> > @@ -10,8 +10,6 @@
>> >  #include <asm/icswx.h>
>> >  #include <uapi/asm/vas-api.h>
>> >  
>> > -struct vas_window;
>> > -
>> >  /*
>> >   * Min and max FIFO sizes are based on Version 1.05 Section
>> > 3.1.4.25
>> >   * (Local FIFO Size Register) of the VAS workbook.
>> > @@ -63,6 +61,54 @@ struct vas_user_win_ref {
>> >  	struct mm_struct *mm;	/* Linux process mm_struct */
>> >  };
>> >  
>> > +/*
>> > + * In-kernel state a VAS window. One per window.
>> > + * powerVM: Used only for Tx windows.
>> > + * powerNV: Used for both Tx and Rx windows.
>> > + */
>> > +struct vas_window {
>> > +	u32 winid;
>> > +	u32 wcreds_max;	/* Window credits */
>> > +	enum vas_cop_type cop;
>> > +	struct vas_user_win_ref task_ref;
>> > +	char *dbgname;
>> > +	struct dentry *dbgdir;
>> > +	union {
>> > +		/* powerNV specific data */
>> > +		struct {
>> > +			void *vinst;	/* points to VAS instance
>> > */
>> > +			bool tx_win;	/* True if send window */
>> > +			bool nx_win;	/* True if NX window */
>> > +			bool user_win;	/* True if user space
>> > window */
>> > +			void *hvwc_map;	/* HV window context */
>> > +			void *uwc_map;	/* OS/User window context
>> > */
>> > +
>> > +			/* Fields applicable only to send windows */
>> > +			void *paste_kaddr;
>> > +			char *paste_addr_name;
>> > +			struct vas_window *rxwin;
>> > +
>> > +			atomic_t num_txwins;	/* Only for receive
>> > windows */
>> > +		} pnv;
>> > +		struct {
>> > +			u64 win_addr;	/* Physical paste address
>> > */
>> > +			u8 win_type;	/* QoS or Default window */
>> > +			u8 status;
>> > +			u32 complete_irq;	/* Completion interrupt */
>> > +			u32 fault_irq;	/* Fault interrupt */
>> > +			u64 domain[6];	/* Associativity domain Ids
>> > */
>> > +					/* this window is allocated */
>> > +			u64 util;
>> > +
>> > +			/* List of windows opened which is used for LPM
>> > */
>> > +			struct list_head win_list;
>> > +			u64 flags;
>> > +			char *name;
>> > +			int fault_virq;
>> > +		} lpar;
>> > +	};
>> > +};
>> 
>> The more typical way to do code like this is have the common bit as
>> its own struct, and then have the users embed it into their own structs.
>> 
>> 
>> struct vas_window {
>> 	u32 winid;
>> 	u32 wcreds_max;	/* Window credits */
>> 	enum vas_cop_type cop;
>> 	struct vas_user_win_ref task_ref;
>> 	char *dbgname;
>> 	struct dentry *dbgdir;
>> };
>> 
>> struct pnv_vas_window {
>> 	struct vas_window vas_window;
>> 
>> 	void *vinst;	/* points to VAS instance */
>> 	bool tx_win;	/* True if send window */
>> 	bool nx_win;	/* True if NX window */
>> 	bool user_win;	/* True if user space window */
>> 	void *hvwc_map;	/* HV window context */
>> 	void *uwc_map;	/* OS/User window context */
>> 
>> 	/* Fields applicable only to send windows */
>> 	void *paste_kaddr;
>> 	char *paste_addr_name;
>> 	struct vas_window *rxwin;
>> 
>> 	atomic_t num_txwins;	/* Only for receive windows */
>> };
>> 
>> Which helps reusability / avoids churn (don't have to update the
>> same 
>> structure to add new functionality), slightly helps naming and union 
>> size mismatches, helps with type checking, etc.
>> 
>> Maybe not a great benefit for your code as is which may not grow more
>> users, but unless there are some good reasons for the unions I would 
>> really consider changing to this style.
>
> Defined platform specific data as union for the following reasons:
> - vas_window address is saved for each file descriptor
> (fp-private_data). If we define separate structs for PowerNV and
> PowerVM, 'struct vas_window' has to be the first element which can add
> confusion.

I don't follow.

I think what you're saying is you want to return a struct vas_window *
to the drive code, ie. you don't want the driver code to know if it's a
pnv window or a pseries one.

ie. you get a vas_window in open and stash it in fp->private_data:

static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
{
	...
	struct coproc_instance *cp_inst;
	struct vas_window *txwin;
	int rc;

	cp_inst = fp->private_data;

	...
	txwin = cp_inst->coproc->vops->open_win(&uattr, cp_inst->coproc->cop_type);
	...
	cp_inst->txwin = txwin;

	return 0;
}

And then you want to pass it back to the backend (powernv/pseries) code
in eg. mmap:

static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
{
	struct coproc_instance *cp_inst = fp->private_data;
	struct vas_window *txwin;
        ...

	txwin = cp_inst->txwin;

	...
	paste_addr = cp_inst->coproc->vops->paste_addr(txwin);


But that can work perfectly fine with Nick's suggestion. You just pass
the vas_window * in and out and the backend code is responsible for
using container_of() to get access to its backend-specific struct.

eg. for powernv it would be something like:

static u64 vas_user_win_paste_addr(struct vas_window *win)
{
	struct pnv_vas_window *pnv_win;
	u64 paste_addr;

	pnv_win = container_of(win, struct pnv_vas_window, vas_window);

	vas_win_paste_addr(pnv_win, &paste_addr, NULL);

	return paste_addr;
}


Another advantage which I don't think Nick mentioned is that you can
have the powernv specific parts private to the powernv code, and
similarly for pseries.

cheers

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
@ 2021-06-04 11:52         ` Michael Ellerman
  0 siblings, 0 replies; 86+ messages in thread
From: Michael Ellerman @ 2021-06-04 11:52 UTC (permalink / raw)
  To: Haren Myneni, Nicholas Piggin, herbert, linux-crypto, linuxppc-dev

Haren Myneni <haren@linux.ibm.com> writes:
> On Thu, 2021-06-03 at 14:38 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:33 pm:
>> > Same vas_window struct is used on powerNV and pseries. So this
>> > patch
>> > changes in struct vas_window to support both platforms and also the
>> > corresponding modifications in powerNV vas code.
>> > 
>> > On powerNV, vas_window is used for both TX and RX windows, whereas
>> > only for TX windows on powerVM. So some elements are specific to
>> > these platforms.
>> > 
>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>> > ---
>> >  arch/powerpc/include/asm/vas.h              |  50 +++++++-
>> >  arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
>> >  arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
>> >  arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
>> >  arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++-----
>> > ----
>> >  arch/powerpc/platforms/powernv/vas.h        |  38 +-----
>> >  6 files changed, 135 insertions(+), 104 deletions(-)
>> > 
>> > diff --git a/arch/powerpc/include/asm/vas.h
>> > b/arch/powerpc/include/asm/vas.h
>> > index 2c1040f399d9..49bfb5be896d 100644
>> > --- a/arch/powerpc/include/asm/vas.h
>> > +++ b/arch/powerpc/include/asm/vas.h
>> > @@ -10,8 +10,6 @@
>> >  #include <asm/icswx.h>
>> >  #include <uapi/asm/vas-api.h>
>> >  
>> > -struct vas_window;
>> > -
>> >  /*
>> >   * Min and max FIFO sizes are based on Version 1.05 Section
>> > 3.1.4.25
>> >   * (Local FIFO Size Register) of the VAS workbook.
>> > @@ -63,6 +61,54 @@ struct vas_user_win_ref {
>> >  	struct mm_struct *mm;	/* Linux process mm_struct */
>> >  };
>> >  
>> > +/*
>> > + * In-kernel state a VAS window. One per window.
>> > + * powerVM: Used only for Tx windows.
>> > + * powerNV: Used for both Tx and Rx windows.
>> > + */
>> > +struct vas_window {
>> > +	u32 winid;
>> > +	u32 wcreds_max;	/* Window credits */
>> > +	enum vas_cop_type cop;
>> > +	struct vas_user_win_ref task_ref;
>> > +	char *dbgname;
>> > +	struct dentry *dbgdir;
>> > +	union {
>> > +		/* powerNV specific data */
>> > +		struct {
>> > +			void *vinst;	/* points to VAS instance
>> > */
>> > +			bool tx_win;	/* True if send window */
>> > +			bool nx_win;	/* True if NX window */
>> > +			bool user_win;	/* True if user space
>> > window */
>> > +			void *hvwc_map;	/* HV window context */
>> > +			void *uwc_map;	/* OS/User window context
>> > */
>> > +
>> > +			/* Fields applicable only to send windows */
>> > +			void *paste_kaddr;
>> > +			char *paste_addr_name;
>> > +			struct vas_window *rxwin;
>> > +
>> > +			atomic_t num_txwins;	/* Only for receive
>> > windows */
>> > +		} pnv;
>> > +		struct {
>> > +			u64 win_addr;	/* Physical paste address
>> > */
>> > +			u8 win_type;	/* QoS or Default window */
>> > +			u8 status;
>> > +			u32 complete_irq;	/* Completion interrupt */
>> > +			u32 fault_irq;	/* Fault interrupt */
>> > +			u64 domain[6];	/* Associativity domain Ids
>> > */
>> > +					/* this window is allocated */
>> > +			u64 util;
>> > +
>> > +			/* List of windows opened which is used for LPM
>> > */
>> > +			struct list_head win_list;
>> > +			u64 flags;
>> > +			char *name;
>> > +			int fault_virq;
>> > +		} lpar;
>> > +	};
>> > +};
>> 
>> The more typical way to do code like this is have the common bit as
>> its own struct, and then have the users embed it into their own structs.
>> 
>> 
>> struct vas_window {
>> 	u32 winid;
>> 	u32 wcreds_max;	/* Window credits */
>> 	enum vas_cop_type cop;
>> 	struct vas_user_win_ref task_ref;
>> 	char *dbgname;
>> 	struct dentry *dbgdir;
>> };
>> 
>> struct pnv_vas_window {
>> 	struct vas_window vas_window;
>> 
>> 	void *vinst;	/* points to VAS instance */
>> 	bool tx_win;	/* True if send window */
>> 	bool nx_win;	/* True if NX window */
>> 	bool user_win;	/* True if user space window */
>> 	void *hvwc_map;	/* HV window context */
>> 	void *uwc_map;	/* OS/User window context */
>> 
>> 	/* Fields applicable only to send windows */
>> 	void *paste_kaddr;
>> 	char *paste_addr_name;
>> 	struct vas_window *rxwin;
>> 
>> 	atomic_t num_txwins;	/* Only for receive windows */
>> };
>> 
>> Which helps reusability / avoids churn (don't have to update the
>> same 
>> structure to add new functionality), slightly helps naming and union 
>> size mismatches, helps with type checking, etc.
>> 
>> Maybe not a great benefit for your code as is which may not grow more
>> users, but unless there are some good reasons for the unions I would 
>> really consider changing to this style.
>
> Defined platform specific data as union for the following reasons:
> - vas_window address is saved for each file descriptor
> (fp-private_data). If we define separate structs for PowerNV and
> PowerVM, 'struct vas_window' has to be the first element which can add
> confusion.

I don't follow.

I think what you're saying is you want to return a struct vas_window *
to the drive code, ie. you don't want the driver code to know if it's a
pnv window or a pseries one.

ie. you get a vas_window in open and stash it in fp->private_data:

static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
{
	...
	struct coproc_instance *cp_inst;
	struct vas_window *txwin;
	int rc;

	cp_inst = fp->private_data;

	...
	txwin = cp_inst->coproc->vops->open_win(&uattr, cp_inst->coproc->cop_type);
	...
	cp_inst->txwin = txwin;

	return 0;
}

And then you want to pass it back to the backend (powernv/pseries) code
in eg. mmap:

static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
{
	struct coproc_instance *cp_inst = fp->private_data;
	struct vas_window *txwin;
        ...

	txwin = cp_inst->txwin;

	...
	paste_addr = cp_inst->coproc->vops->paste_addr(txwin);


But that can work perfectly fine with Nick's suggestion. You just pass
the vas_window * in and out and the backend code is responsible for
using container_of() to get access to its backend-specific struct.

eg. for powernv it would be something like:

static u64 vas_user_win_paste_addr(struct vas_window *win)
{
	struct pnv_vas_window *pnv_win;
	u64 paste_addr;

	pnv_win = container_of(win, struct pnv_vas_window, vas_window);

	vas_win_paste_addr(pnv_win, &paste_addr, NULL);

	return paste_addr;
}


Another advantage which I don't think Nick mentioned is that you can
have the powernv specific parts private to the powernv code, and
similarly for pseries.

cheers

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
  2021-06-04  1:02       ` Haren Myneni
@ 2021-06-04 11:52         ` Michael Ellerman
  -1 siblings, 0 replies; 86+ messages in thread
From: Michael Ellerman @ 2021-06-04 11:52 UTC (permalink / raw)
  To: Haren Myneni, Nicholas Piggin, herbert, linux-crypto, linuxppc-dev
  Cc: haren, hbabu

Haren Myneni <haren@linux.ibm.com> writes:
> On Thu, 2021-06-03 at 14:57 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:42 pm:
>> > Changes to export the following NXGZIP capabilities through sysfs:
>> > 
>> > /sys/devices/vio/ibm,compression-v1/NxGzCaps:
>> 
>> Where's the horrible camel case name coming from? PowerVM?
>
> Yes, pHyp provides the capabalities string.
>
> Capability Description Descriptor Value Descriptor ascii Value
> Overall NX Capabilities 0x4E78204361707320 “Nx Caps ”
> NX GZIP Capabilities 0x4E78477A43617073 “NxGzCaps”

That doesn't mean we have to use that name in sysfs though. In fact we
couldn't use the "Nx Caps " name, because it contains spaces.

And we don't have to squeeze our name into 8 bytes, so it can be less
ugly.

Like "nx_gzip_capabilities"?

cheers

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
@ 2021-06-04 11:52         ` Michael Ellerman
  0 siblings, 0 replies; 86+ messages in thread
From: Michael Ellerman @ 2021-06-04 11:52 UTC (permalink / raw)
  To: Haren Myneni, Nicholas Piggin, herbert, linux-crypto, linuxppc-dev

Haren Myneni <haren@linux.ibm.com> writes:
> On Thu, 2021-06-03 at 14:57 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:42 pm:
>> > Changes to export the following NXGZIP capabilities through sysfs:
>> > 
>> > /sys/devices/vio/ibm,compression-v1/NxGzCaps:
>> 
>> Where's the horrible camel case name coming from? PowerVM?
>
> Yes, pHyp provides the capabalities string.
>
> Capability Description Descriptor Value Descriptor ascii Value
> Overall NX Capabilities 0x4E78204361707320 “Nx Caps ”
> NX GZIP Capabilities 0x4E78477A43617073 “NxGzCaps”

That doesn't mean we have to use that name in sysfs though. In fact we
couldn't use the "Nx Caps " name, because it contains spaces.

And we don't have to squeeze our name into 8 bytes, so it can be less
ugly.

Like "nx_gzip_capabilities"?

cheers

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 09/16] powerpc/pseries/vas: Add HCALL wrappers for VAS handling
  2021-05-21  9:35   ` Haren Myneni
@ 2021-06-04 11:52     ` Michael Ellerman
  -1 siblings, 0 replies; 86+ messages in thread
From: Michael Ellerman @ 2021-06-04 11:52 UTC (permalink / raw)
  To: Haren Myneni, linuxppc-dev, linux-crypto, herbert, npiggin; +Cc: hbabu, haren

Haren Myneni <haren@linux.ibm.com> writes:
> This patch adds the following HCALL wrapper functions to allocate,

Normal spelling is "hcall".

> modify and deallocate VAS windows, and retrieve VAS capabilities.
>
> H_ALLOCATE_VAS_WINDOW: Allocate VAS window
> H_DEALLOCATE_VAS_WINDOW: Close VAS window
> H_MODIFY_VAS_WINDOW: Setup window before using
> H_QUERY_VAS_CAPABILITIES: Get VAS capabilities

Please tell us which version of PAPR, and in which section etc., these
are described in.

> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
> ---
>  arch/powerpc/platforms/pseries/vas.c | 217 +++++++++++++++++++++++++++
>  1 file changed, 217 insertions(+)
>  create mode 100644 arch/powerpc/platforms/pseries/vas.c
>
> diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
> new file mode 100644
> index 000000000000..06960151477c
> --- /dev/null
> +++ b/arch/powerpc/platforms/pseries/vas.c
> @@ -0,0 +1,217 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright 2020-21 IBM Corp.
> + */
> +
> +#define pr_fmt(fmt) "vas: " fmt
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/export.h>
> +#include <linux/types.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/irqdomain.h>
> +#include <linux/interrupt.h>
> +#include <linux/sched/mm.h>
> +#include <linux/mmu_context.h>
> +#include <asm/hvcall.h>
> +#include <asm/hvconsole.h>
> +#include <asm/machdep.h>

Do we need all those headers?

> +#include <asm/plpar_wrappers.h>
> +#include <asm/vas.h>
> +#include "vas.h"
> +
> +#define	VAS_INVALID_WIN_ADDRESS	0xFFFFFFFFFFFFFFFFul
> +#define	VAS_DEFAULT_DOMAIN_ID	0xFFFFFFFFFFFFFFFFul

Some blank lines for formatting please.

> +/* Authority Mask Register (AMR) value is not supported in */
> +/* linux implementation. So pass '0' to modify window HCALL */

Please fix the comment formatting.

> +#define	VAS_AMR_VALUE	0

This is only used in one place. It'd be simpler to just pass 0 and move
the comment there.

> +/* phyp allows one credit per window right now */
> +#define DEF_WIN_CREDS		1
> +
> +static int64_t hcall_return_busy_check(int64_t rc)
> +{

Please use normal kernel types, ie. s64, or just long.

Same comment throughout.

> +	/* Check if we are stalled for some time */
> +	if (H_IS_LONG_BUSY(rc)) {
> +		msleep(get_longbusy_msecs(rc));
> +		rc = H_BUSY;
> +	} else if (rc == H_BUSY) {
> +		cond_resched();
> +	}
> +
> +	return rc;
> +}
> +
> +/*
> + * Allocate VAS window HCALL
> + */
> +static int plpar_vas_allocate_window(struct vas_window *win, u64 *domain,
> +				     u8 wintype, u16 credits)

You don't have to use the "plpar" prefix for these sort of wrappers.

Just naming them after the hcall would probably be clearer, so:

 h_allocate_vas_window(... )

> +{
> +	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
> +	int64_t rc;
> +
> +	do {
> +		rc = plpar_hcall9(H_ALLOCATE_VAS_WINDOW, retbuf, wintype,
> +				  credits, domain[0], domain[1], domain[2],
> +				  domain[3], domain[4], domain[5]);
> +
> +		rc = hcall_return_busy_check(rc);
> +	} while (rc == H_BUSY);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		win->winid = retbuf[0];
> +		win->lpar.win_addr = retbuf[1];
> +		win->lpar.complete_irq = retbuf[2];
> +		win->lpar.fault_irq = retbuf[3];

You shouldn't mutate win until you know there is no error.

> +		if (win->lpar.win_addr == VAS_INVALID_WIN_ADDRESS) {
> +			pr_err("HCALL(%x): COPY/PASTE is not supported\n",
> +				H_ALLOCATE_VAS_WINDOW);
> +			return -ENOTSUPP;
> +		}
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%x): Invalid window type (%u)\n",
> +			H_ALLOCATE_VAS_WINDOW, wintype);
> +		return -EINVAL;
> +	case H_P2:
> +		pr_err("HCALL(%x): Credits(%u) exceed maximum window credits\n",
> +			H_ALLOCATE_VAS_WINDOW, credits);
> +		return -EINVAL;
> +	case H_COP_HW:
> +		pr_err("HCALL(%x): User-mode COPY/PASTE is not supported\n",
> +			H_ALLOCATE_VAS_WINDOW);
> +		return -ENOTSUPP;
> +	case H_RESOURCE:
> +		pr_err("HCALL(%x): LPAR credit limit exceeds window limit\n",
> +			H_ALLOCATE_VAS_WINDOW);
> +		return -EPERM;
> +	case H_CONSTRAINED:
> +		pr_err("HCALL(%x): Credits (%u) are not available\n",
> +			H_ALLOCATE_VAS_WINDOW, credits);
> +		return -EPERM;
> +	default:
> +		pr_err("HCALL(%x): Unexpected error %lld\n",
> +			H_ALLOCATE_VAS_WINDOW, rc);
> +		return -EIO;
> +	}

Do we really need all these error prints? It's very verbose, and
presumably in normal operation none of these are meant to happen anyway.

Can't we just have a single case that prints the error value?

Same comment for the other hcalls.

> +}
> +
> +/*
> + * Deallocate VAS window HCALL.
> + */
> +static int plpar_vas_deallocate_window(u64 winid)
> +{
> +	int64_t rc;
> +
> +	do {
> +		rc = plpar_hcall_norets(H_DEALLOCATE_VAS_WINDOW, winid);
> +
> +		rc = hcall_return_busy_check(rc);
> +	} while (rc == H_BUSY);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%x): Invalid window ID %llu\n",
> +			H_DEALLOCATE_VAS_WINDOW, winid);
> +		return -EINVAL;
> +	case H_STATE:
> +		pr_err("HCALL(%x): Window(%llu): Invalid page table entries\n",
> +			H_DEALLOCATE_VAS_WINDOW, winid);
> +		return -EPERM;
> +	default:
> +		pr_err("HCALL(%x): Unexpected error %lld for window(%llu)\n",
> +			H_DEALLOCATE_VAS_WINDOW, rc, winid);
> +		return -EIO;
> +	}
> +}
> +
> +/*
> + * Modify VAS window.
> + * After the window is opened with allocate window HCALL, configure it
> + * with flags and LPAR PID before using.
> + */
> +static int plpar_vas_modify_window(struct vas_window *win)
> +{
> +	int64_t rc;
> +	u32 lpid = mfspr(SPRN_PID);

The lpid would be SPRN_LPID ?
But you can't read it from a guest. Is the variable just misnamed?

> +
> +	/*
> +	 * AMR value is not supported in Linux implementation
> +	 * phyp ignores it if 0 is passed.
> +	 */

Heh, this comment is already here.

Do you mean the Linux VAS implementation doesn't support AMR? Because
Linux definitely does use AMR.

> +	do {
> +		rc = plpar_hcall_norets(H_MODIFY_VAS_WINDOW, win->winid,
> +					lpid, 0, VAS_MOD_WIN_FLAGS,
> +					VAS_AMR_VALUE);
> +
> +		rc = hcall_return_busy_check(rc);
> +	} while (rc == H_BUSY);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%x): Invalid window ID %u\n",
> +			H_MODIFY_VAS_WINDOW, win->winid);
> +		return -EINVAL;
> +	case H_P2:
> +		pr_err("HCALL(%x): Window(%d): Invalid LPAR Process ID %u\n",
> +			H_MODIFY_VAS_WINDOW, lpid, win->winid);
> +		return -EINVAL;
> +	case H_P3:
> +		/* LPAR thread ID is deprecated on P10 */
> +		pr_err("HCALL(%x): Invalid LPAR Thread ID for window(%u)\n",
> +			H_MODIFY_VAS_WINDOW, win->winid);
> +		return -EINVAL;
> +	case H_STATE:
> +		pr_err("HCALL(%x): Jobs in progress, Can't modify window(%u)\n",
> +			H_MODIFY_VAS_WINDOW, win->winid);
> +		return -EBUSY;
> +	default:
> +		pr_err("HCALL(%x): Unexpected error %lld for window(%u)\n",
> +			H_MODIFY_VAS_WINDOW, rc, win->winid);
> +		return -EIO;
> +	}
> +}
> +
> +/*
> + * This HCALL is used to determine the capabilities that pHyp provides.
> + * @hcall: H_QUERY_VAS_CAPABILITIES or H_QUERY_NX_CAPABILITIES
> + * @query_type: If 0 is passed, phyp returns the overall capabilities
> + *		which provides all feature(s) that are available. Then
> + *		query phyp to get the corresponding capabilities for
> + *		the specific feature.
> + *		Example: H_QUERY_VAS_CAPABILITIES provides VAS GZIP QoS
> + *			and VAS GZIP Default capabilities.
> + *			H_QUERY_NX_CAPABILITIES provides NX GZIP
> + *			capabilities.
> + * @result: Return buffer to save capabilities.
> + */
> +int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
> +					u64 result)
> +{
> +	int64_t rc;
> +
> +	rc = plpar_hcall_norets(hcall, query_type, result);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%llx): Invalid query type %u\n", hcall,
> +			query_type);
> +		return -EINVAL;
> +	case H_PRIVILEGE:
> +		pr_err("HCALL(%llx): Invalid result buffer 0x%llx\n",
> +			hcall, result);
> +		return -EACCES;
> +	default:
> +		pr_err("HCALL(%llx): Unexpected error %lld\n", hcall, rc);
> +		return -EIO;
> +	}
> +}


cheers

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 09/16] powerpc/pseries/vas: Add HCALL wrappers for VAS handling
@ 2021-06-04 11:52     ` Michael Ellerman
  0 siblings, 0 replies; 86+ messages in thread
From: Michael Ellerman @ 2021-06-04 11:52 UTC (permalink / raw)
  To: Haren Myneni, linuxppc-dev, linux-crypto, herbert, npiggin

Haren Myneni <haren@linux.ibm.com> writes:
> This patch adds the following HCALL wrapper functions to allocate,

Normal spelling is "hcall".

> modify and deallocate VAS windows, and retrieve VAS capabilities.
>
> H_ALLOCATE_VAS_WINDOW: Allocate VAS window
> H_DEALLOCATE_VAS_WINDOW: Close VAS window
> H_MODIFY_VAS_WINDOW: Setup window before using
> H_QUERY_VAS_CAPABILITIES: Get VAS capabilities

Please tell us which version of PAPR, and in which section etc., these
are described in.

> Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
> ---
>  arch/powerpc/platforms/pseries/vas.c | 217 +++++++++++++++++++++++++++
>  1 file changed, 217 insertions(+)
>  create mode 100644 arch/powerpc/platforms/pseries/vas.c
>
> diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
> new file mode 100644
> index 000000000000..06960151477c
> --- /dev/null
> +++ b/arch/powerpc/platforms/pseries/vas.c
> @@ -0,0 +1,217 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright 2020-21 IBM Corp.
> + */
> +
> +#define pr_fmt(fmt) "vas: " fmt
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/export.h>
> +#include <linux/types.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/irqdomain.h>
> +#include <linux/interrupt.h>
> +#include <linux/sched/mm.h>
> +#include <linux/mmu_context.h>
> +#include <asm/hvcall.h>
> +#include <asm/hvconsole.h>
> +#include <asm/machdep.h>

Do we need all those headers?

> +#include <asm/plpar_wrappers.h>
> +#include <asm/vas.h>
> +#include "vas.h"
> +
> +#define	VAS_INVALID_WIN_ADDRESS	0xFFFFFFFFFFFFFFFFul
> +#define	VAS_DEFAULT_DOMAIN_ID	0xFFFFFFFFFFFFFFFFul

Some blank lines for formatting please.

> +/* Authority Mask Register (AMR) value is not supported in */
> +/* linux implementation. So pass '0' to modify window HCALL */

Please fix the comment formatting.

> +#define	VAS_AMR_VALUE	0

This is only used in one place. It'd be simpler to just pass 0 and move
the comment there.

> +/* phyp allows one credit per window right now */
> +#define DEF_WIN_CREDS		1
> +
> +static int64_t hcall_return_busy_check(int64_t rc)
> +{

Please use normal kernel types, ie. s64, or just long.

Same comment throughout.

> +	/* Check if we are stalled for some time */
> +	if (H_IS_LONG_BUSY(rc)) {
> +		msleep(get_longbusy_msecs(rc));
> +		rc = H_BUSY;
> +	} else if (rc == H_BUSY) {
> +		cond_resched();
> +	}
> +
> +	return rc;
> +}
> +
> +/*
> + * Allocate VAS window HCALL
> + */
> +static int plpar_vas_allocate_window(struct vas_window *win, u64 *domain,
> +				     u8 wintype, u16 credits)

You don't have to use the "plpar" prefix for these sort of wrappers.

Just naming them after the hcall would probably be clearer, so:

 h_allocate_vas_window(... )

> +{
> +	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
> +	int64_t rc;
> +
> +	do {
> +		rc = plpar_hcall9(H_ALLOCATE_VAS_WINDOW, retbuf, wintype,
> +				  credits, domain[0], domain[1], domain[2],
> +				  domain[3], domain[4], domain[5]);
> +
> +		rc = hcall_return_busy_check(rc);
> +	} while (rc == H_BUSY);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		win->winid = retbuf[0];
> +		win->lpar.win_addr = retbuf[1];
> +		win->lpar.complete_irq = retbuf[2];
> +		win->lpar.fault_irq = retbuf[3];

You shouldn't mutate win until you know there is no error.

> +		if (win->lpar.win_addr == VAS_INVALID_WIN_ADDRESS) {
> +			pr_err("HCALL(%x): COPY/PASTE is not supported\n",
> +				H_ALLOCATE_VAS_WINDOW);
> +			return -ENOTSUPP;
> +		}
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%x): Invalid window type (%u)\n",
> +			H_ALLOCATE_VAS_WINDOW, wintype);
> +		return -EINVAL;
> +	case H_P2:
> +		pr_err("HCALL(%x): Credits(%u) exceed maximum window credits\n",
> +			H_ALLOCATE_VAS_WINDOW, credits);
> +		return -EINVAL;
> +	case H_COP_HW:
> +		pr_err("HCALL(%x): User-mode COPY/PASTE is not supported\n",
> +			H_ALLOCATE_VAS_WINDOW);
> +		return -ENOTSUPP;
> +	case H_RESOURCE:
> +		pr_err("HCALL(%x): LPAR credit limit exceeds window limit\n",
> +			H_ALLOCATE_VAS_WINDOW);
> +		return -EPERM;
> +	case H_CONSTRAINED:
> +		pr_err("HCALL(%x): Credits (%u) are not available\n",
> +			H_ALLOCATE_VAS_WINDOW, credits);
> +		return -EPERM;
> +	default:
> +		pr_err("HCALL(%x): Unexpected error %lld\n",
> +			H_ALLOCATE_VAS_WINDOW, rc);
> +		return -EIO;
> +	}

Do we really need all these error prints? It's very verbose, and
presumably in normal operation none of these are meant to happen anyway.

Can't we just have a single case that prints the error value?

Same comment for the other hcalls.

> +}
> +
> +/*
> + * Deallocate VAS window HCALL.
> + */
> +static int plpar_vas_deallocate_window(u64 winid)
> +{
> +	int64_t rc;
> +
> +	do {
> +		rc = plpar_hcall_norets(H_DEALLOCATE_VAS_WINDOW, winid);
> +
> +		rc = hcall_return_busy_check(rc);
> +	} while (rc == H_BUSY);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%x): Invalid window ID %llu\n",
> +			H_DEALLOCATE_VAS_WINDOW, winid);
> +		return -EINVAL;
> +	case H_STATE:
> +		pr_err("HCALL(%x): Window(%llu): Invalid page table entries\n",
> +			H_DEALLOCATE_VAS_WINDOW, winid);
> +		return -EPERM;
> +	default:
> +		pr_err("HCALL(%x): Unexpected error %lld for window(%llu)\n",
> +			H_DEALLOCATE_VAS_WINDOW, rc, winid);
> +		return -EIO;
> +	}
> +}
> +
> +/*
> + * Modify VAS window.
> + * After the window is opened with allocate window HCALL, configure it
> + * with flags and LPAR PID before using.
> + */
> +static int plpar_vas_modify_window(struct vas_window *win)
> +{
> +	int64_t rc;
> +	u32 lpid = mfspr(SPRN_PID);

The lpid would be SPRN_LPID ?
But you can't read it from a guest. Is the variable just misnamed?

> +
> +	/*
> +	 * AMR value is not supported in Linux implementation
> +	 * phyp ignores it if 0 is passed.
> +	 */

Heh, this comment is already here.

Do you mean the Linux VAS implementation doesn't support AMR? Because
Linux definitely does use AMR.

> +	do {
> +		rc = plpar_hcall_norets(H_MODIFY_VAS_WINDOW, win->winid,
> +					lpid, 0, VAS_MOD_WIN_FLAGS,
> +					VAS_AMR_VALUE);
> +
> +		rc = hcall_return_busy_check(rc);
> +	} while (rc == H_BUSY);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%x): Invalid window ID %u\n",
> +			H_MODIFY_VAS_WINDOW, win->winid);
> +		return -EINVAL;
> +	case H_P2:
> +		pr_err("HCALL(%x): Window(%d): Invalid LPAR Process ID %u\n",
> +			H_MODIFY_VAS_WINDOW, lpid, win->winid);
> +		return -EINVAL;
> +	case H_P3:
> +		/* LPAR thread ID is deprecated on P10 */
> +		pr_err("HCALL(%x): Invalid LPAR Thread ID for window(%u)\n",
> +			H_MODIFY_VAS_WINDOW, win->winid);
> +		return -EINVAL;
> +	case H_STATE:
> +		pr_err("HCALL(%x): Jobs in progress, Can't modify window(%u)\n",
> +			H_MODIFY_VAS_WINDOW, win->winid);
> +		return -EBUSY;
> +	default:
> +		pr_err("HCALL(%x): Unexpected error %lld for window(%u)\n",
> +			H_MODIFY_VAS_WINDOW, rc, win->winid);
> +		return -EIO;
> +	}
> +}
> +
> +/*
> + * This HCALL is used to determine the capabilities that pHyp provides.
> + * @hcall: H_QUERY_VAS_CAPABILITIES or H_QUERY_NX_CAPABILITIES
> + * @query_type: If 0 is passed, phyp returns the overall capabilities
> + *		which provides all feature(s) that are available. Then
> + *		query phyp to get the corresponding capabilities for
> + *		the specific feature.
> + *		Example: H_QUERY_VAS_CAPABILITIES provides VAS GZIP QoS
> + *			and VAS GZIP Default capabilities.
> + *			H_QUERY_NX_CAPABILITIES provides NX GZIP
> + *			capabilities.
> + * @result: Return buffer to save capabilities.
> + */
> +int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
> +					u64 result)
> +{
> +	int64_t rc;
> +
> +	rc = plpar_hcall_norets(hcall, query_type, result);
> +
> +	switch (rc) {
> +	case H_SUCCESS:
> +		return 0;
> +	case H_PARAMETER:
> +		pr_err("HCALL(%llx): Invalid query type %u\n", hcall,
> +			query_type);
> +		return -EINVAL;
> +	case H_PRIVILEGE:
> +		pr_err("HCALL(%llx): Invalid result buffer 0x%llx\n",
> +			hcall, result);
> +		return -EACCES;
> +	default:
> +		pr_err("HCALL(%llx): Unexpected error %lld\n", hcall, rc);
> +		return -EIO;
> +	}
> +}


cheers

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
  2021-06-04 11:52         ` Michael Ellerman
@ 2021-06-04 17:23           ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04 17:23 UTC (permalink / raw)
  To: Michael Ellerman, Nicholas Piggin, herbert, linux-crypto, linuxppc-dev
  Cc: haren, hbabu

On Fri, 2021-06-04 at 21:52 +1000, Michael Ellerman wrote:
> Haren Myneni <haren@linux.ibm.com> writes:
> > On Thu, 2021-06-03 at 14:57 +1000, Nicholas Piggin wrote:
> > > Excerpts from Haren Myneni's message of May 21, 2021 7:42 pm:
> > > > Changes to export the following NXGZIP capabilities through
> > > > sysfs:
> > > > 
> > > > /sys/devices/vio/ibm,compression-v1/NxGzCaps:
> > > 
> > > Where's the horrible camel case name coming from? PowerVM?
> > 
> > Yes, pHyp provides the capabalities string.
> > 
> > Capability Description Descriptor Value Descriptor ascii Value
> > Overall NX Capabilities 0x4E78204361707320 “Nx Caps ”
> > NX GZIP Capabilities 0x4E78477A43617073 “NxGzCaps”
> 
> That doesn't mean we have to use that name in sysfs though. In fact
> we
> couldn't use the "Nx Caps " name, because it contains spaces.
> 
> And we don't have to squeeze our name into 8 bytes, so it can be less
> ugly.
> 
> Like "nx_gzip_capabilities"?

Thanks for your comments. 

'NX Caps " provides the all available features in the hypervisor (only
NX GZIP caps is supported right now) and we export information for the
specific feature via sysfs.

I will change it to "nx_gzip_caps" 

Thanks
Haren

> 
> cheers


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities
@ 2021-06-04 17:23           ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04 17:23 UTC (permalink / raw)
  To: Michael Ellerman, Nicholas Piggin, herbert, linux-crypto, linuxppc-dev

On Fri, 2021-06-04 at 21:52 +1000, Michael Ellerman wrote:
> Haren Myneni <haren@linux.ibm.com> writes:
> > On Thu, 2021-06-03 at 14:57 +1000, Nicholas Piggin wrote:
> > > Excerpts from Haren Myneni's message of May 21, 2021 7:42 pm:
> > > > Changes to export the following NXGZIP capabilities through
> > > > sysfs:
> > > > 
> > > > /sys/devices/vio/ibm,compression-v1/NxGzCaps:
> > > 
> > > Where's the horrible camel case name coming from? PowerVM?
> > 
> > Yes, pHyp provides the capabalities string.
> > 
> > Capability Description Descriptor Value Descriptor ascii Value
> > Overall NX Capabilities 0x4E78204361707320 “Nx Caps ”
> > NX GZIP Capabilities 0x4E78477A43617073 “NxGzCaps”
> 
> That doesn't mean we have to use that name in sysfs though. In fact
> we
> couldn't use the "Nx Caps " name, because it contains spaces.
> 
> And we don't have to squeeze our name into 8 bytes, so it can be less
> ugly.
> 
> Like "nx_gzip_capabilities"?

Thanks for your comments. 

'NX Caps " provides the all available features in the hypervisor (only
NX GZIP caps is supported right now) and we export information for the
specific feature via sysfs.

I will change it to "nx_gzip_caps" 

Thanks
Haren

> 
> cheers


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
  2021-06-04 11:52         ` Michael Ellerman
@ 2021-06-04 21:19           ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04 21:19 UTC (permalink / raw)
  To: Michael Ellerman, Nicholas Piggin, herbert, linux-crypto, linuxppc-dev
  Cc: haren, hbabu

On Fri, 2021-06-04 at 21:52 +1000, Michael Ellerman wrote:
> Haren Myneni <haren@linux.ibm.com> writes:
> > On Thu, 2021-06-03 at 14:38 +1000, Nicholas Piggin wrote:
> > > Excerpts from Haren Myneni's message of May 21, 2021 7:33 pm:
> > > > Same vas_window struct is used on powerNV and pseries. So this
> > > > patch
> > > > changes in struct vas_window to support both platforms and also
> > > > the
> > > > corresponding modifications in powerNV vas code.
> > > > 
> > > > On powerNV, vas_window is used for both TX and RX windows,
> > > > whereas
> > > > only for TX windows on powerVM. So some elements are specific
> > > > to
> > > > these platforms.
> > > > 
> > > > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > > > ---
> > > >  arch/powerpc/include/asm/vas.h              |  50 +++++++-
> > > >  arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
> > > >  arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
> > > >  arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
> > > >  arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++-
> > > > ----
> > > > ----
> > > >  arch/powerpc/platforms/powernv/vas.h        |  38 +-----
> > > >  6 files changed, 135 insertions(+), 104 deletions(-)
> > > > 
> > > > diff --git a/arch/powerpc/include/asm/vas.h
> > > > b/arch/powerpc/include/asm/vas.h
> > > > index 2c1040f399d9..49bfb5be896d 100644
> > > > --- a/arch/powerpc/include/asm/vas.h
> > > > +++ b/arch/powerpc/include/asm/vas.h
> > > > @@ -10,8 +10,6 @@
> > > >  #include <asm/icswx.h>
> > > >  #include <uapi/asm/vas-api.h>
> > > >  
> > > > -struct vas_window;
> > > > -
> > > >  /*
> > > >   * Min and max FIFO sizes are based on Version 1.05 Section
> > > > 3.1.4.25
> > > >   * (Local FIFO Size Register) of the VAS workbook.
> > > > @@ -63,6 +61,54 @@ struct vas_user_win_ref {
> > > >  	struct mm_struct *mm;	/* Linux process mm_struct */
> > > >  };
> > > >  
> > > > +/*
> > > > + * In-kernel state a VAS window. One per window.
> > > > + * powerVM: Used only for Tx windows.
> > > > + * powerNV: Used for both Tx and Rx windows.
> > > > + */
> > > > +struct vas_window {
> > > > +	u32 winid;
> > > > +	u32 wcreds_max;	/* Window credits */
> > > > +	enum vas_cop_type cop;
> > > > +	struct vas_user_win_ref task_ref;
> > > > +	char *dbgname;
> > > > +	struct dentry *dbgdir;
> > > > +	union {
> > > > +		/* powerNV specific data */
> > > > +		struct {
> > > > +			void *vinst;	/* points to VAS
> > > > instance
> > > > */
> > > > +			bool tx_win;	/* True if send window
> > > > */
> > > > +			bool nx_win;	/* True if NX window */
> > > > +			bool user_win;	/* True if user space
> > > > window */
> > > > +			void *hvwc_map;	/* HV window context */
> > > > +			void *uwc_map;	/* OS/User window
> > > > context
> > > > */
> > > > +
> > > > +			/* Fields applicable only to send
> > > > windows */
> > > > +			void *paste_kaddr;
> > > > +			char *paste_addr_name;
> > > > +			struct vas_window *rxwin;
> > > > +
> > > > +			atomic_t num_txwins;	/* Only for
> > > > receive
> > > > windows */
> > > > +		} pnv;
> > > > +		struct {
> > > > +			u64 win_addr;	/* Physical paste
> > > > address
> > > > */
> > > > +			u8 win_type;	/* QoS or Default
> > > > window */
> > > > +			u8 status;
> > > > +			u32 complete_irq;	/* Completion
> > > > interrupt */
> > > > +			u32 fault_irq;	/* Fault interrupt */
> > > > +			u64 domain[6];	/* Associativity domain
> > > > Ids
> > > > */
> > > > +					/* this window is
> > > > allocated */
> > > > +			u64 util;
> > > > +
> > > > +			/* List of windows opened which is used
> > > > for LPM
> > > > */
> > > > +			struct list_head win_list;
> > > > +			u64 flags;
> > > > +			char *name;
> > > > +			int fault_virq;
> > > > +		} lpar;
> > > > +	};
> > > > +};
> > > 
> > > The more typical way to do code like this is have the common bit
> > > as
> > > its own struct, and then have the users embed it into their own
> > > structs.
> > > 
> > > 
> > > struct vas_window {
> > > 	u32 winid;
> > > 	u32 wcreds_max;	/* Window credits */
> > > 	enum vas_cop_type cop;
> > > 	struct vas_user_win_ref task_ref;
> > > 	char *dbgname;
> > > 	struct dentry *dbgdir;
> > > };
> > > 
> > > struct pnv_vas_window {
> > > 	struct vas_window vas_window;
> > > 
> > > 	void *vinst;	/* points to VAS instance */
> > > 	bool tx_win;	/* True if send window */
> > > 	bool nx_win;	/* True if NX window */
> > > 	bool user_win;	/* True if user space window */
> > > 	void *hvwc_map;	/* HV window context */
> > > 	void *uwc_map;	/* OS/User window context */
> > > 
> > > 	/* Fields applicable only to send windows */
> > > 	void *paste_kaddr;
> > > 	char *paste_addr_name;
> > > 	struct vas_window *rxwin;
> > > 
> > > 	atomic_t num_txwins;	/* Only for receive windows */
> > > };
> > > 
> > > Which helps reusability / avoids churn (don't have to update the
> > > same 
> > > structure to add new functionality), slightly helps naming and
> > > union 
> > > size mismatches, helps with type checking, etc.
> > > 
> > > Maybe not a great benefit for your code as is which may not grow
> > > more
> > > users, but unless there are some good reasons for the unions I
> > > would 
> > > really consider changing to this style.
> > 
> > Defined platform specific data as union for the following reasons:
> > - vas_window address is saved for each file descriptor
> > (fp-private_data). If we define separate structs for PowerNV and
> > PowerVM, 'struct vas_window' has to be the first element which can
> > add
> > confusion.
> 
> I don't follow.
> 
> I think what you're saying is you want to return a struct vas_window
> *
> to the drive code, ie. you don't want the driver code to know if it's
> a
> pnv window or a pseries one.
> 
> ie. you get a vas_window in open and stash it in fp->private_data:
> 
> static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
> {
> 	...
> 	struct coproc_instance *cp_inst;
> 	struct vas_window *txwin;
> 	int rc;
> 
> 	cp_inst = fp->private_data;
> 
> 	...
> 	txwin = cp_inst->coproc->vops->open_win(&uattr, cp_inst-
> >coproc->cop_type);
> 	...
> 	cp_inst->txwin = txwin;
> 
> 	return 0;
> }
> 
> And then you want to pass it back to the backend (powernv/pseries)
> code
> in eg. mmap:
> 
> static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
> {
> 	struct coproc_instance *cp_inst = fp->private_data;
> 	struct vas_window *txwin;
>         ...
> 
> 	txwin = cp_inst->txwin;
> 
> 	...
> 	paste_addr = cp_inst->coproc->vops->paste_addr(txwin);
> 
> 
> But that can work perfectly fine with Nick's suggestion. You just
> pass
> the vas_window * in and out and the backend code is responsible for
> using container_of() to get access to its backend-specific struct.
> 
> eg. for powernv it would be something like:
> 
> static u64 vas_user_win_paste_addr(struct vas_window *win)
> {
> 	struct pnv_vas_window *pnv_win;
> 	u64 paste_addr;
> 
> 	pnv_win = container_of(win, struct pnv_vas_window, vas_window);
> 
> 	vas_win_paste_addr(pnv_win, &paste_addr, NULL);
> 
> 	return paste_addr;
> }
> 
> 
> Another advantage which I don't think Nick mentioned is that you can
> have the powernv specific parts private to the powernv code, and
> similarly for pseries.


Intially defined the following struct so that can define platform
specific elements and be exposed to only in platform code. But thought
will be simpler with the union since may not be having lot of windows.

struct vas_window {
    /* common elements */
    void *platform_win;
}

I will make the suggested changes.

Thanks
Haren

> 
> cheers


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 06/16] powerpc/vas:  Define and use common vas_window struct
@ 2021-06-04 21:19           ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04 21:19 UTC (permalink / raw)
  To: Michael Ellerman, Nicholas Piggin, herbert, linux-crypto, linuxppc-dev

On Fri, 2021-06-04 at 21:52 +1000, Michael Ellerman wrote:
> Haren Myneni <haren@linux.ibm.com> writes:
> > On Thu, 2021-06-03 at 14:38 +1000, Nicholas Piggin wrote:
> > > Excerpts from Haren Myneni's message of May 21, 2021 7:33 pm:
> > > > Same vas_window struct is used on powerNV and pseries. So this
> > > > patch
> > > > changes in struct vas_window to support both platforms and also
> > > > the
> > > > corresponding modifications in powerNV vas code.
> > > > 
> > > > On powerNV, vas_window is used for both TX and RX windows,
> > > > whereas
> > > > only for TX windows on powerVM. So some elements are specific
> > > > to
> > > > these platforms.
> > > > 
> > > > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > > > ---
> > > >  arch/powerpc/include/asm/vas.h              |  50 +++++++-
> > > >  arch/powerpc/platforms/powernv/vas-debug.c  |  12 +-
> > > >  arch/powerpc/platforms/powernv/vas-fault.c  |   4 +-
> > > >  arch/powerpc/platforms/powernv/vas-trace.h  |   6 +-
> > > >  arch/powerpc/platforms/powernv/vas-window.c | 129 +++++++++++-
> > > > ----
> > > > ----
> > > >  arch/powerpc/platforms/powernv/vas.h        |  38 +-----
> > > >  6 files changed, 135 insertions(+), 104 deletions(-)
> > > > 
> > > > diff --git a/arch/powerpc/include/asm/vas.h
> > > > b/arch/powerpc/include/asm/vas.h
> > > > index 2c1040f399d9..49bfb5be896d 100644
> > > > --- a/arch/powerpc/include/asm/vas.h
> > > > +++ b/arch/powerpc/include/asm/vas.h
> > > > @@ -10,8 +10,6 @@
> > > >  #include <asm/icswx.h>
> > > >  #include <uapi/asm/vas-api.h>
> > > >  
> > > > -struct vas_window;
> > > > -
> > > >  /*
> > > >   * Min and max FIFO sizes are based on Version 1.05 Section
> > > > 3.1.4.25
> > > >   * (Local FIFO Size Register) of the VAS workbook.
> > > > @@ -63,6 +61,54 @@ struct vas_user_win_ref {
> > > >  	struct mm_struct *mm;	/* Linux process mm_struct */
> > > >  };
> > > >  
> > > > +/*
> > > > + * In-kernel state a VAS window. One per window.
> > > > + * powerVM: Used only for Tx windows.
> > > > + * powerNV: Used for both Tx and Rx windows.
> > > > + */
> > > > +struct vas_window {
> > > > +	u32 winid;
> > > > +	u32 wcreds_max;	/* Window credits */
> > > > +	enum vas_cop_type cop;
> > > > +	struct vas_user_win_ref task_ref;
> > > > +	char *dbgname;
> > > > +	struct dentry *dbgdir;
> > > > +	union {
> > > > +		/* powerNV specific data */
> > > > +		struct {
> > > > +			void *vinst;	/* points to VAS
> > > > instance
> > > > */
> > > > +			bool tx_win;	/* True if send window
> > > > */
> > > > +			bool nx_win;	/* True if NX window */
> > > > +			bool user_win;	/* True if user space
> > > > window */
> > > > +			void *hvwc_map;	/* HV window context */
> > > > +			void *uwc_map;	/* OS/User window
> > > > context
> > > > */
> > > > +
> > > > +			/* Fields applicable only to send
> > > > windows */
> > > > +			void *paste_kaddr;
> > > > +			char *paste_addr_name;
> > > > +			struct vas_window *rxwin;
> > > > +
> > > > +			atomic_t num_txwins;	/* Only for
> > > > receive
> > > > windows */
> > > > +		} pnv;
> > > > +		struct {
> > > > +			u64 win_addr;	/* Physical paste
> > > > address
> > > > */
> > > > +			u8 win_type;	/* QoS or Default
> > > > window */
> > > > +			u8 status;
> > > > +			u32 complete_irq;	/* Completion
> > > > interrupt */
> > > > +			u32 fault_irq;	/* Fault interrupt */
> > > > +			u64 domain[6];	/* Associativity domain
> > > > Ids
> > > > */
> > > > +					/* this window is
> > > > allocated */
> > > > +			u64 util;
> > > > +
> > > > +			/* List of windows opened which is used
> > > > for LPM
> > > > */
> > > > +			struct list_head win_list;
> > > > +			u64 flags;
> > > > +			char *name;
> > > > +			int fault_virq;
> > > > +		} lpar;
> > > > +	};
> > > > +};
> > > 
> > > The more typical way to do code like this is have the common bit
> > > as
> > > its own struct, and then have the users embed it into their own
> > > structs.
> > > 
> > > 
> > > struct vas_window {
> > > 	u32 winid;
> > > 	u32 wcreds_max;	/* Window credits */
> > > 	enum vas_cop_type cop;
> > > 	struct vas_user_win_ref task_ref;
> > > 	char *dbgname;
> > > 	struct dentry *dbgdir;
> > > };
> > > 
> > > struct pnv_vas_window {
> > > 	struct vas_window vas_window;
> > > 
> > > 	void *vinst;	/* points to VAS instance */
> > > 	bool tx_win;	/* True if send window */
> > > 	bool nx_win;	/* True if NX window */
> > > 	bool user_win;	/* True if user space window */
> > > 	void *hvwc_map;	/* HV window context */
> > > 	void *uwc_map;	/* OS/User window context */
> > > 
> > > 	/* Fields applicable only to send windows */
> > > 	void *paste_kaddr;
> > > 	char *paste_addr_name;
> > > 	struct vas_window *rxwin;
> > > 
> > > 	atomic_t num_txwins;	/* Only for receive windows */
> > > };
> > > 
> > > Which helps reusability / avoids churn (don't have to update the
> > > same 
> > > structure to add new functionality), slightly helps naming and
> > > union 
> > > size mismatches, helps with type checking, etc.
> > > 
> > > Maybe not a great benefit for your code as is which may not grow
> > > more
> > > users, but unless there are some good reasons for the unions I
> > > would 
> > > really consider changing to this style.
> > 
> > Defined platform specific data as union for the following reasons:
> > - vas_window address is saved for each file descriptor
> > (fp-private_data). If we define separate structs for PowerNV and
> > PowerVM, 'struct vas_window' has to be the first element which can
> > add
> > confusion.
> 
> I don't follow.
> 
> I think what you're saying is you want to return a struct vas_window
> *
> to the drive code, ie. you don't want the driver code to know if it's
> a
> pnv window or a pseries one.
> 
> ie. you get a vas_window in open and stash it in fp->private_data:
> 
> static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
> {
> 	...
> 	struct coproc_instance *cp_inst;
> 	struct vas_window *txwin;
> 	int rc;
> 
> 	cp_inst = fp->private_data;
> 
> 	...
> 	txwin = cp_inst->coproc->vops->open_win(&uattr, cp_inst-
> >coproc->cop_type);
> 	...
> 	cp_inst->txwin = txwin;
> 
> 	return 0;
> }
> 
> And then you want to pass it back to the backend (powernv/pseries)
> code
> in eg. mmap:
> 
> static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
> {
> 	struct coproc_instance *cp_inst = fp->private_data;
> 	struct vas_window *txwin;
>         ...
> 
> 	txwin = cp_inst->txwin;
> 
> 	...
> 	paste_addr = cp_inst->coproc->vops->paste_addr(txwin);
> 
> 
> But that can work perfectly fine with Nick's suggestion. You just
> pass
> the vas_window * in and out and the backend code is responsible for
> using container_of() to get access to its backend-specific struct.
> 
> eg. for powernv it would be something like:
> 
> static u64 vas_user_win_paste_addr(struct vas_window *win)
> {
> 	struct pnv_vas_window *pnv_win;
> 	u64 paste_addr;
> 
> 	pnv_win = container_of(win, struct pnv_vas_window, vas_window);
> 
> 	vas_win_paste_addr(pnv_win, &paste_addr, NULL);
> 
> 	return paste_addr;
> }
> 
> 
> Another advantage which I don't think Nick mentioned is that you can
> have the powernv specific parts private to the powernv code, and
> similarly for pseries.


Intially defined the following struct so that can define platform
specific elements and be exposed to only in platform code. But thought
will be simpler with the union since may not be having lot of windows.

struct vas_window {
    /* common elements */
    void *platform_win;
}

I will make the suggested changes.

Thanks
Haren

> 
> cheers


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 09/16] powerpc/pseries/vas: Add HCALL wrappers for VAS handling
  2021-06-04 11:52     ` Michael Ellerman
@ 2021-06-04 21:53       ` Haren Myneni
  -1 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04 21:53 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev, linux-crypto, herbert, npiggin
  Cc: hbabu, haren

On Fri, 2021-06-04 at 21:52 +1000, Michael Ellerman wrote:
> Haren Myneni <haren@linux.ibm.com> writes:
> > This patch adds the following HCALL wrapper functions to allocate,
> 
> Normal spelling is "hcall".
> 
> > modify and deallocate VAS windows, and retrieve VAS capabilities.
> > 
> > H_ALLOCATE_VAS_WINDOW: Allocate VAS window
> > H_DEALLOCATE_VAS_WINDOW: Close VAS window
> > H_MODIFY_VAS_WINDOW: Setup window before using
> > H_QUERY_VAS_CAPABILITIES: Get VAS capabilities
> 
> Please tell us which version of PAPR, and in which section etc.,
> these
> are described in.
> 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
> > ---
> >  arch/powerpc/platforms/pseries/vas.c | 217
> > +++++++++++++++++++++++++++
> >  1 file changed, 217 insertions(+)
> >  create mode 100644 arch/powerpc/platforms/pseries/vas.c
> > 
> > diff --git a/arch/powerpc/platforms/pseries/vas.c
> > b/arch/powerpc/platforms/pseries/vas.c
> > new file mode 100644
> > index 000000000000..06960151477c
> > --- /dev/null
> > +++ b/arch/powerpc/platforms/pseries/vas.c
> > @@ -0,0 +1,217 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Copyright 2020-21 IBM Corp.
> > + */
> > +
> > +#define pr_fmt(fmt) "vas: " fmt
> > +
> > +#include <linux/module.h>
> > +#include <linux/kernel.h>
> > +#include <linux/export.h>
> > +#include <linux/types.h>
> > +#include <linux/delay.h>
> > +#include <linux/slab.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/sched/mm.h>
> > +#include <linux/mmu_context.h>
> > +#include <asm/hvcall.h>
> > +#include <asm/hvconsole.h>
> > +#include <asm/machdep.h>
> 
> Do we need all those headers?
> 
> > +#include <asm/plpar_wrappers.h>
> > +#include <asm/vas.h>
> > +#include "vas.h"
> > +
> > +#define	VAS_INVALID_WIN_ADDRESS	0xFFFFFFFFFFFFFFFFul
> > +#define	VAS_DEFAULT_DOMAIN_ID	0xFFFFFFFFFFFFFFFFul
> 
> Some blank lines for formatting please.
> 
> > +/* Authority Mask Register (AMR) value is not supported in */
> > +/* linux implementation. So pass '0' to modify window HCALL */
> 
> Please fix the comment formatting.
> 
> > +#define	VAS_AMR_VALUE	0
> 
> This is only used in one place. It'd be simpler to just pass 0 and
> move
> the comment there.
> 
> > +/* phyp allows one credit per window right now */
> > +#define DEF_WIN_CREDS		1
> > +
> > +static int64_t hcall_return_busy_check(int64_t rc)
> > +{
> 
> Please use normal kernel types, ie. s64, or just long.
> 
> Same comment throughout.
> 
> > +	/* Check if we are stalled for some time */
> > +	if (H_IS_LONG_BUSY(rc)) {
> > +		msleep(get_longbusy_msecs(rc));
> > +		rc = H_BUSY;
> > +	} else if (rc == H_BUSY) {
> > +		cond_resched();
> > +	}
> > +
> > +	return rc;
> > +}
> > +
> > +/*
> > + * Allocate VAS window HCALL
> > + */
> > +static int plpar_vas_allocate_window(struct vas_window *win, u64
> > *domain,
> > +				     u8 wintype, u16 credits)
> 
> You don't have to use the "plpar" prefix for these sort of wrappers.
> 
> Just naming them after the hcall would probably be clearer, so:
> 
>  h_allocate_vas_window(... )
> 
> > +{
> > +	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
> > +	int64_t rc;
> > +
> > +	do {
> > +		rc = plpar_hcall9(H_ALLOCATE_VAS_WINDOW, retbuf,
> > wintype,
> > +				  credits, domain[0], domain[1],
> > domain[2],
> > +				  domain[3], domain[4], domain[5]);
> > +
> > +		rc = hcall_return_busy_check(rc);
> > +	} while (rc == H_BUSY);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		win->winid = retbuf[0];
> > +		win->lpar.win_addr = retbuf[1];
> > +		win->lpar.complete_irq = retbuf[2];
> > +		win->lpar.fault_irq = retbuf[3];
> 
> You shouldn't mutate win until you know there is no error.
> 
> > +		if (win->lpar.win_addr == VAS_INVALID_WIN_ADDRESS) {
> > +			pr_err("HCALL(%x): COPY/PASTE is not
> > supported\n",
> > +				H_ALLOCATE_VAS_WINDOW);
> > +			return -ENOTSUPP;
> > +		}
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%x): Invalid window type (%u)\n",
> > +			H_ALLOCATE_VAS_WINDOW, wintype);
> > +		return -EINVAL;
> > +	case H_P2:
> > +		pr_err("HCALL(%x): Credits(%u) exceed maximum window
> > credits\n",
> > +			H_ALLOCATE_VAS_WINDOW, credits);
> > +		return -EINVAL;
> > +	case H_COP_HW:
> > +		pr_err("HCALL(%x): User-mode COPY/PASTE is not
> > supported\n",
> > +			H_ALLOCATE_VAS_WINDOW);
> > +		return -ENOTSUPP;
> > +	case H_RESOURCE:
> > +		pr_err("HCALL(%x): LPAR credit limit exceeds window
> > limit\n",
> > +			H_ALLOCATE_VAS_WINDOW);
> > +		return -EPERM;
> > +	case H_CONSTRAINED:
> > +		pr_err("HCALL(%x): Credits (%u) are not available\n",
> > +			H_ALLOCATE_VAS_WINDOW, credits);
> > +		return -EPERM;
> > +	default:
> > +		pr_err("HCALL(%x): Unexpected error %lld\n",
> > +			H_ALLOCATE_VAS_WINDOW, rc);
> > +		return -EIO;
> > +	}
> 
> Do we really need all these error prints? It's very verbose, and
> presumably in normal operation none of these are meant to happen
> anyway.
> 
> Can't we just have a single case that prints the error value?

Right, generally we should not see these errors. But few of them are
failures based on argument(s) passing to hcall. like passing invalid
window type or credits are not availavble. 

So can I add error messages for these specific ones and common error
message for other failures with the error code?

case H_PARAMETER:
   	pr_err("HCALL(%x): Invalid window type (%u)\n",
		H_ALLOCATE_VAS_WINDOW, wintype);
case H_CONSTRAINED:
   	pr_err("HCALL(%x): Credits (%u) are not available\n",
		H_ALLOCATE_VAS_WINDOW, credits);
case H_P2:
	pr_err("HCALL(%x): Credits(%u) exceed maximum window
credits\n", H_ALLOCATE_VAS_WINDOW, credits);
default:
	pr_err("HCALL(%x): failure with error code %d\n", 	
		H_ALLOCATE_VAS_WINDOW, rc);


> 
> Same comment for the other hcalls.
> 
> > +}
> > +
> > +/*
> > + * Deallocate VAS window HCALL.
> > + */
> > +static int plpar_vas_deallocate_window(u64 winid)
> > +{
> > +	int64_t rc;
> > +
> > +	do {
> > +		rc = plpar_hcall_norets(H_DEALLOCATE_VAS_WINDOW,
> > winid);
> > +
> > +		rc = hcall_return_busy_check(rc);
> > +	} while (rc == H_BUSY);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%x): Invalid window ID %llu\n",
> > +			H_DEALLOCATE_VAS_WINDOW, winid);
> > +		return -EINVAL;
> > +	case H_STATE:
> > +		pr_err("HCALL(%x): Window(%llu): Invalid page table
> > entries\n",
> > +			H_DEALLOCATE_VAS_WINDOW, winid);
> > +		return -EPERM;
> > +	default:
> > +		pr_err("HCALL(%x): Unexpected error %lld for
> > window(%llu)\n",
> > +			H_DEALLOCATE_VAS_WINDOW, rc, winid);
> > +		return -EIO;
> > +	}
> > +}
> > +
> > +/*
> > + * Modify VAS window.
> > + * After the window is opened with allocate window HCALL,
> > configure it
> > + * with flags and LPAR PID before using.
> > + */
> > +static int plpar_vas_modify_window(struct vas_window *win)
> > +{
> > +	int64_t rc;
> > +	u32 lpid = mfspr(SPRN_PID);
> 
> The lpid would be SPRN_LPID ?
> But you can't read it from a guest. Is the variable just misnamed?

yes, not using in pseries code now, but thought LPID is available in
SPRN_PID - PIDR is SPR48 and access to that in LPAR. Not true?

"processId : The LPAR process ID to bind to the specified window. This
parameter is ignored if the “closeWindow” flag is set.
threadId : The LPAR thread ID to bind to the specified window. This
parameter is ignored if the “closeWindow”
flag is set."

since TIDR is deprecated on p10, we are not passing threadID
> 
> > +
> > +	/*
> > +	 * AMR value is not supported in Linux implementation
> > +	 * phyp ignores it if 0 is passed.
> > +	 */
> 
> Heh, this comment is already here.
> 
> Do you mean the Linux VAS implementation doesn't support AMR? Because
> Linux definitely does use AMR.

Linux VAS implementation does not support AMR. The application /
library has to pass this value with TX_WIN_OPEN ioctl. We do not have
any use case right now. I will change the above comment to make it
clear.

phyp added this interface for future reference and AIX may be using it.

Thanks
Haren
> 
> > +	do {
> > +		rc = plpar_hcall_norets(H_MODIFY_VAS_WINDOW, win-
> > >winid,
> > +					lpid, 0, VAS_MOD_WIN_FLAGS,
> > +					VAS_AMR_VALUE);
> > +
> > +		rc = hcall_return_busy_check(rc);
> > +	} while (rc == H_BUSY);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%x): Invalid window ID %u\n",
> > +			H_MODIFY_VAS_WINDOW, win->winid);
> > +		return -EINVAL;
> > +	case H_P2:
> > +		pr_err("HCALL(%x): Window(%d): Invalid LPAR Process ID
> > %u\n",
> > +			H_MODIFY_VAS_WINDOW, lpid, win->winid);
> > +		return -EINVAL;
> > +	case H_P3:
> > +		/* LPAR thread ID is deprecated on P10 */
> > +		pr_err("HCALL(%x): Invalid LPAR Thread ID for
> > window(%u)\n",
> > +			H_MODIFY_VAS_WINDOW, win->winid);
> > +		return -EINVAL;
> > +	case H_STATE:
> > +		pr_err("HCALL(%x): Jobs in progress, Can't modify
> > window(%u)\n",
> > +			H_MODIFY_VAS_WINDOW, win->winid);
> > +		return -EBUSY;
> > +	default:
> > +		pr_err("HCALL(%x): Unexpected error %lld for
> > window(%u)\n",
> > +			H_MODIFY_VAS_WINDOW, rc, win->winid);
> > +		return -EIO;
> > +	}
> > +}
> > +
> > +/*
> > + * This HCALL is used to determine the capabilities that pHyp
> > provides.
> > + * @hcall: H_QUERY_VAS_CAPABILITIES or H_QUERY_NX_CAPABILITIES
> > + * @query_type: If 0 is passed, phyp returns the overall
> > capabilities
> > + *		which provides all feature(s) that are available. Then
> > + *		query phyp to get the corresponding capabilities for
> > + *		the specific feature.
> > + *		Example: H_QUERY_VAS_CAPABILITIES provides VAS GZIP QoS
> > + *			and VAS GZIP Default capabilities.
> > + *			H_QUERY_NX_CAPABILITIES provides NX GZIP
> > + *			capabilities.
> > + * @result: Return buffer to save capabilities.
> > + */
> > +int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
> > +					u64 result)
> > +{
> > +	int64_t rc;
> > +
> > +	rc = plpar_hcall_norets(hcall, query_type, result);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%llx): Invalid query type %u\n", hcall,
> > +			query_type);
> > +		return -EINVAL;
> > +	case H_PRIVILEGE:
> > +		pr_err("HCALL(%llx): Invalid result buffer 0x%llx\n",
> > +			hcall, result);
> > +		return -EACCES;
> > +	default:
> > +		pr_err("HCALL(%llx): Unexpected error %lld\n", hcall,
> > rc);
> > +		return -EIO;
> > +	}
> > +}
> 
> cheers


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 09/16] powerpc/pseries/vas: Add HCALL wrappers for VAS handling
@ 2021-06-04 21:53       ` Haren Myneni
  0 siblings, 0 replies; 86+ messages in thread
From: Haren Myneni @ 2021-06-04 21:53 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev, linux-crypto, herbert, npiggin

On Fri, 2021-06-04 at 21:52 +1000, Michael Ellerman wrote:
> Haren Myneni <haren@linux.ibm.com> writes:
> > This patch adds the following HCALL wrapper functions to allocate,
> 
> Normal spelling is "hcall".
> 
> > modify and deallocate VAS windows, and retrieve VAS capabilities.
> > 
> > H_ALLOCATE_VAS_WINDOW: Allocate VAS window
> > H_DEALLOCATE_VAS_WINDOW: Close VAS window
> > H_MODIFY_VAS_WINDOW: Setup window before using
> > H_QUERY_VAS_CAPABILITIES: Get VAS capabilities
> 
> Please tell us which version of PAPR, and in which section etc.,
> these
> are described in.
> 
> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
> > Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
> > ---
> >  arch/powerpc/platforms/pseries/vas.c | 217
> > +++++++++++++++++++++++++++
> >  1 file changed, 217 insertions(+)
> >  create mode 100644 arch/powerpc/platforms/pseries/vas.c
> > 
> > diff --git a/arch/powerpc/platforms/pseries/vas.c
> > b/arch/powerpc/platforms/pseries/vas.c
> > new file mode 100644
> > index 000000000000..06960151477c
> > --- /dev/null
> > +++ b/arch/powerpc/platforms/pseries/vas.c
> > @@ -0,0 +1,217 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Copyright 2020-21 IBM Corp.
> > + */
> > +
> > +#define pr_fmt(fmt) "vas: " fmt
> > +
> > +#include <linux/module.h>
> > +#include <linux/kernel.h>
> > +#include <linux/export.h>
> > +#include <linux/types.h>
> > +#include <linux/delay.h>
> > +#include <linux/slab.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/sched/mm.h>
> > +#include <linux/mmu_context.h>
> > +#include <asm/hvcall.h>
> > +#include <asm/hvconsole.h>
> > +#include <asm/machdep.h>
> 
> Do we need all those headers?
> 
> > +#include <asm/plpar_wrappers.h>
> > +#include <asm/vas.h>
> > +#include "vas.h"
> > +
> > +#define	VAS_INVALID_WIN_ADDRESS	0xFFFFFFFFFFFFFFFFul
> > +#define	VAS_DEFAULT_DOMAIN_ID	0xFFFFFFFFFFFFFFFFul
> 
> Some blank lines for formatting please.
> 
> > +/* Authority Mask Register (AMR) value is not supported in */
> > +/* linux implementation. So pass '0' to modify window HCALL */
> 
> Please fix the comment formatting.
> 
> > +#define	VAS_AMR_VALUE	0
> 
> This is only used in one place. It'd be simpler to just pass 0 and
> move
> the comment there.
> 
> > +/* phyp allows one credit per window right now */
> > +#define DEF_WIN_CREDS		1
> > +
> > +static int64_t hcall_return_busy_check(int64_t rc)
> > +{
> 
> Please use normal kernel types, ie. s64, or just long.
> 
> Same comment throughout.
> 
> > +	/* Check if we are stalled for some time */
> > +	if (H_IS_LONG_BUSY(rc)) {
> > +		msleep(get_longbusy_msecs(rc));
> > +		rc = H_BUSY;
> > +	} else if (rc == H_BUSY) {
> > +		cond_resched();
> > +	}
> > +
> > +	return rc;
> > +}
> > +
> > +/*
> > + * Allocate VAS window HCALL
> > + */
> > +static int plpar_vas_allocate_window(struct vas_window *win, u64
> > *domain,
> > +				     u8 wintype, u16 credits)
> 
> You don't have to use the "plpar" prefix for these sort of wrappers.
> 
> Just naming them after the hcall would probably be clearer, so:
> 
>  h_allocate_vas_window(... )
> 
> > +{
> > +	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
> > +	int64_t rc;
> > +
> > +	do {
> > +		rc = plpar_hcall9(H_ALLOCATE_VAS_WINDOW, retbuf,
> > wintype,
> > +				  credits, domain[0], domain[1],
> > domain[2],
> > +				  domain[3], domain[4], domain[5]);
> > +
> > +		rc = hcall_return_busy_check(rc);
> > +	} while (rc == H_BUSY);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		win->winid = retbuf[0];
> > +		win->lpar.win_addr = retbuf[1];
> > +		win->lpar.complete_irq = retbuf[2];
> > +		win->lpar.fault_irq = retbuf[3];
> 
> You shouldn't mutate win until you know there is no error.
> 
> > +		if (win->lpar.win_addr == VAS_INVALID_WIN_ADDRESS) {
> > +			pr_err("HCALL(%x): COPY/PASTE is not
> > supported\n",
> > +				H_ALLOCATE_VAS_WINDOW);
> > +			return -ENOTSUPP;
> > +		}
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%x): Invalid window type (%u)\n",
> > +			H_ALLOCATE_VAS_WINDOW, wintype);
> > +		return -EINVAL;
> > +	case H_P2:
> > +		pr_err("HCALL(%x): Credits(%u) exceed maximum window
> > credits\n",
> > +			H_ALLOCATE_VAS_WINDOW, credits);
> > +		return -EINVAL;
> > +	case H_COP_HW:
> > +		pr_err("HCALL(%x): User-mode COPY/PASTE is not
> > supported\n",
> > +			H_ALLOCATE_VAS_WINDOW);
> > +		return -ENOTSUPP;
> > +	case H_RESOURCE:
> > +		pr_err("HCALL(%x): LPAR credit limit exceeds window
> > limit\n",
> > +			H_ALLOCATE_VAS_WINDOW);
> > +		return -EPERM;
> > +	case H_CONSTRAINED:
> > +		pr_err("HCALL(%x): Credits (%u) are not available\n",
> > +			H_ALLOCATE_VAS_WINDOW, credits);
> > +		return -EPERM;
> > +	default:
> > +		pr_err("HCALL(%x): Unexpected error %lld\n",
> > +			H_ALLOCATE_VAS_WINDOW, rc);
> > +		return -EIO;
> > +	}
> 
> Do we really need all these error prints? It's very verbose, and
> presumably in normal operation none of these are meant to happen
> anyway.
> 
> Can't we just have a single case that prints the error value?

Right, generally we should not see these errors. But few of them are
failures based on argument(s) passing to hcall. like passing invalid
window type or credits are not availavble. 

So can I add error messages for these specific ones and common error
message for other failures with the error code?

case H_PARAMETER:
   	pr_err("HCALL(%x): Invalid window type (%u)\n",
		H_ALLOCATE_VAS_WINDOW, wintype);
case H_CONSTRAINED:
   	pr_err("HCALL(%x): Credits (%u) are not available\n",
		H_ALLOCATE_VAS_WINDOW, credits);
case H_P2:
	pr_err("HCALL(%x): Credits(%u) exceed maximum window
credits\n", H_ALLOCATE_VAS_WINDOW, credits);
default:
	pr_err("HCALL(%x): failure with error code %d\n", 	
		H_ALLOCATE_VAS_WINDOW, rc);


> 
> Same comment for the other hcalls.
> 
> > +}
> > +
> > +/*
> > + * Deallocate VAS window HCALL.
> > + */
> > +static int plpar_vas_deallocate_window(u64 winid)
> > +{
> > +	int64_t rc;
> > +
> > +	do {
> > +		rc = plpar_hcall_norets(H_DEALLOCATE_VAS_WINDOW,
> > winid);
> > +
> > +		rc = hcall_return_busy_check(rc);
> > +	} while (rc == H_BUSY);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%x): Invalid window ID %llu\n",
> > +			H_DEALLOCATE_VAS_WINDOW, winid);
> > +		return -EINVAL;
> > +	case H_STATE:
> > +		pr_err("HCALL(%x): Window(%llu): Invalid page table
> > entries\n",
> > +			H_DEALLOCATE_VAS_WINDOW, winid);
> > +		return -EPERM;
> > +	default:
> > +		pr_err("HCALL(%x): Unexpected error %lld for
> > window(%llu)\n",
> > +			H_DEALLOCATE_VAS_WINDOW, rc, winid);
> > +		return -EIO;
> > +	}
> > +}
> > +
> > +/*
> > + * Modify VAS window.
> > + * After the window is opened with allocate window HCALL,
> > configure it
> > + * with flags and LPAR PID before using.
> > + */
> > +static int plpar_vas_modify_window(struct vas_window *win)
> > +{
> > +	int64_t rc;
> > +	u32 lpid = mfspr(SPRN_PID);
> 
> The lpid would be SPRN_LPID ?
> But you can't read it from a guest. Is the variable just misnamed?

yes, not using in pseries code now, but thought LPID is available in
SPRN_PID - PIDR is SPR48 and access to that in LPAR. Not true?

"processId : The LPAR process ID to bind to the specified window. This
parameter is ignored if the “closeWindow” flag is set.
threadId : The LPAR thread ID to bind to the specified window. This
parameter is ignored if the “closeWindow”
flag is set."

since TIDR is deprecated on p10, we are not passing threadID
> 
> > +
> > +	/*
> > +	 * AMR value is not supported in Linux implementation
> > +	 * phyp ignores it if 0 is passed.
> > +	 */
> 
> Heh, this comment is already here.
> 
> Do you mean the Linux VAS implementation doesn't support AMR? Because
> Linux definitely does use AMR.

Linux VAS implementation does not support AMR. The application /
library has to pass this value with TX_WIN_OPEN ioctl. We do not have
any use case right now. I will change the above comment to make it
clear.

phyp added this interface for future reference and AIX may be using it.

Thanks
Haren
> 
> > +	do {
> > +		rc = plpar_hcall_norets(H_MODIFY_VAS_WINDOW, win-
> > >winid,
> > +					lpid, 0, VAS_MOD_WIN_FLAGS,
> > +					VAS_AMR_VALUE);
> > +
> > +		rc = hcall_return_busy_check(rc);
> > +	} while (rc == H_BUSY);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%x): Invalid window ID %u\n",
> > +			H_MODIFY_VAS_WINDOW, win->winid);
> > +		return -EINVAL;
> > +	case H_P2:
> > +		pr_err("HCALL(%x): Window(%d): Invalid LPAR Process ID
> > %u\n",
> > +			H_MODIFY_VAS_WINDOW, lpid, win->winid);
> > +		return -EINVAL;
> > +	case H_P3:
> > +		/* LPAR thread ID is deprecated on P10 */
> > +		pr_err("HCALL(%x): Invalid LPAR Thread ID for
> > window(%u)\n",
> > +			H_MODIFY_VAS_WINDOW, win->winid);
> > +		return -EINVAL;
> > +	case H_STATE:
> > +		pr_err("HCALL(%x): Jobs in progress, Can't modify
> > window(%u)\n",
> > +			H_MODIFY_VAS_WINDOW, win->winid);
> > +		return -EBUSY;
> > +	default:
> > +		pr_err("HCALL(%x): Unexpected error %lld for
> > window(%u)\n",
> > +			H_MODIFY_VAS_WINDOW, rc, win->winid);
> > +		return -EIO;
> > +	}
> > +}
> > +
> > +/*
> > + * This HCALL is used to determine the capabilities that pHyp
> > provides.
> > + * @hcall: H_QUERY_VAS_CAPABILITIES or H_QUERY_NX_CAPABILITIES
> > + * @query_type: If 0 is passed, phyp returns the overall
> > capabilities
> > + *		which provides all feature(s) that are available. Then
> > + *		query phyp to get the corresponding capabilities for
> > + *		the specific feature.
> > + *		Example: H_QUERY_VAS_CAPABILITIES provides VAS GZIP QoS
> > + *			and VAS GZIP Default capabilities.
> > + *			H_QUERY_NX_CAPABILITIES provides NX GZIP
> > + *			capabilities.
> > + * @result: Return buffer to save capabilities.
> > + */
> > +int plpar_vas_query_capabilities(const u64 hcall, u8 query_type,
> > +					u64 result)
> > +{
> > +	int64_t rc;
> > +
> > +	rc = plpar_hcall_norets(hcall, query_type, result);
> > +
> > +	switch (rc) {
> > +	case H_SUCCESS:
> > +		return 0;
> > +	case H_PARAMETER:
> > +		pr_err("HCALL(%llx): Invalid query type %u\n", hcall,
> > +			query_type);
> > +		return -EINVAL;
> > +	case H_PRIVILEGE:
> > +		pr_err("HCALL(%llx): Invalid result buffer 0x%llx\n",
> > +			hcall, result);
> > +		return -EACCES;
> > +	default:
> > +		pr_err("HCALL(%llx): Unexpected error %lld\n", hcall,
> > rc);
> > +		return -EIO;
> > +	}
> > +}
> 
> cheers


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
  2021-06-04  4:08       ` Haren Myneni
@ 2021-06-05  0:31         ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-05  0:31 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of June 4, 2021 2:08 pm:
> On Thu, 2021-06-03 at 14:21 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:31 pm:
>> > Take pid and mm references when each window opens and drops during
>> > close. This functionality is needed for powerNV and pseries. So
>> > this patch defines the existing code as functions in common book3s
>> > platform vas-api.c
>> > 
>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>> 
>> Seems like a good idea to put these into their own helper functions.
>> 
>> > ---
>> >  arch/powerpc/include/asm/vas.h              | 25 +++++++++
>> >  arch/powerpc/platforms/book3s/vas-api.c     | 51
>> > ++++++++++++++++++
>> >  arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
>> >  arch/powerpc/platforms/powernv/vas-window.c | 57 ++---------------
>> > ----
>> >  arch/powerpc/platforms/powernv/vas.h        |  6 +--
>> >  5 files changed, 88 insertions(+), 61 deletions(-)
>> > 
>> > diff --git a/arch/powerpc/include/asm/vas.h
>> > b/arch/powerpc/include/asm/vas.h
>> > index 668303198772..3f2b02461a76 100644
>> > --- a/arch/powerpc/include/asm/vas.h
>> > +++ b/arch/powerpc/include/asm/vas.h
>> > @@ -5,6 +5,9 @@
>> >  
>> >  #ifndef _ASM_POWERPC_VAS_H
>> >  #define _ASM_POWERPC_VAS_H
>> > +#include <linux/sched/mm.h>
>> > +#include <linux/mmu_context.h>
>> > +#include <asm/icswx.h>
>> >  #include <uapi/asm/vas-api.h>
>> >  
>> >  struct vas_window;
>> > @@ -49,6 +52,17 @@ enum vas_cop_type {
>> >  	VAS_COP_TYPE_MAX,
>> >  };
>> >  
>> > +/*
>> > + * User space VAS windows are opened by tasks and take references
>> > + * to pid and mm until windows are closed.
>> > + * Stores pid, mm, and tgid for each window.
>> > + */
>> > +struct vas_user_win_ref {
>> > +	struct pid *pid;	/* PID of owner */
>> > +	struct pid *tgid;	/* Thread group ID of owner */
>> > +	struct mm_struct *mm;	/* Linux process mm_struct */
>> > +};
>> > +
>> >  /*
>> >   * User space window operations used for powernv and powerVM
>> >   */
>> > @@ -59,6 +73,16 @@ struct vas_user_win_ops {
>> >  	int (*close_win)(void *);
>> >  };
>> >  
>> > +static inline void vas_drop_reference_pid_mm(struct
>> > vas_user_win_ref *ref)
>> > +{
>> > +	/* Drop references to pid and mm */
>> > +	put_pid(ref->pid);
>> > +	if (ref->mm) {
>> > +		mm_context_remove_vas_window(ref->mm);
>> > +		mmdrop(ref->mm);
>> > +	}
>> > +}
>> 
>> You don't have to make up a new name for such a thing because you 
>> already have one
>> 
>> put_vas_user_win_ref(struct vas_user_win_ref *ref)
>> 
>> 
>> > +
>> >  /*
>> >   * Receive window attributes specified by the (in-kernel) owner of
>> > window.
>> >   */
>> > @@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod,
>> > enum vas_cop_type cop_type,
>> >  			    struct vas_user_win_ops *vops);
>> >  void vas_unregister_coproc_api(void);
>> >  
>> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
>> >  #endif /* __ASM_POWERPC_VAS_H */
>> > diff --git a/arch/powerpc/platforms/book3s/vas-api.c
>> > b/arch/powerpc/platforms/book3s/vas-api.c
>> > index 6c39320bfb9b..a0141bfb2e4b 100644
>> > --- a/arch/powerpc/platforms/book3s/vas-api.c
>> > +++ b/arch/powerpc/platforms/book3s/vas-api.c
>> > @@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev,
>> > umode_t *mode)
>> >  	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
>> >  }
>> >  
>> > +/*
>> > + * Take reference to pid and mm
>> > + */
>> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
>> > +{
>> 
>> So this is quite different from a typical refcount object in that
>> it's 
>> opening it for access as well. I would split it in two functions, one
>> matching put_vas_user_win_ref() and appearing in the same place in
>> code,
>> which is up to about mmput and another function that adds the window
>> and
>> does the CP_ABORT etc... hmm, where do you release tgid?
> 
> Basically copied the existing code in to these functions
> (vas_reference_pid_mm/vas_drop_reference_pid_mm) so that useful for
> both platforms. 
> 
> mm_context_add/remove_vas_window() is also like taking reference. So
> instead of adding 2 seperate functions, how about naming
> get/put_vas_user_win_ref() 

It's actually different though. What I'm asking is the parts where you 
interact with core kernel data structure refcounts go into their own 
get/put functions.

Someone who understands that refcounting and looks at the code will care 
about those bits, so having them all together I think is helpful. They 
don't know about adding vas windows or CP_ABORT.

> Regarding tgid, the reference is taking only with pid, but not tgid.
> pid reuse can happen only in the case of multithread applications when
> the child that opened VAS window exits. But these windows will be
> closed when tgid exists. So do not need tgid reference.

I don't understand you.  The code you added does take a reference to 
tgid...

>> > +	/*
>> > +	 * Window opened by a child thread may not be closed when
>> > +	 * it exits. So take reference to its pid and release it
>> > +	 * when the window is free by parent thread.
>> > +	 * Acquire a reference to the task's pid to make sure
>> > +	 * pid will not be re-used - needed only for multithread
>> > +	 * applications.
>> > +	 */
>> > +	task_ref->pid = get_task_pid(current, PIDTYPE_PID);

My question is, where is this reference released. I can't see it. I'm 
asking about existing upstream code really because this patch is just 
copying existing code around.

Thanks,
Nick


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
@ 2021-06-05  0:31         ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-05  0:31 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of June 4, 2021 2:08 pm:
> On Thu, 2021-06-03 at 14:21 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:31 pm:
>> > Take pid and mm references when each window opens and drops during
>> > close. This functionality is needed for powerNV and pseries. So
>> > this patch defines the existing code as functions in common book3s
>> > platform vas-api.c
>> > 
>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>> 
>> Seems like a good idea to put these into their own helper functions.
>> 
>> > ---
>> >  arch/powerpc/include/asm/vas.h              | 25 +++++++++
>> >  arch/powerpc/platforms/book3s/vas-api.c     | 51
>> > ++++++++++++++++++
>> >  arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
>> >  arch/powerpc/platforms/powernv/vas-window.c | 57 ++---------------
>> > ----
>> >  arch/powerpc/platforms/powernv/vas.h        |  6 +--
>> >  5 files changed, 88 insertions(+), 61 deletions(-)
>> > 
>> > diff --git a/arch/powerpc/include/asm/vas.h
>> > b/arch/powerpc/include/asm/vas.h
>> > index 668303198772..3f2b02461a76 100644
>> > --- a/arch/powerpc/include/asm/vas.h
>> > +++ b/arch/powerpc/include/asm/vas.h
>> > @@ -5,6 +5,9 @@
>> >  
>> >  #ifndef _ASM_POWERPC_VAS_H
>> >  #define _ASM_POWERPC_VAS_H
>> > +#include <linux/sched/mm.h>
>> > +#include <linux/mmu_context.h>
>> > +#include <asm/icswx.h>
>> >  #include <uapi/asm/vas-api.h>
>> >  
>> >  struct vas_window;
>> > @@ -49,6 +52,17 @@ enum vas_cop_type {
>> >  	VAS_COP_TYPE_MAX,
>> >  };
>> >  
>> > +/*
>> > + * User space VAS windows are opened by tasks and take references
>> > + * to pid and mm until windows are closed.
>> > + * Stores pid, mm, and tgid for each window.
>> > + */
>> > +struct vas_user_win_ref {
>> > +	struct pid *pid;	/* PID of owner */
>> > +	struct pid *tgid;	/* Thread group ID of owner */
>> > +	struct mm_struct *mm;	/* Linux process mm_struct */
>> > +};
>> > +
>> >  /*
>> >   * User space window operations used for powernv and powerVM
>> >   */
>> > @@ -59,6 +73,16 @@ struct vas_user_win_ops {
>> >  	int (*close_win)(void *);
>> >  };
>> >  
>> > +static inline void vas_drop_reference_pid_mm(struct
>> > vas_user_win_ref *ref)
>> > +{
>> > +	/* Drop references to pid and mm */
>> > +	put_pid(ref->pid);
>> > +	if (ref->mm) {
>> > +		mm_context_remove_vas_window(ref->mm);
>> > +		mmdrop(ref->mm);
>> > +	}
>> > +}
>> 
>> You don't have to make up a new name for such a thing because you 
>> already have one
>> 
>> put_vas_user_win_ref(struct vas_user_win_ref *ref)
>> 
>> 
>> > +
>> >  /*
>> >   * Receive window attributes specified by the (in-kernel) owner of
>> > window.
>> >   */
>> > @@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod,
>> > enum vas_cop_type cop_type,
>> >  			    struct vas_user_win_ops *vops);
>> >  void vas_unregister_coproc_api(void);
>> >  
>> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
>> >  #endif /* __ASM_POWERPC_VAS_H */
>> > diff --git a/arch/powerpc/platforms/book3s/vas-api.c
>> > b/arch/powerpc/platforms/book3s/vas-api.c
>> > index 6c39320bfb9b..a0141bfb2e4b 100644
>> > --- a/arch/powerpc/platforms/book3s/vas-api.c
>> > +++ b/arch/powerpc/platforms/book3s/vas-api.c
>> > @@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev,
>> > umode_t *mode)
>> >  	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
>> >  }
>> >  
>> > +/*
>> > + * Take reference to pid and mm
>> > + */
>> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
>> > +{
>> 
>> So this is quite different from a typical refcount object in that
>> it's 
>> opening it for access as well. I would split it in two functions, one
>> matching put_vas_user_win_ref() and appearing in the same place in
>> code,
>> which is up to about mmput and another function that adds the window
>> and
>> does the CP_ABORT etc... hmm, where do you release tgid?
> 
> Basically copied the existing code in to these functions
> (vas_reference_pid_mm/vas_drop_reference_pid_mm) so that useful for
> both platforms. 
> 
> mm_context_add/remove_vas_window() is also like taking reference. So
> instead of adding 2 seperate functions, how about naming
> get/put_vas_user_win_ref() 

It's actually different though. What I'm asking is the parts where you 
interact with core kernel data structure refcounts go into their own 
get/put functions.

Someone who understands that refcounting and looks at the code will care 
about those bits, so having them all together I think is helpful. They 
don't know about adding vas windows or CP_ABORT.

> Regarding tgid, the reference is taking only with pid, but not tgid.
> pid reuse can happen only in the case of multithread applications when
> the child that opened VAS window exits. But these windows will be
> closed when tgid exists. So do not need tgid reference.

I don't understand you.  The code you added does take a reference to 
tgid...

>> > +	/*
>> > +	 * Window opened by a child thread may not be closed when
>> > +	 * it exits. So take reference to its pid and release it
>> > +	 * when the window is free by parent thread.
>> > +	 * Acquire a reference to the task's pid to make sure
>> > +	 * pid will not be re-used - needed only for multithread
>> > +	 * applications.
>> > +	 */
>> > +	task_ref->pid = get_task_pid(current, PIDTYPE_PID);

My question is, where is this reference released. I can't see it. I'm 
asking about existing upstream code really because this patch is just 
copying existing code around.

Thanks,
Nick


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 07/16] powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
  2021-06-04  1:30       ` Haren Myneni
@ 2021-06-05  0:37         ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-05  0:37 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of June 4, 2021 11:30 am:
> On Thu, 2021-06-03 at 14:47 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:34 pm:
>> > This patch adds HCALLs and other definitions. Also define structs
>> > that are used in VAS implementation on powerVM.
>> > 
>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>> > ---
>> >  arch/powerpc/include/asm/hvcall.h    |   7 ++
>> >  arch/powerpc/include/asm/vas.h       |  32 ++++++++
>> >  arch/powerpc/platforms/pseries/vas.h | 110
>> > +++++++++++++++++++++++++++
>> >  3 files changed, 149 insertions(+)
>> >  create mode 100644 arch/powerpc/platforms/pseries/vas.h
>> > 
>> > diff --git a/arch/powerpc/include/asm/hvcall.h
>> > b/arch/powerpc/include/asm/hvcall.h
>> > index e3b29eda8074..7c3418d1b5e9 100644
>> > --- a/arch/powerpc/include/asm/hvcall.h
>> > +++ b/arch/powerpc/include/asm/hvcall.h
>> > @@ -294,6 +294,13 @@
>> >  #define H_RESIZE_HPT_COMMIT	0x370
>> >  #define H_REGISTER_PROC_TBL	0x37C
>> >  #define H_SIGNAL_SYS_RESET	0x380
>> > +#define H_ALLOCATE_VAS_WINDOW	0x388
>> > +#define H_MODIFY_VAS_WINDOW	0x38C
>> > +#define H_DEALLOCATE_VAS_WINDOW	0x390
>> > +#define H_QUERY_VAS_WINDOW	0x394
>> > +#define H_QUERY_VAS_CAPABILITIES	0x398
>> > +#define H_QUERY_NX_CAPABILITIES	0x39C
>> > +#define H_GET_NX_FAULT		0x3A0
>> >  #define H_INT_GET_SOURCE_INFO   0x3A8
>> >  #define H_INT_SET_SOURCE_CONFIG 0x3AC
>> >  #define H_INT_GET_SOURCE_CONFIG 0x3B0
>> > diff --git a/arch/powerpc/include/asm/vas.h
>> > b/arch/powerpc/include/asm/vas.h
>> > index 49bfb5be896d..371f62d99174 100644
>> > --- a/arch/powerpc/include/asm/vas.h
>> > +++ b/arch/powerpc/include/asm/vas.h
>> > @@ -181,6 +181,7 @@ struct vas_tx_win_attr {
>> >  	bool rx_win_ord_mode;
>> >  };
>> >  
>> > +#ifdef CONFIG_PPC_POWERNV
>> >  /*
>> >   * Helper to map a chip id to VAS id.
>> >   * For POWER9, this is a 1:1 mapping. In the future this maybe a
>> > 1:N
>> > @@ -248,6 +249,37 @@ void vas_win_paste_addr(struct vas_window
>> > *window, u64 *addr,
>> >  int vas_register_api_powernv(struct module *mod, enum vas_cop_type
>> > cop_type,
>> >  			     const char *name);
>> >  void vas_unregister_api_powernv(void);
>> > +#endif
>> > +
>> > +#ifdef CONFIG_PPC_PSERIES
>> > +
>> > +/* VAS Capabilities */
>> > +#define VAS_GZIP_QOS_FEAT	0x1
>> > +#define VAS_GZIP_DEF_FEAT	0x2
>> > +#define VAS_GZIP_QOS_FEAT_BIT	PPC_BIT(VAS_GZIP_QOS_FEAT) /*
>> > Bit 1 */
>> > +#define VAS_GZIP_DEF_FEAT_BIT	PPC_BIT(VAS_GZIP_DEF_FEAT) /*
>> > Bit 2 */
>> > +
>> > +/* NX Capabilities */
>> > +#define VAS_NX_GZIP_FEAT	0x1
>> > +#define VAS_NX_GZIP_FEAT_BIT	PPC_BIT(VAS_NX_GZIP_FEAT) /*
>> > Bit 1 */
>> > +#define VAS_DESCR_LEN		8
>> > +
>> > +/*
>> > + * These structs are used to retrieve overall VAS capabilities
>> > that
>> > + * the hypervisor provides.
>> > + */
>> > +struct hv_vas_all_caps {
>> 
>> ...
>> 
>> > +
>> > +/*
>> > + * Use to get feature specific capabilities from the
>> > + * hypervisor.
>> > + */
>> > +struct hv_vas_ct_caps {
>> 
>> ...
>> 
>> > +/*
>> > + * To get window information from the hypervisor.
>> > + */
>> > +struct hv_vas_win_lpar {
>> 
>> Are any of these names coming from PAPR? If not, then typically we
>> don't 
>> use hv_ kind of prefixes for something we got from the hypervisor,
>> but
>> rather something that's hypervisor privileged or specific information
>> about the hypervisor perhaps (which is not the same as what the 
>> hypervisor may or may not advertise to the guest).
>> 
>> So if these are all capabilities and features the hypervisor
>> advertises 
>> to the LPAR, I think the hv_ should be dropped.
> 
> The hypervisor advertises the available capabalities and the LPAR
> passes buffer to HCALLs to retrieve these capabilties / features (in
> BE). 
> 
> I was using *_be in the previous version. So can I use like 'struct
> vas_ct_caps_be'  
> 
>> 
>> Otherwise seems okay. I would be careful of the "lpar" name. I think 
>> it's okay in this situation where the hypervisor advertises features
>> to 
>> the partition, but in other parts of the vas code you call it
>> pseries_
>> but you also have some lpar_ bits. So aside from interacting with
>> PAPR
>> APIs, it would be safe to consistently use pseries for your driver
>> and
>> type names.
> 
> I can use 'struct hv_vas_win_pseries' or 'struct vas_win_pseries_be'

I'm actually wrong about hv_ prefix now I look a bit further, there are
other structures that do use it for similar hcalls, sorry about that.

I'm not sure I like it too much but it is what it is. I would say don't
worry about churning your hv_ names for now. It's probably better / more 
used than _be postfix. Changing conventions could be a later 
powerpc-wide series if it's that important.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 07/16] powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs
@ 2021-06-05  0:37         ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-05  0:37 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of June 4, 2021 11:30 am:
> On Thu, 2021-06-03 at 14:47 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:34 pm:
>> > This patch adds HCALLs and other definitions. Also define structs
>> > that are used in VAS implementation on powerVM.
>> > 
>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>> > ---
>> >  arch/powerpc/include/asm/hvcall.h    |   7 ++
>> >  arch/powerpc/include/asm/vas.h       |  32 ++++++++
>> >  arch/powerpc/platforms/pseries/vas.h | 110
>> > +++++++++++++++++++++++++++
>> >  3 files changed, 149 insertions(+)
>> >  create mode 100644 arch/powerpc/platforms/pseries/vas.h
>> > 
>> > diff --git a/arch/powerpc/include/asm/hvcall.h
>> > b/arch/powerpc/include/asm/hvcall.h
>> > index e3b29eda8074..7c3418d1b5e9 100644
>> > --- a/arch/powerpc/include/asm/hvcall.h
>> > +++ b/arch/powerpc/include/asm/hvcall.h
>> > @@ -294,6 +294,13 @@
>> >  #define H_RESIZE_HPT_COMMIT	0x370
>> >  #define H_REGISTER_PROC_TBL	0x37C
>> >  #define H_SIGNAL_SYS_RESET	0x380
>> > +#define H_ALLOCATE_VAS_WINDOW	0x388
>> > +#define H_MODIFY_VAS_WINDOW	0x38C
>> > +#define H_DEALLOCATE_VAS_WINDOW	0x390
>> > +#define H_QUERY_VAS_WINDOW	0x394
>> > +#define H_QUERY_VAS_CAPABILITIES	0x398
>> > +#define H_QUERY_NX_CAPABILITIES	0x39C
>> > +#define H_GET_NX_FAULT		0x3A0
>> >  #define H_INT_GET_SOURCE_INFO   0x3A8
>> >  #define H_INT_SET_SOURCE_CONFIG 0x3AC
>> >  #define H_INT_GET_SOURCE_CONFIG 0x3B0
>> > diff --git a/arch/powerpc/include/asm/vas.h
>> > b/arch/powerpc/include/asm/vas.h
>> > index 49bfb5be896d..371f62d99174 100644
>> > --- a/arch/powerpc/include/asm/vas.h
>> > +++ b/arch/powerpc/include/asm/vas.h
>> > @@ -181,6 +181,7 @@ struct vas_tx_win_attr {
>> >  	bool rx_win_ord_mode;
>> >  };
>> >  
>> > +#ifdef CONFIG_PPC_POWERNV
>> >  /*
>> >   * Helper to map a chip id to VAS id.
>> >   * For POWER9, this is a 1:1 mapping. In the future this maybe a
>> > 1:N
>> > @@ -248,6 +249,37 @@ void vas_win_paste_addr(struct vas_window
>> > *window, u64 *addr,
>> >  int vas_register_api_powernv(struct module *mod, enum vas_cop_type
>> > cop_type,
>> >  			     const char *name);
>> >  void vas_unregister_api_powernv(void);
>> > +#endif
>> > +
>> > +#ifdef CONFIG_PPC_PSERIES
>> > +
>> > +/* VAS Capabilities */
>> > +#define VAS_GZIP_QOS_FEAT	0x1
>> > +#define VAS_GZIP_DEF_FEAT	0x2
>> > +#define VAS_GZIP_QOS_FEAT_BIT	PPC_BIT(VAS_GZIP_QOS_FEAT) /*
>> > Bit 1 */
>> > +#define VAS_GZIP_DEF_FEAT_BIT	PPC_BIT(VAS_GZIP_DEF_FEAT) /*
>> > Bit 2 */
>> > +
>> > +/* NX Capabilities */
>> > +#define VAS_NX_GZIP_FEAT	0x1
>> > +#define VAS_NX_GZIP_FEAT_BIT	PPC_BIT(VAS_NX_GZIP_FEAT) /*
>> > Bit 1 */
>> > +#define VAS_DESCR_LEN		8
>> > +
>> > +/*
>> > + * These structs are used to retrieve overall VAS capabilities
>> > that
>> > + * the hypervisor provides.
>> > + */
>> > +struct hv_vas_all_caps {
>> 
>> ...
>> 
>> > +
>> > +/*
>> > + * Use to get feature specific capabilities from the
>> > + * hypervisor.
>> > + */
>> > +struct hv_vas_ct_caps {
>> 
>> ...
>> 
>> > +/*
>> > + * To get window information from the hypervisor.
>> > + */
>> > +struct hv_vas_win_lpar {
>> 
>> Are any of these names coming from PAPR? If not, then typically we
>> don't 
>> use hv_ kind of prefixes for something we got from the hypervisor,
>> but
>> rather something that's hypervisor privileged or specific information
>> about the hypervisor perhaps (which is not the same as what the 
>> hypervisor may or may not advertise to the guest).
>> 
>> So if these are all capabilities and features the hypervisor
>> advertises 
>> to the LPAR, I think the hv_ should be dropped.
> 
> The hypervisor advertises the available capabalities and the LPAR
> passes buffer to HCALLs to retrieve these capabilties / features (in
> BE). 
> 
> I was using *_be in the previous version. So can I use like 'struct
> vas_ct_caps_be'  
> 
>> 
>> Otherwise seems okay. I would be careful of the "lpar" name. I think 
>> it's okay in this situation where the hypervisor advertises features
>> to 
>> the partition, but in other parts of the vas code you call it
>> pseries_
>> but you also have some lpar_ bits. So aside from interacting with
>> PAPR
>> APIs, it would be safe to consistently use pseries for your driver
>> and
>> type names.
> 
> I can use 'struct hv_vas_win_pseries' or 'struct vas_win_pseries_be'

I'm actually wrong about hv_ prefix now I look a bit further, there are
other structures that do use it for similar hcalls, sorry about that.

I'm not sure I like it too much but it is what it is. I would say don't
worry about churning your hv_ names for now. It's probably better / more 
used than _be postfix. Changing conventions could be a later 
powerpc-wide series if it's that important.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 12/16] powerpc/pseries/vas: Setup IRQ and fault handling
  2021-06-04  1:19       ` Haren Myneni
@ 2021-06-05  0:43         ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-05  0:43 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Haren Myneni's message of June 4, 2021 11:19 am:
> On Thu, 2021-06-03 at 15:48 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:39 pm:
>> > NX generates an interrupt when sees a fault on the user space
>> > buffer and the hypervisor forwards that interrupt to OS. Then
>> > the kernel handles the interrupt by issuing H_GET_NX_FAULT hcall
>> > to retrieve the fault CRB information.
>> > 
>> > This patch also adds changes to setup and free IRQ per each
>> > window and also handles the fault by updating the CSB.
>> > 
>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>> > ---
>> >  arch/powerpc/platforms/pseries/vas.c | 111
>> > +++++++++++++++++++++++++++
>> >  1 file changed, 111 insertions(+)
>> > 
>> > diff --git a/arch/powerpc/platforms/pseries/vas.c
>> > b/arch/powerpc/platforms/pseries/vas.c
>> > index ef0c455f6e93..31dc17573f50 100644
>> > --- a/arch/powerpc/platforms/pseries/vas.c
>> > +++ b/arch/powerpc/platforms/pseries/vas.c
>> > @@ -224,6 +224,62 @@ int plpar_vas_query_capabilities(const u64
>> > hcall, u8 query_type,
>> >  }
>> >  EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
>> >  
>> > +/*
>> > + * HCALL to get fault CRB from pHyp.
>> > + */
>> > +static int plpar_get_nx_fault(u32 winid, u64 buffer)
>> > +{
>> > +	int64_t rc;
>> > +
>> > +	rc = plpar_hcall_norets(H_GET_NX_FAULT, winid, buffer);
>> > +
>> > +	switch (rc) {
>> > +	case H_SUCCESS:
>> > +		return 0;
>> > +	case H_PARAMETER:
>> > +		pr_err("HCALL(%x): Invalid window ID %u\n",
>> > H_GET_NX_FAULT,
>> > +		       winid);
>> > +		return -EINVAL;
>> > +	case H_STATE:
>> > +		pr_err("HCALL(%x): No outstanding faults for window ID
>> > %u\n",
>> > +		       H_GET_NX_FAULT, winid);
>> > +		return -EINVAL;
>> > +	case H_PRIVILEGE:
>> > +		pr_err("HCALL(%x): Window(%u): Invalid fault buffer
>> > 0x%llx\n",
>> > +		       H_GET_NX_FAULT, winid, buffer);
>> > +		return -EACCES;
>> > +	default:
>> > +		pr_err("HCALL(%x): Unexpected error %lld for
>> > window(%u)\n",
>> > +		       H_GET_NX_FAULT, rc, winid);
>> > +		return -EIO;
>> > +	}
>> > +}
>> 
>> Out of curiosity, you get one of these errors and it just drops the
>> interrupt on the floor. Then what happens, I assume everything
>> stops. Should it put some error in the csb, or signal the process or
>> something? Or is there nothing very sane that can be done?
> 
> The user space polls on CSB with timout interval. If the kernel or NX
> does not return, the request will be timeout.

Okay, if there is no sane way it can respond to the different error 
cases that's not necessarily unreasonable to just print something in the 
kernel log. Hopefully the kernel log would be useful to the 
administrator / developer / etc, but that's pretty rarely the case for 
Linux errors as it is.

> The hypervisor returns the credit after H_GET_NX_FAULT HCALL is
> successful. Also one credit is assigned for each window. So in this
> case, the error is coming from the hypervisor and the application can
> not issue another request on the same window. 
> 
>> 
>> > +
>> > +/*
>> > + * Handle the fault interrupt.
>> > + * When the fault interrupt is received for each window, query
>> > pHyp to get
>> > + * the fault CRB on the specific fault. Then process the CRB by
>> > updating
>> > + * CSB or send signal if the user space CSB is invalid.
>> > + * Note: pHyp forwards an interrupt for each fault request. So one
>> > fault
>> > + *	CRB to process for each H_GET_NX_FAULT HCALL.
>> > + */
>> > +irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
>> > +{
>> > +	struct vas_window *txwin = data;
>> > +	struct coprocessor_request_block crb;
>> > +	struct vas_user_win_ref *tsk_ref;
>> > +	int rc;
>> > +
>> > +	rc = plpar_get_nx_fault(txwin->winid, (u64)virt_to_phys(&crb));
>> > +	if (!rc) {
>> > +		tsk_ref = &txwin->task_ref;
>> > +		vas_dump_crb(&crb);
>> 
>> This (and existing powernv vas code) is printk()ing a lot of lines
>> per 
>> fault. This should be pretty normal operation I think? It should
>> avoid
>> filling the kernel logs, if so. Particularly if it can be triggered
>> by 
>> userspace.
>> 
>> I know it's existing code, so could be fixed separately from the
>> series.
> 
> printk messages are only if HCALL returns failure or kernel issue (ex:
> not valid window and etc on powerNV). These errors should not be
> depending on the iser space requests. So generally we should not get
> these errors.  

Ah I was looking at dump_crb but that's using pr_devel so that's 
probably okay.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 12/16] powerpc/pseries/vas: Setup IRQ and fault handling
@ 2021-06-05  0:43         ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-05  0:43 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Haren Myneni's message of June 4, 2021 11:19 am:
> On Thu, 2021-06-03 at 15:48 +1000, Nicholas Piggin wrote:
>> Excerpts from Haren Myneni's message of May 21, 2021 7:39 pm:
>> > NX generates an interrupt when sees a fault on the user space
>> > buffer and the hypervisor forwards that interrupt to OS. Then
>> > the kernel handles the interrupt by issuing H_GET_NX_FAULT hcall
>> > to retrieve the fault CRB information.
>> > 
>> > This patch also adds changes to setup and free IRQ per each
>> > window and also handles the fault by updating the CSB.
>> > 
>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>> > ---
>> >  arch/powerpc/platforms/pseries/vas.c | 111
>> > +++++++++++++++++++++++++++
>> >  1 file changed, 111 insertions(+)
>> > 
>> > diff --git a/arch/powerpc/platforms/pseries/vas.c
>> > b/arch/powerpc/platforms/pseries/vas.c
>> > index ef0c455f6e93..31dc17573f50 100644
>> > --- a/arch/powerpc/platforms/pseries/vas.c
>> > +++ b/arch/powerpc/platforms/pseries/vas.c
>> > @@ -224,6 +224,62 @@ int plpar_vas_query_capabilities(const u64
>> > hcall, u8 query_type,
>> >  }
>> >  EXPORT_SYMBOL_GPL(plpar_vas_query_capabilities);
>> >  
>> > +/*
>> > + * HCALL to get fault CRB from pHyp.
>> > + */
>> > +static int plpar_get_nx_fault(u32 winid, u64 buffer)
>> > +{
>> > +	int64_t rc;
>> > +
>> > +	rc = plpar_hcall_norets(H_GET_NX_FAULT, winid, buffer);
>> > +
>> > +	switch (rc) {
>> > +	case H_SUCCESS:
>> > +		return 0;
>> > +	case H_PARAMETER:
>> > +		pr_err("HCALL(%x): Invalid window ID %u\n",
>> > H_GET_NX_FAULT,
>> > +		       winid);
>> > +		return -EINVAL;
>> > +	case H_STATE:
>> > +		pr_err("HCALL(%x): No outstanding faults for window ID
>> > %u\n",
>> > +		       H_GET_NX_FAULT, winid);
>> > +		return -EINVAL;
>> > +	case H_PRIVILEGE:
>> > +		pr_err("HCALL(%x): Window(%u): Invalid fault buffer
>> > 0x%llx\n",
>> > +		       H_GET_NX_FAULT, winid, buffer);
>> > +		return -EACCES;
>> > +	default:
>> > +		pr_err("HCALL(%x): Unexpected error %lld for
>> > window(%u)\n",
>> > +		       H_GET_NX_FAULT, rc, winid);
>> > +		return -EIO;
>> > +	}
>> > +}
>> 
>> Out of curiosity, you get one of these errors and it just drops the
>> interrupt on the floor. Then what happens, I assume everything
>> stops. Should it put some error in the csb, or signal the process or
>> something? Or is there nothing very sane that can be done?
> 
> The user space polls on CSB with timout interval. If the kernel or NX
> does not return, the request will be timeout.

Okay, if there is no sane way it can respond to the different error 
cases that's not necessarily unreasonable to just print something in the 
kernel log. Hopefully the kernel log would be useful to the 
administrator / developer / etc, but that's pretty rarely the case for 
Linux errors as it is.

> The hypervisor returns the credit after H_GET_NX_FAULT HCALL is
> successful. Also one credit is assigned for each window. So in this
> case, the error is coming from the hypervisor and the application can
> not issue another request on the same window. 
> 
>> 
>> > +
>> > +/*
>> > + * Handle the fault interrupt.
>> > + * When the fault interrupt is received for each window, query
>> > pHyp to get
>> > + * the fault CRB on the specific fault. Then process the CRB by
>> > updating
>> > + * CSB or send signal if the user space CSB is invalid.
>> > + * Note: pHyp forwards an interrupt for each fault request. So one
>> > fault
>> > + *	CRB to process for each H_GET_NX_FAULT HCALL.
>> > + */
>> > +irqreturn_t pseries_vas_fault_thread_fn(int irq, void *data)
>> > +{
>> > +	struct vas_window *txwin = data;
>> > +	struct coprocessor_request_block crb;
>> > +	struct vas_user_win_ref *tsk_ref;
>> > +	int rc;
>> > +
>> > +	rc = plpar_get_nx_fault(txwin->winid, (u64)virt_to_phys(&crb));
>> > +	if (!rc) {
>> > +		tsk_ref = &txwin->task_ref;
>> > +		vas_dump_crb(&crb);
>> 
>> This (and existing powernv vas code) is printk()ing a lot of lines
>> per 
>> fault. This should be pretty normal operation I think? It should
>> avoid
>> filling the kernel logs, if so. Particularly if it can be triggered
>> by 
>> userspace.
>> 
>> I know it's existing code, so could be fixed separately from the
>> series.
> 
> printk messages are only if HCALL returns failure or kernel issue (ex:
> not valid window and etc on powerNV). These errors should not be
> depending on the iser space requests. So generally we should not get
> these errors.  

Ah I was looking at dump_crb but that's using pr_devel so that's 
probably okay.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
  2021-06-05  0:31         ` Nicholas Piggin
@ 2021-06-05  3:03           ` Nicholas Piggin
  -1 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-05  3:03 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe; +Cc: haren, hbabu

Excerpts from Nicholas Piggin's message of June 5, 2021 10:31 am:
> Excerpts from Haren Myneni's message of June 4, 2021 2:08 pm:
>> On Thu, 2021-06-03 at 14:21 +1000, Nicholas Piggin wrote:
>>> Excerpts from Haren Myneni's message of May 21, 2021 7:31 pm:
>>> > Take pid and mm references when each window opens and drops during
>>> > close. This functionality is needed for powerNV and pseries. So
>>> > this patch defines the existing code as functions in common book3s
>>> > platform vas-api.c
>>> > 
>>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>>> 
>>> Seems like a good idea to put these into their own helper functions.
>>> 
>>> > ---
>>> >  arch/powerpc/include/asm/vas.h              | 25 +++++++++
>>> >  arch/powerpc/platforms/book3s/vas-api.c     | 51
>>> > ++++++++++++++++++
>>> >  arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
>>> >  arch/powerpc/platforms/powernv/vas-window.c | 57 ++---------------
>>> > ----
>>> >  arch/powerpc/platforms/powernv/vas.h        |  6 +--
>>> >  5 files changed, 88 insertions(+), 61 deletions(-)
>>> > 
>>> > diff --git a/arch/powerpc/include/asm/vas.h
>>> > b/arch/powerpc/include/asm/vas.h
>>> > index 668303198772..3f2b02461a76 100644
>>> > --- a/arch/powerpc/include/asm/vas.h
>>> > +++ b/arch/powerpc/include/asm/vas.h
>>> > @@ -5,6 +5,9 @@
>>> >  
>>> >  #ifndef _ASM_POWERPC_VAS_H
>>> >  #define _ASM_POWERPC_VAS_H
>>> > +#include <linux/sched/mm.h>
>>> > +#include <linux/mmu_context.h>
>>> > +#include <asm/icswx.h>
>>> >  #include <uapi/asm/vas-api.h>
>>> >  
>>> >  struct vas_window;
>>> > @@ -49,6 +52,17 @@ enum vas_cop_type {
>>> >  	VAS_COP_TYPE_MAX,
>>> >  };
>>> >  
>>> > +/*
>>> > + * User space VAS windows are opened by tasks and take references
>>> > + * to pid and mm until windows are closed.
>>> > + * Stores pid, mm, and tgid for each window.
>>> > + */
>>> > +struct vas_user_win_ref {
>>> > +	struct pid *pid;	/* PID of owner */
>>> > +	struct pid *tgid;	/* Thread group ID of owner */
>>> > +	struct mm_struct *mm;	/* Linux process mm_struct */
>>> > +};
>>> > +
>>> >  /*
>>> >   * User space window operations used for powernv and powerVM
>>> >   */
>>> > @@ -59,6 +73,16 @@ struct vas_user_win_ops {
>>> >  	int (*close_win)(void *);
>>> >  };
>>> >  
>>> > +static inline void vas_drop_reference_pid_mm(struct
>>> > vas_user_win_ref *ref)
>>> > +{
>>> > +	/* Drop references to pid and mm */
>>> > +	put_pid(ref->pid);
>>> > +	if (ref->mm) {
>>> > +		mm_context_remove_vas_window(ref->mm);
>>> > +		mmdrop(ref->mm);
>>> > +	}
>>> > +}
>>> 
>>> You don't have to make up a new name for such a thing because you 
>>> already have one
>>> 
>>> put_vas_user_win_ref(struct vas_user_win_ref *ref)
>>> 
>>> 
>>> > +
>>> >  /*
>>> >   * Receive window attributes specified by the (in-kernel) owner of
>>> > window.
>>> >   */
>>> > @@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod,
>>> > enum vas_cop_type cop_type,
>>> >  			    struct vas_user_win_ops *vops);
>>> >  void vas_unregister_coproc_api(void);
>>> >  
>>> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
>>> >  #endif /* __ASM_POWERPC_VAS_H */
>>> > diff --git a/arch/powerpc/platforms/book3s/vas-api.c
>>> > b/arch/powerpc/platforms/book3s/vas-api.c
>>> > index 6c39320bfb9b..a0141bfb2e4b 100644
>>> > --- a/arch/powerpc/platforms/book3s/vas-api.c
>>> > +++ b/arch/powerpc/platforms/book3s/vas-api.c
>>> > @@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev,
>>> > umode_t *mode)
>>> >  	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
>>> >  }
>>> >  
>>> > +/*
>>> > + * Take reference to pid and mm
>>> > + */
>>> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
>>> > +{
>>> 
>>> So this is quite different from a typical refcount object in that
>>> it's 
>>> opening it for access as well. I would split it in two functions, one
>>> matching put_vas_user_win_ref() and appearing in the same place in
>>> code,
>>> which is up to about mmput and another function that adds the window
>>> and
>>> does the CP_ABORT etc... hmm, where do you release tgid?
>> 
>> Basically copied the existing code in to these functions
>> (vas_reference_pid_mm/vas_drop_reference_pid_mm) so that useful for
>> both platforms. 
>> 
>> mm_context_add/remove_vas_window() is also like taking reference. So
>> instead of adding 2 seperate functions, how about naming
>> get/put_vas_user_win_ref() 
> 
> It's actually different though. What I'm asking is the parts where you 
> interact with core kernel data structure refcounts go into their own 
> get/put functions.
> 
> Someone who understands that refcounting and looks at the code will care 
> about those bits, so having them all together I think is helpful. They 
> don't know about adding vas windows or CP_ABORT.
> 
>> Regarding tgid, the reference is taking only with pid, but not tgid.
>> pid reuse can happen only in the case of multithread applications when
>> the child that opened VAS window exits. But these windows will be
>> closed when tgid exists. So do not need tgid reference.
> 
> I don't understand you.  The code you added does take a reference to 
> tgid...
> 
>>> > +	/*
>>> > +	 * Window opened by a child thread may not be closed when
>>> > +	 * it exits. So take reference to its pid and release it
>>> > +	 * when the window is free by parent thread.
>>> > +	 * Acquire a reference to the task's pid to make sure
>>> > +	 * pid will not be re-used - needed only for multithread
>>> > +	 * applications.
>>> > +	 */
>>> > +	task_ref->pid = get_task_pid(current, PIDTYPE_PID);

Quoted the wrong bit obviously:

+       /*
+        * Process closes window during exit. In the case of
+        * multithread application, the child thread can open
+        * window and can exit without closing it. Expects parent
+        * thread to use and close the window. So do not need
+        * to take pid reference for parent thread.
+        */
+       task_ref->tgid = find_get_pid(task_tgid_vnr(current));

aka vas_tx_win_open() in upstream code.

It's not a comment about this patch specificlaly, I just noticed it and 
I wanted to make sure I'm not missing somehting or the existing code 
isn't buggy before the patch goes in.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references
@ 2021-06-05  3:03           ` Nicholas Piggin
  0 siblings, 0 replies; 86+ messages in thread
From: Nicholas Piggin @ 2021-06-05  3:03 UTC (permalink / raw)
  To: Haren Myneni, herbert, linux-crypto, linuxppc-dev, mpe

Excerpts from Nicholas Piggin's message of June 5, 2021 10:31 am:
> Excerpts from Haren Myneni's message of June 4, 2021 2:08 pm:
>> On Thu, 2021-06-03 at 14:21 +1000, Nicholas Piggin wrote:
>>> Excerpts from Haren Myneni's message of May 21, 2021 7:31 pm:
>>> > Take pid and mm references when each window opens and drops during
>>> > close. This functionality is needed for powerNV and pseries. So
>>> > this patch defines the existing code as functions in common book3s
>>> > platform vas-api.c
>>> > 
>>> > Signed-off-by: Haren Myneni <haren@linux.ibm.com>
>>> 
>>> Seems like a good idea to put these into their own helper functions.
>>> 
>>> > ---
>>> >  arch/powerpc/include/asm/vas.h              | 25 +++++++++
>>> >  arch/powerpc/platforms/book3s/vas-api.c     | 51
>>> > ++++++++++++++++++
>>> >  arch/powerpc/platforms/powernv/vas-fault.c  | 10 ++--
>>> >  arch/powerpc/platforms/powernv/vas-window.c | 57 ++---------------
>>> > ----
>>> >  arch/powerpc/platforms/powernv/vas.h        |  6 +--
>>> >  5 files changed, 88 insertions(+), 61 deletions(-)
>>> > 
>>> > diff --git a/arch/powerpc/include/asm/vas.h
>>> > b/arch/powerpc/include/asm/vas.h
>>> > index 668303198772..3f2b02461a76 100644
>>> > --- a/arch/powerpc/include/asm/vas.h
>>> > +++ b/arch/powerpc/include/asm/vas.h
>>> > @@ -5,6 +5,9 @@
>>> >  
>>> >  #ifndef _ASM_POWERPC_VAS_H
>>> >  #define _ASM_POWERPC_VAS_H
>>> > +#include <linux/sched/mm.h>
>>> > +#include <linux/mmu_context.h>
>>> > +#include <asm/icswx.h>
>>> >  #include <uapi/asm/vas-api.h>
>>> >  
>>> >  struct vas_window;
>>> > @@ -49,6 +52,17 @@ enum vas_cop_type {
>>> >  	VAS_COP_TYPE_MAX,
>>> >  };
>>> >  
>>> > +/*
>>> > + * User space VAS windows are opened by tasks and take references
>>> > + * to pid and mm until windows are closed.
>>> > + * Stores pid, mm, and tgid for each window.
>>> > + */
>>> > +struct vas_user_win_ref {
>>> > +	struct pid *pid;	/* PID of owner */
>>> > +	struct pid *tgid;	/* Thread group ID of owner */
>>> > +	struct mm_struct *mm;	/* Linux process mm_struct */
>>> > +};
>>> > +
>>> >  /*
>>> >   * User space window operations used for powernv and powerVM
>>> >   */
>>> > @@ -59,6 +73,16 @@ struct vas_user_win_ops {
>>> >  	int (*close_win)(void *);
>>> >  };
>>> >  
>>> > +static inline void vas_drop_reference_pid_mm(struct
>>> > vas_user_win_ref *ref)
>>> > +{
>>> > +	/* Drop references to pid and mm */
>>> > +	put_pid(ref->pid);
>>> > +	if (ref->mm) {
>>> > +		mm_context_remove_vas_window(ref->mm);
>>> > +		mmdrop(ref->mm);
>>> > +	}
>>> > +}
>>> 
>>> You don't have to make up a new name for such a thing because you 
>>> already have one
>>> 
>>> put_vas_user_win_ref(struct vas_user_win_ref *ref)
>>> 
>>> 
>>> > +
>>> >  /*
>>> >   * Receive window attributes specified by the (in-kernel) owner of
>>> > window.
>>> >   */
>>> > @@ -192,4 +216,5 @@ int vas_register_coproc_api(struct module *mod,
>>> > enum vas_cop_type cop_type,
>>> >  			    struct vas_user_win_ops *vops);
>>> >  void vas_unregister_coproc_api(void);
>>> >  
>>> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref);
>>> >  #endif /* __ASM_POWERPC_VAS_H */
>>> > diff --git a/arch/powerpc/platforms/book3s/vas-api.c
>>> > b/arch/powerpc/platforms/book3s/vas-api.c
>>> > index 6c39320bfb9b..a0141bfb2e4b 100644
>>> > --- a/arch/powerpc/platforms/book3s/vas-api.c
>>> > +++ b/arch/powerpc/platforms/book3s/vas-api.c
>>> > @@ -55,6 +55,57 @@ static char *coproc_devnode(struct device *dev,
>>> > umode_t *mode)
>>> >  	return kasprintf(GFP_KERNEL, "crypto/%s", dev_name(dev));
>>> >  }
>>> >  
>>> > +/*
>>> > + * Take reference to pid and mm
>>> > + */
>>> > +int vas_reference_pid_mm(struct vas_user_win_ref *task_ref)
>>> > +{
>>> 
>>> So this is quite different from a typical refcount object in that
>>> it's 
>>> opening it for access as well. I would split it in two functions, one
>>> matching put_vas_user_win_ref() and appearing in the same place in
>>> code,
>>> which is up to about mmput and another function that adds the window
>>> and
>>> does the CP_ABORT etc... hmm, where do you release tgid?
>> 
>> Basically copied the existing code in to these functions
>> (vas_reference_pid_mm/vas_drop_reference_pid_mm) so that useful for
>> both platforms. 
>> 
>> mm_context_add/remove_vas_window() is also like taking reference. So
>> instead of adding 2 seperate functions, how about naming
>> get/put_vas_user_win_ref() 
> 
> It's actually different though. What I'm asking is the parts where you 
> interact with core kernel data structure refcounts go into their own 
> get/put functions.
> 
> Someone who understands that refcounting and looks at the code will care 
> about those bits, so having them all together I think is helpful. They 
> don't know about adding vas windows or CP_ABORT.
> 
>> Regarding tgid, the reference is taking only with pid, but not tgid.
>> pid reuse can happen only in the case of multithread applications when
>> the child that opened VAS window exits. But these windows will be
>> closed when tgid exists. So do not need tgid reference.
> 
> I don't understand you.  The code you added does take a reference to 
> tgid...
> 
>>> > +	/*
>>> > +	 * Window opened by a child thread may not be closed when
>>> > +	 * it exits. So take reference to its pid and release it
>>> > +	 * when the window is free by parent thread.
>>> > +	 * Acquire a reference to the task's pid to make sure
>>> > +	 * pid will not be re-used - needed only for multithread
>>> > +	 * applications.
>>> > +	 */
>>> > +	task_ref->pid = get_task_pid(current, PIDTYPE_PID);

Quoted the wrong bit obviously:

+       /*
+        * Process closes window during exit. In the case of
+        * multithread application, the child thread can open
+        * window and can exit without closing it. Expects parent
+        * thread to use and close the window. So do not need
+        * to take pid reference for parent thread.
+        */
+       task_ref->tgid = find_get_pid(task_tgid_vnr(current));

aka vas_tx_win_open() in upstream code.

It's not a comment about this patch specificlaly, I just noticed it and 
I wanted to make sure I'm not missing somehting or the existing code 
isn't buggy before the patch goes in.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 86+ messages in thread

end of thread, other threads:[~2021-06-05  3:04 UTC | newest]

Thread overview: 86+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21  9:25 [PATCH v4 00/16] Enable VAS and NX-GZIP support on powerVM Haren Myneni
2021-05-21  9:25 ` Haren Myneni
2021-05-21  9:28 ` [PATCH v4 01/16] powerpc/vas: Move VAS API to book3s common platform Haren Myneni
2021-05-21  9:28   ` Haren Myneni
2021-06-03  3:32   ` Nicholas Piggin
2021-06-03  3:32     ` Nicholas Piggin
2021-06-03 20:23     ` Haren Myneni
2021-06-03 20:23       ` Haren Myneni
2021-05-21  9:29 ` [PATCH v4 02/16] powerpc/powernv/vas: Rename register/unregister functions Haren Myneni
2021-05-21  9:29   ` Haren Myneni
2021-05-21  9:30 ` [PATCH v4 03/16] powerpc/vas: Add platform specific user window operations Haren Myneni
2021-05-21  9:30   ` Haren Myneni
2021-06-03  4:05   ` Nicholas Piggin
2021-06-03  4:05     ` Nicholas Piggin
2021-06-03 20:25     ` Haren Myneni
2021-06-03 20:25       ` Haren Myneni
2021-05-21  9:31 ` [PATCH v4 04/16] powerpc/vas: Create take/drop pid and mm references Haren Myneni
2021-05-21  9:31   ` Haren Myneni
2021-06-03  4:21   ` Nicholas Piggin
2021-06-03  4:21     ` Nicholas Piggin
2021-06-04  4:08     ` Haren Myneni
2021-06-04  4:08       ` Haren Myneni
2021-06-05  0:31       ` Nicholas Piggin
2021-06-05  0:31         ` Nicholas Piggin
2021-06-05  3:03         ` Nicholas Piggin
2021-06-05  3:03           ` Nicholas Piggin
2021-05-21  9:32 ` [PATCH v4 05/16] powerpc/vas: Move update_csb/dump_crb to common book3s platform Haren Myneni
2021-05-21  9:32   ` Haren Myneni
2021-06-03  4:26   ` Nicholas Piggin
2021-06-03  4:26     ` Nicholas Piggin
2021-05-21  9:33 ` [PATCH v4 06/16] powerpc/vas: Define and use common vas_window struct Haren Myneni
2021-05-21  9:33   ` Haren Myneni
2021-06-03  4:38   ` Nicholas Piggin
2021-06-03  4:38     ` Nicholas Piggin
2021-06-04  4:35     ` Haren Myneni
2021-06-04  4:35       ` Haren Myneni
2021-06-04 11:52       ` Michael Ellerman
2021-06-04 11:52         ` Michael Ellerman
2021-06-04 21:19         ` Haren Myneni
2021-06-04 21:19           ` Haren Myneni
2021-05-21  9:34 ` [PATCH v4 07/16] powerpc/pseries/vas: Define VAS/NXGZIP HCALLs and structs Haren Myneni
2021-05-21  9:34   ` Haren Myneni
2021-06-03  4:47   ` Nicholas Piggin
2021-06-03  4:47     ` Nicholas Piggin
2021-06-04  1:30     ` Haren Myneni
2021-06-04  1:30       ` Haren Myneni
2021-06-05  0:37       ` Nicholas Piggin
2021-06-05  0:37         ` Nicholas Piggin
2021-05-21  9:34 ` [PATCH v4 08/16] powerpc/vas: Define QoS credit flag to allocate window Haren Myneni
2021-05-21  9:34   ` Haren Myneni
2021-05-21  9:35 ` [PATCH v4 09/16] powerpc/pseries/vas: Add HCALL wrappers for VAS handling Haren Myneni
2021-05-21  9:35   ` Haren Myneni
2021-06-04 11:52   ` Michael Ellerman
2021-06-04 11:52     ` Michael Ellerman
2021-06-04 21:53     ` Haren Myneni
2021-06-04 21:53       ` Haren Myneni
2021-05-21  9:38 ` [PATCH v4 10/16] powerpc/pseries/vas: Implement getting capabilities from hypervisor Haren Myneni
2021-05-21  9:38   ` Haren Myneni
2021-05-21  9:39 ` [PATCH v4 11/16] powerpc/pseries/vas: Integrate API with open/close windows Haren Myneni
2021-05-21  9:39   ` Haren Myneni
2021-05-21  9:39 ` [PATCH v4 12/16] powerpc/pseries/vas: Setup IRQ and fault handling Haren Myneni
2021-05-21  9:39   ` Haren Myneni
2021-06-03  5:48   ` Nicholas Piggin
2021-06-03  5:48     ` Nicholas Piggin
2021-06-04  1:19     ` Haren Myneni
2021-06-04  1:19       ` Haren Myneni
2021-06-05  0:43       ` Nicholas Piggin
2021-06-05  0:43         ` Nicholas Piggin
2021-05-21  9:40 ` [PATCH v4 13/16] crypto/nx: Rename nx-842-pseries file name to nx-common-pseries Haren Myneni
2021-05-21  9:40   ` Haren Myneni
2021-05-21  9:41 ` [PATCH v4 14/16] crypto/nx: Register and unregister VAS interface Haren Myneni
2021-05-21  9:41   ` Haren Myneni
2021-06-03  4:59   ` Nicholas Piggin
2021-06-03  4:59     ` Nicholas Piggin
2021-05-21  9:41 ` [PATCH v4 15/16] crypto/nx: Get NX capabilities for GZIP coprocessor type Haren Myneni
2021-05-21  9:41   ` Haren Myneni
2021-05-21  9:42 ` [PATCH v4 16/16] crypto/nx: Add sysfs interface to export NX capabilities Haren Myneni
2021-05-21  9:42   ` Haren Myneni
2021-06-03  4:57   ` Nicholas Piggin
2021-06-03  4:57     ` Nicholas Piggin
2021-06-04  1:02     ` Haren Myneni
2021-06-04  1:02       ` Haren Myneni
2021-06-04 11:52       ` Michael Ellerman
2021-06-04 11:52         ` Michael Ellerman
2021-06-04 17:23         ` Haren Myneni
2021-06-04 17:23           ` Haren Myneni

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.