All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/20] Enable build of full Xen for RISC-V
@ 2024-03-15 18:05 Oleksii Kurochko
  2024-03-15 18:05 ` [PATCH v6 01/20] automation: introduce fixed randconfig " Oleksii Kurochko
                   ` (19 more replies)
  0 siblings, 20 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:05 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Doug Goldstein, Stefano Stabellini,
	Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Jan Beulich, Julien Grall, Wei Liu,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk,
	Shawn Anastasio, Roger Pau Monné,
	Rahul Singh, Tamas K Lengyel, Alexandru Isaila, Petre Pircalabu

This patch series performs all of the additions necessary to drop the
build overrides for RISCV and enable the full Xen build. Except in cases
where compatibile implementations already exist (e.g. atomic.h and
bitops.h), the newly added definitions are simple.

The patch series is based on the following patch series:
- [PATCH 0/7] xen/bitops: Reduce the mess, starting with ffs() [1]
- [PATCH] move __read_mostly to xen/cache.h  [2]
- [XEN PATCH v2 1/3] xen: introduce STATIC_ASSERT_UNREACHABLE() [3]


Right now, the patch series doesn't have a direct dependency on [2] and it
provides __read_mostly in the patch:
    [PATCH v3 26/34] xen/riscv: add definition of __read_mostly
However, it will be dropped as soon as [2] is merged or at least when the
final version of the patch [2] is provided.

[1] https://lore.kernel.org/xen-devel/20240313172716.2325427-1-andrew.cooper3@citrix.com/T/#t
[2] https://lore.kernel.org/xen-devel/f25eb5c9-7c14-6e23-8535-2c66772b333e@suse.com/
[3] https://lore.kernel.org/xen-devel/42fc6ae8d3eb802429d29c774502ff232340dc84.1706259490.git.federico.serafini@bugseng.com/

---
Changes in V6:
 - Update the cover letter message: drop already merged dependecies and add
   a new one.
 - Patches were merged to staging:
   - [PATCH v5 02/23] xen/riscv: use some asm-generic headers ( even v4 was
     merged to staging branch, I just wasn't apply changes on top of the latest staging branch )
   - [PATCH v5 03/23] xen/riscv: introduce nospec.h
   - [PATCH v5 10/23] xen/riscv: introduces acrquire, release and full barriers
 - Introduce new patches:
   - xen/riscv: introduce extenstion support check by compiler
   - xen/bitops: put __ffs() and ffz() into linux compatible header
   - xen/bitops: implement fls{l}() in common logic
 - The following patches were dropped:
   - drop some patches related to bitops operations as they were introduced in another
     patch series [...]
   - introduce new version for generic __ffs(), ffz() and fls{l}().
 - Merge patch from patch series "[PATCH v9 0/7]  Introduce generic headers" to this patch
   series as only one patch left in the generic headers patch series and it is more about
   RISC-V.
 - Other changes are specific to specific patches. please look at specific patch.
---
Changes in V5:
 - Update the cover letter as one of the dependencies were merged to staging.
 - Was introduced asm-generic for atomic ops and separate patches for asm-generic bit ops
 - Moved fence.h to separate patch to deal with some patches dependecies on fence.h
 - Patches were dropped as they were merged to staging:
   * [PATCH v4 03/30] xen: add support in public/hvm/save.h for PPC and RISC-V
   * [PATCH v4 04/30] xen/riscv: introduce cpufeature.h
   * [PATCH v4 05/30] xen/riscv: introduce guest_atomics.h
   * [PATCH v4 06/30] xen: avoid generation of empty asm/iommu.h
   * [PATCH v4 08/30] xen/riscv: introduce setup.h
   * [PATCH v4 10/30] xen/riscv: introduce flushtlb.h
   * [PATCH v4 11/30] xen/riscv: introduce smp.h
   * [PATCH v4 15/30] xen/riscv: introduce irq.h
   * [PATCH v4 16/30] xen/riscv: introduce p2m.h
   * [PATCH v4 17/30] xen/riscv: introduce regs.h
   * [PATCH v4 18/30] xen/riscv: introduce time.h
   * [PATCH v4 19/30] xen/riscv: introduce event.h
   * [PATCH v4 22/30] xen/riscv: define an address of frame table
 - Other changes are specific to specific patches. please look at specific patch
---
Changes in V4:
 - Update the cover letter message: new patch series dependencies.
 - Some patches were merged to staging, so they were dropped in this patch series:
     [PATCH v3 09/34] xen/riscv: introduce system.h
     [PATCH v3 18/34] xen/riscv: introduce domain.h
     [PATCH v3 19/34] xen/riscv: introduce guest_access.h
 - Was sent out of this patch series:
     [PATCH v3 16/34] xen/lib: introduce generic find next bit operations
 - [PATCH v3 17/34] xen/riscv: add compilation of generic find-next-bit.c was
   droped as CONFIG_GENERIC_FIND_NEXT_BIT was dropped.
 - All other changes are specific to a specific patch.
---
Changes in V3:
 - Update the cover letter message
 - The following patches were dropped as they were merged to staging:
    [PATCH v2 03/39] xen/riscv:introduce asm/byteorder.h
    [PATCH v2 04/39] xen/riscv: add public arch-riscv.h
    [PATCH v2 05/39] xen/riscv: introduce spinlock.h
    [PATCH v2 20/39] xen/riscv: define bug frame tables in xen.lds.S
    [PATCH v2 34/39] xen: add RISCV support for pmu.h
    [PATCH v2 35/39] xen: add necessary headers to common to build full Xen for RISC-V
 - Instead of the following patches were introduced new:
    [PATCH v2 10/39] xen/riscv: introduce asm/iommu.h
    [PATCH v2 11/39] xen/riscv: introduce asm/nospec.h
 - remove "asm/"  for commit messages which start with "xen/riscv:"
 - code style updates.
 - add emulation of {cmp}xchg_* for 1 and 2 bytes types.
 - code style fixes.
 - add SPDX and footer for the newly added headers.
 - introduce generic find-next-bit.c.
 - some other mionor changes. ( details please find in a patch )
---
Changes in V2:
  - Drop the following patches as they are the part of [2]:
      [PATCH v1 06/57] xen/riscv: introduce paging.h
      [PATCH v1 08/57] xen/riscv: introduce asm/device.h
      [PATCH v1 10/57] xen/riscv: introduce asm/grant_table.h
      [PATCH v1 12/57] xen/riscv: introduce asm/hypercall.h
      [PATCH v1 13/57] xen/riscv: introduce asm/iocap.h
      [PATCH v1 15/57] xen/riscv: introduce asm/mem_access.h
      [PATCH v1 18/57] xen/riscv: introduce asm/random.h
      [PATCH v1 21/57] xen/riscv: introduce asm/xenoprof.h
      [PATCH v1 24/57] xen/riscv: introduce asm/percpu.h
      [PATCH v1 29/57] xen/riscv: introduce asm/hardirq.h
      [PATCH v1 33/57] xen/riscv: introduce asm/altp2m.h
      [PATCH v1 38/57] xen/riscv: introduce asm/monitor.h
      [PATCH v1 39/57] xen/riscv: introduce asm/numa.h
      [PATCH v1 42/57] xen/riscv: introduce asm/softirq.h
  - xen/lib.h in most of the cases were changed to xen/bug.h as
    mostly functionilty of bug.h is used.
  - align arch-riscv.h with Arm's version of it.
  - change the Author of commit with introduction of asm/atomic.h.
  - update some definition from spinlock.h.
  - code style changes.
---

Oleksii Kurochko (20):
  automation: introduce fixed randconfig for RISC-V
  xen/riscv: disable unnecessary configs
  xen/riscv: introduce extenstion support check by compiler
  xen/asm-generic: introduce generic non-atomic test_*bit()
  xen/bitops: implement fls{l}() in common logic
  xen/bitops: put __ffs() and ffz() into linux compatible header
  xen/riscv: introduce bitops.h
  xen/riscv: introduce cmpxchg.h
  xen/riscv: introduce io.h
  xen/riscv: introduce atomic.h
  xen/riscv: introduce monitor.h
  xen/riscv: add definition of __read_mostly
  xen/riscv: add required things to current.h
  xen/riscv: add minimal stuff to page.h to build full Xen
  xen/riscv: add minimal stuff to processor.h to build full Xen
  xen/riscv: add minimal stuff to mm.h to build full Xen
  xen/riscv: introduce vm_event_*() functions
  xen/riscv: add minimal amount of stubs to build full Xen
  xen/riscv: enable full Xen build
  xen/README: add compiler and binutils versions for RISC-V64

 README                                        |   4 +
 automation/gitlab-ci/build.yaml               |  38 +-
 docs/misc/riscv/booting.txt                   |  16 +
 xen/arch/arm/include/asm/arm32/bitops.h       |   2 +-
 xen/arch/arm/include/asm/arm64/bitops.h       |  27 +-
 xen/arch/arm/include/asm/bitops.h             |   7 +-
 xen/arch/ppc/include/asm/bitops.h             |  24 -
 xen/arch/riscv/Makefile                       |  18 +-
 xen/arch/riscv/arch.mk                        |  14 +-
 xen/arch/riscv/configs/tiny64_defconfig       |  17 +
 xen/arch/riscv/early_printk.c                 | 168 -------
 xen/arch/riscv/include/asm/atomic.h           | 263 +++++++++++
 xen/arch/riscv/include/asm/bitops.h           | 144 ++++++
 xen/arch/riscv/include/asm/cache.h            |   2 +
 xen/arch/riscv/include/asm/cmpxchg.h          | 209 +++++++++
 xen/arch/riscv/include/asm/config.h           |   2 +
 xen/arch/riscv/include/asm/current.h          |  19 +
 xen/arch/riscv/include/asm/io.h               | 167 +++++++
 xen/arch/riscv/include/asm/mm.h               | 240 ++++++++++
 xen/arch/riscv/include/asm/monitor.h          |  26 ++
 xen/arch/riscv/include/asm/page.h             |  19 +
 xen/arch/riscv/include/asm/processor.h        |  20 +
 xen/arch/riscv/mm.c                           |  52 ++-
 xen/arch/riscv/setup.c                        |  10 +-
 xen/arch/riscv/stubs.c                        | 415 ++++++++++++++++++
 xen/arch/riscv/traps.c                        |  25 ++
 xen/arch/riscv/vm_event.c                     |  19 +
 xen/arch/x86/include/asm/bitops.h             |   6 +-
 xen/common/bitops.c                           |  22 +
 xen/drivers/passthrough/arm/smmu-v3.c         |   2 +
 xen/include/asm-generic/atomic-ops.h          |  97 ++++
 xen/include/asm-generic/bitops/bitops-bits.h  |  21 +
 .../asm-generic/bitops/generic-non-atomic.h   |  89 ++++
 xen/include/asm-generic/bitops/test-bit.h     |  18 +
 xen/include/xen/bitops.h                      |  24 +
 xen/include/xen/linux-compat.h                |   3 +
 xen/lib/find-next-bit.c                       |   1 +
 37 files changed, 2012 insertions(+), 238 deletions(-)
 create mode 100644 docs/misc/riscv/booting.txt
 create mode 100644 xen/arch/riscv/include/asm/atomic.h
 create mode 100644 xen/arch/riscv/include/asm/bitops.h
 create mode 100644 xen/arch/riscv/include/asm/cmpxchg.h
 create mode 100644 xen/arch/riscv/include/asm/io.h
 create mode 100644 xen/arch/riscv/include/asm/monitor.h
 create mode 100644 xen/arch/riscv/stubs.c
 create mode 100644 xen/arch/riscv/vm_event.c
 create mode 100644 xen/include/asm-generic/atomic-ops.h
 create mode 100644 xen/include/asm-generic/bitops/bitops-bits.h
 create mode 100644 xen/include/asm-generic/bitops/generic-non-atomic.h
 create mode 100644 xen/include/asm-generic/bitops/test-bit.h

-- 
2.43.0



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

* [PATCH v6 01/20] automation: introduce fixed randconfig for RISC-V
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
@ 2024-03-15 18:05 ` Oleksii Kurochko
  2024-03-15 18:05 ` [PATCH v6 02/20] xen/riscv: disable unnecessary configs Oleksii Kurochko
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:05 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Doug Goldstein, Stefano Stabellini, Michal Orzel

This patch introduces the anchor riscv-fixed-randconfig,
which includes all configurations that should be disabled for
randconfig builds.

Suggested-by: Stefano Stabellini <sstabellini@kernel.org>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
---
Changes in V6:
 - new patch for this patch series
 - Reviewed-by and Acked-by was added. ( in another patch series they were
   recieved. )
---
 automation/gitlab-ci/build.yaml | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/automation/gitlab-ci/build.yaml b/automation/gitlab-ci/build.yaml
index 6d2cb18b88..aac29ee13a 100644
--- a/automation/gitlab-ci/build.yaml
+++ b/automation/gitlab-ci/build.yaml
@@ -512,6 +512,14 @@ alpine-3.18-gcc-debug-arm64-boot-cpupools:
       CONFIG_BOOT_TIME_CPUPOOLS=y
 
 # RISC-V 64 cross-build
+.riscv-fixed-randconfig:
+  variables: &riscv-fixed-randconfig
+    EXTRA_FIXED_RANDCONFIG: |
+      CONFIG_COVERAGE=n
+      CONFIG_EXPERT=y
+      CONFIG_GRANT_TABLE=n
+      CONFIG_MEM_ACCESS=n
+
 archlinux-current-gcc-riscv64:
   extends: .gcc-riscv64-cross-build
   variables:
@@ -532,8 +540,7 @@ archlinux-current-gcc-riscv64-randconfig:
     CONTAINER: archlinux:current-riscv64
     KBUILD_DEFCONFIG: tiny64_defconfig
     RANDCONFIG: y
-    EXTRA_FIXED_RANDCONFIG:
-      CONFIG_COVERAGE=n
+    <<: *riscv-fixed-randconfig
 
 archlinux-current-gcc-riscv64-debug-randconfig:
   extends: .gcc-riscv64-cross-build-debug
@@ -541,8 +548,7 @@ archlinux-current-gcc-riscv64-debug-randconfig:
     CONTAINER: archlinux:current-riscv64
     KBUILD_DEFCONFIG: tiny64_defconfig
     RANDCONFIG: y
-    EXTRA_FIXED_RANDCONFIG:
-      CONFIG_COVERAGE=n
+    <<: *riscv-fixed-randconfig
 
 # Power cross-build
 debian-bullseye-gcc-ppc64le:
-- 
2.43.0



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

* [PATCH v6 02/20] xen/riscv: disable unnecessary configs
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
  2024-03-15 18:05 ` [PATCH v6 01/20] automation: introduce fixed randconfig " Oleksii Kurochko
@ 2024-03-15 18:05 ` Oleksii Kurochko
  2024-03-18  7:54   ` Jan Beulich
  2024-03-15 18:05 ` [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler Oleksii Kurochko
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:05 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Doug Goldstein, Stefano Stabellini,
	Alistair Francis, Bob Eshleman, Connor Davis

This patch disables unnecessary configs for two cases:
1. By utilizing EXTRA_FIXED_RANDCONFIG for randconfig builds (GitLab CI jobs).
2. By using tiny64_defconfig for non-randconfig builds.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - Nothing changed. Only rebase.
---
Changes in V5:
 - Rebase and drop duplicated configs in EXTRA_FIXED_RANDCONFIG list
 - Update the commit message
---
Changes in V4:
 - Nothing changed. Only rebase
---
Changes in V3:
 - Remove EXTRA_FIXED_RANDCONFIG for non-randconfig jobs.
   For non-randconfig jobs, it is sufficient to disable configs by using the defconfig.
 - Remove double blank lines in build.yaml file before archlinux-current-gcc-riscv64-debug
---
Changes in V2:
 - update the commit message.
 - remove xen/arch/riscv/Kconfig changes.
---
 automation/gitlab-ci/build.yaml         | 24 ++++++++++++++++++++++++
 xen/arch/riscv/configs/tiny64_defconfig | 17 +++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/automation/gitlab-ci/build.yaml b/automation/gitlab-ci/build.yaml
index aac29ee13a..3b3d2c47dc 100644
--- a/automation/gitlab-ci/build.yaml
+++ b/automation/gitlab-ci/build.yaml
@@ -519,6 +519,30 @@ alpine-3.18-gcc-debug-arm64-boot-cpupools:
       CONFIG_EXPERT=y
       CONFIG_GRANT_TABLE=n
       CONFIG_MEM_ACCESS=n
+      CONFIG_SCHED_CREDIT=n
+      CONFIG_SCHED_CREDIT2=n
+      CONFIG_SCHED_RTDS=n
+      CONFIG_SCHED_NULL=n
+      CONFIG_SCHED_ARINC653=n
+      CONFIG_TRACEBUFFER=n
+      CONFIG_HYPFS=n
+      CONFIG_SPECULATIVE_HARDEN_ARRAY=n
+      CONFIG_ARGO=n
+      CONFIG_HYPFS_CONFIG=n
+      CONFIG_CORE_PARKING=n
+      CONFIG_DEBUG_TRACE=n
+      CONFIG_IOREQ_SERVER=n
+      CONFIG_CRASH_DEBUG=n
+      CONFIG_KEXEC=n
+      CONFIG_LIVEPATCH=n
+      CONFIG_NUMA=n
+      CONFIG_PERF_COUNTERS=n
+      CONFIG_HAS_PMAP=n
+      CONFIG_XENOPROF=n
+      CONFIG_COMPAT=n
+      CONFIG_UBSAN=n
+      CONFIG_NEEDS_LIBELF=n
+      CONFIG_XSM=n
 
 archlinux-current-gcc-riscv64:
   extends: .gcc-riscv64-cross-build
diff --git a/xen/arch/riscv/configs/tiny64_defconfig b/xen/arch/riscv/configs/tiny64_defconfig
index 09defe236b..35915255e6 100644
--- a/xen/arch/riscv/configs/tiny64_defconfig
+++ b/xen/arch/riscv/configs/tiny64_defconfig
@@ -7,6 +7,23 @@
 # CONFIG_GRANT_TABLE is not set
 # CONFIG_SPECULATIVE_HARDEN_ARRAY is not set
 # CONFIG_MEM_ACCESS is not set
+# CONFIG_ARGO is not set
+# CONFIG_HYPFS_CONFIG is not set
+# CONFIG_CORE_PARKING is not set
+# CONFIG_DEBUG_TRACE is not set
+# CONFIG_IOREQ_SERVER is not set
+# CONFIG_CRASH_DEBUG is not setz
+# CONFIG_KEXEC is not set
+# CONFIG_LIVEPATCH is not set
+# CONFIG_NUMA is not set
+# CONFIG_PERF_COUNTERS is not set
+# CONFIG_HAS_PMAP is not set
+# CONFIG_TRACEBUFFER is not set
+# CONFIG_XENOPROF is not set
+# CONFIG_COMPAT is not set
+# CONFIG_COVERAGE is not set
+# CONFIG_UBSAN is not set
+# CONFIG_NEEDS_LIBELF is not set
 
 CONFIG_RISCV_64=y
 CONFIG_DEBUG=y
-- 
2.43.0



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

* [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
  2024-03-15 18:05 ` [PATCH v6 01/20] automation: introduce fixed randconfig " Oleksii Kurochko
  2024-03-15 18:05 ` [PATCH v6 02/20] xen/riscv: disable unnecessary configs Oleksii Kurochko
@ 2024-03-15 18:05 ` Oleksii Kurochko
  2024-03-18 16:58   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 04/20] xen/asm-generic: introduce generic non-atomic test_*bit() Oleksii Kurochko
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:05 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Andrew Cooper, George Dunlap, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu, Alistair Francis,
	Bob Eshleman, Connor Davis

Currently, RISC-V requires two extensions: _zbb and _zihintpause.

This patch introduces a compiler check to check if these extensions
are supported.
Additionally, it introduces the riscv/booting.txt file, which contains
information about the extensions that should be supported by the platform.

In the future, a feature will be introduced to check whether an extension
is supported at runtime.
However, this feature requires functionality for parsing device tree
source (DTS), which is not yet available.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - new patch for this patch series
---
 docs/misc/riscv/booting.txt | 16 ++++++++++++++++
 xen/arch/riscv/arch.mk      | 10 ++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 docs/misc/riscv/booting.txt

diff --git a/docs/misc/riscv/booting.txt b/docs/misc/riscv/booting.txt
new file mode 100644
index 0000000000..cb4d79f12c
--- /dev/null
+++ b/docs/misc/riscv/booting.txt
@@ -0,0 +1,16 @@
+System requirements
+===================
+
+The following extensions are expected to be supported by a system on which
+Xen is run:
+- Zbb:
+  RISC-V doesn't have a CLZ instruction in the base ISA.
+  As a consequence, __builtin_ffs() emits a library call to ffs() on GCC,
+  or a de Bruijn sequence on Clang.
+  Zbb extension adds a CLZ instruction, after which __builtin_ffs() emits
+  a very simple sequence.
+  The similar issue occurs with other __builtin_<bitop>, so it is needed to
+  provide a generic version of bitops in RISC-V bitops.h
+- Zihintpause:
+  On a system that doesn't have this extension, cpu_relax() should be
+  implemented properly.
diff --git a/xen/arch/riscv/arch.mk b/xen/arch/riscv/arch.mk
index 8403f96b6f..da6f8c82eb 100644
--- a/xen/arch/riscv/arch.mk
+++ b/xen/arch/riscv/arch.mk
@@ -3,16 +3,22 @@
 
 $(call cc-options-add,CFLAGS,CC,$(EMBEDDED_EXTRA_CFLAGS))
 
-CFLAGS-$(CONFIG_RISCV_64) += -mabi=lp64
+riscv-abi-$(CONFIG_RISCV_32) := -mabi=ilp32
+riscv-abi-$(CONFIG_RISCV_64) := -mabi=lp64
 
 riscv-march-$(CONFIG_RISCV_ISA_RV64G) := rv64g
 riscv-march-$(CONFIG_RISCV_ISA_C)       := $(riscv-march-y)c
 
+extensions := $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-march-y)_zbb,"",_zbb) \
+              $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-march-y)_zihintpause,"pause",_zihintpause)
+
+extensions := $(subst $(space),,$(extensions))
+
 # Note that -mcmodel=medany is used so that Xen can be mapped
 # into the upper half _or_ the lower half of the address space.
 # -mcmodel=medlow would force Xen into the lower half.
 
-CFLAGS += -march=$(riscv-march-y) -mstrict-align -mcmodel=medany
+CFLAGS += $(riscv-abi-y) -march=$(riscv-march-y)$(extensions) -mstrict-align -mcmodel=medany
 
 # TODO: Drop override when more of the build is working
 override ALL_OBJS-y = arch/$(SRCARCH)/built_in.o
-- 
2.43.0



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

* [PATCH v6 04/20] xen/asm-generic: introduce generic non-atomic test_*bit()
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (2 preceding siblings ...)
  2024-03-15 18:05 ` [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-20 15:30   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 05/20] xen/bitops: implement fls{l}() in common logic Oleksii Kurochko
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Andrew Cooper, George Dunlap, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu

The patch introduces the following generic functions:
* test_bit
* generic___test_and_set_bit
* generic___test_and_clear_bit
* generic___test_and_change_bit

Also, the patch introduces the following generics which are
used by the functions mentioned above:
* BITOP_BITS_PER_WORD
* BITOP_MASK
* BITOP_WORD
* BITOP_TYPE

These functions and macros can be useful for architectures
that don't have corresponding arch-specific instructions.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
 Changes in V6:
  - Nothing changed ( only rebase )
---
 Changes in V5:
   - new patch
---
 xen/include/asm-generic/bitops/bitops-bits.h  | 21 +++++
 .../asm-generic/bitops/generic-non-atomic.h   | 89 +++++++++++++++++++
 xen/include/asm-generic/bitops/test-bit.h     | 18 ++++
 3 files changed, 128 insertions(+)
 create mode 100644 xen/include/asm-generic/bitops/bitops-bits.h
 create mode 100644 xen/include/asm-generic/bitops/generic-non-atomic.h
 create mode 100644 xen/include/asm-generic/bitops/test-bit.h

diff --git a/xen/include/asm-generic/bitops/bitops-bits.h b/xen/include/asm-generic/bitops/bitops-bits.h
new file mode 100644
index 0000000000..4ece2affd6
--- /dev/null
+++ b/xen/include/asm-generic/bitops/bitops-bits.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_GENERIC_BITOPS_BITS_H_
+#define _ASM_GENERIC_BITOPS_BITS_H_
+
+#ifndef BITOP_BITS_PER_WORD
+#define BITOP_BITS_PER_WORD     32
+#endif
+
+#ifndef BITOP_MASK
+#define BITOP_MASK(nr)          (1U << ((nr) % BITOP_BITS_PER_WORD))
+#endif
+
+#ifndef BITOP_WORD
+#define BITOP_WORD(nr)          ((nr) / BITOP_BITS_PER_WORD)
+#endif
+
+#ifndef BITOP_TYPE
+typedef uint32_t bitops_uint_t;
+#endif
+
+#endif /* _ASM_GENERIC_BITOPS_BITS_H_ */
diff --git a/xen/include/asm-generic/bitops/generic-non-atomic.h b/xen/include/asm-generic/bitops/generic-non-atomic.h
new file mode 100644
index 0000000000..02d5721bfe
--- /dev/null
+++ b/xen/include/asm-generic/bitops/generic-non-atomic.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * The file is based on Linux ( 6.4.0 ) header:
+ *   include/asm-generic/bitops/generic-non-atomic.h
+ * 
+ * Only functions that can be reused in Xen were left; others were removed.
+ * 
+ * Also, the following changes were done:
+ *  - it was updated the message inside #ifndef ... #endif.
+ *  - __always_inline -> always_inline to be align with definition in
+ *    xen/compiler.h.
+ *  - update function prototypes from
+ *    generic___test_and_*(unsigned long nr nr, volatile unsigned long *addr) to
+ *    generic___test_and_*(unsigned long nr, volatile void *addr) to be
+ *    consistent with other related macros/defines.
+ *  - convert identations from tabs to spaces.
+ *  - inside generic__test_and_* use 'bitops_uint_t' instead of 'unsigned long'
+ *    to be generic.
+ */
+
+#ifndef __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
+#define __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
+
+#include <xen/compiler.h>
+
+#include <asm-generic/bitops/bitops-bits.h>
+
+#ifndef XEN_BITOPS_H
+#error only <xen/bitops.h> can be included directly
+#endif
+
+/*
+ * Generic definitions for bit operations, should not be used in regular code
+ * directly.
+ */
+
+/**
+ * generic___test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+static always_inline bool
+generic___test_and_set_bit(unsigned long nr, volatile void *addr)
+{
+    bitops_uint_t mask = BITOP_MASK(nr);
+    bitops_uint_t *p = ((bitops_uint_t *)addr) + BITOP_WORD(nr);
+    bitops_uint_t old = *p;
+
+    *p = old | mask;
+    return (old & mask) != 0;
+}
+
+/**
+ * generic___test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+static always_inline bool
+generic___test_and_clear_bit(bitops_uint_t nr, volatile void *addr)
+{
+    bitops_uint_t mask = BITOP_MASK(nr);
+    bitops_uint_t *p = ((bitops_uint_t *)addr) + BITOP_WORD(nr);
+    bitops_uint_t old = *p;
+
+    *p = old & ~mask;
+    return (old & mask) != 0;
+}
+
+/* WARNING: non atomic and it can be reordered! */
+static always_inline bool
+generic___test_and_change_bit(unsigned long nr, volatile void *addr)
+{
+    bitops_uint_t mask = BITOP_MASK(nr);
+    bitops_uint_t *p = ((bitops_uint_t *)addr) + BITOP_WORD(nr);
+    bitops_uint_t old = *p;
+
+    *p = old ^ mask;
+    return (old & mask) != 0;
+}
+
+#endif /* __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H */
diff --git a/xen/include/asm-generic/bitops/test-bit.h b/xen/include/asm-generic/bitops/test-bit.h
new file mode 100644
index 0000000000..6fb414d808
--- /dev/null
+++ b/xen/include/asm-generic/bitops/test-bit.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_GENERIC_BITOPS_TESTBIT_H_
+#define _ASM_GENERIC_BITOPS_TESTBIT_H_
+
+#include <asm-generic/bitops/bitops-bits.h>
+
+/**
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static inline int test_bit(int nr, const volatile void *addr)
+{
+    const volatile bitops_uint_t *p = addr;
+    return 1 & (p[BITOP_WORD(nr)] >> (nr & (BITOP_BITS_PER_WORD - 1)));
+}
+
+#endif /* _ASM_GENERIC_BITOPS_TESTBIT_H_ */
-- 
2.43.0



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

* [PATCH v6 05/20] xen/bitops: implement fls{l}() in common logic
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (3 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 04/20] xen/asm-generic: introduce generic non-atomic test_*bit() Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-20 15:39   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 06/20] xen/bitops: put __ffs() and ffz() into linux compatible header Oleksii Kurochko
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
	George Dunlap, Jan Beulich, Wei Liu, Shawn Anastasio,
	Roger Pau Monné

Return type was left 'int' because of the following compilation error:

./include/xen/kernel.h:18:21: error: comparison of distinct pointer types lacks a cast [-Werror]
       18 |         (void) (&_x == &_y);            \
          |                     ^~
    common/page_alloc.c:1843:34: note: in expansion of macro 'min'
     1843 |         unsigned int inc_order = min(MAX_ORDER, flsl(e - s) - 1);

generic_fls{l} was used instead of __builtin_clz{l}(x) as if x is 0,
the result in undefined.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - new patch for the patch series.
---
 xen/arch/arm/include/asm/arm32/bitops.h |  2 +-
 xen/arch/arm/include/asm/arm64/bitops.h |  6 ++----
 xen/arch/arm/include/asm/bitops.h       |  7 ++-----
 xen/arch/ppc/include/asm/bitops.h       |  3 ---
 xen/arch/x86/include/asm/bitops.h       |  6 ++++--
 xen/common/bitops.c                     | 22 ++++++++++++++++++++++
 xen/include/xen/bitops.h                | 24 ++++++++++++++++++++++++
 7 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/xen/arch/arm/include/asm/arm32/bitops.h b/xen/arch/arm/include/asm/arm32/bitops.h
index d0309d47c1..5552d4e945 100644
--- a/xen/arch/arm/include/asm/arm32/bitops.h
+++ b/xen/arch/arm/include/asm/arm32/bitops.h
@@ -1,7 +1,7 @@
 #ifndef _ARM_ARM32_BITOPS_H
 #define _ARM_ARM32_BITOPS_H
 
-#define flsl fls
+#define arch_flsl fls
 
 /*
  * Little endian assembly bitops.  nr = 0 -> byte 0 bit 0.
diff --git a/xen/arch/arm/include/asm/arm64/bitops.h b/xen/arch/arm/include/asm/arm64/bitops.h
index 0efde29068..5f5d97faa0 100644
--- a/xen/arch/arm/include/asm/arm64/bitops.h
+++ b/xen/arch/arm/include/asm/arm64/bitops.h
@@ -22,17 +22,15 @@ static /*__*/always_inline unsigned long __ffs(unsigned long word)
  */
 #define ffz(x)  __ffs(~(x))
 
-static inline int flsl(unsigned long x)
+static inline int arch_flsl(unsigned long x)
 {
         uint64_t ret;
 
-        if (__builtin_constant_p(x))
-               return generic_flsl(x);
-
         asm("clz\t%0, %1" : "=r" (ret) : "r" (x));
 
         return BITS_PER_LONG - ret;
 }
+#define arch_flsl arch_flsl
 
 /* Based on linux/include/asm-generic/bitops/find.h */
 
diff --git a/xen/arch/arm/include/asm/bitops.h b/xen/arch/arm/include/asm/bitops.h
index 5104334e48..bcf7b48731 100644
--- a/xen/arch/arm/include/asm/bitops.h
+++ b/xen/arch/arm/include/asm/bitops.h
@@ -145,17 +145,14 @@ static inline int test_bit(int nr, const volatile void *addr)
  * the clz instruction for much better code efficiency.
  */
 
-static inline int fls(unsigned int x)
+static inline int arch_fls(unsigned int x)
 {
         int ret;
 
-        if (__builtin_constant_p(x))
-               return generic_fls(x);
-
         asm("clz\t%"__OP32"0, %"__OP32"1" : "=r" (ret) : "r" (x));
         return 32 - ret;
 }
-
+#define arch_fls arch_fls
 
 #define arch_ffs(x) ({ unsigned int __t = (x); fls(ISOLATE_LSB(__t)); })
 #define arch_ffsl(x) ({ unsigned long __t = (x); flsl(ISOLATE_LSB(__t)); })
diff --git a/xen/arch/ppc/include/asm/bitops.h b/xen/arch/ppc/include/asm/bitops.h
index 989d341a44..16447a4be6 100644
--- a/xen/arch/ppc/include/asm/bitops.h
+++ b/xen/arch/ppc/include/asm/bitops.h
@@ -171,9 +171,6 @@ static inline int __test_and_clear_bit(int nr, volatile void *addr)
     return (old & mask) != 0;
 }
 
-#define flsl(x) generic_flsl(x)
-#define fls(x) generic_fls(x)
-
 /* Based on linux/include/asm-generic/bitops/ffz.h */
 /*
  * ffz - find first zero in word.
diff --git a/xen/arch/x86/include/asm/bitops.h b/xen/arch/x86/include/asm/bitops.h
index dd439b69a0..87e91a1b7b 100644
--- a/xen/arch/x86/include/asm/bitops.h
+++ b/xen/arch/x86/include/asm/bitops.h
@@ -438,7 +438,7 @@ static always_inline unsigned int arch_ffsl(unsigned long x)
  *
  * This is defined the same way as ffs.
  */
-static inline int flsl(unsigned long x)
+static always_inline int arch_flsl(unsigned long x)
 {
     long r;
 
@@ -448,8 +448,9 @@ static inline int flsl(unsigned long x)
           "1:" : "=r" (r) : "rm" (x));
     return (int)r+1;
 }
+#define arch_flsl arch_flsl
 
-static inline int fls(unsigned int x)
+static always_inline int arch_fls(unsigned int x)
 {
     int r;
 
@@ -459,6 +460,7 @@ static inline int fls(unsigned int x)
           "1:" : "=r" (r) : "rm" (x));
     return r + 1;
 }
+#define arch_fls arch_fls
 
 /**
  * hweightN - returns the hamming weight of a N-bit word
diff --git a/xen/common/bitops.c b/xen/common/bitops.c
index a8c32f6767..95bc47176b 100644
--- a/xen/common/bitops.c
+++ b/xen/common/bitops.c
@@ -62,9 +62,31 @@ static void test_ffs(void)
     CHECK(ffs64, (uint64_t)0x8000000000000000, 64);
 }
 
+static void test_fls(void)
+{
+    /* unsigned int ffs(unsigned int) */
+    CHECK(fls, 1, 1);
+    CHECK(fls, 3, 2);
+    CHECK(fls, 3U << 30, 32);
+
+    /* unsigned int flsl(unsigned long) */
+    CHECK(flsl, 1, 1);
+    CHECK(flsl, 1UL << (BITS_PER_LONG - 1), BITS_PER_LONG);
+#if BITS_PER_LONG > 32
+    CHECK(flsl, 3UL << 32, 34);
+#endif
+
+    /* unsigned int fls64(uint64_t) */
+    CHECK(fls64, 1, 1);
+    CHECK(fls64, 0x00000000C0000000ULL, 32);
+    CHECK(fls64, 0x0000000180000000ULL, 33);
+    CHECK(fls64, 0xC000000000000000ULL, 64);
+}
+
 static int __init cf_check test_bitops(void)
 {
     test_ffs();
+    test_fls();
 
     return 0;
 }
diff --git a/xen/include/xen/bitops.h b/xen/include/xen/bitops.h
index f14ad0d33a..fac8f768ff 100644
--- a/xen/include/xen/bitops.h
+++ b/xen/include/xen/bitops.h
@@ -69,6 +69,30 @@ static inline int generic_flsl(unsigned long x)
 
 #include <asm/bitops.h>
 
+static always_inline __pure int fls(unsigned int x)
+{
+    if (__builtin_constant_p(x))
+        return generic_fls(x);
+
+#ifndef arch_fls
+#define arch_fls generic_fls
+#endif
+
+    return arch_fls(x);
+}
+
+static always_inline __pure int flsl(unsigned long x)
+{
+    if (__builtin_constant_p(x))
+        return generic_flsl(x);
+
+#ifndef arch_flsl
+#define arch_flsl generic_flsl
+#endif
+
+    return arch_flsl(x);
+}
+
 /*
  * Find First Set bit.  Bits are labelled from 1.
  */
-- 
2.43.0



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

* [PATCH v6 06/20] xen/bitops: put __ffs() and ffz() into linux compatible header
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (4 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 05/20] xen/bitops: implement fls{l}() in common logic Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-20 15:42   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 07/20] xen/riscv: introduce bitops.h Oleksii Kurochko
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
	George Dunlap, Jan Beulich, Wei Liu, Shawn Anastasio,
	Rahul Singh

The mentioned macros exist only because of Linux compatible purpose.

The patch defines __ffs() in terms of Xen bitops and it is safe
to define in this way ( as __ffs() - 1 ) as considering that __ffs()
was defined as __builtin_ctzl(x), which has undefined behavior when x=0,
so it is assumed that such cases are not encountered in the current code.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - new patch for the patch series.
---
 xen/arch/arm/include/asm/arm64/bitops.h | 21 ---------------------
 xen/arch/ppc/include/asm/bitops.h       | 21 ---------------------
 xen/drivers/passthrough/arm/smmu-v3.c   |  2 ++
 xen/include/xen/linux-compat.h          |  3 +++
 xen/lib/find-next-bit.c                 |  1 +
 5 files changed, 6 insertions(+), 42 deletions(-)

diff --git a/xen/arch/arm/include/asm/arm64/bitops.h b/xen/arch/arm/include/asm/arm64/bitops.h
index 5f5d97faa0..2deb134388 100644
--- a/xen/arch/arm/include/asm/arm64/bitops.h
+++ b/xen/arch/arm/include/asm/arm64/bitops.h
@@ -1,27 +1,6 @@
 #ifndef _ARM_ARM64_BITOPS_H
 #define _ARM_ARM64_BITOPS_H
 
-/* Based on linux/include/asm-generic/bitops/builtin-__ffs.h */
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static /*__*/always_inline unsigned long __ffs(unsigned long word)
-{
-        return __builtin_ctzl(word);
-}
-
-/* Based on linux/include/asm-generic/bitops/ffz.h */
-/*
- * ffz - find first zero in word.
- * @word: The word to search
- *
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-#define ffz(x)  __ffs(~(x))
-
 static inline int arch_flsl(unsigned long x)
 {
         uint64_t ret;
diff --git a/xen/arch/ppc/include/asm/bitops.h b/xen/arch/ppc/include/asm/bitops.h
index 16447a4be6..fd157f3632 100644
--- a/xen/arch/ppc/include/asm/bitops.h
+++ b/xen/arch/ppc/include/asm/bitops.h
@@ -171,15 +171,6 @@ static inline int __test_and_clear_bit(int nr, volatile void *addr)
     return (old & mask) != 0;
 }
 
-/* Based on linux/include/asm-generic/bitops/ffz.h */
-/*
- * ffz - find first zero in word.
- * @word: The word to search
- *
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-#define ffz(x) __ffs(~(x))
-
 /**
  * hweightN - returns the hamming weight of a N-bit word
  * @x: the word to weigh
@@ -191,16 +182,4 @@ static inline int __test_and_clear_bit(int nr, volatile void *addr)
 #define hweight16(x) __builtin_popcount((uint16_t)(x))
 #define hweight8(x)  __builtin_popcount((uint8_t)(x))
 
-/* Based on linux/include/asm-generic/bitops/builtin-__ffs.h */
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static always_inline unsigned long __ffs(unsigned long word)
-{
-    return __builtin_ctzl(word);
-}
-
 #endif /* _ASM_PPC_BITOPS_H */
diff --git a/xen/drivers/passthrough/arm/smmu-v3.c b/xen/drivers/passthrough/arm/smmu-v3.c
index b1c40c2c0a..6904962467 100644
--- a/xen/drivers/passthrough/arm/smmu-v3.c
+++ b/xen/drivers/passthrough/arm/smmu-v3.c
@@ -72,12 +72,14 @@
  */
 
 #include <xen/acpi.h>
+#include <xen/bitops.h>
 #include <xen/config.h>
 #include <xen/delay.h>
 #include <xen/errno.h>
 #include <xen/err.h>
 #include <xen/irq.h>
 #include <xen/lib.h>
+#include <xen/linux-compat.h>
 #include <xen/list.h>
 #include <xen/mm.h>
 #include <xen/rbtree.h>
diff --git a/xen/include/xen/linux-compat.h b/xen/include/xen/linux-compat.h
index 62ba71485c..de059bdf12 100644
--- a/xen/include/xen/linux-compat.h
+++ b/xen/include/xen/linux-compat.h
@@ -19,4 +19,7 @@ typedef int64_t __s64;
 
 typedef paddr_t phys_addr_t;
 
+#define __ffs(x) (ffsl(x) - 1)
+#define ffz(x) __ffs(~(x))
+
 #endif /* __XEN_LINUX_COMPAT_H__ */
diff --git a/xen/lib/find-next-bit.c b/xen/lib/find-next-bit.c
index ca6f82277e..b151f7f994 100644
--- a/xen/lib/find-next-bit.c
+++ b/xen/lib/find-next-bit.c
@@ -9,6 +9,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 #include <xen/bitops.h>
+#include <xen/linux-compat.h>
 
 #include <asm/byteorder.h>
 
-- 
2.43.0



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

* [PATCH v6 07/20] xen/riscv: introduce bitops.h
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (5 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 06/20] xen/bitops: put __ffs() and ffz() into linux compatible header Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-20 16:03   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h Oleksii Kurochko
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

Taken from Linux-6.4.0-rc1

Xen's bitops.h consists of several Linux's headers:
* linux/arch/include/asm/bitops.h:
  * The following function were removed as they aren't used in Xen:
        * test_and_set_bit_lock
        * clear_bit_unlock
        * __clear_bit_unlock
  * The following functions were renamed in the way how they are
    used by common code:
        * __test_and_set_bit
        * __test_and_clear_bit
  * The declaration and implementation of the following functios
    were updated to make Xen build happy:
        * clear_bit
        * set_bit
        * __test_and_clear_bit
        * __test_and_set_bit
  * linux/include/asm-generic/bitops/generic-non-atomic.h with the
    following changes:
     * Only functions that can be reused in Xen were left;
       others were removed.
     * it was updated the message inside #ifndef ... #endif.
     * __always_inline -> always_inline to be align with definition in
       xen/compiler.h.
     * update function prototypes from
       generic___test_and_*(unsigned long nr nr, volatile unsigned long *addr)
       to
       generic___test_and_*(unsigned long nr, volatile void *addr) to be
       consistent with other related macros/defines.
     * convert identations from tabs to spaces.
     * inside generic__test_and_* use 'bitops_uint_t' instead of 'unsigned long'
        to be generic.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - rebase clean ups were done: drop unused asm-generic includes
---
 Changes in V5:
   - new patch
---
 xen/arch/riscv/include/asm/bitops.h | 144 ++++++++++++++++++++++++++++
 xen/arch/riscv/include/asm/config.h |   2 +
 2 files changed, 146 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/bitops.h

diff --git a/xen/arch/riscv/include/asm/bitops.h b/xen/arch/riscv/include/asm/bitops.h
new file mode 100644
index 0000000000..21c4868355
--- /dev/null
+++ b/xen/arch/riscv/include/asm/bitops.h
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2012 Regents of the University of California */
+
+#ifndef _ASM_RISCV_BITOPS_H
+#define _ASM_RISCV_BITOPS_H
+
+#include <asm/system.h>
+
+#define BITOP_BITS_PER_WORD BITS_PER_LONG
+
+#define BITOP_TYPE
+typedef uint64_t bitops_uint_t;
+
+#include <asm-generic/bitops/bitops-bits.h>
+
+#define __set_bit(n, p)      set_bit(n, p)
+#define __clear_bit(n, p)    clear_bit(n, p)
+
+/* Based on linux/arch/include/asm/bitops.h */
+
+#if BITS_PER_LONG == 64
+#define __AMO(op)   "amo" #op ".d"
+#elif BITS_PER_LONG == 32
+#define __AMO(op)   "amo" #op ".w"
+#else
+#error "Unexpected BITS_PER_LONG"
+#endif
+
+#define test_and_op_bit_ord(op, mod, nr, addr, ord)     \
+({                                                      \
+    unsigned long res, mask;                            \
+    mask = BITOP_MASK(nr);                              \
+    __asm__ __volatile__ (                              \
+        __AMO(op) #ord " %0, %2, %1"                    \
+        : "=r" (res), "+A" (addr[BITOP_WORD(nr)])       \
+        : "r" (mod(mask))                               \
+        : "memory");                                    \
+    ((res & mask) != 0);                                \
+})
+
+#define __op_bit_ord(op, mod, nr, addr, ord)    \
+    __asm__ __volatile__ (                      \
+        __AMO(op) #ord " zero, %1, %0"          \
+        : "+A" (addr[BITOP_WORD(nr)])           \
+        : "r" (mod(BITOP_MASK(nr)))             \
+        : "memory");
+
+#define test_and_op_bit(op, mod, nr, addr)    \
+    test_and_op_bit_ord(op, mod, nr, addr, .aqrl)
+#define __op_bit(op, mod, nr, addr) \
+    __op_bit_ord(op, mod, nr, addr, )
+
+/* Bitmask modifiers */
+#define NOP(x)    (x)
+#define NOT(x)    (~(x))
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+static inline int test_and_set_bit(int nr, volatile void *p)
+{
+    volatile bitops_uint_t *addr = p;
+
+    return test_and_op_bit(or, NOP, nr, addr);
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ */
+static inline int test_and_clear_bit(int nr, volatile void *p)
+{
+    volatile bitops_uint_t *addr = p;
+
+    return test_and_op_bit(and, NOT, nr, addr);
+}
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void set_bit(int nr, volatile void *p)
+{
+    volatile bitops_uint_t *addr = p;
+
+    __op_bit(or, NOP, nr, addr);
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ */
+static inline void clear_bit(int nr, volatile void *p)
+{
+    volatile bitops_uint_t *addr = p;
+
+    __op_bit(and, NOT, nr, addr);
+}
+
+/**
+ * test_and_change_bit - Toggle (change) a bit and return its old value
+ * @nr: Bit to change
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_op_bit(xor, NOP, nr, addr);
+}
+
+#undef test_and_op_bit
+#undef __op_bit
+#undef NOP
+#undef NOT
+#undef __AMO
+
+#include <asm-generic/bitops/generic-non-atomic.h>
+
+#define __test_and_set_bit generic___test_and_set_bit
+#define __test_and_clear_bit generic___test_and_clear_bit
+#define __test_and_change_bit generic___test_and_change_bit
+
+#include <asm-generic/bitops/test-bit.h>
+
+#endif /* _ASM_RISCV_BITOPS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/riscv/include/asm/config.h b/xen/arch/riscv/include/asm/config.h
index c5f93e6a01..a58086e4b2 100644
--- a/xen/arch/riscv/include/asm/config.h
+++ b/xen/arch/riscv/include/asm/config.h
@@ -113,6 +113,8 @@
 # error "Unsupported RISCV variant"
 #endif
 
+#define BITS_PER_BYTE 8
+
 #define BYTES_PER_LONG (1 << LONG_BYTEORDER)
 #define BITS_PER_LONG  (BYTES_PER_LONG << 3)
 #define POINTER_ALIGN  BYTES_PER_LONG
-- 
2.43.0



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

* [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (6 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 07/20] xen/riscv: introduce bitops.h Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-21 12:07   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 09/20] xen/riscv: introduce io.h Oleksii Kurochko
                   ` (11 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

The header was taken from Linux kernl 6.4.0-rc1.

Addionally, were updated:
* add emulation of {cmp}xchg for 1/2 byte types using 32-bit atomic
  access.
* replace tabs with spaces
* replace __* variale with *__
* introduce generic version of xchg_* and cmpxchg_*.
* drop {cmp}xchg{release,relaxed,acquire} as Xen doesn't use them
* drop barries and use instruction suffixices instead ( .aq, .rl, .aqrl )

Implementation of 4- and 8-byte cases were updated according to the spec:
```
              ....
Linux Construct         RVWMO AMO Mapping
atomic <op> relaxed     amo<op>.{w|d}
atomic <op> acquire     amo<op>.{w|d}.aq
atomic <op> release     amo<op>.{w|d}.rl
atomic <op>             amo<op>.{w|d}.aqrl
Linux Construct         RVWMO LR/SC Mapping
atomic <op> relaxed     loop: lr.{w|d}; <op>; sc.{w|d}; bnez loop
atomic <op> acquire     loop: lr.{w|d}.aq; <op>; sc.{w|d}; bnez loop
atomic <op> release     loop: lr.{w|d}; <op>; sc.{w|d}.aqrl∗ ; bnez loop OR
                        fence.tso; loop: lr.{w|d}; <op>; sc.{w|d}∗ ; bnez loop
atomic <op>             loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl; bnez loop

Table A.5: Mappings from Linux memory primitives to RISC-V primitives

```

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
-  update the commit message? ( As before I don't understand this point. Can you give an example of what sort of opcode / instruction is missing?)
 - Code style fixes
 - change sizeof(*ptr) -> sizeof(*(ptr))
 - update operands names and some local variables for macros emulate_xchg_1_2() and emulate_cmpxchg_1_2()
 - drop {cmp}xchg_{relaxed,acquire,release) versions as they aren't needed for Xen
 - update __amoswap_generic() prototype and defintion: drop pre and post barries.
 - update emulate_xchg_1_2() prototype and definion: add lr_sfx, drop pre and post barries.
 - rename __xchg_generic to __xchg(), make __xchg as static inline function to be able to "#ifndef CONFIG_32BIT case 8:... " 
---
Changes in V5:
 - update the commit message.
 - drop ALIGN_DOWN().
 - update the definition of emulate_xchg_1_2(): 
   - lr.d -> lr.w, sc.d -> sc.w.
   - drop ret argument.
   - code style fixes around asm volatile.
   - update prototype.
   - use asm named operands.
   - rename local variables.
   - add comment above the macros
 - update the definition of __xchg_generic:
   - rename to __xchg()
   - transform it to static inline
   - code style fixes around switch()
   - update prototype.
 - redefine cmpxchg()
 - update emulate_cmpxchg_1_2():
   - update prototype
   - update local variables names and usage of them
   - use name asm operands.
   - add comment above the macros
 - drop pre and post, and use .aq,.rl, .aqrl suffixes.
 - drop {cmp}xchg_{relaxed, aquire, release} as they are not used by Xen.
 - drop unnessary details in comment above emulate_cmpxchg_1_2()
---
Changes in V4:
 - Code style fixes.
 - enforce in __xchg_*() has the same type for new and *ptr, also "\n"
   was removed at the end of asm instruction.
 - dependency from https://lore.kernel.org/xen-devel/cover.1706259490.git.federico.serafini@bugseng.com/
 - switch from ASSERT_UNREACHABLE to STATIC_ASSERT_UNREACHABLE().
 - drop xchg32(ptr, x) and xchg64(ptr, x) as they aren't used.
 - drop cmpxcg{32,64}_{local} as they aren't used.
 - introduce generic version of xchg_* and cmpxchg_*.
 - update the commit message.
---
Changes in V3:
 - update the commit message
 - add emulation of {cmp}xchg_... for 1 and 2 bytes types
---
Changes in V2:
 - update the comment at the top of the header.
 - change xen/lib.h to xen/bug.h.
 - sort inclusion of headers properly.
---
 xen/arch/riscv/include/asm/cmpxchg.h | 209 +++++++++++++++++++++++++++
 1 file changed, 209 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/cmpxchg.h

diff --git a/xen/arch/riscv/include/asm/cmpxchg.h b/xen/arch/riscv/include/asm/cmpxchg.h
new file mode 100644
index 0000000000..aba2858933
--- /dev/null
+++ b/xen/arch/riscv/include/asm/cmpxchg.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (C) 2014 Regents of the University of California */
+
+#ifndef _ASM_RISCV_CMPXCHG_H
+#define _ASM_RISCV_CMPXCHG_H
+
+#include <xen/compiler.h>
+#include <xen/lib.h>
+
+#include <asm/fence.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#define __amoswap_generic(ptr, new, ret, sfx) \
+({ \
+    asm volatile ( \
+        " amoswap" sfx " %0, %2, %1" \
+        : "=r" (ret), "+A" (*ptr) \
+        : "r" (new) \
+        : "memory" ); \
+})
+
+/*
+ * For LR and SC, the A extension requires that the address held in rs1 be
+ * naturally aligned to the size of the operand (i.e., eight-byte aligned
+ * for 64-bit words and four-byte aligned for 32-bit words).
+ * If the address is not naturally aligned, an address-misaligned exception
+ * or an access-fault exception will be generated.
+ *
+ * Thereby:
+ * - for 1-byte xchg access the containing word by clearing low two bits
+ * - for 2-byte xchg ccess the containing word by clearing bit 1.
+ *
+ * If resulting 4-byte access is still misalgined, it will fault just as
+ * non-emulated 4-byte access would.
+ */
+#define emulate_xchg_1_2(ptr, new, lr_sfx, sc_sfx) \
+({ \
+    uint32_t *aligned_ptr = (uint32_t *)((unsigned long)ptr & ~(0x4 - sizeof(*(ptr)))); \
+    unsigned int new_val_pos = ((unsigned long)(ptr) & (0x4 - sizeof(*(ptr)))) * BITS_PER_BYTE; \
+    unsigned long mask = GENMASK(((sizeof(*(ptr))) * BITS_PER_BYTE) - 1, 0) << new_val_pos; \
+    unsigned int new_ = new << new_val_pos; \
+    unsigned int old; \
+    unsigned int scratch; \
+    \
+    asm volatile ( \
+        "0: lr.w" lr_sfx " %[old], %[aligned_ptr]\n" \
+        "   and  %[scratch], %[old], %z[nmask]\n" \
+        "   or   %[scratch], %[scratch], %z[new_]\n" \
+        "   sc.w" sc_sfx " %[scratch], %[scratch], %[aligned_ptr]\n" \
+        "   bnez %[scratch], 0b\n" \
+        : [old] "=&r" (old), [scratch] "=&r" (scratch), [aligned_ptr] "+A" (*aligned_ptr) \
+        : [new_] "rJ" (new_), [nmask] "rJ" (~mask) \
+        : "memory" ); \
+    \
+    (__typeof__(*(ptr)))((old & mask) >> new_val_pos); \
+})
+
+static always_inline unsigned long __xchg(volatile void *ptr, unsigned long new, int size)
+{
+    unsigned long ret;
+
+    switch ( size )
+    {
+    case 1:
+        ret = emulate_xchg_1_2((volatile uint8_t *)ptr, new, ".aq", ".aqrl");
+        break;
+    case 2:
+        ret = emulate_xchg_1_2((volatile uint16_t *)ptr, new, ".aq", ".aqrl");
+        break;
+    case 4:
+        __amoswap_generic((volatile uint32_t *)ptr, new, ret, ".w.aqrl");
+        break;
+#ifndef CONFIG_32BIT
+    case 8:
+        __amoswap_generic((volatile uint64_t *)ptr, new, ret, ".d.aqrl");
+        break;
+#endif
+    default:
+        STATIC_ASSERT_UNREACHABLE();
+    }
+
+    return ret;
+}
+
+#define xchg(ptr, x) \
+({ \
+    __typeof__(*(ptr)) n_ = (x); \
+    (__typeof__(*(ptr))) \
+        __xchg((ptr), (unsigned long)(n_), sizeof(*(ptr))); \
+})
+
+#define __generic_cmpxchg(ptr, old, new, ret, lr_sfx, sc_sfx)	\
+ ({ \
+    register unsigned int rc; \
+    __typeof__(*(ptr)) old__ = (__typeof__(*(ptr)))(old); \
+    __typeof__(*(ptr)) new__ = (__typeof__(*(ptr)))(new); \
+    asm volatile( \
+        "0: lr" lr_sfx " %0, %2\n" \
+        "   bne  %0, %z3, 1f\n" \
+        "   sc" sc_sfx " %1, %z4, %2\n" \
+        "   bnez %1, 0b\n" \
+        "1:\n" \
+        : "=&r" (ret), "=&r" (rc), "+A" (*ptr) \
+        : "rJ" (old__), "rJ" (new__) \
+        : "memory"); \
+ })
+
+/*
+ * For LR and SC, the A extension requires that the address held in rs1 be
+ * naturally aligned to the size of the operand (i.e., eight-byte aligned
+ * for 64-bit words and four-byte aligned for 32-bit words).
+ * If the address is not naturally aligned, an address-misaligned exception
+ * or an access-fault exception will be generated.
+ *
+ * Thereby:
+ * - for 1-byte xchg access the containing word by clearing low two bits
+ * - for 2-byte xchg ccess the containing word by clearing first bit.
+ * 
+ * If resulting 4-byte access is still misalgined, it will fault just as
+ * non-emulated 4-byte access would.
+ *
+ * old_val was casted to unsigned long for cmpxchgptr()
+ */
+#define emulate_cmpxchg_1_2(ptr, old, new, lr_sfx, sc_sfx) \
+({ \
+    uint32_t *aligned_ptr = (uint32_t *)((unsigned long)ptr & ~(0x4 - sizeof(*(ptr)))); \
+    uint8_t new_val_pos = ((unsigned long)(ptr) & (0x4 - sizeof(*(ptr)))) * BITS_PER_BYTE; \
+    unsigned long mask = GENMASK(((sizeof(*(ptr))) * BITS_PER_BYTE) - 1, 0) << new_val_pos; \
+    unsigned int old_ = old << new_val_pos; \
+    unsigned int new_ = new << new_val_pos; \
+    unsigned int old_val; \
+    unsigned int scratch; \
+    \
+    __asm__ __volatile__ ( \
+        "0: lr.w" lr_sfx " %[scratch], %[aligned_ptr]\n" \
+        "   and  %[old_val], %[scratch], %z[mask]\n" \
+        "   bne  %[old_val], %z[old_], 1f\n" \
+        "   xor  %[scratch], %[old_val], %[scratch]\n" \
+        "   or   %[scratch], %[scratch], %z[new_]\n" \
+        "   sc.w" sc_sfx " %[scratch], %[scratch], %[aligned_ptr]\n" \
+        "   bnez %[scratch], 0b\n" \
+        "1:\n" \
+        : [old_val] "=&r" (old_val), [scratch] "=&r" (scratch), [aligned_ptr] "+A" (*aligned_ptr) \
+        : [old_] "rJ" (old_), [new_] "rJ" (new_), \
+          [mask] "rJ" (mask) \
+        : "memory" ); \
+    \
+    (__typeof__(*(ptr)))((unsigned long)old_val >> new_val_pos); \
+})
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+static always_inline unsigned long __cmpxchg(volatile void *ptr,
+                         unsigned long old,
+                         unsigned long new,
+                         int size)
+{
+    unsigned long ret;
+
+    switch ( size )
+    {
+    case 1:
+        ret = emulate_cmpxchg_1_2((volatile uint8_t *)ptr, old, new,
+                                  ".aq", ".aqrl");
+        break;
+    case 2:
+        ret = emulate_cmpxchg_1_2((volatile uint16_t *)ptr, old, new,
+                                   ".aq", ".aqrl");
+        break;
+    case 4:
+        __generic_cmpxchg((volatile uint32_t *)ptr, old, new, ret,
+                          ".w.aq", ".w.aqrl");
+        break;
+#ifndef CONFIG_32BIT
+    case 8:
+        __generic_cmpxchg((volatile uint64_t *)ptr, old, new,
+                           ret, ".d.aq", ".d.aqrl");
+        break;
+#endif
+    default:
+        STATIC_ASSERT_UNREACHABLE();
+    }
+
+    return ret;
+}
+
+#define cmpxchg(ptr, o, n) \
+({ \
+    __typeof__(*(ptr)) o_ = (o); \
+    __typeof__(*(ptr)) n_ = (n); \
+    (__typeof__(*(ptr))) \
+    __cmpxchg((ptr), (unsigned long)(o_), (unsigned long)(n_), \
+              sizeof(*(ptr))); \
+})
+
+#endif /* _ASM_RISCV_CMPXCHG_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.43.0



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

* [PATCH v6 09/20] xen/riscv: introduce io.h
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (7 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-21 12:27   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 10/20] xen/riscv: introduce atomic.h Oleksii Kurochko
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

The header taken form Linux 6.4.0-rc1 and is based on
arch/riscv/include/asm/mmio.h with the following changes:
- drop forcing of endianess for read*(), write*() functions as
  no matter what CPU endianness, what endianness a particular device
  (and hence its MMIO region(s)) is using is entirely independent.
  Hence conversion, where necessary, needs to occur at a layer up.
  Another one reason to drop endianess conversion here is:
  https://patchwork.kernel.org/project/linux-riscv/patch/20190411115623.5749-3-hch@lst.de/
  One of the answers of the author of the commit:
    And we don't know if Linux will be around if that ever changes.
    The point is:
     a) the current RISC-V spec is LE only
     b) the current linux port is LE only except for this little bit
    There is no point in leaving just this bitrotting code around.  It
    just confuses developers, (very very slightly) slows down compiles
    and will bitrot.  It also won't be any significant help to a future
    developer down the road doing a hypothetical BE RISC-V Linux port.
- drop unused argument of __io_ar() macros.
- drop "#define _raw_{read,write}{b,w,l,d,q} _raw_{read,write}{b,w,l,d,q}"
  as they are unnecessary.
- Adopt the Xen code style for this header, considering that significant changes
  are not anticipated in the future.
  In the event of any issues, adapting them to Xen style should be easily
  manageable.
- drop unnecessary  __r variables in macros read*_cpu()
- update inline assembler constraints for addr argument for
  __raw_read{b,w,l,q} and __raw_write{b,w,l,q} to tell a compiler that
 *addr will be accessed.
- add stubs for __raw_readq() and __raw_writeq() for RISCV_32

Addionally, to the header was added definions of ioremap_*().

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - drop unnecessary spaces and fix typos in the file comment.
 - s/CONFIG_64BIT/CONFIG_RISCV_32 as .d suffix for instruction doesn't exist for RV32.
 - add stubs for __raw_readq() and __raw_writeq() for RISCV_32
 - update inline assembler constraints for addr argument for __raw_read{b,w,l,q} and
   __raw_write{b,w,l,q} to tell compiler that *addr will be accessed.
 - s/u8/uint8_t
 - update the commit message
---
Changes in V5:
 - Xen code style related fixes
 - drop #define _raw_{read,write}{b,w,l,d,q} _raw_{read,write}{b,w,l,d,q}
 - drop cpu_to_le16()
 - remove unuused argument in _io_ar()
 - update the commit message 
 - drop unnessary __r variables in macros read*_cpu()
 - update the comments at the top of the header.
---
Changes in V4:
 - delete inner parentheses in macros.
 - s/u<N>/uint<N>.
---
Changes in V3:
 - re-sync with linux kernel
 - update the commit message
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/io.h | 167 ++++++++++++++++++++++++++++++++
 1 file changed, 167 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/io.h

diff --git a/xen/arch/riscv/include/asm/io.h b/xen/arch/riscv/include/asm/io.h
new file mode 100644
index 0000000000..4eb4cd4b49
--- /dev/null
+++ b/xen/arch/riscv/include/asm/io.h
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ *  The header taken form Linux 6.4.0-rc1 and is based on
+ *  arch/riscv/include/asm/mmio.h with the following changes:
+ *   - drop forcing of endianess for read*(), write*() functions as
+ *     no matter what CPU endianness, what endianness a particular device
+ *     (and hence its MMIO region(s)) is using is entirely independent.
+ *     Hence conversion, where necessary, needs to occur at a layer up.
+ *     Another one reason to drop endianess conversion is:
+ *     https://patchwork.kernel.org/project/linux-riscv/patch/20190411115623.5749-3-hch@lst.de/
+ *     One of the answers of the author of the commit:
+ *       And we don't know if Linux will be around if that ever changes.
+ *       The point is:
+ *        a) the current RISC-V spec is LE only
+ *        b) the current linux port is LE only except for this little bit
+ *       There is no point in leaving just this bitrotting code around.  It
+ *       just confuses developers, (very very slightly) slows down compiles
+ *      and will bitrot.  It also won't be any significant help to a future
+ *       developer down the road doing a hypothetical BE RISC-V Linux port.
+ *   - drop unused argument of __io_ar() macros.
+ *   - drop "#define _raw_{read,write}{b,w,l,d,q} _raw_{read,write}{b,w,l,d,q}"
+ *     as they are unnecessary.
+ *   - Adopt the Xen code style for this header, considering that significant
+ *     changes are not anticipated in the future.
+ *     In the event of any issues, adapting them to Xen style should be easily
+ *     manageable.
+ *   - drop unnecessary __r variables in macros read*_cpu()
+ *   - update inline assembler constraints for addr argument for
+ *     __raw_read{b,w,l,q} and __raw_write{b,w,l,q} to tell a compiler that
+ *     *addr will be accessed.
+ *
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2014 Regents of the University of California
+ * Copyright (C) 2024 Vates
+ */
+
+#ifndef _ASM_RISCV_IO_H
+#define _ASM_RISCV_IO_H
+
+#include <asm/byteorder.h>
+
+/*
+ * The RISC-V ISA doesn't yet specify how to query or modify PMAs, so we can't
+ * change the properties of memory regions.  This should be fixed by the
+ * upcoming platform spec.
+ */
+#define ioremap_nocache(addr, size) ioremap(addr, size)
+#define ioremap_wc(addr, size) ioremap(addr, size)
+#define ioremap_wt(addr, size) ioremap(addr, size)
+
+/* Generic IO read/write.  These perform native-endian accesses. */
+static inline void __raw_writeb(uint8_t val, volatile void __iomem *addr)
+{
+    asm volatile ( "sb %1, %0" : "=m" (*(volatile uint8_t __force *)addr) : "r" (val) );
+}
+
+static inline void __raw_writew(uint16_t val, volatile void __iomem *addr)
+{
+    asm volatile ( "sh %1, %0" : "=m" (*(volatile uint16_t __force *)addr) : "r" (val) );
+}
+
+static inline void __raw_writel(uint32_t val, volatile void __iomem *addr)
+{
+    asm volatile ( "sw %1, %0" : "=m" (*(volatile uint32_t __force *)addr) : "r" (val) );
+}
+
+#ifdef CONFIG_RISCV_32
+static inline void __raw_writeq(uint64_t val, volatile void __iomem *addr)
+{
+    BUILD_BUG_ON("unimplemented\n");
+}
+#else
+static inline void __raw_writeq(uint64_t val, volatile void __iomem *addr)
+{
+    asm volatile ( "sd %1, %0" : "=m" (*(volatile uint64_t __force *)addr) : "r" (val) );
+}
+#endif
+
+static inline uint8_t __raw_readb(const volatile void __iomem *addr)
+{
+    uint8_t val;
+
+    asm volatile ( "lb %0, %1" : "=r" (val) : "m" (*(volatile uint8_t __force *)addr) );
+    return val;
+}
+
+static inline uint16_t __raw_readw(const volatile void __iomem *addr)
+{
+    uint16_t val;
+
+    asm volatile ( "lh %0, %1" : "=r" (val) : "m" (*(volatile uint16_t __force *)addr) );
+    return val;
+}
+
+static inline uint32_t __raw_readl(const volatile void __iomem *addr)
+{
+    uint32_t val;
+
+    asm volatile ( "lw %0, %1" : "=r" (val) : "m" (*(volatile uint32_t __force *)addr) );
+    return val;
+}
+
+#ifdef CONFIG_RISCV_32
+static inline uint64_t __raw_readq(const volatile void __iomem *addr)
+{
+    BUILD_BUG_ON("unimplemented\n");
+    return 0;
+}
+#else
+static inline uint64_t __raw_readq(const volatile void __iomem *addr)
+{
+    uint64_t val;
+
+    asm volatile ( "ld %0, %1" : "=r" (val) : "m" (*(volatile uint64_t __force *)addr) );
+    return val;
+}
+#endif
+
+/*
+ * Unordered I/O memory access primitives.  These are even more relaxed than
+ * the relaxed versions, as they don't even order accesses between successive
+ * operations to the I/O regions.
+ */
+#define readb_cpu(c)        __raw_readb(c)
+#define readw_cpu(c)        __raw_readw(c)
+#define readl_cpu(c)        __raw_readl(c)
+
+#define writeb_cpu(v, c)    __raw_writeb(v, c)
+#define writew_cpu(v, c)    __raw_writew(v, c)
+#define writel_cpu(v, c)    __raw_writel(v, c)
+
+#define readq_cpu(c)        __raw_readq(c)
+#define writeq_cpu(v, c)    __raw_writeq(v, c)
+
+/*
+ * I/O memory access primitives. Reads are ordered relative to any
+ * following Normal memory access. Writes are ordered relative to any prior
+ * Normal memory access.  The memory barriers here are necessary as RISC-V
+ * doesn't define any ordering between the memory space and the I/O space.
+ */
+#define __io_br()   do { } while (0)
+#define __io_ar()   asm volatile ( "fence i,r" : : : "memory" );
+#define __io_bw()   asm volatile ( "fence w,o" : : : "memory" );
+#define __io_aw()   do { } while (0)
+
+#define readb(c)    ({ uint8_t  v; __io_br(); v = readb_cpu(c); __io_ar(); v; })
+#define readw(c)    ({ uint16_t v; __io_br(); v = readw_cpu(c); __io_ar(); v; })
+#define readl(c)    ({ uint32_t v; __io_br(); v = readl_cpu(c); __io_ar(); v; })
+
+#define writeb(v, c)    ({ __io_bw(); writeb_cpu(v, c); __io_aw(); })
+#define writew(v, c)    ({ __io_bw(); writew_cpu(v, c); __io_aw(); })
+#define writel(v, c)    ({ __io_bw(); writel_cpu(v, c); __io_aw(); })
+
+#define readq(c)        ({ uint64_t v; __io_br(); v = readq_cpu(c); __io_ar(); v; })
+#define writeq(v, c)    ({ __io_bw(); writeq_cpu(v, c); __io_aw(); })
+
+#endif /* _ASM_RISCV_IO_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.43.0



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

* [PATCH v6 10/20] xen/riscv: introduce atomic.h
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (8 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 09/20] xen/riscv: introduce io.h Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-21 13:03   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 11/20] xen/riscv: introduce monitor.h Oleksii Kurochko
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

Initially the patch was introduced by Bobby, who takes the header from
Linux kernel.

The following changes were done on top of Linux kernel header:
 - atomic##prefix##_*xchg_*(atomic##prefix##_t *v, c_t n) were updated
     to use__*xchg_generic()
 - drop casts in write_atomic() as they are unnecessary
 - drop introduction of WRITE_ONCE() and READ_ONCE().
   Xen provides ACCESS_ONCE()
 - remove zero-length array access in read_atomic()
 - drop defines similar to pattern
 - #define atomic_add_return_relaxed   atomic_add_return_relaxed
 - move not RISC-V specific functions to asm-generic/atomics-ops.h
 - drop  atomic##prefix##_{cmp}xchg_{release, aquire, release}() as they
   are not used in Xen.
 - update the defintion of  atomic##prefix##_{cmp}xchg according to
   {cmp}xchg() implementation in Xen.

Signed-off-by: Bobby Eshleman <bobbyeshleman@gmail.com>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - drop atomic##prefix##_{cmp}xchg_{release, aquire, relaxed} as they aren't used
   by Xen
 - code style fixes.
 - %s/__asm__ __volatile__/asm volatile
 - add explanational comments.
 - move inclusion of "#include <asm-generic/atomic-ops.h>" further down in atomic.h
   header.
---
Changes in V5:
 - fence.h changes were moved to separate patch as patches related to io.h and cmpxchg.h,
   which are dependecies for this patch, also needed changes in fence.h
 - remove accessing of zero-length array
 - drops cast in write_atomic()
 - drop introduction of WRITE_ONCE() and READ_ONCE().
 - drop defines similar to pattern #define atomic_add_return_relaxed   atomic_add_return_relaxed
 - Xen code style fixes
 - move not RISC-V specific functions to asm-generic/atomics-ops.h
---
Changes in V4:
 - do changes related to the updates of [PATCH v3 13/34] xen/riscv: introduce cmpxchg.h
 - drop casts in read_atomic_size(), write_atomic(), add_sized()
 - tabs -> spaces
 - drop #ifdef CONFIG_SMP ... #endif in fence.ha as it is simpler to handle NR_CPUS=1
   the same as NR_CPUS>1 with accepting less than ideal performance.
---
Changes in V3:
  - update the commit message
  - add SPDX for fence.h
  - code style fixes
  - Remove /* TODO: ... */ for add_sized macros. It looks correct to me.
  - re-order the patch
  - merge to this patch fence.h
---
Changes in V2:
 - Change an author of commit. I got this header from Bobby's old repo.
---
 xen/arch/riscv/include/asm/atomic.h  | 263 +++++++++++++++++++++++++++
 xen/include/asm-generic/atomic-ops.h |  97 ++++++++++
 2 files changed, 360 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/atomic.h
 create mode 100644 xen/include/asm-generic/atomic-ops.h

diff --git a/xen/arch/riscv/include/asm/atomic.h b/xen/arch/riscv/include/asm/atomic.h
new file mode 100644
index 0000000000..4964821f3a
--- /dev/null
+++ b/xen/arch/riscv/include/asm/atomic.h
@@ -0,0 +1,263 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Taken and modified from Linux.
+ *
+ * The following changes were done:
+ * - * atomic##prefix##_*xchg_*(atomic##prefix##_t *v, c_t n) were updated
+ *     to use__*xchg_generic()
+ * - drop casts in write_atomic() as they are unnecessary
+ * - drop introduction of WRITE_ONCE() and READ_ONCE().
+ *   Xen provides ACCESS_ONCE()
+ * - remove zero-length array access in read_atomic()
+ * - drop defines similar to pattern
+ *   #define atomic_add_return_relaxed   atomic_add_return_relaxed
+ * - move not RISC-V specific functions to asm-generic/atomics-ops.h
+ * 
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ * Copyright (C) 2024 Vates SAS
+ */
+
+#ifndef _ASM_RISCV_ATOMIC_H
+#define _ASM_RISCV_ATOMIC_H
+
+#include <xen/atomic.h>
+
+#include <asm/cmpxchg.h>
+#include <asm/fence.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+void __bad_atomic_size(void);
+
+/*
+ * Legacy from Linux kernel. For some reason they wanted to have ordered
+ * read/write access. Thereby read* is used instead of read<X>_cpu()
+ */
+static always_inline void read_atomic_size(const volatile void *p,
+                                           void *res,
+                                           unsigned int size)
+{
+    switch ( size )
+    {
+    case 1: *(uint8_t *)res = readb(p); break;
+    case 2: *(uint16_t *)res = readw(p); break;
+    case 4: *(uint32_t *)res = readl(p); break;
+    case 8: *(uint32_t *)res  = readq(p); break;
+    default: __bad_atomic_size(); break;
+    }
+}
+
+#define read_atomic(p) ({                                   \
+    union { typeof(*(p)) val; char c[sizeof(*(p))]; } x_;   \
+    read_atomic_size(p, x_.c, sizeof(*(p)));                \
+    x_.val;                                                 \
+})
+
+#define write_atomic(p, x)                              \
+({                                                      \
+    typeof(*(p)) x__ = (x);                             \
+    switch ( sizeof(*(p)) )                             \
+    {                                                   \
+    case 1: writeb(x__, p); break;                      \
+    case 2: writew(x__, p); break;                      \
+    case 4: writel(x__, p); break;                      \
+    case 8: writeq(x__, p); break;                      \
+    default: __bad_atomic_size(); break;                \
+    }                                                   \
+    x__;                                                \
+})
+
+#define add_sized(p, x)                                 \
+({                                                      \
+    typeof(*(p)) x__ = (x);                             \
+    switch ( sizeof(*(p)) )                             \
+    {                                                   \
+    case 1: writeb(read_atomic(p) + x__, p); break;     \
+    case 2: writew(read_atomic(p) + x__, p); break;     \
+    case 4: writel(read_atomic(p) + x__, p); break;     \
+    case 8: writeq(read_atomic(p) + x__, p); break;     \
+    default: __bad_atomic_size(); break;                \
+    }                                                   \
+})
+
+#define __atomic_acquire_fence() \
+    asm volatile ( RISCV_ACQUIRE_BARRIER "" ::: "memory" )
+
+#define __atomic_release_fence() \
+    asm volatile ( RISCV_RELEASE_BARRIER "" ::: "memory" )
+
+/*
+ * First, the atomic ops that have no ordering constraints and therefor don't
+ * have the AQ or RL bits set.  These don't return anything, so there's only
+ * one version to worry about.
+ */
+#define ATOMIC_OP(op, asm_op, I, asm_type, c_type, prefix)  \
+static inline                                               \
+void atomic##prefix##_##op(c_type i, atomic##prefix##_t *v) \
+{                                                           \
+    asm volatile (                                          \
+        "   amo" #asm_op "." #asm_type " zero, %1, %0"      \
+        : "+A" (v->counter)                                 \
+        : "r" (I)                                           \
+        : "memory" );                                       \
+}                                                           \
+
+/*
+ * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is the reason why
+ * last argument for ATOMIC_OP isn't used.
+ */
+#define ATOMIC_OPS(op, asm_op, I)                           \
+        ATOMIC_OP (op, asm_op, I, w, int,   )
+
+ATOMIC_OPS(add, add,  i)
+ATOMIC_OPS(sub, add, -i)
+ATOMIC_OPS(and, and,  i)
+ATOMIC_OPS( or,  or,  i)
+ATOMIC_OPS(xor, xor,  i)
+
+#undef ATOMIC_OP
+#undef ATOMIC_OPS
+
+#include <asm-generic/atomic-ops.h>
+
+/*
+ * Atomic ops that have ordered, relaxed, acquire, and release variants.
+ * There's two flavors of these: the arithmatic ops have both fetch and return
+ * versions, while the logical ops only have fetch versions.
+ */
+#define ATOMIC_FETCH_OP(op, asm_op, I, asm_type, c_type, prefix)    \
+static inline                                                       \
+c_type atomic##prefix##_fetch_##op##_relaxed(c_type i,              \
+                         atomic##prefix##_t *v)                     \
+{                                                                   \
+    register c_type ret;                                            \
+    asm volatile (                                                  \
+        "   amo" #asm_op "." #asm_type " %1, %2, %0"                \
+        : "+A" (v->counter), "=r" (ret)                             \
+        : "r" (I)                                                   \
+        : "memory" );                                               \
+    return ret;                                                     \
+}                                                                   \
+static inline                                                       \
+c_type atomic##prefix##_fetch_##op(c_type i, atomic##prefix##_t *v) \
+{                                                                   \
+    register c_type ret;                                            \
+    asm volatile (                                                  \
+        "   amo" #asm_op "." #asm_type ".aqrl  %1, %2, %0"          \
+        : "+A" (v->counter), "=r" (ret)                             \
+        : "r" (I)                                                   \
+        : "memory" );                                               \
+    return ret;                                                     \
+}
+
+#define ATOMIC_OP_RETURN(op, asm_op, c_op, I, asm_type, c_type, prefix) \
+static inline                                                           \
+c_type atomic##prefix##_##op##_return_relaxed(c_type i,                 \
+                          atomic##prefix##_t *v)                        \
+{                                                                       \
+        return atomic##prefix##_fetch_##op##_relaxed(i, v) c_op I;      \
+}                                                                       \
+static inline                                                           \
+c_type atomic##prefix##_##op##_return(c_type i, atomic##prefix##_t *v)  \
+{                                                                       \
+        return atomic##prefix##_fetch_##op(i, v) c_op I;                \
+}
+
+/*
+ * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is the reason why
+ * last argument of ATOMIC_FETCH_OP, ATOMIC_OP_RETURN isn't used.
+ */
+#define ATOMIC_OPS(op, asm_op, c_op, I)                                 \
+        ATOMIC_FETCH_OP( op, asm_op,       I, w, int,   )               \
+        ATOMIC_OP_RETURN(op, asm_op, c_op, I, w, int,   )
+
+ATOMIC_OPS(add, add, +,  i)
+ATOMIC_OPS(sub, add, +, -i)
+
+#undef ATOMIC_OPS
+
+#define ATOMIC_OPS(op, asm_op, I) \
+        ATOMIC_FETCH_OP(op, asm_op, I, w, int,   )
+
+ATOMIC_OPS(and, and, i)
+ATOMIC_OPS( or,  or, i)
+ATOMIC_OPS(xor, xor, i)
+
+#undef ATOMIC_OPS
+
+#undef ATOMIC_FETCH_OP
+#undef ATOMIC_OP_RETURN
+
+/* This is required to provide a full barrier on success. */
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+       int prev, rc;
+
+    asm volatile (
+        "0: lr.w     %[p],  %[c]\n"
+        "   beq      %[p],  %[u], 1f\n"
+        "   add      %[rc], %[p], %[a]\n"
+        "   sc.w.rl  %[rc], %[rc], %[c]\n"
+        "   bnez     %[rc], 0b\n"
+        RISCV_FULL_BARRIER
+        "1:\n"
+        : [p] "=&r" (prev), [rc] "=&r" (rc), [c] "+A" (v->counter)
+        : [a] "r" (a), [u] "r" (u)
+        : "memory");
+    return prev;
+}
+
+/*
+ * atomic_{cmp,}xchg is required to have exactly the same ordering semantics as
+ * {cmp,}xchg and the operations that return.
+ */
+#define ATOMIC_OP(c_t, prefix, size)                            \
+static inline                                                   \
+c_t atomic##prefix##_xchg(atomic##prefix##_t *v, c_t n)         \
+{                                                               \
+    return __xchg(&(v->counter), n, size);                      \
+}                                                               \
+static inline                                                   \
+c_t atomic##prefix##_cmpxchg(atomic##prefix##_t *v, c_t o, c_t n) \
+{                                                               \
+    return __cmpxchg(&v->counter, o, n, size);                  \
+}
+
+#define ATOMIC_OPS() \
+    ATOMIC_OP(int,   , 4)
+
+ATOMIC_OPS()
+
+#undef ATOMIC_OPS
+#undef ATOMIC_OP
+
+static inline int atomic_sub_if_positive(atomic_t *v, int offset)
+{
+       int prev, rc;
+
+    asm volatile (
+        "0: lr.w     %[p],  %[c]\n"
+        "   sub      %[rc], %[p], %[o]\n"
+        "   bltz     %[rc], 1f\n"
+        "   sc.w.rl  %[rc], %[rc], %[c]\n"
+        "   bnez     %[rc], 0b\n"
+        "   fence    rw, rw\n"
+        "1:\n"
+        : [p] "=&r" (prev), [rc] "=&r" (rc), [c] "+A" (v->counter)
+        : [o] "r" (offset)
+        : "memory" );
+    return prev - offset;
+}
+
+#endif /* _ASM_RISCV_ATOMIC_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-generic/atomic-ops.h b/xen/include/asm-generic/atomic-ops.h
new file mode 100644
index 0000000000..da1ea5aac2
--- /dev/null
+++ b/xen/include/asm-generic/atomic-ops.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * The header provides default implementations for every xen/atomic.h-provided
+ * forward inline declaration that can be synthesized from other atomic
+ * functions.
+ */
+#ifndef _ASM_GENERIC_ATOMIC_OPS_H_
+#define _ASM_GENERIC_ATOMIC_OPS_H_
+
+#include <xen/atomic.h>
+#include <xen/lib.h>
+
+#ifndef ATOMIC_READ
+static inline int atomic_read(const atomic_t *v)
+{
+    return ACCESS_ONCE(v->counter);
+}
+#endif
+
+#ifndef _ATOMIC_READ
+static inline int _atomic_read(atomic_t v)
+{
+    return v.counter;
+}
+#endif
+
+#ifndef ATOMIC_SET
+static inline void atomic_set(atomic_t *v, int i)
+{
+    ACCESS_ONCE(v->counter) = i;
+}
+#endif
+
+#ifndef _ATOMIC_SET
+static inline void _atomic_set(atomic_t *v, int i)
+{
+    v->counter = i;
+}
+#endif
+
+#ifndef ATOMIC_SUB_AND_TEST
+static inline int atomic_sub_and_test(int i, atomic_t *v)
+{
+    return atomic_sub_return(i, v) == 0;
+}
+#endif
+
+#ifndef ATOMIC_INC
+static inline void atomic_inc(atomic_t *v)
+{
+    atomic_add(1, v);
+}
+#endif
+
+#ifndef ATOMIC_INC_RETURN
+static inline int atomic_inc_return(atomic_t *v)
+{
+    return atomic_add_return(1, v);
+}
+#endif
+
+#ifndef ATOMIC_DEC
+static inline void atomic_dec(atomic_t *v)
+{
+    atomic_sub(1, v);
+}
+#endif
+
+#ifndef ATOMIC_DEC_RETURN
+static inline int atomic_dec_return(atomic_t *v)
+{
+    return atomic_sub_return(1, v);
+}
+#endif
+
+#ifndef ATOMIC_DEC_AND_TEST
+static inline int atomic_dec_and_test(atomic_t *v)
+{
+    return atomic_sub_return(1, v) == 0;
+}
+#endif
+
+#ifndef ATOMIC_ADD_NEGATIVE
+static inline int atomic_add_negative(int i, atomic_t *v)
+{
+    return atomic_add_return(i, v) < 0;
+}
+#endif
+
+#ifndef ATOMIC_INC_AND_TEST
+static inline int atomic_inc_and_test(atomic_t *v)
+{
+    return atomic_add_return(1, v) == 0;
+}
+#endif
+
+#endif /* _ASM_GENERIC_ATOMIC_OPS_H_ */
-- 
2.43.0



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

* [PATCH v6 11/20] xen/riscv: introduce monitor.h
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (9 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 10/20] xen/riscv: introduce atomic.h Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-15 18:06 ` [PATCH v6 12/20] xen/riscv: add definition of __read_mostly Oleksii Kurochko
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Tamas K Lengyel, Alexandru Isaila,
	Petre Pircalabu, Alistair Francis, Bob Eshleman, Connor Davis

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V4/V5/V6:
 - Nothing changed. Only rebase.
---
Changes in V3:
 - new patch.
---
 xen/arch/riscv/include/asm/monitor.h | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 xen/arch/riscv/include/asm/monitor.h

diff --git a/xen/arch/riscv/include/asm/monitor.h b/xen/arch/riscv/include/asm/monitor.h
new file mode 100644
index 0000000000..f4fe2c0690
--- /dev/null
+++ b/xen/arch/riscv/include/asm/monitor.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __ASM_RISCV_MONITOR_H__
+#define __ASM_RISCV_MONITOR_H__
+
+#include <xen/bug.h>
+
+#include <asm-generic/monitor.h>
+
+struct domain;
+
+static inline uint32_t arch_monitor_get_capabilities(struct domain *d)
+{
+    BUG_ON("unimplemented");
+    return 0;
+}
+
+#endif /* __ASM_RISCV_MONITOR_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.43.0



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

* [PATCH v6 12/20] xen/riscv: add definition of __read_mostly
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (10 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 11/20] xen/riscv: introduce monitor.h Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-15 18:06 ` [PATCH v6 13/20] xen/riscv: add required things to current.h Oleksii Kurochko
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

The definition of __read_mostly should be removed in:
https://lore.kernel.org/xen-devel/f25eb5c9-7c14-6e23-8535-2c66772b333e@suse.com/

The patch introduces it in arch-specific header to not
block enabling of full Xen build for RISC-V.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
- [PATCH] move __read_mostly to xen/cache.h  [2]

Right now, the patch series doesn't have a direct dependency on [2] and it
provides __read_mostly in the patch:
    [PATCH v3 26/34] xen/riscv: add definition of __read_mostly
However, it will be dropped as soon as [2] is merged or at least when the
final version of the patch [2] is provided.

[2] https://lore.kernel.org/xen-devel/f25eb5c9-7c14-6e23-8535-2c66772b333e@suse.com/
---
Changes in V4-V7:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/cache.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/xen/arch/riscv/include/asm/cache.h b/xen/arch/riscv/include/asm/cache.h
index 69573eb051..94bd94db53 100644
--- a/xen/arch/riscv/include/asm/cache.h
+++ b/xen/arch/riscv/include/asm/cache.h
@@ -3,4 +3,6 @@
 #ifndef _ASM_RISCV_CACHE_H
 #define _ASM_RISCV_CACHE_H
 
+#define __read_mostly __section(".data.read_mostly")
+
 #endif /* _ASM_RISCV_CACHE_H */
-- 
2.43.0



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

* [PATCH v6 13/20] xen/riscv: add required things to current.h
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (11 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 12/20] xen/riscv: add definition of __read_mostly Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-15 18:06 ` [PATCH v6 14/20] xen/riscv: add minimal stuff to page.h to build full Xen Oleksii Kurochko
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

Add minimal requied things to be able to build full Xen.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in V5/V6:
 - Nothing changed. Only rebase.
---
Changes in V4:
 - BUG() was changed to BUG_ON("unimplemented");
 - Change "xen/bug.h" to "xen/lib.h" as BUG_ON is defined in xen/lib.h.
 - Add Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in V3:
 - add SPDX
 - drop a forward declaration of struct vcpu;
 - update guest_cpu_user_regs() macros
 - replace get_processor_id with smp_processor_id
 - update the commit message
 - code style fixes
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/current.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/xen/arch/riscv/include/asm/current.h b/xen/arch/riscv/include/asm/current.h
index d84f15dc50..aedb6dc732 100644
--- a/xen/arch/riscv/include/asm/current.h
+++ b/xen/arch/riscv/include/asm/current.h
@@ -3,6 +3,21 @@
 #ifndef __ASM_CURRENT_H
 #define __ASM_CURRENT_H
 
+#include <xen/lib.h>
+#include <xen/percpu.h>
+#include <asm/processor.h>
+
+#ifndef __ASSEMBLY__
+
+/* Which VCPU is "current" on this PCPU. */
+DECLARE_PER_CPU(struct vcpu *, curr_vcpu);
+
+#define current            this_cpu(curr_vcpu)
+#define set_current(vcpu)  do { current = (vcpu); } while (0)
+#define get_cpu_current(cpu)  per_cpu(curr_vcpu, cpu)
+
+#define guest_cpu_user_regs() ({ BUG_ON("unimplemented"); NULL; })
+
 #define switch_stack_and_jump(stack, fn) do {               \
     asm volatile (                                          \
             "mv sp, %0\n"                                   \
@@ -10,4 +25,8 @@
     unreachable();                                          \
 } while ( false )
 
+#define get_per_cpu_offset() __per_cpu_offset[smp_processor_id()]
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* __ASM_CURRENT_H */
-- 
2.43.0



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

* [PATCH v6 14/20] xen/riscv: add minimal stuff to page.h to build full Xen
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (12 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 13/20] xen/riscv: add required things to current.h Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-15 18:06 ` [PATCH v6 15/20] xen/riscv: add minimal stuff to processor.h " Oleksii Kurochko
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in V5-6:
 - Nothing changed. Only rebase.
---
Changes in V4:
---
 - Change message -> subject in "Changes in V3"
 - s/BUG/BUG_ON("...")
 - Do proper rebase ( pfn_to_paddr() and paddr_to_pfn() aren't removed ).
---
Changes in V3:
 - update the commit subject
 - add implemetation of PAGE_HYPERVISOR macros
 - add Acked-by: Jan Beulich <jbeulich@suse.com>
 - drop definition of pfn_to_addr, and paddr_to_pfn in <asm/mm.h>
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/page.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/xen/arch/riscv/include/asm/page.h b/xen/arch/riscv/include/asm/page.h
index 95074e29b3..c831e16417 100644
--- a/xen/arch/riscv/include/asm/page.h
+++ b/xen/arch/riscv/include/asm/page.h
@@ -6,6 +6,7 @@
 #ifndef __ASSEMBLY__
 
 #include <xen/const.h>
+#include <xen/bug.h>
 #include <xen/types.h>
 
 #include <asm/mm.h>
@@ -32,6 +33,10 @@
 #define PTE_LEAF_DEFAULT            (PTE_VALID | PTE_READABLE | PTE_WRITABLE)
 #define PTE_TABLE                   (PTE_VALID)
 
+#define PAGE_HYPERVISOR_RW          (PTE_VALID | PTE_READABLE | PTE_WRITABLE)
+
+#define PAGE_HYPERVISOR             PAGE_HYPERVISOR_RW
+
 /* Calculate the offsets into the pagetables for a given VA */
 #define pt_linear_offset(lvl, va)   ((va) >> XEN_PT_LEVEL_SHIFT(lvl))
 
@@ -62,6 +67,20 @@ static inline bool pte_is_valid(pte_t p)
     return p.pte & PTE_VALID;
 }
 
+static inline void invalidate_icache(void)
+{
+    BUG_ON("unimplemented");
+}
+
+#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(dp, sp) memcpy(dp, sp, PAGE_SIZE)
+
+/* TODO: Flush the dcache for an entire page. */
+static inline void flush_page_to_ram(unsigned long mfn, bool sync_icache)
+{
+    BUG_ON("unimplemented");
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_RISCV_PAGE_H */
-- 
2.43.0



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

* [PATCH v6 15/20] xen/riscv: add minimal stuff to processor.h to build full Xen
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (13 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 14/20] xen/riscv: add minimal stuff to page.h to build full Xen Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-21 13:26   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 16/20] xen/riscv: add minimal stuff to mm.h " Oleksii Kurochko
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

The cpu_relax() function, introduced in this commit, is anticipated to
support _zihintpause by the CPU.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - drop incorrect part in riscv/booting.txt and move the introduction of it to
   separate patch.
 - compiler check that __riscv_zihintpause exist was droped to separate patch.
 - minor fixes.
 - drop unnecessary comment.
 - update the commit message.
---
Changes in V5:
 - Code style fixes.
 - drop introduced TOOLCHAIN_HAS_ZIHINTPAUSE and use as-insn instead and use
   as-insn istead.
---
Changes in V4:
 - Change message -> subject in "Changes in V3"
 - Documentation about system requirement was added. In the future, it can be checked if the extension is supported
   by system __riscv_isa_extension_available() ( https://gitlab.com/xen-project/people/olkur/xen/-/commit/737998e89ed305eb92059300c374dfa53d2143fa )
 - update cpu_relax() function to check if __riscv_zihintpause is supported by a toolchain
 - add conditional _zihintpause to -march if it is supported by a toolchain
Changes in V3:
 - update the commit subject
 - rename get_processor_id to smp_processor_id
 - code style fixes
 - update the cpu_relax instruction: use pause instruction instead of div %0, %0, zero
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/include/asm/processor.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/xen/arch/riscv/include/asm/processor.h b/xen/arch/riscv/include/asm/processor.h
index 6db681d805..6846151717 100644
--- a/xen/arch/riscv/include/asm/processor.h
+++ b/xen/arch/riscv/include/asm/processor.h
@@ -12,6 +12,9 @@
 
 #ifndef __ASSEMBLY__
 
+/* TODO: need to be implemeted */
+#define smp_processor_id() 0
+
 /* On stack VCPU state */
 struct cpu_user_regs
 {
@@ -53,6 +56,23 @@ struct cpu_user_regs
     unsigned long pregs;
 };
 
+/* TODO: need to implement */
+#define cpu_to_core(cpu)   0
+#define cpu_to_socket(cpu) 0
+
+static inline void cpu_relax(void)
+{
+#ifdef __riscv_zihintpause
+    /* Reduce instruction retirement. */
+    __asm__ __volatile__ ( "pause" );
+#else
+    /* Encoding of the pause instruction */
+    __asm__ __volatile__ ( ".insn 0x0100000F" );
+#endif
+
+    barrier();
+}
+
 static inline void wfi(void)
 {
     __asm__ __volatile__ ("wfi");
-- 
2.43.0



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

* [PATCH v6 16/20] xen/riscv: add minimal stuff to mm.h to build full Xen
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (14 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 15/20] xen/riscv: add minimal stuff to processor.h " Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-21 13:37   ` Jan Beulich
  2024-03-15 18:06 ` [PATCH v6 17/20] xen/riscv: introduce vm_event_*() functions Oleksii Kurochko
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V6:
 - drop __virt_to_maddr() ( transform to macro ) and __maddr_to_virt ( rename to maddr_to_virt ).
 - parenthesize va in definition of vmap_to_mfn().
 - Code style fixes. 
---
Changes in V5:
 - update the comment around "struct domain *domain;" : zero -> NULL
 - fix ident. for unsigned long val;
 - put page_to_virt() and virt_to_page() close to each other.
 - drop unnessary leading underscore
 - drop a space before the comment: /* Count of uses of this frame as its current type. */
 - drop comment about a page 'not as a shadow'. it is not necessary for RISC-V
---
Changes in V4:
 - update an argument name of PFN_ORDERN macros.
 - drop pad at the end of 'struct page_info'.
 - Change message -> subject in "Changes in V3"
 - delete duplicated macros from riscv/mm.h
 - fix identation in struct page_info
 - align comment for PGC_ macros
 - update definitions of domain_set_alloc_bitsize() and domain_clamp_alloc_bitsize()
 - drop unnessary comments.
 - s/BUG/BUG_ON("...")
 - define __virt_to_maddr, __maddr_to_virt as stubs
 - add inclusion of xen/mm-frame.h for mfn_x and others
 - include "xen/mm.h" instead of "asm/mm.h" to fix compilation issues:
	 In file included from arch/riscv/setup.c:7:
	./arch/riscv/include/asm/mm.h:60:28: error: field 'list' has incomplete type
	   60 |     struct page_list_entry list;
	      |                            ^~~~
	./arch/riscv/include/asm/mm.h:81:43: error: 'MAX_ORDER' undeclared here (not in a function)
	   81 |                 unsigned long first_dirty:MAX_ORDER + 1;
	      |                                           ^~~~~~~~~
	./arch/riscv/include/asm/mm.h:81:31: error: bit-field 'first_dirty' width not an integer constant
	   81 |                 unsigned long first_dirty:MAX_ORDER + 1;
 - Define __virt_to_mfn() and __mfn_to_virt() using maddr_to_mfn() and mfn_to_maddr().
---
Changes in V3:
 - update the commit title
 - introduce DIRECTMAP_VIRT_START.
 - drop changes related pfn_to_paddr() and paddr_to_pfn as they were remvoe in
   [PATCH v2 32/39] xen/riscv: add minimal stuff to asm/page.h to build full Xen
 - code style fixes.
 - drop get_page_nr  and put_page_nr as they don't need for time being
 - drop CONFIG_STATIC_MEMORY related things
 - code style fixes
---
Changes in V2:
 - define stub for arch_get_dma_bitsize(void)
---
 xen/arch/riscv/include/asm/mm.h | 240 ++++++++++++++++++++++++++++++++
 xen/arch/riscv/mm.c             |   2 +-
 xen/arch/riscv/setup.c          |   2 +-
 3 files changed, 242 insertions(+), 2 deletions(-)

diff --git a/xen/arch/riscv/include/asm/mm.h b/xen/arch/riscv/include/asm/mm.h
index 07c7a0abba..c9fd456418 100644
--- a/xen/arch/riscv/include/asm/mm.h
+++ b/xen/arch/riscv/include/asm/mm.h
@@ -3,11 +3,246 @@
 #ifndef _ASM_RISCV_MM_H
 #define _ASM_RISCV_MM_H
 
+#include <public/xen.h>
+#include <xen/bug.h>
+#include <xen/mm-frame.h>
+#include <xen/pdx.h>
+#include <xen/types.h>
+
 #include <asm/page-bits.h>
 
 #define pfn_to_paddr(pfn) ((paddr_t)(pfn) << PAGE_SHIFT)
 #define paddr_to_pfn(pa)  ((unsigned long)((pa) >> PAGE_SHIFT))
 
+#define paddr_to_pdx(pa)    mfn_to_pdx(maddr_to_mfn(pa))
+#define gfn_to_gaddr(gfn)   pfn_to_paddr(gfn_x(gfn))
+#define gaddr_to_gfn(ga)    _gfn(paddr_to_pfn(ga))
+#define mfn_to_maddr(mfn)   pfn_to_paddr(mfn_x(mfn))
+#define maddr_to_mfn(ma)    _mfn(paddr_to_pfn(ma))
+#define vmap_to_mfn(va)     maddr_to_mfn(virt_to_maddr((vaddr_t)(va)))
+#define vmap_to_page(va)    mfn_to_page(vmap_to_mfn(va))
+
+static inline void *maddr_to_virt(unsigned long ma)
+{
+    BUG_ON("unimplemented");
+    return NULL;
+}
+
+#define virt_to_maddr(va) ({ BUG_ON("unimplemented"); 0; })
+
+/* Convert between Xen-heap virtual addresses and machine frame numbers. */
+#define __virt_to_mfn(va)  mfn_x(maddr_to_mfn(virt_to_maddr(va)))
+#define __mfn_to_virt(mfn) maddr_to_virt(mfn_to_maddr(_mfn(mfn)))
+
+/*
+ * We define non-underscored wrappers for above conversion functions.
+ * These are overriden in various source files while underscored version
+ * remain intact.
+ */
+#define virt_to_mfn(va)     __virt_to_mfn(va)
+#define mfn_to_virt(mfn)    __mfn_to_virt(mfn)
+
+struct page_info
+{
+    /* Each frame can be threaded onto a doubly-linked list. */
+    struct page_list_entry list;
+
+    /* Reference count and various PGC_xxx flags and fields. */
+    unsigned long count_info;
+
+    /* Context-dependent fields follow... */
+    union {
+        /* Page is in use: ((count_info & PGC_count_mask) != 0). */
+        struct {
+            /* Type reference count and various PGT_xxx flags and fields. */
+            unsigned long type_info;
+        } inuse;
+
+        /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
+        union {
+            struct {
+                /*
+                 * Index of the first *possibly* unscrubbed page in the buddy.
+                 * One more bit than maximum possible order to accommodate
+                 * INVALID_DIRTY_IDX.
+                 */
+#define INVALID_DIRTY_IDX ((1UL << (MAX_ORDER + 1)) - 1)
+                unsigned long first_dirty:MAX_ORDER + 1;
+
+                /* Do TLBs need flushing for safety before next page use? */
+                bool need_tlbflush:1;
+
+#define BUDDY_NOT_SCRUBBING    0
+#define BUDDY_SCRUBBING        1
+#define BUDDY_SCRUB_ABORT      2
+                unsigned long scrub_state:2;
+            };
+
+            unsigned long val;
+        } free;
+    } u;
+
+    union {
+        /* Page is in use */
+        struct {
+            /* Owner of this page (NULL if page is anonymous). */
+            struct domain *domain;
+        } inuse;
+
+        /* Page is on a free list. */
+        struct {
+            /* Order-size of the free chunk this page is the head of. */
+            unsigned int order;
+        } free;
+    } v;
+
+    union {
+        /*
+         * Timestamp from 'TLB clock', used to avoid extra safety flushes.
+         * Only valid for: a) free pages, and b) pages with zero type count
+         */
+        uint32_t tlbflush_timestamp;
+    };
+};
+
+#define frame_table ((struct page_info *)FRAMETABLE_VIRT_START)
+
+/* PDX of the first page in the frame table. */
+extern unsigned long frametable_base_pdx;
+
+/* Convert between machine frame numbers and page-info structures. */
+#define mfn_to_page(mfn)                                            \
+    (frame_table + (mfn_to_pdx(mfn) - frametable_base_pdx))
+#define page_to_mfn(pg)                                             \
+    pdx_to_mfn((unsigned long)((pg) - frame_table) + frametable_base_pdx)
+
+static inline void *page_to_virt(const struct page_info *pg)
+{
+    return mfn_to_virt(mfn_x(page_to_mfn(pg)));
+}
+
+/* Convert between Xen-heap virtual addresses and page-info structures. */
+static inline struct page_info *virt_to_page(const void *v)
+{
+    BUG_ON("unimplemented");
+    return NULL;
+}
+
+/*
+ * Common code requires get_page_type and put_page_type.
+ * We don't care about typecounts so we just do the minimum to make it
+ * happy.
+ */
+static inline int get_page_type(struct page_info *page, unsigned long type)
+{
+    return 1;
+}
+
+static inline void put_page_type(struct page_info *page)
+{
+}
+
+static inline void put_page_and_type(struct page_info *page)
+{
+    put_page_type(page);
+    put_page(page);
+}
+
+/*
+ * RISC-V does not have an M2P, but common code expects a handful of
+ * M2P-related defines and functions. Provide dummy versions of these.
+ */
+#define INVALID_M2P_ENTRY        (~0UL)
+#define SHARED_M2P_ENTRY         (~0UL - 1UL)
+#define SHARED_M2P(_e)           ((_e) == SHARED_M2P_ENTRY)
+
+#define set_gpfn_from_mfn(mfn, pfn) do { (void)(mfn), (void)(pfn); } while (0)
+#define mfn_to_gfn(d, mfn) ((void)(d), _gfn(mfn_x(mfn)))
+
+#define PDX_GROUP_SHIFT (PAGE_SHIFT + VPN_BITS)
+
+static inline unsigned long domain_get_maximum_gpfn(struct domain *d)
+{
+    BUG_ON("unimplemented");
+    return 0;
+}
+
+static inline long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
+{
+    BUG_ON("unimplemented");
+    return 0;
+}
+
+/*
+ * On RISCV, all the RAM is currently direct mapped in Xen.
+ * Hence return always true.
+ */
+static inline bool arch_mfns_in_directmap(unsigned long mfn, unsigned long nr)
+{
+    return true;
+}
+
+#define PG_shift(idx)   (BITS_PER_LONG - (idx))
+#define PG_mask(x, idx) (x ## UL << PG_shift(idx))
+
+#define PGT_none          PG_mask(0, 1)  /* no special uses of this page   */
+#define PGT_writable_page PG_mask(1, 1)  /* has writable mappings?         */
+#define PGT_type_mask     PG_mask(1, 1)  /* Bits 31 or 63.                 */
+
+/* Count of uses of this frame as its current type. */
+#define PGT_count_width   PG_shift(2)
+#define PGT_count_mask    ((1UL << PGT_count_width) - 1)
+
+/*
+ * Page needs to be scrubbed. Since this bit can only be set on a page that is
+ * free (i.e. in PGC_state_free) we can reuse PGC_allocated bit.
+ */
+#define _PGC_need_scrub   _PGC_allocated
+#define PGC_need_scrub    PGC_allocated
+
+/* Cleared when the owning guest 'frees' this page. */
+#define _PGC_allocated    PG_shift(1)
+#define PGC_allocated     PG_mask(1, 1)
+/* Page is Xen heap? */
+#define _PGC_xen_heap     PG_shift(2)
+#define PGC_xen_heap      PG_mask(1, 2)
+/* Page is broken? */
+#define _PGC_broken       PG_shift(7)
+#define PGC_broken        PG_mask(1, 7)
+/* Mutually-exclusive page states: { inuse, offlining, offlined, free }. */
+#define PGC_state         PG_mask(3, 9)
+#define PGC_state_inuse   PG_mask(0, 9)
+#define PGC_state_offlining PG_mask(1, 9)
+#define PGC_state_offlined PG_mask(2, 9)
+#define PGC_state_free    PG_mask(3, 9)
+#define page_state_is(pg, st) (((pg)->count_info&PGC_state) == PGC_state_##st)
+
+/* Count of references to this frame. */
+#define PGC_count_width   PG_shift(9)
+#define PGC_count_mask    ((1UL << PGC_count_width) - 1)
+
+#define _PGC_extra        PG_shift(10)
+#define PGC_extra         PG_mask(1, 10)
+
+#define is_xen_heap_page(page) ((page)->count_info & PGC_xen_heap)
+#define is_xen_heap_mfn(mfn) \
+    (mfn_valid(mfn) && is_xen_heap_page(mfn_to_page(mfn)))
+
+#define is_xen_fixed_mfn(mfn)                                   \
+    ((mfn_to_maddr(mfn) >= virt_to_maddr((vaddr_t)_start)) &&   \
+     (mfn_to_maddr(mfn) <= virt_to_maddr((vaddr_t)_end - 1)))
+
+#define page_get_owner(p)    (p)->v.inuse.domain
+#define page_set_owner(p, d) ((p)->v.inuse.domain = (d))
+
+/* TODO: implement */
+#define mfn_valid(mfn) ({ (void)(mfn); 0; })
+
+#define domain_set_alloc_bitsize(d) ((void)(d))
+#define domain_clamp_alloc_bitsize(d, b) ((void)(d), (b))
+
+#define PFN_ORDER(pfn) ((pfn)->v.free.order)
+
 extern unsigned char cpu0_boot_stack[];
 
 void setup_initial_pagetables(void);
@@ -20,4 +255,9 @@ unsigned long calc_phys_offset(void);
 
 void turn_on_mmu(unsigned long ra);
 
+static inline unsigned int arch_get_dma_bitsize(void)
+{
+    return 32; /* TODO */
+}
+
 #endif /* _ASM_RISCV_MM_H */
diff --git a/xen/arch/riscv/mm.c b/xen/arch/riscv/mm.c
index 053f043a3d..fe3a43be20 100644
--- a/xen/arch/riscv/mm.c
+++ b/xen/arch/riscv/mm.c
@@ -5,12 +5,12 @@
 #include <xen/init.h>
 #include <xen/kernel.h>
 #include <xen/macros.h>
+#include <xen/mm.h>
 #include <xen/pfn.h>
 
 #include <asm/early_printk.h>
 #include <asm/csr.h>
 #include <asm/current.h>
-#include <asm/mm.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 
diff --git a/xen/arch/riscv/setup.c b/xen/arch/riscv/setup.c
index 6593f601c1..98a94c4c48 100644
--- a/xen/arch/riscv/setup.c
+++ b/xen/arch/riscv/setup.c
@@ -2,9 +2,9 @@
 
 #include <xen/compile.h>
 #include <xen/init.h>
+#include <xen/mm.h>
 
 #include <asm/early_printk.h>
-#include <asm/mm.h>
 
 /* Xen stack for bringing up the first CPU. */
 unsigned char __initdata cpu0_boot_stack[STACK_SIZE]
-- 
2.43.0



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

* [PATCH v6 17/20] xen/riscv: introduce vm_event_*() functions
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (15 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 16/20] xen/riscv: add minimal stuff to mm.h " Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-15 18:06 ` [PATCH v6 18/20] xen/riscv: add minimal amount of stubs to build full Xen Oleksii Kurochko
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Tamas K Lengyel, Alexandru Isaila, Petre Pircalabu

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V5-V6:
 - Only rebase was done.
---
Changes in V4:
  - New patch.
---
 xen/arch/riscv/Makefile   |  1 +
 xen/arch/riscv/vm_event.c | 19 +++++++++++++++++++
 2 files changed, 20 insertions(+)
 create mode 100644 xen/arch/riscv/vm_event.c

diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
index 2fefe14e7c..1ed1a8369b 100644
--- a/xen/arch/riscv/Makefile
+++ b/xen/arch/riscv/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_RISCV_64) += riscv64/
 obj-y += sbi.o
 obj-y += setup.o
 obj-y += traps.o
+obj-y += vm_event.o
 
 $(TARGET): $(TARGET)-syms
 	$(OBJCOPY) -O binary -S $< $@
diff --git a/xen/arch/riscv/vm_event.c b/xen/arch/riscv/vm_event.c
new file mode 100644
index 0000000000..bb1fc73bc1
--- /dev/null
+++ b/xen/arch/riscv/vm_event.c
@@ -0,0 +1,19 @@
+#include <xen/bug.h>
+
+struct vm_event_st;
+struct vcpu;
+
+void vm_event_fill_regs(struct vm_event_st *req)
+{
+    BUG_ON("unimplemented");
+}
+
+void vm_event_set_registers(struct vcpu *v, struct vm_event_st *rsp)
+{
+    BUG_ON("unimplemented");
+}
+
+void vm_event_monitor_next_interrupt(struct vcpu *v)
+{
+    /* Not supported on RISCV. */
+}
-- 
2.43.0



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

* [PATCH v6 18/20] xen/riscv: add minimal amount of stubs to build full Xen
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (16 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 17/20] xen/riscv: introduce vm_event_*() functions Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-15 18:06 ` [PATCH v6 19/20] xen/riscv: enable full Xen build Oleksii Kurochko
  2024-03-15 18:06 ` [PATCH v6 20/20] xen/README: add compiler and binutils versions for RISC-V64 Oleksii Kurochko
  19 siblings, 0 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in V6:
 - update the commit in stubs.c around /* ... common/irq.c ... */
 - add Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in V5:
 - drop unrelated changes
 - assert_failed("unimplmented...") change to BUG_ON()
---
Changes in V4:
  - added new stubs which are necessary for compilation after rebase: __cpu_up(), __cpu_disable(), __cpu_die()
    from smpboot.c
  - back changes related to printk() in early_printk() as they should be removed in the next patch to avoid
    compilation error.
  - update definition of cpu_khz: __read_mostly -> __ro_after_init.
  - drop vm_event_reset_vmtrace(). It is defibed in asm-generic/vm_event.h.
  - move vm_event_*() functions from stubs.c to riscv/vm_event.c.
  - s/BUG/BUG_ON("unimplemented") in stubs.c
  - back irq_actor_none() and irq_actor_none() as common/irq.c isn't compiled at this moment,
    so this function are needed to avoid compilation error.
  - defined max_page to avoid compilation error, it will be removed as soon as common/page_alloc.c will
    be compiled.
---
Changes in V3:
 - code style fixes.
 - update attribute for frametable_base_pdx  and frametable_virt_end to __ro_after_init.
   insteaf of read_mostly.
 - use BUG() instead of assert_failed/WARN for newly introduced stubs.
 - drop "#include <public/vm_event.h>" in stubs.c and use forward declaration instead.
 - drop ack_node() and end_node() as they aren't used now.
---
Changes in V2:
 - define udelay stub
 - remove 'select HAS_PDX' from RISC-V Kconfig because of
   https://lore.kernel.org/xen-devel/20231006144405.1078260-1-andrew.cooper3@citrix.com/
---
 xen/arch/riscv/Makefile |   1 +
 xen/arch/riscv/mm.c     |  50 +++++
 xen/arch/riscv/setup.c  |   8 +
 xen/arch/riscv/stubs.c  | 439 ++++++++++++++++++++++++++++++++++++++++
 xen/arch/riscv/traps.c  |  25 +++
 5 files changed, 523 insertions(+)
 create mode 100644 xen/arch/riscv/stubs.c

diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
index 1ed1a8369b..60afbc0ad9 100644
--- a/xen/arch/riscv/Makefile
+++ b/xen/arch/riscv/Makefile
@@ -4,6 +4,7 @@ obj-y += mm.o
 obj-$(CONFIG_RISCV_64) += riscv64/
 obj-y += sbi.o
 obj-y += setup.o
+obj-y += stubs.o
 obj-y += traps.o
 obj-y += vm_event.o
 
diff --git a/xen/arch/riscv/mm.c b/xen/arch/riscv/mm.c
index fe3a43be20..2c3fb7d72e 100644
--- a/xen/arch/riscv/mm.c
+++ b/xen/arch/riscv/mm.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <xen/bug.h>
 #include <xen/cache.h>
 #include <xen/compiler.h>
 #include <xen/init.h>
@@ -14,6 +15,9 @@
 #include <asm/page.h>
 #include <asm/processor.h>
 
+unsigned long __ro_after_init frametable_base_pdx;
+unsigned long __ro_after_init frametable_virt_end;
+
 struct mmu_desc {
     unsigned int num_levels;
     unsigned int pgtbl_count;
@@ -294,3 +298,49 @@ unsigned long __init calc_phys_offset(void)
     phys_offset = load_start - XEN_VIRT_START;
     return phys_offset;
 }
+
+void put_page(struct page_info *page)
+{
+    BUG_ON("unimplemented");
+}
+
+unsigned long get_upper_mfn_bound(void)
+{
+    /* No memory hotplug yet, so current memory limit is the final one. */
+    return max_page - 1;
+}
+
+void arch_dump_shared_mem_info(void)
+{
+    BUG_ON("unimplemented");
+}
+
+int populate_pt_range(unsigned long virt, unsigned long nr_mfns)
+{
+    BUG_ON("unimplemented");
+    return -1;
+}
+
+int xenmem_add_to_physmap_one(struct domain *d, unsigned int space,
+                              union add_to_physmap_extra extra,
+                              unsigned long idx, gfn_t gfn)
+{
+    BUG_ON("unimplemented");
+
+    return 0;
+}
+
+int destroy_xen_mappings(unsigned long s, unsigned long e)
+{
+    BUG_ON("unimplemented");
+    return -1;
+}
+
+int map_pages_to_xen(unsigned long virt,
+                     mfn_t mfn,
+                     unsigned long nr_mfns,
+                     unsigned int flags)
+{
+    BUG_ON("unimplemented");
+    return -1;
+}
diff --git a/xen/arch/riscv/setup.c b/xen/arch/riscv/setup.c
index 98a94c4c48..8bb5bdb2ae 100644
--- a/xen/arch/riscv/setup.c
+++ b/xen/arch/riscv/setup.c
@@ -1,11 +1,19 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <xen/bug.h>
 #include <xen/compile.h>
 #include <xen/init.h>
 #include <xen/mm.h>
 
+#include <public/version.h>
+
 #include <asm/early_printk.h>
 
+void arch_get_xen_caps(xen_capabilities_info_t *info)
+{
+    BUG_ON("unimplemented");
+}
+
 /* Xen stack for bringing up the first CPU. */
 unsigned char __initdata cpu0_boot_stack[STACK_SIZE]
     __aligned(STACK_SIZE);
diff --git a/xen/arch/riscv/stubs.c b/xen/arch/riscv/stubs.c
new file mode 100644
index 0000000000..8285bcffef
--- /dev/null
+++ b/xen/arch/riscv/stubs.c
@@ -0,0 +1,439 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <xen/cpumask.h>
+#include <xen/domain.h>
+#include <xen/irq.h>
+#include <xen/nodemask.h>
+#include <xen/time.h>
+#include <public/domctl.h>
+
+#include <asm/current.h>
+
+/* smpboot.c */
+
+cpumask_t cpu_online_map;
+cpumask_t cpu_present_map;
+cpumask_t cpu_possible_map;
+
+/* ID of the PCPU we're running on */
+DEFINE_PER_CPU(unsigned int, cpu_id);
+/* XXX these seem awfully x86ish... */
+/* representing HT siblings of each logical CPU */
+DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_mask);
+/* representing HT and core siblings of each logical CPU */
+DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_mask);
+
+nodemask_t __read_mostly node_online_map = { { [0] = 1UL } };
+
+/*
+ * max_page is defined in page_alloc.c which isn't complied for now.
+ * definition of max_page will be remove as soon as page_alloc is built.
+ */
+unsigned long __read_mostly max_page;
+
+/* time.c */
+
+unsigned long __ro_after_init cpu_khz;  /* CPU clock frequency in kHz. */
+
+s_time_t get_s_time(void)
+{
+    BUG_ON("unimplemented");
+}
+
+int reprogram_timer(s_time_t timeout)
+{
+    BUG_ON("unimplemented");
+}
+
+void send_timer_event(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+void domain_set_time_offset(struct domain *d, int64_t time_offset_seconds)
+{
+    BUG_ON("unimplemented");
+}
+
+/* shutdown.c */
+
+void machine_restart(unsigned int delay_millisecs)
+{
+    BUG_ON("unimplemented");
+}
+
+void machine_halt(void)
+{
+    BUG_ON("unimplemented");
+}
+
+/* domctl.c */
+
+long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
+                    XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_get_domain_info(const struct domain *d,
+                          struct xen_domctl_getdomaininfo *info)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
+{
+    BUG_ON("unimplemented");
+}
+
+/* monitor.c */
+
+int arch_monitor_domctl_event(struct domain *d,
+                              struct xen_domctl_monitor_op *mop)
+{
+    BUG_ON("unimplemented");
+}
+
+/* smp.c */
+
+void arch_flush_tlb_mask(const cpumask_t *mask)
+{
+    BUG_ON("unimplemented");
+}
+
+void smp_send_event_check_mask(const cpumask_t *mask)
+{
+    BUG_ON("unimplemented");
+}
+
+void smp_send_call_function_mask(const cpumask_t *mask)
+{
+    BUG_ON("unimplemented");
+}
+
+/* irq.c */
+
+struct pirq *alloc_pirq_struct(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+int pirq_guest_bind(struct vcpu *v, struct pirq *pirq, int will_share)
+{
+    BUG_ON("unimplemented");
+}
+
+void pirq_guest_unbind(struct domain *d, struct pirq *pirq)
+{
+    BUG_ON("unimplemented");
+}
+
+void pirq_set_affinity(struct domain *d, int pirq, const cpumask_t *mask)
+{
+    BUG_ON("unimplemented");
+}
+
+hw_irq_controller no_irq_type = {
+    .typename = "none",
+    .startup = irq_startup_none,
+    .shutdown = irq_shutdown_none,
+    .enable = irq_enable_none,
+    .disable = irq_disable_none,
+};
+
+int arch_init_one_irq_desc(struct irq_desc *desc)
+{
+    BUG_ON("unimplemented");
+}
+
+void smp_send_state_dump(unsigned int cpu)
+{
+    BUG_ON("unimplemented");
+}
+
+/* domain.c */
+
+DEFINE_PER_CPU(struct vcpu *, curr_vcpu);
+unsigned long __per_cpu_offset[NR_CPUS];
+
+void context_switch(struct vcpu *prev, struct vcpu *next)
+{
+    BUG_ON("unimplemented");
+}
+
+void continue_running(struct vcpu *same)
+{
+    BUG_ON("unimplemented");
+}
+
+void sync_local_execstate(void)
+{
+    BUG_ON("unimplemented");
+}
+
+void sync_vcpu_execstate(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+void startup_cpu_idle_loop(void)
+{
+    BUG_ON("unimplemented");
+}
+
+void free_domain_struct(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+void dump_pageframe_info(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+void free_vcpu_struct(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+int arch_vcpu_create(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_vcpu_destroy(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+void vcpu_switch_to_aarch64_mode(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
+{
+    BUG_ON("unimplemented");
+}
+
+int arch_domain_create(struct domain *d,
+                       struct xen_domctl_createdomain *config,
+                       unsigned int flags)
+{
+    BUG_ON("unimplemented");
+}
+
+int arch_domain_teardown(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_domain_destroy(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_domain_shutdown(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_domain_pause(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_domain_unpause(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+int arch_domain_soft_reset(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_domain_creation_finished(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
+{
+    BUG_ON("unimplemented");
+}
+
+int arch_initialise_vcpu(struct vcpu *v, XEN_GUEST_HANDLE_PARAM(void) arg)
+{
+    BUG_ON("unimplemented");
+}
+
+int arch_vcpu_reset(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+int domain_relinquish_resources(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_dump_domain_info(struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_dump_vcpu_info(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+void vcpu_mark_events_pending(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+void vcpu_update_evtchn_irq(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+void vcpu_block_unless_event_pending(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+void vcpu_kick(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+struct domain *alloc_domain_struct(void)
+{
+    BUG_ON("unimplemented");
+}
+
+struct vcpu *alloc_vcpu_struct(const struct domain *d)
+{
+    BUG_ON("unimplemented");
+}
+
+unsigned long
+hypercall_create_continuation(unsigned int op, const char *format, ...)
+{
+    BUG_ON("unimplemented");
+}
+
+int __init parse_arch_dom0_param(const char *s, const char *e)
+{
+    BUG_ON("unimplemented");
+}
+
+/* guestcopy.c */
+
+unsigned long raw_copy_to_guest(void *to, const void *from, unsigned int len)
+{
+    BUG_ON("unimplemented");
+}
+
+unsigned long raw_copy_from_guest(void *to, const void __user *from,
+                                  unsigned int len)
+{
+    BUG_ON("unimplemented");
+}
+
+/* sysctl.c */
+
+long arch_do_sysctl(struct xen_sysctl *sysctl,
+                    XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
+{
+    BUG_ON("unimplemented");
+}
+
+void arch_do_physinfo(struct xen_sysctl_physinfo *pi)
+{
+    BUG_ON("unimplemented");
+}
+
+/* p2m.c */
+
+int arch_set_paging_mempool_size(struct domain *d, uint64_t size)
+{
+    BUG_ON("unimplemented");
+}
+
+int unmap_mmio_regions(struct domain *d,
+                       gfn_t start_gfn,
+                       unsigned long nr,
+                       mfn_t mfn)
+{
+    BUG_ON("unimplemented");
+}
+
+int map_mmio_regions(struct domain *d,
+                     gfn_t start_gfn,
+                     unsigned long nr,
+                     mfn_t mfn)
+{
+    BUG_ON("unimplemented");
+}
+
+int set_foreign_p2m_entry(struct domain *d, const struct domain *fd,
+                          unsigned long gfn, mfn_t mfn)
+{
+    BUG_ON("unimplemented");
+}
+
+/* Return the size of the pool, in bytes. */
+int arch_get_paging_mempool_size(struct domain *d, uint64_t *size)
+{
+    BUG_ON("unimplemented");
+}
+
+/* delay.c */
+
+void udelay(unsigned long usecs)
+{
+    BUG_ON("unimplemented");
+}
+
+/* guest_access.h */ 
+
+static inline unsigned long raw_clear_guest(void *to, unsigned int len)
+{
+    BUG_ON("unimplemented");
+}
+
+/* smpboot.c */
+
+int __cpu_up(unsigned int cpu)
+{
+    BUG_ON("unimplemented");
+}
+
+void __cpu_disable(void)
+{
+    BUG_ON("unimplemented");
+}
+
+void __cpu_die(unsigned int cpu)
+{
+    BUG_ON("unimplemented");
+}
+
+/*
+ * The following functions are defined in common/irq.c, but common/irq.c isn't
+ * built for now. These changes will be removed there when common/irq.c is
+ * ready.
+ */
+
+void cf_check irq_actor_none(struct irq_desc *desc)
+{
+    BUG_ON("unimplemented");
+}
+
+unsigned int cf_check irq_startup_none(struct irq_desc *desc)
+{
+    BUG_ON("unimplemented");
+
+    return 0;
+}
diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c
index ccd3593f5a..5415cf8d90 100644
--- a/xen/arch/riscv/traps.c
+++ b/xen/arch/riscv/traps.c
@@ -4,6 +4,10 @@
  *
  * RISC-V Trap handlers
  */
+
+#include <xen/lib.h>
+#include <xen/sched.h>
+
 #include <asm/processor.h>
 #include <asm/traps.h>
 
@@ -11,3 +15,24 @@ void do_trap(struct cpu_user_regs *cpu_regs)
 {
     die();
 }
+
+void vcpu_show_execution_state(struct vcpu *v)
+{
+    BUG_ON("unimplemented");
+}
+
+void show_execution_state(const struct cpu_user_regs *regs)
+{
+    printk("implement show_execution_state(regs)\n");
+}
+
+void arch_hypercall_tasklet_result(struct vcpu *v, long res)
+{
+    BUG_ON("unimplemented");
+}
+
+enum mc_disposition arch_do_multicall_call(struct mc_state *state)
+{
+    BUG_ON("unimplemented");
+    return mc_continue;
+}
-- 
2.43.0



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

* [PATCH v6 19/20] xen/riscv: enable full Xen build
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (17 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 18/20] xen/riscv: add minimal amount of stubs to build full Xen Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  2024-03-15 18:06 ` [PATCH v6 20/20] xen/README: add compiler and binutils versions for RISC-V64 Oleksii Kurochko
  19 siblings, 0 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Alistair Francis, Bob Eshleman, Connor Davis,
	Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Changes in V5-V6:
 - Nothing changed. Only rebase.
---
Changes in V4:
 - drop stubs for irq_actor_none() and irq_actor_none() as common/irq.c is compiled now.
 - drop defintion of max_page in stubs.c as common/page_alloc.c is compiled now.
 - drop printk() related changes in riscv/early_printk.c as common version will be used.
---
Changes in V3:
 - Reviewed-by: Jan Beulich <jbeulich@suse.com>
 - unrealted change dropped in tiny64_defconfig
---
Changes in V2:
 - Nothing changed. Only rebase.
---
 xen/arch/riscv/Makefile       |  16 +++-
 xen/arch/riscv/arch.mk        |   4 -
 xen/arch/riscv/early_printk.c | 168 ----------------------------------
 xen/arch/riscv/stubs.c        |  24 -----
 4 files changed, 15 insertions(+), 197 deletions(-)

diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
index 60afbc0ad9..81b77b13d6 100644
--- a/xen/arch/riscv/Makefile
+++ b/xen/arch/riscv/Makefile
@@ -12,10 +12,24 @@ $(TARGET): $(TARGET)-syms
 	$(OBJCOPY) -O binary -S $< $@
 
 $(TARGET)-syms: $(objtree)/prelink.o $(obj)/xen.lds
-	$(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds -N $< $(build_id_linker) -o $@
+	$(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds -N $< \
+	    $(objtree)/common/symbols-dummy.o -o $(dot-target).0
+	$(NM) -pa --format=sysv $(dot-target).0 \
+		| $(objtree)/tools/symbols $(all_symbols) --sysv --sort \
+		> $(dot-target).0.S
+	$(MAKE) $(build)=$(@D) $(dot-target).0.o
+	$(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds -N $< \
+	    $(dot-target).0.o -o $(dot-target).1
+	$(NM) -pa --format=sysv $(dot-target).1 \
+		| $(objtree)/tools/symbols $(all_symbols) --sysv --sort \
+		> $(dot-target).1.S
+	$(MAKE) $(build)=$(@D) $(dot-target).1.o
+	$(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds -N $< $(build_id_linker) \
+	    $(dot-target).1.o -o $@
 	$(NM) -pa --format=sysv $@ \
 		| $(objtree)/tools/symbols --all-symbols --xensyms --sysv --sort \
 		> $@.map
+	rm -f $(@D)/.$(@F).[0-9]*
 
 $(obj)/xen.lds: $(src)/xen.lds.S FORCE
 	$(call if_changed_dep,cpp_lds_S)
diff --git a/xen/arch/riscv/arch.mk b/xen/arch/riscv/arch.mk
index da6f8c82eb..97ab935903 100644
--- a/xen/arch/riscv/arch.mk
+++ b/xen/arch/riscv/arch.mk
@@ -19,7 +19,3 @@ extensions := $(subst $(space),,$(extensions))
 # -mcmodel=medlow would force Xen into the lower half.
 
 CFLAGS += $(riscv-abi-y) -march=$(riscv-march-y)$(extensions) -mstrict-align -mcmodel=medany
-
-# TODO: Drop override when more of the build is working
-override ALL_OBJS-y = arch/$(SRCARCH)/built_in.o
-override ALL_LIBS-y =
diff --git a/xen/arch/riscv/early_printk.c b/xen/arch/riscv/early_printk.c
index 60742a042d..610c814f54 100644
--- a/xen/arch/riscv/early_printk.c
+++ b/xen/arch/riscv/early_printk.c
@@ -40,171 +40,3 @@ void early_printk(const char *str)
         str++;
     }
 }
-
-/*
- * The following #if 1 ... #endif should be removed after printk
- * and related stuff are ready.
- */
-#if 1
-
-#include <xen/stdarg.h>
-#include <xen/string.h>
-
-/**
- * strlen - Find the length of a string
- * @s: The string to be sized
- */
-size_t (strlen)(const char * s)
-{
-    const char *sc;
-
-    for (sc = s; *sc != '\0'; ++sc)
-        /* nothing */;
-    return sc - s;
-}
-
-/**
- * memcpy - Copy one area of memory to another
- * @dest: Where to copy to
- * @src: Where to copy from
- * @count: The size of the area.
- *
- * You should not use this function to access IO space, use memcpy_toio()
- * or memcpy_fromio() instead.
- */
-void *(memcpy)(void *dest, const void *src, size_t count)
-{
-    char *tmp = (char *) dest, *s = (char *) src;
-
-    while (count--)
-        *tmp++ = *s++;
-
-    return dest;
-}
-
-int vsnprintf(char* str, size_t size, const char* format, va_list args)
-{
-    size_t i = 0; /* Current position in the output string */
-    size_t written = 0; /* Total number of characters written */
-    char* dest = str;
-
-    while ( format[i] != '\0' && written < size - 1 )
-    {
-        if ( format[i] == '%' )
-        {
-            i++;
-
-            if ( format[i] == '\0' )
-                break;
-
-            if ( format[i] == '%' )
-            {
-                if ( written < size - 1 )
-                {
-                    dest[written] = '%';
-                    written++;
-                }
-                i++;
-                continue;
-            }
-
-            /*
-             * Handle format specifiers.
-             * For simplicity, only %s and %d are implemented here.
-             */
-
-            if ( format[i] == 's' )
-            {
-                char* arg = va_arg(args, char*);
-                size_t arglen = strlen(arg);
-
-                size_t remaining = size - written - 1;
-
-                if ( arglen > remaining )
-                    arglen = remaining;
-
-                memcpy(dest + written, arg, arglen);
-
-                written += arglen;
-                i++;
-            }
-            else if ( format[i] == 'd' )
-            {
-                int arg = va_arg(args, int);
-
-                /* Convert the integer to string representation */
-                char numstr[32]; /* Assumes a maximum of 32 digits */
-                int numlen = 0;
-                int num = arg;
-                size_t remaining;
-
-                if ( arg < 0 )
-                {
-                    if ( written < size - 1 )
-                    {
-                        dest[written] = '-';
-                        written++;
-                    }
-
-                    num = -arg;
-                }
-
-                do
-                {
-                    numstr[numlen] = '0' + num % 10;
-                    num = num / 10;
-                    numlen++;
-                } while ( num > 0 );
-
-                /* Reverse the string */
-                for (int j = 0; j < numlen / 2; j++)
-                {
-                    char tmp = numstr[j];
-                    numstr[j] = numstr[numlen - 1 - j];
-                    numstr[numlen - 1 - j] = tmp;
-                }
-
-                remaining = size - written - 1;
-
-                if ( numlen > remaining )
-                    numlen = remaining;
-
-                memcpy(dest + written, numstr, numlen);
-
-                written += numlen;
-                i++;
-            }
-        }
-        else
-        {
-            if ( written < size - 1 )
-            {
-                dest[written] = format[i];
-                written++;
-            }
-            i++;
-        }
-    }
-
-    if ( size > 0 )
-        dest[written] = '\0';
-
-    return written;
-}
-
-void printk(const char *format, ...)
-{
-    static char buf[1024];
-
-    va_list args;
-    va_start(args, format);
-
-    (void)vsnprintf(buf, sizeof(buf), format, args);
-
-    early_printk(buf);
-
-    va_end(args);
-}
-
-#endif
-
diff --git a/xen/arch/riscv/stubs.c b/xen/arch/riscv/stubs.c
index 8285bcffef..bda35fc347 100644
--- a/xen/arch/riscv/stubs.c
+++ b/xen/arch/riscv/stubs.c
@@ -24,12 +24,6 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_mask);
 
 nodemask_t __read_mostly node_online_map = { { [0] = 1UL } };
 
-/*
- * max_page is defined in page_alloc.c which isn't complied for now.
- * definition of max_page will be remove as soon as page_alloc is built.
- */
-unsigned long __read_mostly max_page;
-
 /* time.c */
 
 unsigned long __ro_after_init cpu_khz;  /* CPU clock frequency in kHz. */
@@ -419,21 +413,3 @@ void __cpu_die(unsigned int cpu)
 {
     BUG_ON("unimplemented");
 }
-
-/*
- * The following functions are defined in common/irq.c, but common/irq.c isn't
- * built for now. These changes will be removed there when common/irq.c is
- * ready.
- */
-
-void cf_check irq_actor_none(struct irq_desc *desc)
-{
-    BUG_ON("unimplemented");
-}
-
-unsigned int cf_check irq_startup_none(struct irq_desc *desc)
-{
-    BUG_ON("unimplemented");
-
-    return 0;
-}
-- 
2.43.0



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

* [PATCH v6 20/20] xen/README: add compiler and binutils versions for RISC-V64
  2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
                   ` (18 preceding siblings ...)
  2024-03-15 18:06 ` [PATCH v6 19/20] xen/riscv: enable full Xen build Oleksii Kurochko
@ 2024-03-15 18:06 ` Oleksii Kurochko
  19 siblings, 0 replies; 61+ messages in thread
From: Oleksii Kurochko @ 2024-03-15 18:06 UTC (permalink / raw)
  To: xen-devel
  Cc: Oleksii Kurochko, Andrew Cooper, George Dunlap, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu

This patch doesn't represent a strict lower bound for GCC and
GNU Binutils; rather, these versions are specifically employed by
the Xen RISC-V container and are anticipated to undergo continuous
testing. Older GCC and GNU Binutils would work,
but this is not a guarantee.

While it is feasible to utilize Clang, it's important to note that,
currently, there is no Xen RISC-V CI job in place to verify the
seamless functioning of the build with Clang.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
 Changes in V6:
  - update the message in README.
---
 Changes in V5:
  - update the commit message and README file with additional explanation about GCC and
    GNU Binutils version. Additionally, it was added information about Clang.
---
 Changes in V4:
  - Update version of GCC (12.2) and GNU Binutils (2.39) to the version
    which are in Xen's contrainter for RISC-V
---
 Changes in V3:
  - new patch
---
 README | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/README b/README
index c8a108449e..30da5ff9c0 100644
--- a/README
+++ b/README
@@ -48,6 +48,10 @@ provided by your OS distributor:
       - For ARM 64-bit:
         - GCC 5.1 or later
         - GNU Binutils 2.24 or later
+      - For RISC-V 64-bit:
+        - GCC 12.2 or later
+        - GNU Binutils 2.39 or later
+          Older GCC and GNU Binutils would work, but this is not a guarantee.
     * POSIX compatible awk
     * Development install of zlib (e.g., zlib-dev)
     * Development install of Python 2.7 or later (e.g., python-dev)
-- 
2.43.0



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

* Re: [PATCH v6 02/20] xen/riscv: disable unnecessary configs
  2024-03-15 18:05 ` [PATCH v6 02/20] xen/riscv: disable unnecessary configs Oleksii Kurochko
@ 2024-03-18  7:54   ` Jan Beulich
  2024-03-18 14:42     ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-18  7:54 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Doug Goldstein, Stefano Stabellini, Alistair Francis,
	Bob Eshleman, Connor Davis, xen-devel

On 15.03.2024 19:05, Oleksii Kurochko wrote:
> --- a/xen/arch/riscv/configs/tiny64_defconfig
> +++ b/xen/arch/riscv/configs/tiny64_defconfig
> @@ -7,6 +7,23 @@
>  # CONFIG_GRANT_TABLE is not set
>  # CONFIG_SPECULATIVE_HARDEN_ARRAY is not set
>  # CONFIG_MEM_ACCESS is not set
> +# CONFIG_ARGO is not set
> +# CONFIG_HYPFS_CONFIG is not set

What exactly is wrong with permitting this?

> +# CONFIG_CORE_PARKING is not set

At the example of this: It cannot be enabled by a user (or randconfig),
it needs to be selected by an arch. Which RISC-V doesn't. Hence why
specify (and not really override) the value here? This may apply to
others as well, at the very least ...

> +# CONFIG_DEBUG_TRACE is not set
> +# CONFIG_IOREQ_SERVER is not set
> +# CONFIG_CRASH_DEBUG is not setz
> +# CONFIG_KEXEC is not set
> +# CONFIG_LIVEPATCH is not set
> +# CONFIG_NUMA is not set
> +# CONFIG_PERF_COUNTERS is not set
> +# CONFIG_HAS_PMAP is not set

... anything CONFIG_HAS_*.

In summary - please limit overrides to what is minimally necessary.

Jan

> +# CONFIG_TRACEBUFFER is not set
> +# CONFIG_XENOPROF is not set
> +# CONFIG_COMPAT is not set
> +# CONFIG_COVERAGE is not set
> +# CONFIG_UBSAN is not set
> +# CONFIG_NEEDS_LIBELF is not set
>  
>  CONFIG_RISCV_64=y
>  CONFIG_DEBUG=y



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

* Re: [PATCH v6 02/20] xen/riscv: disable unnecessary configs
  2024-03-18  7:54   ` Jan Beulich
@ 2024-03-18 14:42     ` Oleksii
  0 siblings, 0 replies; 61+ messages in thread
From: Oleksii @ 2024-03-18 14:42 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Doug Goldstein, Stefano Stabellini, Alistair Francis,
	Bob Eshleman, Connor Davis, xen-devel

On Mon, 2024-03-18 at 08:54 +0100, Jan Beulich wrote:
> On 15.03.2024 19:05, Oleksii Kurochko wrote:
> > --- a/xen/arch/riscv/configs/tiny64_defconfig
> > +++ b/xen/arch/riscv/configs/tiny64_defconfig
> > @@ -7,6 +7,23 @@
> >  # CONFIG_GRANT_TABLE is not set
> >  # CONFIG_SPECULATIVE_HARDEN_ARRAY is not set
> >  # CONFIG_MEM_ACCESS is not set
> > +# CONFIG_ARGO is not set
> > +# CONFIG_HYPFS_CONFIG is not set
> 
> What exactly is wrong with permitting this?
Nothing wrong, I just chose the wrong approach about which configs
should be disabled.

Considering your comment below, I'll limit overrides to what is
minimally necessary.

~ Oleksii
> 
> > +# CONFIG_CORE_PARKING is not set
> 
> At the example of this: It cannot be enabled by a user (or
> randconfig),
> it needs to be selected by an arch. Which RISC-V doesn't. Hence why
> specify (and not really override) the value here? This may apply to
> others as well, at the very least ...
> 
> > +# CONFIG_DEBUG_TRACE is not set
> > +# CONFIG_IOREQ_SERVER is not set
> > +# CONFIG_CRASH_DEBUG is not setz
> > +# CONFIG_KEXEC is not set
> > +# CONFIG_LIVEPATCH is not set
> > +# CONFIG_NUMA is not set
> > +# CONFIG_PERF_COUNTERS is not set
> > +# CONFIG_HAS_PMAP is not set
> 
> ... anything CONFIG_HAS_*.
> 
> In summary - please limit overrides to what is minimally necessary.
> 
> Jan
> 
> > +# CONFIG_TRACEBUFFER is not set
> > +# CONFIG_XENOPROF is not set
> > +# CONFIG_COMPAT is not set
> > +# CONFIG_COVERAGE is not set
> > +# CONFIG_UBSAN is not set
> > +# CONFIG_NEEDS_LIBELF is not set
> >  
> >  CONFIG_RISCV_64=y
> >  CONFIG_DEBUG=y
> 



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

* Re: [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler
  2024-03-15 18:05 ` [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler Oleksii Kurochko
@ 2024-03-18 16:58   ` Jan Beulich
  2024-03-20 18:58     ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-18 16:58 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Alistair Francis, Bob Eshleman, Connor Davis, xen-devel

On 15.03.2024 19:05, Oleksii Kurochko wrote:
> Currently, RISC-V requires two extensions: _zbb and _zihintpause.

Do we really require Zbb already?

> This patch introduces a compiler check to check if these extensions
> are supported.
> Additionally, it introduces the riscv/booting.txt file, which contains
> information about the extensions that should be supported by the platform.
> 
> In the future, a feature will be introduced to check whether an extension
> is supported at runtime.
> However, this feature requires functionality for parsing device tree
> source (DTS), which is not yet available.

Can't you query the CPU for its features?

> --- a/xen/arch/riscv/arch.mk
> +++ b/xen/arch/riscv/arch.mk
> @@ -3,16 +3,22 @@
>  
>  $(call cc-options-add,CFLAGS,CC,$(EMBEDDED_EXTRA_CFLAGS))
>  
> -CFLAGS-$(CONFIG_RISCV_64) += -mabi=lp64
> +riscv-abi-$(CONFIG_RISCV_32) := -mabi=ilp32
> +riscv-abi-$(CONFIG_RISCV_64) := -mabi=lp64
>  
>  riscv-march-$(CONFIG_RISCV_ISA_RV64G) := rv64g
>  riscv-march-$(CONFIG_RISCV_ISA_C)       := $(riscv-march-y)c
>  
> +extensions := $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-march-y)_zbb,"",_zbb) \
> +              $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-march-y)_zihintpause,"pause",_zihintpause)

Imo you want another helper macro here, where all one needs to pass in is
the extension name (i.e. zbb and zihintpause as per above). That'll also
help with line length, I hope.

Jan


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

* Re: [PATCH v6 04/20] xen/asm-generic: introduce generic non-atomic test_*bit()
  2024-03-15 18:06 ` [PATCH v6 04/20] xen/asm-generic: introduce generic non-atomic test_*bit() Oleksii Kurochko
@ 2024-03-20 15:30   ` Jan Beulich
  2024-03-21  9:27     ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-20 15:30 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, xen-devel

On 15.03.2024 19:06, Oleksii Kurochko wrote:
> The patch introduces the following generic functions:
> * test_bit
> * generic___test_and_set_bit
> * generic___test_and_clear_bit
> * generic___test_and_change_bit
> 
> Also, the patch introduces the following generics which are
> used by the functions mentioned above:
> * BITOP_BITS_PER_WORD
> * BITOP_MASK
> * BITOP_WORD
> * BITOP_TYPE
> 
> These functions and macros can be useful for architectures
> that don't have corresponding arch-specific instructions.
> 
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>

First of all: How much syncing has there been versus Andrew's plans?
I don't want to end up in the middle of two entirely different
approaches to the same generalization goal.

> --- /dev/null
> +++ b/xen/include/asm-generic/bitops/bitops-bits.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ASM_GENERIC_BITOPS_BITS_H_
> +#define _ASM_GENERIC_BITOPS_BITS_H_
> +
> +#ifndef BITOP_BITS_PER_WORD
> +#define BITOP_BITS_PER_WORD     32
> +#endif
> +
> +#ifndef BITOP_MASK
> +#define BITOP_MASK(nr)          (1U << ((nr) % BITOP_BITS_PER_WORD))
> +#endif
> +
> +#ifndef BITOP_WORD
> +#define BITOP_WORD(nr)          ((nr) / BITOP_BITS_PER_WORD)
> +#endif
> +
> +#ifndef BITOP_TYPE
> +typedef uint32_t bitops_uint_t;
> +#endif

Is it of practical use to permit overriding of one of BITOP_TYPE and
BITOP_BITS_PER_WORD? I think both want tying together.

Is it further of any use to allow overriding of BITOP_{MASK,WORD}?
There's minimal generalization needed to allow an override of
BITOP_TYPE, though:

#define BITOP_MASK(nr)          ((bitop_uint_t)1 << ((nr) % BITOP_BITS_PER_WORD))

Note that I've omitted the 's' from the typedef name - the macros
all having no 'S', imo the type also shouldn't (or the other way
around).

> --- /dev/null
> +++ b/xen/include/asm-generic/bitops/generic-non-atomic.h
> @@ -0,0 +1,89 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * The file is based on Linux ( 6.4.0 ) header:
> + *   include/asm-generic/bitops/generic-non-atomic.h
> + * 
> + * Only functions that can be reused in Xen were left; others were removed.
> + * 
> + * Also, the following changes were done:
> + *  - it was updated the message inside #ifndef ... #endif.
> + *  - __always_inline -> always_inline to be align with definition in
> + *    xen/compiler.h.
> + *  - update function prototypes from
> + *    generic___test_and_*(unsigned long nr nr, volatile unsigned long *addr) to
> + *    generic___test_and_*(unsigned long nr, volatile void *addr) to be

What's the point of having a whopping 3 successive inner underscores?
Which btw ...

> + *    consistent with other related macros/defines.
> + *  - convert identations from tabs to spaces.
> + *  - inside generic__test_and_* use 'bitops_uint_t' instead of 'unsigned long'
> + *    to be generic.

... shrink to just 2 here.

Oh, and there's no generic__test_bit(), but just test_bit() in a separate
header.

> + */
> +
> +#ifndef __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
> +#define __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
> +
> +#include <xen/compiler.h>
> +
> +#include <asm-generic/bitops/bitops-bits.h>
> +
> +#ifndef XEN_BITOPS_H
> +#error only <xen/bitops.h> can be included directly
> +#endif
> +
> +/*
> + * Generic definitions for bit operations, should not be used in regular code
> + * directly.
> + */
> +
> +/**
> + * generic___test_and_set_bit - Set a bit and return its old value
> + * @nr: Bit to set
> + * @addr: Address to count from
> + *
> + * This operation is non-atomic and can be reordered.
> + * If two examples of this operation race, one can appear to succeed
> + * but actually fail.  You must protect multiple accesses with a lock.
> + */
> +static always_inline bool
> +generic___test_and_set_bit(unsigned long nr, volatile void *addr)
> +{
> +    bitops_uint_t mask = BITOP_MASK(nr);
> +    bitops_uint_t *p = ((bitops_uint_t *)addr) + BITOP_WORD(nr);

If you cast away the volatile here, what's the point of having it in
the parameter declaration? Also such a cast doesn't need an outer
pair of parentheses.

> +    bitops_uint_t old = *p;
> +
> +    *p = old | mask;
> +    return (old & mask) != 0;

Minor: The function returning bool, the "!= 0" (and then also the
parentheses) could be omitted.

> --- /dev/null
> +++ b/xen/include/asm-generic/bitops/test-bit.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ASM_GENERIC_BITOPS_TESTBIT_H_
> +#define _ASM_GENERIC_BITOPS_TESTBIT_H_
> +
> +#include <asm-generic/bitops/bitops-bits.h>
> +
> +/**
> + * test_bit - Determine whether a bit is set
> + * @nr: bit number to test
> + * @addr: Address to start counting from
> + */
> +static inline int test_bit(int nr, const volatile void *addr)
> +{
> +    const volatile bitops_uint_t *p = addr;
> +    return 1 & (p[BITOP_WORD(nr)] >> (nr & (BITOP_BITS_PER_WORD - 1)));
> +}

Interestingly you don't lose the volatile here. Overall the way this
is written would likely benefit the other functions too. There's no
cast needed here and thus also not there.

Jan


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

* Re: [PATCH v6 05/20] xen/bitops: implement fls{l}() in common logic
  2024-03-15 18:06 ` [PATCH v6 05/20] xen/bitops: implement fls{l}() in common logic Oleksii Kurochko
@ 2024-03-20 15:39   ` Jan Beulich
  0 siblings, 0 replies; 61+ messages in thread
From: Jan Beulich @ 2024-03-20 15:39 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Shawn Anastasio, Roger Pau Monné,
	xen-devel

On 15.03.2024 19:06, Oleksii Kurochko wrote:
> Return type was left 'int' because of the following compilation error:
> 
> ./include/xen/kernel.h:18:21: error: comparison of distinct pointer types lacks a cast [-Werror]
>        18 |         (void) (&_x == &_y);            \
>           |                     ^~
>     common/page_alloc.c:1843:34: note: in expansion of macro 'min'
>      1843 |         unsigned int inc_order = min(MAX_ORDER, flsl(e - s) - 1);
> 
> generic_fls{l} was used instead of __builtin_clz{l}(x) as if x is 0,
> the result in undefined.
> 
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>

Assuming Andrew's pending change goes in as posted, I'm okay with this to
(as simply following suit). Without that having happened, I can't very
well offer an ack here. Just one nit:

> --- a/xen/include/xen/bitops.h
> +++ b/xen/include/xen/bitops.h
> @@ -69,6 +69,30 @@ static inline int generic_flsl(unsigned long x)
>  
>  #include <asm/bitops.h>
>  
> +static always_inline __pure int fls(unsigned int x)
> +{
> +    if (__builtin_constant_p(x))

Style (missing blanks immediately inside the parentheses), also again ...

> +        return generic_fls(x);
> +
> +#ifndef arch_fls
> +#define arch_fls generic_fls
> +#endif
> +
> +    return arch_fls(x);
> +}
> +
> +static always_inline __pure int flsl(unsigned long x)
> +{
> +    if (__builtin_constant_p(x))

... here.

Jan


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

* Re: [PATCH v6 06/20] xen/bitops: put __ffs() and ffz() into linux compatible header
  2024-03-15 18:06 ` [PATCH v6 06/20] xen/bitops: put __ffs() and ffz() into linux compatible header Oleksii Kurochko
@ 2024-03-20 15:42   ` Jan Beulich
  2024-03-21  9:33     ` Oleksii
  2024-03-29 18:23     ` Oleksii
  0 siblings, 2 replies; 61+ messages in thread
From: Jan Beulich @ 2024-03-20 15:42 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Shawn Anastasio, Rahul Singh, xen-devel

On 15.03.2024 19:06, Oleksii Kurochko wrote:
> --- a/xen/lib/find-next-bit.c
> +++ b/xen/lib/find-next-bit.c
> @@ -9,6 +9,7 @@
>   * 2 of the License, or (at your option) any later version.
>   */
>  #include <xen/bitops.h>
> +#include <xen/linux-compat.h>
>  
>  #include <asm/byteorder.h>

Hmm, no, a library source would better not include this header. Surely
the ffz() can be taken care of locally here?

Jan


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

* Re: [PATCH v6 07/20] xen/riscv: introduce bitops.h
  2024-03-15 18:06 ` [PATCH v6 07/20] xen/riscv: introduce bitops.h Oleksii Kurochko
@ 2024-03-20 16:03   ` Jan Beulich
  2024-03-21 10:07     ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-20 16:03 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 15.03.2024 19:06, Oleksii Kurochko wrote:
> Taken from Linux-6.4.0-rc1
> 
> Xen's bitops.h consists of several Linux's headers:
> * linux/arch/include/asm/bitops.h:
>   * The following function were removed as they aren't used in Xen:
>         * test_and_set_bit_lock
>         * clear_bit_unlock
>         * __clear_bit_unlock
>   * The following functions were renamed in the way how they are
>     used by common code:
>         * __test_and_set_bit
>         * __test_and_clear_bit
>   * The declaration and implementation of the following functios
>     were updated to make Xen build happy:
>         * clear_bit
>         * set_bit
>         * __test_and_clear_bit
>         * __test_and_set_bit
>   * linux/include/asm-generic/bitops/generic-non-atomic.h with the
>     following changes:
>      * Only functions that can be reused in Xen were left;
>        others were removed.
>      * it was updated the message inside #ifndef ... #endif.
>      * __always_inline -> always_inline to be align with definition in
>        xen/compiler.h.
>      * update function prototypes from
>        generic___test_and_*(unsigned long nr nr, volatile unsigned long *addr)
>        to
>        generic___test_and_*(unsigned long nr, volatile void *addr) to be
>        consistent with other related macros/defines.
>      * convert identations from tabs to spaces.
>      * inside generic__test_and_* use 'bitops_uint_t' instead of 'unsigned long'
>         to be generic.

This last middle level bullet point looks stale here here, with that header
now being introduced in a separate patch.

> --- /dev/null
> +++ b/xen/arch/riscv/include/asm/bitops.h
> @@ -0,0 +1,144 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (C) 2012 Regents of the University of California */
> +
> +#ifndef _ASM_RISCV_BITOPS_H
> +#define _ASM_RISCV_BITOPS_H
> +
> +#include <asm/system.h>
> +
> +#define BITOP_BITS_PER_WORD BITS_PER_LONG
> +
> +#define BITOP_TYPE
> +typedef uint64_t bitops_uint_t;
> +
> +#include <asm-generic/bitops/bitops-bits.h>
> +
> +#define __set_bit(n, p)      set_bit(n, p)
> +#define __clear_bit(n, p)    clear_bit(n, p)

If these cam with a TODO, I wouldn't say anything. But without I take it
they're meant to remain that way, at which point I'd like to ask about
the performance aspect: Surely the AMO insns are more expensive than
whatever more basic insns could be used instead? I'd even go as far as
wondering whether

#define __set_bit(n, p)      ((void)__test_and_set_bit(n, p))
#define __clear_bit(n, p)    ((void)__test_and_clear_bit(n, p))

wouldn't be cheaper (the compiler would recognize the unused result
and eliminate its calculation, I'm pretty sure).

> +/* Based on linux/arch/include/asm/bitops.h */
> +
> +#if BITS_PER_LONG == 64
> +#define __AMO(op)   "amo" #op ".d"
> +#elif BITS_PER_LONG == 32
> +#define __AMO(op)   "amo" #op ".w"

This isn't in line with bitops_uint_t above. With BITOP_BITS_PER_WORD 
also expanding to BITS_PER_LONG, I think you mean to use unsigned long
there. Or else you could move stuff into the conditional here (or
really move the conditional here further up).

However, if you look at Arm64 and x86 code, you will notice that they
avoid 64-bit operations here. I'm afraid I can't easily tell whether
the reason(s) for this have meanwhile disappeared; I fear some of that
is still around.

> +#else
> +#error "Unexpected BITS_PER_LONG"
> +#endif
> +
> +#define test_and_op_bit_ord(op, mod, nr, addr, ord)     \
> +({                                                      \
> +    unsigned long res, mask;                            \
> +    mask = BITOP_MASK(nr);                              \
> +    __asm__ __volatile__ (                              \
> +        __AMO(op) #ord " %0, %2, %1"                    \
> +        : "=r" (res), "+A" (addr[BITOP_WORD(nr)])       \
> +        : "r" (mod(mask))                               \
> +        : "memory");                                    \
> +    ((res & mask) != 0);                                \
> +})
> +
> +#define __op_bit_ord(op, mod, nr, addr, ord)    \
> +    __asm__ __volatile__ (                      \
> +        __AMO(op) #ord " zero, %1, %0"          \
> +        : "+A" (addr[BITOP_WORD(nr)])           \
> +        : "r" (mod(BITOP_MASK(nr)))             \
> +        : "memory");
> +
> +#define test_and_op_bit(op, mod, nr, addr)    \
> +    test_and_op_bit_ord(op, mod, nr, addr, .aqrl)
> +#define __op_bit(op, mod, nr, addr) \
> +    __op_bit_ord(op, mod, nr, addr, )

Why are double underscores left on the non-test_and_ macros? Even
without name space considerations that looks odd here, when talk
is of the atomic forms of the operations, which by convention have
no (double) underscore at their front.

> --- a/xen/arch/riscv/include/asm/config.h
> +++ b/xen/arch/riscv/include/asm/config.h
> @@ -113,6 +113,8 @@
>  # error "Unsupported RISCV variant"
>  #endif
>  
> +#define BITS_PER_BYTE 8
> +
>  #define BYTES_PER_LONG (1 << LONG_BYTEORDER)
>  #define BITS_PER_LONG  (BYTES_PER_LONG << 3)
>  #define POINTER_ALIGN  BYTES_PER_LONG

How's this addition related to the change at hand?

Jan


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

* Re: [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler
  2024-03-18 16:58   ` Jan Beulich
@ 2024-03-20 18:58     ` Oleksii
  2024-03-20 19:44       ` Conor Dooley
  0 siblings, 1 reply; 61+ messages in thread
From: Oleksii @ 2024-03-20 18:58 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Alistair Francis, Bob Eshleman, Connor Davis, xen-devel

On Mon, 2024-03-18 at 17:58 +0100, Jan Beulich wrote:
> On 15.03.2024 19:05, Oleksii Kurochko wrote:
> > Currently, RISC-V requires two extensions: _zbb and _zihintpause.
> 
> Do we really require Zbb already?
After an introduction of Andrew C. patches [1] it is requited for
__builtin_ffs{l}

[1]
https://lore.kernel.org/xen-devel/20240313172716.2325427-1-andrew.cooper3@citrix.com/T/#t
> 
> > This patch introduces a compiler check to check if these extensions
> > are supported.
> > Additionally, it introduces the riscv/booting.txt file, which
> > contains
> > information about the extensions that should be supported by the
> > platform.
> > 
> > In the future, a feature will be introduced to check whether an
> > extension
> > is supported at runtime.
> > However, this feature requires functionality for parsing device
> > tree
> > source (DTS), which is not yet available.
> 
> Can't you query the CPU for its features?
I couldn't find such reg ( or SBI call ) in the spec.

SBI call sbi_probe_extension() exists, but it doesn't check for every
possible extension. As far as I understand it checks only for that one
which are present in SBI spec.

The most closest thing I see how to check that without dts is how it is
done in OpenSBI:
#define csr_read_allowed(csr_num, trap)				\
	({							\
	register ulong tinfo asm("a3") = (ulong)trap;		\
	register ulong ttmp asm("a4");				\
	register ulong mtvec = sbi_hart_expected_trap_addr();	\
	register ulong ret =
0;					\
	((struct sbi_trap_info *)(trap))->cause = 0;		\
	asm volatile(						\
		"add %[ttmp], %[tinfo],
zero\n"			\
		"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n"\
		"csrr %[ret],
%[csr]\n"				\
		"csrw " STR(CSR_MTVEC) ", %[mtvec]"		\
	    : [mtvec] "+&r"(mtvec), [tinfo] "+&r"(tinfo),	\
	      [ttmp] "+&r"(ttmp), [ret] "=&r" (ret)		\
	    : [csr] "i" (csr_num)				\
	    : "memory");					\
	ret;							\
	})							\
...
	/* Detect if hart supports stimecmp CSR(Sstc extension) */
	if (hfeatures->priv_version >= SBI_HART_PRIV_VER_1_12) {
		csr_read_allowed(CSR_STIMECMP, (unsigned long)&trap);
		if (!trap.cause)
			__sbi_hart_update_extension(hfeatures,
					SBI_HART_EXT_SSTC, true);
	}

~ Oleksii

> 
> > --- a/xen/arch/riscv/arch.mk
> > +++ b/xen/arch/riscv/arch.mk
> > @@ -3,16 +3,22 @@
> >  
> >  $(call cc-options-add,CFLAGS,CC,$(EMBEDDED_EXTRA_CFLAGS))
> >  
> > -CFLAGS-$(CONFIG_RISCV_64) += -mabi=lp64
> > +riscv-abi-$(CONFIG_RISCV_32) := -mabi=ilp32
> > +riscv-abi-$(CONFIG_RISCV_64) := -mabi=lp64
> >  
> >  riscv-march-$(CONFIG_RISCV_ISA_RV64G) := rv64g
> >  riscv-march-$(CONFIG_RISCV_ISA_C)       := $(riscv-march-y)c
> >  
> > +extensions := $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-
> > march-y)_zbb,"",_zbb) \
> > +              $(call as-insn,$(CC) $(riscv-abi-y) -march=$(riscv-
> > march-y)_zihintpause,"pause",_zihintpause)
> 
> Imo you want another helper macro here, where all one needs to pass
> in is
> the extension name (i.e. zbb and zihintpause as per above). That'll
> also
> help with line length, I hope.
> 
> Jan



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

* Re: [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler
  2024-03-20 18:58     ` Oleksii
@ 2024-03-20 19:44       ` Conor Dooley
  2024-03-21  8:31         ` Jan Beulich
  2024-03-21  9:07         ` Oleksii
  0 siblings, 2 replies; 61+ messages in thread
From: Conor Dooley @ 2024-03-20 19:44 UTC (permalink / raw)
  To: Oleksii
  Cc: Jan Beulich, Andrew Cooper, George Dunlap, Julien Grall,
	Stefano Stabellini, Wei Liu, Alistair Francis, Bob Eshleman,
	Connor Davis, xen-devel

[-- Attachment #1: Type: text/plain, Size: 4989 bytes --]

On Wed, Mar 20, 2024 at 07:58:05PM +0100, Oleksii wrote:
> On Mon, 2024-03-18 at 17:58 +0100, Jan Beulich wrote:
> > On 15.03.2024 19:05, Oleksii Kurochko wrote:
> > > Currently, RISC-V requires two extensions: _zbb and _zihintpause.
> > 
> > Do we really require Zbb already?
> After an introduction of Andrew C. patches [1] it is requited for
> __builtin_ffs{l}
> 
> [1]
> https://lore.kernel.org/xen-devel/20240313172716.2325427-1-andrew.cooper3@citrix.com/T/#t
> > 
> > > This patch introduces a compiler check to check if these extensions
> > > are supported.
> > > Additionally, it introduces the riscv/booting.txt file, which
> > > contains
> > > information about the extensions that should be supported by the
> > > platform.
> > > 
> > > In the future, a feature will be introduced to check whether an
> > > extension
> > > is supported at runtime.
> > > However, this feature requires functionality for parsing device
> > > tree
> > > source (DTS), which is not yet available.
> > 
> > Can't you query the CPU for its features?
> I couldn't find such reg ( or SBI call ) in the spec.

There isn't.

> SBI call sbi_probe_extension() exists, but it doesn't check for every
> possible extension. As far as I understand it checks only for that one
> which are present in SBI spec.

Yeah, it only checks for SBI extensions, not ISA extensions.

> The most closest thing I see how to check that without dts is how it is
> done in OpenSBI:

IIRC this only "works" because the OpenSBI devs assume that there are no
non-normative behaviours and all CSRs have their ~God~ RVI defined
meanings. Reading a CSR to see if it traps is not behaviour you can really
rely on unless the platform claims to support Sstrict - but Sstrict you'd
have to detect from the DT so chicken and egg for you! It's one of these
new "extensions" from the profiles spec, so it doesn't even have support
in Linux's dt-bindings yet. Up to Xen devs if you guys want to make the
same assumptions as OpenSBI. Linux doesn't and when we discussed this
not too long ago on the U-Boot ML in the context of the rng CSR it was
also decided not to do make the assumption there either.

Personally I wonder if you can just apply the same policy here as you
did with Zbb in the other thread and assume that something with H will
have Zihintpause and leave implementing a "fake" pause as an exercise
for someone that introduces such a system?
If Jess is correct, and I do remember testing this, it's actually
"always" safe to call the pause instruction on CPUs where the extension
is not supported as it uses an encoding of fence that effectively makes
it a into a nop:
https://lore.kernel.org/linux-riscv/2E96A836-764D-4D07-AB79-3861B9CC2B1F@jrtc27.com/
At worst, that'd make cpu_relax() a nop if someone didn't meet that
requirement.

FWIW, Linux's cpu_relax() on RISC-V looks like:
	static inline void cpu_relax(void)
	{
	#ifdef __riscv_muldiv
		int dummy;
		/* In lieu of a halt instruction, induce a long-latency stall. */
		__asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
	#endif
	
	#ifdef CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE
		/*
		 * Reduce instruction retirement.
		 * This assumes the PC changes.
		 */
		__asm__ __volatile__ ("pause");
	#else
		/* Encoding of the pause instruction */
		__asm__ __volatile__ (".4byte 0x100000F");
	#endif
		barrier();
	}

I figure having div is part of your base requirements, so maybe you can
just do something similar in the !zihintpause case if making that
extension a requirement is problematic? 
Doing that invalid div used to be conditional, but cpu_relax() is in the
vdso so the static branch it used to be gated with got removed and its
now unconditional. Probably that's not a constraint on Xen's cpu_relax()?

Oh ye, and we do the .4byte crap so that toolchain support wasn't needed
for Zihintpause given we are using it in exactly one place.

Cheers,
Conor.

> #define csr_read_allowed(csr_num, trap)				\
> 	({							\
> 	register ulong tinfo asm("a3") = (ulong)trap;		\
> 	register ulong ttmp asm("a4");				\
> 	register ulong mtvec = sbi_hart_expected_trap_addr();	\
> 	register ulong ret =
> 0;					\
> 	((struct sbi_trap_info *)(trap))->cause = 0;		\
> 	asm volatile(						\
> 		"add %[ttmp], %[tinfo],
> zero\n"			\
> 		"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n"\
> 		"csrr %[ret],
> %[csr]\n"				\
> 		"csrw " STR(CSR_MTVEC) ", %[mtvec]"		\
> 	    : [mtvec] "+&r"(mtvec), [tinfo] "+&r"(tinfo),	\
> 	      [ttmp] "+&r"(ttmp), [ret] "=&r" (ret)		\
> 	    : [csr] "i" (csr_num)				\
> 	    : "memory");					\
> 	ret;							\
> 	})							\
> ...
> 	/* Detect if hart supports stimecmp CSR(Sstc extension) */
> 	if (hfeatures->priv_version >= SBI_HART_PRIV_VER_1_12) {
> 		csr_read_allowed(CSR_STIMECMP, (unsigned long)&trap);
> 		if (!trap.cause)
> 			__sbi_hart_update_extension(hfeatures,
> 					SBI_HART_EXT_SSTC, true);
> 	}

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler
  2024-03-20 19:44       ` Conor Dooley
@ 2024-03-21  8:31         ` Jan Beulich
  2024-03-21  9:22           ` Conor Dooley
  2024-03-21  9:07         ` Oleksii
  1 sibling, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-21  8:31 UTC (permalink / raw)
  To: Conor Dooley
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Alistair Francis, Bob Eshleman, Connor Davis, xen-devel,
	Oleksii

On 20.03.2024 20:44, Conor Dooley wrote:
> On Wed, Mar 20, 2024 at 07:58:05PM +0100, Oleksii wrote:
>> On Mon, 2024-03-18 at 17:58 +0100, Jan Beulich wrote:
>>> On 15.03.2024 19:05, Oleksii Kurochko wrote:
>>>> Currently, RISC-V requires two extensions: _zbb and _zihintpause.
>>>
>>> Do we really require Zbb already?
>> After an introduction of Andrew C. patches [1] it is requited for
>> __builtin_ffs{l}
>>
>> [1]
>> https://lore.kernel.org/xen-devel/20240313172716.2325427-1-andrew.cooper3@citrix.com/T/#t
>>>
>>>> This patch introduces a compiler check to check if these extensions
>>>> are supported.
>>>> Additionally, it introduces the riscv/booting.txt file, which
>>>> contains
>>>> information about the extensions that should be supported by the
>>>> platform.
>>>>
>>>> In the future, a feature will be introduced to check whether an
>>>> extension
>>>> is supported at runtime.
>>>> However, this feature requires functionality for parsing device
>>>> tree
>>>> source (DTS), which is not yet available.
>>>
>>> Can't you query the CPU for its features?
>> I couldn't find such reg ( or SBI call ) in the spec.
> 
> There isn't.
> 
>> SBI call sbi_probe_extension() exists, but it doesn't check for every
>> possible extension. As far as I understand it checks only for that one
>> which are present in SBI spec.
> 
> Yeah, it only checks for SBI extensions, not ISA extensions.

And there was never a consideration to add, at the architecture level,
some straightforward way for all layers of software to be able to
easily detect availability of extensions? I find the lack thereof
pretty surprising ...

Jan


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

* Re: [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler
  2024-03-20 19:44       ` Conor Dooley
  2024-03-21  8:31         ` Jan Beulich
@ 2024-03-21  9:07         ` Oleksii
  1 sibling, 0 replies; 61+ messages in thread
From: Oleksii @ 2024-03-21  9:07 UTC (permalink / raw)
  To: Conor Dooley
  Cc: Jan Beulich, Andrew Cooper, George Dunlap, Julien Grall,
	Stefano Stabellini, Wei Liu, Alistair Francis, Bob Eshleman,
	Connor Davis, xen-devel

On Wed, 2024-03-20 at 19:44 +0000, Conor Dooley wrote:
> IIRC this only "works" because the OpenSBI devs assume that there are
> no
> non-normative behaviours and all CSRs have their ~God~ RVI defined
> meanings. Reading a CSR to see if it traps is not behaviour you can
> really
> rely on unless the platform claims to support Sstrict - but Sstrict
> you'd
> have to detect from the DT so chicken and egg for you! It's one of
> these
> new "extensions" from the profiles spec, so it doesn't even have
> support
> in Linux's dt-bindings yet. Up to Xen devs if you guys want to make
> the
> same assumptions as OpenSBI. Linux doesn't and when we discussed this
> not too long ago on the U-Boot ML in the context of the rng CSR it
> was
> also decided not to do make the assumption there either.
> 
> Personally I wonder if you can just apply the same policy here as you
> did with Zbb in the other thread and assume that something with H
> will
> have Zihintpause and leave implementing a "fake" pause as an exercise
> for someone that introduces such a system?

If i understand you correctly, then it is done in this way now. Only
build time check is done, but it would be nice also have some runtime
check, and for now, for runtime the "check" is only exists in
booting.txt where it mentioned that Xen expects from CPU to support
some extenstions; otherwise "please implement the following functions".

Anyway, at the moment, the best one runtime check which we can provide
is detect availability of extensions from DT and what I mentioned in
commit message.

~ Oleksii


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

* Re: [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler
  2024-03-21  8:31         ` Jan Beulich
@ 2024-03-21  9:22           ` Conor Dooley
  0 siblings, 0 replies; 61+ messages in thread
From: Conor Dooley @ 2024-03-21  9:22 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Alistair Francis, Bob Eshleman, Connor Davis, xen-devel,
	Oleksii

[-- Attachment #1: Type: text/plain, Size: 2661 bytes --]

On Thu, Mar 21, 2024 at 09:31:59AM +0100, Jan Beulich wrote:
> On 20.03.2024 20:44, Conor Dooley wrote:
> > On Wed, Mar 20, 2024 at 07:58:05PM +0100, Oleksii wrote:
> >> On Mon, 2024-03-18 at 17:58 +0100, Jan Beulich wrote:
> >>> On 15.03.2024 19:05, Oleksii Kurochko wrote:
> >>>> Currently, RISC-V requires two extensions: _zbb and _zihintpause.
> >>>
> >>> Do we really require Zbb already?
> >> After an introduction of Andrew C. patches [1] it is requited for
> >> __builtin_ffs{l}
> >>
> >> [1]
> >> https://lore.kernel.org/xen-devel/20240313172716.2325427-1-andrew.cooper3@citrix.com/T/#t
> >>>
> >>>> This patch introduces a compiler check to check if these extensions
> >>>> are supported.
> >>>> Additionally, it introduces the riscv/booting.txt file, which
> >>>> contains
> >>>> information about the extensions that should be supported by the
> >>>> platform.
> >>>>
> >>>> In the future, a feature will be introduced to check whether an
> >>>> extension
> >>>> is supported at runtime.
> >>>> However, this feature requires functionality for parsing device
> >>>> tree
> >>>> source (DTS), which is not yet available.
> >>>
> >>> Can't you query the CPU for its features?
> >> I couldn't find such reg ( or SBI call ) in the spec.
> > 
> > There isn't.
> > 
> >> SBI call sbi_probe_extension() exists, but it doesn't check for every
> >> possible extension. As far as I understand it checks only for that one
> >> which are present in SBI spec.
> > 
> > Yeah, it only checks for SBI extensions, not ISA extensions.
> 
> And there was never a consideration to add, at the architecture level,
> some straightforward way for all layers of software to be able to
> easily detect availability of extensions? I find the lack thereof
> pretty surprising ...

No, there sorta is. There's a "configuration structure" spec in the
works, but the (public?) documentation for it is very nascent:
https://github.com/riscv/configuration-structure/

It uses (what I seem to recall is an m-mode) CSR to give the address
of an ASN.1 structure in memory which is intended to encode a whole
raft of information. The CSR itself might be M-Mode, but that doesn't
prevent accessing the data itself at any layer in the stack. The last
time I read it I got the impression it was supposed to be usable for
describing an entire system (including things like i2c or spi
controllers). I don't think it ever explicitly says that in the spec,
but there's a note (IIRC) that mentions being unsuitable for describing
devices on dynamic buses like PCI, so that kinda implies anything else
is fair game.

Hope that helps?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v6 04/20] xen/asm-generic: introduce generic non-atomic test_*bit()
  2024-03-20 15:30   ` Jan Beulich
@ 2024-03-21  9:27     ` Oleksii
  0 siblings, 0 replies; 61+ messages in thread
From: Oleksii @ 2024-03-21  9:27 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, xen-devel

On Wed, 2024-03-20 at 16:30 +0100, Jan Beulich wrote:
> On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > The patch introduces the following generic functions:
> > * test_bit
> > * generic___test_and_set_bit
> > * generic___test_and_clear_bit
> > * generic___test_and_change_bit
> > 
> > Also, the patch introduces the following generics which are
> > used by the functions mentioned above:
> > * BITOP_BITS_PER_WORD
> > * BITOP_MASK
> > * BITOP_WORD
> > * BITOP_TYPE
> > 
> > These functions and macros can be useful for architectures
> > that don't have corresponding arch-specific instructions.
> > 
> > Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
> 
> First of all: How much syncing has there been versus Andrew's plans?
> I don't want to end up in the middle of two entirely different
> approaches to the same generalization goal.
We don't have synced about bit operations mentioned in this patch, so I
decided to follow an approach I have for them. But if Andrew's approach
is better, or it would be better to follow one approach instead of
introducing two approaches, I will be happy to rework this patch.

Andrew, what do you think about this bit ops?

> 
> > --- /dev/null
> > +++ b/xen/include/asm-generic/bitops/bitops-bits.h
> > @@ -0,0 +1,21 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef _ASM_GENERIC_BITOPS_BITS_H_
> > +#define _ASM_GENERIC_BITOPS_BITS_H_
> > +
> > +#ifndef BITOP_BITS_PER_WORD
> > +#define BITOP_BITS_PER_WORD     32
> > +#endif
> > +
> > +#ifndef BITOP_MASK
> > +#define BITOP_MASK(nr)          (1U << ((nr) %
> > BITOP_BITS_PER_WORD))
> > +#endif
> > +
> > +#ifndef BITOP_WORD
> > +#define BITOP_WORD(nr)          ((nr) / BITOP_BITS_PER_WORD)
> > +#endif
> > +
> > +#ifndef BITOP_TYPE
> > +typedef uint32_t bitops_uint_t;
> > +#endif
> 
> Is it of practical use to permit overriding of one of BITOP_TYPE and
> BITOP_BITS_PER_WORD? I think both want tying together.
> 
> Is it further of any use to allow overriding of BITOP_{MASK,WORD}?
> There's minimal generalization needed to allow an override of
> BITOP_TYPE, though:
> 
> #define BITOP_MASK(nr)          ((bitop_uint_t)1 << ((nr) %
> BITOP_BITS_PER_WORD))
> 
> Note that I've omitted the 's' from the typedef name - the macros
> all having no 'S', imo the type also shouldn't (or the other way
> around).
If to generalize BITOP_MASK in way you suggest, then there is no need
to allow overriding of BITOP_{MASK,WORD}. I'll update this part.

> 
> > --- /dev/null
> > +++ b/xen/include/asm-generic/bitops/generic-non-atomic.h
> > @@ -0,0 +1,89 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * The file is based on Linux ( 6.4.0 ) header:
> > + *   include/asm-generic/bitops/generic-non-atomic.h
> > + * 
> > + * Only functions that can be reused in Xen were left; others were
> > removed.
> > + * 
> > + * Also, the following changes were done:
> > + *  - it was updated the message inside #ifndef ... #endif.
> > + *  - __always_inline -> always_inline to be align with definition
> > in
> > + *    xen/compiler.h.
> > + *  - update function prototypes from
> > + *    generic___test_and_*(unsigned long nr nr, volatile unsigned
> > long *addr) to
> > + *    generic___test_and_*(unsigned long nr, volatile void *addr)
> > to be
> 
> What's the point of having a whopping 3 successive inner underscores?
> Which btw ...
> 
> > + *    consistent with other related macros/defines.
> > + *  - convert identations from tabs to spaces.
> > + *  - inside generic__test_and_* use 'bitops_uint_t' instead of
> > 'unsigned long'
> > + *    to be generic.
> 
> ... shrink to just 2 here.
> 
> Oh, and there's no generic__test_bit(), but just test_bit() in a
> separate
> header.
I just wanted to show that it is a generic version of __test_and_*
operations. If there is no sense in that, I am okay to update function
names.

~ Oleksii
> 
> > + */
> > +
> > +#ifndef __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
> > +#define __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
> > +
> > +#include <xen/compiler.h>
> > +
> > +#include <asm-generic/bitops/bitops-bits.h>
> > +
> > +#ifndef XEN_BITOPS_H
> > +#error only <xen/bitops.h> can be included directly
> > +#endif
> > +
> > +/*
> > + * Generic definitions for bit operations, should not be used in
> > regular code
> > + * directly.
> > + */
> > +
> > +/**
> > + * generic___test_and_set_bit - Set a bit and return its old value
> > + * @nr: Bit to set
> > + * @addr: Address to count from
> > + *
> > + * This operation is non-atomic and can be reordered.
> > + * If two examples of this operation race, one can appear to
> > succeed
> > + * but actually fail.  You must protect multiple accesses with a
> > lock.
> > + */
> > +static always_inline bool
> > +generic___test_and_set_bit(unsigned long nr, volatile void *addr)
> > +{
> > +    bitops_uint_t mask = BITOP_MASK(nr);
> > +    bitops_uint_t *p = ((bitops_uint_t *)addr) + BITOP_WORD(nr);
> 
> If you cast away the volatile here, what's the point of having it in
> the parameter declaration? Also such a cast doesn't need an outer
> pair of parentheses.
> 
> > +    bitops_uint_t old = *p;
> > +
> > +    *p = old | mask;
> > +    return (old & mask) != 0;
> 
> Minor: The function returning bool, the "!= 0" (and then also the
> parentheses) could be omitted.
> 
> > --- /dev/null
> > +++ b/xen/include/asm-generic/bitops/test-bit.h
> > @@ -0,0 +1,18 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef _ASM_GENERIC_BITOPS_TESTBIT_H_
> > +#define _ASM_GENERIC_BITOPS_TESTBIT_H_
> > +
> > +#include <asm-generic/bitops/bitops-bits.h>
> > +
> > +/**
> > + * test_bit - Determine whether a bit is set
> > + * @nr: bit number to test
> > + * @addr: Address to start counting from
> > + */
> > +static inline int test_bit(int nr, const volatile void *addr)
> > +{
> > +    const volatile bitops_uint_t *p = addr;
> > +    return 1 & (p[BITOP_WORD(nr)] >> (nr & (BITOP_BITS_PER_WORD -
> > 1)));
> > +}
> 
> Interestingly you don't lose the volatile here. Overall the way this
> is written would likely benefit the other functions too. There's no
> cast needed here and thus also not there.
> 
> Jan



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

* Re: [PATCH v6 06/20] xen/bitops: put __ffs() and ffz() into linux compatible header
  2024-03-20 15:42   ` Jan Beulich
@ 2024-03-21  9:33     ` Oleksii
  2024-03-29 18:23     ` Oleksii
  1 sibling, 0 replies; 61+ messages in thread
From: Oleksii @ 2024-03-21  9:33 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Shawn Anastasio, Rahul Singh, xen-devel

On Wed, 2024-03-20 at 16:42 +0100, Jan Beulich wrote:
> On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > --- a/xen/lib/find-next-bit.c
> > +++ b/xen/lib/find-next-bit.c
> > @@ -9,6 +9,7 @@
> >   * 2 of the License, or (at your option) any later version.
> >   */
> >  #include <xen/bitops.h>
> > +#include <xen/linux-compat.h>
> >  
> >  #include <asm/byteorder.h>
> 
> Hmm, no, a library source would better not include this header.
> Surely
> the ffz() can be taken care of locally here?
Considering that ffz() is only used here, then it makes sense to drop
ffz() from xen/linux-compat.h> and defines it here as:
#define ffz(x) ffsl(~(x)) - 1

~ Oleksii


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

* Re: [PATCH v6 07/20] xen/riscv: introduce bitops.h
  2024-03-20 16:03   ` Jan Beulich
@ 2024-03-21 10:07     ` Oleksii
  2024-03-21 10:28       ` Jan Beulich
  0 siblings, 1 reply; 61+ messages in thread
From: Oleksii @ 2024-03-21 10:07 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Wed, 2024-03-20 at 17:03 +0100, Jan Beulich wrote:
> On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > Taken from Linux-6.4.0-rc1
> > 
> > Xen's bitops.h consists of several Linux's headers:
> > * linux/arch/include/asm/bitops.h:
> >   * The following function were removed as they aren't used in Xen:
> >         * test_and_set_bit_lock
> >         * clear_bit_unlock
> >         * __clear_bit_unlock
> >   * The following functions were renamed in the way how they are
> >     used by common code:
> >         * __test_and_set_bit
> >         * __test_and_clear_bit
> >   * The declaration and implementation of the following functios
> >     were updated to make Xen build happy:
> >         * clear_bit
> >         * set_bit
> >         * __test_and_clear_bit
> >         * __test_and_set_bit
> >   * linux/include/asm-generic/bitops/generic-non-atomic.h with the
> >     following changes:
> >      * Only functions that can be reused in Xen were left;
> >        others were removed.
> >      * it was updated the message inside #ifndef ... #endif.
> >      * __always_inline -> always_inline to be align with definition
> > in
> >        xen/compiler.h.
> >      * update function prototypes from
> >        generic___test_and_*(unsigned long nr nr, volatile unsigned
> > long *addr)
> >        to
> >        generic___test_and_*(unsigned long nr, volatile void *addr)
> > to be
> >        consistent with other related macros/defines.
> >      * convert identations from tabs to spaces.
> >      * inside generic__test_and_* use 'bitops_uint_t' instead of
> > 'unsigned long'
> >         to be generic.
> 
> This last middle level bullet point looks stale here here, with that
> header
> now being introduced in a separate patch.
> 
> > --- /dev/null
> > +++ b/xen/arch/riscv/include/asm/bitops.h
> > @@ -0,0 +1,144 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/* Copyright (C) 2012 Regents of the University of California */
> > +
> > +#ifndef _ASM_RISCV_BITOPS_H
> > +#define _ASM_RISCV_BITOPS_H
> > +
> > +#include <asm/system.h>
> > +
> > +#define BITOP_BITS_PER_WORD BITS_PER_LONG
> > +
> > +#define BITOP_TYPE
> > +typedef uint64_t bitops_uint_t;
> > +
> > +#include <asm-generic/bitops/bitops-bits.h>
> > +
> > +#define __set_bit(n, p)      set_bit(n, p)
> > +#define __clear_bit(n, p)    clear_bit(n, p)
> 
> If these cam with a TODO, I wouldn't say anything. But without I take
> it
> they're meant to remain that way, at which point I'd like to ask
> about
> the performance aspect: Surely the AMO insns are more expensive than
> whatever more basic insns could be used instead? I'd even go as far
> as
> wondering whether
> 
> #define __set_bit(n, p)      ((void)__test_and_set_bit(n, p))
> #define __clear_bit(n, p)    ((void)__test_and_clear_bit(n, p))
> 
> wouldn't be cheaper (the compiler would recognize the unused result
> and eliminate its calculation, I'm pretty sure).
It was implemented using atomic ops because of Arm:
/*
 * Non-atomic bit manipulation.
 *
 * Implemented using atomics to be interrupt safe. Could alternatively
 * implement with local interrupt masking.
 */
#define __set_bit(n,p)            set_bit(n,p)
#define __clear_bit(n,p)          clear_bit(n,p)

I though that the same comment is true for x86, but after your comment
I checked x86 implementation, I realized that x86 uses non-atomic
operations.

In this case, it seems to me there is a sense to use non-atomic for
RISC-V too.

> > +/* Based on linux/arch/include/asm/bitops.h */
> > +
> > +#if BITS_PER_LONG == 64
> > +#define __AMO(op)   "amo" #op ".d"
> > +#elif BITS_PER_LONG == 32
> > +#define __AMO(op)   "amo" #op ".w"
> 
> This isn't in line with bitops_uint_t above. With BITOP_BITS_PER_WORD
> also expanding to BITS_PER_LONG, I think you mean to use unsigned
> long
> there. Or else you could move stuff into the conditional here (or
> really move the conditional here further up).
> 
> However, if you look at Arm64 and x86 code, you will notice that they
> avoid 64-bit operations here. I'm afraid I can't easily tell whether
> the reason(s) for this have meanwhile disappeared; I fear some of
> that
> is still around.
> 
> > +#else
> > +#error "Unexpected BITS_PER_LONG"
> > +#endif
> > +
> > +#define test_and_op_bit_ord(op, mod, nr, addr, ord)     \
> > +({                                                      \
> > +    unsigned long res, mask;                            \
> > +    mask = BITOP_MASK(nr);                              \
> > +    __asm__ __volatile__ (                              \
> > +        __AMO(op) #ord " %0, %2, %1"                    \
> > +        : "=r" (res), "+A" (addr[BITOP_WORD(nr)])       \
> > +        : "r" (mod(mask))                               \
> > +        : "memory");                                    \
> > +    ((res & mask) != 0);                                \
> > +})
> > +
> > +#define __op_bit_ord(op, mod, nr, addr, ord)    \
> > +    __asm__ __volatile__ (                      \
> > +        __AMO(op) #ord " zero, %1, %0"          \
> > +        : "+A" (addr[BITOP_WORD(nr)])           \
> > +        : "r" (mod(BITOP_MASK(nr)))             \
> > +        : "memory");
> > +
> > +#define test_and_op_bit(op, mod, nr, addr)    \
> > +    test_and_op_bit_ord(op, mod, nr, addr, .aqrl)
> > +#define __op_bit(op, mod, nr, addr) \
> > +    __op_bit_ord(op, mod, nr, addr, )
> 
> Why are double underscores left on the non-test_and_ macros? Even
> without name space considerations that looks odd here, when talk
> is of the atomic forms of the operations, which by convention have
> no (double) underscore at their front.
Missed to update after Linux kernel. I'll take that into account.

> 
> > --- a/xen/arch/riscv/include/asm/config.h
> > +++ b/xen/arch/riscv/include/asm/config.h
> > @@ -113,6 +113,8 @@
> >  # error "Unsupported RISCV variant"
> >  #endif
> >  
> > +#define BITS_PER_BYTE 8
> > +
> >  #define BYTES_PER_LONG (1 << LONG_BYTEORDER)
> >  #define BITS_PER_LONG  (BYTES_PER_LONG << 3)
> >  #define POINTER_ALIGN  BYTES_PER_LONG
> 
> How's this addition related to the change at hand?
It should be a part of cmpxchg.h patch. Thanks.

~ Oleksii
> 
> Jan



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

* Re: [PATCH v6 07/20] xen/riscv: introduce bitops.h
  2024-03-21 10:07     ` Oleksii
@ 2024-03-21 10:28       ` Jan Beulich
  0 siblings, 0 replies; 61+ messages in thread
From: Jan Beulich @ 2024-03-21 10:28 UTC (permalink / raw)
  To: Oleksii
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 21.03.2024 11:07, Oleksii wrote:
> On Wed, 2024-03-20 at 17:03 +0100, Jan Beulich wrote:
>> On 15.03.2024 19:06, Oleksii Kurochko wrote:
>>> --- /dev/null
>>> +++ b/xen/arch/riscv/include/asm/bitops.h
>>> @@ -0,0 +1,144 @@
>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>> +/* Copyright (C) 2012 Regents of the University of California */
>>> +
>>> +#ifndef _ASM_RISCV_BITOPS_H
>>> +#define _ASM_RISCV_BITOPS_H
>>> +
>>> +#include <asm/system.h>
>>> +
>>> +#define BITOP_BITS_PER_WORD BITS_PER_LONG
>>> +
>>> +#define BITOP_TYPE
>>> +typedef uint64_t bitops_uint_t;
>>> +
>>> +#include <asm-generic/bitops/bitops-bits.h>
>>> +
>>> +#define __set_bit(n, p)      set_bit(n, p)
>>> +#define __clear_bit(n, p)    clear_bit(n, p)
>>
>> If these cam with a TODO, I wouldn't say anything. But without I take
>> it
>> they're meant to remain that way, at which point I'd like to ask
>> about
>> the performance aspect: Surely the AMO insns are more expensive than
>> whatever more basic insns could be used instead? I'd even go as far
>> as
>> wondering whether
>>
>> #define __set_bit(n, p)      ((void)__test_and_set_bit(n, p))
>> #define __clear_bit(n, p)    ((void)__test_and_clear_bit(n, p))
>>
>> wouldn't be cheaper (the compiler would recognize the unused result
>> and eliminate its calculation, I'm pretty sure).
> It was implemented using atomic ops because of Arm:
> /*
>  * Non-atomic bit manipulation.
>  *
>  * Implemented using atomics to be interrupt safe. Could alternatively
>  * implement with local interrupt masking.
>  */
> #define __set_bit(n,p)            set_bit(n,p)
> #define __clear_bit(n,p)          clear_bit(n,p)
> 
> I though that the same comment is true for x86, but after your comment
> I checked x86 implementation, I realized that x86 uses non-atomic
> operations.
> 
> In this case, it seems to me there is a sense to use non-atomic for
> RISC-V too.

Hmm, wait: There's an important difference between x86 on one side and
Arm/RISC-V/PPC and various other more or less RISC-like ones on the other.
x86 has read-modify-write (memory) insns. Therefore even without using
their atomic (LOCKed) forms, they do the update atomically as far as the
local CPU is concerned. That's not the case when you need to use a three
(or more) step load-op-store sequence.

Had you retained Arm's comment, I probably wouldn't even have asked.
Please add such a comment while sticking to this aliasing you have.

Jan


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

* Re: [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h
  2024-03-15 18:06 ` [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h Oleksii Kurochko
@ 2024-03-21 12:07   ` Jan Beulich
  2024-03-22 10:32     ` Oleksii
  2024-04-02 11:43     ` Oleksii
  0 siblings, 2 replies; 61+ messages in thread
From: Jan Beulich @ 2024-03-21 12:07 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 15.03.2024 19:06, Oleksii Kurochko wrote:
> The header was taken from Linux kernl 6.4.0-rc1.
> 
> Addionally, were updated:
> * add emulation of {cmp}xchg for 1/2 byte types using 32-bit atomic
>   access.
> * replace tabs with spaces
> * replace __* variale with *__
> * introduce generic version of xchg_* and cmpxchg_*.
> * drop {cmp}xchg{release,relaxed,acquire} as Xen doesn't use them

With this, ...

> * drop barries and use instruction suffixices instead ( .aq, .rl, .aqrl )
> 
> Implementation of 4- and 8-byte cases were updated according to the spec:
> ```
>               ....
> Linux Construct         RVWMO AMO Mapping
> atomic <op> relaxed     amo<op>.{w|d}
> atomic <op> acquire     amo<op>.{w|d}.aq
> atomic <op> release     amo<op>.{w|d}.rl
> atomic <op>             amo<op>.{w|d}.aqrl
> Linux Construct         RVWMO LR/SC Mapping
> atomic <op> relaxed     loop: lr.{w|d}; <op>; sc.{w|d}; bnez loop
> atomic <op> acquire     loop: lr.{w|d}.aq; <op>; sc.{w|d}; bnez loop
> atomic <op> release     loop: lr.{w|d}; <op>; sc.{w|d}.aqrl∗ ; bnez loop OR
>                         fence.tso; loop: lr.{w|d}; <op>; sc.{w|d}∗ ; bnez loop
> atomic <op>             loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl; bnez loop
> 
> Table A.5: Mappings from Linux memory primitives to RISC-V primitives
> 
> ```

... I consider quoting this table in full, without any further remarks, as
confusing: Three of the lines each are inapplicable now, aiui.

Further what are the two * telling us? Quite likely they aren't there just
accidentally.

Finally, why sc.{w|d}.aqrl when in principle one would expect just
sc.{w|d}.rl?

> --- /dev/null
> +++ b/xen/arch/riscv/include/asm/cmpxchg.h
> @@ -0,0 +1,209 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/* Copyright (C) 2014 Regents of the University of California */
> +
> +#ifndef _ASM_RISCV_CMPXCHG_H
> +#define _ASM_RISCV_CMPXCHG_H
> +
> +#include <xen/compiler.h>
> +#include <xen/lib.h>
> +
> +#include <asm/fence.h>
> +#include <asm/io.h>
> +#include <asm/system.h>
> +
> +#define __amoswap_generic(ptr, new, ret, sfx) \

As before / elsewhere: Is there a strong need for two leading underscores
here? Using just one would already be standard compliant afaict.

> +({ \
> +    asm volatile ( \
> +        " amoswap" sfx " %0, %2, %1" \
> +        : "=r" (ret), "+A" (*ptr) \
> +        : "r" (new) \
> +        : "memory" ); \
> +})

This doesn't need the ({ }) (anymore?):

#define __amoswap_generic(ptr, new, ret, sfx) \
    asm volatile ( \
        " amoswap" sfx " %0, %2, %1" \
        : "=r" (ret), "+A" (*(ptr)) \
        : "r" (new) \
        : "memory" )

(note also the added parentheses).

> +/*
> + * For LR and SC, the A extension requires that the address held in rs1 be
> + * naturally aligned to the size of the operand (i.e., eight-byte aligned
> + * for 64-bit words and four-byte aligned for 32-bit words).
> + * If the address is not naturally aligned, an address-misaligned exception
> + * or an access-fault exception will be generated.
> + *
> + * Thereby:
> + * - for 1-byte xchg access the containing word by clearing low two bits
> + * - for 2-byte xchg ccess the containing word by clearing bit 1.

Nit: "access"

> + * If resulting 4-byte access is still misalgined, it will fault just as
> + * non-emulated 4-byte access would.
> + */
> +#define emulate_xchg_1_2(ptr, new, lr_sfx, sc_sfx) \
> +({ \
> +    uint32_t *aligned_ptr = (uint32_t *)((unsigned long)ptr & ~(0x4 - sizeof(*(ptr)))); \
> +    unsigned int new_val_pos = ((unsigned long)(ptr) & (0x4 - sizeof(*(ptr)))) * BITS_PER_BYTE; \

You parenthesize ptr here correctly, but not in the line above.

Instead of "_pos" in the name, maybe better "_bit"?

Finally, here and elsewhere, please limit line length to 80 chars. (Omitting
the 0x here would help a little, but not quite enough. Question is whether
these wouldn't better be sizeof(*aligned_ptr) anyway.)

> +    unsigned long mask = GENMASK(((sizeof(*(ptr))) * BITS_PER_BYTE) - 1, 0) << new_val_pos; \
> +    unsigned int new_ = new << new_val_pos; \

Similarly new wants parenthesizing here.

> +    unsigned int old; \
> +    unsigned int scratch; \
> +    \
> +    asm volatile ( \
> +        "0: lr.w" lr_sfx " %[old], %[aligned_ptr]\n" \
> +        "   and  %[scratch], %[old], %z[nmask]\n" \
> +        "   or   %[scratch], %[scratch], %z[new_]\n" \
> +        "   sc.w" sc_sfx " %[scratch], %[scratch], %[aligned_ptr]\n" \
> +        "   bnez %[scratch], 0b\n" \
> +        : [old] "=&r" (old), [scratch] "=&r" (scratch), [aligned_ptr] "+A" (*aligned_ptr) \

While for the variable name aligned_ptr is likely helpful, for the operand
name just ptr would certainly do?

> +        : [new_] "rJ" (new_), [nmask] "rJ" (~mask) \

Neither mask nor ~mask can be 0. Hence J here and the z modifier above
look pointless. (new_, otoh, can be 0, so allowing x0 to be used in that
case is certainly desirable.)

As to using ~mask here: Now that we look to have settled on requiring
Zbb, you could use andn instead of and, thus allowing the same register
to be used in the asm() and ...

> +        : "memory" ); \
> +    \
> +    (__typeof__(*(ptr)))((old & mask) >> new_val_pos); \

... for this calculation.

> +})
> +
> +static always_inline unsigned long __xchg(volatile void *ptr, unsigned long new, int size)
> +{
> +    unsigned long ret;
> +
> +    switch ( size )
> +    {
> +    case 1:
> +        ret = emulate_xchg_1_2((volatile uint8_t *)ptr, new, ".aq", ".aqrl");
> +        break;
> +    case 2:
> +        ret = emulate_xchg_1_2((volatile uint16_t *)ptr, new, ".aq", ".aqrl");
> +        break;
> +    case 4:
> +        __amoswap_generic((volatile uint32_t *)ptr, new, ret, ".w.aqrl");
> +        break;
> +#ifndef CONFIG_32BIT

There's no 32BIT Kconfig symbol; all we have is a 64BIT one.

> +    case 8:
> +        __amoswap_generic((volatile uint64_t *)ptr, new, ret, ".d.aqrl");
> +        break;
> +#endif
> +    default:
> +        STATIC_ASSERT_UNREACHABLE();
> +    }
> +
> +    return ret;
> +}
> +
> +#define xchg(ptr, x) \
> +({ \
> +    __typeof__(*(ptr)) n_ = (x); \
> +    (__typeof__(*(ptr))) \
> +        __xchg((ptr), (unsigned long)(n_), sizeof(*(ptr))); \

Nit: While excess parentheses "only" harm readability, they would
nevertheless better be omitted (here: the first argument passed).

> +})
> +
> +#define __generic_cmpxchg(ptr, old, new, ret, lr_sfx, sc_sfx)	\
> + ({ \
> +    register unsigned int rc; \

Nit: We don't normally use "register", unless accompanied by asm() tying
a variable to a specific one.

> +    __typeof__(*(ptr)) old__ = (__typeof__(*(ptr)))(old); \
> +    __typeof__(*(ptr)) new__ = (__typeof__(*(ptr)))(new); \

The casts aren't very nice to have here; I take they're needed for
cmpxchg_ptr() to compile?

> +    asm volatile( \

Nit: Missing blank once again. Would be really nice if you could go
through and sort this uniformly for the series.

> +        "0: lr" lr_sfx " %0, %2\n" \
> +        "   bne  %0, %z3, 1f\n" \
> +        "   sc" sc_sfx " %1, %z4, %2\n" \
> +        "   bnez %1, 0b\n" \
> +        "1:\n" \
> +        : "=&r" (ret), "=&r" (rc), "+A" (*ptr) \
> +        : "rJ" (old__), "rJ" (new__) \

Please could I talk you into using named operands here, too?

Also ptr here is lacking parentheses again.

> +        : "memory"); \

And yet another missing blank.

> + })

At the use site this construct having a normal return value (rather
than ret being passed in) would overall look more natural.

> +/*
> + * For LR and SC, the A extension requires that the address held in rs1 be
> + * naturally aligned to the size of the operand (i.e., eight-byte aligned
> + * for 64-bit words and four-byte aligned for 32-bit words).
> + * If the address is not naturally aligned, an address-misaligned exception
> + * or an access-fault exception will be generated.
> + *
> + * Thereby:
> + * - for 1-byte xchg access the containing word by clearing low two bits
> + * - for 2-byte xchg ccess the containing word by clearing first bit.
> + * 
> + * If resulting 4-byte access is still misalgined, it will fault just as
> + * non-emulated 4-byte access would.
> + *
> + * old_val was casted to unsigned long for cmpxchgptr()
> + */
> +#define emulate_cmpxchg_1_2(ptr, old, new, lr_sfx, sc_sfx) \
> +({ \
> +    uint32_t *aligned_ptr = (uint32_t *)((unsigned long)ptr & ~(0x4 - sizeof(*(ptr)))); \
> +    uint8_t new_val_pos = ((unsigned long)(ptr) & (0x4 - sizeof(*(ptr)))) * BITS_PER_BYTE; \
> +    unsigned long mask = GENMASK(((sizeof(*(ptr))) * BITS_PER_BYTE) - 1, 0) << new_val_pos; \
> +    unsigned int old_ = old << new_val_pos; \
> +    unsigned int new_ = new << new_val_pos; \
> +    unsigned int old_val; \
> +    unsigned int scratch; \
> +    \
> +    __asm__ __volatile__ ( \
> +        "0: lr.w" lr_sfx " %[scratch], %[aligned_ptr]\n" \
> +        "   and  %[old_val], %[scratch], %z[mask]\n" \
> +        "   bne  %[old_val], %z[old_], 1f\n" \
> +        "   xor  %[scratch], %[old_val], %[scratch]\n" \

To be honest I was hoping this line would come with a brief comment.

> +        "   or   %[scratch], %[scratch], %z[new_]\n" \
> +        "   sc.w" sc_sfx " %[scratch], %[scratch], %[aligned_ptr]\n" \
> +        "   bnez %[scratch], 0b\n" \
> +        "1:\n" \
> +        : [old_val] "=&r" (old_val), [scratch] "=&r" (scratch), [aligned_ptr] "+A" (*aligned_ptr) \
> +        : [old_] "rJ" (old_), [new_] "rJ" (new_), \
> +          [mask] "rJ" (mask) \
> +        : "memory" ); \
> +    \
> +    (__typeof__(*(ptr)))((unsigned long)old_val >> new_val_pos); \
> +})

A few of the comments for emulate_xchg_1_2() apply here as well.

> +/*
> + * Atomic compare and exchange.  Compare OLD with MEM, if identical,
> + * store NEW in MEM.  Return the initial value in MEM.  Success is
> + * indicated by comparing RETURN with OLD.
> + */
> +static always_inline unsigned long __cmpxchg(volatile void *ptr,
> +                         unsigned long old,
> +                         unsigned long new,
> +                         int size)

Nit: Inappropriate indentation.

Jan


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

* Re: [PATCH v6 09/20] xen/riscv: introduce io.h
  2024-03-15 18:06 ` [PATCH v6 09/20] xen/riscv: introduce io.h Oleksii Kurochko
@ 2024-03-21 12:27   ` Jan Beulich
  2024-03-22 11:02     ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-21 12:27 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 15.03.2024 19:06, Oleksii Kurochko wrote:
> --- /dev/null
> +++ b/xen/arch/riscv/include/asm/io.h
> @@ -0,0 +1,167 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + *  The header taken form Linux 6.4.0-rc1 and is based on
> + *  arch/riscv/include/asm/mmio.h with the following changes:
> + *   - drop forcing of endianess for read*(), write*() functions as
> + *     no matter what CPU endianness, what endianness a particular device
> + *     (and hence its MMIO region(s)) is using is entirely independent.
> + *     Hence conversion, where necessary, needs to occur at a layer up.
> + *     Another one reason to drop endianess conversion is:
> + *     https://patchwork.kernel.org/project/linux-riscv/patch/20190411115623.5749-3-hch@lst.de/
> + *     One of the answers of the author of the commit:
> + *       And we don't know if Linux will be around if that ever changes.
> + *       The point is:
> + *        a) the current RISC-V spec is LE only
> + *        b) the current linux port is LE only except for this little bit
> + *       There is no point in leaving just this bitrotting code around.  It
> + *       just confuses developers, (very very slightly) slows down compiles
> + *      and will bitrot.  It also won't be any significant help to a future
> + *       developer down the road doing a hypothetical BE RISC-V Linux port.
> + *   - drop unused argument of __io_ar() macros.
> + *   - drop "#define _raw_{read,write}{b,w,l,d,q} _raw_{read,write}{b,w,l,d,q}"

In the commit message I'm not worried as much, but at least here the odd mention
of d as suffixes would better be purged.

> + *     as they are unnecessary.
> + *   - Adopt the Xen code style for this header, considering that significant
> + *     changes are not anticipated in the future.
> + *     In the event of any issues, adapting them to Xen style should be easily
> + *     manageable.
> + *   - drop unnecessary __r variables in macros read*_cpu()
> + *   - update inline assembler constraints for addr argument for
> + *     __raw_read{b,w,l,q} and __raw_write{b,w,l,q} to tell a compiler that
> + *     *addr will be accessed.
> + *
> + * Copyright (C) 1996-2000 Russell King
> + * Copyright (C) 2012 ARM Ltd.
> + * Copyright (C) 2014 Regents of the University of California
> + * Copyright (C) 2024 Vates
> + */
> +
> +#ifndef _ASM_RISCV_IO_H
> +#define _ASM_RISCV_IO_H
> +
> +#include <asm/byteorder.h>
> +
> +/*
> + * The RISC-V ISA doesn't yet specify how to query or modify PMAs, so we can't
> + * change the properties of memory regions.  This should be fixed by the
> + * upcoming platform spec.
> + */
> +#define ioremap_nocache(addr, size) ioremap(addr, size)
> +#define ioremap_wc(addr, size) ioremap(addr, size)
> +#define ioremap_wt(addr, size) ioremap(addr, size)
> +
> +/* Generic IO read/write.  These perform native-endian accesses. */
> +static inline void __raw_writeb(uint8_t val, volatile void __iomem *addr)
> +{
> +    asm volatile ( "sb %1, %0" : "=m" (*(volatile uint8_t __force *)addr) : "r" (val) );

Please respect line length restrictions.

> +}
> +
> +static inline void __raw_writew(uint16_t val, volatile void __iomem *addr)
> +{
> +    asm volatile ( "sh %1, %0" : "=m" (*(volatile uint16_t __force *)addr) : "r" (val) );
> +}
> +
> +static inline void __raw_writel(uint32_t val, volatile void __iomem *addr)
> +{
> +    asm volatile ( "sw %1, %0" : "=m" (*(volatile uint32_t __force *)addr) : "r" (val) );
> +}
> +
> +#ifdef CONFIG_RISCV_32
> +static inline void __raw_writeq(uint64_t val, volatile void __iomem *addr)
> +{
> +    BUILD_BUG_ON("unimplemented\n");
> +}
> +#else
> +static inline void __raw_writeq(uint64_t val, volatile void __iomem *addr)
> +{
> +    asm volatile ( "sd %1, %0" : "=m" (*(volatile uint64_t __force *)addr) : "r" (val) );
> +}
> +#endif

Please avoid code duplication if it easily can be avoided:

static inline void __raw_writeq(uint64_t val, volatile void __iomem *addr)
{
#ifdef CONFIG_RISCV_32
    BUILD_BUG_ON("unimplemented");
#else
    asm volatile ( "sd %1, %0" : "=m" (*(volatile uint64_t __force *)addr) : "r" (val) );
#endif
}

(Note also the dropped \n.)

> +static inline uint8_t __raw_readb(const volatile void __iomem *addr)
> +{
> +    uint8_t val;
> +
> +    asm volatile ( "lb %0, %1" : "=r" (val) : "m" (*(volatile uint8_t __force *)addr) );

Please don't cast away const.

> +    return val;
> +}
> +
> +static inline uint16_t __raw_readw(const volatile void __iomem *addr)
> +{
> +    uint16_t val;
> +
> +    asm volatile ( "lh %0, %1" : "=r" (val) : "m" (*(volatile uint16_t __force *)addr) );
> +    return val;
> +}
> +
> +static inline uint32_t __raw_readl(const volatile void __iomem *addr)
> +{
> +    uint32_t val;
> +
> +    asm volatile ( "lw %0, %1" : "=r" (val) : "m" (*(volatile uint32_t __force *)addr) );
> +    return val;
> +}
> +
> +#ifdef CONFIG_RISCV_32
> +static inline uint64_t __raw_readq(const volatile void __iomem *addr)
> +{
> +    BUILD_BUG_ON("unimplemented\n");
> +    return 0;
> +}
> +#else
> +static inline uint64_t __raw_readq(const volatile void __iomem *addr)
> +{
> +    uint64_t val;
> +
> +    asm volatile ( "ld %0, %1" : "=r" (val) : "m" (*(volatile uint64_t __force *)addr) );
> +    return val;
> +}
> +#endif
> +
> +/*
> + * Unordered I/O memory access primitives.  These are even more relaxed than
> + * the relaxed versions, as they don't even order accesses between successive
> + * operations to the I/O regions.
> + */
> +#define readb_cpu(c)        __raw_readb(c)
> +#define readw_cpu(c)        __raw_readw(c)
> +#define readl_cpu(c)        __raw_readl(c)
> +
> +#define writeb_cpu(v, c)    __raw_writeb(v, c)
> +#define writew_cpu(v, c)    __raw_writew(v, c)
> +#define writel_cpu(v, c)    __raw_writel(v, c)
> +
> +#define readq_cpu(c)        __raw_readq(c)
> +#define writeq_cpu(v, c)    __raw_writeq(v, c)

Since (now?) outside of any #ifdef (which is okay with me), why not each
grouped with their respective 3 siblings?

> +/*
> + * I/O memory access primitives. Reads are ordered relative to any
> + * following Normal memory access. Writes are ordered relative to any prior
> + * Normal memory access.  The memory barriers here are necessary as RISC-V
> + * doesn't define any ordering between the memory space and the I/O space.
> + */
> +#define __io_br()   do { } while (0)
> +#define __io_ar()   asm volatile ( "fence i,r" : : : "memory" );
> +#define __io_bw()   asm volatile ( "fence w,o" : : : "memory" );
> +#define __io_aw()   do { } while (0)
> +
> +#define readb(c)    ({ uint8_t  v; __io_br(); v = readb_cpu(c); __io_ar(); v; })

I'm wary of "v" as a macro local: What if at a use site there's

    x = readb(v);

? That'll fail to compile, provided at the use site v is actually a pointer,
but the reason for the error won't necessarily be obvious. (Hence why in the
past people did prefix underscores on such local variable names, while now
we're advocating for suffixes.)

> +#define readw(c)    ({ uint16_t v; __io_br(); v = readw_cpu(c); __io_ar(); v; })
> +#define readl(c)    ({ uint32_t v; __io_br(); v = readl_cpu(c); __io_ar(); v; })
> +
> +#define writeb(v, c)    ({ __io_bw(); writeb_cpu(v, c); __io_aw(); })
> +#define writew(v, c)    ({ __io_bw(); writew_cpu(v, c); __io_aw(); })
> +#define writel(v, c)    ({ __io_bw(); writel_cpu(v, c); __io_aw(); })
> +
> +#define readq(c)        ({ uint64_t v; __io_br(); v = readq_cpu(c); __io_ar(); v; })
> +#define writeq(v, c)    ({ __io_bw(); writeq_cpu(v, c); __io_aw(); })

Same here then.

Jan


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

* Re: [PATCH v6 10/20] xen/riscv: introduce atomic.h
  2024-03-15 18:06 ` [PATCH v6 10/20] xen/riscv: introduce atomic.h Oleksii Kurochko
@ 2024-03-21 13:03   ` Jan Beulich
  2024-03-22 12:25     ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-21 13:03 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 15.03.2024 19:06, Oleksii Kurochko wrote:
> Initially the patch was introduced by Bobby, who takes the header from
> Linux kernel.
> 
> The following changes were done on top of Linux kernel header:
>  - atomic##prefix##_*xchg_*(atomic##prefix##_t *v, c_t n) were updated
>      to use__*xchg_generic()
>  - drop casts in write_atomic() as they are unnecessary
>  - drop introduction of WRITE_ONCE() and READ_ONCE().
>    Xen provides ACCESS_ONCE()

Here and in the code comment: While this may be describing what you did
on top of what Bobby had, here you're describing differences to the Linux
header.

>  - remove zero-length array access in read_atomic()
>  - drop defines similar to pattern

pattern? Which one? Oh, wait, ...

>  - #define atomic_add_return_relaxed   atomic_add_return_relaxed

... this line really isn't a separate bullet point.

> Changes in V6:
>  - drop atomic##prefix##_{cmp}xchg_{release, aquire, relaxed} as they aren't used
>    by Xen
>  - code style fixes.
>  - %s/__asm__ __volatile__/asm volatile

Btw, this is another activity that could do with being carried out
consistently through the series.

> --- /dev/null
> +++ b/xen/arch/riscv/include/asm/atomic.h
> @@ -0,0 +1,263 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Taken and modified from Linux.
> + *
> + * The following changes were done:
> + * - * atomic##prefix##_*xchg_*(atomic##prefix##_t *v, c_t n) were updated
> + *     to use__*xchg_generic()
> + * - drop casts in write_atomic() as they are unnecessary
> + * - drop introduction of WRITE_ONCE() and READ_ONCE().
> + *   Xen provides ACCESS_ONCE()
> + * - remove zero-length array access in read_atomic()
> + * - drop defines similar to pattern
> + *   #define atomic_add_return_relaxed   atomic_add_return_relaxed
> + * - move not RISC-V specific functions to asm-generic/atomics-ops.h
> + * 
> + * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
> + * Copyright (C) 2012 Regents of the University of California
> + * Copyright (C) 2017 SiFive
> + * Copyright (C) 2024 Vates SAS
> + */
> +
> +#ifndef _ASM_RISCV_ATOMIC_H
> +#define _ASM_RISCV_ATOMIC_H
> +
> +#include <xen/atomic.h>
> +
> +#include <asm/cmpxchg.h>
> +#include <asm/fence.h>
> +#include <asm/io.h>
> +#include <asm/system.h>
> +
> +void __bad_atomic_size(void);
> +
> +/*
> + * Legacy from Linux kernel. For some reason they wanted to have ordered
> + * read/write access. Thereby read* is used instead of read<X>_cpu()

Either read<X> and read<X>_cpu() or read* and read*_cpu(), please.

> + */
> +static always_inline void read_atomic_size(const volatile void *p,
> +                                           void *res,
> +                                           unsigned int size)
> +{
> +    switch ( size )
> +    {
> +    case 1: *(uint8_t *)res = readb(p); break;
> +    case 2: *(uint16_t *)res = readw(p); break;
> +    case 4: *(uint32_t *)res = readl(p); break;
> +    case 8: *(uint32_t *)res  = readq(p); break;

Nit: Excess blank before =.

Also - no #ifdef here to be RV32-ready?

> +    default: __bad_atomic_size(); break;
> +    }
> +}
> +
> +#define read_atomic(p) ({                                   \
> +    union { typeof(*(p)) val; char c[sizeof(*(p))]; } x_;   \

One trailing underscore here, but ...

> +    read_atomic_size(p, x_.c, sizeof(*(p)));                \
> +    x_.val;                                                 \
> +})
> +
> +#define write_atomic(p, x)                              \
> +({                                                      \
> +    typeof(*(p)) x__ = (x);                             \

... two here and ...

> +    switch ( sizeof(*(p)) )                             \
> +    {                                                   \
> +    case 1: writeb(x__, p); break;                      \
> +    case 2: writew(x__, p); break;                      \
> +    case 4: writel(x__, p); break;                      \
> +    case 8: writeq(x__, p); break;                      \
> +    default: __bad_atomic_size(); break;                \
> +    }                                                   \
> +    x__;                                                \
> +})
> +
> +#define add_sized(p, x)                                 \
> +({                                                      \
> +    typeof(*(p)) x__ = (x);                             \

... here?

> +    switch ( sizeof(*(p)) )                             \
> +    {                                                   \
> +    case 1: writeb(read_atomic(p) + x__, p); break;     \
> +    case 2: writew(read_atomic(p) + x__, p); break;     \
> +    case 4: writel(read_atomic(p) + x__, p); break;     \
> +    case 8: writeq(read_atomic(p) + x__, p); break;     \
> +    default: __bad_atomic_size(); break;                \
> +    }                                                   \
> +})
> +
> +#define __atomic_acquire_fence() \
> +    asm volatile ( RISCV_ACQUIRE_BARRIER "" ::: "memory" )
> +
> +#define __atomic_release_fence() \
> +    asm volatile ( RISCV_RELEASE_BARRIER "" ::: "memory" )
> +
> +/*
> + * First, the atomic ops that have no ordering constraints and therefor don't
> + * have the AQ or RL bits set.  These don't return anything, so there's only
> + * one version to worry about.
> + */
> +#define ATOMIC_OP(op, asm_op, I, asm_type, c_type, prefix)  \
> +static inline                                               \
> +void atomic##prefix##_##op(c_type i, atomic##prefix##_t *v) \
> +{                                                           \
> +    asm volatile (                                          \
> +        "   amo" #asm_op "." #asm_type " zero, %1, %0"      \
> +        : "+A" (v->counter)                                 \
> +        : "r" (I)                                           \

Btw, I consider this pretty confusing. At the 1st and 2nd glance this
looks like a mistake, i.e. as if i was meant. Imo ...

> +        : "memory" );                                       \
> +}                                                           \
> +
> +/*
> + * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is the reason why
> + * last argument for ATOMIC_OP isn't used.
> + */
> +#define ATOMIC_OPS(op, asm_op, I)                           \
> +        ATOMIC_OP (op, asm_op, I, w, int,   )
> +
> +ATOMIC_OPS(add, add,  i)
> +ATOMIC_OPS(sub, add, -i)
> +ATOMIC_OPS(and, and,  i)
> +ATOMIC_OPS( or,  or,  i)
> +ATOMIC_OPS(xor, xor,  i)

... here you want to only pass the (unary) operator (and leaving that blank
is as fine as using +).

> +#undef ATOMIC_OP
> +#undef ATOMIC_OPS
> +
> +#include <asm-generic/atomic-ops.h>
> +
> +/*
> + * Atomic ops that have ordered, relaxed, acquire, and release variants.

Only the first is implemented afaict; imo the comment would better reflect
that one way or another.

> + * There's two flavors of these: the arithmatic ops have both fetch and return
> + * versions, while the logical ops only have fetch versions.
> + */
> +#define ATOMIC_FETCH_OP(op, asm_op, I, asm_type, c_type, prefix)    \
> +static inline                                                       \
> +c_type atomic##prefix##_fetch_##op##_relaxed(c_type i,              \
> +                         atomic##prefix##_t *v)                     \
> +{                                                                   \
> +    register c_type ret;                                            \
> +    asm volatile (                                                  \
> +        "   amo" #asm_op "." #asm_type " %1, %2, %0"                \
> +        : "+A" (v->counter), "=r" (ret)                             \
> +        : "r" (I)                                                   \
> +        : "memory" );                                               \
> +    return ret;                                                     \
> +}                                                                   \

Actually a relaxed form is provided here, but does that have any user?

> +static inline                                                       \
> +c_type atomic##prefix##_fetch_##op(c_type i, atomic##prefix##_t *v) \
> +{                                                                   \
> +    register c_type ret;                                            \
> +    asm volatile (                                                  \
> +        "   amo" #asm_op "." #asm_type ".aqrl  %1, %2, %0"          \
> +        : "+A" (v->counter), "=r" (ret)                             \
> +        : "r" (I)                                                   \
> +        : "memory" );                                               \
> +    return ret;                                                     \
> +}
> +
> +#define ATOMIC_OP_RETURN(op, asm_op, c_op, I, asm_type, c_type, prefix) \
> +static inline                                                           \
> +c_type atomic##prefix##_##op##_return_relaxed(c_type i,                 \
> +                          atomic##prefix##_t *v)                        \
> +{                                                                       \
> +        return atomic##prefix##_fetch_##op##_relaxed(i, v) c_op I;      \
> +}                                                                       \
> +static inline                                                           \
> +c_type atomic##prefix##_##op##_return(c_type i, atomic##prefix##_t *v)  \
> +{                                                                       \
> +        return atomic##prefix##_fetch_##op(i, v) c_op I;                \

I (or whatever the replacement expression is going to be following the
earlier comment) wants parenthesizing here.

> +}
> +
> +/*
> + * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is the reason why
> + * last argument of ATOMIC_FETCH_OP, ATOMIC_OP_RETURN isn't used.
> + */
> +#define ATOMIC_OPS(op, asm_op, c_op, I)                                 \
> +        ATOMIC_FETCH_OP( op, asm_op,       I, w, int,   )               \
> +        ATOMIC_OP_RETURN(op, asm_op, c_op, I, w, int,   )
> +
> +ATOMIC_OPS(add, add, +,  i)
> +ATOMIC_OPS(sub, add, +, -i)
> +
> +#undef ATOMIC_OPS
> +
> +#define ATOMIC_OPS(op, asm_op, I) \
> +        ATOMIC_FETCH_OP(op, asm_op, I, w, int,   )
> +
> +ATOMIC_OPS(and, and, i)
> +ATOMIC_OPS( or,  or, i)
> +ATOMIC_OPS(xor, xor, i)
> +
> +#undef ATOMIC_OPS
> +
> +#undef ATOMIC_FETCH_OP
> +#undef ATOMIC_OP_RETURN
> +
> +/* This is required to provide a full barrier on success. */
> +static inline int atomic_add_unless(atomic_t *v, int a, int u)
> +{
> +       int prev, rc;
> +
> +    asm volatile (
> +        "0: lr.w     %[p],  %[c]\n"
> +        "   beq      %[p],  %[u], 1f\n"
> +        "   add      %[rc], %[p], %[a]\n"
> +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
> +        "   bnez     %[rc], 0b\n"
> +        RISCV_FULL_BARRIER

With this and no .aq on the load, why the .rl on the store?

> +        "1:\n"
> +        : [p] "=&r" (prev), [rc] "=&r" (rc), [c] "+A" (v->counter)
> +        : [a] "r" (a), [u] "r" (u)
> +        : "memory");
> +    return prev;
> +}
> +
> +/*
> + * atomic_{cmp,}xchg is required to have exactly the same ordering semantics as
> + * {cmp,}xchg and the operations that return.
> + */
> +#define ATOMIC_OP(c_t, prefix, size)                            \
> +static inline                                                   \
> +c_t atomic##prefix##_xchg(atomic##prefix##_t *v, c_t n)         \
> +{                                                               \
> +    return __xchg(&(v->counter), n, size);                      \

No need for the inner parentheses, just like ...

> +}                                                               \
> +static inline                                                   \
> +c_t atomic##prefix##_cmpxchg(atomic##prefix##_t *v, c_t o, c_t n) \
> +{                                                               \
> +    return __cmpxchg(&v->counter, o, n, size);                  \

... you have it here.

> +}
> +
> +#define ATOMIC_OPS() \
> +    ATOMIC_OP(int,   , 4)
> +
> +ATOMIC_OPS()
> +
> +#undef ATOMIC_OPS
> +#undef ATOMIC_OP
> +
> +static inline int atomic_sub_if_positive(atomic_t *v, int offset)
> +{
> +       int prev, rc;
> +
> +    asm volatile (
> +        "0: lr.w     %[p],  %[c]\n"
> +        "   sub      %[rc], %[p], %[o]\n"
> +        "   bltz     %[rc], 1f\n"
> +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
> +        "   bnez     %[rc], 0b\n"
> +        "   fence    rw, rw\n"
> +        "1:\n"
> +        : [p] "=&r" (prev), [rc] "=&r" (rc), [c] "+A" (v->counter)
> +        : [o] "r" (offset)
> +        : "memory" );
> +    return prev - offset;
> +}

This probably would be nicer if sitting next to atomic_add_unless().

> --- /dev/null
> +++ b/xen/include/asm-generic/atomic-ops.h
> @@ -0,0 +1,97 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * The header provides default implementations for every xen/atomic.h-provided
> + * forward inline declaration that can be synthesized from other atomic
> + * functions.

Or from scratch, as e.g. ...

> + */
> +#ifndef _ASM_GENERIC_ATOMIC_OPS_H_
> +#define _ASM_GENERIC_ATOMIC_OPS_H_
> +
> +#include <xen/atomic.h>
> +#include <xen/lib.h>
> +
> +#ifndef ATOMIC_READ
> +static inline int atomic_read(const atomic_t *v)
> +{
> +    return ACCESS_ONCE(v->counter);
> +}
> +#endif
> +
> +#ifndef _ATOMIC_READ
> +static inline int _atomic_read(atomic_t v)
> +{
> +    return v.counter;
> +}
> +#endif
> +
> +#ifndef ATOMIC_SET
> +static inline void atomic_set(atomic_t *v, int i)
> +{
> +    ACCESS_ONCE(v->counter) = i;
> +}
> +#endif
> +
> +#ifndef _ATOMIC_SET
> +static inline void _atomic_set(atomic_t *v, int i)
> +{
> +    v->counter = i;
> +}
> +#endif

... all of these.

> +#ifndef ATOMIC_SUB_AND_TEST
> +static inline int atomic_sub_and_test(int i, atomic_t *v)
> +{
> +    return atomic_sub_return(i, v) == 0;
> +}
> +#endif
> +
> +#ifndef ATOMIC_INC
> +static inline void atomic_inc(atomic_t *v)
> +{
> +    atomic_add(1, v);
> +}
> +#endif
> +
> +#ifndef ATOMIC_INC_RETURN
> +static inline int atomic_inc_return(atomic_t *v)
> +{
> +    return atomic_add_return(1, v);
> +}
> +#endif
> +
> +#ifndef ATOMIC_DEC
> +static inline void atomic_dec(atomic_t *v)
> +{
> +    atomic_sub(1, v);
> +}
> +#endif
> +
> +#ifndef ATOMIC_DEC_RETURN
> +static inline int atomic_dec_return(atomic_t *v)
> +{
> +    return atomic_sub_return(1, v);
> +}
> +#endif
> +
> +#ifndef ATOMIC_DEC_AND_TEST
> +static inline int atomic_dec_and_test(atomic_t *v)
> +{
> +    return atomic_sub_return(1, v) == 0;
> +}
> +#endif
> +
> +#ifndef ATOMIC_ADD_NEGATIVE
> +static inline int atomic_add_negative(int i, atomic_t *v)
> +{
> +    return atomic_add_return(i, v) < 0;
> +}
> +#endif
> +
> +#ifndef ATOMIC_INC_AND_TEST
> +static inline int atomic_inc_and_test(atomic_t *v)
> +{
> +    return atomic_add_return(1, v) == 0;
> +}
> +#endif

Can this be moved up a little, perhaps next to the other inc-s (or else
next to dec_and_test), please?

Jan


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

* Re: [PATCH v6 15/20] xen/riscv: add minimal stuff to processor.h to build full Xen
  2024-03-15 18:06 ` [PATCH v6 15/20] xen/riscv: add minimal stuff to processor.h " Oleksii Kurochko
@ 2024-03-21 13:26   ` Jan Beulich
  2024-03-22 12:26     ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-21 13:26 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 15.03.2024 19:06, Oleksii Kurochko wrote:
> The cpu_relax() function, introduced in this commit, is anticipated to
> support _zihintpause by the CPU.
> 
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>

Acked-by: Jan Beulich <jbeulich@suse.com>

Looks like this can go in ahead of the other 14 patches?

Jan


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

* Re: [PATCH v6 16/20] xen/riscv: add minimal stuff to mm.h to build full Xen
  2024-03-15 18:06 ` [PATCH v6 16/20] xen/riscv: add minimal stuff to mm.h " Oleksii Kurochko
@ 2024-03-21 13:37   ` Jan Beulich
  0 siblings, 0 replies; 61+ messages in thread
From: Jan Beulich @ 2024-03-21 13:37 UTC (permalink / raw)
  To: Oleksii Kurochko
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 15.03.2024 19:06, Oleksii Kurochko wrote:
> --- a/xen/arch/riscv/include/asm/mm.h
> +++ b/xen/arch/riscv/include/asm/mm.h
> @@ -3,11 +3,246 @@
>  #ifndef _ASM_RISCV_MM_H
>  #define _ASM_RISCV_MM_H
>  
> +#include <public/xen.h>
> +#include <xen/bug.h>
> +#include <xen/mm-frame.h>
> +#include <xen/pdx.h>
> +#include <xen/types.h>
> +
>  #include <asm/page-bits.h>
>  
>  #define pfn_to_paddr(pfn) ((paddr_t)(pfn) << PAGE_SHIFT)
>  #define paddr_to_pfn(pa)  ((unsigned long)((pa) >> PAGE_SHIFT))
>  
> +#define paddr_to_pdx(pa)    mfn_to_pdx(maddr_to_mfn(pa))
> +#define gfn_to_gaddr(gfn)   pfn_to_paddr(gfn_x(gfn))
> +#define gaddr_to_gfn(ga)    _gfn(paddr_to_pfn(ga))
> +#define mfn_to_maddr(mfn)   pfn_to_paddr(mfn_x(mfn))
> +#define maddr_to_mfn(ma)    _mfn(paddr_to_pfn(ma))
> +#define vmap_to_mfn(va)     maddr_to_mfn(virt_to_maddr((vaddr_t)(va)))
> +#define vmap_to_page(va)    mfn_to_page(vmap_to_mfn(va))
> +
> +static inline void *maddr_to_virt(unsigned long ma)

paddr_t as parameter type?

> +{
> +    BUG_ON("unimplemented");
> +    return NULL;
> +}
>[...]
> +#define PFN_ORDER(pfn) ((pfn)->v.free.order)

Would be nice if RISC-V wouldn't repeat the parameter mis-naming: Any of
p, pg, or page would be more suitable here.

With the adjustments:
Acked-by: Jan Beulich <jbeulich@suse.com>

Jan


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

* Re: [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h
  2024-03-21 12:07   ` Jan Beulich
@ 2024-03-22 10:32     ` Oleksii
  2024-03-22 10:42       ` Jan Beulich
  2024-04-02 11:43     ` Oleksii
  1 sibling, 1 reply; 61+ messages in thread
From: Oleksii @ 2024-03-22 10:32 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Thu, 2024-03-21 at 13:07 +0100, Jan Beulich wrote:
> On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > The header was taken from Linux kernl 6.4.0-rc1.
> > 
> > Addionally, were updated:
> > * add emulation of {cmp}xchg for 1/2 byte types using 32-bit atomic
> >   access.
> > * replace tabs with spaces
> > * replace __* variale with *__
> > * introduce generic version of xchg_* and cmpxchg_*.
> > * drop {cmp}xchg{release,relaxed,acquire} as Xen doesn't use them
> 
> With this, ...
> 
> > * drop barries and use instruction suffixices instead ( .aq, .rl,
> > .aqrl )
> > 
> > Implementation of 4- and 8-byte cases were updated according to the
> > spec:
> > ```
> >               ....
> > Linux Construct         RVWMO AMO Mapping
> > atomic <op> relaxed     amo<op>.{w|d}
> > atomic <op> acquire     amo<op>.{w|d}.aq
> > atomic <op> release     amo<op>.{w|d}.rl
> > atomic <op>             amo<op>.{w|d}.aqrl
> > Linux Construct         RVWMO LR/SC Mapping
> > atomic <op> relaxed     loop: lr.{w|d}; <op>; sc.{w|d}; bnez loop
> > atomic <op> acquire     loop: lr.{w|d}.aq; <op>; sc.{w|d}; bnez
> > loop
> > atomic <op> release     loop: lr.{w|d}; <op>; sc.{w|d}.aqrl∗ ; bnez
> > loop OR
> >                         fence.tso; loop: lr.{w|d}; <op>; sc.{w|d}∗
> > ; bnez loop
> > atomic <op>             loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl;
> > bnez loop
> > 
> > Table A.5: Mappings from Linux memory primitives to RISC-V
> > primitives
> > 
> > ```
> 
> ... I consider quoting this table in full, without any further
> remarks, as
> confusing: Three of the lines each are inapplicable now, aiui.
I'll shorten the table then.

> 
> Further what are the two * telling us? Quite likely they aren't there
> just
> accidentally.
> 
> Finally, why sc.{w|d}.aqrl when in principle one would expect just
> sc.{w|d}.rl?
Because according to the last line of table A.5:
    atomic <op>             loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl;
Here it is used sc.{w|d}.aqrl form, so I decided to stick to the what
is mentioned in the table.

> 
> > +})
> > +
> > +static always_inline unsigned long __xchg(volatile void *ptr,
> > unsigned long new, int size)
> > +{
> > +    unsigned long ret;
> > +
> > +    switch ( size )
> > +    {
> > +    case 1:
> > +        ret = emulate_xchg_1_2((volatile uint8_t *)ptr, new,
> > ".aq", ".aqrl");
> > +        break;
> > +    case 2:
> > +        ret = emulate_xchg_1_2((volatile uint16_t *)ptr, new,
> > ".aq", ".aqrl");
> > +        break;
> > +    case 4:
> > +        __amoswap_generic((volatile uint32_t *)ptr, new, ret,
> > ".w.aqrl");
> > +        break;
> > +#ifndef CONFIG_32BIT
> 
> There's no 32BIT Kconfig symbol; all we have is a 64BIT one.
I meant here CONFIG_RISCV_32.

> 
> > +    case 8:
> > +        __amoswap_generic((volatile uint64_t *)ptr, new, ret,
> > ".d.aqrl");
> > +        break;
> > +#endif
> > +    default:
> > +        STATIC_ASSERT_UNREACHABLE();
> > +    }
> > +
> > +    return ret;
> > +}
> > +
> > +#define xchg(ptr, x) \
> > +({ \
> > +    __typeof__(*(ptr)) n_ = (x); \
> > +    (__typeof__(*(ptr))) \
> > +        __xchg((ptr), (unsigned long)(n_), sizeof(*(ptr))); \
> 
> Nit: While excess parentheses "only" harm readability, they would
> nevertheless better be omitted (here: the first argument passed).
> 
> > +})
> > +
> > +#define __generic_cmpxchg(ptr, old, new, ret, lr_sfx, sc_sfx)	\
> > + ({ \
> > +    register unsigned int rc; \
> 
> Nit: We don't normally use "register", unless accompanied by asm()
> tying
> a variable to a specific one.
> 
> > +    __typeof__(*(ptr)) old__ = (__typeof__(*(ptr)))(old); \
> > +    __typeof__(*(ptr)) new__ = (__typeof__(*(ptr)))(new); \
> 
> The casts aren't very nice to have here; I take they're needed for
> cmpxchg_ptr() to compile?
Not really, I have not faced an compilation issue.
The reason why it was added is that lr instruction places the sign-
extended value in destination register, but if not to do cast value for
old and new were generated without sign extension, so, for example:
   u32= 0xbbbbbbbb;
   cmpxchg(&u32, 0xbbbbbbbb, 0xCCCCCCCC), u32);
Will fail because after:
       "0: lr" lr_sfx " %0, %2\n" 
in %0 we will have 0xFFFFFFFFBBBBBBBB, but in %3 we will have
0xBBBBBBBB, so
       bne  %0, %z3, 1f\n"
%0 and %3 are always inequal in case when the most significat bit of
value read from %2 has 1.

But now I realized that it would be better just to use a mask and not
be dependent from compiler code generation, so it would be better to in
the following way ( of course, the macros should be updated accordingly
to remarks you give me ):
   #define __generic_cmpxchg(ptr, old, new, ret, lr_sfx, sc_sfx)	\
    ({ \
       register unsigned int rc; \
       unsigned long mask = GENMASK(((sizeof(*(ptr))) * BITS_PER_BYTE)
   - 1, 0); \
       asm volatile( \
           "0: lr" lr_sfx " %0, %2\n" \
           "   and  %0, %0, %z[mask]\n" \
           "   bne  %0, %z3, 1f\n" \
           "   sc" sc_sfx " %1, %z4, %2\n" \
           "   bnez %1, 0b\n" \
           "1:\n" \
           : "=&r" (ret), "=&r" (rc), "+A" (*ptr) \
           : "rJ" (old), "rJ" (new), [mask] "rJ" (mask)  \
           : "memory"); \
    })
   
> 
> > +    asm volatile( \
> 
> Nit: Missing blank once again. Would be really nice if you could go
> through and sort this uniformly for the series.
> 
> > +        "0: lr" lr_sfx " %0, %2\n" \
> > +        "   bne  %0, %z3, 1f\n" \
> > +        "   sc" sc_sfx " %1, %z4, %2\n" \
> > +        "   bnez %1, 0b\n" \
> > +        "1:\n" \
> > +        : "=&r" (ret), "=&r" (rc), "+A" (*ptr) \
> > +        : "rJ" (old__), "rJ" (new__) \
> 
> Please could I talk you into using named operands here, too?
Sure, I will add them.

~ Oleksii



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

* Re: [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h
  2024-03-22 10:32     ` Oleksii
@ 2024-03-22 10:42       ` Jan Beulich
  2024-03-22 12:52         ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-22 10:42 UTC (permalink / raw)
  To: Oleksii
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 22.03.2024 11:32, Oleksii wrote:
> On Thu, 2024-03-21 at 13:07 +0100, Jan Beulich wrote:
>> On 15.03.2024 19:06, Oleksii Kurochko wrote:
>>> The header was taken from Linux kernl 6.4.0-rc1.
>>>
>>> Addionally, were updated:
>>> * add emulation of {cmp}xchg for 1/2 byte types using 32-bit atomic
>>>   access.
>>> * replace tabs with spaces
>>> * replace __* variale with *__
>>> * introduce generic version of xchg_* and cmpxchg_*.
>>> * drop {cmp}xchg{release,relaxed,acquire} as Xen doesn't use them
>>
>> With this, ...
>>
>>> * drop barries and use instruction suffixices instead ( .aq, .rl,
>>> .aqrl )
>>>
>>> Implementation of 4- and 8-byte cases were updated according to the
>>> spec:
>>> ```
>>>               ....
>>> Linux Construct         RVWMO AMO Mapping
>>> atomic <op> relaxed     amo<op>.{w|d}
>>> atomic <op> acquire     amo<op>.{w|d}.aq
>>> atomic <op> release     amo<op>.{w|d}.rl
>>> atomic <op>             amo<op>.{w|d}.aqrl
>>> Linux Construct         RVWMO LR/SC Mapping
>>> atomic <op> relaxed     loop: lr.{w|d}; <op>; sc.{w|d}; bnez loop
>>> atomic <op> acquire     loop: lr.{w|d}.aq; <op>; sc.{w|d}; bnez
>>> loop
>>> atomic <op> release     loop: lr.{w|d}; <op>; sc.{w|d}.aqrl∗ ; bnez
>>> loop OR
>>>                         fence.tso; loop: lr.{w|d}; <op>; sc.{w|d}∗
>>> ; bnez loop
>>> atomic <op>             loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl;
>>> bnez loop
>>>
>>> Table A.5: Mappings from Linux memory primitives to RISC-V
>>> primitives
>>>
>>> ```
>>
>> ... I consider quoting this table in full, without any further
>> remarks, as
>> confusing: Three of the lines each are inapplicable now, aiui.
> I'll shorten the table then.
> 
>>
>> Further what are the two * telling us? Quite likely they aren't there
>> just
>> accidentally.
>>
>> Finally, why sc.{w|d}.aqrl when in principle one would expect just
>> sc.{w|d}.rl?
> Because according to the last line of table A.5:
>     atomic <op>             loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl;
> Here it is used sc.{w|d}.aqrl form, so I decided to stick to the what
> is mentioned in the table.

I understand it's mentioned that way in the table. But it being that way
is not explained anywhere. Hence my "Why?"

>>> +    __typeof__(*(ptr)) old__ = (__typeof__(*(ptr)))(old); \
>>> +    __typeof__(*(ptr)) new__ = (__typeof__(*(ptr)))(new); \
>>
>> The casts aren't very nice to have here; I take they're needed for
>> cmpxchg_ptr() to compile?
> Not really, I have not faced an compilation issue.
> The reason why it was added is that lr instruction places the sign-
> extended value in destination register, but if not to do cast value for
> old and new were generated without sign extension, so, for example:
>    u32= 0xbbbbbbbb;
>    cmpxchg(&u32, 0xbbbbbbbb, 0xCCCCCCCC), u32);
> Will fail because after:
>        "0: lr" lr_sfx " %0, %2\n" 
> in %0 we will have 0xFFFFFFFFBBBBBBBB, but in %3 we will have
> 0xBBBBBBBB, so
>        bne  %0, %z3, 1f\n"
> %0 and %3 are always inequal in case when the most significat bit of
> value read from %2 has 1.

I'm afraid I don't follow: It's the type conversion you're after, but
that would happen also with the casts omitted.

> But now I realized that it would be better just to use a mask and not
> be dependent from compiler code generation, so it would be better to in
> the following way ( of course, the macros should be updated accordingly
> to remarks you give me ):
>    #define __generic_cmpxchg(ptr, old, new, ret, lr_sfx, sc_sfx)	\
>     ({ \
>        register unsigned int rc; \
>        unsigned long mask = GENMASK(((sizeof(*(ptr))) * BITS_PER_BYTE)
>    - 1, 0); \
>        asm volatile( \
>            "0: lr" lr_sfx " %0, %2\n" \
>            "   and  %0, %0, %z[mask]\n" \
>            "   bne  %0, %z3, 1f\n" \
>            "   sc" sc_sfx " %1, %z4, %2\n" \
>            "   bnez %1, 0b\n" \
>            "1:\n" \
>            : "=&r" (ret), "=&r" (rc), "+A" (*ptr) \
>            : "rJ" (old), "rJ" (new), [mask] "rJ" (mask)  \
>            : "memory"); \
>     })

It'll be up to you whether to switch to such an alternative.

Jan


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

* Re: [PATCH v6 09/20] xen/riscv: introduce io.h
  2024-03-21 12:27   ` Jan Beulich
@ 2024-03-22 11:02     ` Oleksii
  2024-03-22 11:36       ` Jan Beulich
  0 siblings, 1 reply; 61+ messages in thread
From: Oleksii @ 2024-03-22 11:02 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Thu, 2024-03-21 at 13:27 +0100, Jan Beulich wrote:
> On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > --- /dev/null
> > +++ b/xen/arch/riscv/include/asm/io.h
> > @@ -0,0 +1,167 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + *  The header taken form Linux 6.4.0-rc1 and is based on
> > + *  arch/riscv/include/asm/mmio.h with the following changes:
> > + *   - drop forcing of endianess for read*(), write*() functions
> > as
> > + *     no matter what CPU endianness, what endianness a particular
> > device
> > + *     (and hence its MMIO region(s)) is using is entirely
> > independent.
> > + *     Hence conversion, where necessary, needs to occur at a
> > layer up.
> > + *     Another one reason to drop endianess conversion is:
> > + *    
> > https://patchwork.kernel.org/project/linux-riscv/patch/20190411115623.5749-3-hch@lst.de/
> > + *     One of the answers of the author of the commit:
> > + *       And we don't know if Linux will be around if that ever
> > changes.
> > + *       The point is:
> > + *        a) the current RISC-V spec is LE only
> > + *        b) the current linux port is LE only except for this
> > little bit
> > + *       There is no point in leaving just this bitrotting code
> > around.  It
> > + *       just confuses developers, (very very slightly) slows down
> > compiles
> > + *      and will bitrot.  It also won't be any significant help to
> > a future
> > + *       developer down the road doing a hypothetical BE RISC-V
> > Linux port.
> > + *   - drop unused argument of __io_ar() macros.
> > + *   - drop "#define _raw_{read,write}{b,w,l,d,q}
> > _raw_{read,write}{b,w,l,d,q}"
> 
> In the commit message I'm not worried as much, but at least here the
> odd mention
> of d as suffixes would better be purged.
Probably, I use incorrect words, but what I meant that it was dropped:
   #define _raw_{read,write}{b,w,l,d,q} _raw_{read,write}{b,w,l,d,q}
before declaration/definition of inline functions (
__raw_{read,write}{b,w,l,d,q} ).

~ Oleksii




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

* Re: [PATCH v6 09/20] xen/riscv: introduce io.h
  2024-03-22 11:02     ` Oleksii
@ 2024-03-22 11:36       ` Jan Beulich
  2024-03-22 12:55         ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-22 11:36 UTC (permalink / raw)
  To: Oleksii
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 22.03.2024 12:02, Oleksii wrote:
> On Thu, 2024-03-21 at 13:27 +0100, Jan Beulich wrote:
>> On 15.03.2024 19:06, Oleksii Kurochko wrote:
>>> --- /dev/null
>>> +++ b/xen/arch/riscv/include/asm/io.h
>>> @@ -0,0 +1,167 @@
>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>> +/*
>>> + *  The header taken form Linux 6.4.0-rc1 and is based on
>>> + *  arch/riscv/include/asm/mmio.h with the following changes:
>>> + *   - drop forcing of endianess for read*(), write*() functions
>>> as
>>> + *     no matter what CPU endianness, what endianness a particular
>>> device
>>> + *     (and hence its MMIO region(s)) is using is entirely
>>> independent.
>>> + *     Hence conversion, where necessary, needs to occur at a
>>> layer up.
>>> + *     Another one reason to drop endianess conversion is:
>>> + *    
>>> https://patchwork.kernel.org/project/linux-riscv/patch/20190411115623.5749-3-hch@lst.de/
>>> + *     One of the answers of the author of the commit:
>>> + *       And we don't know if Linux will be around if that ever
>>> changes.
>>> + *       The point is:
>>> + *        a) the current RISC-V spec is LE only
>>> + *        b) the current linux port is LE only except for this
>>> little bit
>>> + *       There is no point in leaving just this bitrotting code
>>> around.  It
>>> + *       just confuses developers, (very very slightly) slows down
>>> compiles
>>> + *      and will bitrot.  It also won't be any significant help to
>>> a future
>>> + *       developer down the road doing a hypothetical BE RISC-V
>>> Linux port.
>>> + *   - drop unused argument of __io_ar() macros.
>>> + *   - drop "#define _raw_{read,write}{b,w,l,d,q}
>>> _raw_{read,write}{b,w,l,d,q}"
>>
>> In the commit message I'm not worried as much, but at least here the
>> odd mention
>> of d as suffixes would better be purged.
> Probably, I use incorrect words, but what I meant that it was dropped:
>    #define _raw_{read,write}{b,w,l,d,q} _raw_{read,write}{b,w,l,d,q}
> before declaration/definition of inline functions (
> __raw_{read,write}{b,w,l,d,q} ).

But where did you find a raw_readd() or raw_writed() (with no matter how
many leading underscores)?

Jan


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

* Re: [PATCH v6 10/20] xen/riscv: introduce atomic.h
  2024-03-21 13:03   ` Jan Beulich
@ 2024-03-22 12:25     ` Oleksii
  2024-03-25  8:18       ` Jan Beulich
  0 siblings, 1 reply; 61+ messages in thread
From: Oleksii @ 2024-03-22 12:25 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Thu, 2024-03-21 at 14:03 +0100, Jan Beulich wrote:
> On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > Initially the patch was introduced by Bobby, who takes the header
> > from
> > Linux kernel.
> > 
> > The following changes were done on top of Linux kernel header:
> >  - atomic##prefix##_*xchg_*(atomic##prefix##_t *v, c_t n) were
> > updated
> >      to use__*xchg_generic()
> >  - drop casts in write_atomic() as they are unnecessary
> >  - drop introduction of WRITE_ONCE() and READ_ONCE().
> >    Xen provides ACCESS_ONCE()
> 
> Here and in the code comment: While this may be describing what you
> did
> on top of what Bobby had, here you're describing differences to the
> Linux
> header.
> 
> >  - remove zero-length array access in read_atomic()
> >  - drop defines similar to pattern
> 
> pattern? Which one? Oh, wait, ...
> 
> >  - #define atomic_add_return_relaxed   atomic_add_return_relaxed
> 
> ... this line really isn't a separate bullet point.
Yes, '-' is not needed in this text.

> 
> > + */
> > +static always_inline void read_atomic_size(const volatile void *p,
> > +                                           void *res,
> > +                                           unsigned int size)
> > +{
> > +    switch ( size )
> > +    {
> > +    case 1: *(uint8_t *)res = readb(p); break;
> > +    case 2: *(uint16_t *)res = readw(p); break;
> > +    case 4: *(uint32_t *)res = readl(p); break;
> > +    case 8: *(uint32_t *)res  = readq(p); break;
> 
> Nit: Excess blank before =.
> 
> Also - no #ifdef here to be RV32-ready?
Because there is #ifdef RV32 in io.h for readq().

> 
> > +    default: __bad_atomic_size(); break;
> > +    }
> > +}
> > +
> > +#define read_atomic(p) ({                                   \
> > +    union { typeof(*(p)) val; char c[sizeof(*(p))]; } x_;   \
> 
> One trailing underscore here, but ...
> 
> > +    read_atomic_size(p, x_.c, sizeof(*(p)));                \
> > +    x_.val;                                                 \
> > +})
> > +
> > +#define write_atomic(p, x)                              \
> > +({                                                      \
> > +    typeof(*(p)) x__ = (x);                             \
> 
> ... two here and ...
> 
> > +    switch ( sizeof(*(p)) )                             \
> > +    {                                                   \
> > +    case 1: writeb(x__, p); break;                      \
> > +    case 2: writew(x__, p); break;                      \
> > +    case 4: writel(x__, p); break;                      \
> > +    case 8: writeq(x__, p); break;                      \
> > +    default: __bad_atomic_size(); break;                \
> > +    }                                                   \
> > +    x__;                                                \
> > +})
> > +
> > +#define add_sized(p, x)                                 \
> > +({                                                      \
> > +    typeof(*(p)) x__ = (x);                             \
> 
> ... here?
I'll update in the same way.

> 
> > +    switch ( sizeof(*(p)) )                             \
> > +    {                                                   \
> > +    case 1: writeb(read_atomic(p) + x__, p); break;     \
> > +    case 2: writew(read_atomic(p) + x__, p); break;     \
> > +    case 4: writel(read_atomic(p) + x__, p); break;     \
> > +    case 8: writeq(read_atomic(p) + x__, p); break;     \
> > +    default: __bad_atomic_size(); break;                \
> > +    }                                                   \
> > +})
> > +
> > +#define __atomic_acquire_fence() \
> > +    asm volatile ( RISCV_ACQUIRE_BARRIER "" ::: "memory" )
> > +
> > +#define __atomic_release_fence() \
> > +    asm volatile ( RISCV_RELEASE_BARRIER "" ::: "memory" )
> > +
> > +/*
> > + * First, the atomic ops that have no ordering constraints and
> > therefor don't
> > + * have the AQ or RL bits set.  These don't return anything, so
> > there's only
> > + * one version to worry about.
> > + */
> > +#define ATOMIC_OP(op, asm_op, I, asm_type, c_type, prefix)  \
> > +static inline                                               \
> > +void atomic##prefix##_##op(c_type i, atomic##prefix##_t *v) \
> > +{                                                           \
> > +    asm volatile (                                          \
> > +        "   amo" #asm_op "." #asm_type " zero, %1, %0"      \
> > +        : "+A" (v->counter)                                 \
> > +        : "r" (I)                                           \
> 
> Btw, I consider this pretty confusing. At the 1st and 2nd glance this
> looks like a mistake, i.e. as if i was meant. Imo ...
> 
> > +        : "memory" );                                       \
> > +}                                                           \
> > +
> > +/*
> > + * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is the
> > reason why
> > + * last argument for ATOMIC_OP isn't used.
> > + */
> > +#define ATOMIC_OPS(op, asm_op, I)                           \
> > +        ATOMIC_OP (op, asm_op, I, w, int,   )
> > +
> > +ATOMIC_OPS(add, add,  i)
> > +ATOMIC_OPS(sub, add, -i)
> > +ATOMIC_OPS(and, and,  i)
> > +ATOMIC_OPS( or,  or,  i)
> > +ATOMIC_OPS(xor, xor,  i)
> 
> ... here you want to only pass the (unary) operator (and leaving that
> blank
> is as fine as using +).
I agree that a game with 'i' and 'I' looks confusing, but I am not
really understand what is wrong with using ' i' here. It seems that
preprocessed macros looks fine:
   static inline void atomic_add(int i, atomic_t *v) { asm volatile ( "  
   amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r" (i) :
   "memory" ); }
   
   static inline void atomic_sub(int i, atomic_t *v) { asm volatile ( "  
   amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r" (-i) :
   "memory" ); }

> 
> > +#undef ATOMIC_OP
> > +#undef ATOMIC_OPS
> > +
> > +#include <asm-generic/atomic-ops.h>
> > +
> > +/*
> > + * Atomic ops that have ordered, relaxed, acquire, and release
> > variants.
> 
> Only the first is implemented afaict; imo the comment would better
> reflect
> that one way or another.
> 
> > + * There's two flavors of these: the arithmatic ops have both
> > fetch and return
> > + * versions, while the logical ops only have fetch versions.
> > + */
> > +#define ATOMIC_FETCH_OP(op, asm_op, I, asm_type, c_type,
> > prefix)    \
> > +static
> > inline                                                       \
> > +c_type atomic##prefix##_fetch_##op##_relaxed(c_type
> > i,              \
> > +                         atomic##prefix##_t
> > *v)                     \
> > +{                                                                 
> >   \
> > +    register c_type
> > ret;                                            \
> > +    asm volatile
> > (                                                  \
> > +        "   amo" #asm_op "." #asm_type " %1, %2,
> > %0"                \
> > +        : "+A" (v->counter), "=r"
> > (ret)                             \
> > +        : "r"
> > (I)                                                   \
> > +        : "memory"
> > );                                               \
> > +    return
> > ret;                                                     \
> > +}                                                                 
> >   \
> 
> Actually a relaxed form is provided here, but does that have any
> user?
There is no user for a relaxed form, just overlooked that.

> 
> > +static
> > inline                                                       \
> > +c_type atomic##prefix##_fetch_##op(c_type i, atomic##prefix##_t
> > *v) \
> > +{                                                                 
> >   \
> > +    register c_type
> > ret;                                            \
> > +    asm volatile
> > (                                                  \
> > +        "   amo" #asm_op "." #asm_type ".aqrl  %1, %2,
> > %0"          \
> > +        : "+A" (v->counter), "=r"
> > (ret)                             \
> > +        : "r"
> > (I)                                                   \
> > +        : "memory"
> > );                                               \
> > +    return
> > ret;                                                     \
> > +}
> > +
> > +#define ATOMIC_OP_RETURN(op, asm_op, c_op, I, asm_type, c_type,
> > prefix) \
> > +static
> > inline                                                           \
> > +c_type atomic##prefix##_##op##_return_relaxed(c_type
> > i,                 \
> > +                          atomic##prefix##_t
> > *v)                        \
> > +{                                                                 
> >       \
> > +        return atomic##prefix##_fetch_##op##_relaxed(i, v) c_op
> > I;      \
> > +}                                                                 
> >       \
> > +static
> > inline                                                           \
> > +c_type atomic##prefix##_##op##_return(c_type i, atomic##prefix##_t
> > *v)  \
> > +{                                                                 
> >       \
> > +        return atomic##prefix##_fetch_##op(i, v) c_op
> > I;                \
> 
> I (or whatever the replacement expression is going to be following
> the
> earlier comment) wants parenthesizing here.
> 
> > +}
> > +
> > +/*
> > + * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is the
> > reason why
> > + * last argument of ATOMIC_FETCH_OP, ATOMIC_OP_RETURN isn't used.
> > + */
> > +#define ATOMIC_OPS(op, asm_op, c_op,
> > I)                                 \
> > +        ATOMIC_FETCH_OP( op, asm_op,       I, w, int,  
> > )               \
> > +        ATOMIC_OP_RETURN(op, asm_op, c_op, I, w, int,   )
> > +
> > +ATOMIC_OPS(add, add, +,  i)
> > +ATOMIC_OPS(sub, add, +, -i)
> > +
> > +#undef ATOMIC_OPS
> > +
> > +#define ATOMIC_OPS(op, asm_op, I) \
> > +        ATOMIC_FETCH_OP(op, asm_op, I, w, int,   )
> > +
> > +ATOMIC_OPS(and, and, i)
> > +ATOMIC_OPS( or,  or, i)
> > +ATOMIC_OPS(xor, xor, i)
> > +
> > +#undef ATOMIC_OPS
> > +
> > +#undef ATOMIC_FETCH_OP
> > +#undef ATOMIC_OP_RETURN
> > +
> > +/* This is required to provide a full barrier on success. */
> > +static inline int atomic_add_unless(atomic_t *v, int a, int u)
> > +{
> > +       int prev, rc;
> > +
> > +    asm volatile (
> > +        "0: lr.w     %[p],  %[c]\n"
> > +        "   beq      %[p],  %[u], 1f\n"
> > +        "   add      %[rc], %[p], %[a]\n"
> > +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
> > +        "   bnez     %[rc], 0b\n"
> > +        RISCV_FULL_BARRIER
> 
> With this and no .aq on the load, why the .rl on the store?
It is something that LKMM requires [1].

This is not fully clear to me what is so specific in LKMM, but accoring
to the spec:
   Ordering Annotation Fence-based Equivalent
   l{b|h|w|d|r}.aq     l{b|h|w|d|r}; fence r,rw
   l{b|h|w|d|r}.aqrl   fence rw,rw; l{b|h|w|d|r}; fence r,rw
   s{b|h|w|d|c}.rl     fence rw,w; s{b|h|w|d|c}
   s{b|h|w|d|c}.aqrl   fence rw,w; s{b|h|w|d|c}
   amo<op>.aq          amo<op>; fence r,rw
   amo<op>.rl          fence rw,w; amo<op>
   amo<op>.aqrl        fence rw,rw; amo<op>; fence rw,rw
   Table 2.2: Mappings from .aq and/or .rl to fence-based equivalents.
   An alternative mapping places a fence rw,rw after the existing 
   s{b|h|w|d|c} mapping rather than at the front of the
   l{b|h|w|d|r} mapping.
   
   It is also safe to translate any .aq, .rl, or .aqrl annotation into
   the fence-based snippets of
   Table 2.2. These can also be used as a legal implementation of
   l{b|h|w|d} or s{b|h|w|d} pseu-
   doinstructions for as long as those instructions are not added to
   the ISA.

So according to the spec, it should be:
 sc.w ...
 RISCV_FULL_BARRIER.

Considering [1] and how this code looks before, it seems to me that it
is safe to use lr.w.aq/sc.w.rl here or an fence equivalent.

But in general it ( a combination of fence, .aq, .rl ) can be
considered as the same things in this context, so it is possible to
leave this function as is to be synced here with Linux kernel.

[1]https://lore.kernel.org/lkml/1520274276-21871-1-git-send-email-parri.andrea@gmail.com/

~ Oleksii

> 
> > +        "1:\n"
> > +        : [p] "=&r" (prev), [rc] "=&r" (rc), [c] "+A" (v->counter)
> > +        : [a] "r" (a), [u] "r" (u)
> > +        : "memory");
> > +    return prev;
> > +}
> > +
> > +/*
> > + * atomic_{cmp,}xchg is required to have exactly the same ordering
> > semantics as
> > + * {cmp,}xchg and the operations that return.
> > + */
> > +#define ATOMIC_OP(c_t, prefix, size)                            \
> > +static inline                                                   \
> > +c_t atomic##prefix##_xchg(atomic##prefix##_t *v, c_t n)         \
> > +{                                                               \
> > +    return __xchg(&(v->counter), n, size);                      \
> 
> No need for the inner parentheses, just like ...
> 
> > +}                                                               \
> > +static inline                                                   \
> > +c_t atomic##prefix##_cmpxchg(atomic##prefix##_t *v, c_t o, c_t n)
> > \
> > +{                                                               \
> > +    return __cmpxchg(&v->counter, o, n, size);                  \
> 
> ... you have it here.
> 
> > +}
> > +
> > +#define ATOMIC_OPS() \
> > +    ATOMIC_OP(int,   , 4)
> > +
> > +ATOMIC_OPS()
> > +
> > +#undef ATOMIC_OPS
> > +#undef ATOMIC_OP
> > +
> > +static inline int atomic_sub_if_positive(atomic_t *v, int offset)
> > +{
> > +       int prev, rc;
> > +
> > +    asm volatile (
> > +        "0: lr.w     %[p],  %[c]\n"
> > +        "   sub      %[rc], %[p], %[o]\n"
> > +        "   bltz     %[rc], 1f\n"
> > +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
> > +        "   bnez     %[rc], 0b\n"
> > +        "   fence    rw, rw\n"
> > +        "1:\n"
> > +        : [p] "=&r" (prev), [rc] "=&r" (rc), [c] "+A" (v->counter)
> > +        : [o] "r" (offset)
> > +        : "memory" );
> > +    return prev - offset;
> > +}
> 
> This probably would be nicer if sitting next to atomic_add_unless().
> 
> > --- /dev/null
> > +++ b/xen/include/asm-generic/atomic-ops.h
> > @@ -0,0 +1,97 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * The header provides default implementations for every
> > xen/atomic.h-provided
> > + * forward inline declaration that can be synthesized from other
> > atomic
> > + * functions.
> 
> Or from scratch, as e.g. ...
> 
> > + */
> > +#ifndef _ASM_GENERIC_ATOMIC_OPS_H_
> > +#define _ASM_GENERIC_ATOMIC_OPS_H_
> > +
> > +#include <xen/atomic.h>
> > +#include <xen/lib.h>
> > +
> > +#ifndef ATOMIC_READ
> > +static inline int atomic_read(const atomic_t *v)
> > +{
> > +    return ACCESS_ONCE(v->counter);
> > +}
> > +#endif
> > +
> > +#ifndef _ATOMIC_READ
> > +static inline int _atomic_read(atomic_t v)
> > +{
> > +    return v.counter;
> > +}
> > +#endif
> > +
> > +#ifndef ATOMIC_SET
> > +static inline void atomic_set(atomic_t *v, int i)
> > +{
> > +    ACCESS_ONCE(v->counter) = i;
> > +}
> > +#endif
> > +
> > +#ifndef _ATOMIC_SET
> > +static inline void _atomic_set(atomic_t *v, int i)
> > +{
> > +    v->counter = i;
> > +}
> > +#endif
> 
> ... all of these.
> 
> > +#ifndef ATOMIC_SUB_AND_TEST
> > +static inline int atomic_sub_and_test(int i, atomic_t *v)
> > +{
> > +    return atomic_sub_return(i, v) == 0;
> > +}
> > +#endif
> > +
> > +#ifndef ATOMIC_INC
> > +static inline void atomic_inc(atomic_t *v)
> > +{
> > +    atomic_add(1, v);
> > +}
> > +#endif
> > +
> > +#ifndef ATOMIC_INC_RETURN
> > +static inline int atomic_inc_return(atomic_t *v)
> > +{
> > +    return atomic_add_return(1, v);
> > +}
> > +#endif
> > +
> > +#ifndef ATOMIC_DEC
> > +static inline void atomic_dec(atomic_t *v)
> > +{
> > +    atomic_sub(1, v);
> > +}
> > +#endif
> > +
> > +#ifndef ATOMIC_DEC_RETURN
> > +static inline int atomic_dec_return(atomic_t *v)
> > +{
> > +    return atomic_sub_return(1, v);
> > +}
> > +#endif
> > +
> > +#ifndef ATOMIC_DEC_AND_TEST
> > +static inline int atomic_dec_and_test(atomic_t *v)
> > +{
> > +    return atomic_sub_return(1, v) == 0;
> > +}
> > +#endif
> > +
> > +#ifndef ATOMIC_ADD_NEGATIVE
> > +static inline int atomic_add_negative(int i, atomic_t *v)
> > +{
> > +    return atomic_add_return(i, v) < 0;
> > +}
> > +#endif
> > +
> > +#ifndef ATOMIC_INC_AND_TEST
> > +static inline int atomic_inc_and_test(atomic_t *v)
> > +{
> > +    return atomic_add_return(1, v) == 0;
> > +}
> > +#endif
> 
> Can this be moved up a little, perhaps next to the other inc-s (or
> else
> next to dec_and_test), please?
> 
> Jan


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

* Re: [PATCH v6 15/20] xen/riscv: add minimal stuff to processor.h to build full Xen
  2024-03-21 13:26   ` Jan Beulich
@ 2024-03-22 12:26     ` Oleksii
  0 siblings, 0 replies; 61+ messages in thread
From: Oleksii @ 2024-03-22 12:26 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Thu, 2024-03-21 at 14:26 +0100, Jan Beulich wrote:
> On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > The cpu_relax() function, introduced in this commit, is anticipated
> > to
> > support _zihintpause by the CPU.
> > 
> > Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
> 
> Acked-by: Jan Beulich <jbeulich@suse.com>
Thanks.

> 
> Looks like this can go in ahead of the other 14 patches?
Yes, it can. I'll rebase it ahead.

~ Oleksii


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

* Re: [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h
  2024-03-22 10:42       ` Jan Beulich
@ 2024-03-22 12:52         ` Oleksii
  0 siblings, 0 replies; 61+ messages in thread
From: Oleksii @ 2024-03-22 12:52 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Fri, 2024-03-22 at 11:42 +0100, Jan Beulich wrote:
> On 22.03.2024 11:32, Oleksii wrote:
> > On Thu, 2024-03-21 at 13:07 +0100, Jan Beulich wrote:
> > > On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > > > The header was taken from Linux kernl 6.4.0-rc1.
> > > > 
> > > > Addionally, were updated:
> > > > * add emulation of {cmp}xchg for 1/2 byte types using 32-bit
> > > > atomic
> > > >   access.
> > > > * replace tabs with spaces
> > > > * replace __* variale with *__
> > > > * introduce generic version of xchg_* and cmpxchg_*.
> > > > * drop {cmp}xchg{release,relaxed,acquire} as Xen doesn't use
> > > > them
> > > 
> > > With this, ...
> > > 
> > > > * drop barries and use instruction suffixices instead ( .aq,
> > > > .rl,
> > > > .aqrl )
> > > > 
> > > > Implementation of 4- and 8-byte cases were updated according to
> > > > the
> > > > spec:
> > > > ```
> > > >               ....
> > > > Linux Construct         RVWMO AMO Mapping
> > > > atomic <op> relaxed     amo<op>.{w|d}
> > > > atomic <op> acquire     amo<op>.{w|d}.aq
> > > > atomic <op> release     amo<op>.{w|d}.rl
> > > > atomic <op>             amo<op>.{w|d}.aqrl
> > > > Linux Construct         RVWMO LR/SC Mapping
> > > > atomic <op> relaxed     loop: lr.{w|d}; <op>; sc.{w|d}; bnez
> > > > loop
> > > > atomic <op> acquire     loop: lr.{w|d}.aq; <op>; sc.{w|d}; bnez
> > > > loop
> > > > atomic <op> release     loop: lr.{w|d}; <op>; sc.{w|d}.aqrl∗ ;
> > > > bnez
> > > > loop OR
> > > >                         fence.tso; loop: lr.{w|d}; <op>;
> > > > sc.{w|d}∗
> > > > ; bnez loop
> > > > atomic <op>             loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl;
> > > > bnez loop
> > > > 
> > > > Table A.5: Mappings from Linux memory primitives to RISC-V
> > > > primitives
> > > > 
> > > > ```
> > > 
> > > ... I consider quoting this table in full, without any further
> > > remarks, as
> > > confusing: Three of the lines each are inapplicable now, aiui.
> > I'll shorten the table then.
> > 
> > > 
> > > Further what are the two * telling us? Quite likely they aren't
> > > there
> > > just
> > > accidentally.
> > > 
> > > Finally, why sc.{w|d}.aqrl when in principle one would expect
> > > just
> > > sc.{w|d}.rl?
> > Because according to the last line of table A.5:
> >     atomic <op>             loop: lr.{w|d}.aq; <op>; sc.{w|d}.aqrl;
> > Here it is used sc.{w|d}.aqrl form, so I decided to stick to the
> > what
> > is mentioned in the table.
> 
> I understand it's mentioned that way in the table. But it being that
> way
> is not explained anywhere. Hence my "Why?"
> 
> > > > +    __typeof__(*(ptr)) old__ = (__typeof__(*(ptr)))(old); \
> > > > +    __typeof__(*(ptr)) new__ = (__typeof__(*(ptr)))(new); \
> > > 
> > > The casts aren't very nice to have here; I take they're needed
> > > for
> > > cmpxchg_ptr() to compile?
> > Not really, I have not faced an compilation issue.
> > The reason why it was added is that lr instruction places the sign-
> > extended value in destination register, but if not to do cast value
> > for
> > old and new were generated without sign extension, so, for example:
> >    u32= 0xbbbbbbbb;
> >    cmpxchg(&u32, 0xbbbbbbbb, 0xCCCCCCCC), u32);
> > Will fail because after:
> >        "0: lr" lr_sfx " %0, %2\n" 
> > in %0 we will have 0xFFFFFFFFBBBBBBBB, but in %3 we will have
> > 0xBBBBBBBB, so
> >        bne  %0, %z3, 1f\n"
> > %0 and %3 are always inequal in case when the most significat bit
> > of
> > value read from %2 has 1.
> 
> I'm afraid I don't follow: It's the type conversion you're after, but
> that would happen also with the casts omitted.
Yes, agree it would happen also with the casts omitted, and it was pure
luck that the compiler that with casts the compiler used an immediate
with the most significant bit = 1:
ffffffffc00397f0:       bbbbc7b7                lui     a5,0xbbbbc
ffffffffc00397f4:       bbb78793                add     a5,a5,-1093 #
ffffffffbbbbbbbb <start-0x4444445>
ffffffffc00397f8:       fef42623                sw      a5,-20(s0)
ffffffffc00397fc:       ccccd737                lui     a4,0xccccd
ffffffffc0039800:       ccc7071b                addw    a4,a4,-820 #
ffffffffcccccccc <__bss_end+0xcc7ff44>
ffffffffc0039804:       56fd                    li      a3,-1
ffffffffc0039806:       9281                    srl     a3,a3,0x20
ffffffffc0039808:       fec40513                add     a0,s0,-20
ffffffffc003980c:       140525af                lr.w.aq a1,(a0)
ffffffffc0039810:       00f59563                bne    
a1,a5,ffffffffc003981a <start_xen+0x4e>
ffffffffc0039814:       1ee5262f                sc.w.aqrl      
a2,a4,(a0)

I will update the code with the mask mentioned below to be sure that a5
has always correct value.

~ Oleksii

> 
> > But now I realized that it would be better just to use a mask and
> > not
> > be dependent from compiler code generation, so it would be better
> > to in
> > the following way ( of course, the macros should be updated
> > accordingly
> > to remarks you give me ):
> >    #define __generic_cmpxchg(ptr, old, new, ret, lr_sfx,
> > sc_sfx)	\
> >     ({ \
> >        register unsigned int rc; \
> >        unsigned long mask = GENMASK(((sizeof(*(ptr))) *
> > BITS_PER_BYTE)
> >    - 1, 0); \
> >        asm volatile( \
> >            "0: lr" lr_sfx " %0, %2\n" \
> >            "   and  %0, %0, %z[mask]\n" \
> >            "   bne  %0, %z3, 1f\n" \
> >            "   sc" sc_sfx " %1, %z4, %2\n" \
> >            "   bnez %1, 0b\n" \
> >            "1:\n" \
> >            : "=&r" (ret), "=&r" (rc), "+A" (*ptr) \
> >            : "rJ" (old), "rJ" (new), [mask] "rJ" (mask)  \
> >            : "memory"); \
> >     })
> 
> It'll be up to you whether to switch to such an alternative.
> 
> Jan



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

* Re: [PATCH v6 09/20] xen/riscv: introduce io.h
  2024-03-22 11:36       ` Jan Beulich
@ 2024-03-22 12:55         ` Oleksii
  0 siblings, 0 replies; 61+ messages in thread
From: Oleksii @ 2024-03-22 12:55 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Fri, 2024-03-22 at 12:36 +0100, Jan Beulich wrote:
> On 22.03.2024 12:02, Oleksii wrote:
> > On Thu, 2024-03-21 at 13:27 +0100, Jan Beulich wrote:
> > > On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > > > --- /dev/null
> > > > +++ b/xen/arch/riscv/include/asm/io.h
> > > > @@ -0,0 +1,167 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0-only */
> > > > +/*
> > > > + *  The header taken form Linux 6.4.0-rc1 and is based on
> > > > + *  arch/riscv/include/asm/mmio.h with the following changes:
> > > > + *   - drop forcing of endianess for read*(), write*()
> > > > functions
> > > > as
> > > > + *     no matter what CPU endianness, what endianness a
> > > > particular
> > > > device
> > > > + *     (and hence its MMIO region(s)) is using is entirely
> > > > independent.
> > > > + *     Hence conversion, where necessary, needs to occur at a
> > > > layer up.
> > > > + *     Another one reason to drop endianess conversion is:
> > > > + *    
> > > > https://patchwork.kernel.org/project/linux-riscv/patch/20190411115623.5749-3-hch@lst.de/
> > > > + *     One of the answers of the author of the commit:
> > > > + *       And we don't know if Linux will be around if that
> > > > ever
> > > > changes.
> > > > + *       The point is:
> > > > + *        a) the current RISC-V spec is LE only
> > > > + *        b) the current linux port is LE only except for this
> > > > little bit
> > > > + *       There is no point in leaving just this bitrotting
> > > > code
> > > > around.  It
> > > > + *       just confuses developers, (very very slightly) slows
> > > > down
> > > > compiles
> > > > + *      and will bitrot.  It also won't be any significant
> > > > help to
> > > > a future
> > > > + *       developer down the road doing a hypothetical BE RISC-
> > > > V
> > > > Linux port.
> > > > + *   - drop unused argument of __io_ar() macros.
> > > > + *   - drop "#define _raw_{read,write}{b,w,l,d,q}
> > > > _raw_{read,write}{b,w,l,d,q}"
> > > 
> > > In the commit message I'm not worried as much, but at least here
> > > the
> > > odd mention
> > > of d as suffixes would better be purged.
> > Probably, I use incorrect words, but what I meant that it was
> > dropped:
> >    #define _raw_{read,write}{b,w,l,d,q}
> > _raw_{read,write}{b,w,l,d,q}
> > before declaration/definition of inline functions (
> > __raw_{read,write}{b,w,l,d,q} ).
> 
> But where did you find a raw_readd() or raw_writed() (with no matter
> how
> many leading underscores)?
Oh, {d} options didn't exist. Missed that, wrote it automatically.
Thanks I'll update the commit message and the header comment.

~ Oleksii


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

* Re: [PATCH v6 10/20] xen/riscv: introduce atomic.h
  2024-03-22 12:25     ` Oleksii
@ 2024-03-25  8:18       ` Jan Beulich
  2024-03-26 19:02         ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-25  8:18 UTC (permalink / raw)
  To: Oleksii
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 22.03.2024 13:25, Oleksii wrote:
> On Thu, 2024-03-21 at 14:03 +0100, Jan Beulich wrote:
>> On 15.03.2024 19:06, Oleksii Kurochko wrote:
>>> + */
>>> +static always_inline void read_atomic_size(const volatile void *p,
>>> +                                           void *res,
>>> +                                           unsigned int size)
>>> +{
>>> +    switch ( size )
>>> +    {
>>> +    case 1: *(uint8_t *)res = readb(p); break;
>>> +    case 2: *(uint16_t *)res = readw(p); break;
>>> +    case 4: *(uint32_t *)res = readl(p); break;
>>> +    case 8: *(uint32_t *)res  = readq(p); break;
>>
>> Nit: Excess blank before =.
>>
>> Also - no #ifdef here to be RV32-ready?
> Because there is #ifdef RV32 in io.h for readq().

There you'd run into __raw_readq()'s BUILD_BUG_ON(), afaict even for
1-, 2-, or 4-byte accesses. That's not quite what we want here.

>>> +/*
>>> + * First, the atomic ops that have no ordering constraints and
>>> therefor don't
>>> + * have the AQ or RL bits set.  These don't return anything, so
>>> there's only
>>> + * one version to worry about.
>>> + */
>>> +#define ATOMIC_OP(op, asm_op, I, asm_type, c_type, prefix)  \
>>> +static inline                                               \
>>> +void atomic##prefix##_##op(c_type i, atomic##prefix##_t *v) \
>>> +{                                                           \
>>> +    asm volatile (                                          \
>>> +        "   amo" #asm_op "." #asm_type " zero, %1, %0"      \
>>> +        : "+A" (v->counter)                                 \
>>> +        : "r" (I)                                           \
>>
>> Btw, I consider this pretty confusing. At the 1st and 2nd glance this
>> looks like a mistake, i.e. as if i was meant. Imo ...
>>
>>> +        : "memory" );                                       \
>>> +}                                                           \
>>> +
>>> +/*
>>> + * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is the
>>> reason why
>>> + * last argument for ATOMIC_OP isn't used.
>>> + */
>>> +#define ATOMIC_OPS(op, asm_op, I)                           \
>>> +        ATOMIC_OP (op, asm_op, I, w, int,   )
>>> +
>>> +ATOMIC_OPS(add, add,  i)
>>> +ATOMIC_OPS(sub, add, -i)
>>> +ATOMIC_OPS(and, and,  i)
>>> +ATOMIC_OPS( or,  or,  i)
>>> +ATOMIC_OPS(xor, xor,  i)
>>
>> ... here you want to only pass the (unary) operator (and leaving that
>> blank
>> is as fine as using +).
> I agree that a game with 'i' and 'I' looks confusing, but I am not
> really understand what is wrong with using ' i' here. It seems that
> preprocessed macros looks fine:
>    static inline void atomic_add(int i, atomic_t *v) { asm volatile ( "  
>    amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r" (i) :
>    "memory" ); }
>    
>    static inline void atomic_sub(int i, atomic_t *v) { asm volatile ( "  
>    amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r" (-i) :
>    "memory" ); }

I didn't question the pre-processed result being correct. Instead I said
that I consider the construct confusing to the reader, for looking as if
there was a mistake (in the case of the letter i used). Note also in
particular how the macro invocations need to be in sync with the macro
implementation, for lower case i being used both in the macro and in its
invocations. Anything parameterized would better be fully so, at the
very least to avoid, as said, confusion. (Having macros depend on
context at their use sites _may_ be okay for local helper macros, but
here we're talking about a not even private header file.)

>>> +/* This is required to provide a full barrier on success. */
>>> +static inline int atomic_add_unless(atomic_t *v, int a, int u)
>>> +{
>>> +       int prev, rc;
>>> +
>>> +    asm volatile (
>>> +        "0: lr.w     %[p],  %[c]\n"
>>> +        "   beq      %[p],  %[u], 1f\n"
>>> +        "   add      %[rc], %[p], %[a]\n"
>>> +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
>>> +        "   bnez     %[rc], 0b\n"
>>> +        RISCV_FULL_BARRIER
>>
>> With this and no .aq on the load, why the .rl on the store?
> It is something that LKMM requires [1].
> 
> This is not fully clear to me what is so specific in LKMM, but accoring
> to the spec:
>    Ordering Annotation Fence-based Equivalent
>    l{b|h|w|d|r}.aq     l{b|h|w|d|r}; fence r,rw
>    l{b|h|w|d|r}.aqrl   fence rw,rw; l{b|h|w|d|r}; fence r,rw
>    s{b|h|w|d|c}.rl     fence rw,w; s{b|h|w|d|c}
>    s{b|h|w|d|c}.aqrl   fence rw,w; s{b|h|w|d|c}
>    amo<op>.aq          amo<op>; fence r,rw
>    amo<op>.rl          fence rw,w; amo<op>
>    amo<op>.aqrl        fence rw,rw; amo<op>; fence rw,rw
>    Table 2.2: Mappings from .aq and/or .rl to fence-based equivalents.
>    An alternative mapping places a fence rw,rw after the existing 
>    s{b|h|w|d|c} mapping rather than at the front of the
>    l{b|h|w|d|r} mapping.

I'm afraid I can't spot the specific case in this table. None of the
stores in the right column have a .rl suffix.

>    It is also safe to translate any .aq, .rl, or .aqrl annotation into
>    the fence-based snippets of
>    Table 2.2. These can also be used as a legal implementation of
>    l{b|h|w|d} or s{b|h|w|d} pseu-
>    doinstructions for as long as those instructions are not added to
>    the ISA.
> 
> So according to the spec, it should be:
>  sc.w ...
>  RISCV_FULL_BARRIER.
> 
> Considering [1] and how this code looks before, it seems to me that it
> is safe to use lr.w.aq/sc.w.rl here or an fence equivalent.

Here you say "or". Then why dos the code use sc.?.rl _and_ a fence?

> But in general it ( a combination of fence, .aq, .rl ) can be
> considered as the same things in this context, so it is possible to
> leave this function as is to be synced here with Linux kernel.

In turn I also don't understand this. Yes, the excess .rl certainly
doesn't render things unsafe. But what's the purpose of the .rl? That's
what my original question boiled down to.

Jan

> [1]https://lore.kernel.org/lkml/1520274276-21871-1-git-send-email-parri.andrea@gmail.com/
> 
> ~ Oleksii



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

* Re: [PATCH v6 10/20] xen/riscv: introduce atomic.h
  2024-03-25  8:18       ` Jan Beulich
@ 2024-03-26 19:02         ` Oleksii
  2024-03-26 21:24           ` Oleksii
  2024-03-27  7:40           ` Jan Beulich
  0 siblings, 2 replies; 61+ messages in thread
From: Oleksii @ 2024-03-26 19:02 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Mon, 2024-03-25 at 09:18 +0100, Jan Beulich wrote:
> On 22.03.2024 13:25, Oleksii wrote:
> > On Thu, 2024-03-21 at 14:03 +0100, Jan Beulich wrote:
> > > On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > > > + */
> > > > +static always_inline void read_atomic_size(const volatile void
> > > > *p,
> > > > +                                           void *res,
> > > > +                                           unsigned int size)
> > > > +{
> > > > +    switch ( size )
> > > > +    {
> > > > +    case 1: *(uint8_t *)res = readb(p); break;
> > > > +    case 2: *(uint16_t *)res = readw(p); break;
> > > > +    case 4: *(uint32_t *)res = readl(p); break;
> > > > +    case 8: *(uint32_t *)res  = readq(p); break;
> > > 
> > > Nit: Excess blank before =.
> > > 
> > > Also - no #ifdef here to be RV32-ready?
> > Because there is #ifdef RV32 in io.h for readq().
> 
> There you'd run into __raw_readq()'s BUILD_BUG_ON(), afaict even for
> 1-, 2-, or 4-byte accesses. That's not quite what we want here.
Do you mean that if someone will redefine readq() in another way and
not wrap it by #ifdef RV32? Except this I am not sure that there is an
issue as it will be still a compilation error, so anyway it will be
needed to provide an implementation for __raw_readq().

One of the reason why I decided to wrap with #ifdef RV32 in io.h to not
go over the source code and add wrapping. Also for some code it will be
needed to rewrite it. For example, I am not sure that I can add #ifdef
inside macros, f.e.:
   #define write_atomic(p, x)                              \
   ({                                                      \
       typeof(*(p)) x__ = (x);                             \
       switch ( sizeof(*(p)) )                             \
       {                                                   \
       case 1: writeb(x__, p); break;                      \
       case 2: writew(x__, p); break;                      \
       case 4: writel(x__, p); break;                      \
       case 8: writeq(x__, p); break;                      \
       default: __bad_atomic_size(); break;                \
       }                                                   \
       x__;                                                \
   })

> 
> > > > +/*
> > > > + * First, the atomic ops that have no ordering constraints and
> > > > therefor don't
> > > > + * have the AQ or RL bits set.  These don't return anything,
> > > > so
> > > > there's only
> > > > + * one version to worry about.
> > > > + */
> > > > +#define ATOMIC_OP(op, asm_op, I, asm_type, c_type, prefix)  \
> > > > +static inline                                               \
> > > > +void atomic##prefix##_##op(c_type i, atomic##prefix##_t *v) \
> > > > +{                                                           \
> > > > +    asm volatile (                                          \
> > > > +        "   amo" #asm_op "." #asm_type " zero, %1, %0"      \
> > > > +        : "+A" (v->counter)                                 \
> > > > +        : "r" (I)                                           \
> > > 
> > > Btw, I consider this pretty confusing. At the 1st and 2nd glance
> > > this
> > > looks like a mistake, i.e. as if i was meant. Imo ...
> > > 
> > > > +        : "memory" );                                       \
> > > > +}                                                           \
> > > > +
> > > > +/*
> > > > + * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is
> > > > the
> > > > reason why
> > > > + * last argument for ATOMIC_OP isn't used.
> > > > + */
> > > > +#define ATOMIC_OPS(op, asm_op, I)                           \
> > > > +        ATOMIC_OP (op, asm_op, I, w, int,   )
> > > > +
> > > > +ATOMIC_OPS(add, add,  i)
> > > > +ATOMIC_OPS(sub, add, -i)
> > > > +ATOMIC_OPS(and, and,  i)
> > > > +ATOMIC_OPS( or,  or,  i)
> > > > +ATOMIC_OPS(xor, xor,  i)
> > > 
> > > ... here you want to only pass the (unary) operator (and leaving
> > > that
> > > blank
> > > is as fine as using +).
> > I agree that a game with 'i' and 'I' looks confusing, but I am not
> > really understand what is wrong with using ' i' here. It seems that
> > preprocessed macros looks fine:
> >    static inline void atomic_add(int i, atomic_t *v) { asm volatile
> > ( "  
> >    amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r" (i)
> > :
> >    "memory" ); }
> >    
> >    static inline void atomic_sub(int i, atomic_t *v) { asm volatile
> > ( "  
> >    amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r" (-
> > i) :
> >    "memory" ); }
> 
> I didn't question the pre-processed result being correct. Instead I
> said
> that I consider the construct confusing to the reader, for looking as
> if
> there was a mistake (in the case of the letter i used). Note also in
> particular how the macro invocations need to be in sync with the
> macro
> implementation, for lower case i being used both in the macro and in
> its
> invocations. Anything parameterized would better be fully so, at the
> very least to avoid, as said, confusion. (Having macros depend on
> context at their use sites _may_ be okay for local helper macros, but
> here we're talking about a not even private header file.)
I am not sure then I understand how mentioning '+i' will help
significantly remove confusion.

> 
> > > > +/* This is required to provide a full barrier on success. */
> > > > +static inline int atomic_add_unless(atomic_t *v, int a, int u)
> > > > +{
> > > > +       int prev, rc;
> > > > +
> > > > +    asm volatile (
> > > > +        "0: lr.w     %[p],  %[c]\n"
> > > > +        "   beq      %[p],  %[u], 1f\n"
> > > > +        "   add      %[rc], %[p], %[a]\n"
> > > > +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
> > > > +        "   bnez     %[rc], 0b\n"
> > > > +        RISCV_FULL_BARRIER
> > > 
> > > With this and no .aq on the load, why the .rl on the store?
> > It is something that LKMM requires [1].
> > 
> > This is not fully clear to me what is so specific in LKMM, but
> > accoring
> > to the spec:
> >    Ordering Annotation Fence-based Equivalent
> >    l{b|h|w|d|r}.aq     l{b|h|w|d|r}; fence r,rw
> >    l{b|h|w|d|r}.aqrl   fence rw,rw; l{b|h|w|d|r}; fence r,rw
> >    s{b|h|w|d|c}.rl     fence rw,w; s{b|h|w|d|c}
> >    s{b|h|w|d|c}.aqrl   fence rw,w; s{b|h|w|d|c}
> >    amo<op>.aq          amo<op>; fence r,rw
> >    amo<op>.rl          fence rw,w; amo<op>
> >    amo<op>.aqrl        fence rw,rw; amo<op>; fence rw,rw
> >    Table 2.2: Mappings from .aq and/or .rl to fence-based
> > equivalents.
> >    An alternative mapping places a fence rw,rw after the existing 
> >    s{b|h|w|d|c} mapping rather than at the front of the
> >    l{b|h|w|d|r} mapping.
> 
> I'm afraid I can't spot the specific case in this table. None of the
> stores in the right column have a .rl suffix.
Yes, it is expected.

I am reading this table as (f.e.) amo<op>.rl is an equivalent of fence
rw,w; amo<op>. (without .rl) 

> 
> >    It is also safe to translate any .aq, .rl, or .aqrl annotation
> > into
> >    the fence-based snippets of
> >    Table 2.2. These can also be used as a legal implementation of
> >    l{b|h|w|d} or s{b|h|w|d} pseu-
> >    doinstructions for as long as those instructions are not added
> > to
> >    the ISA.
> > 
> > So according to the spec, it should be:
> >  sc.w ...
> >  RISCV_FULL_BARRIER.
> > 
> > Considering [1] and how this code looks before, it seems to me that
> > it
> > is safe to use lr.w.aq/sc.w.rl here or an fence equivalent.
> 
> Here you say "or". Then why dos the code use sc.?.rl _and_ a fence?
I confused this line with amo<op>.aqrl, so based on the table 2.2 above
s{b|h|w|d|c}.aqrl is transformed to "fence rw,w; s{b|h|w|d|c}", but
Linux kernel decided to strengthen it with full barrier:
   -              "0:\n\t"
   -              "lr.w.aqrl  %[p],  %[c]\n\t"
   -              "beq        %[p],  %[u], 1f\n\t"
   -              "add       %[rc],  %[p], %[a]\n\t"
   -              "sc.w.aqrl %[rc], %[rc], %[c]\n\t"
   -              "bnez      %[rc], 0b\n\t"
   -              "1:"
   +               "0:     lr.w     %[p],  %[c]\n"
   +               "       beq      %[p],  %[u], 1f\n"
   +               "       add      %[rc], %[p], %[a]\n"
   +               "       sc.w.rl  %[rc], %[rc], %[c]\n"
   +               "       bnez     %[rc], 0b\n"
   +               "       fence    rw, rw\n"
   +               "1:\n"
As they have the following issue:
   implementations of atomics such as atomic_cmpxchg() and
   atomic_add_unless() rely on LR/SC pairs,
   which do not give full-ordering with .aqrl; for example, current
   implementations allow the "lr-sc-aqrl-pair-vs-full-barrier" test
   below to end up with the state indicated in the "exists" clause.

> 
> > But in general it ( a combination of fence, .aq, .rl ) can be
> > considered as the same things in this context, so it is possible to
> > leave this function as is to be synced here with Linux kernel.
> 
> In turn I also don't understand this. Yes, the excess .rl certainly
> doesn't render things unsafe. But what's the purpose of the .rl?
> That's
> what my original question boiled down to.
I don't know, either. As I mentioned before, it is enough ( in my
opinion ) to have a FULL barrier or .aq,.rl or .aqrl/.aqrl ( if it
needed to be strengthened) like it was done before in Linux.
It seems to me it is LKMM specific that they need more to be more
strengthened as it RISC-V Memory model requires because:
"sc.w ; fence rw, rw" does not guarantee that all previous reads and
writes finish before the sc itself is globally visible, which might
matter if the sc is unlocking a lock or something.

Despite of the fact, for compare-and-swap loops, RISC-V international
recommends lr.w.aq/lr.d.aq followed by sc.w.rl/sc.d.rl ( as it was
implemeted before in Linux kernel ) I am okay just for safety reasons
and for the reason I mentioned at the last sentence of previous
paragraph to strengthen implementations with fences.

~ Oleksii
> 
> Jan
> 
> > [1]
> > https://lore.kernel.org/lkml/1520274276-21871-1-git-send-email-parri.andrea@gmail.com
> > /
> > 
> > ~ Oleksii
> 



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

* Re: [PATCH v6 10/20] xen/riscv: introduce atomic.h
  2024-03-26 19:02         ` Oleksii
@ 2024-03-26 21:24           ` Oleksii
  2024-03-27  7:40           ` Jan Beulich
  1 sibling, 0 replies; 61+ messages in thread
From: Oleksii @ 2024-03-26 21:24 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Tue, 2024-03-26 at 20:02 +0100, Oleksii wrote:
> On Mon, 2024-03-25 at 09:18 +0100, Jan Beulich wrote:
> > On 22.03.2024 13:25, Oleksii wrote:
> > > On Thu, 2024-03-21 at 14:03 +0100, Jan Beulich wrote:
> > > > On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > > > > + */
> > > > > +static always_inline void read_atomic_size(const volatile
> > > > > void
> > > > > *p,
> > > > > +                                           void *res,
> > > > > +                                           unsigned int
> > > > > size)
> > > > > +{
> > > > > +    switch ( size )
> > > > > +    {
> > > > > +    case 1: *(uint8_t *)res = readb(p); break;
> > > > > +    case 2: *(uint16_t *)res = readw(p); break;
> > > > > +    case 4: *(uint32_t *)res = readl(p); break;
> > > > > +    case 8: *(uint32_t *)res  = readq(p); break;
> > > > 
> > > > Nit: Excess blank before =.
> > > > 
> > > > Also - no #ifdef here to be RV32-ready?
> > > Because there is #ifdef RV32 in io.h for readq().
> > 
> > There you'd run into __raw_readq()'s BUILD_BUG_ON(), afaict even
> > for
> > 1-, 2-, or 4-byte accesses. That's not quite what we want here.
> Do you mean that if someone will redefine readq() in another way and
> not wrap it by #ifdef RV32? Except this I am not sure that there is
> an
> issue as it will be still a compilation error, so anyway it will be
> needed to provide an implementation for __raw_readq().
> 
> One of the reason why I decided to wrap with #ifdef RV32 in io.h to
> not
> go over the source code and add wrapping. Also for some code it will
> be
> needed to rewrite it. For example, I am not sure that I can add
> #ifdef
> inside macros, f.e.:
>    #define write_atomic(p, x)                              \
>    ({                                                      \
>        typeof(*(p)) x__ = (x);                             \
>        switch ( sizeof(*(p)) )                             \
>        {                                                   \
>        case 1: writeb(x__, p); break;                      \
>        case 2: writew(x__, p); break;                      \
>        case 4: writel(x__, p); break;                      \
>        case 8: writeq(x__, p); break;                      \
>        default: __bad_atomic_size(); break;                \
>        }                                                   \
>        x__;                                                \
>    })
> 
> > 
> > > > > +/*
> > > > > + * First, the atomic ops that have no ordering constraints
> > > > > and
> > > > > therefor don't
> > > > > + * have the AQ or RL bits set.  These don't return anything,
> > > > > so
> > > > > there's only
> > > > > + * one version to worry about.
> > > > > + */
> > > > > +#define ATOMIC_OP(op, asm_op, I, asm_type, c_type, prefix) 
> > > > > \
> > > > > +static inline                                              
> > > > > \
> > > > > +void atomic##prefix##_##op(c_type i, atomic##prefix##_t *v)
> > > > > \
> > > > > +{                                                          
> > > > > \
> > > > > +    asm volatile (                                         
> > > > > \
> > > > > +        "   amo" #asm_op "." #asm_type " zero, %1, %0"     
> > > > > \
> > > > > +        : "+A" (v->counter)                                
> > > > > \
> > > > > +        : "r" (I)                                          
> > > > > \
> > > > 
> > > > Btw, I consider this pretty confusing. At the 1st and 2nd
> > > > glance
> > > > this
> > > > looks like a mistake, i.e. as if i was meant. Imo ...
> > > > 
> > > > > +        : "memory" );                                      
> > > > > \
> > > > > +}                                                          
> > > > > \
> > > > > +
> > > > > +/*
> > > > > + * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is
> > > > > the
> > > > > reason why
> > > > > + * last argument for ATOMIC_OP isn't used.
> > > > > + */
> > > > > +#define ATOMIC_OPS(op, asm_op, I)                          
> > > > > \
> > > > > +        ATOMIC_OP (op, asm_op, I, w, int,   )
> > > > > +
> > > > > +ATOMIC_OPS(add, add,  i)
> > > > > +ATOMIC_OPS(sub, add, -i)
> > > > > +ATOMIC_OPS(and, and,  i)
> > > > > +ATOMIC_OPS( or,  or,  i)
> > > > > +ATOMIC_OPS(xor, xor,  i)
> > > > 
> > > > ... here you want to only pass the (unary) operator (and
> > > > leaving
> > > > that
> > > > blank
> > > > is as fine as using +).
> > > I agree that a game with 'i' and 'I' looks confusing, but I am
> > > not
> > > really understand what is wrong with using ' i' here. It seems
> > > that
> > > preprocessed macros looks fine:
> > >    static inline void atomic_add(int i, atomic_t *v) { asm
> > > volatile
> > > ( "  
> > >    amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r"
> > > (i)
> > > :
> > >    "memory" ); }
> > >    
> > >    static inline void atomic_sub(int i, atomic_t *v) { asm
> > > volatile
> > > ( "  
> > >    amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r"
> > > (-
> > > i) :
> > >    "memory" ); }
> > 
> > I didn't question the pre-processed result being correct. Instead I
> > said
> > that I consider the construct confusing to the reader, for looking
> > as
> > if
> > there was a mistake (in the case of the letter i used). Note also
> > in
> > particular how the macro invocations need to be in sync with the
> > macro
> > implementation, for lower case i being used both in the macro and
> > in
> > its
> > invocations. Anything parameterized would better be fully so, at
> > the
> > very least to avoid, as said, confusion. (Having macros depend on
> > context at their use sites _may_ be okay for local helper macros,
> > but
> > here we're talking about a not even private header file.)
> I am not sure then I understand how mentioning '+i' will help
> significantly remove confusion.
> 
> > 
> > > > > +/* This is required to provide a full barrier on success. */
> > > > > +static inline int atomic_add_unless(atomic_t *v, int a, int
> > > > > u)
> > > > > +{
> > > > > +       int prev, rc;
> > > > > +
> > > > > +    asm volatile (
> > > > > +        "0: lr.w     %[p],  %[c]\n"
> > > > > +        "   beq      %[p],  %[u], 1f\n"
> > > > > +        "   add      %[rc], %[p], %[a]\n"
> > > > > +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
> > > > > +        "   bnez     %[rc], 0b\n"
> > > > > +        RISCV_FULL_BARRIER
> > > > 
> > > > With this and no .aq on the load, why the .rl on the store?
> > > It is something that LKMM requires [1].
> > > 
> > > This is not fully clear to me what is so specific in LKMM, but
> > > accoring
> > > to the spec:
> > >    Ordering Annotation Fence-based Equivalent
> > >    l{b|h|w|d|r}.aq     l{b|h|w|d|r}; fence r,rw
> > >    l{b|h|w|d|r}.aqrl   fence rw,rw; l{b|h|w|d|r}; fence r,rw
> > >    s{b|h|w|d|c}.rl     fence rw,w; s{b|h|w|d|c}
> > >    s{b|h|w|d|c}.aqrl   fence rw,w; s{b|h|w|d|c}
> > >    amo<op>.aq          amo<op>; fence r,rw
> > >    amo<op>.rl          fence rw,w; amo<op>
> > >    amo<op>.aqrl        fence rw,rw; amo<op>; fence rw,rw
> > >    Table 2.2: Mappings from .aq and/or .rl to fence-based
> > > equivalents.
> > >    An alternative mapping places a fence rw,rw after the existing
> > >    s{b|h|w|d|c} mapping rather than at the front of the
> > >    l{b|h|w|d|r} mapping.
> > 
> > I'm afraid I can't spot the specific case in this table. None of
> > the
> > stores in the right column have a .rl suffix.
> Yes, it is expected.
> 
> I am reading this table as (f.e.) amo<op>.rl is an equivalent of
> fence
> rw,w; amo<op>. (without .rl) 
> 
> > 
> > >    It is also safe to translate any .aq, .rl, or .aqrl annotation
> > > into
> > >    the fence-based snippets of
> > >    Table 2.2. These can also be used as a legal implementation of
> > >    l{b|h|w|d} or s{b|h|w|d} pseu-
> > >    doinstructions for as long as those instructions are not added
> > > to
> > >    the ISA.
> > > 
> > > So according to the spec, it should be:
> > >  sc.w ...
> > >  RISCV_FULL_BARRIER.
> > > 
> > > Considering [1] and how this code looks before, it seems to me
> > > that
> > > it
> > > is safe to use lr.w.aq/sc.w.rl here or an fence equivalent.
> > 
> > Here you say "or". Then why dos the code use sc.?.rl _and_ a fence?
> I confused this line with amo<op>.aqrl, so based on the table 2.2
> above
> s{b|h|w|d|c}.aqrl is transformed to "fence rw,w; s{b|h|w|d|c}", but
> Linux kernel decided to strengthen it with full barrier:
>    -              "0:\n\t"
>    -              "lr.w.aqrl  %[p],  %[c]\n\t"
>    -              "beq        %[p],  %[u], 1f\n\t"
>    -              "add       %[rc],  %[p], %[a]\n\t"
>    -              "sc.w.aqrl %[rc], %[rc], %[c]\n\t"
>    -              "bnez      %[rc], 0b\n\t"
>    -              "1:"
>    +               "0:     lr.w     %[p],  %[c]\n"
>    +               "       beq      %[p],  %[u], 1f\n"
>    +               "       add      %[rc], %[p], %[a]\n"
>    +               "       sc.w.rl  %[rc], %[rc], %[c]\n"
>    +               "       bnez     %[rc], 0b\n"
>    +               "       fence    rw, rw\n"
>    +               "1:\n"
> As they have the following issue:
>    implementations of atomics such as atomic_cmpxchg() and
>    atomic_add_unless() rely on LR/SC pairs,
>    which do not give full-ordering with .aqrl; for example, current
>    implementations allow the "lr-sc-aqrl-pair-vs-full-barrier" test
>    below to end up with the state indicated in the "exists" clause.
> 
> > 
> > > But in general it ( a combination of fence, .aq, .rl ) can be
> > > considered as the same things in this context, so it is possible
> > > to
> > > leave this function as is to be synced here with Linux kernel.
> > 
> > In turn I also don't understand this. Yes, the excess .rl certainly
> > doesn't render things unsafe. But what's the purpose of the .rl?
> > That's
> > what my original question boiled down to.
> I don't know, either. As I mentioned before, it is enough ( in my
> opinion ) to have a FULL barrier or .aq,.rl or .aqrl/.aqrl ( if it
> needed to be strengthened) like it was done before in Linux.
> It seems to me it is LKMM specific that they need more to be more
> strengthened as it RISC-V Memory model requires because:
> "sc.w ; fence rw, rw" does not guarantee that all previous reads and
> writes finish before the sc itself is globally visible, which might
> matter if the sc is unlocking a lock or something.
> 
> Despite of the fact, for compare-and-swap loops, RISC-V international
> recommends lr.w.aq/lr.d.aq followed by sc.w.rl/sc.d.rl ( as it was
> implemeted before in Linux kernel ) I am okay just for safety reasons
> and for the reason I mentioned at the last sentence of previous
> paragraph to strengthen implementations with fences.
Regarding the necessity of fence rw,rw, there is a commit that is proposingto remove fences: [2].
Additionally, it seems there is another reason why the fences were
added.
At the time when the patch introducing the usage of fences was
implemented,
there were no rules in RVWMO which allowed ld.aq+sc.aqrl to be
considered
as a full barrier [3].
   > > note that Model 2018 explicitly says that "ld.aq+sc.aqrl" is
   ordered
   > > against "earlier or later memory operations from the same hart",
   and
   > > this statement was not in Model 2017.
   > > 
   > > So my understanding of the story is that at some point between
   March and
   > > May 2018, RISV memory model folks decided to add this rule,
which
   does
   > > look more consistent with other parts of the model and is
useful.
   > > 
   > > And this is why (and when) "ld.aq+sc.aqrl" can be used as a
fully-
   ordered
   > > barrier ;-)
   > > 
   > > Now if my understanding is correct, to move forward, it's better
   that 1)
   > > this patch gets resend with the above information (better
rewording
   a
   > > bit), and 2) gets an Acked-by from Dan to confirm this is a
correct
   > > history ;-)

Based on patch [2], it may be possible to remove the full barrier and
switch from sc..rl to sc..aqrl. However, I need to finish reading the
Linux kernel mailing thread to understand why a similar change wasn't
made for the lr instruction ( lr -> lr.aq or lr.aqrl as it was before
).

Does that make sense to you?

[2]
https://lore.kernel.org/linux-riscv/20220505035526.2974382-6-guoren@kernel.org/
[3]https://lore.kernel.org/linux-riscv/YrSo%2F3iUuO0AL76T@boqun-archlinux/

~ Oleksii
> 
> ~ Oleksii
> > 
> > Jan
> > 
> > > [1]
> > >
https://lore.kernel.org/lkml/1520274276-21871-1-git-send-email-parri.andrea@gmail.com
> > > /
> > > 
> > > ~ Oleksii
> > 
> 



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

* Re: [PATCH v6 10/20] xen/riscv: introduce atomic.h
  2024-03-26 19:02         ` Oleksii
  2024-03-26 21:24           ` Oleksii
@ 2024-03-27  7:40           ` Jan Beulich
  2024-03-27 10:28             ` Oleksii
  1 sibling, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-03-27  7:40 UTC (permalink / raw)
  To: Oleksii
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 26.03.2024 20:02, Oleksii wrote:
> On Mon, 2024-03-25 at 09:18 +0100, Jan Beulich wrote:
>> On 22.03.2024 13:25, Oleksii wrote:
>>> On Thu, 2024-03-21 at 14:03 +0100, Jan Beulich wrote:
>>>> On 15.03.2024 19:06, Oleksii Kurochko wrote:
>>>>> + */
>>>>> +static always_inline void read_atomic_size(const volatile void
>>>>> *p,
>>>>> +                                           void *res,
>>>>> +                                           unsigned int size)
>>>>> +{
>>>>> +    switch ( size )
>>>>> +    {
>>>>> +    case 1: *(uint8_t *)res = readb(p); break;
>>>>> +    case 2: *(uint16_t *)res = readw(p); break;
>>>>> +    case 4: *(uint32_t *)res = readl(p); break;
>>>>> +    case 8: *(uint32_t *)res  = readq(p); break;
>>>>
>>>> Nit: Excess blank before =.
>>>>
>>>> Also - no #ifdef here to be RV32-ready?
>>> Because there is #ifdef RV32 in io.h for readq().
>>
>> There you'd run into __raw_readq()'s BUILD_BUG_ON(), afaict even for
>> 1-, 2-, or 4-byte accesses. That's not quite what we want here.
> Do you mean that if someone will redefine readq() in another way and
> not wrap it by #ifdef RV32? Except this I am not sure that there is an
> issue as it will be still a compilation error, so anyway it will be
> needed to provide an implementation for __raw_readq().

No. BUILD_BUG_ON() is a compile-time thing. The compiler will encounter
this construct. And hence it will necessarily fail. Which is why the
other approach (causing a linker error) is used elsewhere. And we're
still only in the course of considering to utilize DCE for something
like STATIC_ASSERT_UNREACHABLE(); iirc there was something getting in
the way there.

> One of the reason why I decided to wrap with #ifdef RV32 in io.h to not
> go over the source code and add wrapping. Also for some code it will be
> needed to rewrite it. For example, I am not sure that I can add #ifdef
> inside macros, f.e.:
>    #define write_atomic(p, x)                              \
>    ({                                                      \
>        typeof(*(p)) x__ = (x);                             \
>        switch ( sizeof(*(p)) )                             \
>        {                                                   \
>        case 1: writeb(x__, p); break;                      \
>        case 2: writew(x__, p); break;                      \
>        case 4: writel(x__, p); break;                      \
>        case 8: writeq(x__, p); break;                      \
>        default: __bad_atomic_size(); break;                \
>        }                                                   \
>        x__;                                                \
>    })

You can't add #ifdef there. Such needs abstracting differently.

But of course there's the option of simply not making any of these
constructs RV32-ready. Yet if so, that then will want doing
consistently.

>>>>> +/*
>>>>> + * First, the atomic ops that have no ordering constraints and
>>>>> therefor don't
>>>>> + * have the AQ or RL bits set.  These don't return anything,
>>>>> so
>>>>> there's only
>>>>> + * one version to worry about.
>>>>> + */
>>>>> +#define ATOMIC_OP(op, asm_op, I, asm_type, c_type, prefix)  \
>>>>> +static inline                                               \
>>>>> +void atomic##prefix##_##op(c_type i, atomic##prefix##_t *v) \
>>>>> +{                                                           \
>>>>> +    asm volatile (                                          \
>>>>> +        "   amo" #asm_op "." #asm_type " zero, %1, %0"      \
>>>>> +        : "+A" (v->counter)                                 \
>>>>> +        : "r" (I)                                           \
>>>>
>>>> Btw, I consider this pretty confusing. At the 1st and 2nd glance
>>>> this
>>>> looks like a mistake, i.e. as if i was meant. Imo ...
>>>>
>>>>> +        : "memory" );                                       \
>>>>> +}                                                           \
>>>>> +
>>>>> +/*
>>>>> + * Only CONFIG_GENERIC_ATOMIC64=y was ported to Xen that is
>>>>> the
>>>>> reason why
>>>>> + * last argument for ATOMIC_OP isn't used.
>>>>> + */
>>>>> +#define ATOMIC_OPS(op, asm_op, I)                           \
>>>>> +        ATOMIC_OP (op, asm_op, I, w, int,   )
>>>>> +
>>>>> +ATOMIC_OPS(add, add,  i)
>>>>> +ATOMIC_OPS(sub, add, -i)
>>>>> +ATOMIC_OPS(and, and,  i)
>>>>> +ATOMIC_OPS( or,  or,  i)
>>>>> +ATOMIC_OPS(xor, xor,  i)
>>>>
>>>> ... here you want to only pass the (unary) operator (and leaving
>>>> that
>>>> blank
>>>> is as fine as using +).
>>> I agree that a game with 'i' and 'I' looks confusing, but I am not
>>> really understand what is wrong with using ' i' here. It seems that
>>> preprocessed macros looks fine:
>>>    static inline void atomic_add(int i, atomic_t *v) { asm volatile
>>> ( "  
>>>    amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r" (i)
>>> :
>>>    "memory" ); }
>>>    
>>>    static inline void atomic_sub(int i, atomic_t *v) { asm volatile
>>> ( "  
>>>    amo" "add" "." "w" " zero, %1, %0" : "+A" (v->counter) : "r" (-
>>> i) :
>>>    "memory" ); }
>>
>> I didn't question the pre-processed result being correct. Instead I
>> said
>> that I consider the construct confusing to the reader, for looking as
>> if
>> there was a mistake (in the case of the letter i used). Note also in
>> particular how the macro invocations need to be in sync with the
>> macro
>> implementation, for lower case i being used both in the macro and in
>> its
>> invocations. Anything parameterized would better be fully so, at the
>> very least to avoid, as said, confusion. (Having macros depend on
>> context at their use sites _may_ be okay for local helper macros, but
>> here we're talking about a not even private header file.)
> I am not sure then I understand how mentioning '+i' will help
> significantly remove confusion.

I'm afraid I don't understand: What "mentioning '+i'" are you referring
to? I'm pretty sure I didn't suggest that. What I suggested was to pass
a bare operator (- or +) as macro argument.

>>>>> +/* This is required to provide a full barrier on success. */
>>>>> +static inline int atomic_add_unless(atomic_t *v, int a, int u)
>>>>> +{
>>>>> +       int prev, rc;
>>>>> +
>>>>> +    asm volatile (
>>>>> +        "0: lr.w     %[p],  %[c]\n"
>>>>> +        "   beq      %[p],  %[u], 1f\n"
>>>>> +        "   add      %[rc], %[p], %[a]\n"
>>>>> +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
>>>>> +        "   bnez     %[rc], 0b\n"
>>>>> +        RISCV_FULL_BARRIER
>>>>
>>>> With this and no .aq on the load, why the .rl on the store?
>>> It is something that LKMM requires [1].
>>>
>>> This is not fully clear to me what is so specific in LKMM, but
>>> accoring
>>> to the spec:
>>>    Ordering Annotation Fence-based Equivalent
>>>    l{b|h|w|d|r}.aq     l{b|h|w|d|r}; fence r,rw
>>>    l{b|h|w|d|r}.aqrl   fence rw,rw; l{b|h|w|d|r}; fence r,rw
>>>    s{b|h|w|d|c}.rl     fence rw,w; s{b|h|w|d|c}
>>>    s{b|h|w|d|c}.aqrl   fence rw,w; s{b|h|w|d|c}
>>>    amo<op>.aq          amo<op>; fence r,rw
>>>    amo<op>.rl          fence rw,w; amo<op>
>>>    amo<op>.aqrl        fence rw,rw; amo<op>; fence rw,rw
>>>    Table 2.2: Mappings from .aq and/or .rl to fence-based
>>> equivalents.
>>>    An alternative mapping places a fence rw,rw after the existing 
>>>    s{b|h|w|d|c} mapping rather than at the front of the
>>>    l{b|h|w|d|r} mapping.
>>
>> I'm afraid I can't spot the specific case in this table. None of the
>> stores in the right column have a .rl suffix.
> Yes, it is expected.
> 
> I am reading this table as (f.e.) amo<op>.rl is an equivalent of fence
> rw,w; amo<op>. (without .rl) 

In which case: How does quoting the table answer my original question?

>>>    It is also safe to translate any .aq, .rl, or .aqrl annotation
>>> into
>>>    the fence-based snippets of
>>>    Table 2.2. These can also be used as a legal implementation of
>>>    l{b|h|w|d} or s{b|h|w|d} pseu-
>>>    doinstructions for as long as those instructions are not added
>>> to
>>>    the ISA.
>>>
>>> So according to the spec, it should be:
>>>  sc.w ...
>>>  RISCV_FULL_BARRIER.
>>>
>>> Considering [1] and how this code looks before, it seems to me that
>>> it
>>> is safe to use lr.w.aq/sc.w.rl here or an fence equivalent.
>>
>> Here you say "or". Then why dos the code use sc.?.rl _and_ a fence?
> I confused this line with amo<op>.aqrl, so based on the table 2.2 above
> s{b|h|w|d|c}.aqrl is transformed to "fence rw,w; s{b|h|w|d|c}", but
> Linux kernel decided to strengthen it with full barrier:
>    -              "0:\n\t"
>    -              "lr.w.aqrl  %[p],  %[c]\n\t"
>    -              "beq        %[p],  %[u], 1f\n\t"
>    -              "add       %[rc],  %[p], %[a]\n\t"
>    -              "sc.w.aqrl %[rc], %[rc], %[c]\n\t"
>    -              "bnez      %[rc], 0b\n\t"
>    -              "1:"
>    +               "0:     lr.w     %[p],  %[c]\n"
>    +               "       beq      %[p],  %[u], 1f\n"
>    +               "       add      %[rc], %[p], %[a]\n"
>    +               "       sc.w.rl  %[rc], %[rc], %[c]\n"
>    +               "       bnez     %[rc], 0b\n"
>    +               "       fence    rw, rw\n"
>    +               "1:\n"
> As they have the following issue:
>    implementations of atomics such as atomic_cmpxchg() and
>    atomic_add_unless() rely on LR/SC pairs,
>    which do not give full-ordering with .aqrl; for example, current
>    implementations allow the "lr-sc-aqrl-pair-vs-full-barrier" test
>    below to end up with the state indicated in the "exists" clause.

Is that really "current implementations", not "the abstract model"?
If so, the use of an explicit fence would be more like a workaround
(and would hence want commenting to that effect).

In neither case can I see my original question answered: Why the .rl
on the store when there is a full fence later?

Jan


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

* Re: [PATCH v6 10/20] xen/riscv: introduce atomic.h
  2024-03-27  7:40           ` Jan Beulich
@ 2024-03-27 10:28             ` Oleksii
  2024-03-27 11:07               ` Jan Beulich
  0 siblings, 1 reply; 61+ messages in thread
From: Oleksii @ 2024-03-27 10:28 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Wed, 2024-03-27 at 08:40 +0100, Jan Beulich wrote:
...

> > > > > > +/* This is required to provide a full barrier on success.
> > > > > > */
> > > > > > +static inline int atomic_add_unless(atomic_t *v, int a,
> > > > > > int u)
> > > > > > +{
> > > > > > +       int prev, rc;
> > > > > > +
> > > > > > +    asm volatile (
> > > > > > +        "0: lr.w     %[p],  %[c]\n"
> > > > > > +        "   beq      %[p],  %[u], 1f\n"
> > > > > > +        "   add      %[rc], %[p], %[a]\n"
> > > > > > +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
> > > > > > +        "   bnez     %[rc], 0b\n"
> > > > > > +        RISCV_FULL_BARRIER
> > > > > 
> > > > > With this and no .aq on the load, why the .rl on the store?
> > > > It is something that LKMM requires [1].
> > > > 
> > > > This is not fully clear to me what is so specific in LKMM, but
> > > > accoring
> > > > to the spec:
> > > >    Ordering Annotation Fence-based Equivalent
> > > >    l{b|h|w|d|r}.aq     l{b|h|w|d|r}; fence r,rw
> > > >    l{b|h|w|d|r}.aqrl   fence rw,rw; l{b|h|w|d|r}; fence r,rw
> > > >    s{b|h|w|d|c}.rl     fence rw,w; s{b|h|w|d|c}
> > > >    s{b|h|w|d|c}.aqrl   fence rw,w; s{b|h|w|d|c}
> > > >    amo<op>.aq          amo<op>; fence r,rw
> > > >    amo<op>.rl          fence rw,w; amo<op>
> > > >    amo<op>.aqrl        fence rw,rw; amo<op>; fence rw,rw
> > > >    Table 2.2: Mappings from .aq and/or .rl to fence-based
> > > > equivalents.
> > > >    An alternative mapping places a fence rw,rw after the
> > > > existing 
> > > >    s{b|h|w|d|c} mapping rather than at the front of the
> > > >    l{b|h|w|d|r} mapping.
> > > 
> > > I'm afraid I can't spot the specific case in this table. None of
> > > the
> > > stores in the right column have a .rl suffix.
> > Yes, it is expected.
> > 
> > I am reading this table as (f.e.) amo<op>.rl is an equivalent of
> > fence
> > rw,w; amo<op>. (without .rl) 
> 
> In which case: How does quoting the table answer my original
> question?
Agree, it is starting to be confusing, so let me give an answer to your
question below.

> 
> > > >    It is also safe to translate any .aq, .rl, or .aqrl
> > > > annotation
> > > > into
> > > >    the fence-based snippets of
> > > >    Table 2.2. These can also be used as a legal implementation
> > > > of
> > > >    l{b|h|w|d} or s{b|h|w|d} pseu-
> > > >    doinstructions for as long as those instructions are not
> > > > added
> > > > to
> > > >    the ISA.
> > > > 
> > > > So according to the spec, it should be:
> > > >  sc.w ...
> > > >  RISCV_FULL_BARRIER.
> > > > 
> > > > Considering [1] and how this code looks before, it seems to me
> > > > that
> > > > it
> > > > is safe to use lr.w.aq/sc.w.rl here or an fence equivalent.
> > > 
> > > Here you say "or". Then why dos the code use sc.?.rl _and_ a
> > > fence?
> > I confused this line with amo<op>.aqrl, so based on the table 2.2
> > above
> > s{b|h|w|d|c}.aqrl is transformed to "fence rw,w; s{b|h|w|d|c}", but
> > Linux kernel decided to strengthen it with full barrier:
> >    -              "0:\n\t"
> >    -              "lr.w.aqrl  %[p],  %[c]\n\t"
> >    -              "beq        %[p],  %[u], 1f\n\t"
> >    -              "add       %[rc],  %[p], %[a]\n\t"
> >    -              "sc.w.aqrl %[rc], %[rc], %[c]\n\t"
> >    -              "bnez      %[rc], 0b\n\t"
> >    -              "1:"
> >    +               "0:     lr.w     %[p],  %[c]\n"
> >    +               "       beq      %[p],  %[u], 1f\n"
> >    +               "       add      %[rc], %[p], %[a]\n"
> >    +               "       sc.w.rl  %[rc], %[rc], %[c]\n"
> >    +               "       bnez     %[rc], 0b\n"
> >    +               "       fence    rw, rw\n"
> >    +               "1:\n"
> > As they have the following issue:
> >    implementations of atomics such as atomic_cmpxchg() and
> >    atomic_add_unless() rely on LR/SC pairs,
> >    which do not give full-ordering with .aqrl; for example, current
> >    implementations allow the "lr-sc-aqrl-pair-vs-full-barrier" test
> >    below to end up with the state indicated in the "exists" clause.
> 
> Is that really "current implementations", not "the abstract model"?
> If so, the use of an explicit fence would be more like a workaround
> (and would hence want commenting to that effect).
> 
> In neither case can I see my original question answered: Why the .rl
> on the store when there is a full fence later?
The good explanation for that was provided in the commit addressing a
similar issue for ARM64 [
https://patchwork.kernel.org/project/linux-arm-kernel/patch/1391516953-14541-1-git-send-email-will.deacon@arm.com/
].
The same holds true for RISC-V since ARM also employs WMO.

I would also like to mention another point, as I indicated in another
email thread
[ https://lists.xen.org/archives/html/xen-devel/2024-03/msg01582.html ]
, that now this fence can be omitted and .aqrl can be used instead.

This was confirmed by Dan (the author of the RVWMO spec)
[https://lore.kernel.org/linux-riscv/41e01514-74ca-84f2-f5cc-2645c444fd8e@nvidia.com/
]

I hope this addresses your original question. Does it?

~ Oleksii



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

* Re: [PATCH v6 10/20] xen/riscv: introduce atomic.h
  2024-03-27 10:28             ` Oleksii
@ 2024-03-27 11:07               ` Jan Beulich
  0 siblings, 0 replies; 61+ messages in thread
From: Jan Beulich @ 2024-03-27 11:07 UTC (permalink / raw)
  To: Oleksii
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 27.03.2024 11:28, Oleksii wrote:
> On Wed, 2024-03-27 at 08:40 +0100, Jan Beulich wrote:
> ...
> 
>>>>>>> +/* This is required to provide a full barrier on success.
>>>>>>> */
>>>>>>> +static inline int atomic_add_unless(atomic_t *v, int a,
>>>>>>> int u)
>>>>>>> +{
>>>>>>> +       int prev, rc;
>>>>>>> +
>>>>>>> +    asm volatile (
>>>>>>> +        "0: lr.w     %[p],  %[c]\n"
>>>>>>> +        "   beq      %[p],  %[u], 1f\n"
>>>>>>> +        "   add      %[rc], %[p], %[a]\n"
>>>>>>> +        "   sc.w.rl  %[rc], %[rc], %[c]\n"
>>>>>>> +        "   bnez     %[rc], 0b\n"
>>>>>>> +        RISCV_FULL_BARRIER
>>>>>>
>>>>>> With this and no .aq on the load, why the .rl on the store?
>>>>> It is something that LKMM requires [1].
>>>>>
>>>>> This is not fully clear to me what is so specific in LKMM, but
>>>>> accoring
>>>>> to the spec:
>>>>>    Ordering Annotation Fence-based Equivalent
>>>>>    l{b|h|w|d|r}.aq     l{b|h|w|d|r}; fence r,rw
>>>>>    l{b|h|w|d|r}.aqrl   fence rw,rw; l{b|h|w|d|r}; fence r,rw
>>>>>    s{b|h|w|d|c}.rl     fence rw,w; s{b|h|w|d|c}
>>>>>    s{b|h|w|d|c}.aqrl   fence rw,w; s{b|h|w|d|c}
>>>>>    amo<op>.aq          amo<op>; fence r,rw
>>>>>    amo<op>.rl          fence rw,w; amo<op>
>>>>>    amo<op>.aqrl        fence rw,rw; amo<op>; fence rw,rw
>>>>>    Table 2.2: Mappings from .aq and/or .rl to fence-based
>>>>> equivalents.
>>>>>    An alternative mapping places a fence rw,rw after the
>>>>> existing 
>>>>>    s{b|h|w|d|c} mapping rather than at the front of the
>>>>>    l{b|h|w|d|r} mapping.
>>>>
>>>> I'm afraid I can't spot the specific case in this table. None of
>>>> the
>>>> stores in the right column have a .rl suffix.
>>> Yes, it is expected.
>>>
>>> I am reading this table as (f.e.) amo<op>.rl is an equivalent of
>>> fence
>>> rw,w; amo<op>. (without .rl) 
>>
>> In which case: How does quoting the table answer my original
>> question?
> Agree, it is starting to be confusing, so let me give an answer to your
> question below.
> 
>>
>>>>>    It is also safe to translate any .aq, .rl, or .aqrl
>>>>> annotation
>>>>> into
>>>>>    the fence-based snippets of
>>>>>    Table 2.2. These can also be used as a legal implementation
>>>>> of
>>>>>    l{b|h|w|d} or s{b|h|w|d} pseu-
>>>>>    doinstructions for as long as those instructions are not
>>>>> added
>>>>> to
>>>>>    the ISA.
>>>>>
>>>>> So according to the spec, it should be:
>>>>>  sc.w ...
>>>>>  RISCV_FULL_BARRIER.
>>>>>
>>>>> Considering [1] and how this code looks before, it seems to me
>>>>> that
>>>>> it
>>>>> is safe to use lr.w.aq/sc.w.rl here or an fence equivalent.
>>>>
>>>> Here you say "or". Then why dos the code use sc.?.rl _and_ a
>>>> fence?
>>> I confused this line with amo<op>.aqrl, so based on the table 2.2
>>> above
>>> s{b|h|w|d|c}.aqrl is transformed to "fence rw,w; s{b|h|w|d|c}", but
>>> Linux kernel decided to strengthen it with full barrier:
>>>    -              "0:\n\t"
>>>    -              "lr.w.aqrl  %[p],  %[c]\n\t"
>>>    -              "beq        %[p],  %[u], 1f\n\t"
>>>    -              "add       %[rc],  %[p], %[a]\n\t"
>>>    -              "sc.w.aqrl %[rc], %[rc], %[c]\n\t"
>>>    -              "bnez      %[rc], 0b\n\t"
>>>    -              "1:"
>>>    +               "0:     lr.w     %[p],  %[c]\n"
>>>    +               "       beq      %[p],  %[u], 1f\n"
>>>    +               "       add      %[rc], %[p], %[a]\n"
>>>    +               "       sc.w.rl  %[rc], %[rc], %[c]\n"
>>>    +               "       bnez     %[rc], 0b\n"
>>>    +               "       fence    rw, rw\n"
>>>    +               "1:\n"
>>> As they have the following issue:
>>>    implementations of atomics such as atomic_cmpxchg() and
>>>    atomic_add_unless() rely on LR/SC pairs,
>>>    which do not give full-ordering with .aqrl; for example, current
>>>    implementations allow the "lr-sc-aqrl-pair-vs-full-barrier" test
>>>    below to end up with the state indicated in the "exists" clause.
>>
>> Is that really "current implementations", not "the abstract model"?
>> If so, the use of an explicit fence would be more like a workaround
>> (and would hence want commenting to that effect).
>>
>> In neither case can I see my original question answered: Why the .rl
>> on the store when there is a full fence later?
> The good explanation for that was provided in the commit addressing a
> similar issue for ARM64 [
> https://patchwork.kernel.org/project/linux-arm-kernel/patch/1391516953-14541-1-git-send-email-will.deacon@arm.com/
> ].
> The same holds true for RISC-V since ARM also employs WMO.
> 
> I would also like to mention another point, as I indicated in another
> email thread
> [ https://lists.xen.org/archives/html/xen-devel/2024-03/msg01582.html ]
> , that now this fence can be omitted and .aqrl can be used instead.
> 
> This was confirmed by Dan (the author of the RVWMO spec)
> [https://lore.kernel.org/linux-riscv/41e01514-74ca-84f2-f5cc-2645c444fd8e@nvidia.com/
> ]
> 
> I hope this addresses your original question. Does it?

I think it does, thanks. Some of this will need putting in at least the
patch description, if not a code comment.

Jan


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

* Re: [PATCH v6 06/20] xen/bitops: put __ffs() and ffz() into linux compatible header
  2024-03-20 15:42   ` Jan Beulich
  2024-03-21  9:33     ` Oleksii
@ 2024-03-29 18:23     ` Oleksii
  2024-04-02  6:46       ` Jan Beulich
  1 sibling, 1 reply; 61+ messages in thread
From: Oleksii @ 2024-03-29 18:23 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Shawn Anastasio, Rahul Singh, xen-devel

On Wed, 2024-03-20 at 16:42 +0100, Jan Beulich wrote:
> On 15.03.2024 19:06, Oleksii Kurochko wrote:
> > --- a/xen/lib/find-next-bit.c
> > +++ b/xen/lib/find-next-bit.c
> > @@ -9,6 +9,7 @@
> >   * 2 of the License, or (at your option) any later version.
> >   */
> >  #include <xen/bitops.h>
> > +#include <xen/linux-compat.h>
> >  
> >  #include <asm/byteorder.h>
> 
> Hmm, no, a library source would better not include this header.
> Surely
> the ffz() can be taken care of locally here?
Except that __ffs() from xen/linux-compat.h is used in find-next-bit.c,
so it seems that it is still need to include the header.

~ Oleksii


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

* Re: [PATCH v6 06/20] xen/bitops: put __ffs() and ffz() into linux compatible header
  2024-03-29 18:23     ` Oleksii
@ 2024-04-02  6:46       ` Jan Beulich
  0 siblings, 0 replies; 61+ messages in thread
From: Jan Beulich @ 2024-04-02  6:46 UTC (permalink / raw)
  To: Oleksii
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Shawn Anastasio, Rahul Singh, xen-devel

On 29.03.2024 19:23, Oleksii wrote:
> On Wed, 2024-03-20 at 16:42 +0100, Jan Beulich wrote:
>> On 15.03.2024 19:06, Oleksii Kurochko wrote:
>>> --- a/xen/lib/find-next-bit.c
>>> +++ b/xen/lib/find-next-bit.c
>>> @@ -9,6 +9,7 @@
>>>   * 2 of the License, or (at your option) any later version.
>>>   */
>>>  #include <xen/bitops.h>
>>> +#include <xen/linux-compat.h>
>>>  
>>>  #include <asm/byteorder.h>
>>
>> Hmm, no, a library source would better not include this header.
>> Surely
>> the ffz() can be taken care of locally here?
> Except that __ffs() from xen/linux-compat.h is used in find-next-bit.c,
> so it seems that it is still need to include the header.

Hmm, no - that __ffs() use, if we mean that to become a Linux compat thing
only, should then be replaced (or covered locally), too, imo.

Jan


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

* Re: [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h
  2024-03-21 12:07   ` Jan Beulich
  2024-03-22 10:32     ` Oleksii
@ 2024-04-02 11:43     ` Oleksii
  2024-04-02 12:54       ` Jan Beulich
  1 sibling, 1 reply; 61+ messages in thread
From: Oleksii @ 2024-04-02 11:43 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Thu, 2024-03-21 at 13:07 +0100, Jan Beulich wrote:
> > + * If resulting 4-byte access is still misalgined, it will fault
> > just as
> > + * non-emulated 4-byte access would.
> > + */
> > +#define emulate_xchg_1_2(ptr, new, lr_sfx, sc_sfx) \
> > +({ \
> > +    uint32_t *aligned_ptr = (uint32_t *)((unsigned long)ptr &
> > ~(0x4 - sizeof(*(ptr)))); \
> > +    unsigned int new_val_pos = ((unsigned long)(ptr) & (0x4 -
> > sizeof(*(ptr)))) * BITS_PER_BYTE; \
> 
> You parenthesize ptr here correctly, but not in the line above.
> 
> Instead of "_pos" in the name, maybe better "_bit"?
> 
> Finally, here and elsewhere, please limit line length to 80 chars.
> (Omitting
> the 0x here would help a little, but not quite enough. Question is
> whether
> these wouldn't better be sizeof(*aligned_ptr) anyway.)

I'm unsure if using sizeof(*aligned_ptr) is correct in this context.
The intention was to determine the position for the value we're
attempting to exchange.

Let's consider a scenario where we have 0xAABBCCDD at address 0x6. Even
though this would result in misaligned access, I believe new_val_pos
should still be calculated accurately. Let's say we want to exchange
two bytes (AABB) with FFFF.

With the current implementation, we would calculate:
0x6 & 2 = 2 * 8 = 16, which is the value on which the new value should
be shifted.

However, if this value is then ANDed with sizeof(*aligned_ptr):
0x6 & 4 = 6 * 8 = 48, which is not the expected value.

Am I overlooking something?

~ Oleksii



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

* Re: [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h
  2024-04-02 11:43     ` Oleksii
@ 2024-04-02 12:54       ` Jan Beulich
  2024-04-02 13:43         ` Oleksii
  0 siblings, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2024-04-02 12:54 UTC (permalink / raw)
  To: Oleksii
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On 02.04.2024 13:43, Oleksii wrote:
> On Thu, 2024-03-21 at 13:07 +0100, Jan Beulich wrote:
>>> + * If resulting 4-byte access is still misalgined, it will fault
>>> just as
>>> + * non-emulated 4-byte access would.
>>> + */
>>> +#define emulate_xchg_1_2(ptr, new, lr_sfx, sc_sfx) \
>>> +({ \
>>> +    uint32_t *aligned_ptr = (uint32_t *)((unsigned long)ptr &
>>> ~(0x4 - sizeof(*(ptr)))); \
>>> +    unsigned int new_val_pos = ((unsigned long)(ptr) & (0x4 -
>>> sizeof(*(ptr)))) * BITS_PER_BYTE; \
>>
>> You parenthesize ptr here correctly, but not in the line above.
>>
>> Instead of "_pos" in the name, maybe better "_bit"?
>>
>> Finally, here and elsewhere, please limit line length to 80 chars.
>> (Omitting
>> the 0x here would help a little, but not quite enough. Question is
>> whether
>> these wouldn't better be sizeof(*aligned_ptr) anyway.)
> 
> I'm unsure if using sizeof(*aligned_ptr) is correct in this context.
> The intention was to determine the position for the value we're
> attempting to exchange.
> 
> Let's consider a scenario where we have 0xAABBCCDD at address 0x6. Even
> though this would result in misaligned access, I believe new_val_pos
> should still be calculated accurately. Let's say we want to exchange
> two bytes (AABB) with FFFF.
> 
> With the current implementation, we would calculate:
> 0x6 & 2 = 2 * 8 = 16, which is the value on which the new value should
> be shifted.
> 
> However, if this value is then ANDed with sizeof(*aligned_ptr):
> 0x6 & 4 = 6 * 8 = 48, which is not the expected value.
> 
> Am I overlooking something?

I'm afraid I can only reply with a counter question (feels like there is
some misunderstanding): Do you agree that 0x4 == 4 == sizeof(*aligned_ptr)?
It's the 0x4 that the latter part of my earlier reply was about. I'm pretty
sure you have, over the various reviews I've done, noticed my dislike for
the use of literal numbers, when those aren't truly "magic".

Jan


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

* Re: [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h
  2024-04-02 12:54       ` Jan Beulich
@ 2024-04-02 13:43         ` Oleksii
  0 siblings, 0 replies; 61+ messages in thread
From: Oleksii @ 2024-04-02 13:43 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Alistair Francis, Bob Eshleman, Connor Davis, Andrew Cooper,
	George Dunlap, Julien Grall, Stefano Stabellini, Wei Liu,
	xen-devel

On Tue, 2024-04-02 at 14:54 +0200, Jan Beulich wrote:
> On 02.04.2024 13:43, Oleksii wrote:
> > On Thu, 2024-03-21 at 13:07 +0100, Jan Beulich wrote:
> > > > + * If resulting 4-byte access is still misalgined, it will
> > > > fault
> > > > just as
> > > > + * non-emulated 4-byte access would.
> > > > + */
> > > > +#define emulate_xchg_1_2(ptr, new, lr_sfx, sc_sfx) \
> > > > +({ \
> > > > +    uint32_t *aligned_ptr = (uint32_t *)((unsigned long)ptr &
> > > > ~(0x4 - sizeof(*(ptr)))); \
> > > > +    unsigned int new_val_pos = ((unsigned long)(ptr) & (0x4 -
> > > > sizeof(*(ptr)))) * BITS_PER_BYTE; \
> > > 
> > > You parenthesize ptr here correctly, but not in the line above.
> > > 
> > > Instead of "_pos" in the name, maybe better "_bit"?
> > > 
> > > Finally, here and elsewhere, please limit line length to 80
> > > chars.
> > > (Omitting
> > > the 0x here would help a little, but not quite enough. Question
> > > is
> > > whether
> > > these wouldn't better be sizeof(*aligned_ptr) anyway.)
> > 
> > I'm unsure if using sizeof(*aligned_ptr) is correct in this
> > context.
> > The intention was to determine the position for the value we're
> > attempting to exchange.
> > 
> > Let's consider a scenario where we have 0xAABBCCDD at address 0x6.
> > Even
> > though this would result in misaligned access, I believe
> > new_val_pos
> > should still be calculated accurately. Let's say we want to
> > exchange
> > two bytes (AABB) with FFFF.
> > 
> > With the current implementation, we would calculate:
> > 0x6 & 2 = 2 * 8 = 16, which is the value on which the new value
> > should
> > be shifted.
> > 
> > However, if this value is then ANDed with sizeof(*aligned_ptr):
> > 0x6 & 4 = 6 * 8 = 48, which is not the expected value.
> > 
> > Am I overlooking something?
> 
> I'm afraid I can only reply with a counter question (feels like there
> is
> some misunderstanding): Do you agree that 0x4 == 4 ==
> sizeof(*aligned_ptr)?
> It's the 0x4 that the latter part of my earlier reply was about. I'm
> pretty
> sure you have, over the various reviews I've done, noticed my dislike
> for
> the use of literal numbers, when those aren't truly "magic".
Yes, it was misunderstading. Thanks for clarifying.

~ Oleksii


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

end of thread, other threads:[~2024-04-02 13:43 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-15 18:05 [PATCH v6 00/20] Enable build of full Xen for RISC-V Oleksii Kurochko
2024-03-15 18:05 ` [PATCH v6 01/20] automation: introduce fixed randconfig " Oleksii Kurochko
2024-03-15 18:05 ` [PATCH v6 02/20] xen/riscv: disable unnecessary configs Oleksii Kurochko
2024-03-18  7:54   ` Jan Beulich
2024-03-18 14:42     ` Oleksii
2024-03-15 18:05 ` [PATCH v6 03/20] xen/riscv: introduce extenstion support check by compiler Oleksii Kurochko
2024-03-18 16:58   ` Jan Beulich
2024-03-20 18:58     ` Oleksii
2024-03-20 19:44       ` Conor Dooley
2024-03-21  8:31         ` Jan Beulich
2024-03-21  9:22           ` Conor Dooley
2024-03-21  9:07         ` Oleksii
2024-03-15 18:06 ` [PATCH v6 04/20] xen/asm-generic: introduce generic non-atomic test_*bit() Oleksii Kurochko
2024-03-20 15:30   ` Jan Beulich
2024-03-21  9:27     ` Oleksii
2024-03-15 18:06 ` [PATCH v6 05/20] xen/bitops: implement fls{l}() in common logic Oleksii Kurochko
2024-03-20 15:39   ` Jan Beulich
2024-03-15 18:06 ` [PATCH v6 06/20] xen/bitops: put __ffs() and ffz() into linux compatible header Oleksii Kurochko
2024-03-20 15:42   ` Jan Beulich
2024-03-21  9:33     ` Oleksii
2024-03-29 18:23     ` Oleksii
2024-04-02  6:46       ` Jan Beulich
2024-03-15 18:06 ` [PATCH v6 07/20] xen/riscv: introduce bitops.h Oleksii Kurochko
2024-03-20 16:03   ` Jan Beulich
2024-03-21 10:07     ` Oleksii
2024-03-21 10:28       ` Jan Beulich
2024-03-15 18:06 ` [PATCH v6 08/20] xen/riscv: introduce cmpxchg.h Oleksii Kurochko
2024-03-21 12:07   ` Jan Beulich
2024-03-22 10:32     ` Oleksii
2024-03-22 10:42       ` Jan Beulich
2024-03-22 12:52         ` Oleksii
2024-04-02 11:43     ` Oleksii
2024-04-02 12:54       ` Jan Beulich
2024-04-02 13:43         ` Oleksii
2024-03-15 18:06 ` [PATCH v6 09/20] xen/riscv: introduce io.h Oleksii Kurochko
2024-03-21 12:27   ` Jan Beulich
2024-03-22 11:02     ` Oleksii
2024-03-22 11:36       ` Jan Beulich
2024-03-22 12:55         ` Oleksii
2024-03-15 18:06 ` [PATCH v6 10/20] xen/riscv: introduce atomic.h Oleksii Kurochko
2024-03-21 13:03   ` Jan Beulich
2024-03-22 12:25     ` Oleksii
2024-03-25  8:18       ` Jan Beulich
2024-03-26 19:02         ` Oleksii
2024-03-26 21:24           ` Oleksii
2024-03-27  7:40           ` Jan Beulich
2024-03-27 10:28             ` Oleksii
2024-03-27 11:07               ` Jan Beulich
2024-03-15 18:06 ` [PATCH v6 11/20] xen/riscv: introduce monitor.h Oleksii Kurochko
2024-03-15 18:06 ` [PATCH v6 12/20] xen/riscv: add definition of __read_mostly Oleksii Kurochko
2024-03-15 18:06 ` [PATCH v6 13/20] xen/riscv: add required things to current.h Oleksii Kurochko
2024-03-15 18:06 ` [PATCH v6 14/20] xen/riscv: add minimal stuff to page.h to build full Xen Oleksii Kurochko
2024-03-15 18:06 ` [PATCH v6 15/20] xen/riscv: add minimal stuff to processor.h " Oleksii Kurochko
2024-03-21 13:26   ` Jan Beulich
2024-03-22 12:26     ` Oleksii
2024-03-15 18:06 ` [PATCH v6 16/20] xen/riscv: add minimal stuff to mm.h " Oleksii Kurochko
2024-03-21 13:37   ` Jan Beulich
2024-03-15 18:06 ` [PATCH v6 17/20] xen/riscv: introduce vm_event_*() functions Oleksii Kurochko
2024-03-15 18:06 ` [PATCH v6 18/20] xen/riscv: add minimal amount of stubs to build full Xen Oleksii Kurochko
2024-03-15 18:06 ` [PATCH v6 19/20] xen/riscv: enable full Xen build Oleksii Kurochko
2024-03-15 18:06 ` [PATCH v6 20/20] xen/README: add compiler and binutils versions for RISC-V64 Oleksii Kurochko

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.