All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 kvmtool 00/11] arm64: Improve PMU support on heterogeneous systems
@ 2022-04-12 13:32 ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

The series can be found at [1].

The series adds support for the KVM_ARM_VCPU_PMU_V3_SET_PMU PMU attribute,
which allows userspace to set a PMU for a VCPU. This PMU is used by KVM
when creating perf events to emulate the guest PMU.

Without settings this attribute, the PMU used when creating events is the
first one that successfully probed when booting, but this is unreliable as
the probe order can change (if the order of the PMUs is changed in the DTB
or if asynchronous driver probing is enabled on the host's command line),
and furthermore it requires the user to have intimate knowledge of how the
PMU was chosen in order to pin the VM on the correct physical CPUs.

With KVM_ARM_VCPU_PMU_V3_SET_PMU, the user is still expected to pin the
VCPUs on a particular set of CPUs, but now it can be any CPUs as long as
they share the same PMU. The set does not depend anymore on the driver
probe order and all that is necessary for the user to know is which CPUs
share the same PMU, which I believe is a more reasonable expectation for
the average user. Pinning the VCPU threads on the desired CPUs can be done
using two methods:

1. By pinning the kvmtool process using taskset.

2. By pinning only the VCPU threads using the kvmtool command line argument
--vcpu-affinity, which this series introduces.

Regarding method #1, the series has the potential to break users of kvmtool
on heterogeneous systems. For example, launching kvmtool like this:

./lkvm run -c2 -m512 -k <kernel> -d <disk> --pmu

will exit with an error when Linux migrates a VCPU thread to a physical CPU
which has a different PMU than the PMU associated with the main thread when
the emulated PMU has been set for the entire VM. I believe this is an
improvement over the current behaviour for two reasons:

* PMU events would have stopped working anyway when the thread migration
  happens, but now KVM kills the VM instead of events silently stopping.
  This can save someone a lot of time and pain debugging the VM.

* Using taskset to pin kvmtool to a set of CPUs which have a particular PMU
  now works.

However, I understand that breaking existing scripts/use cases might not be
desirable, and if requested I can change the series to set the PMU only
when --vcpu-affinity is specified and preserve the current behaviour.

Patches #1-#3 are fixes and can be taken independently of this series.

Patches #4-#7 move the PMU code to aarch64, where it belongs, because the
PMU has never been supported on KVM for arm. This also paves the way for
pulling in the KVM_ARM_VCPU_PMU_V3_SET_PMU attribute, which was not defined
for KVM for arm (when KVM supported arm). This also can be merged right
now, independently of the other patches.

Patch #8 adds the cpumask_* functions which are necessary for subsequent
patches.

Patch #10 adds basic support for KVM_ARM_VCPU_PMU_V3_SET_PMU; the user is
still expected to use taskset to pin the entire VM to the correct CPUs.

Patch #11 expands on #10 by adding the --vcpu-affinity command line
argument to pin VCPUs to the correct CPUs without pinning the rest of the
kvmtool threads.

Changes from v2:

* Patch #3 (" arm/arm64: pmu.h: Add missing header guards") is new.
* Use __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ as per C preprocessor
  common predefined macros [2].
* Do not die if kvmtool is not able to find a PMU associated with the CPUs
  specified by the user with --vcpu-affinity. There are valid reasons for
  someone to do this (like testing what happens with the default PMU, or
  what happens to a guest when PMU events are not working, etc).
* Updated --pmu help text to explain how the PMU is chosen.
* Minor cosmetic fixes.

Changes from v1:

* Patch #2 ("bitops.h: Include wordsize.h to provide the __WORDSIZE
  define") is new.
* Added for_each_cpu(), cpumask_and() and cpumask_subset() functions and
  all the cpumask_* functions are added in one patch.
* Bumped NR_CPUS fro arm64 to 4096 to match the Linux Kconfig option.
* Reworked the way kvmtool specific header files were included to use
  quotes to clearly differentiate them from the system level headers and to
  keep the style consistent with the current code (for example, #include
  <linux/bitops.h> is now "linux/bitops.h").
* Patch #10 ("arm64: Add --vcpu-affinity command line argument") is new.

[1] https://gitlab.arm.com/linux-arm/kvmtool-ae/-/tree/pmu-big-little-fix-v3
[2] https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html

Alexandru Elisei (11):
  linux/err.h: Add missing stdbool.h include
  linux/bitops.h: Include wordsize.h to provide the __WORDSIZE define
  arm/arm64: pmu.h: Add missing header guards
  arm: Move arch specific VCPU features to the arch specific function
  arm: Get rid of the ARM_VCPU_FEATURE_FLAGS() macro
  arm: Make the PMUv3 emulation code arm64 specific
  arm64: Rework set_pmu_attr()
  Add cpumask functions
  update_headers.sh: Sync ABI headers with Linux v5.18-rc2
  arm64: Add support for KVM_ARM_VCPU_PMU_V3_SET_PMU
  arm64: Add --vcpu-affinity command line argument

 Makefile                                      |   8 +-
 arm/aarch32/include/asm/kernel.h              |   8 +
 arm/aarch32/include/kvm/kvm-cpu-arch.h        |   4 -
 arm/aarch64/arm-cpu.c                         |   3 +-
 arm/aarch64/include/asm/kernel.h              |   8 +
 arm/aarch64/include/asm/kvm.h                 |  11 +
 .../arm-common => aarch64/include/asm}/pmu.h  |   4 +
 arm/aarch64/include/kvm/kvm-config-arch.h     |   9 +-
 arm/aarch64/include/kvm/kvm-cpu-arch.h        |   6 -
 arm/aarch64/kvm-cpu.c                         |  21 ++
 arm/aarch64/kvm.c                             |  32 +++
 arm/aarch64/pmu.c                             | 237 ++++++++++++++++
 arm/include/arm-common/kvm-arch.h             |   7 +
 arm/include/arm-common/kvm-config-arch.h      |   1 +
 arm/kvm-cpu.c                                 |  14 +-
 arm/pmu.c                                     |  76 ------
 include/linux/bitmap.h                        |  71 +++++
 include/linux/bitops.h                        |   4 +
 include/linux/bits.h                          |   8 +
 include/linux/cpumask.h                       |  67 +++++
 include/linux/err.h                           |   2 +
 include/linux/find.h                          |  30 ++
 include/linux/kernel.h                        |   6 +
 include/linux/kvm.h                           |  15 +-
 mips/include/asm/kernel.h                     |   8 +
 powerpc/include/asm/kernel.h                  |   8 +
 util/bitmap.c                                 | 256 ++++++++++++++++++
 util/find.c                                   |  40 +++
 x86/include/asm/kernel.h                      |   8 +
 29 files changed, 870 insertions(+), 102 deletions(-)
 create mode 100644 arm/aarch32/include/asm/kernel.h
 create mode 100644 arm/aarch64/include/asm/kernel.h
 rename arm/{include/arm-common => aarch64/include/asm}/pmu.h (55%)
 create mode 100644 arm/aarch64/pmu.c
 delete mode 100644 arm/pmu.c
 create mode 100644 include/linux/bitmap.h
 create mode 100644 include/linux/bits.h
 create mode 100644 include/linux/cpumask.h
 create mode 100644 include/linux/find.h
 create mode 100644 mips/include/asm/kernel.h
 create mode 100644 powerpc/include/asm/kernel.h
 create mode 100644 util/bitmap.c
 create mode 100644 util/find.c
 create mode 100644 x86/include/asm/kernel.h

-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 00/11] arm64: Improve PMU support on heterogeneous systems
@ 2022-04-12 13:32 ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

The series can be found at [1].

The series adds support for the KVM_ARM_VCPU_PMU_V3_SET_PMU PMU attribute,
which allows userspace to set a PMU for a VCPU. This PMU is used by KVM
when creating perf events to emulate the guest PMU.

Without settings this attribute, the PMU used when creating events is the
first one that successfully probed when booting, but this is unreliable as
the probe order can change (if the order of the PMUs is changed in the DTB
or if asynchronous driver probing is enabled on the host's command line),
and furthermore it requires the user to have intimate knowledge of how the
PMU was chosen in order to pin the VM on the correct physical CPUs.

With KVM_ARM_VCPU_PMU_V3_SET_PMU, the user is still expected to pin the
VCPUs on a particular set of CPUs, but now it can be any CPUs as long as
they share the same PMU. The set does not depend anymore on the driver
probe order and all that is necessary for the user to know is which CPUs
share the same PMU, which I believe is a more reasonable expectation for
the average user. Pinning the VCPU threads on the desired CPUs can be done
using two methods:

1. By pinning the kvmtool process using taskset.

2. By pinning only the VCPU threads using the kvmtool command line argument
--vcpu-affinity, which this series introduces.

Regarding method #1, the series has the potential to break users of kvmtool
on heterogeneous systems. For example, launching kvmtool like this:

./lkvm run -c2 -m512 -k <kernel> -d <disk> --pmu

will exit with an error when Linux migrates a VCPU thread to a physical CPU
which has a different PMU than the PMU associated with the main thread when
the emulated PMU has been set for the entire VM. I believe this is an
improvement over the current behaviour for two reasons:

* PMU events would have stopped working anyway when the thread migration
  happens, but now KVM kills the VM instead of events silently stopping.
  This can save someone a lot of time and pain debugging the VM.

* Using taskset to pin kvmtool to a set of CPUs which have a particular PMU
  now works.

However, I understand that breaking existing scripts/use cases might not be
desirable, and if requested I can change the series to set the PMU only
when --vcpu-affinity is specified and preserve the current behaviour.

Patches #1-#3 are fixes and can be taken independently of this series.

Patches #4-#7 move the PMU code to aarch64, where it belongs, because the
PMU has never been supported on KVM for arm. This also paves the way for
pulling in the KVM_ARM_VCPU_PMU_V3_SET_PMU attribute, which was not defined
for KVM for arm (when KVM supported arm). This also can be merged right
now, independently of the other patches.

Patch #8 adds the cpumask_* functions which are necessary for subsequent
patches.

Patch #10 adds basic support for KVM_ARM_VCPU_PMU_V3_SET_PMU; the user is
still expected to use taskset to pin the entire VM to the correct CPUs.

Patch #11 expands on #10 by adding the --vcpu-affinity command line
argument to pin VCPUs to the correct CPUs without pinning the rest of the
kvmtool threads.

Changes from v2:

* Patch #3 (" arm/arm64: pmu.h: Add missing header guards") is new.
* Use __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ as per C preprocessor
  common predefined macros [2].
* Do not die if kvmtool is not able to find a PMU associated with the CPUs
  specified by the user with --vcpu-affinity. There are valid reasons for
  someone to do this (like testing what happens with the default PMU, or
  what happens to a guest when PMU events are not working, etc).
* Updated --pmu help text to explain how the PMU is chosen.
* Minor cosmetic fixes.

Changes from v1:

* Patch #2 ("bitops.h: Include wordsize.h to provide the __WORDSIZE
  define") is new.
* Added for_each_cpu(), cpumask_and() and cpumask_subset() functions and
  all the cpumask_* functions are added in one patch.
* Bumped NR_CPUS fro arm64 to 4096 to match the Linux Kconfig option.
* Reworked the way kvmtool specific header files were included to use
  quotes to clearly differentiate them from the system level headers and to
  keep the style consistent with the current code (for example, #include
  <linux/bitops.h> is now "linux/bitops.h").
* Patch #10 ("arm64: Add --vcpu-affinity command line argument") is new.

[1] https://gitlab.arm.com/linux-arm/kvmtool-ae/-/tree/pmu-big-little-fix-v3
[2] https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html

Alexandru Elisei (11):
  linux/err.h: Add missing stdbool.h include
  linux/bitops.h: Include wordsize.h to provide the __WORDSIZE define
  arm/arm64: pmu.h: Add missing header guards
  arm: Move arch specific VCPU features to the arch specific function
  arm: Get rid of the ARM_VCPU_FEATURE_FLAGS() macro
  arm: Make the PMUv3 emulation code arm64 specific
  arm64: Rework set_pmu_attr()
  Add cpumask functions
  update_headers.sh: Sync ABI headers with Linux v5.18-rc2
  arm64: Add support for KVM_ARM_VCPU_PMU_V3_SET_PMU
  arm64: Add --vcpu-affinity command line argument

 Makefile                                      |   8 +-
 arm/aarch32/include/asm/kernel.h              |   8 +
 arm/aarch32/include/kvm/kvm-cpu-arch.h        |   4 -
 arm/aarch64/arm-cpu.c                         |   3 +-
 arm/aarch64/include/asm/kernel.h              |   8 +
 arm/aarch64/include/asm/kvm.h                 |  11 +
 .../arm-common => aarch64/include/asm}/pmu.h  |   4 +
 arm/aarch64/include/kvm/kvm-config-arch.h     |   9 +-
 arm/aarch64/include/kvm/kvm-cpu-arch.h        |   6 -
 arm/aarch64/kvm-cpu.c                         |  21 ++
 arm/aarch64/kvm.c                             |  32 +++
 arm/aarch64/pmu.c                             | 237 ++++++++++++++++
 arm/include/arm-common/kvm-arch.h             |   7 +
 arm/include/arm-common/kvm-config-arch.h      |   1 +
 arm/kvm-cpu.c                                 |  14 +-
 arm/pmu.c                                     |  76 ------
 include/linux/bitmap.h                        |  71 +++++
 include/linux/bitops.h                        |   4 +
 include/linux/bits.h                          |   8 +
 include/linux/cpumask.h                       |  67 +++++
 include/linux/err.h                           |   2 +
 include/linux/find.h                          |  30 ++
 include/linux/kernel.h                        |   6 +
 include/linux/kvm.h                           |  15 +-
 mips/include/asm/kernel.h                     |   8 +
 powerpc/include/asm/kernel.h                  |   8 +
 util/bitmap.c                                 | 256 ++++++++++++++++++
 util/find.c                                   |  40 +++
 x86/include/asm/kernel.h                      |   8 +
 29 files changed, 870 insertions(+), 102 deletions(-)
 create mode 100644 arm/aarch32/include/asm/kernel.h
 create mode 100644 arm/aarch64/include/asm/kernel.h
 rename arm/{include/arm-common => aarch64/include/asm}/pmu.h (55%)
 create mode 100644 arm/aarch64/pmu.c
 delete mode 100644 arm/pmu.c
 create mode 100644 include/linux/bitmap.h
 create mode 100644 include/linux/bits.h
 create mode 100644 include/linux/cpumask.h
 create mode 100644 include/linux/find.h
 create mode 100644 mips/include/asm/kernel.h
 create mode 100644 powerpc/include/asm/kernel.h
 create mode 100644 util/bitmap.c
 create mode 100644 util/find.c
 create mode 100644 x86/include/asm/kernel.h

-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 01/11] linux/err.h: Add missing stdbool.h include
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Add missing header stdbool.h to avoid errors like this one, which can
happen if the including file doesn't include stdbool.h:

include/linux/err.h:33:15: error: type defaults to ‘int’ in declaration of ‘bool’ [-Werror=implicit-int]
   33 | static inline bool __must_check IS_ERR(__force const void *ptr)
      |               ^~~~
include/linux/err.h:33:15: error: variable ‘bool’ declared ‘inline’ [-Werror]
include/linux/err.h:33:1: error: ‘warn_unused_result’ attribute only applies to function types [-Werror=attributes]
   33 | static inline bool __must_check IS_ERR(__force const void *ptr)
      | ^~~~~~
include/linux/err.h:33:33: error: expected ‘,’ or ‘;’ before ‘IS_ERR’
   33 | static inline bool __must_check IS_ERR(__force const void *ptr)
      |                                 ^~~~~~
include/linux/err.h:38:15: error: type defaults to ‘int’ in declaration of ‘bool’ [-Werror=implicit-int]
   38 | static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
      |               ^~~~
include/linux/err.h:38:15: error: variable ‘bool’ declared ‘inline’ [-Werror]
include/linux/err.h:38:1: error: ‘warn_unused_result’ attribute only applies to function types [-Werror=attributes]
   38 | static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
      | ^~~~~~
include/linux/err.h:38:15: error: redundant redeclaration of ‘bool’ [-Werror=redundant-decls]
   38 | static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
      |               ^~~~
include/linux/err.h:33:15: note: previous declaration of ‘bool’ was here
   33 | static inline bool __must_check IS_ERR(__force const void *ptr)
      |               ^~~~
include/linux/err.h:38:33: error: expected ‘,’ or ‘;’ before ‘IS_ERR_OR_NULL’
   38 | static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
      |                                 ^~~~~~~~~~~~~~
include/linux/err.h: In function ‘PTR_ERR_OR_ZERO’:
include/linux/err.h:58:6: error: implicit declaration of function ‘IS_ERR’ [-Werror=implicit-function-declaration]
   58 |  if (IS_ERR(ptr))
      |      ^~~~~~
include/linux/err.h:58:6: error: nested extern declaration of ‘IS_ERR’ [-Werror=nested-externs]

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 include/linux/err.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/err.h b/include/linux/err.h
index a729120644d5..1256c7abfefa 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -1,6 +1,8 @@
 #ifndef _LINUX_ERR_H
 #define _LINUX_ERR_H
 
+#include <stdbool.h>
+
 #include <linux/compiler.h>
 #include <linux/types.h>
 
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 01/11] linux/err.h: Add missing stdbool.h include
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Add missing header stdbool.h to avoid errors like this one, which can
happen if the including file doesn't include stdbool.h:

include/linux/err.h:33:15: error: type defaults to ‘int’ in declaration of ‘bool’ [-Werror=implicit-int]
   33 | static inline bool __must_check IS_ERR(__force const void *ptr)
      |               ^~~~
include/linux/err.h:33:15: error: variable ‘bool’ declared ‘inline’ [-Werror]
include/linux/err.h:33:1: error: ‘warn_unused_result’ attribute only applies to function types [-Werror=attributes]
   33 | static inline bool __must_check IS_ERR(__force const void *ptr)
      | ^~~~~~
include/linux/err.h:33:33: error: expected ‘,’ or ‘;’ before ‘IS_ERR’
   33 | static inline bool __must_check IS_ERR(__force const void *ptr)
      |                                 ^~~~~~
include/linux/err.h:38:15: error: type defaults to ‘int’ in declaration of ‘bool’ [-Werror=implicit-int]
   38 | static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
      |               ^~~~
include/linux/err.h:38:15: error: variable ‘bool’ declared ‘inline’ [-Werror]
include/linux/err.h:38:1: error: ‘warn_unused_result’ attribute only applies to function types [-Werror=attributes]
   38 | static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
      | ^~~~~~
include/linux/err.h:38:15: error: redundant redeclaration of ‘bool’ [-Werror=redundant-decls]
   38 | static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
      |               ^~~~
include/linux/err.h:33:15: note: previous declaration of ‘bool’ was here
   33 | static inline bool __must_check IS_ERR(__force const void *ptr)
      |               ^~~~
include/linux/err.h:38:33: error: expected ‘,’ or ‘;’ before ‘IS_ERR_OR_NULL’
   38 | static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
      |                                 ^~~~~~~~~~~~~~
include/linux/err.h: In function ‘PTR_ERR_OR_ZERO’:
include/linux/err.h:58:6: error: implicit declaration of function ‘IS_ERR’ [-Werror=implicit-function-declaration]
   58 |  if (IS_ERR(ptr))
      |      ^~~~~~
include/linux/err.h:58:6: error: nested extern declaration of ‘IS_ERR’ [-Werror=nested-externs]

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 include/linux/err.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/err.h b/include/linux/err.h
index a729120644d5..1256c7abfefa 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -1,6 +1,8 @@
 #ifndef _LINUX_ERR_H
 #define _LINUX_ERR_H
 
+#include <stdbool.h>
+
 #include <linux/compiler.h>
 #include <linux/types.h>
 
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 02/11] linux/bitops.h: Include wordsize.h to provide the __WORDSIZE define
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Trying to build a source file which included bitops.h, but didn't also
bring in the definition for __WORDSIZE (by including limits.h, for example)
would result in the following error:

include/linux/bitops.h:8:23: error: ‘__WORDSIZE’ undeclared (first use in this function)
    8 | #define BITS_PER_LONG __WORDSIZE
      |                       ^~~~~~~~~~

The symbol is defined in the bits/wordsize.h header file, include it.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 include/linux/bitops.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 56448b71ebbf..3d31f0acf48e 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -1,6 +1,8 @@
 #ifndef _KVM_LINUX_BITOPS_H_
 #define _KVM_LINUX_BITOPS_H_
 
+#include <bits/wordsize.h>
+
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <asm/hweight.h>
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 02/11] linux/bitops.h: Include wordsize.h to provide the __WORDSIZE define
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Trying to build a source file which included bitops.h, but didn't also
bring in the definition for __WORDSIZE (by including limits.h, for example)
would result in the following error:

include/linux/bitops.h:8:23: error: ‘__WORDSIZE’ undeclared (first use in this function)
    8 | #define BITS_PER_LONG __WORDSIZE
      |                       ^~~~~~~~~~

The symbol is defined in the bits/wordsize.h header file, include it.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 include/linux/bitops.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 56448b71ebbf..3d31f0acf48e 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -1,6 +1,8 @@
 #ifndef _KVM_LINUX_BITOPS_H_
 #define _KVM_LINUX_BITOPS_H_
 
+#include <bits/wordsize.h>
+
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <asm/hweight.h>
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 03/11] arm/arm64: pmu.h: Add missing header guards
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/include/arm-common/pmu.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arm/include/arm-common/pmu.h b/arm/include/arm-common/pmu.h
index 7a170a56dadd..0085f2545553 100644
--- a/arm/include/arm-common/pmu.h
+++ b/arm/include/arm-common/pmu.h
@@ -1,4 +1,8 @@
+#ifndef ARM_COMMON__PMU_H
+#define ARM_COMMON__PMU_H
 
 #define KVM_ARM_PMUv3_PPI			23
 
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm);
+
+#endif /* ARM_COMMON__PMU_H */
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 03/11] arm/arm64: pmu.h: Add missing header guards
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/include/arm-common/pmu.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arm/include/arm-common/pmu.h b/arm/include/arm-common/pmu.h
index 7a170a56dadd..0085f2545553 100644
--- a/arm/include/arm-common/pmu.h
+++ b/arm/include/arm-common/pmu.h
@@ -1,4 +1,8 @@
+#ifndef ARM_COMMON__PMU_H
+#define ARM_COMMON__PMU_H
 
 #define KVM_ARM_PMUv3_PPI			23
 
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm);
+
+#endif /* ARM_COMMON__PMU_H */
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 04/11] arm: Move arch specific VCPU features to the arch specific function
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

KVM_CAP_ARM_EL1_32BIT and KVM_CAP_ARM_PMU_V3 are arm64 specific features.
They are set based on arm64 specific command line options and they target
arm64 hardware features. It makes little sense for kvmtool to set the
features in the code that is shared between arm and arm64. Move the logic
to set the feature bits to the arch specific function
kvm_cpu__select_features(), which is already used by arm64 to set other
arm64 specific features.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/include/kvm/kvm-cpu-arch.h |  4 +---
 arm/aarch64/kvm-cpu.c                  | 12 ++++++++++++
 arm/kvm-cpu.c                          |  8 --------
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/arm/aarch64/include/kvm/kvm-cpu-arch.h b/arm/aarch64/include/kvm/kvm-cpu-arch.h
index 35996dc0a0d6..4cbadf9175d8 100644
--- a/arm/aarch64/include/kvm/kvm-cpu-arch.h
+++ b/arm/aarch64/include/kvm/kvm-cpu-arch.h
@@ -6,9 +6,7 @@
 #include "arm-common/kvm-cpu-arch.h"
 
 #define ARM_VCPU_FEATURE_FLAGS(kvm, cpuid)	{				\
-	[0] = ((!!(cpuid) << KVM_ARM_VCPU_POWER_OFF) |				\
-	       (!!(kvm)->cfg.arch.aarch32_guest << KVM_ARM_VCPU_EL1_32BIT) |	\
-	       (!!(kvm)->cfg.arch.has_pmuv3 << KVM_ARM_VCPU_PMU_V3))		\
+	[0] = (!!(cpuid) << KVM_ARM_VCPU_POWER_OFF),				\
 }
 
 #define ARM_MPIDR_HWID_BITMASK	0xFF00FFFFFFUL
diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c
index 9f3e8586880c..3b6224a599c8 100644
--- a/arm/aarch64/kvm-cpu.c
+++ b/arm/aarch64/kvm-cpu.c
@@ -130,6 +130,18 @@ static void reset_vcpu_aarch64(struct kvm_cpu *vcpu)
 
 void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init *init)
 {
+	if (kvm->cfg.arch.aarch32_guest) {
+		if (!kvm__supports_extension(kvm, KVM_CAP_ARM_EL1_32BIT))
+			die("32bit guests are not supported\n");
+		init->features[0] |= 1UL << KVM_ARM_VCPU_EL1_32BIT;
+	}
+
+	if (kvm->cfg.arch.has_pmuv3) {
+		if (!kvm__supports_extension(kvm, KVM_CAP_ARM_PMU_V3))
+			die("PMUv3 is not supported");
+		init->features[0] |= 1UL << KVM_ARM_VCPU_PMU_V3;
+	}
+
 	/* Enable pointer authentication if available */
 	if (kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_ADDRESS) &&
 	    kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_GENERIC)) {
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 00660d6e7a97..3a5c8a5a8e31 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -46,14 +46,6 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 		.features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
 	};
 
-	if (kvm->cfg.arch.aarch32_guest &&
-	    !kvm__supports_extension(kvm, KVM_CAP_ARM_EL1_32BIT))
-		die("32bit guests are not supported\n");
-
-	if (kvm->cfg.arch.has_pmuv3 &&
-	    !kvm__supports_extension(kvm, KVM_CAP_ARM_PMU_V3))
-		die("PMUv3 is not supported");
-
 	vcpu = calloc(1, sizeof(struct kvm_cpu));
 	if (!vcpu)
 		return NULL;
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 04/11] arm: Move arch specific VCPU features to the arch specific function
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

KVM_CAP_ARM_EL1_32BIT and KVM_CAP_ARM_PMU_V3 are arm64 specific features.
They are set based on arm64 specific command line options and they target
arm64 hardware features. It makes little sense for kvmtool to set the
features in the code that is shared between arm and arm64. Move the logic
to set the feature bits to the arch specific function
kvm_cpu__select_features(), which is already used by arm64 to set other
arm64 specific features.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/include/kvm/kvm-cpu-arch.h |  4 +---
 arm/aarch64/kvm-cpu.c                  | 12 ++++++++++++
 arm/kvm-cpu.c                          |  8 --------
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/arm/aarch64/include/kvm/kvm-cpu-arch.h b/arm/aarch64/include/kvm/kvm-cpu-arch.h
index 35996dc0a0d6..4cbadf9175d8 100644
--- a/arm/aarch64/include/kvm/kvm-cpu-arch.h
+++ b/arm/aarch64/include/kvm/kvm-cpu-arch.h
@@ -6,9 +6,7 @@
 #include "arm-common/kvm-cpu-arch.h"
 
 #define ARM_VCPU_FEATURE_FLAGS(kvm, cpuid)	{				\
-	[0] = ((!!(cpuid) << KVM_ARM_VCPU_POWER_OFF) |				\
-	       (!!(kvm)->cfg.arch.aarch32_guest << KVM_ARM_VCPU_EL1_32BIT) |	\
-	       (!!(kvm)->cfg.arch.has_pmuv3 << KVM_ARM_VCPU_PMU_V3))		\
+	[0] = (!!(cpuid) << KVM_ARM_VCPU_POWER_OFF),				\
 }
 
 #define ARM_MPIDR_HWID_BITMASK	0xFF00FFFFFFUL
diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c
index 9f3e8586880c..3b6224a599c8 100644
--- a/arm/aarch64/kvm-cpu.c
+++ b/arm/aarch64/kvm-cpu.c
@@ -130,6 +130,18 @@ static void reset_vcpu_aarch64(struct kvm_cpu *vcpu)
 
 void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init *init)
 {
+	if (kvm->cfg.arch.aarch32_guest) {
+		if (!kvm__supports_extension(kvm, KVM_CAP_ARM_EL1_32BIT))
+			die("32bit guests are not supported\n");
+		init->features[0] |= 1UL << KVM_ARM_VCPU_EL1_32BIT;
+	}
+
+	if (kvm->cfg.arch.has_pmuv3) {
+		if (!kvm__supports_extension(kvm, KVM_CAP_ARM_PMU_V3))
+			die("PMUv3 is not supported");
+		init->features[0] |= 1UL << KVM_ARM_VCPU_PMU_V3;
+	}
+
 	/* Enable pointer authentication if available */
 	if (kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_ADDRESS) &&
 	    kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_GENERIC)) {
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 00660d6e7a97..3a5c8a5a8e31 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -46,14 +46,6 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 		.features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
 	};
 
-	if (kvm->cfg.arch.aarch32_guest &&
-	    !kvm__supports_extension(kvm, KVM_CAP_ARM_EL1_32BIT))
-		die("32bit guests are not supported\n");
-
-	if (kvm->cfg.arch.has_pmuv3 &&
-	    !kvm__supports_extension(kvm, KVM_CAP_ARM_PMU_V3))
-		die("PMUv3 is not supported");
-
 	vcpu = calloc(1, sizeof(struct kvm_cpu));
 	if (!vcpu)
 		return NULL;
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 05/11] arm: Get rid of the ARM_VCPU_FEATURE_FLAGS() macro
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

The ARM_VCPU_FEATURE_FLAGS() macro sets a feature bit in a rather
convoluted way: if cpu_id is 0, then bit KVM_ARM_VCPU_POWER_OFF is 0,
otherwise is set to 1. There's really no need for this indirection,
especially considering that the macro has been changed to return the same
value for both the arm and arm64 architectures. Replace it with a simple
conditional statement in kvm_cpu__arch_init(), which makes it clearer to
understand.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch32/include/kvm/kvm-cpu-arch.h | 4 ----
 arm/aarch64/include/kvm/kvm-cpu-arch.h | 4 ----
 arm/kvm-cpu.c                          | 6 +++++-
 3 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/arm/aarch32/include/kvm/kvm-cpu-arch.h b/arm/aarch32/include/kvm/kvm-cpu-arch.h
index 6fe020689c28..fd0b387cb539 100644
--- a/arm/aarch32/include/kvm/kvm-cpu-arch.h
+++ b/arm/aarch32/include/kvm/kvm-cpu-arch.h
@@ -5,10 +5,6 @@
 
 #include "arm-common/kvm-cpu-arch.h"
 
-#define ARM_VCPU_FEATURE_FLAGS(kvm, cpuid)	{			\
-	[0] = (!!(cpuid) << KVM_ARM_VCPU_POWER_OFF),			\
-}
-
 #define ARM_MPIDR_HWID_BITMASK	0xFFFFFF
 #define ARM_CPU_ID		0, 0, 0
 #define ARM_CPU_ID_MPIDR	5
diff --git a/arm/aarch64/include/kvm/kvm-cpu-arch.h b/arm/aarch64/include/kvm/kvm-cpu-arch.h
index 4cbadf9175d8..aeae8c138bba 100644
--- a/arm/aarch64/include/kvm/kvm-cpu-arch.h
+++ b/arm/aarch64/include/kvm/kvm-cpu-arch.h
@@ -5,10 +5,6 @@
 
 #include "arm-common/kvm-cpu-arch.h"
 
-#define ARM_VCPU_FEATURE_FLAGS(kvm, cpuid)	{				\
-	[0] = (!!(cpuid) << KVM_ARM_VCPU_POWER_OFF),				\
-}
-
 #define ARM_MPIDR_HWID_BITMASK	0xFF00FFFFFFUL
 #define ARM_CPU_ID		3, 0, 0, 0
 #define ARM_CPU_ID_MPIDR	5
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 3a5c8a5a8e31..98bc5fdf0418 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -43,7 +43,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	unsigned int i;
 	struct kvm_vcpu_init preferred_init;
 	struct kvm_vcpu_init vcpu_init = {
-		.features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
+		.features = {},
 	};
 
 	vcpu = calloc(1, sizeof(struct kvm_cpu));
@@ -63,6 +63,10 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	if (vcpu->kvm_run == MAP_FAILED)
 		die("unable to mmap vcpu fd");
 
+	/* VCPU 0 is the boot CPU, the others start in a poweroff state. */
+	if (cpu_id > 0)
+		vcpu_init.features[0] |= (1UL << KVM_ARM_VCPU_POWER_OFF);
+
 	/* Set KVM_ARM_VCPU_PSCI_0_2 if available */
 	if (kvm__supports_extension(kvm, KVM_CAP_ARM_PSCI_0_2)) {
 		vcpu_init.features[0] |= (1UL << KVM_ARM_VCPU_PSCI_0_2);
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 05/11] arm: Get rid of the ARM_VCPU_FEATURE_FLAGS() macro
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

The ARM_VCPU_FEATURE_FLAGS() macro sets a feature bit in a rather
convoluted way: if cpu_id is 0, then bit KVM_ARM_VCPU_POWER_OFF is 0,
otherwise is set to 1. There's really no need for this indirection,
especially considering that the macro has been changed to return the same
value for both the arm and arm64 architectures. Replace it with a simple
conditional statement in kvm_cpu__arch_init(), which makes it clearer to
understand.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch32/include/kvm/kvm-cpu-arch.h | 4 ----
 arm/aarch64/include/kvm/kvm-cpu-arch.h | 4 ----
 arm/kvm-cpu.c                          | 6 +++++-
 3 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/arm/aarch32/include/kvm/kvm-cpu-arch.h b/arm/aarch32/include/kvm/kvm-cpu-arch.h
index 6fe020689c28..fd0b387cb539 100644
--- a/arm/aarch32/include/kvm/kvm-cpu-arch.h
+++ b/arm/aarch32/include/kvm/kvm-cpu-arch.h
@@ -5,10 +5,6 @@
 
 #include "arm-common/kvm-cpu-arch.h"
 
-#define ARM_VCPU_FEATURE_FLAGS(kvm, cpuid)	{			\
-	[0] = (!!(cpuid) << KVM_ARM_VCPU_POWER_OFF),			\
-}
-
 #define ARM_MPIDR_HWID_BITMASK	0xFFFFFF
 #define ARM_CPU_ID		0, 0, 0
 #define ARM_CPU_ID_MPIDR	5
diff --git a/arm/aarch64/include/kvm/kvm-cpu-arch.h b/arm/aarch64/include/kvm/kvm-cpu-arch.h
index 4cbadf9175d8..aeae8c138bba 100644
--- a/arm/aarch64/include/kvm/kvm-cpu-arch.h
+++ b/arm/aarch64/include/kvm/kvm-cpu-arch.h
@@ -5,10 +5,6 @@
 
 #include "arm-common/kvm-cpu-arch.h"
 
-#define ARM_VCPU_FEATURE_FLAGS(kvm, cpuid)	{				\
-	[0] = (!!(cpuid) << KVM_ARM_VCPU_POWER_OFF),				\
-}
-
 #define ARM_MPIDR_HWID_BITMASK	0xFF00FFFFFFUL
 #define ARM_CPU_ID		3, 0, 0, 0
 #define ARM_CPU_ID_MPIDR	5
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 3a5c8a5a8e31..98bc5fdf0418 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -43,7 +43,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	unsigned int i;
 	struct kvm_vcpu_init preferred_init;
 	struct kvm_vcpu_init vcpu_init = {
-		.features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
+		.features = {},
 	};
 
 	vcpu = calloc(1, sizeof(struct kvm_cpu));
@@ -63,6 +63,10 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	if (vcpu->kvm_run == MAP_FAILED)
 		die("unable to mmap vcpu fd");
 
+	/* VCPU 0 is the boot CPU, the others start in a poweroff state. */
+	if (cpu_id > 0)
+		vcpu_init.features[0] |= (1UL << KVM_ARM_VCPU_POWER_OFF);
+
 	/* Set KVM_ARM_VCPU_PSCI_0_2 if available */
 	if (kvm__supports_extension(kvm, KVM_CAP_ARM_PSCI_0_2)) {
 		vcpu_init.features[0] |= (1UL << KVM_ARM_VCPU_PSCI_0_2);
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 06/11] arm: Make the PMUv3 emulation code arm64 specific
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

KVM for aarch32 does not exist anymore, PMUv3 is a hardware feature
present only on aarch64 CPUs, the command line option to enable the
feature for a VCPU is aarch64 specific, the PMU code is called only from
an aarch64 function and it compiles to an empty stub when ARCH=arm.
There is no reason to have the PMUv3 emulation code in the common code
area for arm and arm64, so move it to the arm64 directory, where it can
be expanded in the future without fear of breaking aarch32 support.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 Makefile                                              | 6 +++---
 arm/aarch64/arm-cpu.c                                 | 3 ++-
 arm/{include/arm-common => aarch64/include/asm}/pmu.h | 6 +++---
 arm/{ => aarch64}/pmu.c                               | 7 ++-----
 4 files changed, 10 insertions(+), 12 deletions(-)
 rename arm/{include/arm-common => aarch64/include/asm}/pmu.h (52%)
 rename arm/{ => aarch64}/pmu.c (93%)

diff --git a/Makefile b/Makefile
index e9121dc39d02..31274353656d 100644
--- a/Makefile
+++ b/Makefile
@@ -159,8 +159,7 @@ endif
 
 # ARM
 OBJS_ARM_COMMON		:= arm/fdt.o arm/gic.o arm/gicv2m.o arm/ioport.o \
-			   arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o \
-			   arm/pmu.o
+			   arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o
 HDRS_ARM_COMMON		:= arm/include
 ifeq ($(ARCH), arm)
 	DEFINES		+= -DCONFIG_ARM
@@ -183,6 +182,7 @@ ifeq ($(ARCH), arm64)
 	OBJS		+= arm/aarch64/kvm-cpu.o
 	OBJS		+= arm/aarch64/kvm.o
 	OBJS		+= arm/aarch64/pvtime.o
+	OBJS		+= arm/aarch64/pmu.o
 	ARCH_INCLUDE	:= $(HDRS_ARM_COMMON)
 	ARCH_INCLUDE	+= -Iarm/aarch64/include
 
@@ -583,4 +583,4 @@ ifneq ($(MAKECMDGOALS),clean)
 
 KVMTOOLS-VERSION-FILE:
 	@$(SHELL_PATH) util/KVMTOOLS-VERSION-GEN $(OUTPUT)
-endif
\ No newline at end of file
+endif
diff --git a/arm/aarch64/arm-cpu.c b/arm/aarch64/arm-cpu.c
index 7e4a3c17c38f..f5c8e1e7a06b 100644
--- a/arm/aarch64/arm-cpu.c
+++ b/arm/aarch64/arm-cpu.c
@@ -5,7 +5,8 @@
 
 #include "arm-common/gic.h"
 #include "arm-common/timer.h"
-#include "arm-common/pmu.h"
+
+#include "asm/pmu.h"
 
 #include <linux/byteorder.h>
 #include <linux/types.h>
diff --git a/arm/include/arm-common/pmu.h b/arm/aarch64/include/asm/pmu.h
similarity index 52%
rename from arm/include/arm-common/pmu.h
rename to arm/aarch64/include/asm/pmu.h
index 0085f2545553..38e3154b11b7 100644
--- a/arm/include/arm-common/pmu.h
+++ b/arm/aarch64/include/asm/pmu.h
@@ -1,8 +1,8 @@
-#ifndef ARM_COMMON__PMU_H
-#define ARM_COMMON__PMU_H
+#ifndef __ARM_PMU_H__
+#define __ARM_PMU_H__
 
 #define KVM_ARM_PMUv3_PPI			23
 
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm);
 
-#endif /* ARM_COMMON__PMU_H */
+#endif /* __ARM_PMU_H__ */
diff --git a/arm/pmu.c b/arm/aarch64/pmu.c
similarity index 93%
rename from arm/pmu.c
rename to arm/aarch64/pmu.c
index 5b058eabb49d..6b190c5e2ae5 100644
--- a/arm/pmu.c
+++ b/arm/aarch64/pmu.c
@@ -4,9 +4,9 @@
 #include "kvm/util.h"
 
 #include "arm-common/gic.h"
-#include "arm-common/pmu.h"
 
-#ifdef CONFIG_ARM64
+#include "asm/pmu.h"
+
 static int set_pmu_attr(struct kvm *kvm, int vcpu_idx,
 			struct kvm_device_attr *attr)
 {
@@ -71,6 +71,3 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 	_FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
 	_FDT(fdt_end_node(fdt));
 }
-#else
-void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm) { }
-#endif
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 06/11] arm: Make the PMUv3 emulation code arm64 specific
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

KVM for aarch32 does not exist anymore, PMUv3 is a hardware feature
present only on aarch64 CPUs, the command line option to enable the
feature for a VCPU is aarch64 specific, the PMU code is called only from
an aarch64 function and it compiles to an empty stub when ARCH=arm.
There is no reason to have the PMUv3 emulation code in the common code
area for arm and arm64, so move it to the arm64 directory, where it can
be expanded in the future without fear of breaking aarch32 support.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 Makefile                                              | 6 +++---
 arm/aarch64/arm-cpu.c                                 | 3 ++-
 arm/{include/arm-common => aarch64/include/asm}/pmu.h | 6 +++---
 arm/{ => aarch64}/pmu.c                               | 7 ++-----
 4 files changed, 10 insertions(+), 12 deletions(-)
 rename arm/{include/arm-common => aarch64/include/asm}/pmu.h (52%)
 rename arm/{ => aarch64}/pmu.c (93%)

diff --git a/Makefile b/Makefile
index e9121dc39d02..31274353656d 100644
--- a/Makefile
+++ b/Makefile
@@ -159,8 +159,7 @@ endif
 
 # ARM
 OBJS_ARM_COMMON		:= arm/fdt.o arm/gic.o arm/gicv2m.o arm/ioport.o \
-			   arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o \
-			   arm/pmu.o
+			   arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o
 HDRS_ARM_COMMON		:= arm/include
 ifeq ($(ARCH), arm)
 	DEFINES		+= -DCONFIG_ARM
@@ -183,6 +182,7 @@ ifeq ($(ARCH), arm64)
 	OBJS		+= arm/aarch64/kvm-cpu.o
 	OBJS		+= arm/aarch64/kvm.o
 	OBJS		+= arm/aarch64/pvtime.o
+	OBJS		+= arm/aarch64/pmu.o
 	ARCH_INCLUDE	:= $(HDRS_ARM_COMMON)
 	ARCH_INCLUDE	+= -Iarm/aarch64/include
 
@@ -583,4 +583,4 @@ ifneq ($(MAKECMDGOALS),clean)
 
 KVMTOOLS-VERSION-FILE:
 	@$(SHELL_PATH) util/KVMTOOLS-VERSION-GEN $(OUTPUT)
-endif
\ No newline at end of file
+endif
diff --git a/arm/aarch64/arm-cpu.c b/arm/aarch64/arm-cpu.c
index 7e4a3c17c38f..f5c8e1e7a06b 100644
--- a/arm/aarch64/arm-cpu.c
+++ b/arm/aarch64/arm-cpu.c
@@ -5,7 +5,8 @@
 
 #include "arm-common/gic.h"
 #include "arm-common/timer.h"
-#include "arm-common/pmu.h"
+
+#include "asm/pmu.h"
 
 #include <linux/byteorder.h>
 #include <linux/types.h>
diff --git a/arm/include/arm-common/pmu.h b/arm/aarch64/include/asm/pmu.h
similarity index 52%
rename from arm/include/arm-common/pmu.h
rename to arm/aarch64/include/asm/pmu.h
index 0085f2545553..38e3154b11b7 100644
--- a/arm/include/arm-common/pmu.h
+++ b/arm/aarch64/include/asm/pmu.h
@@ -1,8 +1,8 @@
-#ifndef ARM_COMMON__PMU_H
-#define ARM_COMMON__PMU_H
+#ifndef __ARM_PMU_H__
+#define __ARM_PMU_H__
 
 #define KVM_ARM_PMUv3_PPI			23
 
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm);
 
-#endif /* ARM_COMMON__PMU_H */
+#endif /* __ARM_PMU_H__ */
diff --git a/arm/pmu.c b/arm/aarch64/pmu.c
similarity index 93%
rename from arm/pmu.c
rename to arm/aarch64/pmu.c
index 5b058eabb49d..6b190c5e2ae5 100644
--- a/arm/pmu.c
+++ b/arm/aarch64/pmu.c
@@ -4,9 +4,9 @@
 #include "kvm/util.h"
 
 #include "arm-common/gic.h"
-#include "arm-common/pmu.h"
 
-#ifdef CONFIG_ARM64
+#include "asm/pmu.h"
+
 static int set_pmu_attr(struct kvm *kvm, int vcpu_idx,
 			struct kvm_device_attr *attr)
 {
@@ -71,6 +71,3 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 	_FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
 	_FDT(fdt_end_node(fdt));
 }
-#else
-void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm) { }
-#endif
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 07/11] arm64: Rework set_pmu_attr()
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

By the time kvmtool generates the DTB node for the PMU, the
KVM_ARM_VCPU_PMU_V3 VCPU feature is already set by kvm_cpu__arch_init().

KVM refuses to run a VCPU if the PMU hasn't been initialized. A PMU
cannot be initialized if the interrupt ID hasn't been set by userspace.
As a consequence, kvmtool will get an error if the interrupt ID or if
the PMU has not been initialized:

KVM_RUN failed: Invalid argument

To make debugging easier, exit with an error message as soon as one the
PMU ioctls fails, instead of waiting until the VCPU is first run.

To avoid the repetition of assigning a new kvm_device_attr struct in the
main body of pmu__generate_fdt_nodes(), which hinders readability of the
function, move the struct to set_pmu_attr().

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/pmu.c | 48 ++++++++++++++++-------------------------------
 1 file changed, 16 insertions(+), 32 deletions(-)

diff --git a/arm/aarch64/pmu.c b/arm/aarch64/pmu.c
index 6b190c5e2ae5..ac5b7bcd6ca9 100644
--- a/arm/aarch64/pmu.c
+++ b/arm/aarch64/pmu.c
@@ -7,30 +7,31 @@
 
 #include "asm/pmu.h"
 
-static int set_pmu_attr(struct kvm *kvm, int vcpu_idx,
-			struct kvm_device_attr *attr)
+static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
 {
-	int ret, fd;
-
-	fd = kvm->cpus[vcpu_idx]->vcpu_fd;
+	struct kvm_device_attr pmu_attr = {
+		.group	= KVM_ARM_VCPU_PMU_V3_CTRL,
+		.addr	= (u64)addr,
+		.attr	= attr,
+	};
+	int ret;
 
-	ret = ioctl(fd, KVM_HAS_DEVICE_ATTR, attr);
+	ret = ioctl(vcpu->vcpu_fd, KVM_HAS_DEVICE_ATTR, &pmu_attr);
 	if (!ret) {
-		ret = ioctl(fd, KVM_SET_DEVICE_ATTR, attr);
+		ret = ioctl(vcpu->vcpu_fd, KVM_SET_DEVICE_ATTR, &pmu_attr);
 		if (ret)
-			perror("PMU KVM_SET_DEVICE_ATTR failed");
+			die_perror("PMU KVM_SET_DEVICE_ATTR");
 	} else {
-		pr_err("Unsupported PMU on vcpu%d\n", vcpu_idx);
+		die_perror("PMU KVM_HAS_DEVICE_ATTR");
 	}
-
-	return ret;
 }
 
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 {
 	const char compatible[] = "arm,armv8-pmuv3";
 	int irq = KVM_ARM_PMUv3_PPI;
-	int i, ret;
+	struct kvm_cpu *vcpu;
+	int i;
 
 	u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \
 		       & GIC_FDT_IRQ_PPI_CPU_MASK;
@@ -44,26 +45,9 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 		return;
 
 	for (i = 0; i < kvm->nrcpus; i++) {
-		struct kvm_device_attr pmu_attr;
-
-		pmu_attr = (struct kvm_device_attr){
-			.group	= KVM_ARM_VCPU_PMU_V3_CTRL,
-			.addr	= (u64)(unsigned long)&irq,
-			.attr	= KVM_ARM_VCPU_PMU_V3_IRQ,
-		};
-
-		ret = set_pmu_attr(kvm, i, &pmu_attr);
-		if (ret)
-			return;
-
-		pmu_attr = (struct kvm_device_attr){
-			.group	= KVM_ARM_VCPU_PMU_V3_CTRL,
-			.attr	= KVM_ARM_VCPU_PMU_V3_INIT,
-		};
-
-		ret = set_pmu_attr(kvm, i, &pmu_attr);
-		if (ret)
-			return;
+		vcpu = kvm->cpus[i];
+		set_pmu_attr(vcpu, &irq, KVM_ARM_VCPU_PMU_V3_IRQ);
+		set_pmu_attr(vcpu, NULL, KVM_ARM_VCPU_PMU_V3_INIT);
 	}
 
 	_FDT(fdt_begin_node(fdt, "pmu"));
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 07/11] arm64: Rework set_pmu_attr()
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

By the time kvmtool generates the DTB node for the PMU, the
KVM_ARM_VCPU_PMU_V3 VCPU feature is already set by kvm_cpu__arch_init().

KVM refuses to run a VCPU if the PMU hasn't been initialized. A PMU
cannot be initialized if the interrupt ID hasn't been set by userspace.
As a consequence, kvmtool will get an error if the interrupt ID or if
the PMU has not been initialized:

KVM_RUN failed: Invalid argument

To make debugging easier, exit with an error message as soon as one the
PMU ioctls fails, instead of waiting until the VCPU is first run.

To avoid the repetition of assigning a new kvm_device_attr struct in the
main body of pmu__generate_fdt_nodes(), which hinders readability of the
function, move the struct to set_pmu_attr().

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/pmu.c | 48 ++++++++++++++++-------------------------------
 1 file changed, 16 insertions(+), 32 deletions(-)

diff --git a/arm/aarch64/pmu.c b/arm/aarch64/pmu.c
index 6b190c5e2ae5..ac5b7bcd6ca9 100644
--- a/arm/aarch64/pmu.c
+++ b/arm/aarch64/pmu.c
@@ -7,30 +7,31 @@
 
 #include "asm/pmu.h"
 
-static int set_pmu_attr(struct kvm *kvm, int vcpu_idx,
-			struct kvm_device_attr *attr)
+static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
 {
-	int ret, fd;
-
-	fd = kvm->cpus[vcpu_idx]->vcpu_fd;
+	struct kvm_device_attr pmu_attr = {
+		.group	= KVM_ARM_VCPU_PMU_V3_CTRL,
+		.addr	= (u64)addr,
+		.attr	= attr,
+	};
+	int ret;
 
-	ret = ioctl(fd, KVM_HAS_DEVICE_ATTR, attr);
+	ret = ioctl(vcpu->vcpu_fd, KVM_HAS_DEVICE_ATTR, &pmu_attr);
 	if (!ret) {
-		ret = ioctl(fd, KVM_SET_DEVICE_ATTR, attr);
+		ret = ioctl(vcpu->vcpu_fd, KVM_SET_DEVICE_ATTR, &pmu_attr);
 		if (ret)
-			perror("PMU KVM_SET_DEVICE_ATTR failed");
+			die_perror("PMU KVM_SET_DEVICE_ATTR");
 	} else {
-		pr_err("Unsupported PMU on vcpu%d\n", vcpu_idx);
+		die_perror("PMU KVM_HAS_DEVICE_ATTR");
 	}
-
-	return ret;
 }
 
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 {
 	const char compatible[] = "arm,armv8-pmuv3";
 	int irq = KVM_ARM_PMUv3_PPI;
-	int i, ret;
+	struct kvm_cpu *vcpu;
+	int i;
 
 	u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \
 		       & GIC_FDT_IRQ_PPI_CPU_MASK;
@@ -44,26 +45,9 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 		return;
 
 	for (i = 0; i < kvm->nrcpus; i++) {
-		struct kvm_device_attr pmu_attr;
-
-		pmu_attr = (struct kvm_device_attr){
-			.group	= KVM_ARM_VCPU_PMU_V3_CTRL,
-			.addr	= (u64)(unsigned long)&irq,
-			.attr	= KVM_ARM_VCPU_PMU_V3_IRQ,
-		};
-
-		ret = set_pmu_attr(kvm, i, &pmu_attr);
-		if (ret)
-			return;
-
-		pmu_attr = (struct kvm_device_attr){
-			.group	= KVM_ARM_VCPU_PMU_V3_CTRL,
-			.attr	= KVM_ARM_VCPU_PMU_V3_INIT,
-		};
-
-		ret = set_pmu_attr(kvm, i, &pmu_attr);
-		if (ret)
-			return;
+		vcpu = kvm->cpus[i];
+		set_pmu_attr(vcpu, &irq, KVM_ARM_VCPU_PMU_V3_IRQ);
+		set_pmu_attr(vcpu, NULL, KVM_ARM_VCPU_PMU_V3_INIT);
 	}
 
 	_FDT(fdt_begin_node(fdt, "pmu"));
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 08/11] Add cpumask functions
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Add a handful of cpumask functions, some of which will be used when
dealing with different PMUs on heterogeneous systems.

The maximum number of CPUs in a system, NR_CPUS, which dictates the size of
the cpumask, has been taken from the Kconfig file for each architecture,
from Linux version 5.16.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 Makefile                         |   2 +
 arm/aarch32/include/asm/kernel.h |   8 +
 arm/aarch64/include/asm/kernel.h |   8 +
 include/linux/bitmap.h           |  71 +++++++++
 include/linux/bitops.h           |   2 +
 include/linux/bits.h             |   8 +
 include/linux/cpumask.h          |  62 ++++++++
 include/linux/find.h             |  30 ++++
 include/linux/kernel.h           |   6 +
 mips/include/asm/kernel.h        |   8 +
 powerpc/include/asm/kernel.h     |   8 +
 util/bitmap.c                    | 256 +++++++++++++++++++++++++++++++
 util/find.c                      |  40 +++++
 x86/include/asm/kernel.h         |   8 +
 14 files changed, 517 insertions(+)
 create mode 100644 arm/aarch32/include/asm/kernel.h
 create mode 100644 arm/aarch64/include/asm/kernel.h
 create mode 100644 include/linux/bitmap.h
 create mode 100644 include/linux/bits.h
 create mode 100644 include/linux/cpumask.h
 create mode 100644 include/linux/find.h
 create mode 100644 mips/include/asm/kernel.h
 create mode 100644 powerpc/include/asm/kernel.h
 create mode 100644 util/bitmap.c
 create mode 100644 util/find.c
 create mode 100644 x86/include/asm/kernel.h

diff --git a/Makefile b/Makefile
index 31274353656d..9e67c7637b1e 100644
--- a/Makefile
+++ b/Makefile
@@ -89,6 +89,8 @@ OBJS	+= net/uip/buf.o
 OBJS	+= net/uip/csum.o
 OBJS	+= net/uip/dhcp.o
 OBJS	+= kvm-cmd.o
+OBJS	+= util/bitmap.o
+OBJS	+= util/find.o
 OBJS	+= util/init.o
 OBJS    += util/iovec.o
 OBJS	+= util/rbtree.o
diff --git a/arm/aarch32/include/asm/kernel.h b/arm/aarch32/include/asm/kernel.h
new file mode 100644
index 000000000000..61296094deb1
--- /dev/null
+++ b/arm/aarch32/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_KERNEL_H
+#define __ASM_KERNEL_H
+
+#define NR_CPUS	32
+
+#endif /* __ASM_KERNEL_H */
diff --git a/arm/aarch64/include/asm/kernel.h b/arm/aarch64/include/asm/kernel.h
new file mode 100644
index 000000000000..a2a8d9ed4059
--- /dev/null
+++ b/arm/aarch64/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_KERNEL_H
+#define __ASM_KERNEL_H
+
+#define NR_CPUS	4096
+
+#endif /* __ASM_KERNEL_H */
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
new file mode 100644
index 000000000000..3b203461415a
--- /dev/null
+++ b/include/linux/bitmap.h
@@ -0,0 +1,71 @@
+#ifndef KVM__BITMAP_H
+#define KVM__BITMAP_H
+
+#include <stdbool.h>
+#include <string.h>
+
+#include "linux/bitops.h"
+
+#define DECLARE_BITMAP(name,bits) \
+	unsigned long name[BITS_TO_LONGS(bits)]
+
+#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
+#define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
+
+static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
+{
+	unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+	memset(dst, 0, len);
+}
+
+#if __BYTE_ORDER__ ==  __ORDER_LITTLE_ENDIAN__
+#define BITMAP_MEM_ALIGNMENT 8
+#else
+#define BITMAP_MEM_ALIGNMENT (8 * sizeof(unsigned long))
+#endif
+#define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1)
+
+void __bitmap_set(unsigned long *map, unsigned int start, int len);
+
+static inline void bitmap_set(unsigned long *map, unsigned int start,
+		unsigned int nbits)
+{
+	if (__builtin_constant_p(nbits) && nbits == 1)
+		set_bit(start, map);
+	else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
+		 IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
+		 __builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
+		 IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
+		memset((char *)map + start / 8, 0xff, nbits / 8);
+	else
+		__bitmap_set(map, start, nbits);
+}
+
+bool __bitmap_and(unsigned long *dst, const unsigned long *src1,
+		  const unsigned long *src2, unsigned int nbits);
+
+static inline bool bitmap_and(unsigned long *dst, const unsigned long *src1,
+			      const unsigned long *src2, unsigned int nbits)
+{
+	if (nbits >= 0 && nbits <= BITS_PER_LONG)
+		return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0;
+
+	return __bitmap_and(dst, src1, src2, nbits);
+}
+
+int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits);
+
+bool __bitmap_subset(const unsigned long *bitmap1, const unsigned long *bitmap2,
+		     unsigned int nbits);
+
+static inline bool bitmap_subset(const unsigned long *src1,
+				 const unsigned long *src2, unsigned int nbits)
+{
+	if (nbits >= 0 && nbits <= BITS_PER_LONG)
+		return !((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits));
+
+	return __bitmap_subset(src1, src2, nbits);
+}
+
+
+#endif /* KVM__BITMAP_H */
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 3d31f0acf48e..ae33922f5743 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -11,6 +11,8 @@
 #define BITS_PER_BYTE           8
 #define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 
+#define BIT_WORD(nr)		((nr) / BITS_PER_LONG)
+
 static inline void set_bit(int nr, unsigned long *addr)
 {
 	addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
diff --git a/include/linux/bits.h b/include/linux/bits.h
new file mode 100644
index 000000000000..37271dd32633
--- /dev/null
+++ b/include/linux/bits.h
@@ -0,0 +1,8 @@
+#ifndef LINUX__BITS_H_
+#define LINUX__BITS_H_
+
+#define GENMASK(h, l) \
+	((~0UL - (1UL << (l)) + 1) & \
+	 (~0UL >> (BITS_PER_LONG - 1 - (h))))
+
+#endif /* LINUX__BITS_H */
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
new file mode 100644
index 000000000000..c4be06621cf4
--- /dev/null
+++ b/include/linux/cpumask.h
@@ -0,0 +1,62 @@
+#ifndef LINUX__CPUMASK_H
+#define LINUX__CPUMASK_H
+
+#include <stdbool.h>
+
+#include "linux/bitmap.h"
+#include "linux/find.h"
+#include "linux/kernel.h"
+
+typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
+
+#define cpumask_bits(maskp)	((maskp)->bits)
+
+static inline void cpumask_set_cpu(int cpu, cpumask_t *dstp)
+{
+	set_bit(cpu, cpumask_bits(dstp));
+}
+
+static inline void cpumask_clear_cpu(int cpu, cpumask_t *dstp)
+{
+	clear_bit(cpu, cpumask_bits(dstp));
+}
+
+static inline bool cpumask_test_cpu(int cpu, const cpumask_t *cpumask)
+{
+	return test_bit(cpu, cpumask_bits((cpumask)));
+}
+
+static inline void cpumask_clear(cpumask_t *dstp)
+{
+	bitmap_zero(cpumask_bits(dstp), NR_CPUS);
+}
+
+static inline bool cpumask_and(cpumask_t *dstp, cpumask_t *src1p,
+			       cpumask_t *src2p)
+{
+	return bitmap_and(cpumask_bits(dstp), cpumask_bits(src1p),
+			  cpumask_bits(src2p), NR_CPUS);
+}
+
+static inline unsigned int cpumask_next(int n, const struct cpumask *srcp)
+{
+	return find_next_bit(cpumask_bits(srcp), NR_CPUS, n + 1);
+}
+
+#define for_each_cpu(cpu, maskp)			\
+	for ((cpu) = -1;				\
+	     (cpu) = cpumask_next((cpu), (maskp)),	\
+	     (cpu) < NR_CPUS;)
+
+static inline int cpulist_parse(const char *buf, cpumask_t *dstp)
+{
+	return bitmap_parselist(buf, cpumask_bits(dstp), NR_CPUS);
+}
+
+static inline bool cpumask_subset(const  cpumask_t *src1p,
+				  const  cpumask_t *src2p)
+{
+	return bitmap_subset(cpumask_bits(src1p), cpumask_bits(src2p), NR_CPUS);
+}
+
+#endif /* LINUX__CPUMASK_H */
diff --git a/include/linux/find.h b/include/linux/find.h
new file mode 100644
index 000000000000..22819150d146
--- /dev/null
+++ b/include/linux/find.h
@@ -0,0 +1,30 @@
+#ifndef LINUX__FIND_H
+#define LINUX__FIND_H
+
+#include <stddef.h>
+
+#include "linux/bitops.h"
+#include "linux/bits.h"
+
+unsigned long _find_next_bit(const unsigned long *addr1,
+		const unsigned long *addr2, unsigned long nbits,
+		unsigned long start, unsigned long invert);
+
+static inline
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+			    unsigned long offset)
+{
+	if (size >= 0 && size <= BITS_PER_LONG) {
+		unsigned long val;
+
+		if (offset >= size)
+			return size;
+
+		val = *addr & GENMASK(size - 1, offset);
+		return val ? (unsigned long)__builtin_ctzl(val) : size;
+	}
+
+	return _find_next_bit(addr, NULL, size, offset, 0);
+}
+
+#endif /* LINUX__FIND_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index f2bff5f12b61..6c22f1c06f6d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -2,10 +2,16 @@
 #ifndef KVM__LINUX_KERNEL_H_
 #define KVM__LINUX_KERNEL_H_
 
+#include "asm/kernel.h"
+
+#define __round_mask(x, y)	((__typeof__(x))((y)-1))
+#define round_down(x, y)	((x) & ~__round_mask(x, y))
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define ALIGN(x,a)		__ALIGN_MASK(x,(typeof(x))(a)-1)
 #define __ALIGN_MASK(x,mask)	(((x)+(mask))&~(mask))
+#define IS_ALIGNED(x, a)	(((x) & ((typeof(x))(a) - 1)) == 0)
 
 #ifndef offsetof
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
diff --git a/mips/include/asm/kernel.h b/mips/include/asm/kernel.h
new file mode 100644
index 000000000000..cbceffd02acd
--- /dev/null
+++ b/mips/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_KERNEL_H
+#define __ASM_KERNEL_H
+
+#define NR_CPUS	256
+
+#endif /* __ASM_KERNEL_H */
diff --git a/powerpc/include/asm/kernel.h b/powerpc/include/asm/kernel.h
new file mode 100644
index 000000000000..7b4fe88efd65
--- /dev/null
+++ b/powerpc/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_KERNEL_H
+#define __ASM_KERNEL_H
+
+#define NR_CPUS	2048
+
+#endif /* __ASM_KERNEL_H */
diff --git a/util/bitmap.c b/util/bitmap.c
new file mode 100644
index 000000000000..8bae1c91499d
--- /dev/null
+++ b/util/bitmap.c
@@ -0,0 +1,256 @@
+/*
+ * Taken from Linux kernel version v5.15.
+ */
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include "linux/bitmap.h"
+#include "linux/bitops.h"
+#include "linux/err.h"
+
+/*
+ * Region 9-38:4/10 describes the following bitmap structure:
+ * 0	   9  12    18			38	     N
+ * .........****......****......****..................
+ *	    ^  ^     ^			 ^	     ^
+ *      start  off   group_len	       end	 nbits
+ */
+struct region {
+	unsigned int start;
+	unsigned int off;
+	unsigned int group_len;
+	unsigned int end;
+	unsigned int nbits;
+};
+
+void __bitmap_set(unsigned long *map, unsigned int start, int len)
+{
+	unsigned long *p = map + BIT_WORD(start);
+	const unsigned int size = start + len;
+	int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+	unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+
+	while (len - bits_to_set >= 0) {
+		*p |= mask_to_set;
+		len -= bits_to_set;
+		bits_to_set = BITS_PER_LONG;
+		mask_to_set = ~0UL;
+		p++;
+	}
+	if (len) {
+		mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+		*p |= mask_to_set;
+	}
+}
+
+static void bitmap_set_region(const struct region *r, unsigned long *bitmap)
+{
+	unsigned int start;
+
+	for (start = r->start; start <= r->end; start += r->group_len)
+		bitmap_set(bitmap, start, min(r->end - start + 1, r->off));
+}
+
+static inline bool __end_of_region(char c)
+{
+	return isspace(c) || c == ',';
+}
+
+static inline bool end_of_str(char c)
+{
+	return c == '\0' || c == '\n';
+}
+
+static inline bool end_of_region(char c)
+{
+	return __end_of_region(c) || end_of_str(c);
+}
+
+/*
+ * The format allows commas and whitespaces at the beginning
+ * of the region.
+ */
+static const char *bitmap_find_region(const char *str)
+{
+	while (__end_of_region(*str))
+		str++;
+
+	return end_of_str(*str) ? NULL : str;
+}
+
+static int bitmap_check_region(const struct region *r)
+{
+	if (r->start > r->end || r->group_len == 0 || r->off > r->group_len)
+		return -EINVAL;
+
+	if (r->end >= r->nbits)
+		return -ERANGE;
+
+	return 0;
+}
+
+static const char *bitmap_getnum(const char *str, unsigned int *num,
+				 unsigned int lastbit)
+{
+	unsigned long long n;
+	char *endptr;
+
+	if (str[0] == 'N') {
+		*num = lastbit;
+		return str + 1;
+	}
+
+	n = strtoll(str, &endptr, 10);
+	/* No digits found. */
+	if (n == 0 && endptr == str)
+		return ERR_PTR(-EINVAL);
+	/* Check for overflows and negative numbers. */
+	if (n == ULLONG_MAX || n != (unsigned long)n || n != (unsigned int)n)
+		return ERR_PTR(-EOVERFLOW);
+
+	*num = n;
+	return endptr;
+}
+
+static const char *bitmap_parse_region(const char *str, struct region *r)
+{
+	unsigned int lastbit = r->nbits - 1;
+
+	if (!strncasecmp(str, "all", 3)) {
+		r->start = 0;
+		r->end = lastbit;
+		str += 3;
+
+		goto check_pattern;
+	}
+
+	str = bitmap_getnum(str, &r->start, lastbit);
+	if (IS_ERR(str))
+		return str;
+
+	if (end_of_region(*str))
+		goto no_end;
+
+	if (*str != '-')
+		return ERR_PTR(-EINVAL);
+
+	str = bitmap_getnum(str + 1, &r->end, lastbit);
+	if (IS_ERR(str))
+		return str;
+
+check_pattern:
+	if (end_of_region(*str))
+		goto no_pattern;
+
+	if (*str != ':')
+		return ERR_PTR(-EINVAL);
+
+	str = bitmap_getnum(str + 1, &r->off, lastbit);
+	if (IS_ERR(str))
+		return str;
+
+	if (*str != '/')
+		return ERR_PTR(-EINVAL);
+
+	return bitmap_getnum(str + 1, &r->group_len, lastbit);
+
+no_end:
+	r->end = r->start;
+no_pattern:
+	r->off = r->end + 1;
+	r->group_len = r->end + 1;
+
+	return end_of_str(*str) ? NULL : str;
+}
+
+/**
+ * bitmap_parselist - convert list format ASCII string to bitmap
+ * @buf: read user string from this buffer; must be terminated
+ *    with a \0 or \n.
+ * @maskp: write resulting mask here
+ * @nmaskbits: number of bits in mask to be written
+ *
+ * Input format is a comma-separated list of decimal numbers and
+ * ranges.  Consecutively set bits are shown as two hyphen-separated
+ * decimal numbers, the smallest and largest bit numbers set in
+ * the range.
+ * Optionally each range can be postfixed to denote that only parts of it
+ * should be set. The range will divided to groups of specific size.
+ * From each group will be used only defined amount of bits.
+ * Syntax: range:used_size/group_size
+ * Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
+ * The value 'N' can be used as a dynamically substituted token for the
+ * maximum allowed value; i.e (nmaskbits - 1).  Keep in mind that it is
+ * dynamic, so if system changes cause the bitmap width to change, such
+ * as more cores in a CPU list, then any ranges using N will also change.
+ *
+ * Returns: 0 on success, -errno on invalid input strings. Error values:
+ *
+ *   - ``-EINVAL``: wrong region format
+ *   - ``-EINVAL``: invalid character in string
+ *   - ``-ERANGE``: bit number specified too large for mask
+ *   - ``-EOVERFLOW``: integer overflow in the input parameters
+ */
+int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits)
+{
+	struct region r;
+	long ret;
+
+	r.nbits = nmaskbits;
+	bitmap_zero(maskp, r.nbits);
+
+	while (buf) {
+		buf = bitmap_find_region(buf);
+		if (buf == NULL)
+			return 0;
+
+		buf = bitmap_parse_region(buf, &r);
+		if (IS_ERR(buf))
+			return PTR_ERR(buf);
+
+		ret = bitmap_check_region(&r);
+		if (ret)
+			return ret;
+
+		bitmap_set_region(&r, maskp);
+	}
+
+	return 0;
+}
+
+bool __bitmap_and(unsigned long *dst, const unsigned long *src1,
+		  const unsigned long *src2, unsigned int nbits)
+{
+	unsigned int lim = nbits / BITS_PER_LONG;
+	unsigned long result = 0;
+	unsigned int k;
+
+	for (k = 0; k < lim; k++)
+		result |= (dst[k] = src1[k] & src2[k]);
+
+	if (nbits % BITS_PER_LONG) {
+		result |= (dst[k] = src1[k] & src2[k] &
+			   BITMAP_LAST_WORD_MASK(nbits));
+	}
+
+	return result != 0;
+}
+
+bool __bitmap_subset(const unsigned long *bitmap1, const unsigned long *bitmap2,
+		     unsigned int nbits)
+{
+	unsigned int k, lim = nbits / BITS_PER_LONG;
+
+	for (k = 0; k < lim; k++)
+		if (bitmap1[k] & ~bitmap2[k])
+			return false;
+
+	if (nbits % BITS_PER_LONG) {
+		if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(nbits))
+			return false;
+	}
+
+	return true;
+}
diff --git a/util/find.c b/util/find.c
new file mode 100644
index 000000000000..a438f2388e00
--- /dev/null
+++ b/util/find.c
@@ -0,0 +1,40 @@
+/*
+ * Taken from Linux kernel version v5.16.
+ */
+#include "linux/bitmap.h"
+#include "linux/find.h"
+#include "linux/kernel.h"
+
+unsigned long _find_next_bit(const unsigned long *addr1,
+		const unsigned long *addr2, unsigned long nbits,
+		unsigned long start, unsigned long invert)
+{
+	unsigned long tmp, mask;
+
+	if (start >= nbits)
+		return nbits;
+
+	tmp = addr1[start / BITS_PER_LONG];
+	if (addr2)
+		tmp &= addr2[start / BITS_PER_LONG];
+	tmp ^= invert;
+
+	/* Handle 1st word. */
+	mask = BITMAP_FIRST_WORD_MASK(start);
+	tmp &= mask;
+
+	start = round_down(start, BITS_PER_LONG);
+
+	while (!tmp) {
+		start += BITS_PER_LONG;
+		if (start >= nbits)
+			return nbits;
+
+		tmp = addr1[start / BITS_PER_LONG];
+		if (addr2)
+			tmp &= addr2[start / BITS_PER_LONG];
+		tmp ^= invert;
+	}
+
+	return min(start + __builtin_ctzl(tmp), nbits);
+}
diff --git a/x86/include/asm/kernel.h b/x86/include/asm/kernel.h
new file mode 100644
index 000000000000..87fad2a0300a
--- /dev/null
+++ b/x86/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_KERNEL_H
+#define _ASM_KERNEL_H
+
+#define NR_CPUS	8196
+
+#endif /* _ASM_KERNEL_H */
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 08/11] Add cpumask functions
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Add a handful of cpumask functions, some of which will be used when
dealing with different PMUs on heterogeneous systems.

The maximum number of CPUs in a system, NR_CPUS, which dictates the size of
the cpumask, has been taken from the Kconfig file for each architecture,
from Linux version 5.16.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 Makefile                         |   2 +
 arm/aarch32/include/asm/kernel.h |   8 +
 arm/aarch64/include/asm/kernel.h |   8 +
 include/linux/bitmap.h           |  71 +++++++++
 include/linux/bitops.h           |   2 +
 include/linux/bits.h             |   8 +
 include/linux/cpumask.h          |  62 ++++++++
 include/linux/find.h             |  30 ++++
 include/linux/kernel.h           |   6 +
 mips/include/asm/kernel.h        |   8 +
 powerpc/include/asm/kernel.h     |   8 +
 util/bitmap.c                    | 256 +++++++++++++++++++++++++++++++
 util/find.c                      |  40 +++++
 x86/include/asm/kernel.h         |   8 +
 14 files changed, 517 insertions(+)
 create mode 100644 arm/aarch32/include/asm/kernel.h
 create mode 100644 arm/aarch64/include/asm/kernel.h
 create mode 100644 include/linux/bitmap.h
 create mode 100644 include/linux/bits.h
 create mode 100644 include/linux/cpumask.h
 create mode 100644 include/linux/find.h
 create mode 100644 mips/include/asm/kernel.h
 create mode 100644 powerpc/include/asm/kernel.h
 create mode 100644 util/bitmap.c
 create mode 100644 util/find.c
 create mode 100644 x86/include/asm/kernel.h

diff --git a/Makefile b/Makefile
index 31274353656d..9e67c7637b1e 100644
--- a/Makefile
+++ b/Makefile
@@ -89,6 +89,8 @@ OBJS	+= net/uip/buf.o
 OBJS	+= net/uip/csum.o
 OBJS	+= net/uip/dhcp.o
 OBJS	+= kvm-cmd.o
+OBJS	+= util/bitmap.o
+OBJS	+= util/find.o
 OBJS	+= util/init.o
 OBJS    += util/iovec.o
 OBJS	+= util/rbtree.o
diff --git a/arm/aarch32/include/asm/kernel.h b/arm/aarch32/include/asm/kernel.h
new file mode 100644
index 000000000000..61296094deb1
--- /dev/null
+++ b/arm/aarch32/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_KERNEL_H
+#define __ASM_KERNEL_H
+
+#define NR_CPUS	32
+
+#endif /* __ASM_KERNEL_H */
diff --git a/arm/aarch64/include/asm/kernel.h b/arm/aarch64/include/asm/kernel.h
new file mode 100644
index 000000000000..a2a8d9ed4059
--- /dev/null
+++ b/arm/aarch64/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_KERNEL_H
+#define __ASM_KERNEL_H
+
+#define NR_CPUS	4096
+
+#endif /* __ASM_KERNEL_H */
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
new file mode 100644
index 000000000000..3b203461415a
--- /dev/null
+++ b/include/linux/bitmap.h
@@ -0,0 +1,71 @@
+#ifndef KVM__BITMAP_H
+#define KVM__BITMAP_H
+
+#include <stdbool.h>
+#include <string.h>
+
+#include "linux/bitops.h"
+
+#define DECLARE_BITMAP(name,bits) \
+	unsigned long name[BITS_TO_LONGS(bits)]
+
+#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
+#define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
+
+static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
+{
+	unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+	memset(dst, 0, len);
+}
+
+#if __BYTE_ORDER__ ==  __ORDER_LITTLE_ENDIAN__
+#define BITMAP_MEM_ALIGNMENT 8
+#else
+#define BITMAP_MEM_ALIGNMENT (8 * sizeof(unsigned long))
+#endif
+#define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1)
+
+void __bitmap_set(unsigned long *map, unsigned int start, int len);
+
+static inline void bitmap_set(unsigned long *map, unsigned int start,
+		unsigned int nbits)
+{
+	if (__builtin_constant_p(nbits) && nbits == 1)
+		set_bit(start, map);
+	else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
+		 IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
+		 __builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
+		 IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
+		memset((char *)map + start / 8, 0xff, nbits / 8);
+	else
+		__bitmap_set(map, start, nbits);
+}
+
+bool __bitmap_and(unsigned long *dst, const unsigned long *src1,
+		  const unsigned long *src2, unsigned int nbits);
+
+static inline bool bitmap_and(unsigned long *dst, const unsigned long *src1,
+			      const unsigned long *src2, unsigned int nbits)
+{
+	if (nbits >= 0 && nbits <= BITS_PER_LONG)
+		return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0;
+
+	return __bitmap_and(dst, src1, src2, nbits);
+}
+
+int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits);
+
+bool __bitmap_subset(const unsigned long *bitmap1, const unsigned long *bitmap2,
+		     unsigned int nbits);
+
+static inline bool bitmap_subset(const unsigned long *src1,
+				 const unsigned long *src2, unsigned int nbits)
+{
+	if (nbits >= 0 && nbits <= BITS_PER_LONG)
+		return !((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits));
+
+	return __bitmap_subset(src1, src2, nbits);
+}
+
+
+#endif /* KVM__BITMAP_H */
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 3d31f0acf48e..ae33922f5743 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -11,6 +11,8 @@
 #define BITS_PER_BYTE           8
 #define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 
+#define BIT_WORD(nr)		((nr) / BITS_PER_LONG)
+
 static inline void set_bit(int nr, unsigned long *addr)
 {
 	addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
diff --git a/include/linux/bits.h b/include/linux/bits.h
new file mode 100644
index 000000000000..37271dd32633
--- /dev/null
+++ b/include/linux/bits.h
@@ -0,0 +1,8 @@
+#ifndef LINUX__BITS_H_
+#define LINUX__BITS_H_
+
+#define GENMASK(h, l) \
+	((~0UL - (1UL << (l)) + 1) & \
+	 (~0UL >> (BITS_PER_LONG - 1 - (h))))
+
+#endif /* LINUX__BITS_H */
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
new file mode 100644
index 000000000000..c4be06621cf4
--- /dev/null
+++ b/include/linux/cpumask.h
@@ -0,0 +1,62 @@
+#ifndef LINUX__CPUMASK_H
+#define LINUX__CPUMASK_H
+
+#include <stdbool.h>
+
+#include "linux/bitmap.h"
+#include "linux/find.h"
+#include "linux/kernel.h"
+
+typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
+
+#define cpumask_bits(maskp)	((maskp)->bits)
+
+static inline void cpumask_set_cpu(int cpu, cpumask_t *dstp)
+{
+	set_bit(cpu, cpumask_bits(dstp));
+}
+
+static inline void cpumask_clear_cpu(int cpu, cpumask_t *dstp)
+{
+	clear_bit(cpu, cpumask_bits(dstp));
+}
+
+static inline bool cpumask_test_cpu(int cpu, const cpumask_t *cpumask)
+{
+	return test_bit(cpu, cpumask_bits((cpumask)));
+}
+
+static inline void cpumask_clear(cpumask_t *dstp)
+{
+	bitmap_zero(cpumask_bits(dstp), NR_CPUS);
+}
+
+static inline bool cpumask_and(cpumask_t *dstp, cpumask_t *src1p,
+			       cpumask_t *src2p)
+{
+	return bitmap_and(cpumask_bits(dstp), cpumask_bits(src1p),
+			  cpumask_bits(src2p), NR_CPUS);
+}
+
+static inline unsigned int cpumask_next(int n, const struct cpumask *srcp)
+{
+	return find_next_bit(cpumask_bits(srcp), NR_CPUS, n + 1);
+}
+
+#define for_each_cpu(cpu, maskp)			\
+	for ((cpu) = -1;				\
+	     (cpu) = cpumask_next((cpu), (maskp)),	\
+	     (cpu) < NR_CPUS;)
+
+static inline int cpulist_parse(const char *buf, cpumask_t *dstp)
+{
+	return bitmap_parselist(buf, cpumask_bits(dstp), NR_CPUS);
+}
+
+static inline bool cpumask_subset(const  cpumask_t *src1p,
+				  const  cpumask_t *src2p)
+{
+	return bitmap_subset(cpumask_bits(src1p), cpumask_bits(src2p), NR_CPUS);
+}
+
+#endif /* LINUX__CPUMASK_H */
diff --git a/include/linux/find.h b/include/linux/find.h
new file mode 100644
index 000000000000..22819150d146
--- /dev/null
+++ b/include/linux/find.h
@@ -0,0 +1,30 @@
+#ifndef LINUX__FIND_H
+#define LINUX__FIND_H
+
+#include <stddef.h>
+
+#include "linux/bitops.h"
+#include "linux/bits.h"
+
+unsigned long _find_next_bit(const unsigned long *addr1,
+		const unsigned long *addr2, unsigned long nbits,
+		unsigned long start, unsigned long invert);
+
+static inline
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+			    unsigned long offset)
+{
+	if (size >= 0 && size <= BITS_PER_LONG) {
+		unsigned long val;
+
+		if (offset >= size)
+			return size;
+
+		val = *addr & GENMASK(size - 1, offset);
+		return val ? (unsigned long)__builtin_ctzl(val) : size;
+	}
+
+	return _find_next_bit(addr, NULL, size, offset, 0);
+}
+
+#endif /* LINUX__FIND_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index f2bff5f12b61..6c22f1c06f6d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -2,10 +2,16 @@
 #ifndef KVM__LINUX_KERNEL_H_
 #define KVM__LINUX_KERNEL_H_
 
+#include "asm/kernel.h"
+
+#define __round_mask(x, y)	((__typeof__(x))((y)-1))
+#define round_down(x, y)	((x) & ~__round_mask(x, y))
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define ALIGN(x,a)		__ALIGN_MASK(x,(typeof(x))(a)-1)
 #define __ALIGN_MASK(x,mask)	(((x)+(mask))&~(mask))
+#define IS_ALIGNED(x, a)	(((x) & ((typeof(x))(a) - 1)) == 0)
 
 #ifndef offsetof
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
diff --git a/mips/include/asm/kernel.h b/mips/include/asm/kernel.h
new file mode 100644
index 000000000000..cbceffd02acd
--- /dev/null
+++ b/mips/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_KERNEL_H
+#define __ASM_KERNEL_H
+
+#define NR_CPUS	256
+
+#endif /* __ASM_KERNEL_H */
diff --git a/powerpc/include/asm/kernel.h b/powerpc/include/asm/kernel.h
new file mode 100644
index 000000000000..7b4fe88efd65
--- /dev/null
+++ b/powerpc/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_KERNEL_H
+#define __ASM_KERNEL_H
+
+#define NR_CPUS	2048
+
+#endif /* __ASM_KERNEL_H */
diff --git a/util/bitmap.c b/util/bitmap.c
new file mode 100644
index 000000000000..8bae1c91499d
--- /dev/null
+++ b/util/bitmap.c
@@ -0,0 +1,256 @@
+/*
+ * Taken from Linux kernel version v5.15.
+ */
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include "linux/bitmap.h"
+#include "linux/bitops.h"
+#include "linux/err.h"
+
+/*
+ * Region 9-38:4/10 describes the following bitmap structure:
+ * 0	   9  12    18			38	     N
+ * .........****......****......****..................
+ *	    ^  ^     ^			 ^	     ^
+ *      start  off   group_len	       end	 nbits
+ */
+struct region {
+	unsigned int start;
+	unsigned int off;
+	unsigned int group_len;
+	unsigned int end;
+	unsigned int nbits;
+};
+
+void __bitmap_set(unsigned long *map, unsigned int start, int len)
+{
+	unsigned long *p = map + BIT_WORD(start);
+	const unsigned int size = start + len;
+	int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+	unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+
+	while (len - bits_to_set >= 0) {
+		*p |= mask_to_set;
+		len -= bits_to_set;
+		bits_to_set = BITS_PER_LONG;
+		mask_to_set = ~0UL;
+		p++;
+	}
+	if (len) {
+		mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+		*p |= mask_to_set;
+	}
+}
+
+static void bitmap_set_region(const struct region *r, unsigned long *bitmap)
+{
+	unsigned int start;
+
+	for (start = r->start; start <= r->end; start += r->group_len)
+		bitmap_set(bitmap, start, min(r->end - start + 1, r->off));
+}
+
+static inline bool __end_of_region(char c)
+{
+	return isspace(c) || c == ',';
+}
+
+static inline bool end_of_str(char c)
+{
+	return c == '\0' || c == '\n';
+}
+
+static inline bool end_of_region(char c)
+{
+	return __end_of_region(c) || end_of_str(c);
+}
+
+/*
+ * The format allows commas and whitespaces at the beginning
+ * of the region.
+ */
+static const char *bitmap_find_region(const char *str)
+{
+	while (__end_of_region(*str))
+		str++;
+
+	return end_of_str(*str) ? NULL : str;
+}
+
+static int bitmap_check_region(const struct region *r)
+{
+	if (r->start > r->end || r->group_len == 0 || r->off > r->group_len)
+		return -EINVAL;
+
+	if (r->end >= r->nbits)
+		return -ERANGE;
+
+	return 0;
+}
+
+static const char *bitmap_getnum(const char *str, unsigned int *num,
+				 unsigned int lastbit)
+{
+	unsigned long long n;
+	char *endptr;
+
+	if (str[0] == 'N') {
+		*num = lastbit;
+		return str + 1;
+	}
+
+	n = strtoll(str, &endptr, 10);
+	/* No digits found. */
+	if (n == 0 && endptr == str)
+		return ERR_PTR(-EINVAL);
+	/* Check for overflows and negative numbers. */
+	if (n == ULLONG_MAX || n != (unsigned long)n || n != (unsigned int)n)
+		return ERR_PTR(-EOVERFLOW);
+
+	*num = n;
+	return endptr;
+}
+
+static const char *bitmap_parse_region(const char *str, struct region *r)
+{
+	unsigned int lastbit = r->nbits - 1;
+
+	if (!strncasecmp(str, "all", 3)) {
+		r->start = 0;
+		r->end = lastbit;
+		str += 3;
+
+		goto check_pattern;
+	}
+
+	str = bitmap_getnum(str, &r->start, lastbit);
+	if (IS_ERR(str))
+		return str;
+
+	if (end_of_region(*str))
+		goto no_end;
+
+	if (*str != '-')
+		return ERR_PTR(-EINVAL);
+
+	str = bitmap_getnum(str + 1, &r->end, lastbit);
+	if (IS_ERR(str))
+		return str;
+
+check_pattern:
+	if (end_of_region(*str))
+		goto no_pattern;
+
+	if (*str != ':')
+		return ERR_PTR(-EINVAL);
+
+	str = bitmap_getnum(str + 1, &r->off, lastbit);
+	if (IS_ERR(str))
+		return str;
+
+	if (*str != '/')
+		return ERR_PTR(-EINVAL);
+
+	return bitmap_getnum(str + 1, &r->group_len, lastbit);
+
+no_end:
+	r->end = r->start;
+no_pattern:
+	r->off = r->end + 1;
+	r->group_len = r->end + 1;
+
+	return end_of_str(*str) ? NULL : str;
+}
+
+/**
+ * bitmap_parselist - convert list format ASCII string to bitmap
+ * @buf: read user string from this buffer; must be terminated
+ *    with a \0 or \n.
+ * @maskp: write resulting mask here
+ * @nmaskbits: number of bits in mask to be written
+ *
+ * Input format is a comma-separated list of decimal numbers and
+ * ranges.  Consecutively set bits are shown as two hyphen-separated
+ * decimal numbers, the smallest and largest bit numbers set in
+ * the range.
+ * Optionally each range can be postfixed to denote that only parts of it
+ * should be set. The range will divided to groups of specific size.
+ * From each group will be used only defined amount of bits.
+ * Syntax: range:used_size/group_size
+ * Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
+ * The value 'N' can be used as a dynamically substituted token for the
+ * maximum allowed value; i.e (nmaskbits - 1).  Keep in mind that it is
+ * dynamic, so if system changes cause the bitmap width to change, such
+ * as more cores in a CPU list, then any ranges using N will also change.
+ *
+ * Returns: 0 on success, -errno on invalid input strings. Error values:
+ *
+ *   - ``-EINVAL``: wrong region format
+ *   - ``-EINVAL``: invalid character in string
+ *   - ``-ERANGE``: bit number specified too large for mask
+ *   - ``-EOVERFLOW``: integer overflow in the input parameters
+ */
+int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits)
+{
+	struct region r;
+	long ret;
+
+	r.nbits = nmaskbits;
+	bitmap_zero(maskp, r.nbits);
+
+	while (buf) {
+		buf = bitmap_find_region(buf);
+		if (buf == NULL)
+			return 0;
+
+		buf = bitmap_parse_region(buf, &r);
+		if (IS_ERR(buf))
+			return PTR_ERR(buf);
+
+		ret = bitmap_check_region(&r);
+		if (ret)
+			return ret;
+
+		bitmap_set_region(&r, maskp);
+	}
+
+	return 0;
+}
+
+bool __bitmap_and(unsigned long *dst, const unsigned long *src1,
+		  const unsigned long *src2, unsigned int nbits)
+{
+	unsigned int lim = nbits / BITS_PER_LONG;
+	unsigned long result = 0;
+	unsigned int k;
+
+	for (k = 0; k < lim; k++)
+		result |= (dst[k] = src1[k] & src2[k]);
+
+	if (nbits % BITS_PER_LONG) {
+		result |= (dst[k] = src1[k] & src2[k] &
+			   BITMAP_LAST_WORD_MASK(nbits));
+	}
+
+	return result != 0;
+}
+
+bool __bitmap_subset(const unsigned long *bitmap1, const unsigned long *bitmap2,
+		     unsigned int nbits)
+{
+	unsigned int k, lim = nbits / BITS_PER_LONG;
+
+	for (k = 0; k < lim; k++)
+		if (bitmap1[k] & ~bitmap2[k])
+			return false;
+
+	if (nbits % BITS_PER_LONG) {
+		if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(nbits))
+			return false;
+	}
+
+	return true;
+}
diff --git a/util/find.c b/util/find.c
new file mode 100644
index 000000000000..a438f2388e00
--- /dev/null
+++ b/util/find.c
@@ -0,0 +1,40 @@
+/*
+ * Taken from Linux kernel version v5.16.
+ */
+#include "linux/bitmap.h"
+#include "linux/find.h"
+#include "linux/kernel.h"
+
+unsigned long _find_next_bit(const unsigned long *addr1,
+		const unsigned long *addr2, unsigned long nbits,
+		unsigned long start, unsigned long invert)
+{
+	unsigned long tmp, mask;
+
+	if (start >= nbits)
+		return nbits;
+
+	tmp = addr1[start / BITS_PER_LONG];
+	if (addr2)
+		tmp &= addr2[start / BITS_PER_LONG];
+	tmp ^= invert;
+
+	/* Handle 1st word. */
+	mask = BITMAP_FIRST_WORD_MASK(start);
+	tmp &= mask;
+
+	start = round_down(start, BITS_PER_LONG);
+
+	while (!tmp) {
+		start += BITS_PER_LONG;
+		if (start >= nbits)
+			return nbits;
+
+		tmp = addr1[start / BITS_PER_LONG];
+		if (addr2)
+			tmp &= addr2[start / BITS_PER_LONG];
+		tmp ^= invert;
+	}
+
+	return min(start + __builtin_ctzl(tmp), nbits);
+}
diff --git a/x86/include/asm/kernel.h b/x86/include/asm/kernel.h
new file mode 100644
index 000000000000..87fad2a0300a
--- /dev/null
+++ b/x86/include/asm/kernel.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_KERNEL_H
+#define _ASM_KERNEL_H
+
+#define NR_CPUS	8196
+
+#endif /* _ASM_KERNEL_H */
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 09/11] update_headers.sh: Sync ABI headers with Linux v5.18-rc2
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/include/asm/kvm.h | 11 +++++++++++
 include/linux/kvm.h           | 15 +++++++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/arm/aarch64/include/asm/kvm.h b/arm/aarch64/include/asm/kvm.h
index 323e251ed37b..c1b6ddc02d2f 100644
--- a/arm/aarch64/include/asm/kvm.h
+++ b/arm/aarch64/include/asm/kvm.h
@@ -367,6 +367,7 @@ struct kvm_arm_copy_mte_tags {
 #define   KVM_ARM_VCPU_PMU_V3_IRQ	0
 #define   KVM_ARM_VCPU_PMU_V3_INIT	1
 #define   KVM_ARM_VCPU_PMU_V3_FILTER	2
+#define   KVM_ARM_VCPU_PMU_V3_SET_PMU	3
 #define KVM_ARM_VCPU_TIMER_CTRL		1
 #define   KVM_ARM_VCPU_TIMER_IRQ_VTIMER		0
 #define   KVM_ARM_VCPU_TIMER_IRQ_PTIMER		1
@@ -418,6 +419,16 @@ struct kvm_arm_copy_mte_tags {
 #define KVM_PSCI_RET_INVAL		PSCI_RET_INVALID_PARAMS
 #define KVM_PSCI_RET_DENIED		PSCI_RET_DENIED
 
+/* arm64-specific kvm_run::system_event flags */
+/*
+ * Reset caused by a PSCI v1.1 SYSTEM_RESET2 call.
+ * Valid only when the system event has a type of KVM_SYSTEM_EVENT_RESET.
+ */
+#define KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2	(1ULL << 0)
+
+/* run->fail_entry.hardware_entry_failure_reason codes. */
+#define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED	(1ULL << 0)
+
 #endif
 
 #endif /* __ARM_KVM_H__ */
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 507ee1f2aa96..91a6fe4e02c0 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -562,9 +562,12 @@ struct kvm_s390_mem_op {
 	__u32 op;		/* type of operation */
 	__u64 buf;		/* buffer in userspace */
 	union {
-		__u8 ar;	/* the access register number */
+		struct {
+			__u8 ar;	/* the access register number */
+			__u8 key;	/* access key, ignored if flag unset */
+		};
 		__u32 sida_offset; /* offset into the sida */
-		__u8 reserved[32]; /* should be set to 0 */
+		__u8 reserved[32]; /* ignored */
 	};
 };
 /* types for kvm_s390_mem_op->op */
@@ -572,9 +575,12 @@ struct kvm_s390_mem_op {
 #define KVM_S390_MEMOP_LOGICAL_WRITE	1
 #define KVM_S390_MEMOP_SIDA_READ	2
 #define KVM_S390_MEMOP_SIDA_WRITE	3
+#define KVM_S390_MEMOP_ABSOLUTE_READ	4
+#define KVM_S390_MEMOP_ABSOLUTE_WRITE	5
 /* flags for kvm_s390_mem_op->flags */
 #define KVM_S390_MEMOP_F_CHECK_ONLY		(1ULL << 0)
 #define KVM_S390_MEMOP_F_INJECT_EXCEPTION	(1ULL << 1)
+#define KVM_S390_MEMOP_F_SKEY_PROTECTION	(1ULL << 2)
 
 /* for KVM_INTERRUPT */
 struct kvm_interrupt {
@@ -1135,6 +1141,9 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_XSAVE2 208
 #define KVM_CAP_SYS_ATTRIBUTES 209
 #define KVM_CAP_PPC_AIL_MODE_3 210
+#define KVM_CAP_S390_MEM_OP_EXTENSION 211
+#define KVM_CAP_PMU_CAPABILITY 212
+#define KVM_CAP_DISABLE_QUIRKS2 213
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1971,6 +1980,8 @@ struct kvm_dirty_gfn {
 #define KVM_BUS_LOCK_DETECTION_OFF             (1 << 0)
 #define KVM_BUS_LOCK_DETECTION_EXIT            (1 << 1)
 
+#define KVM_PMU_CAP_DISABLE                    (1 << 0)
+
 /**
  * struct kvm_stats_header - Header of per vm/vcpu binary statistics data.
  * @flags: Some extra information for header, always 0 for now.
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 09/11] update_headers.sh: Sync ABI headers with Linux v5.18-rc2
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/include/asm/kvm.h | 11 +++++++++++
 include/linux/kvm.h           | 15 +++++++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/arm/aarch64/include/asm/kvm.h b/arm/aarch64/include/asm/kvm.h
index 323e251ed37b..c1b6ddc02d2f 100644
--- a/arm/aarch64/include/asm/kvm.h
+++ b/arm/aarch64/include/asm/kvm.h
@@ -367,6 +367,7 @@ struct kvm_arm_copy_mte_tags {
 #define   KVM_ARM_VCPU_PMU_V3_IRQ	0
 #define   KVM_ARM_VCPU_PMU_V3_INIT	1
 #define   KVM_ARM_VCPU_PMU_V3_FILTER	2
+#define   KVM_ARM_VCPU_PMU_V3_SET_PMU	3
 #define KVM_ARM_VCPU_TIMER_CTRL		1
 #define   KVM_ARM_VCPU_TIMER_IRQ_VTIMER		0
 #define   KVM_ARM_VCPU_TIMER_IRQ_PTIMER		1
@@ -418,6 +419,16 @@ struct kvm_arm_copy_mte_tags {
 #define KVM_PSCI_RET_INVAL		PSCI_RET_INVALID_PARAMS
 #define KVM_PSCI_RET_DENIED		PSCI_RET_DENIED
 
+/* arm64-specific kvm_run::system_event flags */
+/*
+ * Reset caused by a PSCI v1.1 SYSTEM_RESET2 call.
+ * Valid only when the system event has a type of KVM_SYSTEM_EVENT_RESET.
+ */
+#define KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2	(1ULL << 0)
+
+/* run->fail_entry.hardware_entry_failure_reason codes. */
+#define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED	(1ULL << 0)
+
 #endif
 
 #endif /* __ARM_KVM_H__ */
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 507ee1f2aa96..91a6fe4e02c0 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -562,9 +562,12 @@ struct kvm_s390_mem_op {
 	__u32 op;		/* type of operation */
 	__u64 buf;		/* buffer in userspace */
 	union {
-		__u8 ar;	/* the access register number */
+		struct {
+			__u8 ar;	/* the access register number */
+			__u8 key;	/* access key, ignored if flag unset */
+		};
 		__u32 sida_offset; /* offset into the sida */
-		__u8 reserved[32]; /* should be set to 0 */
+		__u8 reserved[32]; /* ignored */
 	};
 };
 /* types for kvm_s390_mem_op->op */
@@ -572,9 +575,12 @@ struct kvm_s390_mem_op {
 #define KVM_S390_MEMOP_LOGICAL_WRITE	1
 #define KVM_S390_MEMOP_SIDA_READ	2
 #define KVM_S390_MEMOP_SIDA_WRITE	3
+#define KVM_S390_MEMOP_ABSOLUTE_READ	4
+#define KVM_S390_MEMOP_ABSOLUTE_WRITE	5
 /* flags for kvm_s390_mem_op->flags */
 #define KVM_S390_MEMOP_F_CHECK_ONLY		(1ULL << 0)
 #define KVM_S390_MEMOP_F_INJECT_EXCEPTION	(1ULL << 1)
+#define KVM_S390_MEMOP_F_SKEY_PROTECTION	(1ULL << 2)
 
 /* for KVM_INTERRUPT */
 struct kvm_interrupt {
@@ -1135,6 +1141,9 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_XSAVE2 208
 #define KVM_CAP_SYS_ATTRIBUTES 209
 #define KVM_CAP_PPC_AIL_MODE_3 210
+#define KVM_CAP_S390_MEM_OP_EXTENSION 211
+#define KVM_CAP_PMU_CAPABILITY 212
+#define KVM_CAP_DISABLE_QUIRKS2 213
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1971,6 +1980,8 @@ struct kvm_dirty_gfn {
 #define KVM_BUS_LOCK_DETECTION_OFF             (1 << 0)
 #define KVM_BUS_LOCK_DETECTION_EXIT            (1 << 1)
 
+#define KVM_PMU_CAP_DISABLE                    (1 << 0)
+
 /**
  * struct kvm_stats_header - Header of per vm/vcpu binary statistics data.
  * @flags: Some extra information for header, always 0 for now.
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 10/11] arm64: Add support for KVM_ARM_VCPU_PMU_V3_SET_PMU
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

The KVM_ARM_VCPU_PMU_V3_CTRL(KVM_ARM_VCPU_PMU_V3_SET_PMU) VCPU ioctl is
used to assign a physical PMU to the events that KVM creates when emulating
the PMU for that VCPU. This is useful on heterogeneous systems, when there
is more than one hardware PMU present. All VCPUs must have the same PMU
assigned.

The assumption that is made in the implementation is that the user will pin
the kvmtool process on a set of CPUs that share the same PMU. This allows
kvmtool to set the same PMU for all VCPUs from the main thread, instead of
in the individual VCPU threads. If a VCPU thread migrates to a CPU which
has a different a PMU than the CPU on which the main thread was executing
when the PMU was set, the KVM_RUN ioctl will fail with kvm_run.exit_reason
set to KVM_EXIT_FAIL_ENTRY, and kvm_run.fail_entry will be populated with
the physical CPU ID on which the VCPU tried to execute.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/include/kvm/kvm-config-arch.h |   4 +-
 arm/aarch64/pmu.c                         | 147 +++++++++++++++++++++-
 2 files changed, 148 insertions(+), 3 deletions(-)

diff --git a/arm/aarch64/include/kvm/kvm-config-arch.h b/arm/aarch64/include/kvm/kvm-config-arch.h
index 3d39cd6d1f4e..b08ee60ee1c4 100644
--- a/arm/aarch64/include/kvm/kvm-config-arch.h
+++ b/arm/aarch64/include/kvm/kvm-config-arch.h
@@ -5,7 +5,9 @@
 	OPT_BOOLEAN('\0', "aarch32", &(cfg)->aarch32_guest,		\
 			"Run AArch32 guest"),				\
 	OPT_BOOLEAN('\0', "pmu", &(cfg)->has_pmuv3,			\
-			"Create PMUv3 device"),				\
+			"Create PMUv3 device. The emulated PMU will be" \
+			" set to the PMU associated with the"		\
+			" main thread"),				\
 	OPT_BOOLEAN('\0', "disable-mte", &(cfg)->mte_disabled,		\
 			"Disable Memory Tagging Extension"),		\
 	OPT_U64('\0', "kaslr-seed", &(cfg)->kaslr_seed,			\
diff --git a/arm/aarch64/pmu.c b/arm/aarch64/pmu.c
index ac5b7bcd6ca9..869a150cd6d3 100644
--- a/arm/aarch64/pmu.c
+++ b/arm/aarch64/pmu.c
@@ -1,3 +1,9 @@
+#include <dirent.h>
+#include <sched.h>
+
+#include "linux/cpumask.h"
+#include "linux/err.h"
+
 #include "kvm/fdt.h"
 #include "kvm/kvm.h"
 #include "kvm/kvm-cpu.h"
@@ -7,6 +13,17 @@
 
 #include "asm/pmu.h"
 
+static bool pmu_has_attr(struct kvm_cpu *vcpu, u64 attr)
+{
+	struct kvm_device_attr pmu_attr = {
+		.group	= KVM_ARM_VCPU_PMU_V3_CTRL,
+		.attr	= attr,
+	};
+	int ret = ioctl(vcpu->vcpu_fd, KVM_HAS_DEVICE_ATTR, &pmu_attr);
+
+	return ret == 0;
+}
+
 static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
 {
 	struct kvm_device_attr pmu_attr = {
@@ -16,8 +33,7 @@ static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
 	};
 	int ret;
 
-	ret = ioctl(vcpu->vcpu_fd, KVM_HAS_DEVICE_ATTR, &pmu_attr);
-	if (!ret) {
+	if (pmu_has_attr(vcpu, attr)) {
 		ret = ioctl(vcpu->vcpu_fd, KVM_SET_DEVICE_ATTR, &pmu_attr);
 		if (ret)
 			die_perror("PMU KVM_SET_DEVICE_ATTR");
@@ -26,11 +42,124 @@ static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
 	}
 }
 
+#define SYS_EVENT_SOURCE	"/sys/bus/event_source/devices/"
+/*
+ * int is 32 bits and INT_MAX translates in decimal to 2 * 10^9.
+ * Make room for newline and NUL.
+ */
+#define PMU_ID_MAXLEN		12
+
+/*
+ * In the case of homogeneous systems, there only one hardware PMU, and all
+ * VCPUs will use the same PMU, regardless of where the attribute gets set.
+ *
+ * For heterogeneous systems, the assumption is that the user has pinned the VM
+ * (via taskset or similar) to a set of CPUs that share the same hardware PMU.
+ * This simplifies things for kvmtool, as correctness is not affected by setting
+ * the PMU for each VCPU from the main thread, instead of setting it from each
+ * individual VCPU thread.
+ */
+static int find_pmu(void)
+{
+	char buf[PMU_ID_MAXLEN];
+	struct dirent *dirent;
+	char *cpulist, *path;
+	int pmu_id = -ENXIO;
+	unsigned long val;
+	cpumask_t cpumask;
+	ssize_t fd_sz;
+	int this_cpu;
+	int fd, ret;
+	DIR *dir;
+
+	memset(buf, 0, PMU_ID_MAXLEN);
+
+	this_cpu = sched_getcpu();
+	if (this_cpu < 0)
+		return -errno;
+
+	cpulist = calloc(1, PAGE_SIZE);
+	if (!cpulist)
+		die_perror("calloc");
+
+	path = calloc(1, PAGE_SIZE);
+	if (!path)
+		die_perror("calloc");
+
+	dir = opendir(SYS_EVENT_SOURCE);
+	if (!dir) {
+		pmu_id = -errno;
+		goto out_free;
+	}
+
+	/* Make the compiler happy by copying the NUL terminating byte. */
+	strncpy(path, SYS_EVENT_SOURCE, strlen(SYS_EVENT_SOURCE) + 1);
+
+	while ((dirent = readdir(dir))) {
+		if (dirent->d_type != DT_LNK)
+			continue;
+
+		strcat(path, dirent->d_name);
+		strcat(path, "/cpus");
+		fd = open(path, O_RDONLY);
+		if (fd < 0)
+			goto next_dir;
+
+		fd_sz = read_file(fd, cpulist, PAGE_SIZE);
+		if (fd_sz < 0) {
+			pmu_id = -errno;
+			goto out_free;
+		}
+		close(fd);
+
+		ret = cpulist_parse(cpulist, &cpumask);
+		if (ret) {
+			pmu_id = ret;
+			goto out_free;
+		}
+
+		if (!cpumask_test_cpu(this_cpu, &cpumask))
+			goto next_dir;
+
+		strcpy(&path[strlen(path) - 4], "type");
+		fd = open(path, O_RDONLY);
+		if (fd < 0)
+			goto next_dir;
+
+		fd_sz = read_file(fd, buf, PMU_ID_MAXLEN - 1);
+		if (fd_sz < 0) {
+			pmu_id = -errno;
+			goto out_free;
+		}
+		close(fd);
+
+		val = strtoul(buf, NULL, 10);
+		if (val > INT_MAX) {
+			pmu_id = -EOVERFLOW;
+			goto out_free;
+		}
+		pmu_id = (int)val;
+		pr_debug("Using PMU %s (id %d)", dirent->d_name, pmu_id);
+		break;
+
+next_dir:
+		/* Reset path. */
+		memset(&path[strlen(SYS_EVENT_SOURCE)], '\0',
+		       strlen(path) - strlen(SYS_EVENT_SOURCE));
+	}
+
+out_free:
+	free(path);
+	free(cpulist);
+	return pmu_id;
+}
+
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 {
 	const char compatible[] = "arm,armv8-pmuv3";
 	int irq = KVM_ARM_PMUv3_PPI;
 	struct kvm_cpu *vcpu;
+	int pmu_id = -ENXIO;
 	int i;
 
 	u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \
@@ -44,9 +173,23 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 	if (!kvm->cfg.arch.has_pmuv3)
 		return;
 
+	if (pmu_has_attr(kvm->cpus[0], KVM_ARM_VCPU_PMU_V3_SET_PMU)) {
+		pmu_id = find_pmu();
+		if (pmu_id < 0) {
+			pr_debug("Failed to find a PMU (errno: %d), "
+				 "PMU events might not work", -pmu_id);
+		}
+	}
+
 	for (i = 0; i < kvm->nrcpus; i++) {
 		vcpu = kvm->cpus[i];
 		set_pmu_attr(vcpu, &irq, KVM_ARM_VCPU_PMU_V3_IRQ);
+		/*
+		 * PMU IDs 0-5 are reserved; a positive value means a PMU was
+		 * found.
+		 */
+		if (pmu_id > 0)
+			set_pmu_attr(vcpu, &pmu_id, KVM_ARM_VCPU_PMU_V3_SET_PMU);
 		set_pmu_attr(vcpu, NULL, KVM_ARM_VCPU_PMU_V3_INIT);
 	}
 
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 10/11] arm64: Add support for KVM_ARM_VCPU_PMU_V3_SET_PMU
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

The KVM_ARM_VCPU_PMU_V3_CTRL(KVM_ARM_VCPU_PMU_V3_SET_PMU) VCPU ioctl is
used to assign a physical PMU to the events that KVM creates when emulating
the PMU for that VCPU. This is useful on heterogeneous systems, when there
is more than one hardware PMU present. All VCPUs must have the same PMU
assigned.

The assumption that is made in the implementation is that the user will pin
the kvmtool process on a set of CPUs that share the same PMU. This allows
kvmtool to set the same PMU for all VCPUs from the main thread, instead of
in the individual VCPU threads. If a VCPU thread migrates to a CPU which
has a different a PMU than the CPU on which the main thread was executing
when the PMU was set, the KVM_RUN ioctl will fail with kvm_run.exit_reason
set to KVM_EXIT_FAIL_ENTRY, and kvm_run.fail_entry will be populated with
the physical CPU ID on which the VCPU tried to execute.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/include/kvm/kvm-config-arch.h |   4 +-
 arm/aarch64/pmu.c                         | 147 +++++++++++++++++++++-
 2 files changed, 148 insertions(+), 3 deletions(-)

diff --git a/arm/aarch64/include/kvm/kvm-config-arch.h b/arm/aarch64/include/kvm/kvm-config-arch.h
index 3d39cd6d1f4e..b08ee60ee1c4 100644
--- a/arm/aarch64/include/kvm/kvm-config-arch.h
+++ b/arm/aarch64/include/kvm/kvm-config-arch.h
@@ -5,7 +5,9 @@
 	OPT_BOOLEAN('\0', "aarch32", &(cfg)->aarch32_guest,		\
 			"Run AArch32 guest"),				\
 	OPT_BOOLEAN('\0', "pmu", &(cfg)->has_pmuv3,			\
-			"Create PMUv3 device"),				\
+			"Create PMUv3 device. The emulated PMU will be" \
+			" set to the PMU associated with the"		\
+			" main thread"),				\
 	OPT_BOOLEAN('\0', "disable-mte", &(cfg)->mte_disabled,		\
 			"Disable Memory Tagging Extension"),		\
 	OPT_U64('\0', "kaslr-seed", &(cfg)->kaslr_seed,			\
diff --git a/arm/aarch64/pmu.c b/arm/aarch64/pmu.c
index ac5b7bcd6ca9..869a150cd6d3 100644
--- a/arm/aarch64/pmu.c
+++ b/arm/aarch64/pmu.c
@@ -1,3 +1,9 @@
+#include <dirent.h>
+#include <sched.h>
+
+#include "linux/cpumask.h"
+#include "linux/err.h"
+
 #include "kvm/fdt.h"
 #include "kvm/kvm.h"
 #include "kvm/kvm-cpu.h"
@@ -7,6 +13,17 @@
 
 #include "asm/pmu.h"
 
+static bool pmu_has_attr(struct kvm_cpu *vcpu, u64 attr)
+{
+	struct kvm_device_attr pmu_attr = {
+		.group	= KVM_ARM_VCPU_PMU_V3_CTRL,
+		.attr	= attr,
+	};
+	int ret = ioctl(vcpu->vcpu_fd, KVM_HAS_DEVICE_ATTR, &pmu_attr);
+
+	return ret == 0;
+}
+
 static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
 {
 	struct kvm_device_attr pmu_attr = {
@@ -16,8 +33,7 @@ static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
 	};
 	int ret;
 
-	ret = ioctl(vcpu->vcpu_fd, KVM_HAS_DEVICE_ATTR, &pmu_attr);
-	if (!ret) {
+	if (pmu_has_attr(vcpu, attr)) {
 		ret = ioctl(vcpu->vcpu_fd, KVM_SET_DEVICE_ATTR, &pmu_attr);
 		if (ret)
 			die_perror("PMU KVM_SET_DEVICE_ATTR");
@@ -26,11 +42,124 @@ static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
 	}
 }
 
+#define SYS_EVENT_SOURCE	"/sys/bus/event_source/devices/"
+/*
+ * int is 32 bits and INT_MAX translates in decimal to 2 * 10^9.
+ * Make room for newline and NUL.
+ */
+#define PMU_ID_MAXLEN		12
+
+/*
+ * In the case of homogeneous systems, there only one hardware PMU, and all
+ * VCPUs will use the same PMU, regardless of where the attribute gets set.
+ *
+ * For heterogeneous systems, the assumption is that the user has pinned the VM
+ * (via taskset or similar) to a set of CPUs that share the same hardware PMU.
+ * This simplifies things for kvmtool, as correctness is not affected by setting
+ * the PMU for each VCPU from the main thread, instead of setting it from each
+ * individual VCPU thread.
+ */
+static int find_pmu(void)
+{
+	char buf[PMU_ID_MAXLEN];
+	struct dirent *dirent;
+	char *cpulist, *path;
+	int pmu_id = -ENXIO;
+	unsigned long val;
+	cpumask_t cpumask;
+	ssize_t fd_sz;
+	int this_cpu;
+	int fd, ret;
+	DIR *dir;
+
+	memset(buf, 0, PMU_ID_MAXLEN);
+
+	this_cpu = sched_getcpu();
+	if (this_cpu < 0)
+		return -errno;
+
+	cpulist = calloc(1, PAGE_SIZE);
+	if (!cpulist)
+		die_perror("calloc");
+
+	path = calloc(1, PAGE_SIZE);
+	if (!path)
+		die_perror("calloc");
+
+	dir = opendir(SYS_EVENT_SOURCE);
+	if (!dir) {
+		pmu_id = -errno;
+		goto out_free;
+	}
+
+	/* Make the compiler happy by copying the NUL terminating byte. */
+	strncpy(path, SYS_EVENT_SOURCE, strlen(SYS_EVENT_SOURCE) + 1);
+
+	while ((dirent = readdir(dir))) {
+		if (dirent->d_type != DT_LNK)
+			continue;
+
+		strcat(path, dirent->d_name);
+		strcat(path, "/cpus");
+		fd = open(path, O_RDONLY);
+		if (fd < 0)
+			goto next_dir;
+
+		fd_sz = read_file(fd, cpulist, PAGE_SIZE);
+		if (fd_sz < 0) {
+			pmu_id = -errno;
+			goto out_free;
+		}
+		close(fd);
+
+		ret = cpulist_parse(cpulist, &cpumask);
+		if (ret) {
+			pmu_id = ret;
+			goto out_free;
+		}
+
+		if (!cpumask_test_cpu(this_cpu, &cpumask))
+			goto next_dir;
+
+		strcpy(&path[strlen(path) - 4], "type");
+		fd = open(path, O_RDONLY);
+		if (fd < 0)
+			goto next_dir;
+
+		fd_sz = read_file(fd, buf, PMU_ID_MAXLEN - 1);
+		if (fd_sz < 0) {
+			pmu_id = -errno;
+			goto out_free;
+		}
+		close(fd);
+
+		val = strtoul(buf, NULL, 10);
+		if (val > INT_MAX) {
+			pmu_id = -EOVERFLOW;
+			goto out_free;
+		}
+		pmu_id = (int)val;
+		pr_debug("Using PMU %s (id %d)", dirent->d_name, pmu_id);
+		break;
+
+next_dir:
+		/* Reset path. */
+		memset(&path[strlen(SYS_EVENT_SOURCE)], '\0',
+		       strlen(path) - strlen(SYS_EVENT_SOURCE));
+	}
+
+out_free:
+	free(path);
+	free(cpulist);
+	return pmu_id;
+}
+
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 {
 	const char compatible[] = "arm,armv8-pmuv3";
 	int irq = KVM_ARM_PMUv3_PPI;
 	struct kvm_cpu *vcpu;
+	int pmu_id = -ENXIO;
 	int i;
 
 	u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \
@@ -44,9 +173,23 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 	if (!kvm->cfg.arch.has_pmuv3)
 		return;
 
+	if (pmu_has_attr(kvm->cpus[0], KVM_ARM_VCPU_PMU_V3_SET_PMU)) {
+		pmu_id = find_pmu();
+		if (pmu_id < 0) {
+			pr_debug("Failed to find a PMU (errno: %d), "
+				 "PMU events might not work", -pmu_id);
+		}
+	}
+
 	for (i = 0; i < kvm->nrcpus; i++) {
 		vcpu = kvm->cpus[i];
 		set_pmu_attr(vcpu, &irq, KVM_ARM_VCPU_PMU_V3_IRQ);
+		/*
+		 * PMU IDs 0-5 are reserved; a positive value means a PMU was
+		 * found.
+		 */
+		if (pmu_id > 0)
+			set_pmu_attr(vcpu, &pmu_id, KVM_ARM_VCPU_PMU_V3_SET_PMU);
 		set_pmu_attr(vcpu, NULL, KVM_ARM_VCPU_PMU_V3_INIT);
 	}
 
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v3 kvmtool 11/11] arm64: Add --vcpu-affinity command line argument
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-04-12 13:32   ` Alexandru Elisei
  -1 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Add a new command line argument, --vcpu-affinity, to set the CPU affinity
for the VCPUs. The affinity is expressed as a cpulist and will apply to all
VCPU threads.

This gives the user a second option for choosing the PMU on a heterogeneous
system. The PMU setup code, when --vcpu-affinity is specified, will search
for the PMU associated with the CPUs specified with this command line
argument instead of the PMU associated with the CPU on which the main
thread is executing.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/include/kvm/kvm-config-arch.h |  7 +-
 arm/aarch64/kvm-cpu.c                     |  9 +++
 arm/aarch64/kvm.c                         | 32 +++++++++
 arm/aarch64/pmu.c                         | 79 +++++++++++++++++------
 arm/include/arm-common/kvm-arch.h         |  7 ++
 arm/include/arm-common/kvm-config-arch.h  |  1 +
 include/linux/cpumask.h                   |  5 ++
 7 files changed, 118 insertions(+), 22 deletions(-)

diff --git a/arm/aarch64/include/kvm/kvm-config-arch.h b/arm/aarch64/include/kvm/kvm-config-arch.h
index b08ee60ee1c4..eae8080d3fd9 100644
--- a/arm/aarch64/include/kvm/kvm-config-arch.h
+++ b/arm/aarch64/include/kvm/kvm-config-arch.h
@@ -1,15 +1,20 @@
 #ifndef KVM__KVM_CONFIG_ARCH_H
 #define KVM__KVM_CONFIG_ARCH_H
 
+int vcpu_affinity_parser(const struct option *opt, const char *arg, int unset);
+
 #define ARM_OPT_ARCH_RUN(cfg)						\
 	OPT_BOOLEAN('\0', "aarch32", &(cfg)->aarch32_guest,		\
 			"Run AArch32 guest"),				\
 	OPT_BOOLEAN('\0', "pmu", &(cfg)->has_pmuv3,			\
 			"Create PMUv3 device. The emulated PMU will be" \
 			" set to the PMU associated with the"		\
-			" main thread"),				\
+			" main thread, unless --vcpu-affinity is set"),	\
 	OPT_BOOLEAN('\0', "disable-mte", &(cfg)->mte_disabled,		\
 			"Disable Memory Tagging Extension"),		\
+	OPT_CALLBACK('\0', "vcpu-affinity", kvm, "cpulist",  		\
+			"Specify the CPU affinity that will apply to "	\
+			"all VCPUs", vcpu_affinity_parser, kvm),	\
 	OPT_U64('\0', "kaslr-seed", &(cfg)->kaslr_seed,			\
 			"Specify random seed for Kernel Address Space "	\
 			"Layout Randomization (KASLR)"),		\
diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c
index 3b6224a599c8..4ac0fafae06b 100644
--- a/arm/aarch64/kvm-cpu.c
+++ b/arm/aarch64/kvm-cpu.c
@@ -88,7 +88,16 @@ static void reset_vcpu_aarch64(struct kvm_cpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
 	struct kvm_one_reg reg;
+	cpu_set_t *affinity;
 	u64 data;
+	int ret;
+
+	affinity = kvm->arch.vcpu_affinity_cpuset;
+	if (affinity) {
+		ret = sched_setaffinity(0, sizeof(cpu_set_t), affinity);
+		if (ret == -1)
+			die_perror("sched_setaffinity");
+	}
 
 	reg.addr = (u64)&data;
 
diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
index 28d608d98831..1b992dd592d4 100644
--- a/arm/aarch64/kvm.c
+++ b/arm/aarch64/kvm.c
@@ -3,8 +3,40 @@
 #include <asm/image.h>
 
 #include <linux/byteorder.h>
+#include <linux/cpumask.h>
+
 #include <kvm/util.h>
 
+int vcpu_affinity_parser(const struct option *opt, const char *arg, int unset)
+{
+	struct kvm *kvm = opt->ptr;
+	const char *cpulist = arg;
+	cpumask_t *cpumask;
+	int cpu, ret;
+
+	kvm->cfg.arch.vcpu_affinity = cpulist;
+
+	cpumask = calloc(1, cpumask_size());
+	if (!cpumask)
+		die_perror("calloc");
+
+	ret = cpulist_parse(cpulist, cpumask);
+	if (ret) {
+		free(cpumask);
+		return ret;
+	}
+
+	kvm->arch.vcpu_affinity_cpuset = CPU_ALLOC(NR_CPUS);
+	if (!kvm->arch.vcpu_affinity_cpuset)
+		die_perror("CPU_ALLOC");
+	CPU_ZERO_S(CPU_ALLOC_SIZE(NR_CPUS), kvm->arch.vcpu_affinity_cpuset);
+
+	for_each_cpu(cpu, cpumask)
+		CPU_SET(cpu, kvm->arch.vcpu_affinity_cpuset);
+
+	return 0;
+}
+
 /*
  * Return the TEXT_OFFSET value that the guest kernel expects. Note
  * that pre-3.17 kernels expose this value using the native endianness
diff --git a/arm/aarch64/pmu.c b/arm/aarch64/pmu.c
index 869a150cd6d3..5f189b32b6d0 100644
--- a/arm/aarch64/pmu.c
+++ b/arm/aarch64/pmu.c
@@ -49,34 +49,19 @@ static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
  */
 #define PMU_ID_MAXLEN		12
 
-/*
- * In the case of homogeneous systems, there only one hardware PMU, and all
- * VCPUs will use the same PMU, regardless of where the attribute gets set.
- *
- * For heterogeneous systems, the assumption is that the user has pinned the VM
- * (via taskset or similar) to a set of CPUs that share the same hardware PMU.
- * This simplifies things for kvmtool, as correctness is not affected by setting
- * the PMU for each VCPU from the main thread, instead of setting it from each
- * individual VCPU thread.
- */
-static int find_pmu(void)
+static int find_pmu_cpumask(struct kvm *kvm, cpumask_t *cpumask)
 {
+	cpumask_t pmu_cpumask, tmp;
 	char buf[PMU_ID_MAXLEN];
 	struct dirent *dirent;
 	char *cpulist, *path;
 	int pmu_id = -ENXIO;
 	unsigned long val;
-	cpumask_t cpumask;
 	ssize_t fd_sz;
-	int this_cpu;
 	int fd, ret;
 	DIR *dir;
 
-	memset(buf, 0, PMU_ID_MAXLEN);
-
-	this_cpu = sched_getcpu();
-	if (this_cpu < 0)
-		return -errno;
+	memset(buf, 0, sizeof(buf));
 
 	cpulist = calloc(1, PAGE_SIZE);
 	if (!cpulist)
@@ -112,15 +97,27 @@ static int find_pmu(void)
 		}
 		close(fd);
 
-		ret = cpulist_parse(cpulist, &cpumask);
+		ret = cpulist_parse(cpulist, &pmu_cpumask);
 		if (ret) {
 			pmu_id = ret;
 			goto out_free;
 		}
 
-		if (!cpumask_test_cpu(this_cpu, &cpumask))
+		if (!cpumask_and(&tmp, cpumask, &pmu_cpumask))
 			goto next_dir;
 
+		/*
+		 * One CPU cannot more than one PMU, hence the set of CPUs which
+		 * share PMU A and the set of CPUs which share PMU B are
+		 * disjoint. If the target CPUs and the current PMU have at
+		 * least one CPU in common, but the target CPUs is not a subset
+		 * of the current PMU, then a PMU which is associated with all
+		 * the target CPUs does not exist. Stop searching for a PMU when
+		 * this happens.
+		 */
+		if (!cpumask_subset(cpumask, &pmu_cpumask))
+			goto out_free;
+
 		strcpy(&path[strlen(path) - 4], "type");
 		fd = open(path, O_RDONLY);
 		if (fd < 0)
@@ -154,6 +151,46 @@ out_free:
 	return pmu_id;
 }
 
+/*
+ * In the case of homogeneous systems, there only one hardware PMU, and all
+ * VCPUs will use the same PMU, regardless of the physical CPUs on which the
+ * VCPU threads will be executing.
+ *
+ * For heterogeneous systems, there are 2 ways for the user to ensure that the
+ * VM runs on CPUs that have the same PMU:
+ *
+ * 1. By pinning the entire VM to the desired CPUs, in which case kvmtool will
+ * choose the PMU associated with the CPU on which the main thread is executing
+ * (the thread that calls find_pmu()).
+ *
+ * 2. By setting the affinity mask for the VCPUs with the --vcpu-affinity
+ * command line argument. All CPUs in the affinity mask must have the same PMU,
+ * otherwise kvmtool will not be able to set a PMU.
+ */
+static int find_pmu(struct kvm *kvm)
+{
+	cpumask_t *cpumask;
+	int i, this_cpu;
+
+	cpumask = calloc(1, cpumask_size());
+	if (!cpumask)
+		die_perror("calloc");
+
+	if (!kvm->arch.vcpu_affinity_cpuset) {
+		this_cpu = sched_getcpu();
+		if (this_cpu < 0)
+			return -errno;
+		cpumask_set_cpu(this_cpu, cpumask);
+	} else {
+		for (i = 0; i < CPU_SETSIZE; i ++) {
+			if (CPU_ISSET(i, kvm->arch.vcpu_affinity_cpuset))
+				cpumask_set_cpu(i, cpumask);
+		}
+	}
+
+	return find_pmu_cpumask(kvm, cpumask);
+}
+
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 {
 	const char compatible[] = "arm,armv8-pmuv3";
@@ -174,7 +211,7 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 		return;
 
 	if (pmu_has_attr(kvm->cpus[0], KVM_ARM_VCPU_PMU_V3_SET_PMU)) {
-		pmu_id = find_pmu();
+		pmu_id = find_pmu(kvm);
 		if (pmu_id < 0) {
 			pr_debug("Failed to find a PMU (errno: %d), "
 				 "PMU events might not work", -pmu_id);
diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index 43b1f77df394..fc55360d4d15 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -2,6 +2,11 @@
 #define ARM_COMMON__KVM_ARCH_H
 
 #include <stdbool.h>
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <sched.h>
+
 #include <linux/const.h>
 #include <linux/types.h>
 
@@ -105,6 +110,8 @@ struct kvm_arch {
 	u64	initrd_guest_start;
 	u64	initrd_size;
 	u64	dtb_guest_start;
+
+	cpu_set_t *vcpu_affinity_cpuset;
 };
 
 #endif /* ARM_COMMON__KVM_ARCH_H */
diff --git a/arm/include/arm-common/kvm-config-arch.h b/arm/include/arm-common/kvm-config-arch.h
index cdcbf235ac4e..9949bfe47ba8 100644
--- a/arm/include/arm-common/kvm-config-arch.h
+++ b/arm/include/arm-common/kvm-config-arch.h
@@ -5,6 +5,7 @@
 
 struct kvm_config_arch {
 	const char	*dump_dtb_filename;
+	const char	*vcpu_affinity;
 	unsigned int	force_cntfrq;
 	bool		virtio_trans_pci;
 	bool		aarch32_guest;
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index c4be06621cf4..e6b764b5dd89 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -11,6 +11,11 @@ typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
 
 #define cpumask_bits(maskp)	((maskp)->bits)
 
+static inline unsigned int cpumask_size(void)
+{
+	return BITS_TO_LONGS(NR_CPUS) * sizeof(long);
+}
+
 static inline void cpumask_set_cpu(int cpu, cpumask_t *dstp)
 {
 	set_bit(cpu, cpumask_bits(dstp));
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v3 kvmtool 11/11] arm64: Add --vcpu-affinity command line argument
@ 2022-04-12 13:32   ` Alexandru Elisei
  0 siblings, 0 replies; 26+ messages in thread
From: Alexandru Elisei @ 2022-04-12 13:32 UTC (permalink / raw)
  To: will, julien.thierry.kdev, linux-arm-kernel, kvmarm, maz,
	james.morse, suzuki.poulose, mark.rutland, andre.przywara

Add a new command line argument, --vcpu-affinity, to set the CPU affinity
for the VCPUs. The affinity is expressed as a cpulist and will apply to all
VCPU threads.

This gives the user a second option for choosing the PMU on a heterogeneous
system. The PMU setup code, when --vcpu-affinity is specified, will search
for the PMU associated with the CPUs specified with this command line
argument instead of the PMU associated with the CPU on which the main
thread is executing.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
 arm/aarch64/include/kvm/kvm-config-arch.h |  7 +-
 arm/aarch64/kvm-cpu.c                     |  9 +++
 arm/aarch64/kvm.c                         | 32 +++++++++
 arm/aarch64/pmu.c                         | 79 +++++++++++++++++------
 arm/include/arm-common/kvm-arch.h         |  7 ++
 arm/include/arm-common/kvm-config-arch.h  |  1 +
 include/linux/cpumask.h                   |  5 ++
 7 files changed, 118 insertions(+), 22 deletions(-)

diff --git a/arm/aarch64/include/kvm/kvm-config-arch.h b/arm/aarch64/include/kvm/kvm-config-arch.h
index b08ee60ee1c4..eae8080d3fd9 100644
--- a/arm/aarch64/include/kvm/kvm-config-arch.h
+++ b/arm/aarch64/include/kvm/kvm-config-arch.h
@@ -1,15 +1,20 @@
 #ifndef KVM__KVM_CONFIG_ARCH_H
 #define KVM__KVM_CONFIG_ARCH_H
 
+int vcpu_affinity_parser(const struct option *opt, const char *arg, int unset);
+
 #define ARM_OPT_ARCH_RUN(cfg)						\
 	OPT_BOOLEAN('\0', "aarch32", &(cfg)->aarch32_guest,		\
 			"Run AArch32 guest"),				\
 	OPT_BOOLEAN('\0', "pmu", &(cfg)->has_pmuv3,			\
 			"Create PMUv3 device. The emulated PMU will be" \
 			" set to the PMU associated with the"		\
-			" main thread"),				\
+			" main thread, unless --vcpu-affinity is set"),	\
 	OPT_BOOLEAN('\0', "disable-mte", &(cfg)->mte_disabled,		\
 			"Disable Memory Tagging Extension"),		\
+	OPT_CALLBACK('\0', "vcpu-affinity", kvm, "cpulist",  		\
+			"Specify the CPU affinity that will apply to "	\
+			"all VCPUs", vcpu_affinity_parser, kvm),	\
 	OPT_U64('\0', "kaslr-seed", &(cfg)->kaslr_seed,			\
 			"Specify random seed for Kernel Address Space "	\
 			"Layout Randomization (KASLR)"),		\
diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c
index 3b6224a599c8..4ac0fafae06b 100644
--- a/arm/aarch64/kvm-cpu.c
+++ b/arm/aarch64/kvm-cpu.c
@@ -88,7 +88,16 @@ static void reset_vcpu_aarch64(struct kvm_cpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
 	struct kvm_one_reg reg;
+	cpu_set_t *affinity;
 	u64 data;
+	int ret;
+
+	affinity = kvm->arch.vcpu_affinity_cpuset;
+	if (affinity) {
+		ret = sched_setaffinity(0, sizeof(cpu_set_t), affinity);
+		if (ret == -1)
+			die_perror("sched_setaffinity");
+	}
 
 	reg.addr = (u64)&data;
 
diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
index 28d608d98831..1b992dd592d4 100644
--- a/arm/aarch64/kvm.c
+++ b/arm/aarch64/kvm.c
@@ -3,8 +3,40 @@
 #include <asm/image.h>
 
 #include <linux/byteorder.h>
+#include <linux/cpumask.h>
+
 #include <kvm/util.h>
 
+int vcpu_affinity_parser(const struct option *opt, const char *arg, int unset)
+{
+	struct kvm *kvm = opt->ptr;
+	const char *cpulist = arg;
+	cpumask_t *cpumask;
+	int cpu, ret;
+
+	kvm->cfg.arch.vcpu_affinity = cpulist;
+
+	cpumask = calloc(1, cpumask_size());
+	if (!cpumask)
+		die_perror("calloc");
+
+	ret = cpulist_parse(cpulist, cpumask);
+	if (ret) {
+		free(cpumask);
+		return ret;
+	}
+
+	kvm->arch.vcpu_affinity_cpuset = CPU_ALLOC(NR_CPUS);
+	if (!kvm->arch.vcpu_affinity_cpuset)
+		die_perror("CPU_ALLOC");
+	CPU_ZERO_S(CPU_ALLOC_SIZE(NR_CPUS), kvm->arch.vcpu_affinity_cpuset);
+
+	for_each_cpu(cpu, cpumask)
+		CPU_SET(cpu, kvm->arch.vcpu_affinity_cpuset);
+
+	return 0;
+}
+
 /*
  * Return the TEXT_OFFSET value that the guest kernel expects. Note
  * that pre-3.17 kernels expose this value using the native endianness
diff --git a/arm/aarch64/pmu.c b/arm/aarch64/pmu.c
index 869a150cd6d3..5f189b32b6d0 100644
--- a/arm/aarch64/pmu.c
+++ b/arm/aarch64/pmu.c
@@ -49,34 +49,19 @@ static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
  */
 #define PMU_ID_MAXLEN		12
 
-/*
- * In the case of homogeneous systems, there only one hardware PMU, and all
- * VCPUs will use the same PMU, regardless of where the attribute gets set.
- *
- * For heterogeneous systems, the assumption is that the user has pinned the VM
- * (via taskset or similar) to a set of CPUs that share the same hardware PMU.
- * This simplifies things for kvmtool, as correctness is not affected by setting
- * the PMU for each VCPU from the main thread, instead of setting it from each
- * individual VCPU thread.
- */
-static int find_pmu(void)
+static int find_pmu_cpumask(struct kvm *kvm, cpumask_t *cpumask)
 {
+	cpumask_t pmu_cpumask, tmp;
 	char buf[PMU_ID_MAXLEN];
 	struct dirent *dirent;
 	char *cpulist, *path;
 	int pmu_id = -ENXIO;
 	unsigned long val;
-	cpumask_t cpumask;
 	ssize_t fd_sz;
-	int this_cpu;
 	int fd, ret;
 	DIR *dir;
 
-	memset(buf, 0, PMU_ID_MAXLEN);
-
-	this_cpu = sched_getcpu();
-	if (this_cpu < 0)
-		return -errno;
+	memset(buf, 0, sizeof(buf));
 
 	cpulist = calloc(1, PAGE_SIZE);
 	if (!cpulist)
@@ -112,15 +97,27 @@ static int find_pmu(void)
 		}
 		close(fd);
 
-		ret = cpulist_parse(cpulist, &cpumask);
+		ret = cpulist_parse(cpulist, &pmu_cpumask);
 		if (ret) {
 			pmu_id = ret;
 			goto out_free;
 		}
 
-		if (!cpumask_test_cpu(this_cpu, &cpumask))
+		if (!cpumask_and(&tmp, cpumask, &pmu_cpumask))
 			goto next_dir;
 
+		/*
+		 * One CPU cannot more than one PMU, hence the set of CPUs which
+		 * share PMU A and the set of CPUs which share PMU B are
+		 * disjoint. If the target CPUs and the current PMU have at
+		 * least one CPU in common, but the target CPUs is not a subset
+		 * of the current PMU, then a PMU which is associated with all
+		 * the target CPUs does not exist. Stop searching for a PMU when
+		 * this happens.
+		 */
+		if (!cpumask_subset(cpumask, &pmu_cpumask))
+			goto out_free;
+
 		strcpy(&path[strlen(path) - 4], "type");
 		fd = open(path, O_RDONLY);
 		if (fd < 0)
@@ -154,6 +151,46 @@ out_free:
 	return pmu_id;
 }
 
+/*
+ * In the case of homogeneous systems, there only one hardware PMU, and all
+ * VCPUs will use the same PMU, regardless of the physical CPUs on which the
+ * VCPU threads will be executing.
+ *
+ * For heterogeneous systems, there are 2 ways for the user to ensure that the
+ * VM runs on CPUs that have the same PMU:
+ *
+ * 1. By pinning the entire VM to the desired CPUs, in which case kvmtool will
+ * choose the PMU associated with the CPU on which the main thread is executing
+ * (the thread that calls find_pmu()).
+ *
+ * 2. By setting the affinity mask for the VCPUs with the --vcpu-affinity
+ * command line argument. All CPUs in the affinity mask must have the same PMU,
+ * otherwise kvmtool will not be able to set a PMU.
+ */
+static int find_pmu(struct kvm *kvm)
+{
+	cpumask_t *cpumask;
+	int i, this_cpu;
+
+	cpumask = calloc(1, cpumask_size());
+	if (!cpumask)
+		die_perror("calloc");
+
+	if (!kvm->arch.vcpu_affinity_cpuset) {
+		this_cpu = sched_getcpu();
+		if (this_cpu < 0)
+			return -errno;
+		cpumask_set_cpu(this_cpu, cpumask);
+	} else {
+		for (i = 0; i < CPU_SETSIZE; i ++) {
+			if (CPU_ISSET(i, kvm->arch.vcpu_affinity_cpuset))
+				cpumask_set_cpu(i, cpumask);
+		}
+	}
+
+	return find_pmu_cpumask(kvm, cpumask);
+}
+
 void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 {
 	const char compatible[] = "arm,armv8-pmuv3";
@@ -174,7 +211,7 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
 		return;
 
 	if (pmu_has_attr(kvm->cpus[0], KVM_ARM_VCPU_PMU_V3_SET_PMU)) {
-		pmu_id = find_pmu();
+		pmu_id = find_pmu(kvm);
 		if (pmu_id < 0) {
 			pr_debug("Failed to find a PMU (errno: %d), "
 				 "PMU events might not work", -pmu_id);
diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index 43b1f77df394..fc55360d4d15 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -2,6 +2,11 @@
 #define ARM_COMMON__KVM_ARCH_H
 
 #include <stdbool.h>
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <sched.h>
+
 #include <linux/const.h>
 #include <linux/types.h>
 
@@ -105,6 +110,8 @@ struct kvm_arch {
 	u64	initrd_guest_start;
 	u64	initrd_size;
 	u64	dtb_guest_start;
+
+	cpu_set_t *vcpu_affinity_cpuset;
 };
 
 #endif /* ARM_COMMON__KVM_ARCH_H */
diff --git a/arm/include/arm-common/kvm-config-arch.h b/arm/include/arm-common/kvm-config-arch.h
index cdcbf235ac4e..9949bfe47ba8 100644
--- a/arm/include/arm-common/kvm-config-arch.h
+++ b/arm/include/arm-common/kvm-config-arch.h
@@ -5,6 +5,7 @@
 
 struct kvm_config_arch {
 	const char	*dump_dtb_filename;
+	const char	*vcpu_affinity;
 	unsigned int	force_cntfrq;
 	bool		virtio_trans_pci;
 	bool		aarch32_guest;
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index c4be06621cf4..e6b764b5dd89 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -11,6 +11,11 @@ typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
 
 #define cpumask_bits(maskp)	((maskp)->bits)
 
+static inline unsigned int cpumask_size(void)
+{
+	return BITS_TO_LONGS(NR_CPUS) * sizeof(long);
+}
+
 static inline void cpumask_set_cpu(int cpu, cpumask_t *dstp)
 {
 	set_bit(cpu, cpumask_bits(dstp));
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v3 kvmtool 00/11] arm64: Improve PMU support on heterogeneous systems
  2022-04-12 13:32 ` Alexandru Elisei
@ 2022-05-06 14:43   ` Will Deacon
  -1 siblings, 0 replies; 26+ messages in thread
From: Will Deacon @ 2022-05-06 14:43 UTC (permalink / raw)
  To: andre.przywara, linux-arm-kernel, suzuki.poulose, maz,
	james.morse, Alexandru Elisei, julien.thierry.kdev, mark.rutland,
	kvmarm
  Cc: catalin.marinas, kernel-team, Will Deacon

On Tue, 12 Apr 2022 14:32:20 +0100, Alexandru Elisei wrote:
> The series can be found at [1].
> 
> The series adds support for the KVM_ARM_VCPU_PMU_V3_SET_PMU PMU attribute,
> which allows userspace to set a PMU for a VCPU. This PMU is used by KVM
> when creating perf events to emulate the guest PMU.
> 
> Without settings this attribute, the PMU used when creating events is the
> first one that successfully probed when booting, but this is unreliable as
> the probe order can change (if the order of the PMUs is changed in the DTB
> or if asynchronous driver probing is enabled on the host's command line),
> and furthermore it requires the user to have intimate knowledge of how the
> PMU was chosen in order to pin the VM on the correct physical CPUs.
> 
> [...]

Applied to kvmtool (master), thanks!

[01/11] linux/err.h: Add missing stdbool.h include
        https://git.kernel.org/will/kvmtool/c/443cd881b471
[02/11] linux/bitops.h: Include wordsize.h to provide the __WORDSIZE define
        https://git.kernel.org/will/kvmtool/c/d9b64eb6aa05
[03/11] arm/arm64: pmu.h: Add missing header guards
        https://git.kernel.org/will/kvmtool/c/5898515dc727
[04/11] arm: Move arch specific VCPU features to the arch specific function
        https://git.kernel.org/will/kvmtool/c/412ee1375de8
[05/11] arm: Get rid of the ARM_VCPU_FEATURE_FLAGS() macro
        https://git.kernel.org/will/kvmtool/c/b23aed2ae11e
[06/11] arm: Make the PMUv3 emulation code arm64 specific
        https://git.kernel.org/will/kvmtool/c/f57ce4477092
[07/11] arm64: Rework set_pmu_attr()
        https://git.kernel.org/will/kvmtool/c/83713e75cd65
[08/11] Add cpumask functions
        https://git.kernel.org/will/kvmtool/c/0febaae00bb6
[09/11] update_headers.sh: Sync ABI headers with Linux v5.18-rc2
        https://git.kernel.org/will/kvmtool/c/083a976e0f08
[10/11] arm64: Add support for KVM_ARM_VCPU_PMU_V3_SET_PMU
        https://git.kernel.org/will/kvmtool/c/1393bda01407
[11/11] arm64: Add --vcpu-affinity command line argument
        https://git.kernel.org/will/kvmtool/c/4639b72f61a3

Cheers,
-- 
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH v3 kvmtool 00/11] arm64: Improve PMU support on heterogeneous systems
@ 2022-05-06 14:43   ` Will Deacon
  0 siblings, 0 replies; 26+ messages in thread
From: Will Deacon @ 2022-05-06 14:43 UTC (permalink / raw)
  To: andre.przywara, linux-arm-kernel, suzuki.poulose, maz,
	james.morse, Alexandru Elisei, julien.thierry.kdev, mark.rutland,
	kvmarm
  Cc: catalin.marinas, kernel-team, Will Deacon

On Tue, 12 Apr 2022 14:32:20 +0100, Alexandru Elisei wrote:
> The series can be found at [1].
> 
> The series adds support for the KVM_ARM_VCPU_PMU_V3_SET_PMU PMU attribute,
> which allows userspace to set a PMU for a VCPU. This PMU is used by KVM
> when creating perf events to emulate the guest PMU.
> 
> Without settings this attribute, the PMU used when creating events is the
> first one that successfully probed when booting, but this is unreliable as
> the probe order can change (if the order of the PMUs is changed in the DTB
> or if asynchronous driver probing is enabled on the host's command line),
> and furthermore it requires the user to have intimate knowledge of how the
> PMU was chosen in order to pin the VM on the correct physical CPUs.
> 
> [...]

Applied to kvmtool (master), thanks!

[01/11] linux/err.h: Add missing stdbool.h include
        https://git.kernel.org/will/kvmtool/c/443cd881b471
[02/11] linux/bitops.h: Include wordsize.h to provide the __WORDSIZE define
        https://git.kernel.org/will/kvmtool/c/d9b64eb6aa05
[03/11] arm/arm64: pmu.h: Add missing header guards
        https://git.kernel.org/will/kvmtool/c/5898515dc727
[04/11] arm: Move arch specific VCPU features to the arch specific function
        https://git.kernel.org/will/kvmtool/c/412ee1375de8
[05/11] arm: Get rid of the ARM_VCPU_FEATURE_FLAGS() macro
        https://git.kernel.org/will/kvmtool/c/b23aed2ae11e
[06/11] arm: Make the PMUv3 emulation code arm64 specific
        https://git.kernel.org/will/kvmtool/c/f57ce4477092
[07/11] arm64: Rework set_pmu_attr()
        https://git.kernel.org/will/kvmtool/c/83713e75cd65
[08/11] Add cpumask functions
        https://git.kernel.org/will/kvmtool/c/0febaae00bb6
[09/11] update_headers.sh: Sync ABI headers with Linux v5.18-rc2
        https://git.kernel.org/will/kvmtool/c/083a976e0f08
[10/11] arm64: Add support for KVM_ARM_VCPU_PMU_V3_SET_PMU
        https://git.kernel.org/will/kvmtool/c/1393bda01407
[11/11] arm64: Add --vcpu-affinity command line argument
        https://git.kernel.org/will/kvmtool/c/4639b72f61a3

Cheers,
-- 
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2022-05-06 14:44 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-12 13:32 [PATCH v3 kvmtool 00/11] arm64: Improve PMU support on heterogeneous systems Alexandru Elisei
2022-04-12 13:32 ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 01/11] linux/err.h: Add missing stdbool.h include Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 02/11] linux/bitops.h: Include wordsize.h to provide the __WORDSIZE define Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 03/11] arm/arm64: pmu.h: Add missing header guards Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 04/11] arm: Move arch specific VCPU features to the arch specific function Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 05/11] arm: Get rid of the ARM_VCPU_FEATURE_FLAGS() macro Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 06/11] arm: Make the PMUv3 emulation code arm64 specific Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 07/11] arm64: Rework set_pmu_attr() Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 08/11] Add cpumask functions Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 09/11] update_headers.sh: Sync ABI headers with Linux v5.18-rc2 Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 10/11] arm64: Add support for KVM_ARM_VCPU_PMU_V3_SET_PMU Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-04-12 13:32 ` [PATCH v3 kvmtool 11/11] arm64: Add --vcpu-affinity command line argument Alexandru Elisei
2022-04-12 13:32   ` Alexandru Elisei
2022-05-06 14:43 ` [PATCH v3 kvmtool 00/11] arm64: Improve PMU support on heterogeneous systems Will Deacon
2022-05-06 14:43   ` Will Deacon

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.