All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/13] Arm cache coloring
@ 2024-01-02  9:51 Carlo Nonato
  2024-01-02  9:51 ` [PATCH v5 01/13] xen/common: add cache coloring common code Carlo Nonato
                   ` (13 more replies)
  0 siblings, 14 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Andrew Cooper, George Dunlap, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Anthony PERARD, Juergen Gross

Shared caches in multi-core CPU architectures represent a problem for
predictability of memory access latency. This jeopardizes applicability
of many Arm platform in real-time critical and mixed-criticality
scenarios. We introduce support for cache partitioning with page
coloring, a transparent software technique that enables isolation
between domains and Xen, and thus avoids cache interference.

When creating a domain, a simple syntax (e.g. `0-3` or `4-11`) allows
the user to define assignments of cache partitions ids, called colors,
where assigning different colors guarantees no mutual eviction on cache
will ever happen. This instructs the Xen memory allocator to provide
the i-th color assignee only with pages that maps to color i, i.e. that
are indexed in the i-th cache partition.

The proposed implementation supports the dom0less feature.
The proposed implementation doesn't support the static-mem feature.
The solution has been tested in several scenarios, including Xilinx Zynq
MPSoCs.

In this patch series there are two major unacceptable workarounds for which
I want to ask you for comments:
 - #3: allocate_memory() has been moved in dom0less_build.c, so I just copied
 it back to make it compile.
 - #13: consider_modules() has been moved to arm32 only. Again I just copied it.

Carlo Nonato (12):
  xen/common: add cache coloring common code
  xen/arm: add cache coloring initialization
  xen/arm: add Dom0 cache coloring support
  xen: extend domctl interface for cache coloring
  tools: add support for cache coloring configuration
  xen/arm: add support for cache coloring configuration via device-tree
  xen/page_alloc: introduce init_free_page_fields() helper
  xen/page_alloc: introduce preserved page flags macro
  xen: add cache coloring allocator for domains
  xen/arm: use domain memory to allocate p2m page tables
  Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START"
  xen/arm: add cache coloring support for Xen

Luca Miccio (1):
  xen/arm: add Xen cache colors command line parameter

 docs/man/xl.cfg.5.pod.in                |  10 +
 docs/misc/arm/cache-coloring.rst        | 209 ++++++++++++
 docs/misc/arm/device-tree/booting.txt   |   4 +
 docs/misc/xen-command-line.pandoc       |  61 ++++
 tools/include/libxl.h                   |   5 +
 tools/include/xenctrl.h                 |   9 +
 tools/libs/ctrl/xc_domain.c             |  34 ++
 tools/libs/light/libxl_create.c         |   9 +
 tools/libs/light/libxl_types.idl        |   1 +
 tools/xl/xl_parse.c                     |  38 ++-
 xen/arch/Kconfig                        |  28 ++
 xen/arch/arm/Kconfig                    |   1 +
 xen/arch/arm/Makefile                   |   1 +
 xen/arch/arm/alternative.c              |   9 +-
 xen/arch/arm/arm64/mmu/head.S           |  48 +++
 xen/arch/arm/arm64/mmu/mm.c             |  26 +-
 xen/arch/arm/dom0less-build.c           |  19 ++
 xen/arch/arm/domain_build.c             |  60 +++-
 xen/arch/arm/include/asm/llc-coloring.h |  46 +++
 xen/arch/arm/include/asm/mm.h           |  12 +-
 xen/arch/arm/include/asm/mmu/layout.h   |   2 +
 xen/arch/arm/include/asm/processor.h    |  16 +
 xen/arch/arm/llc-coloring.c             | 409 ++++++++++++++++++++++++
 xen/arch/arm/mmu/p2m.c                  |   4 +-
 xen/arch/arm/mmu/setup.c                |  83 ++++-
 xen/arch/arm/mmu/smpboot.c              |  11 +-
 xen/arch/arm/psci.c                     |   9 +-
 xen/arch/arm/setup.c                    | 172 +++++++++-
 xen/arch/arm/smpboot.c                  |   9 +-
 xen/common/Kconfig                      |   3 +
 xen/common/domain.c                     |   4 +
 xen/common/domctl.c                     |  11 +
 xen/common/keyhandler.c                 |   4 +
 xen/common/page_alloc.c                 | 217 ++++++++++++-
 xen/include/public/domctl.h             |  10 +-
 xen/include/xen/llc-coloring.h          |  53 +++
 xen/include/xen/sched.h                 |   5 +
 37 files changed, 1610 insertions(+), 42 deletions(-)
 create mode 100644 docs/misc/arm/cache-coloring.rst
 create mode 100644 xen/arch/arm/include/asm/llc-coloring.h
 create mode 100644 xen/arch/arm/llc-coloring.c
 create mode 100644 xen/include/xen/llc-coloring.h

-- 
2.34.1



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

* [PATCH v5 01/13] xen/common: add cache coloring common code
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-04 18:39   ` Julien Grall
                     ` (2 more replies)
  2024-01-02  9:51 ` [PATCH v5 02/13] xen/arm: add cache coloring initialization Carlo Nonato
                   ` (12 subsequent siblings)
  13 siblings, 3 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Andrew Cooper, George Dunlap, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu, Marco Solieri

This commit adds the Last Level Cache (LLC) coloring common header, Kconfig
options and functions. Since this is an arch specific feature, actual
implementation is postponed to later patches and Kconfig options are placed
under xen/arch.

LLC colors are a property of the domain, so the domain struct has to be
extended.

Based on original work from: Luca Miccio <lucmiccio@gmail.com>

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- used - instead of _ for filenames
- removed domain_create_llc_colored()
- removed stub functions
- coloring domain fields are now #ifdef protected
v4:
- Kconfig options moved to xen/arch
- removed range for CONFIG_NR_LLC_COLORS
- added "llc_coloring_enabled" global to later implement the boot-time
  switch
- added domain_create_llc_colored() to be able to pass colors
- added is_domain_llc_colored() macro
---
 xen/arch/Kconfig               | 16 ++++++++++++
 xen/common/Kconfig             |  3 +++
 xen/common/domain.c            |  4 +++
 xen/common/keyhandler.c        |  4 +++
 xen/include/xen/llc-coloring.h | 46 ++++++++++++++++++++++++++++++++++
 xen/include/xen/sched.h        |  5 ++++
 6 files changed, 78 insertions(+)
 create mode 100644 xen/include/xen/llc-coloring.h

diff --git a/xen/arch/Kconfig b/xen/arch/Kconfig
index 67ba38f32f..aad7e9da38 100644
--- a/xen/arch/Kconfig
+++ b/xen/arch/Kconfig
@@ -31,3 +31,19 @@ config NR_NUMA_NODES
 	  associated with multiple-nodes management. It is the upper bound of
 	  the number of NUMA nodes that the scheduler, memory allocation and
 	  other NUMA-aware components can handle.
+
+config LLC_COLORING
+	bool "Last Level Cache (LLC) coloring" if EXPERT
+	depends on HAS_LLC_COLORING
+
+config NR_LLC_COLORS
+	int "Maximum number of LLC colors"
+	default 128
+	depends on LLC_COLORING
+	help
+	  Controls the build-time size of various arrays associated with LLC
+	  coloring. Refer to cache coloring documentation for how to compute the
+	  number of colors supported by the platform. This is only an upper
+	  bound. The runtime value is autocomputed or manually set via cmdline.
+	  The default value corresponds to an 8 MiB 16-ways LLC, which should be
+	  more than what needed in the general case.
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 310ad4229c..e383f09d97 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -71,6 +71,9 @@ config HAS_IOPORTS
 config HAS_KEXEC
 	bool
 
+config HAS_LLC_COLORING
+	bool
+
 config HAS_PMAP
 	bool
 
diff --git a/xen/common/domain.c b/xen/common/domain.c
index f6f5574996..491585b0bb 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -7,6 +7,7 @@
 #include <xen/compat.h>
 #include <xen/init.h>
 #include <xen/lib.h>
+#include <xen/llc-coloring.h>
 #include <xen/ctype.h>
 #include <xen/err.h>
 #include <xen/param.h>
@@ -1144,6 +1145,9 @@ static void cf_check complete_domain_destroy(struct rcu_head *head)
     struct vcpu *v;
     int i;
 
+    if ( is_domain_llc_colored(d) )
+        domain_llc_coloring_free(d);
+
     /*
      * Flush all state for the vCPU previously having run on the current CPU.
      * This is in particular relevant for x86 HVM ones on VMX, so that this
diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
index 99a2d72a02..27c2d324d8 100644
--- a/xen/common/keyhandler.c
+++ b/xen/common/keyhandler.c
@@ -6,6 +6,7 @@
 #include <xen/debugger.h>
 #include <xen/delay.h>
 #include <xen/keyhandler.h>
+#include <xen/llc-coloring.h>
 #include <xen/param.h>
 #include <xen/shutdown.h>
 #include <xen/event.h>
@@ -307,6 +308,9 @@ static void cf_check dump_domains(unsigned char key)
 
         arch_dump_domain_info(d);
 
+        if ( is_domain_llc_colored(d) )
+            domain_dump_llc_colors(d);
+
         rangeset_domain_printk(d);
 
         dump_pageframe_info(d);
diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
new file mode 100644
index 0000000000..cedd97d4b5
--- /dev/null
+++ b/xen/include/xen/llc-coloring.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Last Level Cache (LLC) coloring common header
+ *
+ * Copyright (C) 2022 Xilinx Inc.
+ *
+ * Authors:
+ *    Carlo Nonato <carlo.nonato@minervasys.tech>
+ */
+#ifndef __COLORING_H__
+#define __COLORING_H__
+
+#include <xen/sched.h>
+#include <public/domctl.h>
+
+#ifdef CONFIG_HAS_LLC_COLORING
+
+#include <asm/llc-coloring.h>
+
+#ifdef CONFIG_LLC_COLORING
+extern bool llc_coloring_enabled;
+#define llc_coloring_enabled (llc_coloring_enabled)
+#endif
+
+#endif
+
+#ifndef llc_coloring_enabled
+#define llc_coloring_enabled (false)
+#endif
+
+#define is_domain_llc_colored(d) (llc_coloring_enabled)
+
+void domain_llc_coloring_free(struct domain *d);
+void domain_dump_llc_colors(struct domain *d);
+
+#endif /* __COLORING_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 9da91e0e62..dae7fab673 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -626,6 +626,11 @@ struct domain
 
     /* Holding CDF_* constant. Internal flags for domain creation. */
     unsigned int cdf;
+
+#ifdef CONFIG_LLC_COLORING
+    unsigned int *llc_colors;
+    unsigned int num_llc_colors;
+#endif
 };
 
 static inline struct page_list_head *page_to_list(
-- 
2.34.1



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

* [PATCH v5 02/13] xen/arm: add cache coloring initialization
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
  2024-01-02  9:51 ` [PATCH v5 01/13] xen/common: add cache coloring common code Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-04 19:24   ` Julien Grall
  2024-01-02  9:51 ` [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support Carlo Nonato
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Andrew Cooper, George Dunlap,
	Jan Beulich, Wei Liu, Marco Solieri

This commit implements functions declared in the LLC coloring common header
for arm64 and adds documentation. It also adds two command line options: a
runtime switch for the cache coloring feature and the LLC way size
parameter.

The feature init function consists of an auto probing of the cache layout
necessary to retrieve the LLC way size which is used to compute the number
of platform colors. It also adds a debug-key to dump general cache coloring
info.

Static memory allocation and cache coloring are incompatible because static
memory can't be guaranteed to use only colors assigned to the domain.
Panic during domUs creation when both are enabled.

Based on original work from: Luca Miccio <lucmiccio@gmail.com>

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- used - instead of _ for filenames
- moved static-mem check in this patch
- moved dom0 colors parsing in next patch
- moved color allocation and configuration in next patch
- moved check_colors() in next patch
- colors are now printed in short form
v4:
- added "llc-coloring" cmdline option for the boot-time switch
- dom0 colors are now checked during domain init as for any other domain
- fixed processor.h masks bit width
- check for overflow in parse_color_config()
- check_colors() now checks also that colors are sorted and unique
---
 docs/misc/arm/cache-coloring.rst        |  97 ++++++++++++++
 docs/misc/xen-command-line.pandoc       |  28 +++++
 xen/arch/arm/Kconfig                    |   1 +
 xen/arch/arm/Makefile                   |   1 +
 xen/arch/arm/dom0less-build.c           |   6 +
 xen/arch/arm/include/asm/llc-coloring.h |  28 +++++
 xen/arch/arm/include/asm/processor.h    |  16 +++
 xen/arch/arm/llc-coloring.c             | 161 ++++++++++++++++++++++++
 xen/arch/arm/setup.c                    |   7 ++
 9 files changed, 345 insertions(+)
 create mode 100644 docs/misc/arm/cache-coloring.rst
 create mode 100644 xen/arch/arm/include/asm/llc-coloring.h
 create mode 100644 xen/arch/arm/llc-coloring.c

diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
new file mode 100644
index 0000000000..eabf8f5d1b
--- /dev/null
+++ b/docs/misc/arm/cache-coloring.rst
@@ -0,0 +1,97 @@
+Xen cache coloring user guide
+=============================
+
+The cache coloring support in Xen allows to reserve Last Level Cache (LLC)
+partitions for Dom0, DomUs and Xen itself. Currently only ARM64 is supported.
+
+To compile LLC coloring support set ``CONFIG_LLC_COLORING=y``.
+
+If needed, change the maximum number of colors with
+``CONFIG_NR_LLC_COLORS=<n>``.
+
+Compile Xen and the toolstack and then configure it via
+`Command line parameters`_.
+
+Background
+**********
+
+Cache hierarchy of a modern multi-core CPU typically has first levels dedicated
+to each core (hence using multiple cache units), while the last level is shared
+among all of them. Such configuration implies that memory operations on one
+core (e.g. running a DomU) are able to generate interference on another core
+(e.g .hosting another DomU). Cache coloring allows eliminating this
+mutual interference, and thus guaranteeing higher and more predictable
+performances for memory accesses.
+The key concept underlying cache coloring is a fragmentation of the memory
+space into a set of sub-spaces called colors that are mapped to disjoint cache
+partitions. Technically, the whole memory space is first divided into a number
+of subsequent regions. Then each region is in turn divided into a number of
+subsequent sub-colors. The generic i-th color is then obtained by all the
+i-th sub-colors in each region.
+
+::
+
+                            Region j            Region j+1
+                .....................   ............
+                .                     . .
+                .                       .
+            _ _ _______________ _ _____________________ _ _
+                |     |     |     |     |     |     |
+                | c_0 | c_1 |     | c_n | c_0 | c_1 |
+           _ _ _|_____|_____|_ _ _|_____|_____|_____|_ _ _
+                    :                       :
+                    :                       :...         ... .
+                    :                            color 0
+                    :...........................         ... .
+                                                :
+          . . ..................................:
+
+There are two pragmatic lesson to be learnt.
+
+1. If one wants to avoid cache interference between two domains, different
+   colors needs to be used for their memory.
+
+2. Color assignment must privilege contiguity in the partitioning. E.g.,
+   assigning colors (0,1) to domain I  and (2,3) to domain  J is better than
+   assigning colors (0,2) to I and (1,3) to J.
+
+How to compute the number of colors
+***********************************
+
+To compute the number of available colors for a specific platform, the size of
+an LLC way and the page size used by Xen must be known. The first parameter can
+be found in the processor manual or can be also computed dividing the total
+cache size by the number of its ways. The second parameter is the minimum
+amount of memory that can be mapped by the hypervisor, thus dividing the way
+size by the page size, the number of total cache partitions is found. So for
+example, an Arm Cortex-A53 with a 16-ways associative 1 MiB LLC, can isolate up
+to 16 colors when pages are 4 KiB in size.
+
+Cache layout is probed automatically by Xen itself, but a possibility to
+manually set the way size it's left for the user to overcome failing situations
+or for debugging/testing purposes. See `Command line parameters`_ for more
+information on that.
+
+Command line parameters
+***********************
+
+More specific documentation is available at `docs/misc/xen-command-line.pandoc`.
+
++----------------------+-------------------------------+
+| **Parameter**        | **Description**               |
++----------------------+-------------------------------+
+| ``llc-coloring``     | enable coloring at runtime    |
++----------------------+-------------------------------+
+| ``llc-way-size``     | set the LLC way size          |
++----------------------+-------------------------------+
+
+Known issues and limitations
+****************************
+
+"xen,static-mem" isn't supported when coloring is enabled
+#########################################################
+
+In the domain configuration, "xen,static-mem" allows memory to be statically
+allocated to the domain. This isn't possibile when LLC coloring is enabled,
+because that memory can't be guaranteed to use only colors assigned to the
+domain.
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 8e65f8bd18..22d2d5b6cf 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -1713,6 +1713,34 @@ This option is intended for debugging purposes only.  Enable MSR_DEBUGCTL.LBR
 in hypervisor context to be able to dump the Last Interrupt/Exception To/From
 record with other registers.
 
+### llc-coloring (arm64)
+> `= <boolean>`
+
+> Default: `false`
+
+Flag to enable or disable LLC coloring support at runtime. This options is
+available only when `CONFIG_LLC_COLORING` is enabled. See the general
+cache coloring documentation for more info.
+
+### llc-way-size (arm64)
+> `= <size>`
+
+> Default: `Obtained from the hardware`
+
+Specify the way size of the Last Level Cache. This options is available only
+when `CONFIG_LLC_COLORING` is enabled. It is an optional, expert-only parameter
+and it is used to calculate the number of available LLC colors on the platform.
+It can be obtained by dividing the total LLC size by the number of its
+associative ways.
+By default, the value is automatically computed by probing the hardware, but in
+case of specific needs, it can be manually set. Those include failing probing
+and debugging/testing purposes so that it's possibile to emulate platforms with
+different number of supported colors.
+An important detail to highlight is that the current implementation of the
+cache coloring technique requires the number of colors to be a power of 2, and
+consequently, also the LLC way size must be so. A value that doesn't match this
+requirement is aligned down to the previous power of 2.
+
 ### lock-depth-size
 > `= <integer>`
 
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 50e9bfae1a..55143f86a9 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -8,6 +8,7 @@ config ARM_64
 	depends on !ARM_32
 	select 64BIT
 	select HAS_FAST_MULTIPLY
+	select HAS_LLC_COLORING
 
 config ARM
 	def_bool y
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 33c677672f..c9a1cd298d 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_IOREQ_SERVER) += ioreq.o
 obj-y += irq.o
 obj-y += kernel.init.o
 obj-$(CONFIG_LIVEPATCH) += livepatch.o
+obj-$(CONFIG_LLC_COLORING) += llc-coloring.o
 obj-y += mem_access.o
 obj-y += mm.o
 obj-y += monitor.o
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index fb63ec6fd1..1142f7f74a 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -5,6 +5,7 @@
 #include <xen/grant_table.h>
 #include <xen/iocap.h>
 #include <xen/libfdt/libfdt.h>
+#include <xen/llc-coloring.h>
 #include <xen/sched.h>
 #include <xen/serial.h>
 #include <xen/sizes.h>
@@ -879,7 +880,12 @@ void __init create_domUs(void)
             panic("No more domain IDs available\n");
 
         if ( dt_find_property(node, "xen,static-mem", NULL) )
+        {
+            if ( llc_coloring_enabled )
+                panic("LLC coloring and static memory are incompatible\n");
+
             flags |= CDF_staticmem;
+        }
 
         if ( dt_property_read_bool(node, "direct-map") )
         {
diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
new file mode 100644
index 0000000000..7885e9e3f5
--- /dev/null
+++ b/xen/arch/arm/include/asm/llc-coloring.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Last Level Cache (LLC) coloring support for ARM
+ *
+ * Copyright (C) 2022 Xilinx Inc.
+ *
+ * Authors:
+ *    Luca Miccio <lucmiccio@gmail.com>
+ *    Carlo Nonato <carlo.nonato@minervasys.tech>
+ */
+#ifndef __ASM_ARM_COLORING_H__
+#define __ASM_ARM_COLORING_H__
+
+#include <xen/init.h>
+
+bool __init llc_coloring_init(void);
+
+#endif /* __ASM_ARM_COLORING_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h
index 8e02410465..fd5e8eba98 100644
--- a/xen/arch/arm/include/asm/processor.h
+++ b/xen/arch/arm/include/asm/processor.h
@@ -18,6 +18,22 @@
 #define CTR_IDC_SHIFT       28
 #define CTR_DIC_SHIFT       29
 
+/* CCSIDR Current Cache Size ID Register */
+#define CCSIDR_LINESIZE_MASK            _AC(0x7, ULL)
+#define CCSIDR_NUMSETS_SHIFT            13
+#define CCSIDR_NUMSETS_MASK             _AC(0x3fff, ULL)
+#define CCSIDR_NUMSETS_SHIFT_FEAT_CCIDX 32
+#define CCSIDR_NUMSETS_MASK_FEAT_CCIDX  _AC(0xffffff, ULL)
+
+/* CCSELR Cache Size Selection Register */
+#define CCSELR_LEVEL_MASK  _AC(0x7, UL)
+#define CCSELR_LEVEL_SHIFT 1
+
+/* CLIDR Cache Level ID Register */
+#define CLIDR_CTYPEn_SHIFT(n) (3 * (n - 1))
+#define CLIDR_CTYPEn_MASK     _AC(0x7, UL)
+#define CLIDR_CTYPEn_LEVELS   7
+
 #define ICACHE_POLICY_VPIPT  0
 #define ICACHE_POLICY_AIVIVT 1
 #define ICACHE_POLICY_VIPT   2
diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
new file mode 100644
index 0000000000..37d647f038
--- /dev/null
+++ b/xen/arch/arm/llc-coloring.c
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Last Level Cache (LLC) coloring support for ARM
+ *
+ * Copyright (C) 2022 Xilinx Inc.
+ *
+ * Authors:
+ *    Luca Miccio <lucmiccio@gmail.com>
+ *    Carlo Nonato <carlo.nonato@minervasys.tech>
+ */
+#include <xen/errno.h>
+#include <xen/keyhandler.h>
+#include <xen/llc-coloring.h>
+#include <xen/param.h>
+#include <xen/types.h>
+
+#include <asm/processor.h>
+#include <asm/sysregs.h>
+
+bool __ro_after_init llc_coloring_enabled;
+boolean_param("llc-coloring", llc_coloring_enabled);
+
+/* Size of an LLC way */
+static unsigned int __ro_after_init llc_way_size;
+size_param("llc-way-size", llc_way_size);
+/* Number of colors available in the LLC */
+static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
+
+/* Return the LLC way size by probing the hardware */
+static unsigned int __init get_llc_way_size(void)
+{
+    register_t ccsidr_el1;
+    register_t clidr_el1 = READ_SYSREG(CLIDR_EL1);
+    register_t csselr_el1 = READ_SYSREG(CSSELR_EL1);
+    register_t id_aa64mmfr2_el1 = READ_SYSREG(ID_AA64MMFR2_EL1);
+    uint32_t ccsidr_numsets_shift = CCSIDR_NUMSETS_SHIFT;
+    uint32_t ccsidr_numsets_mask = CCSIDR_NUMSETS_MASK;
+    unsigned int n, line_size, num_sets;
+
+    for ( n = CLIDR_CTYPEn_LEVELS;
+          n != 0 && !((clidr_el1 >> CLIDR_CTYPEn_SHIFT(n)) & CLIDR_CTYPEn_MASK);
+          n-- );
+
+    if ( n == 0 )
+        return 0;
+
+    WRITE_SYSREG(((n - 1) & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT,
+                 CSSELR_EL1);
+    isb();
+
+    ccsidr_el1 = READ_SYSREG(CCSIDR_EL1);
+
+    /* Arm ARM: (Log2(Number of bytes in cache line)) - 4 */
+    line_size = 1 << ((ccsidr_el1 & CCSIDR_LINESIZE_MASK) + 4);
+
+    /* If FEAT_CCIDX is enabled, CCSIDR_EL1 has a different bit layout */
+    if ( (id_aa64mmfr2_el1 >> ID_AA64MMFR2_CCIDX_SHIFT) & 0x7 )
+    {
+        ccsidr_numsets_shift = CCSIDR_NUMSETS_SHIFT_FEAT_CCIDX;
+        ccsidr_numsets_mask = CCSIDR_NUMSETS_MASK_FEAT_CCIDX;
+    }
+    /* Arm ARM: (Number of sets in cache) - 1 */
+    num_sets = ((ccsidr_el1 >> ccsidr_numsets_shift) & ccsidr_numsets_mask) + 1;
+
+    printk(XENLOG_INFO "LLC found: L%u (line size: %u bytes, sets num: %u)\n",
+           n, line_size, num_sets);
+
+    /* Restore value in CSSELR_EL1 */
+    WRITE_SYSREG(csselr_el1, CSSELR_EL1);
+    isb();
+
+    return line_size * num_sets;
+}
+
+static void print_colors(unsigned int *colors, unsigned int num_colors)
+{
+    unsigned int i;
+
+    printk("{ ");
+    for ( i = 0; i < num_colors; i++ ) {
+        unsigned int start = colors[i], end = colors[i];
+
+        printk("%u", start);
+
+        for ( ;
+              i < num_colors - 1 && colors[i] + 1 == colors[i + 1];
+              i++, end++ );
+
+        if ( start != end )
+            printk("-%u", end);
+
+        if ( i < num_colors - 1 )
+            printk(", ");
+    }
+    printk(" }\n");
+}
+
+static void dump_coloring_info(unsigned char key)
+{
+    printk("'%c' pressed -> dumping LLC coloring general info\n", key);
+    printk("LLC way size: %u KiB\n", llc_way_size >> 10);
+    printk("Number of LLC colors supported: %u\n", nr_colors);
+}
+
+bool __init llc_coloring_init(void)
+{
+    if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
+    {
+        printk(XENLOG_ERR
+               "Probed LLC way size is 0 and no custom value provided\n");
+        return false;
+    }
+
+    /*
+     * The maximum number of colors must be a power of 2 in order to correctly
+     * map them to bits of an address, so also the LLC way size must be so.
+     */
+    if ( llc_way_size & (llc_way_size - 1) )
+    {
+        printk(XENLOG_WARNING "LLC way size (%u) isn't a power of 2.\n",
+               llc_way_size);
+        llc_way_size = 1U << flsl(llc_way_size);
+        printk(XENLOG_WARNING
+               "Using %u instead. Performances will be suboptimal\n",
+               llc_way_size);
+    }
+
+    nr_colors = llc_way_size >> PAGE_SHIFT;
+
+    if ( nr_colors < 2 || nr_colors > CONFIG_NR_LLC_COLORS )
+    {
+        printk(XENLOG_ERR "Number of LLC colors (%u) not in range [2, %u]\n",
+               nr_colors, CONFIG_NR_LLC_COLORS);
+        return false;
+    }
+
+    register_keyhandler('K', dump_coloring_info, "dump LLC coloring info", 1);
+
+    return true;
+}
+
+void domain_llc_coloring_free(struct domain *d)
+{
+    xfree(d->llc_colors);
+}
+
+void domain_dump_llc_colors(struct domain *d)
+{
+    printk("Domain %pd has %u LLC colors: ", d, d->num_llc_colors);
+    print_colors(d->llc_colors, d->num_llc_colors);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 59dd9bb25a..4c16b566db 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -12,6 +12,7 @@
 #include <xen/device_tree.h>
 #include <xen/domain_page.h>
 #include <xen/grant_table.h>
+#include <xen/llc-coloring.h>
 #include <xen/types.h>
 #include <xen/string.h>
 #include <xen/serial.h>
@@ -746,6 +747,12 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
     printk("Command line: %s\n", cmdline);
     cmdline_parse(cmdline);
 
+    if ( llc_coloring_enabled )
+    {
+        if ( !llc_coloring_init() )
+            panic("Xen LLC coloring support: setup failed\n");
+    }
+
     setup_mm();
 
     /* Parse the ACPI tables for possible boot-time configuration */
-- 
2.34.1



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

* [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
  2024-01-02  9:51 ` [PATCH v5 01/13] xen/common: add cache coloring common code Carlo Nonato
  2024-01-02  9:51 ` [PATCH v5 02/13] xen/arm: add cache coloring initialization Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-04 19:54   ` Julien Grall
  2024-01-02  9:51 ` [PATCH v5 04/13] xen: extend domctl interface for cache coloring Carlo Nonato
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Andrew Cooper, George Dunlap,
	Jan Beulich, Wei Liu, Marco Solieri

This commit allows the user to set the cache coloring configuration for
Dom0 via a command line parameter.
Since cache coloring and static memory are incompatible, direct mapping
Dom0 isn't possible when coloring is enabled.

A common configuration syntax for cache colors is also introduced.

Based on original work from: Luca Miccio <lucmiccio@gmail.com>

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- Carlo Nonato as the new author
- moved dom0 colors parsing (parse_colors()) in this patch
- added dom0_set_llc_colors() to set dom0 colors after creation
- moved color allocation and checking in this patch
- error handling when allocating color arrays
- FIXME: copy pasted allocate_memory() cause it got moved
v4:
- dom0 colors are dynamically allocated as for any other domain
  (colors are duplicated in dom0_colors and in the new array, but logic
  is simpler)
---
 docs/misc/arm/cache-coloring.rst        |  29 ++++++
 docs/misc/xen-command-line.pandoc       |   9 ++
 xen/arch/arm/domain_build.c             |  60 ++++++++++-
 xen/arch/arm/include/asm/llc-coloring.h |   1 +
 xen/arch/arm/llc-coloring.c             | 128 ++++++++++++++++++++++++
 5 files changed, 224 insertions(+), 3 deletions(-)

diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
index eabf8f5d1b..acf82c3df8 100644
--- a/docs/misc/arm/cache-coloring.rst
+++ b/docs/misc/arm/cache-coloring.rst
@@ -84,6 +84,35 @@ More specific documentation is available at `docs/misc/xen-command-line.pandoc`.
 +----------------------+-------------------------------+
 | ``llc-way-size``     | set the LLC way size          |
 +----------------------+-------------------------------+
+| ``dom0-llc-colors``  | Dom0 color configuration      |
++----------------------+-------------------------------+
+
+Colors selection format
+***********************
+
+Regardless of the memory pool that has to be colored (Xen, Dom0/DomUs),
+the color selection can be expressed using the same syntax. In particular a
+comma-separated list of colors or ranges of colors is used.
+Ranges are hyphen-separated intervals (such as `0-4`) and are inclusive on both
+sides.
+
+Note that:
+
+- no spaces are allowed between values.
+- no overlapping ranges or duplicated colors are allowed.
+- values must be written in ascending order.
+
+Examples:
+
++-------------------+-----------------------------+
+| **Configuration** | **Actual selection**        |
++-------------------+-----------------------------+
+| 1-2,5-8           | [1, 2, 5, 6, 7, 8]          |
++-------------------+-----------------------------+
+| 4-8,10,11,12      | [4, 5, 6, 7, 8, 10, 11, 12] |
++-------------------+-----------------------------+
+| 0                 | [0]                         |
++-------------------+-----------------------------+
 
 Known issues and limitations
 ****************************
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 22d2d5b6cf..51f6adf035 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -963,6 +963,15 @@ Controls for the dom0 IOMMU setup.
 
 Specify a list of IO ports to be excluded from dom0 access.
 
+### dom0-llc-colors (arm64)
+> `= List of [ <integer> | <integer>-<integer> ]`
+
+> Default: `All available LLC colors`
+
+Specify dom0 LLC color configuration. This options is available only when
+`CONFIG_LLC_COLORING` is enabled. If the parameter is not set, all available
+colors are chosen and the user is warned on Xen serial console.
+
 ### dom0_max_vcpus
 
 Either:
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 6945b9755d..482c059bfa 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2,6 +2,7 @@
 #include <xen/init.h>
 #include <xen/compile.h>
 #include <xen/lib.h>
+#include <xen/llc-coloring.h>
 #include <xen/mm.h>
 #include <xen/param.h>
 #include <xen/domain_page.h>
@@ -414,7 +415,7 @@ static void __init allocate_memory_11(struct domain *d,
     }
 }
 
-#ifdef CONFIG_DOM0LESS_BOOT
+#if defined(CONFIG_DOM0LESS_BOOT) || defined(CONFIG_LLC_COLORING)
 bool __init allocate_bank_memory(struct domain *d, struct kernel_info *kinfo,
                                  gfn_t sgfn, paddr_t tot_size)
 {
@@ -478,6 +479,49 @@ bool __init allocate_bank_memory(struct domain *d, struct kernel_info *kinfo,
 }
 #endif
 
+static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
+{
+    unsigned int i;
+    paddr_t bank_size;
+
+    printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n",
+           /* Don't want format this as PRIpaddr (16 digit hex) */
+           (unsigned long)(kinfo->unassigned_mem >> 20), d);
+
+    kinfo->mem.nr_banks = 0;
+    bank_size = MIN(GUEST_RAM0_SIZE, kinfo->unassigned_mem);
+    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM0_BASE),
+                               bank_size) )
+        goto fail;
+
+    bank_size = MIN(GUEST_RAM1_SIZE, kinfo->unassigned_mem);
+    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM1_BASE),
+                               bank_size) )
+        goto fail;
+
+    if ( kinfo->unassigned_mem )
+        goto fail;
+
+    for( i = 0; i < kinfo->mem.nr_banks; i++ )
+    {
+        printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
+               d,
+               i,
+               kinfo->mem.bank[i].start,
+               kinfo->mem.bank[i].start + kinfo->mem.bank[i].size,
+               /* Don't want format this as PRIpaddr (16 digit hex) */
+               (unsigned long)(kinfo->mem.bank[i].size >> 20));
+    }
+
+    return;
+
+fail:
+    panic("Failed to allocate requested domain memory."
+          /* Don't want format this as PRIpaddr (16 digit hex) */
+          " %ldKB unallocated. Fix the VMs configurations.\n",
+          (unsigned long)kinfo->unassigned_mem >> 10);
+}
+
 /*
  * When PCI passthrough is available we want to keep the
  * "linux,pci-domain" in sync for every host bridge.
@@ -2072,7 +2116,10 @@ static int __init construct_dom0(struct domain *d)
     /* type must be set before allocate_memory */
     d->arch.type = kinfo.type;
 #endif
-    allocate_memory_11(d, &kinfo);
+    if ( is_domain_llc_colored(d) )
+        allocate_memory(d, &kinfo);
+    else
+        allocate_memory_11(d, &kinfo);
     find_gnttab_region(d, &kinfo);
 
     rc = process_shm_chosen(d, &kinfo);
@@ -2116,6 +2163,7 @@ void __init create_dom0(void)
         .max_maptrack_frames = -1,
         .grant_opts = XEN_DOMCTL_GRANT_version(opt_gnttab_max_version),
     };
+    unsigned int flags = CDF_privileged;
     int rc;
 
     /* The vGIC for DOM0 is exactly emulating the hardware GIC */
@@ -2143,10 +2191,16 @@ void __init create_dom0(void)
             panic("SVE vector length error\n");
     }
 
-    dom0 = domain_create(0, &dom0_cfg, CDF_privileged | CDF_directmap);
+    if ( !llc_coloring_enabled )
+        flags |= CDF_directmap;
+
+    dom0 = domain_create(0, &dom0_cfg, flags);
     if ( IS_ERR(dom0) )
         panic("Error creating domain 0 (rc = %ld)\n", PTR_ERR(dom0));
 
+    if ( llc_coloring_enabled && (rc = dom0_set_llc_colors(dom0)) )
+        panic("Error initializing LLC coloring for domain 0 (rc = %d)", rc);
+
     if ( alloc_dom0_vcpu0(dom0) == NULL )
         panic("Error creating domain 0 vcpu0\n");
 
diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
index 7885e9e3f5..ee5551e3cc 100644
--- a/xen/arch/arm/include/asm/llc-coloring.h
+++ b/xen/arch/arm/include/asm/llc-coloring.h
@@ -14,6 +14,7 @@
 #include <xen/init.h>
 
 bool __init llc_coloring_init(void);
+int dom0_set_llc_colors(struct domain *d);
 
 #endif /* __ASM_ARM_COLORING_H__ */
 
diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
index 37d647f038..5ce58aba70 100644
--- a/xen/arch/arm/llc-coloring.c
+++ b/xen/arch/arm/llc-coloring.c
@@ -26,6 +26,63 @@ size_param("llc-way-size", llc_way_size);
 /* Number of colors available in the LLC */
 static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
 
+static unsigned int __ro_after_init dom0_colors[CONFIG_NR_LLC_COLORS];
+static unsigned int __ro_after_init dom0_num_colors;
+
+/*
+ * Parse the coloring configuration given in the buf string, following the
+ * syntax below.
+ *
+ * COLOR_CONFIGURATION ::= COLOR | RANGE,...,COLOR | RANGE
+ * RANGE               ::= COLOR-COLOR
+ *
+ * Example: "0,2-6,15-16" represents the set of colors: 0,2,3,4,5,6,15,16.
+ */
+static int parse_color_config(const char *buf, unsigned int *colors,
+                              unsigned int *num_colors)
+{
+    const char *s = buf;
+
+    if ( !colors || !num_colors )
+        return -EINVAL;
+
+    *num_colors = 0;
+
+    while ( *s != '\0' )
+    {
+        if ( *s != ',' )
+        {
+            unsigned int color, start, end;
+
+            start = simple_strtoul(s, &s, 0);
+
+            if ( *s == '-' )    /* Range */
+            {
+                s++;
+                end = simple_strtoul(s, &s, 0);
+            }
+            else                /* Single value */
+                end = start;
+
+            if ( start > end || (end - start) > UINT_MAX - *num_colors ||
+                 *num_colors + (end - start) >= nr_colors )
+                return -EINVAL;
+            for ( color = start; color <= end; color++ )
+                colors[(*num_colors)++] = color;
+        }
+        else
+            s++;
+    }
+
+    return *s ? -EINVAL : 0;
+}
+
+static int __init parse_dom0_colors(const char *s)
+{
+    return parse_color_config(s, dom0_colors, &dom0_num_colors);
+}
+custom_param("dom0-llc-colors", parse_dom0_colors);
+
 /* Return the LLC way size by probing the hardware */
 static unsigned int __init get_llc_way_size(void)
 {
@@ -102,6 +159,28 @@ static void dump_coloring_info(unsigned char key)
     printk("Number of LLC colors supported: %u\n", nr_colors);
 }
 
+static bool check_colors(unsigned int *colors, unsigned int num_colors)
+{
+    unsigned int i;
+
+    if ( num_colors > nr_colors )
+    {
+        printk(XENLOG_ERR "Number of LLC colors requested > %u\n", nr_colors);
+        return false;
+    }
+
+    for ( i = 0; i < num_colors; i++ )
+    {
+        if ( colors[i] >= nr_colors )
+        {
+            printk(XENLOG_ERR "LLC color %u >= %u\n", colors[i], nr_colors);
+            return false;
+        }
+    }
+
+    return true;
+}
+
 bool __init llc_coloring_init(void)
 {
     if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
@@ -150,6 +229,55 @@ void domain_dump_llc_colors(struct domain *d)
     print_colors(d->llc_colors, d->num_llc_colors);
 }
 
+static int domain_alloc_colors(struct domain *d, unsigned int num_colors)
+{
+    d->num_llc_colors = num_colors;
+
+    if ( !num_colors )
+        return 0;
+
+    d->llc_colors = xmalloc_array(unsigned int, num_colors);
+    if ( !d->llc_colors )
+    {
+        printk("Can't allocate LLC colors for domain %pd\n", d);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int domain_check_colors(struct domain *d)
+{
+    unsigned int i;
+
+    if ( !d->num_llc_colors )
+    {
+        printk(XENLOG_WARNING
+               "LLC color config not found for %pd. Using default\n", d);
+        if ( domain_alloc_colors(d, nr_colors) )
+            return -ENOMEM;
+        for ( i = 0; i < nr_colors; i++ )
+            d->llc_colors[i] = i;
+    }
+    else if ( !check_colors(d->llc_colors, d->num_llc_colors) )
+    {
+        printk(XENLOG_ERR "Bad LLC color config for %pd\n", d);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+int dom0_set_llc_colors(struct domain *d)
+{
+    if ( domain_alloc_colors(d, dom0_num_colors) )
+        return -ENOMEM;
+
+    memcpy(d->llc_colors, dom0_colors, sizeof(unsigned int) * dom0_num_colors);
+
+    return domain_check_colors(d);
+}
+
 /*
  * Local variables:
  * mode: C
-- 
2.34.1



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

* [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (2 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-05 17:26   ` Julien Grall
  2024-01-08  8:43   ` Jan Beulich
  2024-01-02  9:51 ` [PATCH v5 05/13] tools: add support for cache coloring configuration Carlo Nonato
                   ` (9 subsequent siblings)
  13 siblings, 2 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Andrew Cooper, George Dunlap,
	Jan Beulich, Wei Liu, Marco Solieri

This commit updates the domctl interface to allow the user to set cache
coloring configurations from the toolstack.
It also implements the functionality for arm64.

Based on original work from: Luca Miccio <lucmiccio@gmail.com>

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- added a new hypercall to set colors
- uint for the guest handle
v4:
- updated XEN_DOMCTL_INTERFACE_VERSION
---
 xen/arch/arm/llc-coloring.c    | 17 +++++++++++++++++
 xen/common/domctl.c            | 11 +++++++++++
 xen/include/public/domctl.h    | 10 +++++++++-
 xen/include/xen/llc-coloring.h |  3 +++
 4 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
index 5ce58aba70..a08614ec36 100644
--- a/xen/arch/arm/llc-coloring.c
+++ b/xen/arch/arm/llc-coloring.c
@@ -9,6 +9,7 @@
  *    Carlo Nonato <carlo.nonato@minervasys.tech>
  */
 #include <xen/errno.h>
+#include <xen/guest_access.h>
 #include <xen/keyhandler.h>
 #include <xen/llc-coloring.h>
 #include <xen/param.h>
@@ -278,6 +279,22 @@ int dom0_set_llc_colors(struct domain *d)
     return domain_check_colors(d);
 }
 
+int domain_set_llc_colors_domctl(struct domain *d,
+                                 const struct xen_domctl_set_llc_colors *config)
+{
+    if ( d->num_llc_colors )
+        return -EEXIST;
+
+    if ( domain_alloc_colors(d, config->num_llc_colors) )
+        return -ENOMEM;
+
+    if ( copy_from_guest(d->llc_colors, config->llc_colors,
+                         config->num_llc_colors) )
+        return -EFAULT;
+
+    return domain_check_colors(d);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index f5a71ee5f7..b6867d0602 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -8,6 +8,7 @@
 
 #include <xen/types.h>
 #include <xen/lib.h>
+#include <xen/llc-coloring.h>
 #include <xen/err.h>
 #include <xen/mm.h>
 #include <xen/sched.h>
@@ -858,6 +859,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
                 __HYPERVISOR_domctl, "h", u_domctl);
         break;
 
+    case XEN_DOMCTL_set_llc_colors:
+        if ( !llc_coloring_enabled )
+            break;
+
+        ret = domain_set_llc_colors_domctl(d, &op->u.set_llc_colors);
+        if ( ret == -EEXIST )
+            printk(XENLOG_ERR
+                   "Can't set LLC colors on an already created domain\n");
+        break;
+
     default:
         ret = arch_do_domctl(op, d, u_domctl);
         break;
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index a33f9ec32b..2b12069294 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -21,7 +21,7 @@
 #include "hvm/save.h"
 #include "memory.h"
 
-#define XEN_DOMCTL_INTERFACE_VERSION 0x00000016
+#define XEN_DOMCTL_INTERFACE_VERSION 0x00000017
 
 /*
  * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
@@ -1190,6 +1190,12 @@ struct xen_domctl_vmtrace_op {
 typedef struct xen_domctl_vmtrace_op xen_domctl_vmtrace_op_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_vmtrace_op_t);
 
+struct xen_domctl_set_llc_colors {
+    /* IN LLC coloring parameters */
+    unsigned int num_llc_colors;
+    XEN_GUEST_HANDLE_64(uint) llc_colors;
+};
+
 struct xen_domctl {
     uint32_t cmd;
 #define XEN_DOMCTL_createdomain                   1
@@ -1277,6 +1283,7 @@ struct xen_domctl {
 #define XEN_DOMCTL_vmtrace_op                    84
 #define XEN_DOMCTL_get_paging_mempool_size       85
 #define XEN_DOMCTL_set_paging_mempool_size       86
+#define XEN_DOMCTL_set_llc_colors                87
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -1339,6 +1346,7 @@ struct xen_domctl {
         struct xen_domctl_vuart_op          vuart_op;
         struct xen_domctl_vmtrace_op        vmtrace_op;
         struct xen_domctl_paging_mempool    paging_mempool;
+        struct xen_domctl_set_llc_colors    set_llc_colors;
         uint8_t                             pad[128];
     } u;
 };
diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
index cedd97d4b5..fa2edc8ad8 100644
--- a/xen/include/xen/llc-coloring.h
+++ b/xen/include/xen/llc-coloring.h
@@ -33,6 +33,9 @@ extern bool llc_coloring_enabled;
 void domain_llc_coloring_free(struct domain *d);
 void domain_dump_llc_colors(struct domain *d);
 
+int domain_set_llc_colors_domctl(struct domain *d,
+                                 const struct xen_domctl_set_llc_colors *config);
+
 #endif /* __COLORING_H__ */
 
 /*
-- 
2.34.1



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

* [PATCH v5 05/13] tools: add support for cache coloring configuration
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (3 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 04/13] xen: extend domctl interface for cache coloring Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-02  9:51 ` [PATCH v5 06/13] xen/arm: add support for cache coloring configuration via device-tree Carlo Nonato
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Wei Liu, Anthony PERARD, Juergen Gross, Marco Solieri

Add a new "llc_colors" parameter that defines the LLC color assignment for
a domain. The user can specify one or more color ranges using the same
syntax used everywhere else for color config described in the
documentation.
The parameter is defined as a list of strings that represent the color
ranges.

Documentation is also added.

Based on original work from: Luca Miccio <lucmiccio@gmail.com>

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- added LIBXL_HAVE_BUILDINFO_LLC_COLORS
- moved color configuration in xc_domain_set_llc_colors() cause of the new
  hypercall
v4:
- removed overlapping color ranges checks during parsing
- moved hypercall buffer initialization in libxenctrl
---
 docs/man/xl.cfg.5.pod.in         | 10 +++++++++
 tools/include/libxl.h            |  5 +++++
 tools/include/xenctrl.h          |  9 ++++++++
 tools/libs/ctrl/xc_domain.c      | 34 ++++++++++++++++++++++++++++
 tools/libs/light/libxl_create.c  |  9 ++++++++
 tools/libs/light/libxl_types.idl |  1 +
 tools/xl/xl_parse.c              | 38 +++++++++++++++++++++++++++++++-
 7 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index 2e234b450e..c50b280190 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -3031,6 +3031,16 @@ raised.
 
 =back
 
+=over 4
+
+=item B<llc_colors=[ "RANGE", "RANGE", ...]>
+
+Specify the Last Level Cache (LLC) color configuration for the guest.
+B<RANGE> can be either a single color value or a hypen-separated closed
+interval of colors (such as "0-4").
+
+=back
+
 =head3 x86
 
 =over 4
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index 907aa0a330..16f56913b2 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -1340,6 +1340,11 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src);
  */
 #define LIBXL_HAVE_BUILDINFO_HVM_SYSTEM_FIRMWARE
 
+/*
+ * The libxl_domain_build_info has the llc_colors array.
+ */
+#define LIBXL_HAVE_BUILDINFO_LLC_COLORS 1
+
 /*
  * ERROR_REMUS_XXX error code only exists from Xen 4.5, Xen 4.6 and it
  * is changed to ERROR_CHECKPOINT_XXX in Xen 4.7
diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
index 2ef8b4e054..4b541fffd2 100644
--- a/tools/include/xenctrl.h
+++ b/tools/include/xenctrl.h
@@ -2653,6 +2653,15 @@ int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout, uint32
 int xc_domain_cacheflush(xc_interface *xch, uint32_t domid,
                          xen_pfn_t start_pfn, xen_pfn_t nr_pfns);
 
+/*
+ * Set LLC colors for a domain.
+ * This is an internal hypercall. It can only be used directly after domain
+ * creation. An attempt to use it afterwards will result in an error.
+ */
+int xc_domain_set_llc_colors(xc_interface *xch, uint32_t domid,
+                             const unsigned int *llc_colors,
+                             unsigned int num_llc_colors);
+
 #if defined(__arm__) || defined(__aarch64__)
 int xc_dt_overlay(xc_interface *xch, void *overlay_fdt,
                   uint32_t overlay_fdt_size, uint8_t overlay_op);
diff --git a/tools/libs/ctrl/xc_domain.c b/tools/libs/ctrl/xc_domain.c
index f2d9d14b4d..734f68acd6 100644
--- a/tools/libs/ctrl/xc_domain.c
+++ b/tools/libs/ctrl/xc_domain.c
@@ -2180,6 +2180,40 @@ int xc_domain_soft_reset(xc_interface *xch,
     domctl.domain = domid;
     return do_domctl(xch, &domctl);
 }
+
+int xc_domain_set_llc_colors(xc_interface *xch, uint32_t domid,
+                             const unsigned int *llc_colors,
+                             unsigned int num_llc_colors)
+{
+    DECLARE_DOMCTL;
+    DECLARE_HYPERCALL_BUFFER(uint32_t, local);
+    int ret = -1;
+
+    if ( num_llc_colors )
+    {
+        size_t bytes = sizeof(uint32_t) * num_llc_colors;
+
+        local = xc_hypercall_buffer_alloc(xch, local, bytes);
+        if ( local == NULL )
+        {
+            PERROR("Could not allocate LLC colors for set_llc_colors");
+            return -ENOMEM;
+        }
+        memcpy(local, llc_colors, bytes);
+        set_xen_guest_handle(domctl.u.set_llc_colors.llc_colors, local);
+    }
+
+    domctl.cmd = XEN_DOMCTL_set_llc_colors;
+    domctl.domain = domid;
+    domctl.u.set_llc_colors.num_llc_colors = num_llc_colors;
+
+    ret = do_domctl(xch, &domctl);
+
+    if ( local )
+        xc_hypercall_buffer_free(xch, local);
+
+    return ret;
+}
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c
index ce1d431103..db25019452 100644
--- a/tools/libs/light/libxl_create.c
+++ b/tools/libs/light/libxl_create.c
@@ -725,6 +725,15 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
             /* A new domain now exists */
             *domid = local_domid;
 
+            ret = xc_domain_set_llc_colors(ctx->xch, local_domid,
+                                           b_info->llc_colors,
+                                           b_info->num_llc_colors);
+            if (ret < 0) {
+                LOGED(ERROR, local_domid, "LLC colors allocation failed");
+                rc = ERROR_FAIL;
+                goto out;
+            }
+
             rc = libxl__is_domid_recent(gc, local_domid, &recent);
             if (rc)
                 goto out;
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index 7d8bd5d216..78031d8bcb 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -610,6 +610,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
     ("ioports",          Array(libxl_ioport_range, "num_ioports")),
     ("irqs",             Array(uint32, "num_irqs")),
     ("iomem",            Array(libxl_iomem_range, "num_iomem")),
+    ("llc_colors",       Array(uint32, "num_llc_colors")),
     ("claim_mode",	     libxl_defbool),
     ("event_channels",   uint32),
     ("kernel",           string),
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index ed983200c3..0eefe873a4 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -1294,7 +1294,7 @@ void parse_config_data(const char *config_source,
     XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
                    *usbctrls, *usbdevs, *p9devs, *vdispls, *pvcallsifs_devs;
     XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs,
-                   *mca_caps, *smbios;
+                   *mca_caps, *smbios, *llc_colors;
     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian, num_mca_caps;
     int num_smbios;
     int pci_power_mgmt = 0;
@@ -1302,6 +1302,7 @@ void parse_config_data(const char *config_source,
     int pci_permissive = 0;
     int pci_seize = 0;
     int i, e;
+    int num_llc_colors;
     char *kernel_basename;
 
     libxl_domain_create_info *c_info = &d_config->c_info;
@@ -1445,6 +1446,41 @@ void parse_config_data(const char *config_source,
     if (!xlu_cfg_get_long (config, "maxmem", &l, 0))
         b_info->max_memkb = l * 1024;
 
+    if (!xlu_cfg_get_list(config, "llc_colors", &llc_colors, &num_llc_colors, 0)) {
+        int cur_index = 0;
+
+        b_info->num_llc_colors = 0;
+        for (i = 0; i < num_llc_colors; i++) {
+            uint32_t start = 0, end = 0, k;
+
+            buf = xlu_cfg_get_listitem(llc_colors, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Can't get element %d in LLC color list\n", i);
+                exit(1);
+            }
+
+            if (sscanf(buf, "%" SCNu32 "-%" SCNu32, &start, &end) != 2) {
+                if (sscanf(buf, "%" SCNu32, &start) != 1) {
+                    fprintf(stderr, "xl: Invalid LLC color range: %s\n", buf);
+                    exit(1);
+                }
+                end = start;
+            } else if (start > end) {
+                fprintf(stderr,
+                        "xl: Start LLC color is greater than end: %s\n", buf);
+                exit(1);
+            }
+
+            b_info->num_llc_colors += (end - start) + 1;
+            b_info->llc_colors = (uint32_t *)realloc(b_info->llc_colors,
+                        sizeof(*b_info->llc_colors) * b_info->num_llc_colors);
+
+            for (k = start; k <= end; k++)
+                b_info->llc_colors[cur_index++] = k;
+        }
+    }
+
     if (!xlu_cfg_get_long (config, "vcpus", &l, 0)) {
         vcpus = l;
         if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, l)) {
-- 
2.34.1



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

* [PATCH v5 06/13] xen/arm: add support for cache coloring configuration via device-tree
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (4 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 05/13] tools: add support for cache coloring configuration Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-05 17:38   ` Julien Grall
  2024-01-02  9:51 ` [PATCH v5 07/13] xen/page_alloc: introduce init_free_page_fields() helper Carlo Nonato
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Marco Solieri

This commit adds the "llc-colors" Device Tree attribute that can be used
for DomUs and Dom0less color configurations. The syntax is the same used
for every color config.

Based on original work from: Luca Miccio <lucmiccio@gmail.com>

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- static-mem check has been moved in a previous patch
- added domain_set_llc_colors_from_str() to set colors after domain creation
---
 docs/misc/arm/cache-coloring.rst        | 48 ++++++++++++++++++++++++-
 docs/misc/arm/device-tree/booting.txt   |  4 +++
 xen/arch/arm/dom0less-build.c           | 13 +++++++
 xen/arch/arm/include/asm/llc-coloring.h |  1 +
 xen/arch/arm/llc-coloring.c             | 17 +++++++++
 5 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
index acf82c3df8..ae1dd8f4af 100644
--- a/docs/misc/arm/cache-coloring.rst
+++ b/docs/misc/arm/cache-coloring.rst
@@ -10,7 +10,7 @@ If needed, change the maximum number of colors with
 ``CONFIG_NR_LLC_COLORS=<n>``.
 
 Compile Xen and the toolstack and then configure it via
-`Command line parameters`_.
+`Command line parameters`_. For DomUs follow `DomUs configuration`_.
 
 Background
 **********
@@ -114,6 +114,52 @@ Examples:
 | 0                 | [0]                         |
 +-------------------+-----------------------------+
 
+DomUs configuration
+*******************
+
+DomUs colors can be set via Device Tree, also for Dom0less configurations
+(documentation at `docs/misc/arm/device-tree/booting.txt`) using the
+``llc-colors`` option. For example:
+
+::
+
+    xen,xen-bootargs = "console=dtuart dtuart=serial0 dom0_mem=1G dom0_max_vcpus=1 sched=null llc-coloring=on llc-way-size=64K dom0-llc-colors=2-6";
+    xen,dom0-bootargs "console=hvc0 earlycon=xen earlyprintk=xen root=/dev/ram0"
+
+    dom0 {
+        compatible = "xen,linux-zimage" "xen,multiboot-module";
+        reg = <0x0 0x1000000 0x0 15858176>;
+    };
+
+    dom0-ramdisk {
+        compatible = "xen,linux-initrd" "xen,multiboot-module";
+        reg = <0x0 0x2000000 0x0 20638062>;
+    };
+
+    domU0 {
+        #address-cells = <0x1>;
+        #size-cells = <0x1>;
+        compatible = "xen,domain";
+        memory = <0x0 0x40000>;
+        llc-colors = "4-8,10,11,12";
+        cpus = <0x1>;
+        vpl011 = <0x1>;
+
+        module@2000000 {
+            compatible = "multiboot,kernel", "multiboot,module";
+            reg = <0x2000000 0xffffff>;
+            bootargs = "console=ttyAMA0";
+        };
+
+        module@30000000 {
+            compatible = "multiboot,ramdisk", "multiboot,module";
+            reg = <0x3000000 0xffffff>;
+        };
+    };
+
+**Note:** If no color configuration is provided for a domain, the default one,
+which corresponds to all available colors, is used instead.
+
 Known issues and limitations
 ****************************
 
diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
index bbd955e9c2..e9f9862e9c 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -162,6 +162,10 @@ with the following properties:
 
     An integer specifying the number of vcpus to allocate to the guest.
 
+- llc-colors
+    A string specifying the LLC color configuration for the guest.
+    Refer to "docs/misc/arm/cache_coloring.rst" for syntax.
+
 - vpl011
 
     An empty property to enable/disable a virtual pl011 for the guest to
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index 1142f7f74a..eb39f5291f 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -850,6 +850,7 @@ void __init create_domUs(void)
     struct dt_device_node *node;
     const struct dt_device_node *cpupool_node,
                                 *chosen = dt_find_node_by_path("/chosen");
+    const char *llc_colors_str = NULL;
 
     BUG_ON(chosen == NULL);
     dt_for_each_child_node(chosen, node)
@@ -993,6 +994,13 @@ void __init create_domUs(void)
 #endif
         }
 
+        dt_property_read_string(node, "llc-colors", &llc_colors_str);
+        if ( llc_coloring_enabled && !llc_colors_str )
+            panic("'llc-colors' is required when LLC coloring is enabled\n");
+        else if ( !llc_coloring_enabled && llc_colors_str)
+            printk(XENLOG_WARNING
+                   "'llc-colors' found, but LLC coloring is disabled\n");
+
         /*
          * The variable max_init_domid is initialized with zero, so here it's
          * very important to use the pre-increment operator to call
@@ -1003,6 +1011,11 @@ void __init create_domUs(void)
             panic("Error creating domain %s (rc = %ld)\n",
                   dt_node_name(node), PTR_ERR(d));
 
+        if ( llc_coloring_enabled &&
+             (rc = domain_set_llc_colors_from_str(d, llc_colors_str)) )
+            panic("Error initializing LLC coloring for domain %s (rc = %d)\n",
+                  dt_node_name(node), rc);
+
         d->is_console = true;
         dt_device_set_used_by(node, d->domain_id);
 
diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
index ee5551e3cc..5f9b0a8121 100644
--- a/xen/arch/arm/include/asm/llc-coloring.h
+++ b/xen/arch/arm/include/asm/llc-coloring.h
@@ -15,6 +15,7 @@
 
 bool __init llc_coloring_init(void);
 int dom0_set_llc_colors(struct domain *d);
+int domain_set_llc_colors_from_str(struct domain *d, const char *str);
 
 #endif /* __ASM_ARM_COLORING_H__ */
 
diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
index a08614ec36..d3de5f14cb 100644
--- a/xen/arch/arm/llc-coloring.c
+++ b/xen/arch/arm/llc-coloring.c
@@ -295,6 +295,23 @@ int domain_set_llc_colors_domctl(struct domain *d,
     return domain_check_colors(d);
 }
 
+int domain_set_llc_colors_from_str(struct domain *d, const char *str)
+{
+    int err;
+
+    if ( domain_alloc_colors(d, nr_colors) )
+        return -ENOMEM;
+
+    err = parse_color_config(str, d->llc_colors, &d->num_llc_colors);
+    if ( err )
+    {
+        printk(XENLOG_ERR "Error parsing LLC color configuration.");
+        return err;
+    }
+
+    return domain_check_colors(d);
+}
+
 /*
  * Local variables:
  * mode: C
-- 
2.34.1



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

* [PATCH v5 07/13] xen/page_alloc: introduce init_free_page_fields() helper
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (5 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 06/13] xen/arm: add support for cache coloring configuration via device-tree Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-09 10:36   ` Jan Beulich
  2024-01-02  9:51 ` [PATCH v5 08/13] xen/page_alloc: introduce preserved page flags macro Carlo Nonato
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Andrew Cooper, George Dunlap, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu, Marco Solieri

Introduce a new helper to initialize fields that have different uses for
free pages.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- new patch
---
 xen/common/page_alloc.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index d874525916..9ee3981bb5 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -928,6 +928,13 @@ static struct page_info *get_free_buddy(unsigned int zone_lo,
     }
 }
 
+/* Initialise fields which have other uses for free pages. */
+static void init_free_page_fields(struct page_info *pg)
+{
+    pg->u.inuse.type_info = PGT_TYPE_INFO_INITIALIZER;
+    page_set_owner(pg, NULL);
+}
+
 /* Allocate 2^@order contiguous pages. */
 static struct page_info *alloc_heap_pages(
     unsigned int zone_lo, unsigned int zone_hi,
@@ -1036,10 +1043,7 @@ static struct page_info *alloc_heap_pages(
             accumulate_tlbflush(&need_tlbflush, &pg[i],
                                 &tlbflush_timestamp);
 
-        /* Initialise fields which have other uses for free pages. */
-        pg[i].u.inuse.type_info = PGT_TYPE_INFO_INITIALIZER;
-        page_set_owner(&pg[i], NULL);
-
+        init_free_page_fields(&pg[i]);
     }
 
     spin_unlock(&heap_lock);
@@ -2802,9 +2806,7 @@ static bool prepare_staticmem_pages(struct page_info *pg, unsigned long nr_mfns,
          * to PGC_state_inuse.
          */
         pg[i].count_info = PGC_static | PGC_state_inuse;
-        /* Initialise fields which have other uses for free pages. */
-        pg[i].u.inuse.type_info = PGT_TYPE_INFO_INITIALIZER;
-        page_set_owner(&pg[i], NULL);
+        init_free_page_fields(&pg[i]);
     }
 
     spin_unlock(&heap_lock);
-- 
2.34.1



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

* [PATCH v5 08/13] xen/page_alloc: introduce preserved page flags macro
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (6 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 07/13] xen/page_alloc: introduce init_free_page_fields() helper Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-08 17:08   ` Jan Beulich
  2024-01-02  9:51 ` [PATCH v5 09/13] xen: add cache coloring allocator for domains Carlo Nonato
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Andrew Cooper, George Dunlap, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu, Marco Solieri

PGC_static and PGC_extra are flags that needs to be preserved when assigning
a page. Define a new macro that groups those flags and use it instead of
or'ing every time.

The new macro is used also in free_heap_pages() allowing future commits to
extended it with other flags that must stop merging, as it now works for
PGC_static. PGC_extra is no harm here since it's only ever being set on
allocated pages.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- new patch
---
 xen/common/page_alloc.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 9ee3981bb5..3bf3120287 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -158,6 +158,8 @@
 #define PGC_static 0
 #endif
 
+#define preserved_flags (PGC_extra | PGC_static)
+
 #ifndef PGT_TYPE_INFO_INITIALIZER
 #define PGT_TYPE_INFO_INITIALIZER 0
 #endif
@@ -1504,7 +1506,7 @@ static void free_heap_pages(
             /* Merge with predecessor block? */
             if ( !mfn_valid(page_to_mfn(predecessor)) ||
                  !page_state_is(predecessor, free) ||
-                 (predecessor->count_info & PGC_static) ||
+                 (predecessor->count_info & preserved_flags) ||
                  (PFN_ORDER(predecessor) != order) ||
                  (page_to_nid(predecessor) != node) )
                 break;
@@ -1528,7 +1530,7 @@ static void free_heap_pages(
             /* Merge with successor block? */
             if ( !mfn_valid(page_to_mfn(successor)) ||
                  !page_state_is(successor, free) ||
-                 (successor->count_info & PGC_static) ||
+                 (successor->count_info & preserved_flags) ||
                  (PFN_ORDER(successor) != order) ||
                  (page_to_nid(successor) != node) )
                 break;
@@ -2365,7 +2367,7 @@ int assign_pages(
 
         for ( i = 0; i < nr; i++ )
         {
-            ASSERT(!(pg[i].count_info & ~(PGC_extra | PGC_static)));
+            ASSERT(!(pg[i].count_info & ~preserved_flags));
             if ( pg[i].count_info & PGC_extra )
                 extra_pages++;
         }
@@ -2425,7 +2427,7 @@ int assign_pages(
         page_set_owner(&pg[i], d);
         smp_wmb(); /* Domain pointer must be visible before updating refcnt. */
         pg[i].count_info =
-            (pg[i].count_info & (PGC_extra | PGC_static)) | PGC_allocated | 1;
+            (pg[i].count_info & preserved_flags) | PGC_allocated | 1;
 
         page_list_add_tail(&pg[i], page_to_list(d, &pg[i]));
     }
-- 
2.34.1



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

* [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (7 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 08/13] xen/page_alloc: introduce preserved page flags macro Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-09 10:28   ` Jan Beulich
  2024-01-02  9:51 ` [PATCH v5 10/13] xen/arm: use domain memory to allocate p2m page tables Carlo Nonato
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Andrew Cooper, George Dunlap,
	Jan Beulich, Wei Liu, Marco Solieri

This commit adds a new memory page allocator that implements the cache
coloring mechanism. The allocation algorithm enforces equal frequency
distribution of cache partitions, following the coloring configuration of a
domain. This allows an even utilization of cache sets for every domain.

Pages are stored in a color-indexed array of lists. Those lists are filled
by a simple init function which computes the color of each page.
When a domain requests a page, the allocator extract the page from the list
with the maximum number of free pages between those that the domain can
access, given its coloring configuration.

The allocator can only handle requests of order-0 pages. This allows for
easier implementation and since cache coloring targets only embedded systems,
it's assumed not to be a major problem.

The buddy allocator must coexist with the colored one because the Xen heap
isn't colored. For this reason a new Kconfig option and a command line
parameter are added to let the user set the amount of memory reserved for
the buddy allocator. Even when cache coloring is enabled, this memory
isn't managed by the colored allocator.

Colored heap information is dumped in the dump_heap() debug-key function.

Based on original work from: Luca Miccio <lucmiccio@gmail.com>

Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
---
v5:
- Carlo Nonato as the new author
- the colored allocator balances color usage for each domain and it searches
  linearly only in the number of colors (FIXME removed)
- addedd scrub functionality
- removed stub functions (still requires some macro definition)
- addr_to_color turned to mfn_to_color for easier operations
- removed BUG_ON in init_color_heap_pages() in favor of panic()
- only non empty page lists are logged in dump_color_heap()
v4:
- moved colored allocator code after buddy allocator because it now has
  some dependencies on buddy functions
- buddy_alloc_size is now used only by the colored allocator
- fixed a bug that allowed the buddy to merge pages when they were colored
- free_color_heap_page() now calls mark_page_free()
- free_color_heap_page() uses of the frametable array for faster searches
- added FIXME comment for the linear search in free_color_heap_page()
- removed alloc_color_domheap_page() to let the colored allocator exploit
  some more buddy allocator code
- alloc_color_heap_page() now allocs min address pages first
- reduced the mess in end_boot_allocator(): use the first loop for
  init_color_heap_pages()
- fixed page_list_add_prev() (list.h) since it was doing the opposite of
  what it was supposed to do
- fixed page_list_add_prev() (non list.h) to check also for next existence
- removed unused page_list_add_next()
- moved p2m code in another patch
---
 docs/misc/arm/cache-coloring.rst  |  37 ++++++
 docs/misc/xen-command-line.pandoc |  14 +++
 xen/arch/Kconfig                  |  12 ++
 xen/arch/arm/include/asm/mm.h     |   5 +
 xen/arch/arm/llc-coloring.c       |  13 ++
 xen/common/page_alloc.c           | 193 +++++++++++++++++++++++++++++-
 xen/include/xen/llc-coloring.h    |   4 +
 7 files changed, 273 insertions(+), 5 deletions(-)

diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
index ae1dd8f4af..c5582340da 100644
--- a/docs/misc/arm/cache-coloring.rst
+++ b/docs/misc/arm/cache-coloring.rst
@@ -9,6 +9,9 @@ To compile LLC coloring support set ``CONFIG_LLC_COLORING=y``.
 If needed, change the maximum number of colors with
 ``CONFIG_NR_LLC_COLORS=<n>``.
 
+If needed, change the buddy allocator reserved size with
+``CONFIG_BUDDY_ALLOCATOR_SIZE=<n>``.
+
 Compile Xen and the toolstack and then configure it via
 `Command line parameters`_. For DomUs follow `DomUs configuration`_.
 
@@ -86,6 +89,8 @@ More specific documentation is available at `docs/misc/xen-command-line.pandoc`.
 +----------------------+-------------------------------+
 | ``dom0-llc-colors``  | Dom0 color configuration      |
 +----------------------+-------------------------------+
+| ``buddy-alloc-size`` | Buddy allocator reserved size |
++----------------------+-------------------------------+
 
 Colors selection format
 ***********************
@@ -160,6 +165,17 @@ DomUs colors can be set via Device Tree, also for Dom0less configurations
 **Note:** If no color configuration is provided for a domain, the default one,
 which corresponds to all available colors, is used instead.
 
+Colored allocator and buddy allocator
+*************************************
+
+The colored allocator distributes pages based on color configurations of
+domains so that each domains only gets pages of its own colors.
+The colored allocator is meant as an alternative to the buddy allocator because
+its allocation policy is by definition incompatible with the generic one. Since
+the Xen heap is not colored yet, we need to support the coexistence of the two
+allocators and some memory must be left for the buddy one. Buddy memory
+reservation is configured via Kconfig or via command-line.
+
 Known issues and limitations
 ****************************
 
@@ -170,3 +186,24 @@ In the domain configuration, "xen,static-mem" allows memory to be statically
 allocated to the domain. This isn't possibile when LLC coloring is enabled,
 because that memory can't be guaranteed to use only colors assigned to the
 domain.
+
+Cache coloring is intended only for embedded systems
+####################################################
+
+The current implementation aims to satisfy the need of predictability in
+embedded systems with small amount of memory to be managed in a colored way.
+Given that, some shortcuts are taken in the development. Expect worse
+performances on larger systems.
+
+Colored allocator can only make use of order-0 pages
+####################################################
+
+The cache coloring technique relies on memory mappings and on the smallest
+amount of memory that can be mapped to achieve the maximum number of colors
+(cache partitions) possible. This amount is what is normally called a page and,
+in Xen terminology, the order-0 page is the smallest one. The fairly simple
+colored allocator currently implemented, makes use only of such pages.
+It must be said that a more complex one could, in theory, adopt higher order
+pages if the colors selection contained adjacent colors. Two subsequent colors,
+for example, can be represented by an order-1 page, four colors correspond to
+an order-2 page, etc.
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 51f6adf035..163fe7bcb1 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -270,6 +270,20 @@ and not running softirqs. Reduce this if softirqs are not being run frequently
 enough. Setting this to a high value may cause boot failure, particularly if
 the NMI watchdog is also enabled.
 
+### buddy-alloc-size (arm64)
+> `= <size>`
+
+> Default: `64M`
+
+Amount of memory reserved for the buddy allocator when colored allocator is
+active. This options is parsed only when LLC coloring support is enabled.
+The colored allocator is meant as an alternative to the buddy allocator,
+because its allocation policy is by definition incompatible with the generic
+one. Since the Xen heap systems is not colored yet, we need to support the
+coexistence of the two allocators for now. This parameter, which is optional
+and for expert only, it's used to set the amount of memory reserved to the
+buddy allocator.
+
 ### cet
     = List of [ shstk=<bool>, ibt=<bool> ]
 
diff --git a/xen/arch/Kconfig b/xen/arch/Kconfig
index aad7e9da38..f4c1406c02 100644
--- a/xen/arch/Kconfig
+++ b/xen/arch/Kconfig
@@ -47,3 +47,15 @@ config NR_LLC_COLORS
 	  bound. The runtime value is autocomputed or manually set via cmdline.
 	  The default value corresponds to an 8 MiB 16-ways LLC, which should be
 	  more than what needed in the general case.
+
+config BUDDY_ALLOCATOR_SIZE
+	int "Buddy allocator reserved memory size (MiB)"
+	default "64"
+	depends on LLC_COLORING
+	help
+	  Amount of memory reserved for the buddy allocator to work alongside
+	  the colored one. The colored allocator is meant as an alternative to
+	  the buddy allocator because its allocation policy is by definition
+	  incompatible with the generic one. Since the Xen heap is not colored
+	  yet, we need to support the coexistence of the two allocators and some
+	  memory must be left for the buddy one.
diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
index cbcf3bf147..1829c559d6 100644
--- a/xen/arch/arm/include/asm/mm.h
+++ b/xen/arch/arm/include/asm/mm.h
@@ -145,6 +145,11 @@ struct page_info
 #else
 #define PGC_static     0
 #endif
+#ifdef CONFIG_LLC_COLORING
+/* Page is cache colored */
+#define _PGC_colored      PG_shift(4)
+#define PGC_colored       PG_mask(1, 4)
+#endif
 /* ... */
 /* Page is broken? */
 #define _PGC_broken       PG_shift(7)
diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
index d3de5f14cb..526129cc43 100644
--- a/xen/arch/arm/llc-coloring.c
+++ b/xen/arch/arm/llc-coloring.c
@@ -30,6 +30,9 @@ static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
 static unsigned int __ro_after_init dom0_colors[CONFIG_NR_LLC_COLORS];
 static unsigned int __ro_after_init dom0_num_colors;
 
+#define mfn_color_mask              (nr_colors - 1)
+#define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
+
 /*
  * Parse the coloring configuration given in the buf string, following the
  * syntax below.
@@ -312,6 +315,16 @@ int domain_set_llc_colors_from_str(struct domain *d, const char *str)
     return domain_check_colors(d);
 }
 
+unsigned int page_to_llc_color(const struct page_info *pg)
+{
+    return mfn_to_color(page_to_mfn(pg));
+}
+
+unsigned int get_nr_llc_colors(void)
+{
+    return nr_colors;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 3bf3120287..54f52e8677 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -126,6 +126,7 @@
 #include <xen/irq.h>
 #include <xen/keyhandler.h>
 #include <xen/lib.h>
+#include <xen/llc-coloring.h>
 #include <xen/mm.h>
 #include <xen/nodemask.h>
 #include <xen/numa.h>
@@ -158,7 +159,11 @@
 #define PGC_static 0
 #endif
 
-#define preserved_flags (PGC_extra | PGC_static)
+#ifndef PGC_colored
+#define PGC_colored 0
+#endif
+
+#define preserved_flags (PGC_extra | PGC_static | PGC_colored)
 
 #ifndef PGT_TYPE_INFO_INITIALIZER
 #define PGT_TYPE_INFO_INITIALIZER 0
@@ -1946,6 +1951,162 @@ static unsigned long avail_heap_pages(
     return free_pages;
 }
 
+/*************************
+ * COLORED SIDE-ALLOCATOR
+ *
+ * Pages are grouped by LLC color in lists which are globally referred to as the
+ * color heap. Lists are populated in end_boot_allocator().
+ * After initialization there will be N lists where N is the number of
+ * available colors on the platform.
+ */
+static struct page_list_head *__ro_after_init _color_heap;
+static unsigned long *__ro_after_init free_colored_pages;
+
+/* Memory required for buddy allocator to work with colored one */
+#ifdef CONFIG_LLC_COLORING
+static unsigned long __initdata buddy_alloc_size =
+    MB(CONFIG_BUDDY_ALLOCATOR_SIZE);
+size_param("buddy-alloc-size", buddy_alloc_size);
+
+#define domain_num_llc_colors(d) ((d)->num_llc_colors)
+#define domain_llc_color(d, i)   ((d)->llc_colors[(i)])
+#else
+static unsigned long __initdata buddy_alloc_size;
+
+#define domain_num_llc_colors(d) 0
+#define domain_llc_color(d, i)   0
+#define page_to_llc_color(p)     0
+#define get_nr_llc_colors()      0
+#endif
+
+#define color_heap(color) (&_color_heap[color])
+
+void free_color_heap_page(struct page_info *pg, bool need_scrub)
+{
+    unsigned int color = page_to_llc_color(pg);
+    struct page_list_head *head = color_heap(color);
+
+    spin_lock(&heap_lock);
+
+    mark_page_free(pg, page_to_mfn(pg));
+
+    if ( need_scrub )
+    {
+        pg->count_info |= PGC_need_scrub;
+        poison_one_page(pg);
+    }
+
+    pg->count_info |= PGC_colored;
+    free_colored_pages[color]++;
+    page_list_add(pg, head);
+
+    spin_unlock(&heap_lock);
+}
+
+struct page_info *alloc_color_heap_page(unsigned int memflags, struct domain *d)
+{
+    struct page_info *pg = NULL;
+    unsigned int i, color;
+    unsigned long max = 0;
+    bool need_tlbflush = false;
+    uint32_t tlbflush_timestamp = 0;
+    bool scrub = !(memflags & MEMF_no_scrub);
+
+    spin_lock(&heap_lock);
+
+    for ( i = 0; i < domain_num_llc_colors(d); i++ )
+    {
+        unsigned long free = free_colored_pages[domain_llc_color(d, i)];
+
+        if ( free > max )
+        {
+            color = domain_llc_color(d, i);
+            pg = page_list_first(color_heap(color));
+            max = free;
+        }
+    }
+
+    if ( !pg )
+    {
+        spin_unlock(&heap_lock);
+        return NULL;
+    }
+
+    pg->count_info = PGC_state_inuse | PGC_colored |
+                     (pg->count_info & PGC_need_scrub);
+    free_colored_pages[color]--;
+    page_list_del(pg, color_heap(color));
+
+    if ( !(memflags & MEMF_no_tlbflush) )
+        accumulate_tlbflush(&need_tlbflush, pg, &tlbflush_timestamp);
+
+    init_free_page_fields(pg);
+
+    spin_unlock(&heap_lock);
+
+    if ( test_and_clear_bit(_PGC_need_scrub, &pg->count_info) && scrub )
+        scrub_one_page(pg);
+    else if ( scrub )
+        check_one_page(pg);
+
+    if ( need_tlbflush )
+        filtered_flush_tlb_mask(tlbflush_timestamp);
+
+    flush_page_to_ram(mfn_x(page_to_mfn(pg)),
+                      !(memflags & MEMF_no_icache_flush));
+
+    return pg;
+}
+
+void __init init_color_heap_pages(struct page_info *pg, unsigned long nr_pages)
+{
+    unsigned int i;
+    bool need_scrub = (system_state < SYS_STATE_active &&
+                       opt_bootscrub == BOOTSCRUB_IDLE);
+
+    if ( buddy_alloc_size )
+    {
+        unsigned long buddy_pages = min(PFN_DOWN(buddy_alloc_size), nr_pages);
+
+        init_heap_pages(pg, buddy_pages);
+        nr_pages -= buddy_pages;
+        buddy_alloc_size -= buddy_pages << PAGE_SHIFT;
+        pg += buddy_pages;
+    }
+
+    if ( !_color_heap )
+    {
+        unsigned int nr_colors = get_nr_llc_colors();
+
+        _color_heap = xmalloc_array(struct page_list_head, nr_colors);
+        free_colored_pages = xzalloc_array(unsigned long, nr_colors);
+        if ( !_color_heap || !free_colored_pages )
+            panic("Can't allocate colored heap. Buddy reserved size is too low");
+
+        for ( i = 0; i < nr_colors; i++ )
+            INIT_PAGE_LIST_HEAD(color_heap(i));
+    }
+
+    if ( nr_pages )
+        printk(XENLOG_DEBUG
+               "Init color heap with %lu pages starting from: %#"PRIx64"\n",
+               nr_pages, page_to_maddr(pg));
+
+    for ( i = 0; i < nr_pages; i++ )
+        free_color_heap_page(&pg[i], need_scrub);
+}
+
+void dump_color_heap(void)
+{
+    unsigned int color;
+
+    printk("Dumping color heap info\n");
+    for ( color = 0; color < get_nr_llc_colors(); color++ )
+        if ( free_colored_pages[color] > 0 )
+            printk("Color heap[%u]: %lu pages\n",
+                   color, free_colored_pages[color]);
+}
+
 void __init end_boot_allocator(void)
 {
     unsigned int i;
@@ -1965,7 +2126,13 @@ void __init end_boot_allocator(void)
     for ( i = nr_bootmem_regions; i-- > 0; )
     {
         struct bootmem_region *r = &bootmem_region_list[i];
-        if ( r->s < r->e )
+
+        if ( r->s >= r->e )
+            continue;
+
+        if ( llc_coloring_enabled )
+            init_color_heap_pages(mfn_to_page(_mfn(r->s)), r->e - r->s);
+        else
             init_heap_pages(mfn_to_page(_mfn(r->s)), r->e - r->s);
     }
     nr_bootmem_regions = 0;
@@ -2461,7 +2628,14 @@ struct page_info *alloc_domheap_pages(
     if ( memflags & MEMF_no_owner )
         memflags |= MEMF_no_refcount;
 
-    if ( !dma_bitsize )
+    /* Only domains are supported for coloring */
+    if ( d && is_domain_llc_colored(d) )
+    {
+        /* Colored allocation must be done on 0 order */
+        if ( order || (pg = alloc_color_heap_page(memflags, d)) == NULL )
+            return NULL;
+    }
+    else if ( !dma_bitsize )
         memflags &= ~MEMF_no_dma;
     else if ( (dma_zone = bits_to_zone(dma_bitsize)) < zone_hi )
         pg = alloc_heap_pages(dma_zone + 1, zone_hi, order, memflags, d);
@@ -2486,7 +2660,10 @@ struct page_info *alloc_domheap_pages(
         }
         if ( assign_page(pg, order, d, memflags) )
         {
-            free_heap_pages(pg, order, memflags & MEMF_no_scrub);
+            if ( pg->count_info & PGC_colored )
+                free_color_heap_page(pg, memflags & MEMF_no_scrub);
+            else
+                free_heap_pages(pg, order, memflags & MEMF_no_scrub);
             return NULL;
         }
     }
@@ -2569,7 +2746,10 @@ void free_domheap_pages(struct page_info *pg, unsigned int order)
             scrub = 1;
         }
 
-        free_heap_pages(pg, order, scrub);
+        if ( pg->count_info & PGC_colored )
+            free_color_heap_page(pg, scrub);
+        else
+            free_heap_pages(pg, order, scrub);
     }
 
     if ( drop_dom_ref )
@@ -2676,6 +2856,9 @@ static void cf_check dump_heap(unsigned char key)
             continue;
         printk("Node %d has %lu unscrubbed pages\n", i, node_need_scrub[i]);
     }
+
+    if ( llc_coloring_enabled )
+        dump_color_heap();
 }
 
 static __init int cf_check register_heap_trigger(void)
diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
index fa2edc8ad8..7cd481e955 100644
--- a/xen/include/xen/llc-coloring.h
+++ b/xen/include/xen/llc-coloring.h
@@ -36,6 +36,10 @@ void domain_dump_llc_colors(struct domain *d);
 int domain_set_llc_colors_domctl(struct domain *d,
                                  const struct xen_domctl_set_llc_colors *config);
 
+struct page_info;
+unsigned int page_to_llc_color(const struct page_info *pg);
+unsigned int get_nr_llc_colors(void);
+
 #endif /* __COLORING_H__ */
 
 /*
-- 
2.34.1



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

* [PATCH v5 10/13] xen/arm: use domain memory to allocate p2m page tables
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (8 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 09/13] xen: add cache coloring allocator for domains Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-05 17:54   ` Julien Grall
  2024-01-02  9:51 ` [PATCH v5 11/13] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START" Carlo Nonato
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Marco Solieri

Cache colored domains can benefit from having p2m page tables allocated
with the same coloring schema so that isolation can be achieved also for
those kind of memory accesses.
In order to do that, the domain struct is passed to the allocator and the
MEMF_no_owner flag is used.

This will be useful also when NUMA will be supported on Arm.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- new patch
---
 xen/arch/arm/mmu/p2m.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/mmu/p2m.c b/xen/arch/arm/mmu/p2m.c
index 41fcca011c..d02a478cb8 100644
--- a/xen/arch/arm/mmu/p2m.c
+++ b/xen/arch/arm/mmu/p2m.c
@@ -32,7 +32,7 @@ static struct page_info *p2m_alloc_page(struct domain *d)
      */
     if ( is_hardware_domain(d) )
     {
-        pg = alloc_domheap_page(NULL, 0);
+        pg = alloc_domheap_page(d, MEMF_no_owner);
         if ( pg == NULL )
             printk(XENLOG_G_ERR "Failed to allocate P2M pages for hwdom.\n");
     }
@@ -81,7 +81,7 @@ int p2m_set_allocation(struct domain *d, unsigned long pages, bool *preempted)
         if ( d->arch.paging.p2m_total_pages < pages )
         {
             /* Need to allocate more memory from domheap */
-            pg = alloc_domheap_page(NULL, 0);
+            pg = alloc_domheap_page(d, MEMF_no_owner);
             if ( pg == NULL )
             {
                 printk(XENLOG_ERR "Failed to allocate P2M pages.\n");
-- 
2.34.1



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

* [PATCH v5 11/13] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START"
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (9 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 10/13] xen/arm: use domain memory to allocate p2m page tables Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-05 18:20   ` Julien Grall
  2024-01-02  9:51 ` [PATCH v5 12/13] xen/arm: add Xen cache colors command line parameter Carlo Nonato
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Marco Solieri

This reverts commit 0c18fb76323bfb13615b6f13c98767face2d8097 (not clean).

This is not a clean revert since the rework of the memory layout, but it is
sufficiently similar to a clean one.
The only difference is that the BOOT_RELOC_VIRT_START must match the new
layout.

Cache coloring support for Xen needs to relocate Xen code and data in a new
colored physical space. The BOOT_RELOC_VIRT_START will be used as the virtual
base address for a temporary mapping to this new space.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 xen/arch/arm/include/asm/mmu/layout.h | 2 ++
 xen/arch/arm/mmu/setup.c              | 1 +
 2 files changed, 3 insertions(+)

diff --git a/xen/arch/arm/include/asm/mmu/layout.h b/xen/arch/arm/include/asm/mmu/layout.h
index eac7eef885..30031f74d9 100644
--- a/xen/arch/arm/include/asm/mmu/layout.h
+++ b/xen/arch/arm/include/asm/mmu/layout.h
@@ -74,6 +74,8 @@
 #define BOOT_FDT_VIRT_START     (FIXMAP_VIRT_START + FIXMAP_VIRT_SIZE)
 #define BOOT_FDT_VIRT_SIZE      _AT(vaddr_t, MB(4))
 
+#define BOOT_RELOC_VIRT_START   (BOOT_FDT_VIRT_START + BOOT_FDT_VIRT_SIZE)
+
 #ifdef CONFIG_LIVEPATCH
 #define LIVEPATCH_VMAP_START    (BOOT_FDT_VIRT_START + BOOT_FDT_VIRT_SIZE)
 #define LIVEPATCH_VMAP_SIZE    _AT(vaddr_t, MB(2))
diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
index d5264e51bc..37b6d230ad 100644
--- a/xen/arch/arm/mmu/setup.c
+++ b/xen/arch/arm/mmu/setup.c
@@ -69,6 +69,7 @@ static void __init __maybe_unused build_assertions(void)
     /* 2MB aligned regions */
     BUILD_BUG_ON(XEN_VIRT_START & ~SECOND_MASK);
     BUILD_BUG_ON(FIXMAP_ADDR(0) & ~SECOND_MASK);
+    BUILD_BUG_ON(BOOT_RELOC_VIRT_START & ~SECOND_MASK);
     /* 1GB aligned regions */
 #ifdef CONFIG_ARM_32
     BUILD_BUG_ON(XENHEAP_VIRT_START & ~FIRST_MASK);
-- 
2.34.1



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

* [PATCH v5 12/13] xen/arm: add Xen cache colors command line parameter
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (10 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 11/13] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START" Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-05 18:00   ` Julien Grall
  2024-01-02  9:51 ` [PATCH v5 13/13] xen/arm: add cache coloring support for Xen Carlo Nonato
  2024-01-03 13:34 ` [PATCH v5 00/13] Arm cache coloring Michal Orzel
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Luca Miccio, Andrew Cooper, George Dunlap, Jan Beulich,
	Julien Grall, Stefano Stabellini, Wei Liu, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Marco Solieri, Carlo Nonato

From: Luca Miccio <lucmiccio@gmail.com>

This commit adds a new command line parameter to configure Xen cache colors.
These colors can be dumped with the cache coloring info debug-key.

By default, Xen uses the first color.
Benchmarking the VM interrupt response time provides an estimation of
LLC usage by Xen's most latency-critical runtime task. Results on Arm
Cortex-A53 on Xilinx Zynq UltraScale+ XCZU9EG show that one color, which
reserves 64 KiB of L2, is enough to attain best responsiveness.

More colors are instead very likely to be needed on processors whose L1
cache is physically-indexed and physically-tagged, such as Cortex-A57.
In such cases, coloring applies to L1 also, and there typically are two
distinct L1-colors. Therefore, reserving only one color for Xen would
senselessly partitions a cache memory that is already private, i.e.
underutilize it. The default amount of Xen colors is thus set to one.

Signed-off-by: Luca Miccio <lucmiccio@gmail.com>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
---
 docs/misc/xen-command-line.pandoc | 10 ++++++++++
 xen/arch/arm/llc-coloring.c       | 29 +++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 163fe7bcb1..f983f22796 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -2877,6 +2877,16 @@ mode.
 **WARNING: `x2apic_phys` is deprecated and superseded by `x2apic-mode`.
 The latter takes precedence if both are set.**
 
+### xen-llc-colors (arm64)
+> `= List of [ <integer> | <integer>-<integer> ]`
+
+> Default: `0: the lowermost color`
+
+Specify Xen LLC color configuration. This options is available only when
+`CONFIG_LLC_COLORING` is enabled.
+Two colors are most likely needed on platforms where private caches are
+physically indexed, e.g. the L1 instruction cache of the Arm Cortex-A57.
+
 ### xenheap_megabytes (arm32)
 > `= <size>`
 
diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
index 526129cc43..99ea69ad39 100644
--- a/xen/arch/arm/llc-coloring.c
+++ b/xen/arch/arm/llc-coloring.c
@@ -18,6 +18,9 @@
 #include <asm/processor.h>
 #include <asm/sysregs.h>
 
+#define XEN_DEFAULT_COLOR       0
+#define XEN_DEFAULT_NUM_COLORS  1
+
 bool __ro_after_init llc_coloring_enabled;
 boolean_param("llc-coloring", llc_coloring_enabled);
 
@@ -30,6 +33,9 @@ static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
 static unsigned int __ro_after_init dom0_colors[CONFIG_NR_LLC_COLORS];
 static unsigned int __ro_after_init dom0_num_colors;
 
+static unsigned int __ro_after_init xen_colors[CONFIG_NR_LLC_COLORS];
+static unsigned int __ro_after_init xen_num_colors;
+
 #define mfn_color_mask              (nr_colors - 1)
 #define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
 
@@ -87,6 +93,12 @@ static int __init parse_dom0_colors(const char *s)
 }
 custom_param("dom0-llc-colors", parse_dom0_colors);
 
+static int __init parse_xen_colors(const char *s)
+{
+    return parse_color_config(s, xen_colors, &xen_num_colors);
+}
+custom_param("xen-llc-colors", parse_xen_colors);
+
 /* Return the LLC way size by probing the hardware */
 static unsigned int __init get_llc_way_size(void)
 {
@@ -161,6 +173,8 @@ static void dump_coloring_info(unsigned char key)
     printk("'%c' pressed -> dumping LLC coloring general info\n", key);
     printk("LLC way size: %u KiB\n", llc_way_size >> 10);
     printk("Number of LLC colors supported: %u\n", nr_colors);
+    printk("Xen has %u LLC colors: ", xen_num_colors);
+    print_colors(xen_colors, xen_num_colors);
 }
 
 static bool check_colors(unsigned int *colors, unsigned int num_colors)
@@ -217,6 +231,21 @@ bool __init llc_coloring_init(void)
         return false;
     }
 
+    if ( !xen_num_colors )
+    {
+        printk(XENLOG_WARNING
+               "Xen LLC color config not found. Using default color: %u\n",
+               XEN_DEFAULT_COLOR);
+        xen_colors[0] = XEN_DEFAULT_COLOR;
+        xen_num_colors = XEN_DEFAULT_NUM_COLORS;
+    }
+
+    if ( !check_colors(xen_colors, xen_num_colors) )
+    {
+        printk(XENLOG_ERR "Bad LLC color config for Xen\n");
+        return false;
+    }
+
     register_keyhandler('K', dump_coloring_info, "dump LLC coloring info", 1);
 
     return true;
-- 
2.34.1



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

* [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (11 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 12/13] xen/arm: add Xen cache colors command line parameter Carlo Nonato
@ 2024-01-02  9:51 ` Carlo Nonato
  2024-01-05 19:12   ` Julien Grall
  2024-01-03 13:34 ` [PATCH v5 00/13] Arm cache coloring Michal Orzel
  13 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-02  9:51 UTC (permalink / raw)
  To: xen-devel
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Marco Solieri

This commit adds the cache coloring support for Xen own physical space.

It extends the implementation of setup_pagetables() to make use of Xen
cache coloring configuration. Page tables construction is essentially the
same except for the fact that PTEs point to a new temporary mapped,
physically colored space.

The temporary mapping is also used to relocate Xen to the new physical
space starting at the address taken from the old get_xen_paddr() function
which is brought back for the occasion.
The temporary mapping is finally converted to a mapping of the "old"
(meaning the original physical space) Xen code, so that the boot CPU can
actually address the variables and functions used by secondary CPUs until
they enable the MMU. This happens when the boot CPU needs to bring up other
CPUs (psci.c and smpboot.c) and when the TTBR value is passed to them
(prepare_secondary_mm()).

Finally, since the alternative framework needs to remap the Xen text and
inittext sections, this operation must be done in a coloring-aware way.
The function xen_remap_colored() is introduced for that.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
v5:
- FIXME: consider_modules copy pasted since it got moved
v4:
- removed set_value_for_secondary() because it was wrongly cleaning cache
- relocate_xen() now calls switch_ttbr_id()
---
 xen/arch/arm/alternative.c              |   9 +-
 xen/arch/arm/arm64/mmu/head.S           |  48 +++++++
 xen/arch/arm/arm64/mmu/mm.c             |  26 +++-
 xen/arch/arm/include/asm/llc-coloring.h |  16 +++
 xen/arch/arm/include/asm/mm.h           |   7 +-
 xen/arch/arm/llc-coloring.c             |  44 +++++++
 xen/arch/arm/mmu/setup.c                |  82 +++++++++++-
 xen/arch/arm/mmu/smpboot.c              |  11 +-
 xen/arch/arm/psci.c                     |   9 +-
 xen/arch/arm/setup.c                    | 165 +++++++++++++++++++++++-
 xen/arch/arm/smpboot.c                  |   9 +-
 11 files changed, 406 insertions(+), 20 deletions(-)

diff --git a/xen/arch/arm/alternative.c b/xen/arch/arm/alternative.c
index 016e66978b..54cbc2afad 100644
--- a/xen/arch/arm/alternative.c
+++ b/xen/arch/arm/alternative.c
@@ -9,6 +9,7 @@
 #include <xen/init.h>
 #include <xen/types.h>
 #include <xen/kernel.h>
+#include <xen/llc-coloring.h>
 #include <xen/mm.h>
 #include <xen/vmap.h>
 #include <xen/smp.h>
@@ -209,8 +210,12 @@ void __init apply_alternatives_all(void)
      * The text and inittext section are read-only. So re-map Xen to
      * be able to patch the code.
      */
-    xenmap = __vmap(&xen_mfn, 1U << xen_order, 1, 1, PAGE_HYPERVISOR,
-                    VMAP_DEFAULT);
+    if ( llc_coloring_enabled )
+        xenmap = xen_remap_colored(xen_mfn, xen_size);
+    else
+        xenmap = __vmap(&xen_mfn, 1U << xen_order, 1, 1, PAGE_HYPERVISOR,
+                        VMAP_DEFAULT);
+
     /* Re-mapping Xen is not expected to fail during boot. */
     BUG_ON(!xenmap);
 
diff --git a/xen/arch/arm/arm64/mmu/head.S b/xen/arch/arm/arm64/mmu/head.S
index 10774f30e4..6f0cc72897 100644
--- a/xen/arch/arm/arm64/mmu/head.S
+++ b/xen/arch/arm/arm64/mmu/head.S
@@ -419,6 +419,54 @@ fail:   PRINT("- Boot failed -\r\n")
         b     1b
 ENDPROC(fail)
 
+/* Copy Xen to new location and switch TTBR
+ * x0    ttbr
+ * x1    source address
+ * x2    destination address
+ * x3    length
+ *
+ * Source and destination must be word aligned, length is rounded up
+ * to a 16 byte boundary.
+ *
+ * MUST BE VERY CAREFUL when saving things to RAM over the copy */
+ENTRY(relocate_xen)
+        /* Copy 16 bytes at a time using:
+         *   x9: counter
+         *   x10: data
+         *   x11: data
+         *   x12: source
+         *   x13: destination
+         */
+        mov     x9, x3
+        mov     x12, x1
+        mov     x13, x2
+
+1:      ldp     x10, x11, [x12], #16
+        stp     x10, x11, [x13], #16
+
+        subs    x9, x9, #16
+        bgt     1b
+
+        /* Flush destination from dcache using:
+         * x9: counter
+         * x10: step
+         * x11: vaddr
+         */
+        dsb   sy        /* So the CPU issues all writes to the range */
+
+        mov   x9, x3
+        ldr   x10, =dcache_line_bytes /* x10 := step */
+        ldr   x10, [x10]
+        mov   x11, x2
+
+1:      dc    cvac, x11
+
+        add   x11, x11, x10
+        subs  x9, x9, x10
+        bgt   1b
+
+        b switch_ttbr_id
+
 /*
  * Switch TTBR
  *
diff --git a/xen/arch/arm/arm64/mmu/mm.c b/xen/arch/arm/arm64/mmu/mm.c
index d2651c9486..5a26d64ab7 100644
--- a/xen/arch/arm/arm64/mmu/mm.c
+++ b/xen/arch/arm/arm64/mmu/mm.c
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 
 #include <xen/init.h>
+#include <xen/llc-coloring.h>
 #include <xen/mm.h>
 #include <xen/pfn.h>
 
@@ -125,27 +126,44 @@ void update_identity_mapping(bool enable)
 }
 
 extern void switch_ttbr_id(uint64_t ttbr);
+extern void relocate_xen(uint64_t ttbr, void *src, void *dst, size_t len);
 
 typedef void (switch_ttbr_fn)(uint64_t ttbr);
+typedef void (relocate_xen_fn)(uint64_t ttbr, void *src, void *dst, size_t len);
 
 void __init switch_ttbr(uint64_t ttbr)
 {
-    vaddr_t id_addr = virt_to_maddr(switch_ttbr_id);
-    switch_ttbr_fn *fn = (switch_ttbr_fn *)id_addr;
+    vaddr_t vaddr, id_addr;
     lpae_t pte;
 
+    if ( llc_coloring_enabled )
+        vaddr = (vaddr_t)relocate_xen;
+    else
+        vaddr = (vaddr_t)switch_ttbr_id;
+
+    id_addr = virt_to_maddr(vaddr);
+
     /* Enable the identity mapping in the boot page tables */
     update_identity_mapping(true);
 
     /* Enable the identity mapping in the runtime page tables */
-    pte = pte_of_xenaddr((vaddr_t)switch_ttbr_id);
+    pte = pte_of_xenaddr(vaddr);
     pte.pt.table = 1;
     pte.pt.xn = 0;
     pte.pt.ro = 1;
     write_pte(&xen_third_id[third_table_offset(id_addr)], pte);
 
     /* Switch TTBR */
-    fn(ttbr);
+    if ( llc_coloring_enabled )
+    {
+        relocate_xen_fn *fn = (relocate_xen_fn *)id_addr;
+        fn(ttbr, _start, (void *)BOOT_RELOC_VIRT_START, _end - _start);
+    }
+    else
+    {
+        switch_ttbr_fn *fn = (switch_ttbr_fn *)id_addr;
+        fn(ttbr);
+    }
 
     /*
      * Disable the identity mapping in the runtime page tables.
diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
index 5f9b0a8121..4d6071e50b 100644
--- a/xen/arch/arm/include/asm/llc-coloring.h
+++ b/xen/arch/arm/include/asm/llc-coloring.h
@@ -12,11 +12,27 @@
 #define __ASM_ARM_COLORING_H__
 
 #include <xen/init.h>
+#include <xen/mm-frame.h>
+
+/**
+ * Iterate over each Xen mfn in the colored space.
+ * @mfn:    the current mfn. The first non colored mfn must be provided as the
+ *          starting point.
+ * @i:      loop index.
+ */
+#define for_each_xen_colored_mfn(mfn, i)        \
+    for ( i = 0, mfn = xen_colored_mfn(mfn);    \
+          i < (_end - _start) >> PAGE_SHIFT;    \
+          i++, mfn = xen_colored_mfn(mfn_add(mfn, 1)) )
 
 bool __init llc_coloring_init(void);
 int dom0_set_llc_colors(struct domain *d);
 int domain_set_llc_colors_from_str(struct domain *d, const char *str);
 
+paddr_t xen_colored_map_size(paddr_t size);
+mfn_t xen_colored_mfn(mfn_t mfn);
+void *xen_remap_colored(mfn_t xen_fn, paddr_t xen_size);
+
 #endif /* __ASM_ARM_COLORING_H__ */
 
 /*
diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
index 1829c559d6..311f092cf2 100644
--- a/xen/arch/arm/include/asm/mm.h
+++ b/xen/arch/arm/include/asm/mm.h
@@ -203,12 +203,17 @@ extern unsigned long frametable_base_pdx;
 
 #define PDX_GROUP_SHIFT SECOND_SHIFT
 
+#define virt_to_reloc_virt(virt) \
+    (((vaddr_t)virt) - XEN_VIRT_START + BOOT_RELOC_VIRT_START)
+
 /* Boot-time pagetable setup */
-extern void setup_pagetables(unsigned long boot_phys_offset);
+extern void setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr);
 /* Map FDT in boot pagetable */
 extern void *early_fdt_map(paddr_t fdt_paddr);
 /* Remove early mappings */
 extern void remove_early_mappings(void);
+/* Remove early LLC coloring mappings */
+extern void remove_llc_coloring_mappings(void);
 /* Prepare the memory subystem to bring-up the given secondary CPU */
 extern int prepare_secondary_mm(int cpu);
 /* Map a frame table to cover physical addresses ps through pe */
diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
index 99ea69ad39..f434efc45b 100644
--- a/xen/arch/arm/llc-coloring.c
+++ b/xen/arch/arm/llc-coloring.c
@@ -14,6 +14,7 @@
 #include <xen/llc-coloring.h>
 #include <xen/param.h>
 #include <xen/types.h>
+#include <xen/vmap.h>
 
 #include <asm/processor.h>
 #include <asm/sysregs.h>
@@ -38,6 +39,7 @@ static unsigned int __ro_after_init xen_num_colors;
 
 #define mfn_color_mask              (nr_colors - 1)
 #define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
+#define mfn_set_color(mfn, color)   ((mfn_x(mfn) & ~mfn_color_mask) | (color))
 
 /*
  * Parse the coloring configuration given in the buf string, following the
@@ -354,6 +356,48 @@ unsigned int get_nr_llc_colors(void)
     return nr_colors;
 }
 
+paddr_t xen_colored_map_size(paddr_t size)
+{
+    return ROUNDUP(size * nr_colors, XEN_PADDR_ALIGN);
+}
+
+mfn_t xen_colored_mfn(mfn_t mfn)
+{
+    unsigned int i, color = mfn_to_color(mfn);
+
+    for( i = 0; i < xen_num_colors; i++ )
+    {
+        if ( color == xen_colors[i] )
+            return mfn;
+        else if ( color < xen_colors[i] )
+            return mfn_set_color(mfn, xen_colors[i]);
+    }
+
+    /* Jump to next color space (nr_colors mfns) and use the first color */
+    return mfn_set_color(mfn_add(mfn, nr_colors), xen_colors[0]);
+}
+
+void *xen_remap_colored(mfn_t xen_mfn, paddr_t xen_size)
+{
+    unsigned int i;
+    void *xenmap;
+    mfn_t *xen_colored_mfns;
+
+    xen_colored_mfns = xmalloc_array(mfn_t, xen_size >> PAGE_SHIFT);
+    if ( !xen_colored_mfns )
+        panic("Can't allocate LLC colored MFNs\n");
+
+    for_each_xen_colored_mfn( xen_mfn, i )
+    {
+        xen_colored_mfns[i] = xen_mfn;
+    }
+
+    xenmap = vmap(xen_colored_mfns, xen_size >> PAGE_SHIFT);
+    xfree(xen_colored_mfns);
+
+    return xenmap;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
index 37b6d230ad..66b674eeab 100644
--- a/xen/arch/arm/mmu/setup.c
+++ b/xen/arch/arm/mmu/setup.c
@@ -7,6 +7,7 @@
 
 #include <xen/init.h>
 #include <xen/libfdt/libfdt.h>
+#include <xen/llc-coloring.h>
 #include <xen/sizes.h>
 #include <xen/vmap.h>
 
@@ -39,6 +40,10 @@ DEFINE_PER_CPU(lpae_t *, xen_pgtable);
 static DEFINE_PAGE_TABLE(cpu0_pgtable);
 #endif
 
+#ifdef CONFIG_LLC_COLORING
+static DEFINE_PAGE_TABLE(xen_colored_temp);
+#endif
+
 /* Common pagetable leaves */
 /* Second level page table used to cover Xen virtual address space */
 static DEFINE_PAGE_TABLE(xen_second);
@@ -130,7 +135,12 @@ static void __init __maybe_unused build_assertions(void)
 
 lpae_t __init pte_of_xenaddr(vaddr_t va)
 {
-    paddr_t ma = va + phys_offset;
+    paddr_t ma;
+
+    if ( llc_coloring_enabled )
+        ma = virt_to_maddr(virt_to_reloc_virt(va));
+    else
+        ma = va + phys_offset;
 
     return mfn_to_xen_entry(maddr_to_mfn(ma), MT_NORMAL);
 }
@@ -216,11 +226,55 @@ static void xen_pt_enforce_wnx(void)
     flush_xen_tlb_local();
 }
 
+#ifdef CONFIG_LLC_COLORING
+static void __init create_llc_coloring_mappings(paddr_t xen_paddr)
+{
+    lpae_t pte;
+    unsigned int i;
+    mfn_t mfn = maddr_to_mfn(xen_paddr);
+
+    for_each_xen_colored_mfn( mfn, i )
+    {
+        pte = mfn_to_xen_entry(mfn, MT_NORMAL);
+        pte.pt.table = 1; /* level 3 mappings always have this bit set */
+        xen_colored_temp[i] = pte;
+    }
+
+    pte = mfn_to_xen_entry(virt_to_mfn(xen_colored_temp), MT_NORMAL);
+    pte.pt.table = 1;
+    write_pte(&boot_second[second_table_offset(BOOT_RELOC_VIRT_START)], pte);
+}
+
+void __init remove_llc_coloring_mappings(void)
+{
+    int rc;
+
+    /* destroy the _PAGE_BLOCK mapping */
+    rc = modify_xen_mappings(BOOT_RELOC_VIRT_START,
+                             BOOT_RELOC_VIRT_START + SZ_2M,
+                             _PAGE_BLOCK);
+    BUG_ON(rc);
+}
+#else
+static void __init create_llc_coloring_mappings(paddr_t xen_paddr) {}
+void __init remove_llc_coloring_mappings(void) {}
+#endif /* CONFIG_LLC_COLORING */
+
 /*
- * Boot-time pagetable setup.
+ * Boot-time pagetable setup with coloring support
  * Changes here may need matching changes in head.S
+ *
+ * The coloring support consists of:
+ * - Create a temporary colored mapping that conforms to Xen color selection.
+ * - pte_of_xenaddr takes care of translating the virtual addresses to the
+ *   new colored physical space and the returns the pte, so that the page table
+ *   initialization can remain the same.
+ * - Copy Xen to the new colored physical space by exploiting the temporary
+ *   mapping.
+ * - Update TTBR0_EL2 with the new root page table address.
  */
-void __init setup_pagetables(unsigned long boot_phys_offset)
+
+void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
 {
     uint64_t ttbr;
     lpae_t pte, *p;
@@ -228,6 +282,9 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
 
     phys_offset = boot_phys_offset;
 
+    if ( llc_coloring_enabled )
+        create_llc_coloring_mappings(xen_paddr);
+
     arch_setup_page_tables();
 
 #ifdef CONFIG_ARM_64
@@ -281,10 +338,13 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
     pte.pt.table = 1;
     xen_second[second_table_offset(FIXMAP_ADDR(0))] = pte;
 
+    if ( llc_coloring_enabled )
+        ttbr = virt_to_maddr(virt_to_reloc_virt(xen_pgtable));
+    else
 #ifdef CONFIG_ARM_64
-    ttbr = (uintptr_t) xen_pgtable + phys_offset;
+        ttbr = (uintptr_t) xen_pgtable + phys_offset;
 #else
-    ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
+        ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
 #endif
 
     switch_ttbr(ttbr);
@@ -294,6 +354,18 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
 #ifdef CONFIG_ARM_32
     per_cpu(xen_pgtable, 0) = cpu0_pgtable;
 #endif
+
+    /*
+    * Keep original Xen memory mapped because secondary CPUs still point to it
+    * and a few variables needs to be accessed by the master CPU in order to
+    * let them boot. This mapping will also replace the one created at the
+    * beginning of setup_pagetables.
+    */
+    if ( llc_coloring_enabled )
+        map_pages_to_xen(BOOT_RELOC_VIRT_START,
+                         maddr_to_mfn(XEN_VIRT_START + phys_offset),
+                         SZ_2M >> PAGE_SHIFT, PAGE_HYPERVISOR_RW | _PAGE_BLOCK);
+
 }
 
 void *__init arch_vmap_virt_end(void)
diff --git a/xen/arch/arm/mmu/smpboot.c b/xen/arch/arm/mmu/smpboot.c
index b6fc0aae07..a69183ec88 100644
--- a/xen/arch/arm/mmu/smpboot.c
+++ b/xen/arch/arm/mmu/smpboot.c
@@ -6,6 +6,7 @@
  */
 
 #include <xen/domain_page.h>
+#include <xen/llc-coloring.h>
 
 #include <asm/setup.h>
 
@@ -71,14 +72,20 @@ static void clear_boot_pagetables(void)
 #ifdef CONFIG_ARM_64
 int prepare_secondary_mm(int cpu)
 {
+    uint64_t *init_ttbr_addr = &init_ttbr;
+
     clear_boot_pagetables();
 
+    if ( llc_coloring_enabled )
+        init_ttbr_addr = (uint64_t *)virt_to_reloc_virt(&init_ttbr);
+
     /*
      * Set init_ttbr for this CPU coming up. All CPUs share a single setof
      * pagetables, but rewrite it each time for consistency with 32 bit.
      */
-    init_ttbr = virt_to_maddr(xen_pgtable);
-    clean_dcache(init_ttbr);
+    *init_ttbr_addr = virt_to_maddr(xen_pgtable);
+    clean_dcache(*init_ttbr_addr);
+
     return 0;
 }
 #else
diff --git a/xen/arch/arm/psci.c b/xen/arch/arm/psci.c
index 695d2fa1f1..23e298c477 100644
--- a/xen/arch/arm/psci.c
+++ b/xen/arch/arm/psci.c
@@ -11,6 +11,7 @@
 
 #include <xen/types.h>
 #include <xen/init.h>
+#include <xen/llc-coloring.h>
 #include <xen/mm.h>
 #include <xen/smp.h>
 #include <asm/cpufeature.h>
@@ -39,9 +40,13 @@ static uint32_t psci_cpu_on_nr;
 int call_psci_cpu_on(int cpu)
 {
     struct arm_smccc_res res;
+    vaddr_t init_secondary_addr = (vaddr_t)init_secondary;
 
-    arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu), __pa(init_secondary),
-                  &res);
+    if ( llc_coloring_enabled )
+        init_secondary_addr = virt_to_reloc_virt(init_secondary);
+
+    arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu),
+                  __pa(init_secondary_addr), &res);
 
     return PSCI_RET(res);
 }
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 4c16b566db..ebbbf39477 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -545,6 +545,100 @@ static void * __init relocate_fdt(paddr_t dtb_paddr, size_t dtb_size)
     return fdt;
 }
 
+#ifdef CONFIG_LLC_COLORING
+/*
+ * Returns the end address of the highest region in the range s..e
+ * with required size and alignment that does not conflict with the
+ * modules from first_mod to nr_modules.
+ *
+ * For non-recursive callers first_mod should normally be 0 (all
+ * modules and Xen itself) or 1 (all modules but not Xen).
+ */
+static paddr_t __init consider_modules(paddr_t s, paddr_t e,
+                                       uint32_t size, paddr_t align,
+                                       int first_mod)
+{
+    const struct bootmodules *mi = &bootinfo.modules;
+    int i;
+    int nr;
+
+    s = (s+align-1) & ~(align-1);
+    e = e & ~(align-1);
+
+    if ( s > e ||  e - s < size )
+        return 0;
+
+    /* First check the boot modules */
+    for ( i = first_mod; i < mi->nr_mods; i++ )
+    {
+        paddr_t mod_s = mi->module[i].start;
+        paddr_t mod_e = mod_s + mi->module[i].size;
+
+        if ( s < mod_e && mod_s < e )
+        {
+            mod_e = consider_modules(mod_e, e, size, align, i+1);
+            if ( mod_e )
+                return mod_e;
+
+            return consider_modules(s, mod_s, size, align, i+1);
+        }
+    }
+
+    /* Now check any fdt reserved areas. */
+
+    nr = fdt_num_mem_rsv(device_tree_flattened);
+
+    for ( ; i < mi->nr_mods + nr; i++ )
+    {
+        paddr_t mod_s, mod_e;
+
+        if ( fdt_get_mem_rsv_paddr(device_tree_flattened,
+                                   i - mi->nr_mods,
+                                   &mod_s, &mod_e ) < 0 )
+            /* If we can't read it, pretend it doesn't exist... */
+            continue;
+
+        /* fdt_get_mem_rsv_paddr returns length */
+        mod_e += mod_s;
+
+        if ( s < mod_e && mod_s < e )
+        {
+            mod_e = consider_modules(mod_e, e, size, align, i+1);
+            if ( mod_e )
+                return mod_e;
+
+            return consider_modules(s, mod_s, size, align, i+1);
+        }
+    }
+
+    /*
+     * i is the current bootmodule we are evaluating, across all
+     * possible kinds of bootmodules.
+     *
+     * When retrieving the corresponding reserved-memory addresses, we
+     * need to index the bootinfo.reserved_mem bank starting from 0, and
+     * only counting the reserved-memory modules. Hence, we need to use
+     * i - nr.
+     */
+    nr += mi->nr_mods;
+    for ( ; i - nr < bootinfo.reserved_mem.nr_banks; i++ )
+    {
+        paddr_t r_s = bootinfo.reserved_mem.bank[i - nr].start;
+        paddr_t r_e = r_s + bootinfo.reserved_mem.bank[i - nr].size;
+
+        if ( s < r_e && r_s < e )
+        {
+            r_e = consider_modules(r_e, e, size, align, i + 1);
+            if ( r_e )
+                return r_e;
+
+            return consider_modules(s, r_s, size, align, i + 1);
+        }
+    }
+    return e;
+}
+#endif
+
 /*
  * Return the end of the non-module region starting at s. In other
  * words return s the start of the next modules after s.
@@ -579,6 +673,62 @@ static paddr_t __init next_module(paddr_t s, paddr_t *end)
     return lowest;
 }
 
+#ifdef CONFIG_LLC_COLORING
+/**
+ * get_xen_paddr - get physical address to relocate Xen to
+ *
+ * Xen is relocated to as near to the top of RAM as possible and
+ * aligned to a XEN_PADDR_ALIGN boundary.
+ */
+static paddr_t __init get_xen_paddr(uint32_t xen_size)
+{
+    struct meminfo *mi = &bootinfo.mem;
+    paddr_t min_size;
+    paddr_t paddr = 0;
+    int i;
+
+    min_size = (xen_size + (XEN_PADDR_ALIGN-1)) & ~(XEN_PADDR_ALIGN-1);
+
+    /* Find the highest bank with enough space. */
+    for ( i = 0; i < mi->nr_banks; i++ )
+    {
+        const struct membank *bank = &mi->bank[i];
+        paddr_t s, e;
+
+        if ( bank->size >= min_size )
+        {
+            e = consider_modules(bank->start, bank->start + bank->size,
+                                 min_size, XEN_PADDR_ALIGN, 0);
+            if ( !e )
+                continue;
+
+#ifdef CONFIG_ARM_32
+            /* Xen must be under 4GB */
+            if ( e > 0x100000000ULL )
+                e = 0x100000000ULL;
+            if ( e < bank->start )
+                continue;
+#endif
+
+            s = e - min_size;
+
+            if ( s > paddr )
+                paddr = s;
+        }
+    }
+
+    if ( !paddr )
+        panic("Not enough memory to relocate Xen\n");
+
+    printk("Placing Xen at 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
+           paddr, paddr + min_size);
+
+    return paddr;
+}
+#else
+static paddr_t __init get_xen_paddr(uint32_t xen_size) { return 0; }
+#endif
+
 void __init init_pdx(void)
 {
     paddr_t bank_start, bank_size, bank_end;
@@ -724,8 +874,6 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
     /* Initialize traps early allow us to get backtrace when an error occurred */
     init_traps();
 
-    setup_pagetables(boot_phys_offset);
-
     smp_clear_cpu_maps();
 
     device_tree_flattened = early_fdt_map(fdt_paddr);
@@ -751,8 +899,13 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
     {
         if ( !llc_coloring_init() )
             panic("Xen LLC coloring support: setup failed\n");
+        xen_bootmodule->size = xen_colored_map_size(_end - _start);
+        xen_bootmodule->start = get_xen_paddr(xen_bootmodule->size);
     }
 
+    setup_pagetables(boot_phys_offset, xen_bootmodule->start);
+    device_tree_flattened = early_fdt_map(fdt_paddr);
+
     setup_mm();
 
     /* Parse the ACPI tables for possible boot-time configuration */
@@ -867,6 +1020,14 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
 
     setup_virt_paging();
 
+    /*
+     * The removal is done earlier than discard_initial_modules beacuse the
+     * livepatch init uses a virtual address equal to BOOT_RELOC_VIRT_START.
+     * Remove LLC coloring mappings to expose a clear state to the livepatch
+     * module.
+     */
+    if ( llc_coloring_enabled )
+        remove_llc_coloring_mappings();
     do_initcalls();
 
     /*
diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
index 7110bc11fc..7ed7357d58 100644
--- a/xen/arch/arm/smpboot.c
+++ b/xen/arch/arm/smpboot.c
@@ -14,6 +14,7 @@
 #include <xen/domain_page.h>
 #include <xen/errno.h>
 #include <xen/init.h>
+#include <xen/llc-coloring.h>
 #include <xen/mm.h>
 #include <xen/param.h>
 #include <xen/sched.h>
@@ -444,6 +445,7 @@ int __cpu_up(unsigned int cpu)
 {
     int rc;
     s_time_t deadline;
+    unsigned long *smp_up_cpu_addr = &smp_up_cpu;
 
     printk("Bringing up CPU%d\n", cpu);
 
@@ -459,9 +461,12 @@ int __cpu_up(unsigned int cpu)
     /* Tell the remote CPU what its logical CPU ID is. */
     init_data.cpuid = cpu;
 
+    if ( llc_coloring_enabled )
+        smp_up_cpu_addr = (unsigned long *)virt_to_reloc_virt(&smp_up_cpu);
+
     /* Open the gate for this CPU */
-    smp_up_cpu = cpu_logical_map(cpu);
-    clean_dcache(smp_up_cpu);
+    *smp_up_cpu_addr = cpu_logical_map(cpu);
+    clean_dcache(*smp_up_cpu_addr);
 
     rc = arch_cpu_up(cpu);
 
-- 
2.34.1



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

* Re: [PATCH v5 00/13] Arm cache coloring
  2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
                   ` (12 preceding siblings ...)
  2024-01-02  9:51 ` [PATCH v5 13/13] xen/arm: add cache coloring support for Xen Carlo Nonato
@ 2024-01-03 13:34 ` Michal Orzel
  2024-01-04  0:05   ` Stefano Stabellini
  13 siblings, 1 reply; 90+ messages in thread
From: Michal Orzel @ 2024-01-03 13:34 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Andrew Cooper, George Dunlap, Jan Beulich, Julien Grall,
	Stefano Stabellini, Wei Liu, Bertrand Marquis, Volodymyr Babchuk,
	Anthony PERARD, Juergen Gross

Hi,

On 02/01/2024 10:51, Carlo Nonato wrote:
> 
> 
> Shared caches in multi-core CPU architectures represent a problem for
> predictability of memory access latency. This jeopardizes applicability
> of many Arm platform in real-time critical and mixed-criticality
> scenarios. We introduce support for cache partitioning with page
> coloring, a transparent software technique that enables isolation
> between domains and Xen, and thus avoids cache interference.
> 
> When creating a domain, a simple syntax (e.g. `0-3` or `4-11`) allows
> the user to define assignments of cache partitions ids, called colors,
> where assigning different colors guarantees no mutual eviction on cache
> will ever happen. This instructs the Xen memory allocator to provide
> the i-th color assignee only with pages that maps to color i, i.e. that
> are indexed in the i-th cache partition.
> 
> The proposed implementation supports the dom0less feature.
> The proposed implementation doesn't support the static-mem feature.
> The solution has been tested in several scenarios, including Xilinx Zynq
> MPSoCs.
> 
> In this patch series there are two major unacceptable workarounds for which
> I want to ask you for comments:
>  - #3: allocate_memory() has been moved in dom0less_build.c, so I just copied
>  it back to make it compile.
I would move it to domain_build.c and add a prototype in domain_build.h.
You could guard it together with allocate_bank_memory() for DOM0LESS || LLC or just
remove the guards (in former case, you would need to protect your call with #ifdef in construct_dom0()).

>  - #13: consider_modules() has been moved to arm32 only. Again I just copied it.
I would move it to setup.c and add a prototype in setup.h.
As for the guards, if we want them (personally I don't see the need), you would need LLC || (ARM_32 && MMU).

BTW. Patchew reports some build issues in your series:
https://gitlab.com/xen-project/patchew/xen/-/pipelines/1124313980

Make sure to build test your series on different arches. You can ask on IRC to become a member
on gitlab so that you can trigger the pipeline by pushing the changes to your fork on people/<you>/xen.

~Michal


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

* Re: [PATCH v5 00/13] Arm cache coloring
  2024-01-03 13:34 ` [PATCH v5 00/13] Arm cache coloring Michal Orzel
@ 2024-01-04  0:05   ` Stefano Stabellini
  2024-01-04  1:55     ` Stefano Stabellini
  0 siblings, 1 reply; 90+ messages in thread
From: Stefano Stabellini @ 2024-01-04  0:05 UTC (permalink / raw)
  To: Michal Orzel
  Cc: Carlo Nonato, xen-devel, Andrew Cooper, George Dunlap,
	Jan Beulich, Julien Grall, Stefano Stabellini, Wei Liu,
	Bertrand Marquis, Volodymyr Babchuk, Anthony PERARD,
	Juergen Gross

On Wed, 3 Jan 2024, Michal Orzel wrote:
> Hi,
> 
> On 02/01/2024 10:51, Carlo Nonato wrote:
> > 
> > 
> > Shared caches in multi-core CPU architectures represent a problem for
> > predictability of memory access latency. This jeopardizes applicability
> > of many Arm platform in real-time critical and mixed-criticality
> > scenarios. We introduce support for cache partitioning with page
> > coloring, a transparent software technique that enables isolation
> > between domains and Xen, and thus avoids cache interference.
> > 
> > When creating a domain, a simple syntax (e.g. `0-3` or `4-11`) allows
> > the user to define assignments of cache partitions ids, called colors,
> > where assigning different colors guarantees no mutual eviction on cache
> > will ever happen. This instructs the Xen memory allocator to provide
> > the i-th color assignee only with pages that maps to color i, i.e. that
> > are indexed in the i-th cache partition.
> > 
> > The proposed implementation supports the dom0less feature.
> > The proposed implementation doesn't support the static-mem feature.
> > The solution has been tested in several scenarios, including Xilinx Zynq
> > MPSoCs.
> > 
> > In this patch series there are two major unacceptable workarounds for which
> > I want to ask you for comments:
> >  - #3: allocate_memory() has been moved in dom0less_build.c, so I just copied
> >  it back to make it compile.
> I would move it to domain_build.c and add a prototype in domain_build.h.
> You could guard it together with allocate_bank_memory() for DOM0LESS || LLC or just
> remove the guards (in former case, you would need to protect your call with #ifdef in construct_dom0()).
> 
> >  - #13: consider_modules() has been moved to arm32 only. Again I just copied it.
> I would move it to setup.c and add a prototype in setup.h.
> As for the guards, if we want them (personally I don't see the need), you would need LLC || (ARM_32 && MMU).
> 
> BTW. Patchew reports some build issues in your series:
> https://gitlab.com/xen-project/patchew/xen/-/pipelines/1124313980
> 
> Make sure to build test your series on different arches. You can ask on IRC to become a member
> on gitlab so that you can trigger the pipeline by pushing the changes to your fork on people/<you>/xen.

Also I tried this patch series on the "staging" branch and Xen failed to
boot, no messages at all from Xen so it must be an early boot failure. I
am passing this command line options to Xen and running it on QEMU:

dom0_mem=1024M dom0_max_vcpus=1 xen-llc-colors=0 dom0-llc-colors=1-5 llc-way-size=65535 llc-coloring=true



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

* Re: [PATCH v5 00/13] Arm cache coloring
  2024-01-04  0:05   ` Stefano Stabellini
@ 2024-01-04  1:55     ` Stefano Stabellini
  2024-01-04  9:37       ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Stefano Stabellini @ 2024-01-04  1:55 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Michal Orzel, Carlo Nonato, xen-devel, Andrew Cooper,
	George Dunlap, Jan Beulich, Julien Grall, Wei Liu,
	Bertrand Marquis, Volodymyr Babchuk, Anthony PERARD,
	Juergen Gross

On Wed, 3 Jan 2024, Stefano Stabellini wrote:
> Also I tried this patch series on the "staging" branch and Xen failed to
> boot, no messages at all from Xen so it must be an early boot failure. I
> am passing this command line options to Xen and running it on QEMU:
> 
> dom0_mem=1024M dom0_max_vcpus=1 xen-llc-colors=0 dom0-llc-colors=1-5 llc-way-size=65535 llc-coloring=true

I managed to make it to work successfully with the following command
line:

xen-llc-colors=0 dom0-llc-colors=1-5 llc-way-size=64K llc-coloring=on

I think the problem was llc-way-size that needs to be rounded up (64K
instead of 65535).

Also I found a few build issues when building for other architectures or
different kconfig options. This patch addresses those issues (however it
is not to be taken as is as the build issues should not be introduced in
the first place and there are probably better way to fix them, but I
hope it can help).

Cheers,

Stefano


diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
index f434efc45b..efe5cf3c23 100644
--- a/xen/arch/arm/llc-coloring.c
+++ b/xen/arch/arm/llc-coloring.c
@@ -39,7 +39,7 @@ static unsigned int __ro_after_init xen_num_colors;
 
 #define mfn_color_mask              (nr_colors - 1)
 #define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
-#define mfn_set_color(mfn, color)   ((mfn_x(mfn) & ~mfn_color_mask) | (color))
+#define mfn_set_color(mfn, color)   (_mfn((mfn_x(mfn) & ~mfn_color_mask) | (color)))
 
 /*
  * Parse the coloring configuration given in the buf string, following the
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 3bb0c9221f..bf16703e24 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -610,10 +610,10 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
     pte.pt.table = 1;
     xen_second[second_table_offset(FIXMAP_ADDR(0))] = pte;
 
+#ifdef CONFIG_ARM_64
     if ( llc_coloring_enabled )
         ttbr = virt_to_maddr(virt_to_reloc_virt(xen_pgtable));
     else
-#ifdef CONFIG_ARM_64
         ttbr = (uintptr_t) xen_pgtable + phys_offset;
 #else
         ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
index 7cd481e955..516139c4ff 100644
--- a/xen/include/xen/llc-coloring.h
+++ b/xen/include/xen/llc-coloring.h
@@ -21,7 +21,27 @@
 extern bool llc_coloring_enabled;
 #define llc_coloring_enabled (llc_coloring_enabled)
 #endif
-
+#else
+static inline void *xen_remap_colored(mfn_t xen_fn, paddr_t xen_size)
+{
+    return NULL;
+}
+static inline int domain_set_llc_colors_from_str(struct domain *d, const char *str)
+{
+    return -ENOSYS;
+}
+static inline int dom0_set_llc_colors(struct domain *d)
+{
+    return 0;
+}
+static inline bool llc_coloring_init(void)
+{
+    return false;
+}
+static inline paddr_t xen_colored_map_size(paddr_t size)
+{
+    return 0;
+}
 #endif
 
 #ifndef llc_coloring_enabled


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

* Re: [PATCH v5 00/13] Arm cache coloring
  2024-01-04  1:55     ` Stefano Stabellini
@ 2024-01-04  9:37       ` Carlo Nonato
  2024-01-04 10:19         ` Michal Orzel
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-04  9:37 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Michal Orzel, xen-devel, Andrew Cooper, George Dunlap,
	Jan Beulich, Julien Grall, Wei Liu, Bertrand Marquis,
	Volodymyr Babchuk, Anthony PERARD, Juergen Gross

Hi Stefano,

On Thu, Jan 4, 2024 at 2:55 AM Stefano Stabellini
<sstabellini@kernel.org> wrote:
>
> On Wed, 3 Jan 2024, Stefano Stabellini wrote:
> > Also I tried this patch series on the "staging" branch and Xen failed to
> > boot, no messages at all from Xen so it must be an early boot failure. I
> > am passing this command line options to Xen and running it on QEMU:
> >
> > dom0_mem=1024M dom0_max_vcpus=1 xen-llc-colors=0 dom0-llc-colors=1-5 llc-way-size=65535 llc-coloring=true
>
> I managed to make it to work successfully with the following command
> line:
>
> xen-llc-colors=0 dom0-llc-colors=1-5 llc-way-size=64K llc-coloring=on
>
> I think the problem was llc-way-size that needs to be rounded up (64K
> instead of 65535).
>
> Also I found a few build issues when building for other architectures or
> different kconfig options. This patch addresses those issues (however it
> is not to be taken as is as the build issues should not be introduced in
> the first place and there are probably better way to fix them, but I
> hope it can help).
>
> Cheers,
>
> Stefano
>
>
> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> index f434efc45b..efe5cf3c23 100644
> --- a/xen/arch/arm/llc-coloring.c
> +++ b/xen/arch/arm/llc-coloring.c
> @@ -39,7 +39,7 @@ static unsigned int __ro_after_init xen_num_colors;
>
>  #define mfn_color_mask              (nr_colors - 1)
>  #define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
> -#define mfn_set_color(mfn, color)   ((mfn_x(mfn) & ~mfn_color_mask) | (color))
> +#define mfn_set_color(mfn, color)   (_mfn((mfn_x(mfn) & ~mfn_color_mask) | (color)))

Thanks for spotting this.

>  /*
>   * Parse the coloring configuration given in the buf string, following the
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index 3bb0c9221f..bf16703e24 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -610,10 +610,10 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
>      pte.pt.table = 1;
>      xen_second[second_table_offset(FIXMAP_ADDR(0))] = pte;
>
> +#ifdef CONFIG_ARM_64
>      if ( llc_coloring_enabled )
>          ttbr = virt_to_maddr(virt_to_reloc_virt(xen_pgtable));
>      else
> -#ifdef CONFIG_ARM_64
>          ttbr = (uintptr_t) xen_pgtable + phys_offset;
>  #else
>          ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
> diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
> index 7cd481e955..516139c4ff 100644
> --- a/xen/include/xen/llc-coloring.h
> +++ b/xen/include/xen/llc-coloring.h
> @@ -21,7 +21,27 @@
>  extern bool llc_coloring_enabled;
>  #define llc_coloring_enabled (llc_coloring_enabled)
>  #endif
> -
> +#else
> +static inline void *xen_remap_colored(mfn_t xen_fn, paddr_t xen_size)
> +{
> +    return NULL;
> +}
> +static inline int domain_set_llc_colors_from_str(struct domain *d, const char *str)
> +{
> +    return -ENOSYS;
> +}
> +static inline int dom0_set_llc_colors(struct domain *d)
> +{
> +    return 0;
> +}
> +static inline bool llc_coloring_init(void)
> +{
> +    return false;
> +}
> +static inline paddr_t xen_colored_map_size(paddr_t size)
> +{
> +    return 0;
> +}
>  #endif
>
>  #ifndef llc_coloring_enabled

Sorry for the compilation mess.

This is definitely a solution, but I wonder if the best thing to do would be
to move all signatures in the common header, without the stubs, relying again
on DCE. This seems a little strange to me because users of some of those
functions are only in arm code, and they always have to be protected with
llc_coloring_enabled global variable/macro if, but it works (now I'm
compiling also for arm32 and x86).

Thanks.


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

* Re: [PATCH v5 00/13] Arm cache coloring
  2024-01-04  9:37       ` Carlo Nonato
@ 2024-01-04 10:19         ` Michal Orzel
  2024-01-04 17:56           ` Stefano Stabellini
  0 siblings, 1 reply; 90+ messages in thread
From: Michal Orzel @ 2024-01-04 10:19 UTC (permalink / raw)
  To: Carlo Nonato, Stefano Stabellini
  Cc: xen-devel, Andrew Cooper, George Dunlap, Jan Beulich,
	Julien Grall, Wei Liu, Bertrand Marquis, Volodymyr Babchuk,
	Anthony PERARD, Juergen Gross



On 04/01/2024 10:37, Carlo Nonato wrote:
> 
> 
> Hi Stefano,
> 
> On Thu, Jan 4, 2024 at 2:55 AM Stefano Stabellini
> <sstabellini@kernel.org> wrote:
>>
>> On Wed, 3 Jan 2024, Stefano Stabellini wrote:
>>> Also I tried this patch series on the "staging" branch and Xen failed to
>>> boot, no messages at all from Xen so it must be an early boot failure. I
>>> am passing this command line options to Xen and running it on QEMU:
>>>
>>> dom0_mem=1024M dom0_max_vcpus=1 xen-llc-colors=0 dom0-llc-colors=1-5 llc-way-size=65535 llc-coloring=true
>>
>> I managed to make it to work successfully with the following command
>> line:
>>
>> xen-llc-colors=0 dom0-llc-colors=1-5 llc-way-size=64K llc-coloring=on
>>
>> I think the problem was llc-way-size that needs to be rounded up (64K
>> instead of 65535).
>>
>> Also I found a few build issues when building for other architectures or
>> different kconfig options. This patch addresses those issues (however it
>> is not to be taken as is as the build issues should not be introduced in
>> the first place and there are probably better way to fix them, but I
>> hope it can help).
>>
>> Cheers,
>>
>> Stefano
>>
>>
>> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
>> index f434efc45b..efe5cf3c23 100644
>> --- a/xen/arch/arm/llc-coloring.c
>> +++ b/xen/arch/arm/llc-coloring.c
>> @@ -39,7 +39,7 @@ static unsigned int __ro_after_init xen_num_colors;
>>
>>  #define mfn_color_mask              (nr_colors - 1)
>>  #define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
>> -#define mfn_set_color(mfn, color)   ((mfn_x(mfn) & ~mfn_color_mask) | (color))
>> +#define mfn_set_color(mfn, color)   (_mfn((mfn_x(mfn) & ~mfn_color_mask) | (color)))
> 
> Thanks for spotting this.
> 
>>  /*
>>   * Parse the coloring configuration given in the buf string, following the
>> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
>> index 3bb0c9221f..bf16703e24 100644
>> --- a/xen/arch/arm/mm.c
>> +++ b/xen/arch/arm/mm.c
>> @@ -610,10 +610,10 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
>>      pte.pt.table = 1;
>>      xen_second[second_table_offset(FIXMAP_ADDR(0))] = pte;
>>
>> +#ifdef CONFIG_ARM_64
>>      if ( llc_coloring_enabled )
>>          ttbr = virt_to_maddr(virt_to_reloc_virt(xen_pgtable));
>>      else
>> -#ifdef CONFIG_ARM_64
>>          ttbr = (uintptr_t) xen_pgtable + phys_offset;
>>  #else
>>          ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
>> diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
>> index 7cd481e955..516139c4ff 100644
>> --- a/xen/include/xen/llc-coloring.h
>> +++ b/xen/include/xen/llc-coloring.h
>> @@ -21,7 +21,27 @@
>>  extern bool llc_coloring_enabled;
>>  #define llc_coloring_enabled (llc_coloring_enabled)
>>  #endif
>> -
>> +#else
>> +static inline void *xen_remap_colored(mfn_t xen_fn, paddr_t xen_size)
>> +{
>> +    return NULL;
>> +}
>> +static inline int domain_set_llc_colors_from_str(struct domain *d, const char *str)
>> +{
>> +    return -ENOSYS;
>> +}
>> +static inline int dom0_set_llc_colors(struct domain *d)
>> +{
>> +    return 0;
>> +}
>> +static inline bool llc_coloring_init(void)
>> +{
>> +    return false;
>> +}
>> +static inline paddr_t xen_colored_map_size(paddr_t size)
>> +{
>> +    return 0;
>> +}
>>  #endif
>>
>>  #ifndef llc_coloring_enabled
> 
> Sorry for the compilation mess.
> 
> This is definitely a solution, but I wonder if the best thing to do would be
> to move all signatures in the common header, without the stubs, relying again
> on DCE. This seems a little strange to me because users of some of those
> functions are only in arm code, and they always have to be protected with
> llc_coloring_enabled global variable/macro if, but it works (now I'm
> compiling also for arm32 and x86).
There are a lot of places in Xen relying on DCE, so I'd be ok with that (you can wait
for Stefano's opinion). Furthermore, you already rely on that in case of e.g. domain_set_llc_colors_domctl,
domain_llc_coloring_free.

~Michal


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

* Re: [PATCH v5 00/13] Arm cache coloring
  2024-01-04 10:19         ` Michal Orzel
@ 2024-01-04 17:56           ` Stefano Stabellini
  0 siblings, 0 replies; 90+ messages in thread
From: Stefano Stabellini @ 2024-01-04 17:56 UTC (permalink / raw)
  To: Michal Orzel
  Cc: Carlo Nonato, Stefano Stabellini, xen-devel, Andrew Cooper,
	George Dunlap, Jan Beulich, Julien Grall, Wei Liu,
	Bertrand Marquis, Volodymyr Babchuk, Anthony PERARD,
	Juergen Gross

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

On Thu, 4 Jan 2024, Michal Orzel wrote:
> On 04/01/2024 10:37, Carlo Nonato wrote:
> > Hi Stefano,
> > 
> > On Thu, Jan 4, 2024 at 2:55 AM Stefano Stabellini
> > <sstabellini@kernel.org> wrote:
> >>
> >> On Wed, 3 Jan 2024, Stefano Stabellini wrote:
> >>> Also I tried this patch series on the "staging" branch and Xen failed to
> >>> boot, no messages at all from Xen so it must be an early boot failure. I
> >>> am passing this command line options to Xen and running it on QEMU:
> >>>
> >>> dom0_mem=1024M dom0_max_vcpus=1 xen-llc-colors=0 dom0-llc-colors=1-5 llc-way-size=65535 llc-coloring=true
> >>
> >> I managed to make it to work successfully with the following command
> >> line:
> >>
> >> xen-llc-colors=0 dom0-llc-colors=1-5 llc-way-size=64K llc-coloring=on
> >>
> >> I think the problem was llc-way-size that needs to be rounded up (64K
> >> instead of 65535).
> >>
> >> Also I found a few build issues when building for other architectures or
> >> different kconfig options. This patch addresses those issues (however it
> >> is not to be taken as is as the build issues should not be introduced in
> >> the first place and there are probably better way to fix them, but I
> >> hope it can help).
> >>
> >> Cheers,
> >>
> >> Stefano
> >>
> >>
> >> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> >> index f434efc45b..efe5cf3c23 100644
> >> --- a/xen/arch/arm/llc-coloring.c
> >> +++ b/xen/arch/arm/llc-coloring.c
> >> @@ -39,7 +39,7 @@ static unsigned int __ro_after_init xen_num_colors;
> >>
> >>  #define mfn_color_mask              (nr_colors - 1)
> >>  #define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
> >> -#define mfn_set_color(mfn, color)   ((mfn_x(mfn) & ~mfn_color_mask) | (color))
> >> +#define mfn_set_color(mfn, color)   (_mfn((mfn_x(mfn) & ~mfn_color_mask) | (color)))
> > 
> > Thanks for spotting this.
> > 
> >>  /*
> >>   * Parse the coloring configuration given in the buf string, following the
> >> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> >> index 3bb0c9221f..bf16703e24 100644
> >> --- a/xen/arch/arm/mm.c
> >> +++ b/xen/arch/arm/mm.c
> >> @@ -610,10 +610,10 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
> >>      pte.pt.table = 1;
> >>      xen_second[second_table_offset(FIXMAP_ADDR(0))] = pte;
> >>
> >> +#ifdef CONFIG_ARM_64
> >>      if ( llc_coloring_enabled )
> >>          ttbr = virt_to_maddr(virt_to_reloc_virt(xen_pgtable));
> >>      else
> >> -#ifdef CONFIG_ARM_64
> >>          ttbr = (uintptr_t) xen_pgtable + phys_offset;
> >>  #else
> >>          ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
> >> diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
> >> index 7cd481e955..516139c4ff 100644
> >> --- a/xen/include/xen/llc-coloring.h
> >> +++ b/xen/include/xen/llc-coloring.h
> >> @@ -21,7 +21,27 @@
> >>  extern bool llc_coloring_enabled;
> >>  #define llc_coloring_enabled (llc_coloring_enabled)
> >>  #endif
> >> -
> >> +#else
> >> +static inline void *xen_remap_colored(mfn_t xen_fn, paddr_t xen_size)
> >> +{
> >> +    return NULL;
> >> +}
> >> +static inline int domain_set_llc_colors_from_str(struct domain *d, const char *str)
> >> +{
> >> +    return -ENOSYS;
> >> +}
> >> +static inline int dom0_set_llc_colors(struct domain *d)
> >> +{
> >> +    return 0;
> >> +}
> >> +static inline bool llc_coloring_init(void)
> >> +{
> >> +    return false;
> >> +}
> >> +static inline paddr_t xen_colored_map_size(paddr_t size)
> >> +{
> >> +    return 0;
> >> +}
> >>  #endif
> >>
> >>  #ifndef llc_coloring_enabled
> > 
> > Sorry for the compilation mess.
> > 
> > This is definitely a solution, but I wonder if the best thing to do would be
> > to move all signatures in the common header, without the stubs, relying again
> > on DCE. This seems a little strange to me because users of some of those
> > functions are only in arm code, and they always have to be protected with
> > llc_coloring_enabled global variable/macro if, but it works (now I'm
> > compiling also for arm32 and x86).
> There are a lot of places in Xen relying on DCE, so I'd be ok with that (you can wait
> for Stefano's opinion). Furthermore, you already rely on that in case of e.g. domain_set_llc_colors_domctl,
> domain_llc_coloring_free.
 
Yeah I think that would be fine

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

* Re: [PATCH v5 01/13] xen/common: add cache coloring common code
  2024-01-02  9:51 ` [PATCH v5 01/13] xen/common: add cache coloring common code Carlo Nonato
@ 2024-01-04 18:39   ` Julien Grall
  2024-01-04 19:59   ` Julien Grall
  2024-01-08 16:53   ` Jan Beulich
  2 siblings, 0 replies; 90+ messages in thread
From: Julien Grall @ 2024-01-04 18:39 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Andrew Cooper, George Dunlap, Jan Beulich, Stefano Stabellini,
	Wei Liu, Marco Solieri

Hi Carlo,

On 02/01/2024 09:51, Carlo Nonato wrote:
> This commit adds the Last Level Cache (LLC) coloring common header, Kconfig
> options and functions. Since this is an arch specific feature, actual
> implementation is postponed to later patches and Kconfig options are placed
> under xen/arch.
> 
> LLC colors are a property of the domain, so the domain struct has to be
> extended.

The interface below looks ok. I have left some comments below.

> 
> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
> v5:
> - used - instead of _ for filenames
> - removed domain_create_llc_colored()
> - removed stub functions
> - coloring domain fields are now #ifdef protected
> v4:
> - Kconfig options moved to xen/arch
> - removed range for CONFIG_NR_LLC_COLORS
> - added "llc_coloring_enabled" global to later implement the boot-time
>    switch
> - added domain_create_llc_colored() to be able to pass colors
> - added is_domain_llc_colored() macro
> ---
>   xen/arch/Kconfig               | 16 ++++++++++++
>   xen/common/Kconfig             |  3 +++
>   xen/common/domain.c            |  4 +++
>   xen/common/keyhandler.c        |  4 +++
>   xen/include/xen/llc-coloring.h | 46 ++++++++++++++++++++++++++++++++++
>   xen/include/xen/sched.h        |  5 ++++
>   6 files changed, 78 insertions(+)
>   create mode 100644 xen/include/xen/llc-coloring.h
> 
> diff --git a/xen/arch/Kconfig b/xen/arch/Kconfig
> index 67ba38f32f..aad7e9da38 100644
> --- a/xen/arch/Kconfig
> +++ b/xen/arch/Kconfig
> @@ -31,3 +31,19 @@ config NR_NUMA_NODES
>   	  associated with multiple-nodes management. It is the upper bound of
>   	  the number of NUMA nodes that the scheduler, memory allocation and
>   	  other NUMA-aware components can handle.
> +
> +config LLC_COLORING
> +	bool "Last Level Cache (LLC) coloring" if EXPERT
> +	depends on HAS_LLC_COLORING
> +
> +config NR_LLC_COLORS
> +	int "Maximum number of LLC colors"
> +	default 128
> +	depends on LLC_COLORING
> +	help
> +	  Controls the build-time size of various arrays associated with LLC
> +	  coloring. Refer to cache coloring documentation for how to compute the
> +	  number of colors supported by the platform. This is only an upper
> +	  bound. The runtime value is autocomputed or manually set via cmdline.
> +	  The default value corresponds to an 8 MiB 16-ways LLC, which should be
> +	  more than what needed in the general case.
> diff --git a/xen/common/Kconfig b/xen/common/Kconfig
> index 310ad4229c..e383f09d97 100644
> --- a/xen/common/Kconfig
> +++ b/xen/common/Kconfig
> @@ -71,6 +71,9 @@ config HAS_IOPORTS
>   config HAS_KEXEC
>   	bool
>   
> +config HAS_LLC_COLORING
> +	bool
> +
>   config HAS_PMAP
>   	bool
>   
> diff --git a/xen/common/domain.c b/xen/common/domain.c
> index f6f5574996..491585b0bb 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -7,6 +7,7 @@
>   #include <xen/compat.h>
>   #include <xen/init.h>
>   #include <xen/lib.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/ctype.h>
>   #include <xen/err.h>
>   #include <xen/param.h>
> @@ -1144,6 +1145,9 @@ static void cf_check complete_domain_destroy(struct rcu_head *head)
>       struct vcpu *v;
>       int i;
>   
> +    if ( is_domain_llc_colored(d) )
> +        domain_llc_coloring_free(d);
> +
>       /*
>        * Flush all state for the vCPU previously having run on the current CPU.
>        * This is in particular relevant for x86 HVM ones on VMX, so that this
> diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
> index 99a2d72a02..27c2d324d8 100644
> --- a/xen/common/keyhandler.c
> +++ b/xen/common/keyhandler.c
> @@ -6,6 +6,7 @@
>   #include <xen/debugger.h>
>   #include <xen/delay.h>
>   #include <xen/keyhandler.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/param.h>
>   #include <xen/shutdown.h>
>   #include <xen/event.h>
> @@ -307,6 +308,9 @@ static void cf_check dump_domains(unsigned char key)
>   
>           arch_dump_domain_info(d);
>   
> +        if ( is_domain_llc_colored(d) )
> +            domain_dump_llc_colors(d);
> +
>           rangeset_domain_printk(d);
>   
>           dump_pageframe_info(d);
> diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
> new file mode 100644
> index 0000000000..cedd97d4b5
> --- /dev/null
> +++ b/xen/include/xen/llc-coloring.h
> @@ -0,0 +1,46 @@
> +/* SPDX-License-Identifier: GPL-2.0 */

For new SPDX we should use GPL-2.0-only. AFAIK, this is equivalent 
license but with a clearer name.

> +/*
> + * Last Level Cache (LLC) coloring common header
> + *
> + * Copyright (C) 2022 Xilinx Inc.
> + *
> + * Authors:
> + *    Carlo Nonato <carlo.nonato@minervasys.tech>

NIT: We don't usually add the authors in the code and instead rely on 
the Author/Signed-off-by in the commit.

If you want to keep it, then I will query why you added yourself but not 
Marco Solieri or Luca Miccio.

> + */
> +#ifndef __COLORING_H__
> +#define __COLORING_H__
> +
> +#include <xen/sched.h>
> +#include <public/domctl.h>
> +
> +#ifdef CONFIG_HAS_LLC_COLORING
> +
> +#include <asm/llc-coloring.h>
> +
> +#ifdef CONFIG_LLC_COLORING
> +extern bool llc_coloring_enabled;
> +#define llc_coloring_enabled (llc_coloring_enabled)

I don't really understand why you need the define here. Wouldn't it be 
clearer to have a #else and then ...

> +#endif
> +
> +#endif
> +
> +#ifndef llc_coloring_enabled
> +#define llc_coloring_enabled (false)

... define llc_coloring_enabled?

Also NIT: The parentheses are not necessary.

> +#endif
> +
> +#define is_domain_llc_colored(d) (llc_coloring_enabled)

You want to evaluate d. But here I would consider to use a static 
inline. Nowadays, we favor static inline helpers over macros as they add 
typesafety and you don't need to do trick (e.v. (void)(d)) to interpret 
the arguments.

> +
> +void domain_llc_coloring_free(struct domain *d);
> +void domain_dump_llc_colors(struct domain *d);

Looking at the usage, 'd' could be const.

> +
> +#endif /* __COLORING_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
> index 9da91e0e62..dae7fab673 100644
> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -626,6 +626,11 @@ struct domain
>   
>       /* Holding CDF_* constant. Internal flags for domain creation. */
>       unsigned int cdf;
> +
> +#ifdef CONFIG_LLC_COLORING
> +    unsigned int *llc_colors;
> +    unsigned int num_llc_colors;
> +#endif
>   };
>   
>   static inline struct page_list_head *page_to_list(

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 02/13] xen/arm: add cache coloring initialization
  2024-01-02  9:51 ` [PATCH v5 02/13] xen/arm: add cache coloring initialization Carlo Nonato
@ 2024-01-04 19:24   ` Julien Grall
  2024-01-05 16:34     ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-04 19:24 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Carlo,

On 02/01/2024 09:51, Carlo Nonato wrote:
> This commit implements functions declared in the LLC coloring common header
> for arm64 and adds documentation. It also adds two command line options: a
> runtime switch for the cache coloring feature and the LLC way size
> parameter.
> 
> The feature init function consists of an auto probing of the cache layout
> necessary to retrieve the LLC way size which is used to compute the number
> of platform colors. It also adds a debug-key to dump general cache coloring
> info.
> 
> Static memory allocation and cache coloring are incompatible because static
> memory can't be guaranteed to use only colors assigned to the domain.
> Panic during domUs creation when both are enabled.
> 
> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
> v5:
> - used - instead of _ for filenames
> - moved static-mem check in this patch
> - moved dom0 colors parsing in next patch
> - moved color allocation and configuration in next patch
> - moved check_colors() in next patch
> - colors are now printed in short form
> v4:
> - added "llc-coloring" cmdline option for the boot-time switch
> - dom0 colors are now checked during domain init as for any other domain
> - fixed processor.h masks bit width
> - check for overflow in parse_color_config()
> - check_colors() now checks also that colors are sorted and unique
> ---
>   docs/misc/arm/cache-coloring.rst        |  97 ++++++++++++++
>   docs/misc/xen-command-line.pandoc       |  28 +++++
>   xen/arch/arm/Kconfig                    |   1 +
>   xen/arch/arm/Makefile                   |   1 +
>   xen/arch/arm/dom0less-build.c           |   6 +
>   xen/arch/arm/include/asm/llc-coloring.h |  28 +++++
>   xen/arch/arm/include/asm/processor.h    |  16 +++
>   xen/arch/arm/llc-coloring.c             | 161 ++++++++++++++++++++++++
>   xen/arch/arm/setup.c                    |   7 ++
>   9 files changed, 345 insertions(+)
>   create mode 100644 docs/misc/arm/cache-coloring.rst
>   create mode 100644 xen/arch/arm/include/asm/llc-coloring.h
>   create mode 100644 xen/arch/arm/llc-coloring.c
> 
> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> new file mode 100644
> index 0000000000..eabf8f5d1b
> --- /dev/null
> +++ b/docs/misc/arm/cache-coloring.rst
> @@ -0,0 +1,97 @@
> +Xen cache coloring user guide
> +=============================
> +
> +The cache coloring support in Xen allows to reserve Last Level Cache (LLC)
> +partitions for Dom0, DomUs and Xen itself. Currently only ARM64 is supported.
> +
> +To compile LLC coloring support set ``CONFIG_LLC_COLORING=y``.
> +
> +If needed, change the maximum number of colors with
> +``CONFIG_NR_LLC_COLORS=<n>``.
> +
> +Compile Xen and the toolstack and then configure it via
> +`Command line parameters`_.
> +
> +Background
> +**********
> +
> +Cache hierarchy of a modern multi-core CPU typically has first levels dedicated
> +to each core (hence using multiple cache units), while the last level is shared
> +among all of them. Such configuration implies that memory operations on one
> +core (e.g. running a DomU) are able to generate interference on another core
> +(e.g .hosting another DomU). Cache coloring allows eliminating this
> +mutual interference, and thus guaranteeing higher and more predictable
> +performances for memory accesses.
> +The key concept underlying cache coloring is a fragmentation of the memory
> +space into a set of sub-spaces called colors that are mapped to disjoint cache
> +partitions. Technically, the whole memory space is first divided into a number
> +of subsequent regions. Then each region is in turn divided into a number of
> +subsequent sub-colors. The generic i-th color is then obtained by all the
> +i-th sub-colors in each region.
> +
> +::
> +
> +                            Region j            Region j+1
> +                .....................   ............
> +                .                     . .
> +                .                       .
> +            _ _ _______________ _ _____________________ _ _
> +                |     |     |     |     |     |     |
> +                | c_0 | c_1 |     | c_n | c_0 | c_1 |
> +           _ _ _|_____|_____|_ _ _|_____|_____|_____|_ _ _
> +                    :                       :
> +                    :                       :...         ... .
> +                    :                            color 0
> +                    :...........................         ... .
> +                                                :
> +          . . ..................................:
> +
> +There are two pragmatic lesson to be learnt.
> +
> +1. If one wants to avoid cache interference between two domains, different
> +   colors needs to be used for their memory.
> +
> +2. Color assignment must privilege contiguity in the partitioning. E.g.,
> +   assigning colors (0,1) to domain I  and (2,3) to domain  J is better than
> +   assigning colors (0,2) to I and (1,3) to J.
> +
> +How to compute the number of colors
> +***********************************
> +
> +To compute the number of available colors for a specific platform, the size of
> +an LLC way and the page size used by Xen must be known.

Looking at the get_llc_way_size(), you are using CLIDR_EL1 which doesn't 
contains the system caches. They are invisible to the software but I 
guess could have an impact for cache coloring.

Can you clarify if by Last Cache Level, you mean the last visible cache?

> The first parameter can
> +be found in the processor manual or can be also computed dividing the total
> +cache size by the number of its ways. The second parameter is the minimum
> +amount of memory that can be mapped by the hypervisor, thus dividing the way
> +size by the page size, the number of total cache partitions is found. So for
> +example, an Arm Cortex-A53 with a 16-ways associative 1 MiB LLC, can isolate up
> +to 16 colors when pages are 4 KiB in size.
> +
> +Cache layout is probed automatically by Xen itself, but a possibility to
> +manually set the way size it's left for the user to overcome failing situations
> +or for debugging/testing purposes. See `Command line parameters`_ for more
> +information on that.
> +
> +Command line parameters
> +***********************
> +
> +More specific documentation is available at `docs/misc/xen-command-line.pandoc`.
> +
> ++----------------------+-------------------------------+
> +| **Parameter**        | **Description**               |
> ++----------------------+-------------------------------+
> +| ``llc-coloring``     | enable coloring at runtime    |
> ++----------------------+-------------------------------+
> +| ``llc-way-size``     | set the LLC way size          |
> ++----------------------+-------------------------------+
> +
> +Known issues and limitations
> +****************************
> +
> +"xen,static-mem" isn't supported when coloring is enabled
> +#########################################################
> +
> +In the domain configuration, "xen,static-mem" allows memory to be statically
> +allocated to the domain. This isn't possibile when LLC coloring is enabled,
> +because that memory can't be guaranteed to use only colors assigned to the
> +domain.
> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> index 8e65f8bd18..22d2d5b6cf 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -1713,6 +1713,34 @@ This option is intended for debugging purposes only.  Enable MSR_DEBUGCTL.LBR
>   in hypervisor context to be able to dump the Last Interrupt/Exception To/From
>   record with other registers.
>   
> +### llc-coloring (arm64)
> +> `= <boolean>`
> +
> +> Default: `false`
> +
> +Flag to enable or disable LLC coloring support at runtime. This options is
> +available only when `CONFIG_LLC_COLORING` is enabled. See the general
> +cache coloring documentation for more info.
> +
> +### llc-way-size (arm64)
> +> `= <size>`
> +
> +> Default: `Obtained from the hardware`
> +
> +Specify the way size of the Last Level Cache. This options is available only
> +when `CONFIG_LLC_COLORING` is enabled. It is an optional, expert-only parameter
> +and it is used to calculate the number of available LLC colors on the platform.
> +It can be obtained by dividing the total LLC size by the number of its
> +associative ways.
> +By default, the value is automatically computed by probing the hardware, but in
> +case of specific needs, it can be manually set. Those include failing probing
> +and debugging/testing purposes so that it's possibile to emulate platforms with

typo: s/possibile/possible/

> +different number of supported colors.
> +An important detail to highlight is that the current implementation of the
> +cache coloring technique requires the number of colors to be a power of 2, and
> +consequently, also the LLC way size must be so. A value that doesn't match this
> +requirement is aligned down to the previous power of 2.

Possibly a matter of taste here, but I would prefer if we simply throw 
an error. This makes more obvious that the size provided by the user was 
incorrect.

> +
>   ### lock-depth-size
>   > `= <integer>`
>   
> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> index 50e9bfae1a..55143f86a9 100644
> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -8,6 +8,7 @@ config ARM_64
>   	depends on !ARM_32
>   	select 64BIT
>   	select HAS_FAST_MULTIPLY
> +	select HAS_LLC_COLORING
>   
>   config ARM
>   	def_bool y
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 33c677672f..c9a1cd298d 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_IOREQ_SERVER) += ioreq.o
>   obj-y += irq.o
>   obj-y += kernel.init.o
>   obj-$(CONFIG_LIVEPATCH) += livepatch.o
> +obj-$(CONFIG_LLC_COLORING) += llc-coloring.o
>   obj-y += mem_access.o
>   obj-y += mm.o
>   obj-y += monitor.o
> diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
> index fb63ec6fd1..1142f7f74a 100644
> --- a/xen/arch/arm/dom0less-build.c
> +++ b/xen/arch/arm/dom0less-build.c
> @@ -5,6 +5,7 @@
>   #include <xen/grant_table.h>
>   #include <xen/iocap.h>
>   #include <xen/libfdt/libfdt.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/sched.h>
>   #include <xen/serial.h>
>   #include <xen/sizes.h>
> @@ -879,7 +880,12 @@ void __init create_domUs(void)
>               panic("No more domain IDs available\n");
>   
>           if ( dt_find_property(node, "xen,static-mem", NULL) )
> +        {
> +            if ( llc_coloring_enabled )
> +                panic("LLC coloring and static memory are incompatible\n");
> +
>               flags |= CDF_staticmem;
> +        }
>   
>           if ( dt_property_read_bool(node, "direct-map") )
>           {
> diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
> new file mode 100644
> index 0000000000..7885e9e3f5
> --- /dev/null
> +++ b/xen/arch/arm/include/asm/llc-coloring.h
> @@ -0,0 +1,28 @@
> +/* SPDX-License-Identifier: GPL-2.0 */

Please use GPL-2.0-only.

> +/*
> + * Last Level Cache (LLC) coloring support for ARM
> + *
> + * Copyright (C) 2022 Xilinx Inc.
> + *
> + * Authors:
> + *    Luca Miccio <lucmiccio@gmail.com>
> + *    Carlo Nonato <carlo.nonato@minervasys.tech>

Same question as before for the authorship.

> + */
> +#ifndef __ASM_ARM_COLORING_H__
> +#define __ASM_ARM_COLORING_H__
> +
> +#include <xen/init.h>
> +
> +bool __init llc_coloring_init(void);

The __init attribute is not necessary here. It is sufficient on the 
definition.

> +
> +#endif /* __ASM_ARM_COLORING_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h
> index 8e02410465..fd5e8eba98 100644
> --- a/xen/arch/arm/include/asm/processor.h
> +++ b/xen/arch/arm/include/asm/processor.h
> @@ -18,6 +18,22 @@
>   #define CTR_IDC_SHIFT       28
>   #define CTR_DIC_SHIFT       29
>   
> +/* CCSIDR Current Cache Size ID Register */
> +#define CCSIDR_LINESIZE_MASK            _AC(0x7, ULL)
> +#define CCSIDR_NUMSETS_SHIFT            13
> +#define CCSIDR_NUMSETS_MASK             _AC(0x3fff, ULL)
> +#define CCSIDR_NUMSETS_SHIFT_FEAT_CCIDX 32
> +#define CCSIDR_NUMSETS_MASK_FEAT_CCIDX  _AC(0xffffff, ULL)
> +
> +/* CCSELR Cache Size Selection Register */

Typo: s/CCSELR/CSSELR/

> +#define CCSELR_LEVEL_MASK  _AC(0x7, UL)
> +#define CCSELR_LEVEL_SHIFT 1
> +
> +/* CLIDR Cache Level ID Register */
> +#define CLIDR_CTYPEn_SHIFT(n) (3 * (n - 1))
> +#define CLIDR_CTYPEn_MASK     _AC(0x7, UL)
> +#define CLIDR_CTYPEn_LEVELS   7
> +
>   #define ICACHE_POLICY_VPIPT  0
>   #define ICACHE_POLICY_AIVIVT 1
>   #define ICACHE_POLICY_VIPT   2
> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> new file mode 100644
> index 0000000000..37d647f038
> --- /dev/null
> +++ b/xen/arch/arm/llc-coloring.c
> @@ -0,0 +1,161 @@
> +/* SPDX-License-Identifier: GPL-2.0 */

GPL-2.0-only

> +/*
> + * Last Level Cache (LLC) coloring support for ARM
> + *
> + * Copyright (C) 2022 Xilinx Inc.
> + *
> + * Authors:
> + *    Luca Miccio <lucmiccio@gmail.com>
> + *    Carlo Nonato <carlo.nonato@minervasys.tech>

Same question as before for the authorship.

> + */
> +#include <xen/errno.h>
> +#include <xen/keyhandler.h>
> +#include <xen/llc-coloring.h>
> +#include <xen/param.h>
> +#include <xen/types.h>
> +
> +#include <asm/processor.h>
> +#include <asm/sysregs.h>
> +
> +bool __ro_after_init llc_coloring_enabled;
> +boolean_param("llc-coloring", llc_coloring_enabled);
> +
> +/* Size of an LLC way */
> +static unsigned int __ro_after_init llc_way_size;
> +size_param("llc-way-size", llc_way_size);
> +/* Number of colors available in the LLC */
> +static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
> +
> +/* Return the LLC way size by probing the hardware */
> +static unsigned int __init get_llc_way_size(void)
> +{
> +    register_t ccsidr_el1;
> +    register_t clidr_el1 = READ_SYSREG(CLIDR_EL1);
> +    register_t csselr_el1 = READ_SYSREG(CSSELR_EL1);
> +    register_t id_aa64mmfr2_el1 = READ_SYSREG(ID_AA64MMFR2_EL1);
> +    uint32_t ccsidr_numsets_shift = CCSIDR_NUMSETS_SHIFT;
> +    uint32_t ccsidr_numsets_mask = CCSIDR_NUMSETS_MASK;
> +    unsigned int n, line_size, num_sets;
> +
> +    for ( n = CLIDR_CTYPEn_LEVELS;
> +          n != 0 && !((clidr_el1 >> CLIDR_CTYPEn_SHIFT(n)) & CLIDR_CTYPEn_MASK);
> +          n-- );
> +
> +    if ( n == 0 )
> +        return 0;


Shouldn't you check cache type of the level is either 0b011 (Separate 
instruction and cache) or 0b100 (Unified cache)?

> +
> +    WRITE_SYSREG(((n - 1) & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT,

NIT: masking (n - 1) looks a bit odd as it already indicates the cache 
level. It actually made me wonder if the other bits have a meaning. So I 
would drop the mask.

> +                 CSSELR_EL1);
> +    isb();
> +
> +    ccsidr_el1 = READ_SYSREG(CCSIDR_EL1);
> +
> +    /* Arm ARM: (Log2(Number of bytes in cache line)) - 4 */
> +    line_size = 1 << ((ccsidr_el1 & CCSIDR_LINESIZE_MASK) + 4);

Please use 1U even thought the shift should not be big enough to result 
to an overflow.

> +
> +    /* If FEAT_CCIDX is enabled, CCSIDR_EL1 has a different bit layout */
> +    if ( (id_aa64mmfr2_el1 >> ID_AA64MMFR2_CCIDX_SHIFT) & 0x7 )
> +    {
> +        ccsidr_numsets_shift = CCSIDR_NUMSETS_SHIFT_FEAT_CCIDX;
> +        ccsidr_numsets_mask = CCSIDR_NUMSETS_MASK_FEAT_CCIDX;
> +    }
> +    /* Arm ARM: (Number of sets in cache) - 1 */
> +    num_sets = ((ccsidr_el1 >> ccsidr_numsets_shift) & ccsidr_numsets_mask) + 1;
> +
> +    printk(XENLOG_INFO "LLC found: L%u (line size: %u bytes, sets num: %u)\n",
> +           n, line_size, num_sets);
> +
> +    /* Restore value in CSSELR_EL1 */
> +    WRITE_SYSREG(csselr_el1, CSSELR_EL1);
> +    isb();
> +
> +    return line_size * num_sets;
> +}
> +
> +static void print_colors(unsigned int *colors, unsigned int num_colors)

I think colors can be const. In general, I would prefer if 
variable/parameters that should not be modified are const.

> +{
> +    unsigned int i;
> +
> +    printk("{ ");
> +    for ( i = 0; i < num_colors; i++ ) {
> +        unsigned int start = colors[i], end = colors[i];
> +
> +        printk("%u", start);
> +
> +        for ( ;
> +              i < num_colors - 1 && colors[i] + 1 == colors[i + 1];
> +              i++, end++ );
> +
> +        if ( start != end )
> +            printk("-%u", end);
> +
> +        if ( i < num_colors - 1 )
> +            printk(", ");
> +    }
> +    printk(" }\n");
> +}
> +
> +static void dump_coloring_info(unsigned char key)
> +{
> +    printk("'%c' pressed -> dumping LLC coloring general info\n", key);
> +    printk("LLC way size: %u KiB\n", llc_way_size >> 10);
> +    printk("Number of LLC colors supported: %u\n", nr_colors);
> +}
> +
> +bool __init llc_coloring_init(void)
> +{
> +    if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
> +    {
> +        printk(XENLOG_ERR
> +               "Probed LLC way size is 0 and no custom value provided\n");
> +        return false;
> +    }
> +
> +    /*
> +     * The maximum number of colors must be a power of 2 in order to correctly
> +     * map them to bits of an address, so also the LLC way size must be so.
> +     */
> +    if ( llc_way_size & (llc_way_size - 1) )
> +    {
> +        printk(XENLOG_WARNING "LLC way size (%u) isn't a power of 2.\n",
> +               llc_way_size);
> +        llc_way_size = 1U << flsl(llc_way_size);
> +        printk(XENLOG_WARNING
> +               "Using %u instead. Performances will be suboptimal\n",
> +               llc_way_size);
> +    }
> +
> +    nr_colors = llc_way_size >> PAGE_SHIFT;
> +
> +    if ( nr_colors < 2 || nr_colors > CONFIG_NR_LLC_COLORS )

I didn't find any documentation explaining why we need at least two 
colors. I guess you want to make sure that there is a color for Xen and 
domain. But I wonder what could wrong with just one color (other than 
been pointless)?

> +    {
> +        printk(XENLOG_ERR "Number of LLC colors (%u) not in range [2, %u]\n",
> +               nr_colors, CONFIG_NR_LLC_COLORS);
> +        return false;
> +    }
> +
> +    register_keyhandler('K', dump_coloring_info, "dump LLC coloring info", 1);
> +
> +    return true;
> +}
> +
> +void domain_llc_coloring_free(struct domain *d)
> +{
> +    xfree(d->llc_colors);
> +}
> +
> +void domain_dump_llc_colors(struct domain *d)
> +{
> +    printk("Domain %pd has %u LLC colors: ", d, d->num_llc_colors);
> +    print_colors(d->llc_colors, d->num_llc_colors);
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 59dd9bb25a..4c16b566db 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -12,6 +12,7 @@
>   #include <xen/device_tree.h>
>   #include <xen/domain_page.h>
>   #include <xen/grant_table.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/types.h>
>   #include <xen/string.h>
>   #include <xen/serial.h>
> @@ -746,6 +747,12 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
>       printk("Command line: %s\n", cmdline);
>       cmdline_parse(cmdline);
>   
> +    if ( llc_coloring_enabled )

I would consider to move llc_coloring_enabled in llc_coloring_init(). 
But if you prefer to keep the check here, then I would at least request 
to merge the two ifs. I.e.

if ( llc_coloring_enabled && !llc_coloring_init() )

That said...

> +    {
> +        if ( !llc_coloring_init() )
> +            panic("Xen LLC coloring support: setup failed\n");
> +    }
> +
>       setup_mm();

... shouldn't the coloring happen in setup_mm()? After all, this is part 
of the memory subystem and I suspect this will not work with the 
upcoming MPU support.

>   
>       /* Parse the ACPI tables for possible boot-time configuration */

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support
  2024-01-02  9:51 ` [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support Carlo Nonato
@ 2024-01-04 19:54   ` Julien Grall
  2024-01-05 16:52     ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-04 19:54 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Carlo,

On 02/01/2024 09:51, Carlo Nonato wrote:
> This commit allows the user to set the cache coloring configuration for
> Dom0 via a command line parameter.
> Since cache coloring and static memory are incompatible, direct mapping
> Dom0 isn't possible when coloring is enabled.
> 
> A common configuration syntax for cache colors is also introduced.
> 
> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
> v5:
> - Carlo Nonato as the new author
> - moved dom0 colors parsing (parse_colors()) in this patch
> - added dom0_set_llc_colors() to set dom0 colors after creation
> - moved color allocation and checking in this patch
> - error handling when allocating color arrays
> - FIXME: copy pasted allocate_memory() cause it got moved
> v4:
> - dom0 colors are dynamically allocated as for any other domain
>    (colors are duplicated in dom0_colors and in the new array, but logic
>    is simpler)
> ---
>   docs/misc/arm/cache-coloring.rst        |  29 ++++++
>   docs/misc/xen-command-line.pandoc       |   9 ++
>   xen/arch/arm/domain_build.c             |  60 ++++++++++-
>   xen/arch/arm/include/asm/llc-coloring.h |   1 +
>   xen/arch/arm/llc-coloring.c             | 128 ++++++++++++++++++++++++
>   5 files changed, 224 insertions(+), 3 deletions(-)
> 
> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> index eabf8f5d1b..acf82c3df8 100644
> --- a/docs/misc/arm/cache-coloring.rst
> +++ b/docs/misc/arm/cache-coloring.rst
> @@ -84,6 +84,35 @@ More specific documentation is available at `docs/misc/xen-command-line.pandoc`.
>   +----------------------+-------------------------------+
>   | ``llc-way-size``     | set the LLC way size          |
>   +----------------------+-------------------------------+
> +| ``dom0-llc-colors``  | Dom0 color configuration      |
> ++----------------------+-------------------------------+
> +
> +Colors selection format
> +***********************
> +
> +Regardless of the memory pool that has to be colored (Xen, Dom0/DomUs),
> +the color selection can be expressed using the same syntax. In particular a
> +comma-separated list of colors or ranges of colors is used.
> +Ranges are hyphen-separated intervals (such as `0-4`) and are inclusive on both
> +sides.
> +
> +Note that:
> +
> +- no spaces are allowed between values.
> +- no overlapping ranges or duplicated colors are allowed.
> +- values must be written in ascending order.
> +
> +Examples:
> +
> ++-------------------+-----------------------------+
> +| **Configuration** | **Actual selection**        |
> ++-------------------+-----------------------------+
> +| 1-2,5-8           | [1, 2, 5, 6, 7, 8]          |
> ++-------------------+-----------------------------+
> +| 4-8,10,11,12      | [4, 5, 6, 7, 8, 10, 11, 12] |
> ++-------------------+-----------------------------+
> +| 0                 | [0]                         |
> ++-------------------+-----------------------------+
>   
>   Known issues and limitations
>   ****************************
> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> index 22d2d5b6cf..51f6adf035 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -963,6 +963,15 @@ Controls for the dom0 IOMMU setup.
>   
>   Specify a list of IO ports to be excluded from dom0 access.
>   
> +### dom0-llc-colors (arm64)
> +> `= List of [ <integer> | <integer>-<integer> ]`

Someone reading only xen-command-line.pandoc would not know how each 
item of the list is separated. Can this be clarified?

> +
> +> Default: `All available LLC colors`
> +
> +Specify dom0 LLC color configuration. This options is available only when
> +`CONFIG_LLC_COLORING` is enabled. If the parameter is not set, all available
> +colors are chosen and the user is warned on Xen serial console.

I would drop anything starting from  "and the user ...". This is really 
implementation define and the reader of the doc should not need to know 
that.

> +
>   ### dom0_max_vcpus
>   
>   Either:
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 6945b9755d..482c059bfa 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -2,6 +2,7 @@
>   #include <xen/init.h>
>   #include <xen/compile.h>
>   #include <xen/lib.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/mm.h>
>   #include <xen/param.h>
>   #include <xen/domain_page.h>
> @@ -414,7 +415,7 @@ static void __init allocate_memory_11(struct domain *d,
>       }
>   }
>   
> -#ifdef CONFIG_DOM0LESS_BOOT
> +#if defined(CONFIG_DOM0LESS_BOOT) || defined(CONFIG_LLC_COLORING)
>   bool __init allocate_bank_memory(struct domain *d, struct kernel_info *kinfo,
>                                    gfn_t sgfn, paddr_t tot_size)
>   {
> @@ -478,6 +479,49 @@ bool __init allocate_bank_memory(struct domain *d, struct kernel_info *kinfo,
>   }
>   #endif
>   
> +static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)

I saw the discussion on the cover letter. I agree that allocate_memory() 
should be moved back here (ideally in a separate patch) to avoid 
duplication.

> +{
> +    unsigned int i;
> +    paddr_t bank_size;
> +
> +    printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n",
> +           /* Don't want format this as PRIpaddr (16 digit hex) */
> +           (unsigned long)(kinfo->unassigned_mem >> 20), d);
> +
> +    kinfo->mem.nr_banks = 0;
> +    bank_size = MIN(GUEST_RAM0_SIZE, kinfo->unassigned_mem);
> +    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM0_BASE),
> +                               bank_size) )
> +        goto fail;
> +
> +    bank_size = MIN(GUEST_RAM1_SIZE, kinfo->unassigned_mem);
> +    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM1_BASE),
> +                               bank_size) )
> +        goto fail;
> +
> +    if ( kinfo->unassigned_mem )
> +        goto fail;
> +
> +    for( i = 0; i < kinfo->mem.nr_banks; i++ )
> +    {
> +        printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
> +               d,
> +               i,
> +               kinfo->mem.bank[i].start,
> +               kinfo->mem.bank[i].start + kinfo->mem.bank[i].size,
> +               /* Don't want format this as PRIpaddr (16 digit hex) */
> +               (unsigned long)(kinfo->mem.bank[i].size >> 20));
> +    }
> +
> +    return;
> +
> +fail:
> +    panic("Failed to allocate requested domain memory."
> +          /* Don't want format this as PRIpaddr (16 digit hex) */
> +          " %ldKB unallocated. Fix the VMs configurations.\n",
> +          (unsigned long)kinfo->unassigned_mem >> 10);
> +}
> +
>   /*
>    * When PCI passthrough is available we want to keep the
>    * "linux,pci-domain" in sync for every host bridge.
> @@ -2072,7 +2116,10 @@ static int __init construct_dom0(struct domain *d)
>       /* type must be set before allocate_memory */
>       d->arch.type = kinfo.type;
>   #endif
> -    allocate_memory_11(d, &kinfo);
> +    if ( is_domain_llc_colored(d) )

To me the choice here is more related to whether the domain direct 
mapped rather than the color itself. So I would rather prefer if we use 
is_domain_direct_mapped() even if this means the compiler will not be 
able to drop optimize the if when cache coloring is disabled.

> +        allocate_memory(d, &kinfo);
> +    else
> +        allocate_memory_11(d, &kinfo);
>       find_gnttab_region(d, &kinfo);
>   
>       rc = process_shm_chosen(d, &kinfo);
> @@ -2116,6 +2163,7 @@ void __init create_dom0(void)
>           .max_maptrack_frames = -1,
>           .grant_opts = XEN_DOMCTL_GRANT_version(opt_gnttab_max_version),
>       };
> +    unsigned int flags = CDF_privileged;
>       int rc;
>   
>       /* The vGIC for DOM0 is exactly emulating the hardware GIC */
> @@ -2143,10 +2191,16 @@ void __init create_dom0(void)
>               panic("SVE vector length error\n");
>       }
>   
> -    dom0 = domain_create(0, &dom0_cfg, CDF_privileged | CDF_directmap);
> +    if ( !llc_coloring_enabled )
> +        flags |= CDF_directmap;
> +
> +    dom0 = domain_create(0, &dom0_cfg, flags);
>       if ( IS_ERR(dom0) )
>           panic("Error creating domain 0 (rc = %ld)\n", PTR_ERR(dom0));
>   
> +    if ( llc_coloring_enabled && (rc = dom0_set_llc_colors(dom0)) )
> +        panic("Error initializing LLC coloring for domain 0 (rc = %d)", rc);
> +
>       if ( alloc_dom0_vcpu0(dom0) == NULL )
>           panic("Error creating domain 0 vcpu0\n");
>   
> diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
> index 7885e9e3f5..ee5551e3cc 100644
> --- a/xen/arch/arm/include/asm/llc-coloring.h
> +++ b/xen/arch/arm/include/asm/llc-coloring.h
> @@ -14,6 +14,7 @@
>   #include <xen/init.h>
>   
>   bool __init llc_coloring_init(void);
> +int dom0_set_llc_colors(struct domain *d);
>   
>   #endif /* __ASM_ARM_COLORING_H__ */
>   
> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> index 37d647f038..5ce58aba70 100644
> --- a/xen/arch/arm/llc-coloring.c
> +++ b/xen/arch/arm/llc-coloring.c
> @@ -26,6 +26,63 @@ size_param("llc-way-size", llc_way_size);
>   /* Number of colors available in the LLC */
>   static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
>   
> +static unsigned int __ro_after_init dom0_colors[CONFIG_NR_LLC_COLORS];
> +static unsigned int __ro_after_init dom0_num_colors;

Any reason to keep dom0_colors/dom0_num_colors after init?

> +
> +/*
> + * Parse the coloring configuration given in the buf string, following the
> + * syntax below.
> + *
> + * COLOR_CONFIGURATION ::= COLOR | RANGE,...,COLOR | RANGE
> + * RANGE               ::= COLOR-COLOR
> + *
> + * Example: "0,2-6,15-16" represents the set of colors: 0,2,3,4,5,6,15,16.
> + */
> +static int parse_color_config(const char *buf, unsigned int *colors,
> +                              unsigned int *num_colors)
> +{
> +    const char *s = buf;
> +
> +    if ( !colors || !num_colors )
> +        return -EINVAL;
> +
> +    *num_colors = 0;
> +
> +    while ( *s != '\0' )
> +    {
> +        if ( *s != ',' )
> +        {
> +            unsigned int color, start, end;
> +
> +            start = simple_strtoul(s, &s, 0);
> +
> +            if ( *s == '-' )    /* Range */
> +            {
> +                s++;
> +                end = simple_strtoul(s, &s, 0);
> +            }
> +            else                /* Single value */
> +                end = start;
> +
> +            if ( start > end || (end - start) > UINT_MAX - *num_colors ||

I am always confused with operatator predence and this is even more 
confusing because some similar operations have parentheses but not 
others. Can you ask you to use () around UINT_MAX - *num_colors.

> +                 *num_colors + (end - start) >= nr_colors )

Same here. This will make a lot more obvious what you intend to write.

> +                return -EINVAL;
> +            for ( color = start; color <= end; color++ )
> +                colors[(*num_colors)++] = color;
> +        }
> +        else
> +            s++;
> +    }
> +
> +    return *s ? -EINVAL : 0;
> +}
> +
> +static int __init parse_dom0_colors(const char *s)
> +{
> +    return parse_color_config(s, dom0_colors, &dom0_num_colors);
> +}
> +custom_param("dom0-llc-colors", parse_dom0_colors);
> +
>   /* Return the LLC way size by probing the hardware */
>   static unsigned int __init get_llc_way_size(void)
>   {
> @@ -102,6 +159,28 @@ static void dump_coloring_info(unsigned char key)
>       printk("Number of LLC colors supported: %u\n", nr_colors);
>   }
>   
> +static bool check_colors(unsigned int *colors, unsigned int num_colors)
> +{
> +    unsigned int i;
> +
> +    if ( num_colors > nr_colors )
> +    {
> +        printk(XENLOG_ERR "Number of LLC colors requested > %u\n", nr_colors);
> +        return false;
> +    }
> +
> +    for ( i = 0; i < num_colors; i++ )
> +    {
> +        if ( colors[i] >= nr_colors )
> +        {
> +            printk(XENLOG_ERR "LLC color %u >= %u\n", colors[i], nr_colors);
> +            return false;
> +        }
> +    }
> +
> +    return true;
> +}
> +
>   bool __init llc_coloring_init(void)
>   {
>       if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
> @@ -150,6 +229,55 @@ void domain_dump_llc_colors(struct domain *d)
>       print_colors(d->llc_colors, d->num_llc_colors);
>   }
>   
> +static int domain_alloc_colors(struct domain *d, unsigned int num_colors)
> +{
> +    d->num_llc_colors = num_colors;

Shouldn't this be set *only* after the array was allocated?

> +
> +    if ( !num_colors )
> +        return 0;
> +
> +    d->llc_colors = xmalloc_array(unsigned int, num_colors);

Can I ask to introduce malloc and free within the same patch? I know 
this could introduce unused temporarily unused code. But at least it is 
easier to confirm that the two paths are correct.

> +    if ( !d->llc_colors )
> +    {
> +        printk("Can't allocate LLC colors for domain %pd\n", d);

NIT: Above you use XENLOG_ERR for printk. But not here. To me they have 
the same severity. So can you explain the difference?

> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +static int domain_check_colors(struct domain *d)
> +{
> +    unsigned int i;
> +
> +    if ( !d->num_llc_colors )
> +    {
> +        printk(XENLOG_WARNING
> +               "LLC color config not found for %pd. Using default\n", d);
> +        if ( domain_alloc_colors(d, nr_colors) )
> +            return -ENOMEM;
> +        for ( i = 0; i < nr_colors; i++ )
> +            d->llc_colors[i] = i;
> +    }
> +    else if ( !check_colors(d->llc_colors, d->num_llc_colors) )
> +    {
> +        printk(XENLOG_ERR "Bad LLC color config for %pd\n", d);
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +int dom0_set_llc_colors(struct domain *d)
> +{
> +    if ( domain_alloc_colors(d, dom0_num_colors) )
> +        return -ENOMEM;
> +
> +    memcpy(d->llc_colors, dom0_colors, sizeof(unsigned int) * dom0_num_colors);
> +
> +    return domain_check_colors(d);
> +}
> +
>   /*
>    * Local variables:
>    * mode: C

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 01/13] xen/common: add cache coloring common code
  2024-01-02  9:51 ` [PATCH v5 01/13] xen/common: add cache coloring common code Carlo Nonato
  2024-01-04 18:39   ` Julien Grall
@ 2024-01-04 19:59   ` Julien Grall
  2024-01-04 21:43     ` Stefano Stabellini
  2024-01-08 16:53   ` Jan Beulich
  2 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-04 19:59 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Andrew Cooper, George Dunlap, Jan Beulich, Stefano Stabellini,
	Wei Liu, Marco Solieri

Hi,

On 02/01/2024 09:51, Carlo Nonato wrote:
> This commit adds the Last Level Cache (LLC) coloring common header, Kconfig
> options and functions. Since this is an arch specific feature, actual
> implementation is postponed to later patches and Kconfig options are placed
> under xen/arch.
> 
> LLC colors are a property of the domain, so the domain struct has to be
> extended.
> 
> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
> v5:
> - used - instead of _ for filenames
> - removed domain_create_llc_colored()
> - removed stub functions
> - coloring domain fields are now #ifdef protected
> v4:
> - Kconfig options moved to xen/arch
> - removed range for CONFIG_NR_LLC_COLORS
> - added "llc_coloring_enabled" global to later implement the boot-time
>    switch
> - added domain_create_llc_colored() to be able to pass colors
> - added is_domain_llc_colored() macro
> ---
>   xen/arch/Kconfig               | 16 ++++++++++++
>   xen/common/Kconfig             |  3 +++
>   xen/common/domain.c            |  4 +++
>   xen/common/keyhandler.c        |  4 +++
>   xen/include/xen/llc-coloring.h | 46 ++++++++++++++++++++++++++++++++++
>   xen/include/xen/sched.h        |  5 ++++
>   6 files changed, 78 insertions(+)
>   create mode 100644 xen/include/xen/llc-coloring.h
> 
> diff --git a/xen/arch/Kconfig b/xen/arch/Kconfig
> index 67ba38f32f..aad7e9da38 100644
> --- a/xen/arch/Kconfig
> +++ b/xen/arch/Kconfig
> @@ -31,3 +31,19 @@ config NR_NUMA_NODES
>   	  associated with multiple-nodes management. It is the upper bound of
>   	  the number of NUMA nodes that the scheduler, memory allocation and
>   	  other NUMA-aware components can handle.
> +
> +config LLC_COLORING
> +	bool "Last Level Cache (LLC) coloring" if EXPERT

While look at the rest of the series, I noticed that SUPPORT.md is not 
updated. Can this be done?

I think the feature should be in experimental for now. We can decide to 
switch to tech preview before Xen 4.19 is out and the support is completed.

Stefano, what do you think?

Cheers

-- 
Julien Grall


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

* Re: [PATCH v5 01/13] xen/common: add cache coloring common code
  2024-01-04 19:59   ` Julien Grall
@ 2024-01-04 21:43     ` Stefano Stabellini
  2024-01-05 16:32       ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Stefano Stabellini @ 2024-01-04 21:43 UTC (permalink / raw)
  To: Julien Grall
  Cc: Carlo Nonato, xen-devel, Andrew Cooper, George Dunlap,
	Jan Beulich, Stefano Stabellini, Wei Liu, Marco Solieri

On Thu, 4 Jan 2024, Julien Grall wrote:
> Hi,
> 
> On 02/01/2024 09:51, Carlo Nonato wrote:
> > This commit adds the Last Level Cache (LLC) coloring common header, Kconfig
> > options and functions. Since this is an arch specific feature, actual
> > implementation is postponed to later patches and Kconfig options are placed
> > under xen/arch.
> > 
> > LLC colors are a property of the domain, so the domain struct has to be
> > extended.
> > 
> > Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> > 
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > ---
> > v5:
> > - used - instead of _ for filenames
> > - removed domain_create_llc_colored()
> > - removed stub functions
> > - coloring domain fields are now #ifdef protected
> > v4:
> > - Kconfig options moved to xen/arch
> > - removed range for CONFIG_NR_LLC_COLORS
> > - added "llc_coloring_enabled" global to later implement the boot-time
> >    switch
> > - added domain_create_llc_colored() to be able to pass colors
> > - added is_domain_llc_colored() macro
> > ---
> >   xen/arch/Kconfig               | 16 ++++++++++++
> >   xen/common/Kconfig             |  3 +++
> >   xen/common/domain.c            |  4 +++
> >   xen/common/keyhandler.c        |  4 +++
> >   xen/include/xen/llc-coloring.h | 46 ++++++++++++++++++++++++++++++++++
> >   xen/include/xen/sched.h        |  5 ++++
> >   6 files changed, 78 insertions(+)
> >   create mode 100644 xen/include/xen/llc-coloring.h
> > 
> > diff --git a/xen/arch/Kconfig b/xen/arch/Kconfig
> > index 67ba38f32f..aad7e9da38 100644
> > --- a/xen/arch/Kconfig
> > +++ b/xen/arch/Kconfig
> > @@ -31,3 +31,19 @@ config NR_NUMA_NODES
> >   	  associated with multiple-nodes management. It is the upper bound of
> >   	  the number of NUMA nodes that the scheduler, memory allocation and
> >   	  other NUMA-aware components can handle.
> > +
> > +config LLC_COLORING
> > +	bool "Last Level Cache (LLC) coloring" if EXPERT
> 
> While look at the rest of the series, I noticed that SUPPORT.md is not
> updated. Can this be done?
> 
> I think the feature should be in experimental for now. We can decide to switch
> to tech preview before Xen 4.19 is out and the support is completed.
> 
> Stefano, what do you think?

That's reasonable


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

* Re: [PATCH v5 01/13] xen/common: add cache coloring common code
  2024-01-04 21:43     ` Stefano Stabellini
@ 2024-01-05 16:32       ` Carlo Nonato
  2024-01-25 18:26         ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-05 16:32 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Julien Grall, xen-devel, Andrew Cooper, George Dunlap,
	Jan Beulich, Wei Liu, Marco Solieri

Hi Stefano, Julien,

On Thu, Jan 4, 2024 at 10:43 PM Stefano Stabellini
<sstabellini@kernel.org> wrote:
>
> On Thu, 4 Jan 2024, Julien Grall wrote:
> > Hi,
> >
> > On 02/01/2024 09:51, Carlo Nonato wrote:
> > > This commit adds the Last Level Cache (LLC) coloring common header, Kconfig
> > > options and functions. Since this is an arch specific feature, actual
> > > implementation is postponed to later patches and Kconfig options are placed
> > > under xen/arch.
> > >
> > > LLC colors are a property of the domain, so the domain struct has to be
> > > extended.
> > >
> > > Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> > >
> > > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > > ---
> > > v5:
> > > - used - instead of _ for filenames
> > > - removed domain_create_llc_colored()
> > > - removed stub functions
> > > - coloring domain fields are now #ifdef protected
> > > v4:
> > > - Kconfig options moved to xen/arch
> > > - removed range for CONFIG_NR_LLC_COLORS
> > > - added "llc_coloring_enabled" global to later implement the boot-time
> > >    switch
> > > - added domain_create_llc_colored() to be able to pass colors
> > > - added is_domain_llc_colored() macro
> > > ---
> > >   xen/arch/Kconfig               | 16 ++++++++++++
> > >   xen/common/Kconfig             |  3 +++
> > >   xen/common/domain.c            |  4 +++
> > >   xen/common/keyhandler.c        |  4 +++
> > >   xen/include/xen/llc-coloring.h | 46 ++++++++++++++++++++++++++++++++++
> > >   xen/include/xen/sched.h        |  5 ++++
> > >   6 files changed, 78 insertions(+)
> > >   create mode 100644 xen/include/xen/llc-coloring.h
> > >
> > > diff --git a/xen/arch/Kconfig b/xen/arch/Kconfig
> > > index 67ba38f32f..aad7e9da38 100644
> > > --- a/xen/arch/Kconfig
> > > +++ b/xen/arch/Kconfig
> > > @@ -31,3 +31,19 @@ config NR_NUMA_NODES
> > >       associated with multiple-nodes management. It is the upper bound of
> > >       the number of NUMA nodes that the scheduler, memory allocation and
> > >       other NUMA-aware components can handle.
> > > +
> > > +config LLC_COLORING
> > > +   bool "Last Level Cache (LLC) coloring" if EXPERT
> >
> > While look at the rest of the series, I noticed that SUPPORT.md is not
> > updated. Can this be done?
> >
> > I think the feature should be in experimental for now. We can decide to switch
> > to tech preview before Xen 4.19 is out and the support is completed.
> >
> > Stefano, what do you think?
>
> That's reasonable

I would put it under "Resource management" features. Are you ok with it?

Thanks.


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

* Re: [PATCH v5 02/13] xen/arm: add cache coloring initialization
  2024-01-04 19:24   ` Julien Grall
@ 2024-01-05 16:34     ` Carlo Nonato
  2024-01-05 17:44       ` Julien Grall
  2024-01-11 10:17       ` Carlo Nonato
  0 siblings, 2 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-05 16:34 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien,

On Thu, Jan 4, 2024 at 8:25 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 02/01/2024 09:51, Carlo Nonato wrote:
> > This commit implements functions declared in the LLC coloring common header
> > for arm64 and adds documentation. It also adds two command line options: a
> > runtime switch for the cache coloring feature and the LLC way size
> > parameter.
> >
> > The feature init function consists of an auto probing of the cache layout
> > necessary to retrieve the LLC way size which is used to compute the number
> > of platform colors. It also adds a debug-key to dump general cache coloring
> > info.
> >
> > Static memory allocation and cache coloring are incompatible because static
> > memory can't be guaranteed to use only colors assigned to the domain.
> > Panic during domUs creation when both are enabled.
> >
> > Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> >
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > ---
> > v5:
> > - used - instead of _ for filenames
> > - moved static-mem check in this patch
> > - moved dom0 colors parsing in next patch
> > - moved color allocation and configuration in next patch
> > - moved check_colors() in next patch
> > - colors are now printed in short form
> > v4:
> > - added "llc-coloring" cmdline option for the boot-time switch
> > - dom0 colors are now checked during domain init as for any other domain
> > - fixed processor.h masks bit width
> > - check for overflow in parse_color_config()
> > - check_colors() now checks also that colors are sorted and unique
> > ---
> >   docs/misc/arm/cache-coloring.rst        |  97 ++++++++++++++
> >   docs/misc/xen-command-line.pandoc       |  28 +++++
> >   xen/arch/arm/Kconfig                    |   1 +
> >   xen/arch/arm/Makefile                   |   1 +
> >   xen/arch/arm/dom0less-build.c           |   6 +
> >   xen/arch/arm/include/asm/llc-coloring.h |  28 +++++
> >   xen/arch/arm/include/asm/processor.h    |  16 +++
> >   xen/arch/arm/llc-coloring.c             | 161 ++++++++++++++++++++++++
> >   xen/arch/arm/setup.c                    |   7 ++
> >   9 files changed, 345 insertions(+)
> >   create mode 100644 docs/misc/arm/cache-coloring.rst
> >   create mode 100644 xen/arch/arm/include/asm/llc-coloring.h
> >   create mode 100644 xen/arch/arm/llc-coloring.c
> >
> > diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> > new file mode 100644
> > index 0000000000..eabf8f5d1b
> > --- /dev/null
> > +++ b/docs/misc/arm/cache-coloring.rst
> > @@ -0,0 +1,97 @@
> > +Xen cache coloring user guide
> > +=============================
> > +
> > +The cache coloring support in Xen allows to reserve Last Level Cache (LLC)
> > +partitions for Dom0, DomUs and Xen itself. Currently only ARM64 is supported.
> > +
> > +To compile LLC coloring support set ``CONFIG_LLC_COLORING=y``.
> > +
> > +If needed, change the maximum number of colors with
> > +``CONFIG_NR_LLC_COLORS=<n>``.
> > +
> > +Compile Xen and the toolstack and then configure it via
> > +`Command line parameters`_.
> > +
> > +Background
> > +**********
> > +
> > +Cache hierarchy of a modern multi-core CPU typically has first levels dedicated
> > +to each core (hence using multiple cache units), while the last level is shared
> > +among all of them. Such configuration implies that memory operations on one
> > +core (e.g. running a DomU) are able to generate interference on another core
> > +(e.g .hosting another DomU). Cache coloring allows eliminating this
> > +mutual interference, and thus guaranteeing higher and more predictable
> > +performances for memory accesses.
> > +The key concept underlying cache coloring is a fragmentation of the memory
> > +space into a set of sub-spaces called colors that are mapped to disjoint cache
> > +partitions. Technically, the whole memory space is first divided into a number
> > +of subsequent regions. Then each region is in turn divided into a number of
> > +subsequent sub-colors. The generic i-th color is then obtained by all the
> > +i-th sub-colors in each region.
> > +
> > +::
> > +
> > +                            Region j            Region j+1
> > +                .....................   ............
> > +                .                     . .
> > +                .                       .
> > +            _ _ _______________ _ _____________________ _ _
> > +                |     |     |     |     |     |     |
> > +                | c_0 | c_1 |     | c_n | c_0 | c_1 |
> > +           _ _ _|_____|_____|_ _ _|_____|_____|_____|_ _ _
> > +                    :                       :
> > +                    :                       :...         ... .
> > +                    :                            color 0
> > +                    :...........................         ... .
> > +                                                :
> > +          . . ..................................:
> > +
> > +There are two pragmatic lesson to be learnt.
> > +
> > +1. If one wants to avoid cache interference between two domains, different
> > +   colors needs to be used for their memory.
> > +
> > +2. Color assignment must privilege contiguity in the partitioning. E.g.,
> > +   assigning colors (0,1) to domain I  and (2,3) to domain  J is better than
> > +   assigning colors (0,2) to I and (1,3) to J.
> > +
> > +How to compute the number of colors
> > +***********************************
> > +
> > +To compute the number of available colors for a specific platform, the size of
> > +an LLC way and the page size used by Xen must be known.
>
> Looking at the get_llc_way_size(), you are using CLIDR_EL1 which doesn't
> contains the system caches. They are invisible to the software but I
> guess could have an impact for cache coloring.
>
> Can you clarify if by Last Cache Level, you mean the last visible cache?

We are targeting only Cortex-A53, A57 and A72 where the "last level" is L2.
This "generic" approach for last level computation is inevitably problematic,
but I think that defining it as the last visible cache is the best thing we
can do. Remember also that this computation is overridable with the
appropriate command line parameter, so it's still possible to target
cache architectures that aren't discovered by this code (which are rare cases
since cache-coloring is already a small niche).

> > The first parameter can
> > +be found in the processor manual or can be also computed dividing the total
> > +cache size by the number of its ways. The second parameter is the minimum
> > +amount of memory that can be mapped by the hypervisor, thus dividing the way
> > +size by the page size, the number of total cache partitions is found. So for
> > +example, an Arm Cortex-A53 with a 16-ways associative 1 MiB LLC, can isolate up
> > +to 16 colors when pages are 4 KiB in size.
> > +
> > +Cache layout is probed automatically by Xen itself, but a possibility to
> > +manually set the way size it's left for the user to overcome failing situations
> > +or for debugging/testing purposes. See `Command line parameters`_ for more
> > +information on that.
> > +
> > +Command line parameters
> > +***********************
> > +
> > +More specific documentation is available at `docs/misc/xen-command-line.pandoc`.
> > +
> > ++----------------------+-------------------------------+
> > +| **Parameter**        | **Description**               |
> > ++----------------------+-------------------------------+
> > +| ``llc-coloring``     | enable coloring at runtime    |
> > ++----------------------+-------------------------------+
> > +| ``llc-way-size``     | set the LLC way size          |
> > ++----------------------+-------------------------------+
> > +
> > +Known issues and limitations
> > +****************************
> > +
> > +"xen,static-mem" isn't supported when coloring is enabled
> > +#########################################################
> > +
> > +In the domain configuration, "xen,static-mem" allows memory to be statically
> > +allocated to the domain. This isn't possibile when LLC coloring is enabled,
> > +because that memory can't be guaranteed to use only colors assigned to the
> > +domain.
> > diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> > index 8e65f8bd18..22d2d5b6cf 100644
> > --- a/docs/misc/xen-command-line.pandoc
> > +++ b/docs/misc/xen-command-line.pandoc
> > @@ -1713,6 +1713,34 @@ This option is intended for debugging purposes only.  Enable MSR_DEBUGCTL.LBR
> >   in hypervisor context to be able to dump the Last Interrupt/Exception To/From
> >   record with other registers.
> >
> > +### llc-coloring (arm64)
> > +> `= <boolean>`
> > +
> > +> Default: `false`
> > +
> > +Flag to enable or disable LLC coloring support at runtime. This options is
> > +available only when `CONFIG_LLC_COLORING` is enabled. See the general
> > +cache coloring documentation for more info.
> > +
> > +### llc-way-size (arm64)
> > +> `= <size>`
> > +
> > +> Default: `Obtained from the hardware`
> > +
> > +Specify the way size of the Last Level Cache. This options is available only
> > +when `CONFIG_LLC_COLORING` is enabled. It is an optional, expert-only parameter
> > +and it is used to calculate the number of available LLC colors on the platform.
> > +It can be obtained by dividing the total LLC size by the number of its
> > +associative ways.
> > +By default, the value is automatically computed by probing the hardware, but in
> > +case of specific needs, it can be manually set. Those include failing probing
> > +and debugging/testing purposes so that it's possibile to emulate platforms with
>
> typo: s/possibile/possible/
>
> > +different number of supported colors.
> > +An important detail to highlight is that the current implementation of the
> > +cache coloring technique requires the number of colors to be a power of 2, and
> > +consequently, also the LLC way size must be so. A value that doesn't match this
> > +requirement is aligned down to the previous power of 2.
>
> Possibly a matter of taste here, but I would prefer if we simply throw
> an error. This makes more obvious that the size provided by the user was
> incorrect.
>
> > +
> >   ### lock-depth-size
> >   > `= <integer>`
> >
> > diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> > index 50e9bfae1a..55143f86a9 100644
> > --- a/xen/arch/arm/Kconfig
> > +++ b/xen/arch/arm/Kconfig
> > @@ -8,6 +8,7 @@ config ARM_64
> >       depends on !ARM_32
> >       select 64BIT
> >       select HAS_FAST_MULTIPLY
> > +     select HAS_LLC_COLORING
> >
> >   config ARM
> >       def_bool y
> > diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> > index 33c677672f..c9a1cd298d 100644
> > --- a/xen/arch/arm/Makefile
> > +++ b/xen/arch/arm/Makefile
> > @@ -37,6 +37,7 @@ obj-$(CONFIG_IOREQ_SERVER) += ioreq.o
> >   obj-y += irq.o
> >   obj-y += kernel.init.o
> >   obj-$(CONFIG_LIVEPATCH) += livepatch.o
> > +obj-$(CONFIG_LLC_COLORING) += llc-coloring.o
> >   obj-y += mem_access.o
> >   obj-y += mm.o
> >   obj-y += monitor.o
> > diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
> > index fb63ec6fd1..1142f7f74a 100644
> > --- a/xen/arch/arm/dom0less-build.c
> > +++ b/xen/arch/arm/dom0less-build.c
> > @@ -5,6 +5,7 @@
> >   #include <xen/grant_table.h>
> >   #include <xen/iocap.h>
> >   #include <xen/libfdt/libfdt.h>
> > +#include <xen/llc-coloring.h>
> >   #include <xen/sched.h>
> >   #include <xen/serial.h>
> >   #include <xen/sizes.h>
> > @@ -879,7 +880,12 @@ void __init create_domUs(void)
> >               panic("No more domain IDs available\n");
> >
> >           if ( dt_find_property(node, "xen,static-mem", NULL) )
> > +        {
> > +            if ( llc_coloring_enabled )
> > +                panic("LLC coloring and static memory are incompatible\n");
> > +
> >               flags |= CDF_staticmem;
> > +        }
> >
> >           if ( dt_property_read_bool(node, "direct-map") )
> >           {
> > diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
> > new file mode 100644
> > index 0000000000..7885e9e3f5
> > --- /dev/null
> > +++ b/xen/arch/arm/include/asm/llc-coloring.h
> > @@ -0,0 +1,28 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
>
> Please use GPL-2.0-only.
>
> > +/*
> > + * Last Level Cache (LLC) coloring support for ARM
> > + *
> > + * Copyright (C) 2022 Xilinx Inc.
> > + *
> > + * Authors:
> > + *    Luca Miccio <lucmiccio@gmail.com>
> > + *    Carlo Nonato <carlo.nonato@minervasys.tech>
>
> Same question as before for the authorship.
>
> > + */
> > +#ifndef __ASM_ARM_COLORING_H__
> > +#define __ASM_ARM_COLORING_H__
> > +
> > +#include <xen/init.h>
> > +
> > +bool __init llc_coloring_init(void);
>
> The __init attribute is not necessary here. It is sufficient on the
> definition.
>
> > +
> > +#endif /* __ASM_ARM_COLORING_H__ */
> > +
> > +/*
> > + * Local variables:
> > + * mode: C
> > + * c-file-style: "BSD"
> > + * c-basic-offset: 4
> > + * tab-width: 4
> > + * indent-tabs-mode: nil
> > + * End:
> > + */
> > diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h
> > index 8e02410465..fd5e8eba98 100644
> > --- a/xen/arch/arm/include/asm/processor.h
> > +++ b/xen/arch/arm/include/asm/processor.h
> > @@ -18,6 +18,22 @@
> >   #define CTR_IDC_SHIFT       28
> >   #define CTR_DIC_SHIFT       29
> >
> > +/* CCSIDR Current Cache Size ID Register */
> > +#define CCSIDR_LINESIZE_MASK            _AC(0x7, ULL)
> > +#define CCSIDR_NUMSETS_SHIFT            13
> > +#define CCSIDR_NUMSETS_MASK             _AC(0x3fff, ULL)
> > +#define CCSIDR_NUMSETS_SHIFT_FEAT_CCIDX 32
> > +#define CCSIDR_NUMSETS_MASK_FEAT_CCIDX  _AC(0xffffff, ULL)
> > +
> > +/* CCSELR Cache Size Selection Register */
>
> Typo: s/CCSELR/CSSELR/
>
> > +#define CCSELR_LEVEL_MASK  _AC(0x7, UL)
> > +#define CCSELR_LEVEL_SHIFT 1
> > +
> > +/* CLIDR Cache Level ID Register */
> > +#define CLIDR_CTYPEn_SHIFT(n) (3 * (n - 1))
> > +#define CLIDR_CTYPEn_MASK     _AC(0x7, UL)
> > +#define CLIDR_CTYPEn_LEVELS   7
> > +
> >   #define ICACHE_POLICY_VPIPT  0
> >   #define ICACHE_POLICY_AIVIVT 1
> >   #define ICACHE_POLICY_VIPT   2
> > diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> > new file mode 100644
> > index 0000000000..37d647f038
> > --- /dev/null
> > +++ b/xen/arch/arm/llc-coloring.c
> > @@ -0,0 +1,161 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
>
> GPL-2.0-only
>
> > +/*
> > + * Last Level Cache (LLC) coloring support for ARM
> > + *
> > + * Copyright (C) 2022 Xilinx Inc.
> > + *
> > + * Authors:
> > + *    Luca Miccio <lucmiccio@gmail.com>
> > + *    Carlo Nonato <carlo.nonato@minervasys.tech>
>
> Same question as before for the authorship.
>
> > + */
> > +#include <xen/errno.h>
> > +#include <xen/keyhandler.h>
> > +#include <xen/llc-coloring.h>
> > +#include <xen/param.h>
> > +#include <xen/types.h>
> > +
> > +#include <asm/processor.h>
> > +#include <asm/sysregs.h>
> > +
> > +bool __ro_after_init llc_coloring_enabled;
> > +boolean_param("llc-coloring", llc_coloring_enabled);
> > +
> > +/* Size of an LLC way */
> > +static unsigned int __ro_after_init llc_way_size;
> > +size_param("llc-way-size", llc_way_size);
> > +/* Number of colors available in the LLC */
> > +static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
> > +
> > +/* Return the LLC way size by probing the hardware */
> > +static unsigned int __init get_llc_way_size(void)
> > +{
> > +    register_t ccsidr_el1;
> > +    register_t clidr_el1 = READ_SYSREG(CLIDR_EL1);
> > +    register_t csselr_el1 = READ_SYSREG(CSSELR_EL1);
> > +    register_t id_aa64mmfr2_el1 = READ_SYSREG(ID_AA64MMFR2_EL1);
> > +    uint32_t ccsidr_numsets_shift = CCSIDR_NUMSETS_SHIFT;
> > +    uint32_t ccsidr_numsets_mask = CCSIDR_NUMSETS_MASK;
> > +    unsigned int n, line_size, num_sets;
> > +
> > +    for ( n = CLIDR_CTYPEn_LEVELS;
> > +          n != 0 && !((clidr_el1 >> CLIDR_CTYPEn_SHIFT(n)) & CLIDR_CTYPEn_MASK);
> > +          n-- );
> > +
> > +    if ( n == 0 )
> > +        return 0;
>
>
> Shouldn't you check cache type of the level is either 0b011 (Separate
> instruction and cache) or 0b100 (Unified cache)?

Yes this is better.

> > +
> > +    WRITE_SYSREG(((n - 1) & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT,
>
> NIT: masking (n - 1) looks a bit odd as it already indicates the cache
> level. It actually made me wonder if the other bits have a meaning. So I
> would drop the mask.
>
> > +                 CSSELR_EL1);
> > +    isb();
> > +
> > +    ccsidr_el1 = READ_SYSREG(CCSIDR_EL1);
> > +
> > +    /* Arm ARM: (Log2(Number of bytes in cache line)) - 4 */
> > +    line_size = 1 << ((ccsidr_el1 & CCSIDR_LINESIZE_MASK) + 4);
>
> Please use 1U even thought the shift should not be big enough to result
> to an overflow.
>
> > +
> > +    /* If FEAT_CCIDX is enabled, CCSIDR_EL1 has a different bit layout */
> > +    if ( (id_aa64mmfr2_el1 >> ID_AA64MMFR2_CCIDX_SHIFT) & 0x7 )
> > +    {
> > +        ccsidr_numsets_shift = CCSIDR_NUMSETS_SHIFT_FEAT_CCIDX;
> > +        ccsidr_numsets_mask = CCSIDR_NUMSETS_MASK_FEAT_CCIDX;
> > +    }
> > +    /* Arm ARM: (Number of sets in cache) - 1 */
> > +    num_sets = ((ccsidr_el1 >> ccsidr_numsets_shift) & ccsidr_numsets_mask) + 1;
> > +
> > +    printk(XENLOG_INFO "LLC found: L%u (line size: %u bytes, sets num: %u)\n",
> > +           n, line_size, num_sets);
> > +
> > +    /* Restore value in CSSELR_EL1 */
> > +    WRITE_SYSREG(csselr_el1, CSSELR_EL1);
> > +    isb();
> > +
> > +    return line_size * num_sets;
> > +}
> > +
> > +static void print_colors(unsigned int *colors, unsigned int num_colors)
>
> I think colors can be const. In general, I would prefer if
> variable/parameters that should not be modified are const.
>
> > +{
> > +    unsigned int i;
> > +
> > +    printk("{ ");
> > +    for ( i = 0; i < num_colors; i++ ) {
> > +        unsigned int start = colors[i], end = colors[i];
> > +
> > +        printk("%u", start);
> > +
> > +        for ( ;
> > +              i < num_colors - 1 && colors[i] + 1 == colors[i + 1];
> > +              i++, end++ );
> > +
> > +        if ( start != end )
> > +            printk("-%u", end);
> > +
> > +        if ( i < num_colors - 1 )
> > +            printk(", ");
> > +    }
> > +    printk(" }\n");
> > +}
> > +
> > +static void dump_coloring_info(unsigned char key)
> > +{
> > +    printk("'%c' pressed -> dumping LLC coloring general info\n", key);
> > +    printk("LLC way size: %u KiB\n", llc_way_size >> 10);
> > +    printk("Number of LLC colors supported: %u\n", nr_colors);
> > +}
> > +
> > +bool __init llc_coloring_init(void)
> > +{
> > +    if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
> > +    {
> > +        printk(XENLOG_ERR
> > +               "Probed LLC way size is 0 and no custom value provided\n");
> > +        return false;
> > +    }
> > +
> > +    /*
> > +     * The maximum number of colors must be a power of 2 in order to correctly
> > +     * map them to bits of an address, so also the LLC way size must be so.
> > +     */
> > +    if ( llc_way_size & (llc_way_size - 1) )
> > +    {
> > +        printk(XENLOG_WARNING "LLC way size (%u) isn't a power of 2.\n",
> > +               llc_way_size);
> > +        llc_way_size = 1U << flsl(llc_way_size);
> > +        printk(XENLOG_WARNING
> > +               "Using %u instead. Performances will be suboptimal\n",
> > +               llc_way_size);
> > +    }
> > +
> > +    nr_colors = llc_way_size >> PAGE_SHIFT;
> > +
> > +    if ( nr_colors < 2 || nr_colors > CONFIG_NR_LLC_COLORS )
>
> I didn't find any documentation explaining why we need at least two
> colors. I guess you want to make sure that there is a color for Xen and
> domain. But I wonder what could wrong with just one color (other than
> been pointless)?

Yes, it would just be pointless. I'll change it to 1.

> > +    {
> > +        printk(XENLOG_ERR "Number of LLC colors (%u) not in range [2, %u]\n",
> > +               nr_colors, CONFIG_NR_LLC_COLORS);
> > +        return false;
> > +    }
> > +
> > +    register_keyhandler('K', dump_coloring_info, "dump LLC coloring info", 1);
> > +
> > +    return true;
> > +}
> > +
> > +void domain_llc_coloring_free(struct domain *d)
> > +{
> > +    xfree(d->llc_colors);
> > +}
> > +
> > +void domain_dump_llc_colors(struct domain *d)
> > +{
> > +    printk("Domain %pd has %u LLC colors: ", d, d->num_llc_colors);
> > +    print_colors(d->llc_colors, d->num_llc_colors);
> > +}
> > +
> > +/*
> > + * Local variables:
> > + * mode: C
> > + * c-file-style: "BSD"
> > + * c-basic-offset: 4
> > + * tab-width: 4
> > + * indent-tabs-mode: nil
> > + * End:
> > + */
> > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> > index 59dd9bb25a..4c16b566db 100644
> > --- a/xen/arch/arm/setup.c
> > +++ b/xen/arch/arm/setup.c
> > @@ -12,6 +12,7 @@
> >   #include <xen/device_tree.h>
> >   #include <xen/domain_page.h>
> >   #include <xen/grant_table.h>
> > +#include <xen/llc-coloring.h>
> >   #include <xen/types.h>
> >   #include <xen/string.h>
> >   #include <xen/serial.h>
> > @@ -746,6 +747,12 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
> >       printk("Command line: %s\n", cmdline);
> >       cmdline_parse(cmdline);
> >
> > +    if ( llc_coloring_enabled )
>
> I would consider to move llc_coloring_enabled in llc_coloring_init().
> But if you prefer to keep the check here, then I would at least request
> to merge the two ifs. I.e.
>
> if ( llc_coloring_enabled && !llc_coloring_init() )
>
> That said...
>
> > +    {
> > +        if ( !llc_coloring_init() )
> > +            panic("Xen LLC coloring support: setup failed\n");
> > +    }
> > +
> >       setup_mm();
>
> ... shouldn't the coloring happen in setup_mm()? After all, this is part
> of the memory subystem and I suspect this will not work with the
> upcoming MPU support.

Coloring initialization must happen before setup_pagetables() otherwise it
isn't possible to color the hypervisor code. In later patches
setup_pagetables() is moved after coloring init so I don't think it would
make sense to have it in setup_mm().

> >
> >       /* Parse the ACPI tables for possible boot-time configuration */
>
> Cheers,
>
> --
> Julien Grall

Thanks.


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

* Re: [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support
  2024-01-04 19:54   ` Julien Grall
@ 2024-01-05 16:52     ` Carlo Nonato
  2024-01-05 17:50       ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-05 16:52 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien,

On Thu, Jan 4, 2024 at 8:54 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 02/01/2024 09:51, Carlo Nonato wrote:
> > This commit allows the user to set the cache coloring configuration for
> > Dom0 via a command line parameter.
> > Since cache coloring and static memory are incompatible, direct mapping
> > Dom0 isn't possible when coloring is enabled.
> >
> > A common configuration syntax for cache colors is also introduced.
> >
> > Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> >
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > ---
> > v5:
> > - Carlo Nonato as the new author
> > - moved dom0 colors parsing (parse_colors()) in this patch
> > - added dom0_set_llc_colors() to set dom0 colors after creation
> > - moved color allocation and checking in this patch
> > - error handling when allocating color arrays
> > - FIXME: copy pasted allocate_memory() cause it got moved
> > v4:
> > - dom0 colors are dynamically allocated as for any other domain
> >    (colors are duplicated in dom0_colors and in the new array, but logic
> >    is simpler)
> > ---
> >   docs/misc/arm/cache-coloring.rst        |  29 ++++++
> >   docs/misc/xen-command-line.pandoc       |   9 ++
> >   xen/arch/arm/domain_build.c             |  60 ++++++++++-
> >   xen/arch/arm/include/asm/llc-coloring.h |   1 +
> >   xen/arch/arm/llc-coloring.c             | 128 ++++++++++++++++++++++++
> >   5 files changed, 224 insertions(+), 3 deletions(-)
> >
> > diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> > index eabf8f5d1b..acf82c3df8 100644
> > --- a/docs/misc/arm/cache-coloring.rst
> > +++ b/docs/misc/arm/cache-coloring.rst
> > @@ -84,6 +84,35 @@ More specific documentation is available at `docs/misc/xen-command-line.pandoc`.
> >   +----------------------+-------------------------------+
> >   | ``llc-way-size``     | set the LLC way size          |
> >   +----------------------+-------------------------------+
> > +| ``dom0-llc-colors``  | Dom0 color configuration      |
> > ++----------------------+-------------------------------+
> > +
> > +Colors selection format
> > +***********************
> > +
> > +Regardless of the memory pool that has to be colored (Xen, Dom0/DomUs),
> > +the color selection can be expressed using the same syntax. In particular a
> > +comma-separated list of colors or ranges of colors is used.
> > +Ranges are hyphen-separated intervals (such as `0-4`) and are inclusive on both
> > +sides.
> > +
> > +Note that:
> > +
> > +- no spaces are allowed between values.
> > +- no overlapping ranges or duplicated colors are allowed.
> > +- values must be written in ascending order.
> > +
> > +Examples:
> > +
> > ++-------------------+-----------------------------+
> > +| **Configuration** | **Actual selection**        |
> > ++-------------------+-----------------------------+
> > +| 1-2,5-8           | [1, 2, 5, 6, 7, 8]          |
> > ++-------------------+-----------------------------+
> > +| 4-8,10,11,12      | [4, 5, 6, 7, 8, 10, 11, 12] |
> > ++-------------------+-----------------------------+
> > +| 0                 | [0]                         |
> > ++-------------------+-----------------------------+
> >
> >   Known issues and limitations
> >   ****************************
> > diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> > index 22d2d5b6cf..51f6adf035 100644
> > --- a/docs/misc/xen-command-line.pandoc
> > +++ b/docs/misc/xen-command-line.pandoc
> > @@ -963,6 +963,15 @@ Controls for the dom0 IOMMU setup.
> >
> >   Specify a list of IO ports to be excluded from dom0 access.
> >
> > +### dom0-llc-colors (arm64)
> > +> `= List of [ <integer> | <integer>-<integer> ]`
>
> Someone reading only xen-command-line.pandoc would not know how each
> item of the list is separated. Can this be clarified?

Isn't it already known that the list is comma separated? It's written at the
beginning of this file for the "List" type.
I can also point to cache-coloring documentation if needed.

> > +
> > +> Default: `All available LLC colors`
> > +
> > +Specify dom0 LLC color configuration. This options is available only when
> > +`CONFIG_LLC_COLORING` is enabled. If the parameter is not set, all available
> > +colors are chosen and the user is warned on Xen serial console.
>
> I would drop anything starting from  "and the user ...". This is really
> implementation define and the reader of the doc should not need to know
> that.
>
> > +
> >   ### dom0_max_vcpus
> >
> >   Either:
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 6945b9755d..482c059bfa 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -2,6 +2,7 @@
> >   #include <xen/init.h>
> >   #include <xen/compile.h>
> >   #include <xen/lib.h>
> > +#include <xen/llc-coloring.h>
> >   #include <xen/mm.h>
> >   #include <xen/param.h>
> >   #include <xen/domain_page.h>
> > @@ -414,7 +415,7 @@ static void __init allocate_memory_11(struct domain *d,
> >       }
> >   }
> >
> > -#ifdef CONFIG_DOM0LESS_BOOT
> > +#if defined(CONFIG_DOM0LESS_BOOT) || defined(CONFIG_LLC_COLORING)
> >   bool __init allocate_bank_memory(struct domain *d, struct kernel_info *kinfo,
> >                                    gfn_t sgfn, paddr_t tot_size)
> >   {
> > @@ -478,6 +479,49 @@ bool __init allocate_bank_memory(struct domain *d, struct kernel_info *kinfo,
> >   }
> >   #endif
> >
> > +static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
>
> I saw the discussion on the cover letter. I agree that allocate_memory()
> should be moved back here (ideally in a separate patch) to avoid
> duplication.
>
> > +{
> > +    unsigned int i;
> > +    paddr_t bank_size;
> > +
> > +    printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n",
> > +           /* Don't want format this as PRIpaddr (16 digit hex) */
> > +           (unsigned long)(kinfo->unassigned_mem >> 20), d);
> > +
> > +    kinfo->mem.nr_banks = 0;
> > +    bank_size = MIN(GUEST_RAM0_SIZE, kinfo->unassigned_mem);
> > +    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM0_BASE),
> > +                               bank_size) )
> > +        goto fail;
> > +
> > +    bank_size = MIN(GUEST_RAM1_SIZE, kinfo->unassigned_mem);
> > +    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM1_BASE),
> > +                               bank_size) )
> > +        goto fail;
> > +
> > +    if ( kinfo->unassigned_mem )
> > +        goto fail;
> > +
> > +    for( i = 0; i < kinfo->mem.nr_banks; i++ )
> > +    {
> > +        printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
> > +               d,
> > +               i,
> > +               kinfo->mem.bank[i].start,
> > +               kinfo->mem.bank[i].start + kinfo->mem.bank[i].size,
> > +               /* Don't want format this as PRIpaddr (16 digit hex) */
> > +               (unsigned long)(kinfo->mem.bank[i].size >> 20));
> > +    }
> > +
> > +    return;
> > +
> > +fail:
> > +    panic("Failed to allocate requested domain memory."
> > +          /* Don't want format this as PRIpaddr (16 digit hex) */
> > +          " %ldKB unallocated. Fix the VMs configurations.\n",
> > +          (unsigned long)kinfo->unassigned_mem >> 10);
> > +}
> > +
> >   /*
> >    * When PCI passthrough is available we want to keep the
> >    * "linux,pci-domain" in sync for every host bridge.
> > @@ -2072,7 +2116,10 @@ static int __init construct_dom0(struct domain *d)
> >       /* type must be set before allocate_memory */
> >       d->arch.type = kinfo.type;
> >   #endif
> > -    allocate_memory_11(d, &kinfo);
> > +    if ( is_domain_llc_colored(d) )
>
> To me the choice here is more related to whether the domain direct
> mapped rather than the color itself. So I would rather prefer if we use
> is_domain_direct_mapped() even if this means the compiler will not be
> able to drop optimize the if when cache coloring is disabled.
>
> > +        allocate_memory(d, &kinfo);
> > +    else
> > +        allocate_memory_11(d, &kinfo);
> >       find_gnttab_region(d, &kinfo);
> >
> >       rc = process_shm_chosen(d, &kinfo);
> > @@ -2116,6 +2163,7 @@ void __init create_dom0(void)
> >           .max_maptrack_frames = -1,
> >           .grant_opts = XEN_DOMCTL_GRANT_version(opt_gnttab_max_version),
> >       };
> > +    unsigned int flags = CDF_privileged;
> >       int rc;
> >
> >       /* The vGIC for DOM0 is exactly emulating the hardware GIC */
> > @@ -2143,10 +2191,16 @@ void __init create_dom0(void)
> >               panic("SVE vector length error\n");
> >       }
> >
> > -    dom0 = domain_create(0, &dom0_cfg, CDF_privileged | CDF_directmap);
> > +    if ( !llc_coloring_enabled )
> > +        flags |= CDF_directmap;
> > +
> > +    dom0 = domain_create(0, &dom0_cfg, flags);
> >       if ( IS_ERR(dom0) )
> >           panic("Error creating domain 0 (rc = %ld)\n", PTR_ERR(dom0));
> >
> > +    if ( llc_coloring_enabled && (rc = dom0_set_llc_colors(dom0)) )
> > +        panic("Error initializing LLC coloring for domain 0 (rc = %d)", rc);
> > +
> >       if ( alloc_dom0_vcpu0(dom0) == NULL )
> >           panic("Error creating domain 0 vcpu0\n");
> >
> > diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
> > index 7885e9e3f5..ee5551e3cc 100644
> > --- a/xen/arch/arm/include/asm/llc-coloring.h
> > +++ b/xen/arch/arm/include/asm/llc-coloring.h
> > @@ -14,6 +14,7 @@
> >   #include <xen/init.h>
> >
> >   bool __init llc_coloring_init(void);
> > +int dom0_set_llc_colors(struct domain *d);
> >
> >   #endif /* __ASM_ARM_COLORING_H__ */
> >
> > diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> > index 37d647f038..5ce58aba70 100644
> > --- a/xen/arch/arm/llc-coloring.c
> > +++ b/xen/arch/arm/llc-coloring.c
> > @@ -26,6 +26,63 @@ size_param("llc-way-size", llc_way_size);
> >   /* Number of colors available in the LLC */
> >   static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
> >
> > +static unsigned int __ro_after_init dom0_colors[CONFIG_NR_LLC_COLORS];
> > +static unsigned int __ro_after_init dom0_num_colors;
>
> Any reason to keep dom0_colors/dom0_num_colors after init?

Nope.

> > +
> > +/*
> > + * Parse the coloring configuration given in the buf string, following the
> > + * syntax below.
> > + *
> > + * COLOR_CONFIGURATION ::= COLOR | RANGE,...,COLOR | RANGE
> > + * RANGE               ::= COLOR-COLOR
> > + *
> > + * Example: "0,2-6,15-16" represents the set of colors: 0,2,3,4,5,6,15,16.
> > + */
> > +static int parse_color_config(const char *buf, unsigned int *colors,
> > +                              unsigned int *num_colors)
> > +{
> > +    const char *s = buf;
> > +
> > +    if ( !colors || !num_colors )
> > +        return -EINVAL;
> > +
> > +    *num_colors = 0;
> > +
> > +    while ( *s != '\0' )
> > +    {
> > +        if ( *s != ',' )
> > +        {
> > +            unsigned int color, start, end;
> > +
> > +            start = simple_strtoul(s, &s, 0);
> > +
> > +            if ( *s == '-' )    /* Range */
> > +            {
> > +                s++;
> > +                end = simple_strtoul(s, &s, 0);
> > +            }
> > +            else                /* Single value */
> > +                end = start;
> > +
> > +            if ( start > end || (end - start) > UINT_MAX - *num_colors ||
>
> I am always confused with operatator predence and this is even more
> confusing because some similar operations have parentheses but not
> others. Can you ask you to use () around UINT_MAX - *num_colors.
>
> > +                 *num_colors + (end - start) >= nr_colors )
>
> Same here. This will make a lot more obvious what you intend to write.
>
> > +                return -EINVAL;
> > +            for ( color = start; color <= end; color++ )
> > +                colors[(*num_colors)++] = color;
> > +        }
> > +        else
> > +            s++;
> > +    }
> > +
> > +    return *s ? -EINVAL : 0;
> > +}
> > +
> > +static int __init parse_dom0_colors(const char *s)
> > +{
> > +    return parse_color_config(s, dom0_colors, &dom0_num_colors);
> > +}
> > +custom_param("dom0-llc-colors", parse_dom0_colors);
> > +
> >   /* Return the LLC way size by probing the hardware */
> >   static unsigned int __init get_llc_way_size(void)
> >   {
> > @@ -102,6 +159,28 @@ static void dump_coloring_info(unsigned char key)
> >       printk("Number of LLC colors supported: %u\n", nr_colors);
> >   }
> >
> > +static bool check_colors(unsigned int *colors, unsigned int num_colors)
> > +{
> > +    unsigned int i;
> > +
> > +    if ( num_colors > nr_colors )
> > +    {
> > +        printk(XENLOG_ERR "Number of LLC colors requested > %u\n", nr_colors);
> > +        return false;
> > +    }
> > +
> > +    for ( i = 0; i < num_colors; i++ )
> > +    {
> > +        if ( colors[i] >= nr_colors )
> > +        {
> > +            printk(XENLOG_ERR "LLC color %u >= %u\n", colors[i], nr_colors);
> > +            return false;
> > +        }
> > +    }
> > +
> > +    return true;
> > +}
> > +
> >   bool __init llc_coloring_init(void)
> >   {
> >       if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
> > @@ -150,6 +229,55 @@ void domain_dump_llc_colors(struct domain *d)
> >       print_colors(d->llc_colors, d->num_llc_colors);
> >   }
> >
> > +static int domain_alloc_colors(struct domain *d, unsigned int num_colors)
> > +{
> > +    d->num_llc_colors = num_colors;
>
> Shouldn't this be set *only* after the array was allocated?

Yes, it works also like I did, but it's cleaner like you said. I can also drop
the next if.

> > +
> > +    if ( !num_colors )
> > +        return 0;
> > +
> > +    d->llc_colors = xmalloc_array(unsigned int, num_colors);
>
> Can I ask to introduce malloc and free within the same patch? I know
> this could introduce unused temporarily unused code. But at least it is
> easier to confirm that the two paths are correct.

Ok.

> > +    if ( !d->llc_colors )
> > +    {
> > +        printk("Can't allocate LLC colors for domain %pd\n", d);
>
> NIT: Above you use XENLOG_ERR for printk. But not here. To me they have
> the same severity. So can you explain the difference?

Just forgot it.

> > +        return -1;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int domain_check_colors(struct domain *d)
> > +{
> > +    unsigned int i;
> > +
> > +    if ( !d->num_llc_colors )
> > +    {
> > +        printk(XENLOG_WARNING
> > +               "LLC color config not found for %pd. Using default\n", d);
> > +        if ( domain_alloc_colors(d, nr_colors) )
> > +            return -ENOMEM;
> > +        for ( i = 0; i < nr_colors; i++ )
> > +            d->llc_colors[i] = i;
> > +    }
> > +    else if ( !check_colors(d->llc_colors, d->num_llc_colors) )
> > +    {
> > +        printk(XENLOG_ERR "Bad LLC color config for %pd\n", d);
> > +        return -EINVAL;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +int dom0_set_llc_colors(struct domain *d)
> > +{
> > +    if ( domain_alloc_colors(d, dom0_num_colors) )
> > +        return -ENOMEM;
> > +
> > +    memcpy(d->llc_colors, dom0_colors, sizeof(unsigned int) * dom0_num_colors);
> > +
> > +    return domain_check_colors(d);
> > +}
> > +
> >   /*
> >    * Local variables:
> >    * mode: C
>
> Cheers,
>
> --
> Julien Grall

Thanks.


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-02  9:51 ` [PATCH v5 04/13] xen: extend domctl interface for cache coloring Carlo Nonato
@ 2024-01-05 17:26   ` Julien Grall
  2024-01-08 10:27     ` Carlo Nonato
  2024-01-08  8:43   ` Jan Beulich
  1 sibling, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-05 17:26 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Carlo,

On 02/01/2024 09:51, Carlo Nonato wrote:
> This commit updates the domctl interface to allow the user to set cache
> coloring configurations from the toolstack.
> It also implements the functionality for arm64.
> 
> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
> v5:
> - added a new hypercall to set colors
> - uint for the guest handle
> v4:
> - updated XEN_DOMCTL_INTERFACE_VERSION
> ---
>   xen/arch/arm/llc-coloring.c    | 17 +++++++++++++++++
>   xen/common/domctl.c            | 11 +++++++++++
>   xen/include/public/domctl.h    | 10 +++++++++-
>   xen/include/xen/llc-coloring.h |  3 +++
>   4 files changed, 40 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> index 5ce58aba70..a08614ec36 100644
> --- a/xen/arch/arm/llc-coloring.c
> +++ b/xen/arch/arm/llc-coloring.c
> @@ -9,6 +9,7 @@
>    *    Carlo Nonato <carlo.nonato@minervasys.tech>
>    */
>   #include <xen/errno.h>
> +#include <xen/guest_access.h>
>   #include <xen/keyhandler.h>
>   #include <xen/llc-coloring.h>
>   #include <xen/param.h>
> @@ -278,6 +279,22 @@ int dom0_set_llc_colors(struct domain *d)
>       return domain_check_colors(d);
>   }
>   
> +int domain_set_llc_colors_domctl(struct domain *d,
> +                                 const struct xen_domctl_set_llc_colors *config)
> +{
> +    if ( d->num_llc_colors )
> +        return -EEXIST;
> +
> +    if ( domain_alloc_colors(d, config->num_llc_colors) )

domain_alloc_colors() doesn't sanity check config->num_llc_colors before 
allocating the array. You want a check the size before so we would not 
try to allocate an arbitrary amount of memory.

> +        return -ENOMEM;
> +
> +    if ( copy_from_guest(d->llc_colors, config->llc_colors,
> +                         config->num_llc_colors) )
> +        return -EFAULT;
> +
> +    return domain_check_colors(d);
> +}
> +
>   /*
>    * Local variables:
>    * mode: C
> diff --git a/xen/common/domctl.c b/xen/common/domctl.c
> index f5a71ee5f7..b6867d0602 100644
> --- a/xen/common/domctl.c
> +++ b/xen/common/domctl.c
> @@ -8,6 +8,7 @@
>   
>   #include <xen/types.h>
>   #include <xen/lib.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/err.h>
>   #include <xen/mm.h>
>   #include <xen/sched.h>
> @@ -858,6 +859,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>                   __HYPERVISOR_domctl, "h", u_domctl);
>           break;
>   
> +    case XEN_DOMCTL_set_llc_colors:
> +        if ( !llc_coloring_enabled )
> +            break;
> +
> +        ret = domain_set_llc_colors_domctl(d, &op->u.set_llc_colors);
> +        if ( ret == -EEXIST )
> +            printk(XENLOG_ERR
> +                   "Can't set LLC colors on an already created domain\n");

To me, the message doesn't match the check in 
domain_set_llc_colors_domctl(). But I think you want to check that no 
memory was yet allocated to the domain. Otherwise, you coloring will be 
wrong.

Also, it is a bit unclear why you print a message for -EEXIST but not 
the others. In this instance, I would consider to print nothing at all.

> +        break;
> +
>       default:
>           ret = arch_do_domctl(op, d, u_domctl);
>           break;
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index a33f9ec32b..2b12069294 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -21,7 +21,7 @@
>   #include "hvm/save.h"
>   #include "memory.h"
>   
> -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000016
> +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000017
>   
>   /*
>    * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
> @@ -1190,6 +1190,12 @@ struct xen_domctl_vmtrace_op {
>   typedef struct xen_domctl_vmtrace_op xen_domctl_vmtrace_op_t;
>   DEFINE_XEN_GUEST_HANDLE(xen_domctl_vmtrace_op_t);
>   
> +struct xen_domctl_set_llc_colors {
> +    /* IN LLC coloring parameters */
> +    unsigned int num_llc_colors;

I think there will be a padding here. So can you make it explicit?

> +    XEN_GUEST_HANDLE_64(uint) llc_colors;
> +};
> +
>   struct xen_domctl {
>       uint32_t cmd;
>   #define XEN_DOMCTL_createdomain                   1
> @@ -1277,6 +1283,7 @@ struct xen_domctl {
>   #define XEN_DOMCTL_vmtrace_op                    84
>   #define XEN_DOMCTL_get_paging_mempool_size       85
>   #define XEN_DOMCTL_set_paging_mempool_size       86
> +#define XEN_DOMCTL_set_llc_colors                87
>   #define XEN_DOMCTL_gdbsx_guestmemio            1000
>   #define XEN_DOMCTL_gdbsx_pausevcpu             1001
>   #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
> @@ -1339,6 +1346,7 @@ struct xen_domctl {
>           struct xen_domctl_vuart_op          vuart_op;
>           struct xen_domctl_vmtrace_op        vmtrace_op;
>           struct xen_domctl_paging_mempool    paging_mempool;
> +        struct xen_domctl_set_llc_colors    set_llc_colors;
>           uint8_t                             pad[128];
>       } u;
>   };
> diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
> index cedd97d4b5..fa2edc8ad8 100644
> --- a/xen/include/xen/llc-coloring.h
> +++ b/xen/include/xen/llc-coloring.h
> @@ -33,6 +33,9 @@ extern bool llc_coloring_enabled;
>   void domain_llc_coloring_free(struct domain *d);
>   void domain_dump_llc_colors(struct domain *d);
>   
> +int domain_set_llc_colors_domctl(struct domain *d,
> +                                 const struct xen_domctl_set_llc_colors *config);
> +
>   #endif /* __COLORING_H__ */
>   
>   /*

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 06/13] xen/arm: add support for cache coloring configuration via device-tree
  2024-01-02  9:51 ` [PATCH v5 06/13] xen/arm: add support for cache coloring configuration via device-tree Carlo Nonato
@ 2024-01-05 17:38   ` Julien Grall
  2024-01-08 11:26     ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-05 17:38 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Carlo,

On 02/01/2024 09:51, Carlo Nonato wrote:
> This commit adds the "llc-colors" Device Tree attribute that can be used
> for DomUs and Dom0less color configurations. The syntax is the same used
> for every color config.
> 
> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
> v5:
> - static-mem check has been moved in a previous patch
> - added domain_set_llc_colors_from_str() to set colors after domain creation
> ---
>   docs/misc/arm/cache-coloring.rst        | 48 ++++++++++++++++++++++++-
>   docs/misc/arm/device-tree/booting.txt   |  4 +++
>   xen/arch/arm/dom0less-build.c           | 13 +++++++
>   xen/arch/arm/include/asm/llc-coloring.h |  1 +
>   xen/arch/arm/llc-coloring.c             | 17 +++++++++
>   5 files changed, 82 insertions(+), 1 deletion(-)
> 
> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> index acf82c3df8..ae1dd8f4af 100644
> --- a/docs/misc/arm/cache-coloring.rst
> +++ b/docs/misc/arm/cache-coloring.rst
> @@ -10,7 +10,7 @@ If needed, change the maximum number of colors with
>   ``CONFIG_NR_LLC_COLORS=<n>``.
>   
>   Compile Xen and the toolstack and then configure it via
> -`Command line parameters`_.
> +`Command line parameters`_. For DomUs follow `DomUs configuration`_.
>   
>   Background
>   **********
> @@ -114,6 +114,52 @@ Examples:
>   | 0                 | [0]                         |
>   +-------------------+-----------------------------+
>   
> +DomUs configuration
> +*******************
> +
> +DomUs colors can be set via Device Tree, also for Dom0less configurations
> +(documentation at `docs/misc/arm/device-tree/booting.txt`) using the
> +``llc-colors`` option. For example:
> +
> +::
> +
> +    xen,xen-bootargs = "console=dtuart dtuart=serial0 dom0_mem=1G dom0_max_vcpus=1 sched=null llc-coloring=on llc-way-size=64K dom0-llc-colors=2-6";
> +    xen,dom0-bootargs "console=hvc0 earlycon=xen earlyprintk=xen root=/dev/ram0"
> +
> +    dom0 {
> +        compatible = "xen,linux-zimage" "xen,multiboot-module";
> +        reg = <0x0 0x1000000 0x0 15858176>;
> +    };
> +
> +    dom0-ramdisk {
> +        compatible = "xen,linux-initrd" "xen,multiboot-module";
> +        reg = <0x0 0x2000000 0x0 20638062>;
> +    };
> +
> +    domU0 {
> +        #address-cells = <0x1>;
> +        #size-cells = <0x1>;
> +        compatible = "xen,domain";
> +        memory = <0x0 0x40000>;
> +        llc-colors = "4-8,10,11,12";
> +        cpus = <0x1>;
> +        vpl011 = <0x1>;
> +
> +        module@2000000 {
> +            compatible = "multiboot,kernel", "multiboot,module";
> +            reg = <0x2000000 0xffffff>;
> +            bootargs = "console=ttyAMA0";
> +        };
> +
> +        module@30000000 {
> +            compatible = "multiboot,ramdisk", "multiboot,module";
> +            reg = <0x3000000 0xffffff>;
> +        };
> +    };
> +
> +**Note:** If no color configuration is provided for a domain, the default one,
> +which corresponds to all available colors, is used instead.

Looking at your code, it will use *all* the colors. Some of the colors 
might have been assigned to a domain. I am not entirely convinced this 
is good idea to allow this as a default setup.


> +
>   Known issues and limitations
>   ****************************
>   
> diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
> index bbd955e9c2..e9f9862e9c 100644
> --- a/docs/misc/arm/device-tree/booting.txt
> +++ b/docs/misc/arm/device-tree/booting.txt
> @@ -162,6 +162,10 @@ with the following properties:
>   
>       An integer specifying the number of vcpus to allocate to the guest.
>   
> +- llc-colors
> +    A string specifying the LLC color configuration for the guest.
> +    Refer to "docs/misc/arm/cache_coloring.rst" for syntax.
> +
>   - vpl011
>   
>       An empty property to enable/disable a virtual pl011 for the guest to
> diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
> index 1142f7f74a..eb39f5291f 100644
> --- a/xen/arch/arm/dom0less-build.c
> +++ b/xen/arch/arm/dom0less-build.c
> @@ -850,6 +850,7 @@ void __init create_domUs(void)
>       struct dt_device_node *node;
>       const struct dt_device_node *cpupool_node,
>                                   *chosen = dt_find_node_by_path("/chosen");
> +    const char *llc_colors_str = NULL;
>   
>       BUG_ON(chosen == NULL);
>       dt_for_each_child_node(chosen, node)
> @@ -993,6 +994,13 @@ void __init create_domUs(void)
>   #endif
>           }
>   
> +        dt_property_read_string(node, "llc-colors", &llc_colors_str);
> +        if ( llc_coloring_enabled && !llc_colors_str )
> +            panic("'llc-colors' is required when LLC coloring is enabled\n");

In the documentation you wrote:

"**Note:** If no color configuration is provided for a domain, the 
default one,which corresponds to all available colors, is used instead."

I interpret as you want to continue rather than panic-ing. That said, I 
much prefer the panic version.

> +        else if ( !llc_coloring_enabled && llc_colors_str)
> +            printk(XENLOG_WARNING
> +                   "'llc-colors' found, but LLC coloring is disabled\n");
> +
>           /*
>            * The variable max_init_domid is initialized with zero, so here it's
>            * very important to use the pre-increment operator to call
> @@ -1003,6 +1011,11 @@ void __init create_domUs(void)
>               panic("Error creating domain %s (rc = %ld)\n",
>                     dt_node_name(node), PTR_ERR(d));
>   
> +        if ( llc_coloring_enabled &&
> +             (rc = domain_set_llc_colors_from_str(d, llc_colors_str)) )
> +            panic("Error initializing LLC coloring for domain %s (rc = %d)\n",
> +                  dt_node_name(node), rc);
> +
>           d->is_console = true;
>           dt_device_set_used_by(node, d->domain_id);
>   
> diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
> index ee5551e3cc..5f9b0a8121 100644
> --- a/xen/arch/arm/include/asm/llc-coloring.h
> +++ b/xen/arch/arm/include/asm/llc-coloring.h
> @@ -15,6 +15,7 @@
>   
>   bool __init llc_coloring_init(void);
>   int dom0_set_llc_colors(struct domain *d);
> +int domain_set_llc_colors_from_str(struct domain *d, const char *str);
>   
>   #endif /* __ASM_ARM_COLORING_H__ */
>   
> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> index a08614ec36..d3de5f14cb 100644
> --- a/xen/arch/arm/llc-coloring.c
> +++ b/xen/arch/arm/llc-coloring.c
> @@ -295,6 +295,23 @@ int domain_set_llc_colors_domctl(struct domain *d,
>       return domain_check_colors(d);
>   }
>   
> +int domain_set_llc_colors_from_str(struct domain *d, const char *str)
> +{
> +    int err;
> +
> +    if ( domain_alloc_colors(d, nr_colors) )

This code is somewhat confusing and would deserve some explanation. 
AFAICT, you are allocating a large array because parse_color_config() 
expects an array of nr_colors.

d->num_llc_colors will also be set to nr_colors but then overriden by 
parse_color_config().

It feels to me that maybe set num_llc_colors() in domain_alloc_colors() 
is not right.

> +        return -ENOMEM;
> +
> +    err = parse_color_config(str, d->llc_colors, &d->num_llc_colors);
> +    if ( err )
> +    {
> +        printk(XENLOG_ERR "Error parsing LLC color configuration.");
> +        return err;
> +    }
> +
> +    return domain_check_colors(d);
> +}
> +
>   /*
>    * Local variables:
>    * mode: C

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 02/13] xen/arm: add cache coloring initialization
  2024-01-05 16:34     ` Carlo Nonato
@ 2024-01-05 17:44       ` Julien Grall
  2024-01-11 10:17       ` Carlo Nonato
  1 sibling, 0 replies; 90+ messages in thread
From: Julien Grall @ 2024-01-05 17:44 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Carlo,

On 05/01/2024 16:34, Carlo Nonato wrote:
> On Thu, Jan 4, 2024 at 8:25 PM Julien Grall <julien@xen.org> wrote:
>>
>> Hi Carlo,
>>
>> On 02/01/2024 09:51, Carlo Nonato wrote:
>>> This commit implements functions declared in the LLC coloring common header
>>> for arm64 and adds documentation. It also adds two command line options: a
>>> runtime switch for the cache coloring feature and the LLC way size
>>> parameter.
>>>
>>> The feature init function consists of an auto probing of the cache layout
>>> necessary to retrieve the LLC way size which is used to compute the number
>>> of platform colors. It also adds a debug-key to dump general cache coloring
>>> info.
>>>
>>> Static memory allocation and cache coloring are incompatible because static
>>> memory can't be guaranteed to use only colors assigned to the domain.
>>> Panic during domUs creation when both are enabled.
>>>
>>> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
>>>
>>> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
>>> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
>>> ---
>>> v5:
>>> - used - instead of _ for filenames
>>> - moved static-mem check in this patch
>>> - moved dom0 colors parsing in next patch
>>> - moved color allocation and configuration in next patch
>>> - moved check_colors() in next patch
>>> - colors are now printed in short form
>>> v4:
>>> - added "llc-coloring" cmdline option for the boot-time switch
>>> - dom0 colors are now checked during domain init as for any other domain
>>> - fixed processor.h masks bit width
>>> - check for overflow in parse_color_config()
>>> - check_colors() now checks also that colors are sorted and unique
>>> ---
>>>    docs/misc/arm/cache-coloring.rst        |  97 ++++++++++++++
>>>    docs/misc/xen-command-line.pandoc       |  28 +++++
>>>    xen/arch/arm/Kconfig                    |   1 +
>>>    xen/arch/arm/Makefile                   |   1 +
>>>    xen/arch/arm/dom0less-build.c           |   6 +
>>>    xen/arch/arm/include/asm/llc-coloring.h |  28 +++++
>>>    xen/arch/arm/include/asm/processor.h    |  16 +++
>>>    xen/arch/arm/llc-coloring.c             | 161 ++++++++++++++++++++++++
>>>    xen/arch/arm/setup.c                    |   7 ++
>>>    9 files changed, 345 insertions(+)
>>>    create mode 100644 docs/misc/arm/cache-coloring.rst
>>>    create mode 100644 xen/arch/arm/include/asm/llc-coloring.h
>>>    create mode 100644 xen/arch/arm/llc-coloring.c
>>>
>>> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
>>> new file mode 100644
>>> index 0000000000..eabf8f5d1b
>>> --- /dev/null
>>> +++ b/docs/misc/arm/cache-coloring.rst
>>> @@ -0,0 +1,97 @@
>>> +Xen cache coloring user guide
>>> +=============================
>>> +
>>> +The cache coloring support in Xen allows to reserve Last Level Cache (LLC)
>>> +partitions for Dom0, DomUs and Xen itself. Currently only ARM64 is supported.
>>> +
>>> +To compile LLC coloring support set ``CONFIG_LLC_COLORING=y``.
>>> +
>>> +If needed, change the maximum number of colors with
>>> +``CONFIG_NR_LLC_COLORS=<n>``.
>>> +
>>> +Compile Xen and the toolstack and then configure it via
>>> +`Command line parameters`_.
>>> +
>>> +Background
>>> +**********
>>> +
>>> +Cache hierarchy of a modern multi-core CPU typically has first levels dedicated
>>> +to each core (hence using multiple cache units), while the last level is shared
>>> +among all of them. Such configuration implies that memory operations on one
>>> +core (e.g. running a DomU) are able to generate interference on another core
>>> +(e.g .hosting another DomU). Cache coloring allows eliminating this
>>> +mutual interference, and thus guaranteeing higher and more predictable
>>> +performances for memory accesses.
>>> +The key concept underlying cache coloring is a fragmentation of the memory
>>> +space into a set of sub-spaces called colors that are mapped to disjoint cache
>>> +partitions. Technically, the whole memory space is first divided into a number
>>> +of subsequent regions. Then each region is in turn divided into a number of
>>> +subsequent sub-colors. The generic i-th color is then obtained by all the
>>> +i-th sub-colors in each region.
>>> +
>>> +::
>>> +
>>> +                            Region j            Region j+1
>>> +                .....................   ............
>>> +                .                     . .
>>> +                .                       .
>>> +            _ _ _______________ _ _____________________ _ _
>>> +                |     |     |     |     |     |     |
>>> +                | c_0 | c_1 |     | c_n | c_0 | c_1 |
>>> +           _ _ _|_____|_____|_ _ _|_____|_____|_____|_ _ _
>>> +                    :                       :
>>> +                    :                       :...         ... .
>>> +                    :                            color 0
>>> +                    :...........................         ... .
>>> +                                                :
>>> +          . . ..................................:
>>> +
>>> +There are two pragmatic lesson to be learnt.
>>> +
>>> +1. If one wants to avoid cache interference between two domains, different
>>> +   colors needs to be used for their memory.
>>> +
>>> +2. Color assignment must privilege contiguity in the partitioning. E.g.,
>>> +   assigning colors (0,1) to domain I  and (2,3) to domain  J is better than
>>> +   assigning colors (0,2) to I and (1,3) to J.
>>> +
>>> +How to compute the number of colors
>>> +***********************************
>>> +
>>> +To compute the number of available colors for a specific platform, the size of
>>> +an LLC way and the page size used by Xen must be known.
>>
>> Looking at the get_llc_way_size(), you are using CLIDR_EL1 which doesn't
>> contains the system caches. They are invisible to the software but I
>> guess could have an impact for cache coloring.
>>
>> Can you clarify if by Last Cache Level, you mean the last visible cache?
> 
> We are targeting only Cortex-A53, A57 and A72 where the "last level" is L2.
> This "generic" approach for last level computation is inevitably problematic,
> but I think that defining it as the last visible cache is the best thing we
> can do. Remember also that this computation is overridable with the
> appropriate command line parameter, so it's still possible to target
> cache architectures that aren't discovered by this code (which are rare cases
> since cache-coloring is already a small niche).

I understand that and I don't mind which definition is chosen. I just 
want the documentation to be clear enough so there is little to no 
interpretation left.

[...]

>>> +    {
>>> +        printk(XENLOG_ERR "Number of LLC colors (%u) not in range [2, %u]\n",
>>> +               nr_colors, CONFIG_NR_LLC_COLORS);
>>> +        return false;
>>> +    }
>>> +
>>> +    register_keyhandler('K', dump_coloring_info, "dump LLC coloring info", 1);
>>> +
>>> +    return true;
>>> +}
>>> +
>>> +void domain_llc_coloring_free(struct domain *d)
>>> +{
>>> +    xfree(d->llc_colors);
>>> +}
>>> +
>>> +void domain_dump_llc_colors(struct domain *d)
>>> +{
>>> +    printk("Domain %pd has %u LLC colors: ", d, d->num_llc_colors);
>>> +    print_colors(d->llc_colors, d->num_llc_colors);
>>> +}
>>> +
>>> +/*
>>> + * Local variables:
>>> + * mode: C
>>> + * c-file-style: "BSD"
>>> + * c-basic-offset: 4
>>> + * tab-width: 4
>>> + * indent-tabs-mode: nil
>>> + * End:
>>> + */
>>> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
>>> index 59dd9bb25a..4c16b566db 100644
>>> --- a/xen/arch/arm/setup.c
>>> +++ b/xen/arch/arm/setup.c
>>> @@ -12,6 +12,7 @@
>>>    #include <xen/device_tree.h>
>>>    #include <xen/domain_page.h>
>>>    #include <xen/grant_table.h>
>>> +#include <xen/llc-coloring.h>
>>>    #include <xen/types.h>
>>>    #include <xen/string.h>
>>>    #include <xen/serial.h>
>>> @@ -746,6 +747,12 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
>>>        printk("Command line: %s\n", cmdline);
>>>        cmdline_parse(cmdline);
>>>
>>> +    if ( llc_coloring_enabled )
>>
>> I would consider to move llc_coloring_enabled in llc_coloring_init().
>> But if you prefer to keep the check here, then I would at least request
>> to merge the two ifs. I.e.
>>
>> if ( llc_coloring_enabled && !llc_coloring_init() )
>>
>> That said...
>>
>>> +    {
>>> +        if ( !llc_coloring_init() )
>>> +            panic("Xen LLC coloring support: setup failed\n");
>>> +    }
>>> +
>>>        setup_mm();
>>
>> ... shouldn't the coloring happen in setup_mm()? After all, this is part
>> of the memory subystem and I suspect this will not work with the
>> upcoming MPU support.
> 
> Coloring initialization must happen before setup_pagetables() otherwise it
> isn't possible to color the hypervisor code. In later patches
> setup_pagetables() is moved after coloring init so I don't think it would
> make sense to have it in setup_mm().

If you decide to move setup_page_tables() just close to setup_mm(). 
Then, I think the call should be moved to setup_mm().

I will have a look at the rest of the series and come back to this point.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support
  2024-01-05 16:52     ` Carlo Nonato
@ 2024-01-05 17:50       ` Julien Grall
  2024-01-08 10:06         ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-05 17:50 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri



On 05/01/2024 16:52, Carlo Nonato wrote:
> Hi Julien,
> 
> On Thu, Jan 4, 2024 at 8:54 PM Julien Grall <julien@xen.org> wrote:
>>
>> Hi Carlo,
>>
>> On 02/01/2024 09:51, Carlo Nonato wrote:
>>> This commit allows the user to set the cache coloring configuration for
>>> Dom0 via a command line parameter.
>>> Since cache coloring and static memory are incompatible, direct mapping
>>> Dom0 isn't possible when coloring is enabled.
>>>
>>> A common configuration syntax for cache colors is also introduced.
>>>
>>> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
>>>
>>> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
>>> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
>>> ---
>>> v5:
>>> - Carlo Nonato as the new author
>>> - moved dom0 colors parsing (parse_colors()) in this patch
>>> - added dom0_set_llc_colors() to set dom0 colors after creation
>>> - moved color allocation and checking in this patch
>>> - error handling when allocating color arrays
>>> - FIXME: copy pasted allocate_memory() cause it got moved
>>> v4:
>>> - dom0 colors are dynamically allocated as for any other domain
>>>     (colors are duplicated in dom0_colors and in the new array, but logic
>>>     is simpler)
>>> ---
>>>    docs/misc/arm/cache-coloring.rst        |  29 ++++++
>>>    docs/misc/xen-command-line.pandoc       |   9 ++
>>>    xen/arch/arm/domain_build.c             |  60 ++++++++++-
>>>    xen/arch/arm/include/asm/llc-coloring.h |   1 +
>>>    xen/arch/arm/llc-coloring.c             | 128 ++++++++++++++++++++++++
>>>    5 files changed, 224 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
>>> index eabf8f5d1b..acf82c3df8 100644
>>> --- a/docs/misc/arm/cache-coloring.rst
>>> +++ b/docs/misc/arm/cache-coloring.rst
>>> @@ -84,6 +84,35 @@ More specific documentation is available at `docs/misc/xen-command-line.pandoc`.
>>>    +----------------------+-------------------------------+
>>>    | ``llc-way-size``     | set the LLC way size          |
>>>    +----------------------+-------------------------------+
>>> +| ``dom0-llc-colors``  | Dom0 color configuration      |
>>> ++----------------------+-------------------------------+
>>> +
>>> +Colors selection format
>>> +***********************
>>> +
>>> +Regardless of the memory pool that has to be colored (Xen, Dom0/DomUs),
>>> +the color selection can be expressed using the same syntax. In particular a
>>> +comma-separated list of colors or ranges of colors is used.
>>> +Ranges are hyphen-separated intervals (such as `0-4`) and are inclusive on both
>>> +sides.
>>> +
>>> +Note that:
>>> +
>>> +- no spaces are allowed between values.
>>> +- no overlapping ranges or duplicated colors are allowed.
>>> +- values must be written in ascending order.
>>> +
>>> +Examples:
>>> +
>>> ++-------------------+-----------------------------+
>>> +| **Configuration** | **Actual selection**        |
>>> ++-------------------+-----------------------------+
>>> +| 1-2,5-8           | [1, 2, 5, 6, 7, 8]          |
>>> ++-------------------+-----------------------------+
>>> +| 4-8,10,11,12      | [4, 5, 6, 7, 8, 10, 11, 12] |
>>> ++-------------------+-----------------------------+
>>> +| 0                 | [0]                         |
>>> ++-------------------+-----------------------------+
>>>
>>>    Known issues and limitations
>>>    ****************************
>>> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
>>> index 22d2d5b6cf..51f6adf035 100644
>>> --- a/docs/misc/xen-command-line.pandoc
>>> +++ b/docs/misc/xen-command-line.pandoc
>>> @@ -963,6 +963,15 @@ Controls for the dom0 IOMMU setup.
>>>
>>>    Specify a list of IO ports to be excluded from dom0 access.
>>>
>>> +### dom0-llc-colors (arm64)
>>> +> `= List of [ <integer> | <integer>-<integer> ]`
>>
>> Someone reading only xen-command-line.pandoc would not know how each
>> item of the list is separated. Can this be clarified?
> 
> Isn't it already known that the list is comma separated? It's written at the
> beginning of this file for the "List" type.
> I can also point to cache-coloring documentation if needed.

Ah I forgot that part. Please ignore this comment.

[...]

>>> +                return -EINVAL;
>>> +            for ( color = start; color <= end; color++ )
>>> +                colors[(*num_colors)++] = color;
>>> +        }
>>> +        else
>>> +            s++;
>>> +    }
>>> +
>>> +    return *s ? -EINVAL : 0;
>>> +}
>>> +
>>> +static int __init parse_dom0_colors(const char *s)
>>> +{
>>> +    return parse_color_config(s, dom0_colors, &dom0_num_colors);
>>> +}
>>> +custom_param("dom0-llc-colors", parse_dom0_colors);
>>> +
>>>    /* Return the LLC way size by probing the hardware */
>>>    static unsigned int __init get_llc_way_size(void)
>>>    {
>>> @@ -102,6 +159,28 @@ static void dump_coloring_info(unsigned char key)
>>>        printk("Number of LLC colors supported: %u\n", nr_colors);
>>>    }
>>>
>>> +static bool check_colors(unsigned int *colors, unsigned int num_colors)
>>> +{
>>> +    unsigned int i;
>>> +
>>> +    if ( num_colors > nr_colors )
>>> +    {
>>> +        printk(XENLOG_ERR "Number of LLC colors requested > %u\n", nr_colors);
>>> +        return false;
>>> +    }
>>> +
>>> +    for ( i = 0; i < num_colors; i++ )
>>> +    {
>>> +        if ( colors[i] >= nr_colors )
>>> +        {
>>> +            printk(XENLOG_ERR "LLC color %u >= %u\n", colors[i], nr_colors);
>>> +            return false;
>>> +        }
>>> +    }
>>> +
>>> +    return true;
>>> +}
>>> +
>>>    bool __init llc_coloring_init(void)
>>>    {
>>>        if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
>>> @@ -150,6 +229,55 @@ void domain_dump_llc_colors(struct domain *d)
>>>        print_colors(d->llc_colors, d->num_llc_colors);
>>>    }
>>>
>>> +static int domain_alloc_colors(struct domain *d, unsigned int num_colors)
>>> +{
>>> +    d->num_llc_colors = num_colors;
>>
>> Shouldn't this be set *only* after the array was allocated?
> 
> Yes, it works also like I did, but it's cleaner like you said. 

Actually, looking at the rest of the code. I think  d->num_llc_colors 
should be set outside of domain_alloc_colors().

One of the reason is at least in the dom0less case, you will override 
the value afterwards.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 10/13] xen/arm: use domain memory to allocate p2m page tables
  2024-01-02  9:51 ` [PATCH v5 10/13] xen/arm: use domain memory to allocate p2m page tables Carlo Nonato
@ 2024-01-05 17:54   ` Julien Grall
  0 siblings, 0 replies; 90+ messages in thread
From: Julien Grall @ 2024-01-05 17:54 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Carlo,

On 02/01/2024 09:51, Carlo Nonato wrote:
> Cache colored domains can benefit from having p2m page tables allocated
> with the same coloring schema so that isolation can be achieved also for
> those kind of memory accesses.
> In order to do that, the domain struct is passed to the allocator and the
> MEMF_no_owner flag is used.
> 
> This will be useful also when NUMA will be supported on Arm.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>

Acked-by: Julien Grall <julien@xen.org>

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 12/13] xen/arm: add Xen cache colors command line parameter
  2024-01-02  9:51 ` [PATCH v5 12/13] xen/arm: add Xen cache colors command line parameter Carlo Nonato
@ 2024-01-05 18:00   ` Julien Grall
  2024-01-05 23:09     ` Stefano Stabellini
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-05 18:00 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Luca Miccio, Andrew Cooper, George Dunlap, Jan Beulich,
	Stefano Stabellini, Wei Liu, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi,

On 02/01/2024 09:51, Carlo Nonato wrote:
> From: Luca Miccio <lucmiccio@gmail.com>
> 
> This commit adds a new command line parameter to configure Xen cache colors.
> These colors can be dumped with the cache coloring info debug-key.
> 
> By default, Xen uses the first color.
> Benchmarking the VM interrupt response time provides an estimation of
> LLC usage by Xen's most latency-critical runtime task. Results on Arm
> Cortex-A53 on Xilinx Zynq UltraScale+ XCZU9EG show that one color, which
> reserves 64 KiB of L2, is enough to attain best responsiveness.

Would you be able to share some numbers? This is quite helpful if in the 
future we need to revise the default.

> 
> More colors are instead very likely to be needed on processors whose L1
> cache is physically-indexed and physically-tagged, such as Cortex-A57.
> In such cases, coloring applies to L1 also, and there typically are two
> distinct L1-colors. Therefore, reserving only one color for Xen would
> senselessly partitions a cache memory that is already private, i.e.
> underutilize it. The default amount of Xen colors is thus set to one.
> 
> Signed-off-by: Luca Miccio <lucmiccio@gmail.com>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> ---
>   docs/misc/xen-command-line.pandoc | 10 ++++++++++
>   xen/arch/arm/llc-coloring.c       | 29 +++++++++++++++++++++++++++++
>   2 files changed, 39 insertions(+)
> 
> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> index 163fe7bcb1..f983f22796 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -2877,6 +2877,16 @@ mode.
>   **WARNING: `x2apic_phys` is deprecated and superseded by `x2apic-mode`.
>   The latter takes precedence if both are set.**
>   
> +### xen-llc-colors (arm64)
> +> `= List of [ <integer> | <integer>-<integer> ]`
> +
> +> Default: `0: the lowermost color`
> +
> +Specify Xen LLC color configuration. This options is available only when
> +`CONFIG_LLC_COLORING` is enabled.
> +Two colors are most likely needed on platforms where private caches are
> +physically indexed, e.g. the L1 instruction cache of the Arm Cortex-A57.
> +
>   ### xenheap_megabytes (arm32)
>   > `= <size>`
>   
> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> index 526129cc43..99ea69ad39 100644
> --- a/xen/arch/arm/llc-coloring.c
> +++ b/xen/arch/arm/llc-coloring.c
> @@ -18,6 +18,9 @@
>   #include <asm/processor.h>
>   #include <asm/sysregs.h>
>   
> +#define XEN_DEFAULT_COLOR       0
> +#define XEN_DEFAULT_NUM_COLORS  1
> +
>   bool __ro_after_init llc_coloring_enabled;
>   boolean_param("llc-coloring", llc_coloring_enabled);
>   
> @@ -30,6 +33,9 @@ static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
>   static unsigned int __ro_after_init dom0_colors[CONFIG_NR_LLC_COLORS];
>   static unsigned int __ro_after_init dom0_num_colors;
>   
> +static unsigned int __ro_after_init xen_colors[CONFIG_NR_LLC_COLORS];
> +static unsigned int __ro_after_init xen_num_colors;
> +
>   #define mfn_color_mask              (nr_colors - 1)
>   #define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
>   
> @@ -87,6 +93,12 @@ static int __init parse_dom0_colors(const char *s)
>   }
>   custom_param("dom0-llc-colors", parse_dom0_colors);
>   
> +static int __init parse_xen_colors(const char *s)
> +{
> +    return parse_color_config(s, xen_colors, &xen_num_colors);
> +}
> +custom_param("xen-llc-colors", parse_xen_colors);
> +
>   /* Return the LLC way size by probing the hardware */
>   static unsigned int __init get_llc_way_size(void)
>   {
> @@ -161,6 +173,8 @@ static void dump_coloring_info(unsigned char key)
>       printk("'%c' pressed -> dumping LLC coloring general info\n", key);
>       printk("LLC way size: %u KiB\n", llc_way_size >> 10);
>       printk("Number of LLC colors supported: %u\n", nr_colors);
> +    printk("Xen has %u LLC colors: ", xen_num_colors);
> +    print_colors(xen_colors, xen_num_colors);
>   }
>   
>   static bool check_colors(unsigned int *colors, unsigned int num_colors)
> @@ -217,6 +231,21 @@ bool __init llc_coloring_init(void)
>           return false;
>       }
>   
> +    if ( !xen_num_colors )
> +    {
> +        printk(XENLOG_WARNING
> +               "Xen LLC color config not found. Using default color: %u\n",
> +               XEN_DEFAULT_COLOR);
> +        xen_colors[0] = XEN_DEFAULT_COLOR;
> +        xen_num_colors = XEN_DEFAULT_NUM_COLORS;
> +    }
> +
> +    if ( !check_colors(xen_colors, xen_num_colors) )
> +    {
> +        printk(XENLOG_ERR "Bad LLC color config for Xen\n");
> +        return false;
> +    }
> +
>       register_keyhandler('K', dump_coloring_info, "dump LLC coloring info", 1);
>   
>       return true;

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 11/13] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START"
  2024-01-02  9:51 ` [PATCH v5 11/13] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START" Carlo Nonato
@ 2024-01-05 18:20   ` Julien Grall
  2024-01-08 11:28     ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-05 18:20 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Carlo,

On 02/01/2024 09:51, Carlo Nonato wrote:
> This reverts commit 0c18fb76323bfb13615b6f13c98767face2d8097 (not clean).
> 
> This is not a clean revert since the rework of the memory layout, but it is
> sufficiently similar to a clean one.
> The only difference is that the BOOT_RELOC_VIRT_START must match the new
> layout.
> 
> Cache coloring support for Xen needs to relocate Xen code and data in a new
> colored physical space. The BOOT_RELOC_VIRT_START will be used as the virtual
> base address for a temporary mapping to this new space.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
>   xen/arch/arm/include/asm/mmu/layout.h | 2 ++
>   xen/arch/arm/mmu/setup.c              | 1 +
>   2 files changed, 3 insertions(+)
> 
> diff --git a/xen/arch/arm/include/asm/mmu/layout.h b/xen/arch/arm/include/asm/mmu/layout.h
> index eac7eef885..30031f74d9 100644
> --- a/xen/arch/arm/include/asm/mmu/layout.h
> +++ b/xen/arch/arm/include/asm/mmu/layout.h
> @@ -74,6 +74,8 @@
>   #define BOOT_FDT_VIRT_START     (FIXMAP_VIRT_START + FIXMAP_VIRT_SIZE)
>   #define BOOT_FDT_VIRT_SIZE      _AT(vaddr_t, MB(4))
>   
> +#define BOOT_RELOC_VIRT_START   (BOOT_FDT_VIRT_START + BOOT_FDT_VIRT_SIZE)

This new addition wants to be documented in the layout comment in a few 
lines above. Also, the area you are using is 2MB whereas Xen can now be 
up to 8MB.

Secondly, you want to add a BOOTRELOC_VIRT_SIZE with a check in 
build_assertions() making sure that this is at least as big as 
XEN_VIRT_SIZE.

Overall, I am not sure this is really a revert at this point. The idea 
is the same, but you are defining BOOT_FDT_VIRT_START differently.

To me it feels like it belong to the first patch where you will use it. 
And that would be ok to mention in the commit message that the idea was 
borrowed from a previously reverted commit.

> +
>   #ifdef CONFIG_LIVEPATCH
>   #define LIVEPATCH_VMAP_START    (BOOT_FDT_VIRT_START + BOOT_FDT_VIRT_SIZE)
>   #define LIVEPATCH_VMAP_SIZE    _AT(vaddr_t, MB(2))
> diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
> index d5264e51bc..37b6d230ad 100644
> --- a/xen/arch/arm/mmu/setup.c
> +++ b/xen/arch/arm/mmu/setup.c
> @@ -69,6 +69,7 @@ static void __init __maybe_unused build_assertions(void)
>       /* 2MB aligned regions */
>       BUILD_BUG_ON(XEN_VIRT_START & ~SECOND_MASK);
>       BUILD_BUG_ON(FIXMAP_ADDR(0) & ~SECOND_MASK);
> +    BUILD_BUG_ON(BOOT_RELOC_VIRT_START & ~SECOND_MASK);
>       /* 1GB aligned regions */
>   #ifdef CONFIG_ARM_32
>       BUILD_BUG_ON(XENHEAP_VIRT_START & ~FIRST_MASK);

-- 
Julien Grall


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-02  9:51 ` [PATCH v5 13/13] xen/arm: add cache coloring support for Xen Carlo Nonato
@ 2024-01-05 19:12   ` Julien Grall
  2024-01-13 17:07     ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-05 19:12 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Carlo,

On 02/01/2024 09:51, Carlo Nonato wrote:
> This commit adds the cache coloring support for Xen own physical space.
> 
> It extends the implementation of setup_pagetables() to make use of Xen
> cache coloring configuration. Page tables construction is essentially the
> same except for the fact that PTEs point to a new temporary mapped,
> physically colored space.
> 
> The temporary mapping is also used to relocate Xen to the new physical
> space starting at the address taken from the old get_xen_paddr() function
> which is brought back for the occasion.
> The temporary mapping is finally converted to a mapping of the "old"
> (meaning the original physical space) Xen code, so that the boot CPU can
> actually address the variables and functions used by secondary CPUs until
> they enable the MMU. This happens when the boot CPU needs to bring up other
> CPUs (psci.c and smpboot.c) and when the TTBR value is passed to them
> (prepare_secondary_mm()).
> 
> Finally, since the alternative framework needs to remap the Xen text and
> inittext sections, this operation must be done in a coloring-aware way.
> The function xen_remap_colored() is introduced for that.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
> v5:
> - FIXME: consider_modules copy pasted since it got moved
> v4:
> - removed set_value_for_secondary() because it was wrongly cleaning cache
> - relocate_xen() now calls switch_ttbr_id()
> ---
>   xen/arch/arm/alternative.c              |   9 +-
>   xen/arch/arm/arm64/mmu/head.S           |  48 +++++++
>   xen/arch/arm/arm64/mmu/mm.c             |  26 +++-
>   xen/arch/arm/include/asm/llc-coloring.h |  16 +++
>   xen/arch/arm/include/asm/mm.h           |   7 +-
>   xen/arch/arm/llc-coloring.c             |  44 +++++++
>   xen/arch/arm/mmu/setup.c                |  82 +++++++++++-
>   xen/arch/arm/mmu/smpboot.c              |  11 +-
>   xen/arch/arm/psci.c                     |   9 +-
>   xen/arch/arm/setup.c                    | 165 +++++++++++++++++++++++-
>   xen/arch/arm/smpboot.c                  |   9 +-

This patch has is touching a lot of different components. I think this 
want to be split in more smaller chunk. It would also be help to mention 
what code has been copied from previous Xen. For instance, 
relocate_xen() is clearly a copy of f60658c6ae47.

>   11 files changed, 406 insertions(+), 20 deletions(-)
> 
> diff --git a/xen/arch/arm/alternative.c b/xen/arch/arm/alternative.c
> index 016e66978b..54cbc2afad 100644
> --- a/xen/arch/arm/alternative.c
> +++ b/xen/arch/arm/alternative.c
> @@ -9,6 +9,7 @@
>   #include <xen/init.h>
>   #include <xen/types.h>
>   #include <xen/kernel.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/mm.h>
>   #include <xen/vmap.h>
>   #include <xen/smp.h>
> @@ -209,8 +210,12 @@ void __init apply_alternatives_all(void)
>        * The text and inittext section are read-only. So re-map Xen to
>        * be able to patch the code.
>        */
> -    xenmap = __vmap(&xen_mfn, 1U << xen_order, 1, 1, PAGE_HYPERVISOR,
> -                    VMAP_DEFAULT);
> +    if ( llc_coloring_enabled )
> +        xenmap = xen_remap_colored(xen_mfn, xen_size);
> +    else
> +        xenmap = __vmap(&xen_mfn, 1U << xen_order, 1, 1, PAGE_HYPERVISOR,
> +                        VMAP_DEFAULT);
> +
>       /* Re-mapping Xen is not expected to fail during boot. */
>       BUG_ON(!xenmap);
>   
> diff --git a/xen/arch/arm/arm64/mmu/head.S b/xen/arch/arm/arm64/mmu/head.S
> index 10774f30e4..6f0cc72897 100644
> --- a/xen/arch/arm/arm64/mmu/head.S
> +++ b/xen/arch/arm/arm64/mmu/head.S
> @@ -419,6 +419,54 @@ fail:   PRINT("- Boot failed -\r\n")
>           b     1b
>   ENDPROC(fail)
>   
> +/* Copy Xen to new location and switch TTBR
> + * x0    ttbr
> + * x1    source address
> + * x2    destination address
> + * x3    length
> + *
> + * Source and destination must be word aligned, length is rounded up
> + * to a 16 byte boundary.
> + *
> + * MUST BE VERY CAREFUL when saving things to RAM over the copy */

If you plan to re-introduce code, then please at least make sure it 
match the coding style. For comments, it should be:

/*
  * Foo
  * Bar
  */

> +ENTRY(relocate_xen)
> +        /* Copy 16 bytes at a time using:
> +         *   x9: counter
> +         *   x10: data
> +         *   x11: data
> +         *   x12: source
> +         *   x13: destination
> +         */
> +        mov     x9, x3
> +        mov     x12, x1
> +        mov     x13, x2
> +
> +1:      ldp     x10, x11, [x12], #16
> +        stp     x10, x11, [x13], #16
> +
> +        subs    x9, x9, #16
> +        bgt     1b
> +
> +        /* Flush destination from dcache using:

I would explain why you need the flush. AFAICT, this is because you want 
the data to be visible to the instruction cache. I would also point out 
that you need the instruction cache flush in switch_ttbr_id() where the 
sentence "This should not be necessary ..." should be now reworked 
(AFAIK it is mandatory for cache coloring).

> +         * x9: counter
> +         * x10: step
> +         * x11: vaddr
> +         */
> +        dsb   sy        /* So the CPU issues all writes to the range */
> +
> +        mov   x9, x3
> +        ldr   x10, =dcache_line_bytes /* x10 := step */
> +        ldr   x10, [x10]
> +        mov   x11, x2
> +
> +1:      dc    cvac, x11
> +
> +        add   x11, x11, x10
> +        subs  x9, x9, x10
> +        bgt   1b
> +

I would add a comment here explaining you are relying on the dsb/isb in 
switch_ttbr_id().

> +        b switch_ttbr_id
> +
>   /*
>    * Switch TTBR
>    *
> diff --git a/xen/arch/arm/arm64/mmu/mm.c b/xen/arch/arm/arm64/mmu/mm.c
> index d2651c9486..5a26d64ab7 100644
> --- a/xen/arch/arm/arm64/mmu/mm.c
> +++ b/xen/arch/arm/arm64/mmu/mm.c
> @@ -1,6 +1,7 @@
>   /* SPDX-License-Identifier: GPL-2.0 */
>   
>   #include <xen/init.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/mm.h>
>   #include <xen/pfn.h>
>   
> @@ -125,27 +126,44 @@ void update_identity_mapping(bool enable)
>   }
>   
>   extern void switch_ttbr_id(uint64_t ttbr);
> +extern void relocate_xen(uint64_t ttbr, void *src, void *dst, size_t len);
>   
>   typedef void (switch_ttbr_fn)(uint64_t ttbr);
> +typedef void (relocate_xen_fn)(uint64_t ttbr, void *src, void *dst, size_t len);
>   
>   void __init switch_ttbr(uint64_t ttbr)
>   {
> -    vaddr_t id_addr = virt_to_maddr(switch_ttbr_id);
> -    switch_ttbr_fn *fn = (switch_ttbr_fn *)id_addr;
> +    vaddr_t vaddr, id_addr;
>       lpae_t pte;
>   
> +    if ( llc_coloring_enabled )
> +        vaddr = (vaddr_t)relocate_xen;
> +    else
> +        vaddr = (vaddr_t)switch_ttbr_id;
> +
> +    id_addr = virt_to_maddr(vaddr);
> +
>       /* Enable the identity mapping in the boot page tables */
>       update_identity_mapping(true);
>   
>       /* Enable the identity mapping in the runtime page tables */
> -    pte = pte_of_xenaddr((vaddr_t)switch_ttbr_id);
> +    pte = pte_of_xenaddr(vaddr);
>       pte.pt.table = 1;
>       pte.pt.xn = 0;
>       pte.pt.ro = 1;
>       write_pte(&xen_third_id[third_table_offset(id_addr)], pte);
>   
>       /* Switch TTBR */
> -    fn(ttbr);
> +    if ( llc_coloring_enabled )
> +    {
> +        relocate_xen_fn *fn = (relocate_xen_fn *)id_addr;

Coding style: We tend to add a new line after variable declaration.

> +        fn(ttbr, _start, (void *)BOOT_RELOC_VIRT_START, _end - _start);
> +    }
> +    else
> +    {
> +        switch_ttbr_fn *fn = (switch_ttbr_fn *)id_addr;

Ditto for the coding style.

> +        fn(ttbr);
> +    }
>   
>       /*
>        * Disable the identity mapping in the runtime page tables.
> diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
> index 5f9b0a8121..4d6071e50b 100644
> --- a/xen/arch/arm/include/asm/llc-coloring.h
> +++ b/xen/arch/arm/include/asm/llc-coloring.h
> @@ -12,11 +12,27 @@
>   #define __ASM_ARM_COLORING_H__
>   
>   #include <xen/init.h>
> +#include <xen/mm-frame.h>
> +
> +/**
> + * Iterate over each Xen mfn in the colored space.
> + * @mfn:    the current mfn. The first non colored mfn must be provided as the
> + *          starting point.
> + * @i:      loop index.
> + */
> +#define for_each_xen_colored_mfn(mfn, i)        \
> +    for ( i = 0, mfn = xen_colored_mfn(mfn);    \
> +          i < (_end - _start) >> PAGE_SHIFT;    \
> +          i++, mfn = xen_colored_mfn(mfn_add(mfn, 1)) )
>   
>   bool __init llc_coloring_init(void);
>   int dom0_set_llc_colors(struct domain *d);
>   int domain_set_llc_colors_from_str(struct domain *d, const char *str);
>   
> +paddr_t xen_colored_map_size(paddr_t size);
> +mfn_t xen_colored_mfn(mfn_t mfn);
> +void *xen_remap_colored(mfn_t xen_fn, paddr_t xen_size);
> +
>   #endif /* __ASM_ARM_COLORING_H__ */
>   
>   /*
> diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
> index 1829c559d6..311f092cf2 100644
> --- a/xen/arch/arm/include/asm/mm.h
> +++ b/xen/arch/arm/include/asm/mm.h
> @@ -203,12 +203,17 @@ extern unsigned long frametable_base_pdx;
>   
>   #define PDX_GROUP_SHIFT SECOND_SHIFT
>   
> +#define virt_to_reloc_virt(virt) \
> +    (((vaddr_t)virt) - XEN_VIRT_START + BOOT_RELOC_VIRT_START)
> +
>   /* Boot-time pagetable setup */
> -extern void setup_pagetables(unsigned long boot_phys_offset);
> +extern void setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr);
>   /* Map FDT in boot pagetable */
>   extern void *early_fdt_map(paddr_t fdt_paddr);
>   /* Remove early mappings */
>   extern void remove_early_mappings(void);
> +/* Remove early LLC coloring mappings */
> +extern void remove_llc_coloring_mappings(void);
>   /* Prepare the memory subystem to bring-up the given secondary CPU */
>   extern int prepare_secondary_mm(int cpu);
>   /* Map a frame table to cover physical addresses ps through pe */
> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> index 99ea69ad39..f434efc45b 100644
> --- a/xen/arch/arm/llc-coloring.c
> +++ b/xen/arch/arm/llc-coloring.c
> @@ -14,6 +14,7 @@
>   #include <xen/llc-coloring.h>
>   #include <xen/param.h>
>   #include <xen/types.h>
> +#include <xen/vmap.h>
>   
>   #include <asm/processor.h>
>   #include <asm/sysregs.h>
> @@ -38,6 +39,7 @@ static unsigned int __ro_after_init xen_num_colors;
>   
>   #define mfn_color_mask              (nr_colors - 1)
>   #define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
> +#define mfn_set_color(mfn, color)   ((mfn_x(mfn) & ~mfn_color_mask) | (color))
>   
>   /*
>    * Parse the coloring configuration given in the buf string, following the
> @@ -354,6 +356,48 @@ unsigned int get_nr_llc_colors(void)
>       return nr_colors;
>   }
>   
> +paddr_t xen_colored_map_size(paddr_t size)
> +{
> +    return ROUNDUP(size * nr_colors, XEN_PADDR_ALIGN);
> +}
> + > +mfn_t xen_colored_mfn(mfn_t mfn)

Is this going to be used outside of boot? If not, then please add 
__init. If yes, then can you point me where?

> +{
> +    unsigned int i, color = mfn_to_color(mfn);
> +
> +    for( i = 0; i < xen_num_colors; i++ )
> +    {
> +        if ( color == xen_colors[i] )
> +            return mfn;
> +        else if ( color < xen_colors[i] )
> +            return mfn_set_color(mfn, xen_colors[i]);
> +    }
> +
> +    /* Jump to next color space (nr_colors mfns) and use the first color */
> +    return mfn_set_color(mfn_add(mfn, nr_colors), xen_colors[0]);
> +}
> +
> +void *xen_remap_colored(mfn_t xen_mfn, paddr_t xen_size)

I think this function can be __init.

> +{
> +    unsigned int i;
> +    void *xenmap;
> +    mfn_t *xen_colored_mfns;
> +
> +    xen_colored_mfns = xmalloc_array(mfn_t, xen_size >> PAGE_SHIFT);
> +    if ( !xen_colored_mfns )
> +        panic("Can't allocate LLC colored MFNs\n");
Let's try to limit the number of panic(). In this case, I think you 
should return NULL and let the caller decide.

> +
> +    for_each_xen_colored_mfn( xen_mfn, i )
> +    {
> +        xen_colored_mfns[i] = xen_mfn;
> +    }
> +
> +    xenmap = vmap(xen_colored_mfns, xen_size >> PAGE_SHIFT);
> +    xfree(xen_colored_mfns);
> +
> +    return xenmap;
> +}
> +
>   /*
>    * Local variables:
>    * mode: C
> diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
> index 37b6d230ad..66b674eeab 100644
> --- a/xen/arch/arm/mmu/setup.c
> +++ b/xen/arch/arm/mmu/setup.c
> @@ -7,6 +7,7 @@
>   
>   #include <xen/init.h>
>   #include <xen/libfdt/libfdt.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/sizes.h>
>   #include <xen/vmap.h>
>   
> @@ -39,6 +40,10 @@ DEFINE_PER_CPU(lpae_t *, xen_pgtable);
>   static DEFINE_PAGE_TABLE(cpu0_pgtable);
>   #endif
>   
> +#ifdef CONFIG_LLC_COLORING
> +static DEFINE_PAGE_TABLE(xen_colored_temp);
> +#endif

Does this actually need to be static? And if yes, then is it necessary 
to be kept the boot as completed?

Also, this is not going to be enough to cover Xen. See above.


> +
>   /* Common pagetable leaves */
>   /* Second level page table used to cover Xen virtual address space */
>   static DEFINE_PAGE_TABLE(xen_second);
> @@ -130,7 +135,12 @@ static void __init __maybe_unused build_assertions(void)
>   
>   lpae_t __init pte_of_xenaddr(vaddr_t va)
>   {
> -    paddr_t ma = va + phys_offset;
> +    paddr_t ma;
> +
> +    if ( llc_coloring_enabled )
> +        ma = virt_to_maddr(virt_to_reloc_virt(va));
> +    else
> +        ma = va + phys_offset;
>   
>       return mfn_to_xen_entry(maddr_to_mfn(ma), MT_NORMAL);
>   }
> @@ -216,11 +226,55 @@ static void xen_pt_enforce_wnx(void)
>       flush_xen_tlb_local();
>   }
>   
> +#ifdef CONFIG_LLC_COLORING
> +static void __init create_llc_coloring_mappings(paddr_t xen_paddr)
> +{
> +    lpae_t pte;
> +    unsigned int i;
> +    mfn_t mfn = maddr_to_mfn(xen_paddr);
> +
> +    for_each_xen_colored_mfn( mfn, i )
> +    {
> +        pte = mfn_to_xen_entry(mfn, MT_NORMAL);
> +        pte.pt.table = 1; /* level 3 mappings always have this bit set */
> +        xen_colored_temp[i] = pte;
> +    }
> +
> +    pte = mfn_to_xen_entry(virt_to_mfn(xen_colored_temp), MT_NORMAL);
> +    pte.pt.table = 1;
> +    write_pte(&boot_second[second_table_offset(BOOT_RELOC_VIRT_START)], pte);
> +}
> +
> +void __init remove_llc_coloring_mappings(void)
> +{
> +    int rc;
> +
> +    /* destroy the _PAGE_BLOCK mapping */
> +    rc = modify_xen_mappings(BOOT_RELOC_VIRT_START,
> +                             BOOT_RELOC_VIRT_START + SZ_2M,

See above, Xen can now be bigger than 2MB. The limit is 8MB and could 
change in the future.

> +                             _PAGE_BLOCK);
> +    BUG_ON(rc);
> +}
> +#else
> +static void __init create_llc_coloring_mappings(paddr_t xen_paddr) {}
> +void __init remove_llc_coloring_mappings(void) {}

Both should never be called when !CONFIG_LCC_COLORING, correct? If so, 
then please add ASSERT_UNREACHABLE() in their body.

> +#endif /* CONFIG_LLC_COLORING */
> +
>   /*
> - * Boot-time pagetable setup.
> + * Boot-time pagetable setup with coloring support
>    * Changes here may need matching changes in head.S
> + *
> + * The coloring support consists of:
> + * - Create a temporary colored mapping that conforms to Xen color selection.
> + * - pte_of_xenaddr takes care of translating the virtual addresses to the
> + *   new colored physical space and the returns the pte, so that the page table
> + *   initialization can remain the same.
> + * - Copy Xen to the new colored physical space by exploiting the temporary
> + *   mapping.
> + * - Update TTBR0_EL2 with the new root page table address.
>    */
> -void __init setup_pagetables(unsigned long boot_phys_offset)
> +
> +void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
>   {
>       uint64_t ttbr;
>       lpae_t pte, *p;
> @@ -228,6 +282,9 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
>   
>       phys_offset = boot_phys_offset;
>   
> +    if ( llc_coloring_enabled )
> +        create_llc_coloring_mappings(xen_paddr);
> +
>       arch_setup_page_tables();
>   
>   #ifdef CONFIG_ARM_64
> @@ -281,10 +338,13 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
>       pte.pt.table = 1;
>       xen_second[second_table_offset(FIXMAP_ADDR(0))] = pte;
>   
> +    if ( llc_coloring_enabled )
> +        ttbr = virt_to_maddr(virt_to_reloc_virt(xen_pgtable));

xen_pgtable is only valid for Arm64. But rather than ifdef-ing. I would 
consder to move...

> +    else
>   #ifdef CONFIG_ARM_64
> -    ttbr = (uintptr_t) xen_pgtable + phys_offset;
> +        ttbr = (uintptr_t) xen_pgtable + phys_offset;
>   #else
> -    ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
> +        ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
>   #endif
>   
>       switch_ttbr(ttbr);
> @@ -294,6 +354,18 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
>   #ifdef CONFIG_ARM_32
>       per_cpu(xen_pgtable, 0) = cpu0_pgtable;
>   #endif

.. these two lines before hand so you can use THIS_CPU_PGTABLE.

> +
> +    /*

Coding style: It looks like you have one space too much before /*.

> +    * Keep original Xen memory mapped because secondary CPUs still point to it
> +    * and a few variables needs to be accessed by the master CPU in order to
> +    * let them boot. This mapping will also replace the one created at the
> +    * beginning of setup_pagetables.
> +    */

It feels wrong to keep the full Xen (even temporarily) just for CPU 
bring-up. But I don't think this is necessary. The secondary CPUs 
outside of code in head.S, secondary CPU should only need to access to 
init_ttbr and smp_cpu_up.

The last one is already questionable because the CPU should never wait 
in Xen. Instead they would be held somewhere else. But that's separate 
issue.

Anyway, if you move init_ttbr and smp_cpu_up in the identity mapped 
area, then you will not need to copy of Xen. Instead, secondary CPUs 
should be able to jump to the new Xen directly.

This will also avoid to spread cache coloring changes in every Xen 
components.

> +    if ( llc_coloring_enabled )
> +        map_pages_to_xen(BOOT_RELOC_VIRT_START,
> +                         maddr_to_mfn(XEN_VIRT_START + phys_offset),
> +                         SZ_2M >> PAGE_SHIFT, PAGE_HYPERVISOR_RW | _PAGE_BLOCK);
> +
>   }
>   
>   void *__init arch_vmap_virt_end(void)
> diff --git a/xen/arch/arm/mmu/smpboot.c b/xen/arch/arm/mmu/smpboot.c
> index b6fc0aae07..a69183ec88 100644
> --- a/xen/arch/arm/mmu/smpboot.c
> +++ b/xen/arch/arm/mmu/smpboot.c
> @@ -6,6 +6,7 @@
>    */
>   
>   #include <xen/domain_page.h>
> +#include <xen/llc-coloring.h>
>   
>   #include <asm/setup.h>
>   
> @@ -71,14 +72,20 @@ static void clear_boot_pagetables(void)
>   #ifdef CONFIG_ARM_64
>   int prepare_secondary_mm(int cpu)
>   {
> +    uint64_t *init_ttbr_addr = &init_ttbr;
> +
>       clear_boot_pagetables();
>   
> +    if ( llc_coloring_enabled )
> +        init_ttbr_addr = (uint64_t *)virt_to_reloc_virt(&init_ttbr);
> +
>       /*
>        * Set init_ttbr for this CPU coming up. All CPUs share a single setof
>        * pagetables, but rewrite it each time for consistency with 32 bit.
>        */
> -    init_ttbr = virt_to_maddr(xen_pgtable);
> -    clean_dcache(init_ttbr);
> +    *init_ttbr_addr = virt_to_maddr(xen_pgtable);
> +    clean_dcache(*init_ttbr_addr);
> +
>       return 0;
>   }
>   #else
> diff --git a/xen/arch/arm/psci.c b/xen/arch/arm/psci.c
> index 695d2fa1f1..23e298c477 100644
> --- a/xen/arch/arm/psci.c
> +++ b/xen/arch/arm/psci.c
> @@ -11,6 +11,7 @@
>   
>   #include <xen/types.h>
>   #include <xen/init.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/mm.h>
>   #include <xen/smp.h>
>   #include <asm/cpufeature.h>
> @@ -39,9 +40,13 @@ static uint32_t psci_cpu_on_nr;
>   int call_psci_cpu_on(int cpu)
>   {
>       struct arm_smccc_res res;
> +    vaddr_t init_secondary_addr = (vaddr_t)init_secondary;
>   
> -    arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu), __pa(init_secondary),
> -                  &res);
> +    if ( llc_coloring_enabled )
> +        init_secondary_addr = virt_to_reloc_virt(init_secondary);
> +
> +    arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu),
> +                  __pa(init_secondary_addr), &res);
>   
>       return PSCI_RET(res);
>   }

[...]

> +#ifdef CONFIG_LLC_COLORING
> +/**
> + * get_xen_paddr - get physical address to relocate Xen to
> + *
> + * Xen is relocated to as near to the top of RAM as possible and
> + * aligned to a XEN_PADDR_ALIGN boundary.
> + */
> +static paddr_t __init get_xen_paddr(uint32_t xen_size)
> +{
> +    struct meminfo *mi = &bootinfo.mem;
> +    paddr_t min_size;
> +    paddr_t paddr = 0;
> +    int i;
> +
> +    min_size = (xen_size + (XEN_PADDR_ALIGN-1)) & ~(XEN_PADDR_ALIGN-1);
> +
> +    /* Find the highest bank with enough space. */
> +    for ( i = 0; i < mi->nr_banks; i++ )
> +    {
> +        const struct membank *bank = &mi->bank[i];
> +        paddr_t s, e;
> +
> +        if ( bank->size >= min_size )
> +        {
> +            e = consider_modules(bank->start, bank->start + bank->size,
> +                                 min_size, XEN_PADDR_ALIGN, 0);
> +            if ( !e )
> +                continue;
> +
> +#ifdef CONFIG_ARM_32
> +            /* Xen must be under 4GB */
> +            if ( e > 0x100000000ULL )
> +                e = 0x100000000ULL;
> +            if ( e < bank->start )
> +                continue;
> +#endif
> +
> +            s = e - min_size;
> +
> +            if ( s > paddr )
> +                paddr = s;
> +        }
> +    }
> +
> +    if ( !paddr )
> +        panic("Not enough memory to relocate Xen\n");
> +
> +    printk("Placing Xen at 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
> +           paddr, paddr + min_size);
> +
> +    return paddr;
> +}
> +#else
> +static paddr_t __init get_xen_paddr(uint32_t xen_size) { return 0; }
> +#endif
> +
>   void __init init_pdx(void)
>   {
>       paddr_t bank_start, bank_size, bank_end;
> @@ -724,8 +874,6 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
>       /* Initialize traps early allow us to get backtrace when an error occurred */
>       init_traps();
>   
> -    setup_pagetables(boot_phys_offset);
> -
>       smp_clear_cpu_maps();
>   
>       device_tree_flattened = early_fdt_map(fdt_paddr);
> @@ -751,8 +899,13 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
>       {
>           if ( !llc_coloring_init() )
>               panic("Xen LLC coloring support: setup failed\n");
> +        xen_bootmodule->size = xen_colored_map_size(_end - _start);
> +        xen_bootmodule->start = get_xen_paddr(xen_bootmodule->size);

As you update xen_bootmodule, wouldn't this mean that the non-relocated 
Xen would could be passed to the bootallocator?

>       } >
> +    setup_pagetables(boot_phys_offset, xen_bootmodule->start);

The new placement of setup_pagetables() deserve an explanation.

> +    device_tree_flattened = early_fdt_map(fdt_paddr);
> +
>       setup_mm();
>   
>       /* Parse the ACPI tables for possible boot-time configuration */
> @@ -867,6 +1020,14 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
>   
>       setup_virt_paging();
>   
> +    /*
> +     * The removal is done earlier than discard_initial_modules beacuse the

Typo: s/beacuase/because/

> +     * livepatch init uses a virtual address equal to BOOT_RELOC_VIRT_START.
> +     * Remove LLC coloring mappings to expose a clear state to the livepatch
> +     * module.
> +     */
> +    if ( llc_coloring_enabled )
> +        remove_llc_coloring_mappings();
>       do_initcalls();
>   
>       /*
> diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
> index 7110bc11fc..7ed7357d58 100644
> --- a/xen/arch/arm/smpboot.c
> +++ b/xen/arch/arm/smpboot.c
> @@ -14,6 +14,7 @@
>   #include <xen/domain_page.h>
>   #include <xen/errno.h>
>   #include <xen/init.h>
> +#include <xen/llc-coloring.h>
>   #include <xen/mm.h>
>   #include <xen/param.h>
>   #include <xen/sched.h>
> @@ -444,6 +445,7 @@ int __cpu_up(unsigned int cpu)
>   {
>       int rc;
>       s_time_t deadline;
> +    unsigned long *smp_up_cpu_addr = &smp_up_cpu;
>   
>       printk("Bringing up CPU%d\n", cpu);
>   
> @@ -459,9 +461,12 @@ int __cpu_up(unsigned int cpu)
>       /* Tell the remote CPU what its logical CPU ID is. */
>       init_data.cpuid = cpu;
>   
> +    if ( llc_coloring_enabled )
> +        smp_up_cpu_addr = (unsigned long *)virt_to_reloc_virt(&smp_up_cpu);
> +
>       /* Open the gate for this CPU */
> -    smp_up_cpu = cpu_logical_map(cpu);
> -    clean_dcache(smp_up_cpu);
> +    *smp_up_cpu_addr = cpu_logical_map(cpu);
> +    clean_dcache(*smp_up_cpu_addr);
>   
>       rc = arch_cpu_up(cpu);
>   

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 12/13] xen/arm: add Xen cache colors command line parameter
  2024-01-05 18:00   ` Julien Grall
@ 2024-01-05 23:09     ` Stefano Stabellini
  2024-01-25 18:28       ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Stefano Stabellini @ 2024-01-05 23:09 UTC (permalink / raw)
  To: Julien Grall
  Cc: Carlo Nonato, xen-devel, Luca Miccio, Andrew Cooper,
	George Dunlap, Jan Beulich, Stefano Stabellini, Wei Liu,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Marco Solieri

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

On Fri, 5 Jan 2024, Julien Grall wrote:
> Hi,
> 
> On 02/01/2024 09:51, Carlo Nonato wrote:
> > From: Luca Miccio <lucmiccio@gmail.com>
> > 
> > This commit adds a new command line parameter to configure Xen cache colors.
> > These colors can be dumped with the cache coloring info debug-key.
> > 
> > By default, Xen uses the first color.
> > Benchmarking the VM interrupt response time provides an estimation of
> > LLC usage by Xen's most latency-critical runtime task. Results on Arm
> > Cortex-A53 on Xilinx Zynq UltraScale+ XCZU9EG show that one color, which
> > reserves 64 KiB of L2, is enough to attain best responsiveness.
> 
> Would you be able to share some numbers? This is quite helpful if in the
> future we need to revise the default.

Here are the numbers for Xen 1 color vs Xen 2 colors.

We are measuring IRQ lantecy using a baremetal app (a unikernel) that
has 0.5 us latency on native without interference.

Running the same application on Xen with 3 interference agents (3 other
VMs that keep thrashing the cache):

- Xen 1 color latency:  3.1 us
- Xen 2 color2 latency: 3.1 us

[-- Attachment #2: Type: application/pdf, Size: 516799 bytes --]

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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-02  9:51 ` [PATCH v5 04/13] xen: extend domctl interface for cache coloring Carlo Nonato
  2024-01-05 17:26   ` Julien Grall
@ 2024-01-08  8:43   ` Jan Beulich
  2024-01-08 11:22     ` Carlo Nonato
  1 sibling, 1 reply; 90+ messages in thread
From: Jan Beulich @ 2024-01-08  8:43 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, xen-devel

On 02.01.2024 10:51, Carlo Nonato wrote:
> --- a/xen/arch/arm/llc-coloring.c
> +++ b/xen/arch/arm/llc-coloring.c
> @@ -9,6 +9,7 @@
>   *    Carlo Nonato <carlo.nonato@minervasys.tech>
>   */
>  #include <xen/errno.h>
> +#include <xen/guest_access.h>
>  #include <xen/keyhandler.h>
>  #include <xen/llc-coloring.h>
>  #include <xen/param.h>
> @@ -278,6 +279,22 @@ int dom0_set_llc_colors(struct domain *d)
>      return domain_check_colors(d);
>  }
>  
> +int domain_set_llc_colors_domctl(struct domain *d,
> +                                 const struct xen_domctl_set_llc_colors *config)
> +{
> +    if ( d->num_llc_colors )
> +        return -EEXIST;
> +
> +    if ( domain_alloc_colors(d, config->num_llc_colors) )
> +        return -ENOMEM;
> +
> +    if ( copy_from_guest(d->llc_colors, config->llc_colors,
> +                         config->num_llc_colors) )
> +        return -EFAULT;
> +
> +    return domain_check_colors(d);
> +}

What part of this is Arm-specific? I ask in particular because while you
place this in an Arm-specific source file, ...

> --- a/xen/common/domctl.c
> +++ b/xen/common/domctl.c
> @@ -8,6 +8,7 @@
>  
>  #include <xen/types.h>
>  #include <xen/lib.h>
> +#include <xen/llc-coloring.h>
>  #include <xen/err.h>
>  #include <xen/mm.h>
>  #include <xen/sched.h>
> @@ -858,6 +859,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>                  __HYPERVISOR_domctl, "h", u_domctl);
>          break;
>  
> +    case XEN_DOMCTL_set_llc_colors:
> +        if ( !llc_coloring_enabled )
> +            break;
> +
> +        ret = domain_set_llc_colors_domctl(d, &op->u.set_llc_colors);
> +        if ( ret == -EEXIST )
> +            printk(XENLOG_ERR
> +                   "Can't set LLC colors on an already created domain\n");
> +        break;
> +
>      default:
>          ret = arch_do_domctl(op, d, u_domctl);
>          break;

... you don't handle the new domctl in Arm's arch_do_domctl().

> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -21,7 +21,7 @@
>  #include "hvm/save.h"
>  #include "memory.h"
>  
> -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000016
> +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000017

There's no need for such a bump when ...

> @@ -1190,6 +1190,12 @@ struct xen_domctl_vmtrace_op {
>  typedef struct xen_domctl_vmtrace_op xen_domctl_vmtrace_op_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_domctl_vmtrace_op_t);
>  
> +struct xen_domctl_set_llc_colors {
> +    /* IN LLC coloring parameters */
> +    unsigned int num_llc_colors;
> +    XEN_GUEST_HANDLE_64(uint) llc_colors;
> +};
> +
>  struct xen_domctl {
>      uint32_t cmd;
>  #define XEN_DOMCTL_createdomain                   1
> @@ -1277,6 +1283,7 @@ struct xen_domctl {
>  #define XEN_DOMCTL_vmtrace_op                    84
>  #define XEN_DOMCTL_get_paging_mempool_size       85
>  #define XEN_DOMCTL_set_paging_mempool_size       86
> +#define XEN_DOMCTL_set_llc_colors                87
>  #define XEN_DOMCTL_gdbsx_guestmemio            1000
>  #define XEN_DOMCTL_gdbsx_pausevcpu             1001
>  #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
> @@ -1339,6 +1346,7 @@ struct xen_domctl {
>          struct xen_domctl_vuart_op          vuart_op;
>          struct xen_domctl_vmtrace_op        vmtrace_op;
>          struct xen_domctl_paging_mempool    paging_mempool;
> +        struct xen_domctl_set_llc_colors    set_llc_colors;
>          uint8_t                             pad[128];
>      } u;
>  };

... all you do is add a new domctl.

As to the new struct - you'll want to use uint<N>_t there, not
unsigned int.

Jan


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

* Re: [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support
  2024-01-05 17:50       ` Julien Grall
@ 2024-01-08 10:06         ` Carlo Nonato
  2024-01-08 10:25           ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 10:06 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien,

On Fri, Jan 5, 2024 at 6:50 PM Julien Grall <julien@xen.org> wrote:
>
>
>
> On 05/01/2024 16:52, Carlo Nonato wrote:
> > Hi Julien,
> >
> > On Thu, Jan 4, 2024 at 8:54 PM Julien Grall <julien@xen.org> wrote:
> >>
> >> Hi Carlo,
> >>
> >> On 02/01/2024 09:51, Carlo Nonato wrote:
> >>> This commit allows the user to set the cache coloring configuration for
> >>> Dom0 via a command line parameter.
> >>> Since cache coloring and static memory are incompatible, direct mapping
> >>> Dom0 isn't possible when coloring is enabled.
> >>>
> >>> A common configuration syntax for cache colors is also introduced.
> >>>
> >>> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> >>>
> >>> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> >>> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> >>> ---
> >>> v5:
> >>> - Carlo Nonato as the new author
> >>> - moved dom0 colors parsing (parse_colors()) in this patch
> >>> - added dom0_set_llc_colors() to set dom0 colors after creation
> >>> - moved color allocation and checking in this patch
> >>> - error handling when allocating color arrays
> >>> - FIXME: copy pasted allocate_memory() cause it got moved
> >>> v4:
> >>> - dom0 colors are dynamically allocated as for any other domain
> >>>     (colors are duplicated in dom0_colors and in the new array, but logic
> >>>     is simpler)
> >>> ---
> >>>    docs/misc/arm/cache-coloring.rst        |  29 ++++++
> >>>    docs/misc/xen-command-line.pandoc       |   9 ++
> >>>    xen/arch/arm/domain_build.c             |  60 ++++++++++-
> >>>    xen/arch/arm/include/asm/llc-coloring.h |   1 +
> >>>    xen/arch/arm/llc-coloring.c             | 128 ++++++++++++++++++++++++
> >>>    5 files changed, 224 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> >>> index eabf8f5d1b..acf82c3df8 100644
> >>> --- a/docs/misc/arm/cache-coloring.rst
> >>> +++ b/docs/misc/arm/cache-coloring.rst
> >>> @@ -84,6 +84,35 @@ More specific documentation is available at `docs/misc/xen-command-line.pandoc`.
> >>>    +----------------------+-------------------------------+
> >>>    | ``llc-way-size``     | set the LLC way size          |
> >>>    +----------------------+-------------------------------+
> >>> +| ``dom0-llc-colors``  | Dom0 color configuration      |
> >>> ++----------------------+-------------------------------+
> >>> +
> >>> +Colors selection format
> >>> +***********************
> >>> +
> >>> +Regardless of the memory pool that has to be colored (Xen, Dom0/DomUs),
> >>> +the color selection can be expressed using the same syntax. In particular a
> >>> +comma-separated list of colors or ranges of colors is used.
> >>> +Ranges are hyphen-separated intervals (such as `0-4`) and are inclusive on both
> >>> +sides.
> >>> +
> >>> +Note that:
> >>> +
> >>> +- no spaces are allowed between values.
> >>> +- no overlapping ranges or duplicated colors are allowed.
> >>> +- values must be written in ascending order.
> >>> +
> >>> +Examples:
> >>> +
> >>> ++-------------------+-----------------------------+
> >>> +| **Configuration** | **Actual selection**        |
> >>> ++-------------------+-----------------------------+
> >>> +| 1-2,5-8           | [1, 2, 5, 6, 7, 8]          |
> >>> ++-------------------+-----------------------------+
> >>> +| 4-8,10,11,12      | [4, 5, 6, 7, 8, 10, 11, 12] |
> >>> ++-------------------+-----------------------------+
> >>> +| 0                 | [0]                         |
> >>> ++-------------------+-----------------------------+
> >>>
> >>>    Known issues and limitations
> >>>    ****************************
> >>> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> >>> index 22d2d5b6cf..51f6adf035 100644
> >>> --- a/docs/misc/xen-command-line.pandoc
> >>> +++ b/docs/misc/xen-command-line.pandoc
> >>> @@ -963,6 +963,15 @@ Controls for the dom0 IOMMU setup.
> >>>
> >>>    Specify a list of IO ports to be excluded from dom0 access.
> >>>
> >>> +### dom0-llc-colors (arm64)
> >>> +> `= List of [ <integer> | <integer>-<integer> ]`
> >>
> >> Someone reading only xen-command-line.pandoc would not know how each
> >> item of the list is separated. Can this be clarified?
> >
> > Isn't it already known that the list is comma separated? It's written at the
> > beginning of this file for the "List" type.
> > I can also point to cache-coloring documentation if needed.
>
> Ah I forgot that part. Please ignore this comment.
>
> [...]
>
> >>> +                return -EINVAL;
> >>> +            for ( color = start; color <= end; color++ )
> >>> +                colors[(*num_colors)++] = color;
> >>> +        }
> >>> +        else
> >>> +            s++;
> >>> +    }
> >>> +
> >>> +    return *s ? -EINVAL : 0;
> >>> +}
> >>> +
> >>> +static int __init parse_dom0_colors(const char *s)
> >>> +{
> >>> +    return parse_color_config(s, dom0_colors, &dom0_num_colors);
> >>> +}
> >>> +custom_param("dom0-llc-colors", parse_dom0_colors);
> >>> +
> >>>    /* Return the LLC way size by probing the hardware */
> >>>    static unsigned int __init get_llc_way_size(void)
> >>>    {
> >>> @@ -102,6 +159,28 @@ static void dump_coloring_info(unsigned char key)
> >>>        printk("Number of LLC colors supported: %u\n", nr_colors);
> >>>    }
> >>>
> >>> +static bool check_colors(unsigned int *colors, unsigned int num_colors)
> >>> +{
> >>> +    unsigned int i;
> >>> +
> >>> +    if ( num_colors > nr_colors )
> >>> +    {
> >>> +        printk(XENLOG_ERR "Number of LLC colors requested > %u\n", nr_colors);
> >>> +        return false;
> >>> +    }
> >>> +
> >>> +    for ( i = 0; i < num_colors; i++ )
> >>> +    {
> >>> +        if ( colors[i] >= nr_colors )
> >>> +        {
> >>> +            printk(XENLOG_ERR "LLC color %u >= %u\n", colors[i], nr_colors);
> >>> +            return false;
> >>> +        }
> >>> +    }
> >>> +
> >>> +    return true;
> >>> +}
> >>> +
> >>>    bool __init llc_coloring_init(void)
> >>>    {
> >>>        if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
> >>> @@ -150,6 +229,55 @@ void domain_dump_llc_colors(struct domain *d)
> >>>        print_colors(d->llc_colors, d->num_llc_colors);
> >>>    }
> >>>
> >>> +static int domain_alloc_colors(struct domain *d, unsigned int num_colors)
> >>> +{
> >>> +    d->num_llc_colors = num_colors;
> >>
> >> Shouldn't this be set *only* after the array was allocated?
> >
> > Yes, it works also like I did, but it's cleaner like you said.
>
> Actually, looking at the rest of the code. I think  d->num_llc_colors
> should be set outside of domain_alloc_colors().
>
> One of the reason is at least in the dom0less case, you will override
> the value afterwards.

In that case I need to allocate the array before parsing the string.
I allocate a full array then the string is parsed and the actual size is found
at the end of this phase. Knowing the actual size would require two parsing
stages. Yes I'm wasting a bit of memory by oversizing the array here. Is it
a problem?

Thanks.

> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support
  2024-01-08 10:06         ` Carlo Nonato
@ 2024-01-08 10:25           ` Julien Grall
  2024-01-08 11:04             ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-08 10:25 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Carlo,

On 08/01/2024 10:06, Carlo Nonato wrote:
>> One of the reason is at least in the dom0less case, you will override
>> the value afterwards.
> 
> In that case I need to allocate the array before parsing the string.
> I allocate a full array then the string is parsed and the actual size is found
> at the end of this phase. Knowing the actual size would require two parsing
> stages. Yes I'm wasting a bit of memory by oversizing the array here. Is it
> a problem?

While wasting memory is indeed not nice. This wasn't the main reason of 
this comment.

The reason is that you seem to set d->num_lcc_colors will but will never 
be read before it gets overwritten. Looking again at the code, you are 
also assuming parse_colors() will always take an array of nr_colors.

It would be better if parse_colors() takes the maximum size of the array 
in parameter. This would harden the code and it makes more sense for 
domain_alloc_colors() to set d->num_lcc_colors.

Also, I just noticed you have a global variable named nr_colors and the 
function parse_colors() takes an argument called *num_colors. This is 
quite confusing, can we have better name?

Maybe rename nr_colors to nr_global_colors and and num_colors to 
nr_array_colors?

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-05 17:26   ` Julien Grall
@ 2024-01-08 10:27     ` Carlo Nonato
  2024-01-08 11:00       ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 10:27 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien,

On Fri, Jan 5, 2024 at 6:26 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 02/01/2024 09:51, Carlo Nonato wrote:
> > This commit updates the domctl interface to allow the user to set cache
> > coloring configurations from the toolstack.
> > It also implements the functionality for arm64.
> >
> > Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> >
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > ---
> > v5:
> > - added a new hypercall to set colors
> > - uint for the guest handle
> > v4:
> > - updated XEN_DOMCTL_INTERFACE_VERSION
> > ---
> >   xen/arch/arm/llc-coloring.c    | 17 +++++++++++++++++
> >   xen/common/domctl.c            | 11 +++++++++++
> >   xen/include/public/domctl.h    | 10 +++++++++-
> >   xen/include/xen/llc-coloring.h |  3 +++
> >   4 files changed, 40 insertions(+), 1 deletion(-)
> >
> > diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> > index 5ce58aba70..a08614ec36 100644
> > --- a/xen/arch/arm/llc-coloring.c
> > +++ b/xen/arch/arm/llc-coloring.c
> > @@ -9,6 +9,7 @@
> >    *    Carlo Nonato <carlo.nonato@minervasys.tech>
> >    */
> >   #include <xen/errno.h>
> > +#include <xen/guest_access.h>
> >   #include <xen/keyhandler.h>
> >   #include <xen/llc-coloring.h>
> >   #include <xen/param.h>
> > @@ -278,6 +279,22 @@ int dom0_set_llc_colors(struct domain *d)
> >       return domain_check_colors(d);
> >   }
> >
> > +int domain_set_llc_colors_domctl(struct domain *d,
> > +                                 const struct xen_domctl_set_llc_colors *config)
> > +{
> > +    if ( d->num_llc_colors )
> > +        return -EEXIST;
> > +
> > +    if ( domain_alloc_colors(d, config->num_llc_colors) )
>
> domain_alloc_colors() doesn't sanity check config->num_llc_colors before
> allocating the array. You want a check the size before so we would not
> try to allocate an arbitrary amount of memory.
>
> > +        return -ENOMEM;
> > +
> > +    if ( copy_from_guest(d->llc_colors, config->llc_colors,
> > +                         config->num_llc_colors) )
> > +        return -EFAULT;
> > +
> > +    return domain_check_colors(d);
> > +}
> > +
> >   /*
> >    * Local variables:
> >    * mode: C
> > diff --git a/xen/common/domctl.c b/xen/common/domctl.c
> > index f5a71ee5f7..b6867d0602 100644
> > --- a/xen/common/domctl.c
> > +++ b/xen/common/domctl.c
> > @@ -8,6 +8,7 @@
> >
> >   #include <xen/types.h>
> >   #include <xen/lib.h>
> > +#include <xen/llc-coloring.h>
> >   #include <xen/err.h>
> >   #include <xen/mm.h>
> >   #include <xen/sched.h>
> > @@ -858,6 +859,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
> >                   __HYPERVISOR_domctl, "h", u_domctl);
> >           break;
> >
> > +    case XEN_DOMCTL_set_llc_colors:
> > +        if ( !llc_coloring_enabled )
> > +            break;
> > +
> > +        ret = domain_set_llc_colors_domctl(d, &op->u.set_llc_colors);
> > +        if ( ret == -EEXIST )
> > +            printk(XENLOG_ERR
> > +                   "Can't set LLC colors on an already created domain\n");
>
> To me, the message doesn't match the check in
> domain_set_llc_colors_domctl(). But I think you want to check that no
> memory was yet allocated to the domain. Otherwise, you coloring will be
> wrong.
>
> Also, it is a bit unclear why you print a message for -EEXIST but not
> the others. In this instance, I would consider to print nothing at all.

The problem here is that we don't support recoloring. When a domain is
created it receives a coloring configuration and it can't change. If this
hypercall is called twice I have to stop the second time somehow. I'm ok
with printing nothing, but -EEXIST to me seems logical.

> > +        break;
> > +
> >       default:
> >           ret = arch_do_domctl(op, d, u_domctl);
> >           break;
> > diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> > index a33f9ec32b..2b12069294 100644
> > --- a/xen/include/public/domctl.h
> > +++ b/xen/include/public/domctl.h
> > @@ -21,7 +21,7 @@
> >   #include "hvm/save.h"
> >   #include "memory.h"
> >
> > -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000016
> > +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000017
> >
> >   /*
> >    * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
> > @@ -1190,6 +1190,12 @@ struct xen_domctl_vmtrace_op {
> >   typedef struct xen_domctl_vmtrace_op xen_domctl_vmtrace_op_t;
> >   DEFINE_XEN_GUEST_HANDLE(xen_domctl_vmtrace_op_t);
> >
> > +struct xen_domctl_set_llc_colors {
> > +    /* IN LLC coloring parameters */
> > +    unsigned int num_llc_colors;
>
> I think there will be a padding here. So can you make it explicit?
>
> > +    XEN_GUEST_HANDLE_64(uint) llc_colors;
> > +};
> > +
> >   struct xen_domctl {
> >       uint32_t cmd;
> >   #define XEN_DOMCTL_createdomain                   1
> > @@ -1277,6 +1283,7 @@ struct xen_domctl {
> >   #define XEN_DOMCTL_vmtrace_op                    84
> >   #define XEN_DOMCTL_get_paging_mempool_size       85
> >   #define XEN_DOMCTL_set_paging_mempool_size       86
> > +#define XEN_DOMCTL_set_llc_colors                87
> >   #define XEN_DOMCTL_gdbsx_guestmemio            1000
> >   #define XEN_DOMCTL_gdbsx_pausevcpu             1001
> >   #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
> > @@ -1339,6 +1346,7 @@ struct xen_domctl {
> >           struct xen_domctl_vuart_op          vuart_op;
> >           struct xen_domctl_vmtrace_op        vmtrace_op;
> >           struct xen_domctl_paging_mempool    paging_mempool;
> > +        struct xen_domctl_set_llc_colors    set_llc_colors;
> >           uint8_t                             pad[128];
> >       } u;
> >   };
> > diff --git a/xen/include/xen/llc-coloring.h b/xen/include/xen/llc-coloring.h
> > index cedd97d4b5..fa2edc8ad8 100644
> > --- a/xen/include/xen/llc-coloring.h
> > +++ b/xen/include/xen/llc-coloring.h
> > @@ -33,6 +33,9 @@ extern bool llc_coloring_enabled;
> >   void domain_llc_coloring_free(struct domain *d);
> >   void domain_dump_llc_colors(struct domain *d);
> >
> > +int domain_set_llc_colors_domctl(struct domain *d,
> > +                                 const struct xen_domctl_set_llc_colors *config);
> > +
> >   #endif /* __COLORING_H__ */
> >
> >   /*
>
> Cheers,
>
> --
> Julien Grall

Thanks.


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 10:27     ` Carlo Nonato
@ 2024-01-08 11:00       ` Julien Grall
  2024-01-08 11:19         ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-08 11:00 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Carlo,

On 08/01/2024 10:27, Carlo Nonato wrote:
> On Fri, Jan 5, 2024 at 6:26 PM Julien Grall <julien@xen.org> wrote:
>> On 02/01/2024 09:51, Carlo Nonato wrote:
>>> This commit updates the domctl interface to allow the user to set cache
>>> coloring configurations from the toolstack.
>>> It also implements the functionality for arm64.
>>>
>>> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
>>>
>>> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
>>> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
>>> ---
>>> v5:
>>> - added a new hypercall to set colors
>>> - uint for the guest handle
>>> v4:
>>> - updated XEN_DOMCTL_INTERFACE_VERSION
>>> ---
>>>    xen/arch/arm/llc-coloring.c    | 17 +++++++++++++++++
>>>    xen/common/domctl.c            | 11 +++++++++++
>>>    xen/include/public/domctl.h    | 10 +++++++++-
>>>    xen/include/xen/llc-coloring.h |  3 +++
>>>    4 files changed, 40 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
>>> index 5ce58aba70..a08614ec36 100644
>>> --- a/xen/arch/arm/llc-coloring.c
>>> +++ b/xen/arch/arm/llc-coloring.c
>>> @@ -9,6 +9,7 @@
>>>     *    Carlo Nonato <carlo.nonato@minervasys.tech>
>>>     */
>>>    #include <xen/errno.h>
>>> +#include <xen/guest_access.h>
>>>    #include <xen/keyhandler.h>
>>>    #include <xen/llc-coloring.h>
>>>    #include <xen/param.h>
>>> @@ -278,6 +279,22 @@ int dom0_set_llc_colors(struct domain *d)
>>>        return domain_check_colors(d);
>>>    }
>>>
>>> +int domain_set_llc_colors_domctl(struct domain *d,
>>> +                                 const struct xen_domctl_set_llc_colors *config)
>>> +{
>>> +    if ( d->num_llc_colors )
>>> +        return -EEXIST;
>>> +
>>> +    if ( domain_alloc_colors(d, config->num_llc_colors) )
>>
>> domain_alloc_colors() doesn't sanity check config->num_llc_colors before
>> allocating the array. You want a check the size before so we would not
>> try to allocate an arbitrary amount of memory.
>>
>>> +        return -ENOMEM;
>>> +
>>> +    if ( copy_from_guest(d->llc_colors, config->llc_colors,
>>> +                         config->num_llc_colors) )
>>> +        return -EFAULT;
>>> +
>>> +    return domain_check_colors(d);
>>> +}
>>> +
>>>    /*
>>>     * Local variables:
>>>     * mode: C
>>> diff --git a/xen/common/domctl.c b/xen/common/domctl.c
>>> index f5a71ee5f7..b6867d0602 100644
>>> --- a/xen/common/domctl.c
>>> +++ b/xen/common/domctl.c
>>> @@ -8,6 +8,7 @@
>>>
>>>    #include <xen/types.h>
>>>    #include <xen/lib.h>
>>> +#include <xen/llc-coloring.h>
>>>    #include <xen/err.h>
>>>    #include <xen/mm.h>
>>>    #include <xen/sched.h>
>>> @@ -858,6 +859,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>>>                    __HYPERVISOR_domctl, "h", u_domctl);
>>>            break;
>>>
>>> +    case XEN_DOMCTL_set_llc_colors:
>>> +        if ( !llc_coloring_enabled )
>>> +            break;
>>> +
>>> +        ret = domain_set_llc_colors_domctl(d, &op->u.set_llc_colors);
>>> +        if ( ret == -EEXIST )
>>> +            printk(XENLOG_ERR
>>> +                   "Can't set LLC colors on an already created domain\n");
>>
>> To me, the message doesn't match the check in
>> domain_set_llc_colors_domctl(). But I think you want to check that no
>> memory was yet allocated to the domain. Otherwise, you coloring will be
>> wrong.
>>
>> Also, it is a bit unclear why you print a message for -EEXIST but not
>> the others. In this instance, I would consider to print nothing at all.
> 
> The problem here is that we don't support recoloring. When a domain is
> created it receives a coloring configuration and it can't change. If this
> hypercall is called twice I have to stop the second time somehow.
Looking at your check what you prevent is a toolstack updating the array 
twice. But that would be ok (/!\ I am not saying we should allow it) so 
long no memory has been allocated to the domain.

But I also consider we would re-color once we started to allocate memory 
for the domain (either RAM or P2M). This seems to be missed out in your 
check.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support
  2024-01-08 10:25           ` Julien Grall
@ 2024-01-08 11:04             ` Carlo Nonato
  2024-01-08 11:44               ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 11:04 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien,

On Mon, Jan 8, 2024 at 11:25 AM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 08/01/2024 10:06, Carlo Nonato wrote:
> >> One of the reason is at least in the dom0less case, you will override
> >> the value afterwards.
> >
> > In that case I need to allocate the array before parsing the string.
> > I allocate a full array then the string is parsed and the actual size is found
> > at the end of this phase. Knowing the actual size would require two parsing
> > stages. Yes I'm wasting a bit of memory by oversizing the array here. Is it
> > a problem?
>
> While wasting memory is indeed not nice. This wasn't the main reason of
> this comment.
>
> The reason is that you seem to set d->num_lcc_colors will but will never
> be read before it gets overwritten. Looking again at the code, you are
> also assuming parse_colors() will always take an array of nr_colors.

Ok, I think I understood, but that happens only in dom0less case because
d->num_llc_colors is overwritten after parsing. In other cases it's ok to set
it there. Anyway I can move the assignment out of the function if that is
clearer.

> It would be better if parse_colors() takes the maximum size of the array
> in parameter. This would harden the code and it makes more sense for
> domain_alloc_colors() to set d->num_lcc_colors.

I don't understand this. parse_colors() must take only arrays of nr_colors
size (the global, maximum number of colors), otherwise the parsed string
config could exceed the array size. Since we don't know in advance the real
size before parsing, I think it's better to pass only arrays that are already
allocated with the maximum size.
Doing as you said I would still pass nr_colors as the maximum size, but that
would be strange since the global would still be accessible.
If domain_alloc_colors() setting d->num_llc_colors is so confusing,
I will just move the assignment after the function call.

> Also, I just noticed you have a global variable named nr_colors and the
> function parse_colors() takes an argument called *num_colors. This is
> quite confusing, can we have better name?
>
> Maybe rename nr_colors to nr_global_colors and and num_colors to
> nr_array_colors?

I agree with the fact that naming is confusing. I would opt for max_nr_colors
for the global.

Thanks.

> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 11:00       ` Julien Grall
@ 2024-01-08 11:19         ` Carlo Nonato
  2024-01-08 11:35           ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 11:19 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien,

On Mon, Jan 8, 2024 at 12:01 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 08/01/2024 10:27, Carlo Nonato wrote:
> > On Fri, Jan 5, 2024 at 6:26 PM Julien Grall <julien@xen.org> wrote:
> >> On 02/01/2024 09:51, Carlo Nonato wrote:
> >>> This commit updates the domctl interface to allow the user to set cache
> >>> coloring configurations from the toolstack.
> >>> It also implements the functionality for arm64.
> >>>
> >>> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> >>>
> >>> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> >>> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> >>> ---
> >>> v5:
> >>> - added a new hypercall to set colors
> >>> - uint for the guest handle
> >>> v4:
> >>> - updated XEN_DOMCTL_INTERFACE_VERSION
> >>> ---
> >>>    xen/arch/arm/llc-coloring.c    | 17 +++++++++++++++++
> >>>    xen/common/domctl.c            | 11 +++++++++++
> >>>    xen/include/public/domctl.h    | 10 +++++++++-
> >>>    xen/include/xen/llc-coloring.h |  3 +++
> >>>    4 files changed, 40 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> >>> index 5ce58aba70..a08614ec36 100644
> >>> --- a/xen/arch/arm/llc-coloring.c
> >>> +++ b/xen/arch/arm/llc-coloring.c
> >>> @@ -9,6 +9,7 @@
> >>>     *    Carlo Nonato <carlo.nonato@minervasys.tech>
> >>>     */
> >>>    #include <xen/errno.h>
> >>> +#include <xen/guest_access.h>
> >>>    #include <xen/keyhandler.h>
> >>>    #include <xen/llc-coloring.h>
> >>>    #include <xen/param.h>
> >>> @@ -278,6 +279,22 @@ int dom0_set_llc_colors(struct domain *d)
> >>>        return domain_check_colors(d);
> >>>    }
> >>>
> >>> +int domain_set_llc_colors_domctl(struct domain *d,
> >>> +                                 const struct xen_domctl_set_llc_colors *config)
> >>> +{
> >>> +    if ( d->num_llc_colors )
> >>> +        return -EEXIST;
> >>> +
> >>> +    if ( domain_alloc_colors(d, config->num_llc_colors) )
> >>
> >> domain_alloc_colors() doesn't sanity check config->num_llc_colors before
> >> allocating the array. You want a check the size before so we would not
> >> try to allocate an arbitrary amount of memory.
> >>
> >>> +        return -ENOMEM;
> >>> +
> >>> +    if ( copy_from_guest(d->llc_colors, config->llc_colors,
> >>> +                         config->num_llc_colors) )
> >>> +        return -EFAULT;
> >>> +
> >>> +    return domain_check_colors(d);
> >>> +}
> >>> +
> >>>    /*
> >>>     * Local variables:
> >>>     * mode: C
> >>> diff --git a/xen/common/domctl.c b/xen/common/domctl.c
> >>> index f5a71ee5f7..b6867d0602 100644
> >>> --- a/xen/common/domctl.c
> >>> +++ b/xen/common/domctl.c
> >>> @@ -8,6 +8,7 @@
> >>>
> >>>    #include <xen/types.h>
> >>>    #include <xen/lib.h>
> >>> +#include <xen/llc-coloring.h>
> >>>    #include <xen/err.h>
> >>>    #include <xen/mm.h>
> >>>    #include <xen/sched.h>
> >>> @@ -858,6 +859,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
> >>>                    __HYPERVISOR_domctl, "h", u_domctl);
> >>>            break;
> >>>
> >>> +    case XEN_DOMCTL_set_llc_colors:
> >>> +        if ( !llc_coloring_enabled )
> >>> +            break;
> >>> +
> >>> +        ret = domain_set_llc_colors_domctl(d, &op->u.set_llc_colors);
> >>> +        if ( ret == -EEXIST )
> >>> +            printk(XENLOG_ERR
> >>> +                   "Can't set LLC colors on an already created domain\n");
> >>
> >> To me, the message doesn't match the check in
> >> domain_set_llc_colors_domctl(). But I think you want to check that no
> >> memory was yet allocated to the domain. Otherwise, you coloring will be
> >> wrong.
> >>
> >> Also, it is a bit unclear why you print a message for -EEXIST but not
> >> the others. In this instance, I would consider to print nothing at all.
> >
> > The problem here is that we don't support recoloring. When a domain is
> > created it receives a coloring configuration and it can't change. If this
> > hypercall is called twice I have to stop the second time somehow.
> Looking at your check what you prevent is a toolstack updating the array
> twice. But that would be ok (/!\ I am not saying we should allow it) so
> long no memory has been allocated to the domain.
>
> But I also consider we would re-color once we started to allocate memory
> for the domain (either RAM or P2M). This seems to be missed out in your
> check.

So you want to be able to change colors if no memory has yet been allocated?
I don't know what to check that.

> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08  8:43   ` Jan Beulich
@ 2024-01-08 11:22     ` Carlo Nonato
  0 siblings, 0 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 11:22 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, xen-devel

Hi Jan,

On Mon, Jan 8, 2024 at 9:43 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 02.01.2024 10:51, Carlo Nonato wrote:
> > --- a/xen/arch/arm/llc-coloring.c
> > +++ b/xen/arch/arm/llc-coloring.c
> > @@ -9,6 +9,7 @@
> >   *    Carlo Nonato <carlo.nonato@minervasys.tech>
> >   */
> >  #include <xen/errno.h>
> > +#include <xen/guest_access.h>
> >  #include <xen/keyhandler.h>
> >  #include <xen/llc-coloring.h>
> >  #include <xen/param.h>
> > @@ -278,6 +279,22 @@ int dom0_set_llc_colors(struct domain *d)
> >      return domain_check_colors(d);
> >  }
> >
> > +int domain_set_llc_colors_domctl(struct domain *d,
> > +                                 const struct xen_domctl_set_llc_colors *config)
> > +{
> > +    if ( d->num_llc_colors )
> > +        return -EEXIST;
> > +
> > +    if ( domain_alloc_colors(d, config->num_llc_colors) )
> > +        return -ENOMEM;
> > +
> > +    if ( copy_from_guest(d->llc_colors, config->llc_colors,
> > +                         config->num_llc_colors) )
> > +        return -EFAULT;
> > +
> > +    return domain_check_colors(d);
> > +}
>
> What part of this is Arm-specific? I ask in particular because while you
> place this in an Arm-specific source file, ...
>
> > --- a/xen/common/domctl.c
> > +++ b/xen/common/domctl.c
> > @@ -8,6 +8,7 @@
> >
> >  #include <xen/types.h>
> >  #include <xen/lib.h>
> > +#include <xen/llc-coloring.h>
> >  #include <xen/err.h>
> >  #include <xen/mm.h>
> >  #include <xen/sched.h>
> > @@ -858,6 +859,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
> >                  __HYPERVISOR_domctl, "h", u_domctl);
> >          break;
> >
> > +    case XEN_DOMCTL_set_llc_colors:
> > +        if ( !llc_coloring_enabled )
> > +            break;
> > +
> > +        ret = domain_set_llc_colors_domctl(d, &op->u.set_llc_colors);
> > +        if ( ret == -EEXIST )
> > +            printk(XENLOG_ERR
> > +                   "Can't set LLC colors on an already created domain\n");
> > +        break;
> > +
> >      default:
> >          ret = arch_do_domctl(op, d, u_domctl);
> >          break;
>
> ... you don't handle the new domctl in Arm's arch_do_domctl().

No arm specific code here. I need a new xen/common/llc-coloring.c file where
to put common stuff.

> > --- a/xen/include/public/domctl.h
> > +++ b/xen/include/public/domctl.h
> > @@ -21,7 +21,7 @@
> >  #include "hvm/save.h"
> >  #include "memory.h"
> >
> > -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000016
> > +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000017
>
> There's no need for such a bump when ...
>
> > @@ -1190,6 +1190,12 @@ struct xen_domctl_vmtrace_op {
> >  typedef struct xen_domctl_vmtrace_op xen_domctl_vmtrace_op_t;
> >  DEFINE_XEN_GUEST_HANDLE(xen_domctl_vmtrace_op_t);
> >
> > +struct xen_domctl_set_llc_colors {
> > +    /* IN LLC coloring parameters */
> > +    unsigned int num_llc_colors;
> > +    XEN_GUEST_HANDLE_64(uint) llc_colors;
> > +};
> > +
> >  struct xen_domctl {
> >      uint32_t cmd;
> >  #define XEN_DOMCTL_createdomain                   1
> > @@ -1277,6 +1283,7 @@ struct xen_domctl {
> >  #define XEN_DOMCTL_vmtrace_op                    84
> >  #define XEN_DOMCTL_get_paging_mempool_size       85
> >  #define XEN_DOMCTL_set_paging_mempool_size       86
> > +#define XEN_DOMCTL_set_llc_colors                87
> >  #define XEN_DOMCTL_gdbsx_guestmemio            1000
> >  #define XEN_DOMCTL_gdbsx_pausevcpu             1001
> >  #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
> > @@ -1339,6 +1346,7 @@ struct xen_domctl {
> >          struct xen_domctl_vuart_op          vuart_op;
> >          struct xen_domctl_vmtrace_op        vmtrace_op;
> >          struct xen_domctl_paging_mempool    paging_mempool;
> > +        struct xen_domctl_set_llc_colors    set_llc_colors;
> >          uint8_t                             pad[128];
> >      } u;
> >  };
>
> ... all you do is add a new domctl.
>
> As to the new struct - you'll want to use uint<N>_t there, not
> unsigned int.
>
> Jan

Thanks.


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

* Re: [PATCH v5 06/13] xen/arm: add support for cache coloring configuration via device-tree
  2024-01-05 17:38   ` Julien Grall
@ 2024-01-08 11:26     ` Carlo Nonato
  0 siblings, 0 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 11:26 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Julien,

On Fri, Jan 5, 2024 at 6:38 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 02/01/2024 09:51, Carlo Nonato wrote:
> > This commit adds the "llc-colors" Device Tree attribute that can be used
> > for DomUs and Dom0less color configurations. The syntax is the same used
> > for every color config.
> >
> > Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> >
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > ---
> > v5:
> > - static-mem check has been moved in a previous patch
> > - added domain_set_llc_colors_from_str() to set colors after domain creation
> > ---
> >   docs/misc/arm/cache-coloring.rst        | 48 ++++++++++++++++++++++++-
> >   docs/misc/arm/device-tree/booting.txt   |  4 +++
> >   xen/arch/arm/dom0less-build.c           | 13 +++++++
> >   xen/arch/arm/include/asm/llc-coloring.h |  1 +
> >   xen/arch/arm/llc-coloring.c             | 17 +++++++++
> >   5 files changed, 82 insertions(+), 1 deletion(-)
> >
> > diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> > index acf82c3df8..ae1dd8f4af 100644
> > --- a/docs/misc/arm/cache-coloring.rst
> > +++ b/docs/misc/arm/cache-coloring.rst
> > @@ -10,7 +10,7 @@ If needed, change the maximum number of colors with
> >   ``CONFIG_NR_LLC_COLORS=<n>``.
> >
> >   Compile Xen and the toolstack and then configure it via
> > -`Command line parameters`_.
> > +`Command line parameters`_. For DomUs follow `DomUs configuration`_.
> >
> >   Background
> >   **********
> > @@ -114,6 +114,52 @@ Examples:
> >   | 0                 | [0]                         |
> >   +-------------------+-----------------------------+
> >
> > +DomUs configuration
> > +*******************
> > +
> > +DomUs colors can be set via Device Tree, also for Dom0less configurations
> > +(documentation at `docs/misc/arm/device-tree/booting.txt`) using the
> > +``llc-colors`` option. For example:
> > +
> > +::
> > +
> > +    xen,xen-bootargs = "console=dtuart dtuart=serial0 dom0_mem=1G dom0_max_vcpus=1 sched=null llc-coloring=on llc-way-size=64K dom0-llc-colors=2-6";
> > +    xen,dom0-bootargs "console=hvc0 earlycon=xen earlyprintk=xen root=/dev/ram0"
> > +
> > +    dom0 {
> > +        compatible = "xen,linux-zimage" "xen,multiboot-module";
> > +        reg = <0x0 0x1000000 0x0 15858176>;
> > +    };
> > +
> > +    dom0-ramdisk {
> > +        compatible = "xen,linux-initrd" "xen,multiboot-module";
> > +        reg = <0x0 0x2000000 0x0 20638062>;
> > +    };
> > +
> > +    domU0 {
> > +        #address-cells = <0x1>;
> > +        #size-cells = <0x1>;
> > +        compatible = "xen,domain";
> > +        memory = <0x0 0x40000>;
> > +        llc-colors = "4-8,10,11,12";
> > +        cpus = <0x1>;
> > +        vpl011 = <0x1>;
> > +
> > +        module@2000000 {
> > +            compatible = "multiboot,kernel", "multiboot,module";
> > +            reg = <0x2000000 0xffffff>;
> > +            bootargs = "console=ttyAMA0";
> > +        };
> > +
> > +        module@30000000 {
> > +            compatible = "multiboot,ramdisk", "multiboot,module";
> > +            reg = <0x3000000 0xffffff>;
> > +        };
> > +    };
> > +
> > +**Note:** If no color configuration is provided for a domain, the default one,
> > +which corresponds to all available colors, is used instead.
>
> Looking at your code, it will use *all* the colors. Some of the colors
> might have been assigned to a domain. I am not entirely convinced this
> is good idea to allow this as a default setup.
>
>
> > +
> >   Known issues and limitations
> >   ****************************
> >
> > diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
> > index bbd955e9c2..e9f9862e9c 100644
> > --- a/docs/misc/arm/device-tree/booting.txt
> > +++ b/docs/misc/arm/device-tree/booting.txt
> > @@ -162,6 +162,10 @@ with the following properties:
> >
> >       An integer specifying the number of vcpus to allocate to the guest.
> >
> > +- llc-colors
> > +    A string specifying the LLC color configuration for the guest.
> > +    Refer to "docs/misc/arm/cache_coloring.rst" for syntax.
> > +
> >   - vpl011
> >
> >       An empty property to enable/disable a virtual pl011 for the guest to
> > diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
> > index 1142f7f74a..eb39f5291f 100644
> > --- a/xen/arch/arm/dom0less-build.c
> > +++ b/xen/arch/arm/dom0less-build.c
> > @@ -850,6 +850,7 @@ void __init create_domUs(void)
> >       struct dt_device_node *node;
> >       const struct dt_device_node *cpupool_node,
> >                                   *chosen = dt_find_node_by_path("/chosen");
> > +    const char *llc_colors_str = NULL;
> >
> >       BUG_ON(chosen == NULL);
> >       dt_for_each_child_node(chosen, node)
> > @@ -993,6 +994,13 @@ void __init create_domUs(void)
> >   #endif
> >           }
> >
> > +        dt_property_read_string(node, "llc-colors", &llc_colors_str);
> > +        if ( llc_coloring_enabled && !llc_colors_str )
> > +            panic("'llc-colors' is required when LLC coloring is enabled\n");
>
> In the documentation you wrote:
>
> "**Note:** If no color configuration is provided for a domain, the
> default one,which corresponds to all available colors, is used instead."
>
> I interpret as you want to continue rather than panic-ing. That said, I
> much prefer the panic version.

Will do as you said. No problem from my side.

> > +        else if ( !llc_coloring_enabled && llc_colors_str)
> > +            printk(XENLOG_WARNING
> > +                   "'llc-colors' found, but LLC coloring is disabled\n");
> > +
> >           /*
> >            * The variable max_init_domid is initialized with zero, so here it's
> >            * very important to use the pre-increment operator to call
> > @@ -1003,6 +1011,11 @@ void __init create_domUs(void)
> >               panic("Error creating domain %s (rc = %ld)\n",
> >                     dt_node_name(node), PTR_ERR(d));
> >
> > +        if ( llc_coloring_enabled &&
> > +             (rc = domain_set_llc_colors_from_str(d, llc_colors_str)) )
> > +            panic("Error initializing LLC coloring for domain %s (rc = %d)\n",
> > +                  dt_node_name(node), rc);
> > +
> >           d->is_console = true;
> >           dt_device_set_used_by(node, d->domain_id);
> >
> > diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
> > index ee5551e3cc..5f9b0a8121 100644
> > --- a/xen/arch/arm/include/asm/llc-coloring.h
> > +++ b/xen/arch/arm/include/asm/llc-coloring.h
> > @@ -15,6 +15,7 @@
> >
> >   bool __init llc_coloring_init(void);
> >   int dom0_set_llc_colors(struct domain *d);
> > +int domain_set_llc_colors_from_str(struct domain *d, const char *str);
> >
> >   #endif /* __ASM_ARM_COLORING_H__ */
> >
> > diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> > index a08614ec36..d3de5f14cb 100644
> > --- a/xen/arch/arm/llc-coloring.c
> > +++ b/xen/arch/arm/llc-coloring.c
> > @@ -295,6 +295,23 @@ int domain_set_llc_colors_domctl(struct domain *d,
> >       return domain_check_colors(d);
> >   }
> >
> > +int domain_set_llc_colors_from_str(struct domain *d, const char *str)
> > +{
> > +    int err;
> > +
> > +    if ( domain_alloc_colors(d, nr_colors) )
>
> This code is somewhat confusing and would deserve some explanation.
> AFAICT, you are allocating a large array because parse_color_config()
> expects an array of nr_colors.
>
> d->num_llc_colors will also be set to nr_colors but then overriden by
> parse_color_config().
>
> It feels to me that maybe set num_llc_colors() in domain_alloc_colors()
> is not right.

As previously discussed, I can move the d->num_llc_colors assignment out of
that function.

> > +        return -ENOMEM;
> > +
> > +    err = parse_color_config(str, d->llc_colors, &d->num_llc_colors);
> > +    if ( err )
> > +    {
> > +        printk(XENLOG_ERR "Error parsing LLC color configuration.");
> > +        return err;
> > +    }
> > +
> > +    return domain_check_colors(d);
> > +}
> > +
> >   /*
> >    * Local variables:
> >    * mode: C
>
> Cheers,

Thanks.
>
> --
> Julien Grall


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

* Re: [PATCH v5 11/13] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START"
  2024-01-05 18:20   ` Julien Grall
@ 2024-01-08 11:28     ` Carlo Nonato
  0 siblings, 0 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 11:28 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Julien,

On Fri, Jan 5, 2024 at 7:20 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 02/01/2024 09:51, Carlo Nonato wrote:
> > This reverts commit 0c18fb76323bfb13615b6f13c98767face2d8097 (not clean).
> >
> > This is not a clean revert since the rework of the memory layout, but it is
> > sufficiently similar to a clean one.
> > The only difference is that the BOOT_RELOC_VIRT_START must match the new
> > layout.
> >
> > Cache coloring support for Xen needs to relocate Xen code and data in a new
> > colored physical space. The BOOT_RELOC_VIRT_START will be used as the virtual
> > base address for a temporary mapping to this new space.
> >
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > ---
> >   xen/arch/arm/include/asm/mmu/layout.h | 2 ++
> >   xen/arch/arm/mmu/setup.c              | 1 +
> >   2 files changed, 3 insertions(+)
> >
> > diff --git a/xen/arch/arm/include/asm/mmu/layout.h b/xen/arch/arm/include/asm/mmu/layout.h
> > index eac7eef885..30031f74d9 100644
> > --- a/xen/arch/arm/include/asm/mmu/layout.h
> > +++ b/xen/arch/arm/include/asm/mmu/layout.h
> > @@ -74,6 +74,8 @@
> >   #define BOOT_FDT_VIRT_START     (FIXMAP_VIRT_START + FIXMAP_VIRT_SIZE)
> >   #define BOOT_FDT_VIRT_SIZE      _AT(vaddr_t, MB(4))
> >
> > +#define BOOT_RELOC_VIRT_START   (BOOT_FDT_VIRT_START + BOOT_FDT_VIRT_SIZE)
>
> This new addition wants to be documented in the layout comment in a few
> lines above. Also, the area you are using is 2MB whereas Xen can now be
> up to 8MB.
>
> Secondly, you want to add a BOOTRELOC_VIRT_SIZE with a check in
> build_assertions() making sure that this is at least as big as
> XEN_VIRT_SIZE.
>
> Overall, I am not sure this is really a revert at this point. The idea
> is the same, but you are defining BOOT_FDT_VIRT_START differently.
>
> To me it feels like it belong to the first patch where you will use it.
> And that would be ok to mention in the commit message that the idea was
> borrowed from a previously reverted commit.

Ok, nice.

> > +
> >   #ifdef CONFIG_LIVEPATCH
> >   #define LIVEPATCH_VMAP_START    (BOOT_FDT_VIRT_START + BOOT_FDT_VIRT_SIZE)
> >   #define LIVEPATCH_VMAP_SIZE    _AT(vaddr_t, MB(2))
> > diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
> > index d5264e51bc..37b6d230ad 100644
> > --- a/xen/arch/arm/mmu/setup.c
> > +++ b/xen/arch/arm/mmu/setup.c
> > @@ -69,6 +69,7 @@ static void __init __maybe_unused build_assertions(void)
> >       /* 2MB aligned regions */
> >       BUILD_BUG_ON(XEN_VIRT_START & ~SECOND_MASK);
> >       BUILD_BUG_ON(FIXMAP_ADDR(0) & ~SECOND_MASK);
> > +    BUILD_BUG_ON(BOOT_RELOC_VIRT_START & ~SECOND_MASK);
> >       /* 1GB aligned regions */
> >   #ifdef CONFIG_ARM_32
> >       BUILD_BUG_ON(XENHEAP_VIRT_START & ~FIRST_MASK);
>
> --
> Julien Grall

Thanks.


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 11:19         ` Carlo Nonato
@ 2024-01-08 11:35           ` Julien Grall
  2024-01-08 15:18             ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-08 11:35 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Carlo,

On 08/01/2024 11:19, Carlo Nonato wrote:
> Hi Julien,
> 
> On Mon, Jan 8, 2024 at 12:01 PM Julien Grall <julien@xen.org> wrote:
>>
>> Hi Carlo,
>>
>> On 08/01/2024 10:27, Carlo Nonato wrote:
>>> On Fri, Jan 5, 2024 at 6:26 PM Julien Grall <julien@xen.org> wrote:
>>>> On 02/01/2024 09:51, Carlo Nonato wrote:
>>>>> This commit updates the domctl interface to allow the user to set cache
>>>>> coloring configurations from the toolstack.
>>>>> It also implements the functionality for arm64.
>>>>>
>>>>> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
>>>>>
>>>>> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
>>>>> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
>>>>> ---
>>>>> v5:
>>>>> - added a new hypercall to set colors
>>>>> - uint for the guest handle
>>>>> v4:
>>>>> - updated XEN_DOMCTL_INTERFACE_VERSION
>>>>> ---
>>>>>     xen/arch/arm/llc-coloring.c    | 17 +++++++++++++++++
>>>>>     xen/common/domctl.c            | 11 +++++++++++
>>>>>     xen/include/public/domctl.h    | 10 +++++++++-
>>>>>     xen/include/xen/llc-coloring.h |  3 +++
>>>>>     4 files changed, 40 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
>>>>> index 5ce58aba70..a08614ec36 100644
>>>>> --- a/xen/arch/arm/llc-coloring.c
>>>>> +++ b/xen/arch/arm/llc-coloring.c
>>>>> @@ -9,6 +9,7 @@
>>>>>      *    Carlo Nonato <carlo.nonato@minervasys.tech>
>>>>>      */
>>>>>     #include <xen/errno.h>
>>>>> +#include <xen/guest_access.h>
>>>>>     #include <xen/keyhandler.h>
>>>>>     #include <xen/llc-coloring.h>
>>>>>     #include <xen/param.h>
>>>>> @@ -278,6 +279,22 @@ int dom0_set_llc_colors(struct domain *d)
>>>>>         return domain_check_colors(d);
>>>>>     }
>>>>>
>>>>> +int domain_set_llc_colors_domctl(struct domain *d,
>>>>> +                                 const struct xen_domctl_set_llc_colors *config)
>>>>> +{
>>>>> +    if ( d->num_llc_colors )
>>>>> +        return -EEXIST;
>>>>> +
>>>>> +    if ( domain_alloc_colors(d, config->num_llc_colors) )
>>>>
>>>> domain_alloc_colors() doesn't sanity check config->num_llc_colors before
>>>> allocating the array. You want a check the size before so we would not
>>>> try to allocate an arbitrary amount of memory.
>>>>
>>>>> +        return -ENOMEM;
>>>>> +
>>>>> +    if ( copy_from_guest(d->llc_colors, config->llc_colors,
>>>>> +                         config->num_llc_colors) )
>>>>> +        return -EFAULT;
>>>>> +
>>>>> +    return domain_check_colors(d);
>>>>> +}
>>>>> +
>>>>>     /*
>>>>>      * Local variables:
>>>>>      * mode: C
>>>>> diff --git a/xen/common/domctl.c b/xen/common/domctl.c
>>>>> index f5a71ee5f7..b6867d0602 100644
>>>>> --- a/xen/common/domctl.c
>>>>> +++ b/xen/common/domctl.c
>>>>> @@ -8,6 +8,7 @@
>>>>>
>>>>>     #include <xen/types.h>
>>>>>     #include <xen/lib.h>
>>>>> +#include <xen/llc-coloring.h>
>>>>>     #include <xen/err.h>
>>>>>     #include <xen/mm.h>
>>>>>     #include <xen/sched.h>
>>>>> @@ -858,6 +859,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>>>>>                     __HYPERVISOR_domctl, "h", u_domctl);
>>>>>             break;
>>>>>
>>>>> +    case XEN_DOMCTL_set_llc_colors:
>>>>> +        if ( !llc_coloring_enabled )
>>>>> +            break;
>>>>> +
>>>>> +        ret = domain_set_llc_colors_domctl(d, &op->u.set_llc_colors);
>>>>> +        if ( ret == -EEXIST )
>>>>> +            printk(XENLOG_ERR
>>>>> +                   "Can't set LLC colors on an already created domain\n");
>>>>
>>>> To me, the message doesn't match the check in
>>>> domain_set_llc_colors_domctl(). But I think you want to check that no
>>>> memory was yet allocated to the domain. Otherwise, you coloring will be
>>>> wrong.
>>>>
>>>> Also, it is a bit unclear why you print a message for -EEXIST but not
>>>> the others. In this instance, I would consider to print nothing at all.
>>>
>>> The problem here is that we don't support recoloring. When a domain is
>>> created it receives a coloring configuration and it can't change. If this
>>> hypercall is called twice I have to stop the second time somehow.
>> Looking at your check what you prevent is a toolstack updating the array
>> twice. But that would be ok (/!\ I am not saying we should allow it) so
>> long no memory has been allocated to the domain.
>>
>> But I also consider we would re-color once we started to allocate memory
>> for the domain (either RAM or P2M). This seems to be missed out in your
>> check.
> 
> So you want to be able to change colors if no memory has yet been allocated?

No. I am saying that that we should not be able to allow changing the 
colors after the memory has been allocated. To give an example, your 
current code would allow:

   1) Setup the P2M pools or allocate RAM
   2) Set the color

This would render the coloring configuration moot.

Whether we want to allow changing the coloring before hand is a 
different question and as I wrote earlier on, I don't mind if you want 
to forbid that.

> I don't know what to check that.

You can check the size of the P2M pool (d->arch.paging.p2m_total_pages) 
is still 0. I think for RAM, you can check d->tot_pages == 0.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support
  2024-01-08 11:04             ` Carlo Nonato
@ 2024-01-08 11:44               ` Julien Grall
  2024-01-08 11:55                 ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-08 11:44 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri



On 08/01/2024 11:04, Carlo Nonato wrote:
> Hi Julien,
> 
> On Mon, Jan 8, 2024 at 11:25 AM Julien Grall <julien@xen.org> wrote:
>>
>> Hi Carlo,
>>
>> On 08/01/2024 10:06, Carlo Nonato wrote:
>>>> One of the reason is at least in the dom0less case, you will override
>>>> the value afterwards.
>>>
>>> In that case I need to allocate the array before parsing the string.
>>> I allocate a full array then the string is parsed and the actual size is found
>>> at the end of this phase. Knowing the actual size would require two parsing
>>> stages. Yes I'm wasting a bit of memory by oversizing the array here. Is it
>>> a problem?
>>
>> While wasting memory is indeed not nice. This wasn't the main reason of
>> this comment.
>>
>> The reason is that you seem to set d->num_lcc_colors will but will never
>> be read before it gets overwritten. Looking again at the code, you are
>> also assuming parse_colors() will always take an array of nr_colors.
> 
> Ok, I think I understood, but that happens only in dom0less case because
> d->num_llc_colors is overwritten after parsing. In other cases it's ok to set
> it there. Anyway I can move the assignment out of the function if that is
> clearer.
> 
>> It would be better if parse_colors() takes the maximum size of the array
>> in parameter. This would harden the code and it makes more sense for
>> domain_alloc_colors() to set d->num_lcc_colors.
> 
> I don't understand this. parse_colors() must take only arrays of nr_colors
> size (the global, maximum number of colors), otherwise the parsed string
> config could exceed the array size. Since we don't know in advance the real
> size before parsing, I think it's better to pass only arrays that are already
> allocated with the maximum size.

My concern is there is a disconnect. From the code, it is not obvious at 
all that parse_colors() only want to accept an array of nr_colors. If 
you pass an extra argument (or re-use the one you pass) for the array 
size and use within the code, then it makes more obvious that your array 
is always the correct size.

At least to me, this is a good practice in C to always pass the array 
and its size together (other language have that embedded). But I can 
appreciate this is not view like that for everyone. The minimum would be 
to document this requirement in a comment

> Doing as you said I would still pass nr_colors as the maximum size, but that
> would be strange since the global would still be accessible.

I don't really see the problem here. Your code doesn't need to use the 
global variable.

> If domain_alloc_colors() setting d->num_llc_colors is so confusing,
> I will just move the assignment after the function call.
> 
>> Also, I just noticed you have a global variable named nr_colors and the
>> function parse_colors() takes an argument called *num_colors. This is
>> quite confusing, can we have better name?
>>
>> Maybe rename nr_colors to nr_global_colors and and num_colors to
>> nr_array_colors?
> 
> I agree with the fact that naming is confusing. I would opt for max_nr_colors
> for the global.

I am fine with that.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support
  2024-01-08 11:44               ` Julien Grall
@ 2024-01-08 11:55                 ` Carlo Nonato
  0 siblings, 0 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 11:55 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

On Mon, Jan 8, 2024 at 12:44 PM Julien Grall <julien@xen.org> wrote:
>
>
>
> On 08/01/2024 11:04, Carlo Nonato wrote:
> > Hi Julien,
> >
> > On Mon, Jan 8, 2024 at 11:25 AM Julien Grall <julien@xen.org> wrote:
> >>
> >> Hi Carlo,
> >>
> >> On 08/01/2024 10:06, Carlo Nonato wrote:
> >>>> One of the reason is at least in the dom0less case, you will override
> >>>> the value afterwards.
> >>>
> >>> In that case I need to allocate the array before parsing the string.
> >>> I allocate a full array then the string is parsed and the actual size is found
> >>> at the end of this phase. Knowing the actual size would require two parsing
> >>> stages. Yes I'm wasting a bit of memory by oversizing the array here. Is it
> >>> a problem?
> >>
> >> While wasting memory is indeed not nice. This wasn't the main reason of
> >> this comment.
> >>
> >> The reason is that you seem to set d->num_lcc_colors will but will never
> >> be read before it gets overwritten. Looking again at the code, you are
> >> also assuming parse_colors() will always take an array of nr_colors.
> >
> > Ok, I think I understood, but that happens only in dom0less case because
> > d->num_llc_colors is overwritten after parsing. In other cases it's ok to set
> > it there. Anyway I can move the assignment out of the function if that is
> > clearer.
> >
> >> It would be better if parse_colors() takes the maximum size of the array
> >> in parameter. This would harden the code and it makes more sense for
> >> domain_alloc_colors() to set d->num_lcc_colors.
> >
> > I don't understand this. parse_colors() must take only arrays of nr_colors
> > size (the global, maximum number of colors), otherwise the parsed string
> > config could exceed the array size. Since we don't know in advance the real
> > size before parsing, I think it's better to pass only arrays that are already
> > allocated with the maximum size.
>
> My concern is there is a disconnect. From the code, it is not obvious at
> all that parse_colors() only want to accept an array of nr_colors. If
> you pass an extra argument (or re-use the one you pass) for the array
> size and use within the code, then it makes more obvious that your array
> is always the correct size.
>
> At least to me, this is a good practice in C to always pass the array
> and its size together (other language have that embedded). But I can
> appreciate this is not view like that for everyone. The minimum would be
> to document this requirement in a comment

Ok got it. Thanks for the explanation.

> > Doing as you said I would still pass nr_colors as the maximum size, but that
> > would be strange since the global would still be accessible.
>
> I don't really see the problem here. Your code doesn't need to use the
> global variable.
>
> > If domain_alloc_colors() setting d->num_llc_colors is so confusing,
> > I will just move the assignment after the function call.
> >
> >> Also, I just noticed you have a global variable named nr_colors and the
> >> function parse_colors() takes an argument called *num_colors. This is
> >> quite confusing, can we have better name?
> >>
> >> Maybe rename nr_colors to nr_global_colors and and num_colors to
> >> nr_array_colors?
> >
> > I agree with the fact that naming is confusing. I would opt for max_nr_colors
> > for the global.
>
> I am fine with that.
>
> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 11:35           ` Julien Grall
@ 2024-01-08 15:18             ` Carlo Nonato
  2024-01-08 15:31               ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 15:18 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien

On Mon, Jan 8, 2024 at 12:36 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 08/01/2024 11:19, Carlo Nonato wrote:
> > Hi Julien,
> >
> > On Mon, Jan 8, 2024 at 12:01 PM Julien Grall <julien@xen.org> wrote:
> >>
> >> Hi Carlo,
> >>
> >> On 08/01/2024 10:27, Carlo Nonato wrote:
> >>> On Fri, Jan 5, 2024 at 6:26 PM Julien Grall <julien@xen.org> wrote:
> >>>> On 02/01/2024 09:51, Carlo Nonato wrote:
> >>>>> This commit updates the domctl interface to allow the user to set cache
> >>>>> coloring configurations from the toolstack.
> >>>>> It also implements the functionality for arm64.
> >>>>>
> >>>>> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
> >>>>>
> >>>>> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> >>>>> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> >>>>> ---
> >>>>> v5:
> >>>>> - added a new hypercall to set colors
> >>>>> - uint for the guest handle
> >>>>> v4:
> >>>>> - updated XEN_DOMCTL_INTERFACE_VERSION
> >>>>> ---
> >>>>>     xen/arch/arm/llc-coloring.c    | 17 +++++++++++++++++
> >>>>>     xen/common/domctl.c            | 11 +++++++++++
> >>>>>     xen/include/public/domctl.h    | 10 +++++++++-
> >>>>>     xen/include/xen/llc-coloring.h |  3 +++
> >>>>>     4 files changed, 40 insertions(+), 1 deletion(-)
> >>>>>
> >>>>> diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> >>>>> index 5ce58aba70..a08614ec36 100644
> >>>>> --- a/xen/arch/arm/llc-coloring.c
> >>>>> +++ b/xen/arch/arm/llc-coloring.c
> >>>>> @@ -9,6 +9,7 @@
> >>>>>      *    Carlo Nonato <carlo.nonato@minervasys.tech>
> >>>>>      */
> >>>>>     #include <xen/errno.h>
> >>>>> +#include <xen/guest_access.h>
> >>>>>     #include <xen/keyhandler.h>
> >>>>>     #include <xen/llc-coloring.h>
> >>>>>     #include <xen/param.h>
> >>>>> @@ -278,6 +279,22 @@ int dom0_set_llc_colors(struct domain *d)
> >>>>>         return domain_check_colors(d);
> >>>>>     }
> >>>>>
> >>>>> +int domain_set_llc_colors_domctl(struct domain *d,
> >>>>> +                                 const struct xen_domctl_set_llc_colors *config)
> >>>>> +{
> >>>>> +    if ( d->num_llc_colors )
> >>>>> +        return -EEXIST;
> >>>>> +
> >>>>> +    if ( domain_alloc_colors(d, config->num_llc_colors) )
> >>>>
> >>>> domain_alloc_colors() doesn't sanity check config->num_llc_colors before
> >>>> allocating the array. You want a check the size before so we would not
> >>>> try to allocate an arbitrary amount of memory.
> >>>>
> >>>>> +        return -ENOMEM;
> >>>>> +
> >>>>> +    if ( copy_from_guest(d->llc_colors, config->llc_colors,
> >>>>> +                         config->num_llc_colors) )
> >>>>> +        return -EFAULT;
> >>>>> +
> >>>>> +    return domain_check_colors(d);
> >>>>> +}
> >>>>> +
> >>>>>     /*
> >>>>>      * Local variables:
> >>>>>      * mode: C
> >>>>> diff --git a/xen/common/domctl.c b/xen/common/domctl.c
> >>>>> index f5a71ee5f7..b6867d0602 100644
> >>>>> --- a/xen/common/domctl.c
> >>>>> +++ b/xen/common/domctl.c
> >>>>> @@ -8,6 +8,7 @@
> >>>>>
> >>>>>     #include <xen/types.h>
> >>>>>     #include <xen/lib.h>
> >>>>> +#include <xen/llc-coloring.h>
> >>>>>     #include <xen/err.h>
> >>>>>     #include <xen/mm.h>
> >>>>>     #include <xen/sched.h>
> >>>>> @@ -858,6 +859,16 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
> >>>>>                     __HYPERVISOR_domctl, "h", u_domctl);
> >>>>>             break;
> >>>>>
> >>>>> +    case XEN_DOMCTL_set_llc_colors:
> >>>>> +        if ( !llc_coloring_enabled )
> >>>>> +            break;
> >>>>> +
> >>>>> +        ret = domain_set_llc_colors_domctl(d, &op->u.set_llc_colors);
> >>>>> +        if ( ret == -EEXIST )
> >>>>> +            printk(XENLOG_ERR
> >>>>> +                   "Can't set LLC colors on an already created domain\n");
> >>>>
> >>>> To me, the message doesn't match the check in
> >>>> domain_set_llc_colors_domctl(). But I think you want to check that no
> >>>> memory was yet allocated to the domain. Otherwise, you coloring will be
> >>>> wrong.
> >>>>
> >>>> Also, it is a bit unclear why you print a message for -EEXIST but not
> >>>> the others. In this instance, I would consider to print nothing at all.
> >>>
> >>> The problem here is that we don't support recoloring. When a domain is
> >>> created it receives a coloring configuration and it can't change. If this
> >>> hypercall is called twice I have to stop the second time somehow.
> >> Looking at your check what you prevent is a toolstack updating the array
> >> twice. But that would be ok (/!\ I am not saying we should allow it) so
> >> long no memory has been allocated to the domain.
> >>
> >> But I also consider we would re-color once we started to allocate memory
> >> for the domain (either RAM or P2M). This seems to be missed out in your
> >> check.
> >
> > So you want to be able to change colors if no memory has yet been allocated?
>
> No. I am saying that that we should not be able to allow changing the
> colors after the memory has been allocated. To give an example, your
> current code would allow:
>
>    1) Setup the P2M pools or allocate RAM
>    2) Set the color
>
> This would render the coloring configuration moot.
>
> Whether we want to allow changing the coloring before hand is a
> different question and as I wrote earlier on, I don't mind if you want
> to forbid that.

At the moment I'm relying on the toolstack in the sense that I know that it
will set colors right after domain creation and before memory allocation.
Calling alloc_domheap_pages() without a coloring configuration makes Xen
crash, so it's mandatory to have the configuration done before any allocation.
I know that we shouldn't rely on the toolstack this much, but I didn't
find a better way. Given this assumption, looking for an already existing
color configuration of a domain is sufficient to avoid what you are saying.

Is it possible to enforce such a constraint with domctl?
I mean to be sure that this domctl will be called at a precise time.

Thanks.

> > I don't know what to check that.
>
> You can check the size of the P2M pool (d->arch.paging.p2m_total_pages)
> is still 0. I think for RAM, you can check d->tot_pages == 0.
>
> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 15:18             ` Carlo Nonato
@ 2024-01-08 15:31               ` Julien Grall
  2024-01-08 16:31                 ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-08 15:31 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi,

On 08/01/2024 15:18, Carlo Nonato wrote:
>> No. I am saying that that we should not be able to allow changing the
>> colors after the memory has been allocated. To give an example, your
>> current code would allow:
>>
>>     1) Setup the P2M pools or allocate RAM
>>     2) Set the color
>>
>> This would render the coloring configuration moot.
>>
>> Whether we want to allow changing the coloring before hand is a
>> different question and as I wrote earlier on, I don't mind if you want
>> to forbid that.
> 
> At the moment I'm relying on the toolstack in the sense that I know that it
> will set colors right after domain creation and before memory allocation.
> Calling alloc_domheap_pages() without a coloring configuration makes Xen
> crash, so it's mandatory to have the configuration done before any allocation.
> I know that we shouldn't rely on the toolstack this much, but I didn't
> find a better way. Given this assumption, looking for an already existing
> color configuration of a domain is sufficient to avoid what you are saying.
> 
> Is it possible to enforce such a constraint with domctl? > I mean to be sure that this domctl will be called at a precise time.

Yes. You can...

> 
> Thanks.
> 
>>> I don't know what to check that.
>>
>> You can check the size of the P2M pool (d->arch.paging.p2m_total_pages)
>> is still 0. I think for RAM, you can check d->tot_pages == 0.

... reject the call if either of the two fields are not zero.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 15:31               ` Julien Grall
@ 2024-01-08 16:31                 ` Carlo Nonato
  2024-01-08 16:40                   ` Jan Beulich
  2024-01-08 16:49                   ` Julien Grall
  0 siblings, 2 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 16:31 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien,

On Mon, Jan 8, 2024 at 4:32 PM Julien Grall <julien@xen.org> wrote:
>
> Hi,
>
> On 08/01/2024 15:18, Carlo Nonato wrote:
> >> No. I am saying that that we should not be able to allow changing the
> >> colors after the memory has been allocated. To give an example, your
> >> current code would allow:
> >>
> >>     1) Setup the P2M pools or allocate RAM
> >>     2) Set the color
> >>
> >> This would render the coloring configuration moot.
> >>
> >> Whether we want to allow changing the coloring before hand is a
> >> different question and as I wrote earlier on, I don't mind if you want
> >> to forbid that.
> >
> > At the moment I'm relying on the toolstack in the sense that I know that it
> > will set colors right after domain creation and before memory allocation.
> > Calling alloc_domheap_pages() without a coloring configuration makes Xen
> > crash, so it's mandatory to have the configuration done before any allocation.
> > I know that we shouldn't rely on the toolstack this much, but I didn't
> > find a better way. Given this assumption, looking for an already existing
> > color configuration of a domain is sufficient to avoid what you are saying.
> >
> > Is it possible to enforce such a constraint with domctl? > I mean to be sure that this domctl will be called at a precise time.
>
> Yes. You can...
>
> >
> > Thanks.
> >
> >>> I don't know what to check that.
> >>
> >> You can check the size of the P2M pool (d->arch.paging.p2m_total_pages)
> >> is still 0. I think for RAM, you can check d->tot_pages == 0.
>
> ... reject the call if either of the two fields are not zero.

What I'm saying is that Xen would crash before even reaching this point if no
colors were provided. Let's say that the toolstack or whatever hypercall user
isn't calling this domctl at all (or not at the right time), then the domain
colored allocator would always return null pages since there are no colors.
We would have a crash and your if (or mine) would be useless.

Let's say that now the domctl is called at the right time (no p2m,
no tot_pages, no colors) then we can set the colors and everything works.
From this point other calls to this domctl would be skipped because of your
if which is equivalent to mine (checking for colors existence).

Also bringing in checks on p2m would require arch specific code which I was
trying to avoid.

Thanks.

> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 16:31                 ` Carlo Nonato
@ 2024-01-08 16:40                   ` Jan Beulich
  2024-01-08 16:50                     ` Carlo Nonato
  2024-01-08 16:49                   ` Julien Grall
  1 sibling, 1 reply; 90+ messages in thread
From: Jan Beulich @ 2024-01-08 16:40 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, Julien Grall

On 08.01.2024 17:31, Carlo Nonato wrote:
> On Mon, Jan 8, 2024 at 4:32 PM Julien Grall <julien@xen.org> wrote:
>> On 08/01/2024 15:18, Carlo Nonato wrote:
>>>> No. I am saying that that we should not be able to allow changing the
>>>> colors after the memory has been allocated. To give an example, your
>>>> current code would allow:
>>>>
>>>>     1) Setup the P2M pools or allocate RAM
>>>>     2) Set the color
>>>>
>>>> This would render the coloring configuration moot.
>>>>
>>>> Whether we want to allow changing the coloring before hand is a
>>>> different question and as I wrote earlier on, I don't mind if you want
>>>> to forbid that.
>>>
>>> At the moment I'm relying on the toolstack in the sense that I know that it
>>> will set colors right after domain creation and before memory allocation.
>>> Calling alloc_domheap_pages() without a coloring configuration makes Xen
>>> crash, so it's mandatory to have the configuration done before any allocation.
>>> I know that we shouldn't rely on the toolstack this much, but I didn't
>>> find a better way. Given this assumption, looking for an already existing
>>> color configuration of a domain is sufficient to avoid what you are saying.
>>>
>>> Is it possible to enforce such a constraint with domctl? > I mean to be sure that this domctl will be called at a precise time.
>>
>> Yes. You can...
>>
>>>
>>> Thanks.
>>>
>>>>> I don't know what to check that.
>>>>
>>>> You can check the size of the P2M pool (d->arch.paging.p2m_total_pages)
>>>> is still 0. I think for RAM, you can check d->tot_pages == 0.
>>
>> ... reject the call if either of the two fields are not zero.
> 
> What I'm saying is that Xen would crash before even reaching this point if no
> colors were provided. Let's say that the toolstack or whatever hypercall user
> isn't calling this domctl at all (or not at the right time), then the domain
> colored allocator would always return null pages since there are no colors.
> We would have a crash and your if (or mine) would be useless.

Why is it that you can't simply allocated arbitrary memory if coloring
information wasn't set up front? Aiui that'll be required anyway, as
there shouldn't be a restriction that all domains have to use coloring.

Jan


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 16:31                 ` Carlo Nonato
  2024-01-08 16:40                   ` Jan Beulich
@ 2024-01-08 16:49                   ` Julien Grall
  1 sibling, 0 replies; 90+ messages in thread
From: Julien Grall @ 2024-01-08 16:49 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Carlo,

On 08/01/2024 16:31, Carlo Nonato wrote:
> On Mon, Jan 8, 2024 at 4:32 PM Julien Grall <julien@xen.org> wrote:
>>
>> Hi,
>>
>> On 08/01/2024 15:18, Carlo Nonato wrote:
>>>> No. I am saying that that we should not be able to allow changing the
>>>> colors after the memory has been allocated. To give an example, your
>>>> current code would allow:
>>>>
>>>>      1) Setup the P2M pools or allocate RAM
>>>>      2) Set the color
>>>>
>>>> This would render the coloring configuration moot.
>>>>
>>>> Whether we want to allow changing the coloring before hand is a
>>>> different question and as I wrote earlier on, I don't mind if you want
>>>> to forbid that.
>>>
>>> At the moment I'm relying on the toolstack in the sense that I know that it
>>> will set colors right after domain creation and before memory allocation.
>>> Calling alloc_domheap_pages() without a coloring configuration makes Xen
>>> crash, so it's mandatory to have the configuration done before any allocation.
>>> I know that we shouldn't rely on the toolstack this much, but I didn't
>>> find a better way. Given this assumption, looking for an already existing
>>> color configuration of a domain is sufficient to avoid what you are saying.
>>>
>>> Is it possible to enforce such a constraint with domctl? > I mean to be sure that this domctl will be called at a precise time.
>>
>> Yes. You can...
>>
>>>
>>> Thanks.
>>>
>>>>> I don't know what to check that.
>>>>
>>>> You can check the size of the P2M pool (d->arch.paging.p2m_total_pages)
>>>> is still 0. I think for RAM, you can check d->tot_pages == 0.
>>
>> ... reject the call if either of the two fields are not zero.
> 
> What I'm saying is that Xen would crash before even reaching this point if no
> colors were provided. Let's say that the toolstack or whatever hypercall user
> isn't calling this domctl at all (or not at the right time), then the domain
> colored allocator would always return null pages since there are no colors.
> We would have a crash and your if (or mine) would be useless.

Really? I can believe that NULL may be returned but a crash... If that's 
the case, then this should be fixed.

> 
> Let's say that now the domctl is called at the right time (no p2m,
> no tot_pages, no colors) then we can set the colors and everything works.
>  From this point other calls to this domctl would be skipped because of your
> if which is equivalent to mine (checking for colors existence).

So I misunderstood the implementation of is_domain_llc_colored(). I 
would have thought it was based on whether the domain has colors. But 
instead, it is based on whether coloring is enabled globally.

So I agree that the checks are not necessary today. But if 
is_domain_llc_colored() is changed, then this may not be correct anymore.

So I think there are some clarifications required. If the 'd' will never 
matter, then probably is_domain_llc_colored() should be removed. If not, 
then we want to add the check in the domctl (or at minimum document it).

> 
> Also bringing in checks on p2m would require arch specific code which I was
> trying to avoid.

Fair enough. But the first step is to make the sure the code is correct 
and Xen doesn't crash. We can then discuss about avoiding arch specific 
code.

BTW, all your LLC code is implemented in arch/arm. So if it is really 
intended to contain zero arch specific code, then shouldn't it be 
implemented in common/?

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 16:40                   ` Jan Beulich
@ 2024-01-08 16:50                     ` Carlo Nonato
  2024-01-08 21:21                       ` Stefano Stabellini
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-08 16:50 UTC (permalink / raw)
  To: Jan Beulich
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, Julien Grall

Hi Jan,

On Mon, Jan 8, 2024 at 5:40 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 08.01.2024 17:31, Carlo Nonato wrote:
> > On Mon, Jan 8, 2024 at 4:32 PM Julien Grall <julien@xen.org> wrote:
> >> On 08/01/2024 15:18, Carlo Nonato wrote:
> >>>> No. I am saying that that we should not be able to allow changing the
> >>>> colors after the memory has been allocated. To give an example, your
> >>>> current code would allow:
> >>>>
> >>>>     1) Setup the P2M pools or allocate RAM
> >>>>     2) Set the color
> >>>>
> >>>> This would render the coloring configuration moot.
> >>>>
> >>>> Whether we want to allow changing the coloring before hand is a
> >>>> different question and as I wrote earlier on, I don't mind if you want
> >>>> to forbid that.
> >>>
> >>> At the moment I'm relying on the toolstack in the sense that I know that it
> >>> will set colors right after domain creation and before memory allocation.
> >>> Calling alloc_domheap_pages() without a coloring configuration makes Xen
> >>> crash, so it's mandatory to have the configuration done before any allocation.
> >>> I know that we shouldn't rely on the toolstack this much, but I didn't
> >>> find a better way. Given this assumption, looking for an already existing
> >>> color configuration of a domain is sufficient to avoid what you are saying.
> >>>
> >>> Is it possible to enforce such a constraint with domctl? > I mean to be sure that this domctl will be called at a precise time.
> >>
> >> Yes. You can...
> >>
> >>>
> >>> Thanks.
> >>>
> >>>>> I don't know what to check that.
> >>>>
> >>>> You can check the size of the P2M pool (d->arch.paging.p2m_total_pages)
> >>>> is still 0. I think for RAM, you can check d->tot_pages == 0.
> >>
> >> ... reject the call if either of the two fields are not zero.
> >
> > What I'm saying is that Xen would crash before even reaching this point if no
> > colors were provided. Let's say that the toolstack or whatever hypercall user
> > isn't calling this domctl at all (or not at the right time), then the domain
> > colored allocator would always return null pages since there are no colors.
> > We would have a crash and your if (or mine) would be useless.
>
> Why is it that you can't simply allocated arbitrary memory if coloring
> information wasn't set up front? Aiui that'll be required anyway, as
> there shouldn't be a restriction that all domains have to use coloring.

If coloring is enabled all domains are colored. It's one of our first
assumptions. We haven't developed something that works hybridly and supporting
that would require some rework.

> Jan


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

* Re: [PATCH v5 01/13] xen/common: add cache coloring common code
  2024-01-02  9:51 ` [PATCH v5 01/13] xen/common: add cache coloring common code Carlo Nonato
  2024-01-04 18:39   ` Julien Grall
  2024-01-04 19:59   ` Julien Grall
@ 2024-01-08 16:53   ` Jan Beulich
  2024-01-11 10:10     ` Carlo Nonato
  2 siblings, 1 reply; 90+ messages in thread
From: Jan Beulich @ 2024-01-08 16:53 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Marco Solieri, xen-devel

On 02.01.2024 10:51, Carlo Nonato wrote:
> This commit adds the Last Level Cache (LLC) coloring common header, Kconfig
> options and functions. Since this is an arch specific feature, actual
> implementation is postponed to later patches and Kconfig options are placed
> under xen/arch.

As a general remark / nit: "This commit", "this patch", or alike aren't
well suited for descriptions.

> --- a/xen/arch/Kconfig
> +++ b/xen/arch/Kconfig
> @@ -31,3 +31,19 @@ config NR_NUMA_NODES
>  	  associated with multiple-nodes management. It is the upper bound of
>  	  the number of NUMA nodes that the scheduler, memory allocation and
>  	  other NUMA-aware components can handle.
> +
> +config LLC_COLORING
> +	bool "Last Level Cache (LLC) coloring" if EXPERT
> +	depends on HAS_LLC_COLORING
> +
> +config NR_LLC_COLORS
> +	int "Maximum number of LLC colors"
> +	default 128

What if I set to value to 0? Or to an unreasonably large one? You don't
bound the value range at all.

> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -7,6 +7,7 @@
>  #include <xen/compat.h>
>  #include <xen/init.h>
>  #include <xen/lib.h>
> +#include <xen/llc-coloring.h>
>  #include <xen/ctype.h>
>  #include <xen/err.h>
>  #include <xen/param.h>
> @@ -1144,6 +1145,9 @@ static void cf_check complete_domain_destroy(struct rcu_head *head)
>      struct vcpu *v;
>      int i;
>  
> +    if ( is_domain_llc_colored(d) )
> +        domain_llc_coloring_free(d);

Would be nice if the freeing function could be called unconditionally,
being a no-op for non-colored domains.

Further - is it really necessary to do this freeing this late?

> --- a/xen/common/keyhandler.c
> +++ b/xen/common/keyhandler.c
> @@ -6,6 +6,7 @@
>  #include <xen/debugger.h>
>  #include <xen/delay.h>
>  #include <xen/keyhandler.h>
> +#include <xen/llc-coloring.h>
>  #include <xen/param.h>
>  #include <xen/shutdown.h>
>  #include <xen/event.h>
> @@ -307,6 +308,9 @@ static void cf_check dump_domains(unsigned char key)
>  
>          arch_dump_domain_info(d);
>  
> +        if ( is_domain_llc_colored(d) )
> +            domain_dump_llc_colors(d);

I'm less concerned of the conditional here, but along the lines of the
comment above, it could of course again be the function that simply is
a no-op for non-colored domains.

> --- /dev/null
> +++ b/xen/include/xen/llc-coloring.h
> @@ -0,0 +1,46 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Last Level Cache (LLC) coloring common header
> + *
> + * Copyright (C) 2022 Xilinx Inc.
> + *
> + * Authors:
> + *    Carlo Nonato <carlo.nonato@minervasys.tech>
> + */
> +#ifndef __COLORING_H__
> +#define __COLORING_H__
> +
> +#include <xen/sched.h>
> +#include <public/domctl.h>
> +
> +#ifdef CONFIG_HAS_LLC_COLORING

Why does this matter here? IOW why ...

> +#include <asm/llc-coloring.h>
> +
> +#ifdef CONFIG_LLC_COLORING

... is it not just this which is checked?

> +extern bool llc_coloring_enabled;
> +#define llc_coloring_enabled (llc_coloring_enabled)
> +#endif
> +
> +#endif
> +
> +#ifndef llc_coloring_enabled
> +#define llc_coloring_enabled (false)
> +#endif

+1 to the question Julien has raised here.

> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -626,6 +626,11 @@ struct domain
>  
>      /* Holding CDF_* constant. Internal flags for domain creation. */
>      unsigned int cdf;
> +
> +#ifdef CONFIG_LLC_COLORING
> +    unsigned int *llc_colors;

Can the color values change over the lifetime of a domain? If not,
it may be prudent to have this be pointer-to-const.

Jan

> +    unsigned int num_llc_colors;
> +#endif
>  };
>  
>  static inline struct page_list_head *page_to_list(



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

* Re: [PATCH v5 08/13] xen/page_alloc: introduce preserved page flags macro
  2024-01-02  9:51 ` [PATCH v5 08/13] xen/page_alloc: introduce preserved page flags macro Carlo Nonato
@ 2024-01-08 17:08   ` Jan Beulich
  2024-01-12 10:01     ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Jan Beulich @ 2024-01-08 17:08 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Marco Solieri

On 02.01.2024 10:51, Carlo Nonato wrote:
> PGC_static and PGC_extra are flags that needs to be preserved when assigning
> a page. Define a new macro that groups those flags and use it instead of
> or'ing every time.
> 
> The new macro is used also in free_heap_pages() allowing future commits to
> extended it with other flags that must stop merging, as it now works for
> PGC_static. PGC_extra is no harm here since it's only ever being set on
> allocated pages.

Is it? I can't see where free_domheap_pages() would clear it before calling
free_heap_pages(). Or wait, that may happen in mark_page_free(), but then
PGC_static would be cleared there, too. I must be missing something.

> --- a/xen/common/page_alloc.c
> +++ b/xen/common/page_alloc.c
> @@ -158,6 +158,8 @@
>  #define PGC_static 0
>  #endif
>  
> +#define preserved_flags (PGC_extra | PGC_static)

I think this wants to (a) have a PGC_ prefix and (b) as a #define be all
capitals.

> @@ -1504,7 +1506,7 @@ static void free_heap_pages(
>              /* Merge with predecessor block? */
>              if ( !mfn_valid(page_to_mfn(predecessor)) ||
>                   !page_state_is(predecessor, free) ||
> -                 (predecessor->count_info & PGC_static) ||
> +                 (predecessor->count_info & preserved_flags) ||
>                   (PFN_ORDER(predecessor) != order) ||
>                   (page_to_nid(predecessor) != node) )
>                  break;
> @@ -1528,7 +1530,7 @@ static void free_heap_pages(
>              /* Merge with successor block? */
>              if ( !mfn_valid(page_to_mfn(successor)) ||
>                   !page_state_is(successor, free) ||
> -                 (successor->count_info & PGC_static) ||
> +                 (successor->count_info & preserved_flags) ||
>                   (PFN_ORDER(successor) != order) ||
>                   (page_to_nid(successor) != node) )
>                  break;

Irrespective of the comment at the top, this looks like an abuse of the
new constant: There's nothing inherently making preserved flags also
suppress merging (assuming it was properly checked that both sided have
the same flags set/clear).

Jan


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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 16:50                     ` Carlo Nonato
@ 2024-01-08 21:21                       ` Stefano Stabellini
  2024-01-09  9:34                         ` Jan Beulich
  0 siblings, 1 reply; 90+ messages in thread
From: Stefano Stabellini @ 2024-01-08 21:21 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: Jan Beulich, xen-devel, Stefano Stabellini, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Andrew Cooper, George Dunlap,
	Wei Liu, Marco Solieri, Julien Grall

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

On Mon, 8 Jan 2024, Carlo Nonato wrote:
> Hi Jan,
> 
> On Mon, Jan 8, 2024 at 5:40 PM Jan Beulich <jbeulich@suse.com> wrote:
> >
> > On 08.01.2024 17:31, Carlo Nonato wrote:
> > > On Mon, Jan 8, 2024 at 4:32 PM Julien Grall <julien@xen.org> wrote:
> > >> On 08/01/2024 15:18, Carlo Nonato wrote:
> > >>>> No. I am saying that that we should not be able to allow changing the
> > >>>> colors after the memory has been allocated. To give an example, your
> > >>>> current code would allow:
> > >>>>
> > >>>>     1) Setup the P2M pools or allocate RAM
> > >>>>     2) Set the color
> > >>>>
> > >>>> This would render the coloring configuration moot.
> > >>>>
> > >>>> Whether we want to allow changing the coloring before hand is a
> > >>>> different question and as I wrote earlier on, I don't mind if you want
> > >>>> to forbid that.
> > >>>
> > >>> At the moment I'm relying on the toolstack in the sense that I know that it
> > >>> will set colors right after domain creation and before memory allocation.
> > >>> Calling alloc_domheap_pages() without a coloring configuration makes Xen
> > >>> crash, so it's mandatory to have the configuration done before any allocation.
> > >>> I know that we shouldn't rely on the toolstack this much, but I didn't
> > >>> find a better way. Given this assumption, looking for an already existing
> > >>> color configuration of a domain is sufficient to avoid what you are saying.
> > >>>
> > >>> Is it possible to enforce such a constraint with domctl? > I mean to be sure that this domctl will be called at a precise time.
> > >>
> > >> Yes. You can...
> > >>
> > >>>
> > >>> Thanks.
> > >>>
> > >>>>> I don't know what to check that.
> > >>>>
> > >>>> You can check the size of the P2M pool (d->arch.paging.p2m_total_pages)
> > >>>> is still 0. I think for RAM, you can check d->tot_pages == 0.
> > >>
> > >> ... reject the call if either of the two fields are not zero.
> > >
> > > What I'm saying is that Xen would crash before even reaching this point if no
> > > colors were provided. Let's say that the toolstack or whatever hypercall user
> > > isn't calling this domctl at all (or not at the right time), then the domain
> > > colored allocator would always return null pages since there are no colors.
> > > We would have a crash and your if (or mine) would be useless.
> >
> > Why is it that you can't simply allocated arbitrary memory if coloring
> > information wasn't set up front? Aiui that'll be required anyway, as
> > there shouldn't be a restriction that all domains have to use coloring.
> 
> If coloring is enabled all domains are colored. It's one of our first
> assumptions. We haven't developed something that works hybridly and supporting
> that would require some rework.

I think that's a good assumption and I wouldn't go in the direction of
supporting a mix of colored and non-colored. To benefit from cache
coloring, all domains need to be colored, otherwise a single non-colored
domain could thrash the cache of everyone else.

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

* Re: [PATCH v5 04/13] xen: extend domctl interface for cache coloring
  2024-01-08 21:21                       ` Stefano Stabellini
@ 2024-01-09  9:34                         ` Jan Beulich
  0 siblings, 0 replies; 90+ messages in thread
From: Jan Beulich @ 2024-01-09  9:34 UTC (permalink / raw)
  To: Stefano Stabellini, Carlo Nonato
  Cc: xen-devel, Bertrand Marquis, Michal Orzel, Volodymyr Babchuk,
	Andrew Cooper, George Dunlap, Wei Liu, Marco Solieri,
	Julien Grall

On 08.01.2024 22:21, Stefano Stabellini wrote:
> On Mon, 8 Jan 2024, Carlo Nonato wrote:
>> Hi Jan,
>>
>> On Mon, Jan 8, 2024 at 5:40 PM Jan Beulich <jbeulich@suse.com> wrote:
>>>
>>> On 08.01.2024 17:31, Carlo Nonato wrote:
>>>> On Mon, Jan 8, 2024 at 4:32 PM Julien Grall <julien@xen.org> wrote:
>>>>> On 08/01/2024 15:18, Carlo Nonato wrote:
>>>>>>> No. I am saying that that we should not be able to allow changing the
>>>>>>> colors after the memory has been allocated. To give an example, your
>>>>>>> current code would allow:
>>>>>>>
>>>>>>>     1) Setup the P2M pools or allocate RAM
>>>>>>>     2) Set the color
>>>>>>>
>>>>>>> This would render the coloring configuration moot.
>>>>>>>
>>>>>>> Whether we want to allow changing the coloring before hand is a
>>>>>>> different question and as I wrote earlier on, I don't mind if you want
>>>>>>> to forbid that.
>>>>>>
>>>>>> At the moment I'm relying on the toolstack in the sense that I know that it
>>>>>> will set colors right after domain creation and before memory allocation.
>>>>>> Calling alloc_domheap_pages() without a coloring configuration makes Xen
>>>>>> crash, so it's mandatory to have the configuration done before any allocation.
>>>>>> I know that we shouldn't rely on the toolstack this much, but I didn't
>>>>>> find a better way. Given this assumption, looking for an already existing
>>>>>> color configuration of a domain is sufficient to avoid what you are saying.
>>>>>>
>>>>>> Is it possible to enforce such a constraint with domctl? > I mean to be sure that this domctl will be called at a precise time.
>>>>>
>>>>> Yes. You can...
>>>>>
>>>>>>
>>>>>> Thanks.
>>>>>>
>>>>>>>> I don't know what to check that.
>>>>>>>
>>>>>>> You can check the size of the P2M pool (d->arch.paging.p2m_total_pages)
>>>>>>> is still 0. I think for RAM, you can check d->tot_pages == 0.
>>>>>
>>>>> ... reject the call if either of the two fields are not zero.
>>>>
>>>> What I'm saying is that Xen would crash before even reaching this point if no
>>>> colors were provided. Let's say that the toolstack or whatever hypercall user
>>>> isn't calling this domctl at all (or not at the right time), then the domain
>>>> colored allocator would always return null pages since there are no colors.
>>>> We would have a crash and your if (or mine) would be useless.
>>>
>>> Why is it that you can't simply allocated arbitrary memory if coloring
>>> information wasn't set up front? Aiui that'll be required anyway, as
>>> there shouldn't be a restriction that all domains have to use coloring.
>>
>> If coloring is enabled all domains are colored. It's one of our first
>> assumptions. We haven't developed something that works hybridly and supporting
>> that would require some rework.
> 
> I think that's a good assumption and I wouldn't go in the direction of
> supporting a mix of colored and non-colored. To benefit from cache
> coloring, all domains need to be colored, otherwise a single non-colored
> domain could thrash the cache of everyone else.

In which case the tool stack not having set up coloring data first should
lead to all allocation attempts failing. No crashes whatsoever.

Jan


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

* Re: [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-02  9:51 ` [PATCH v5 09/13] xen: add cache coloring allocator for domains Carlo Nonato
@ 2024-01-09 10:28   ` Jan Beulich
  2024-01-09 10:33     ` Jan Beulich
                       ` (2 more replies)
  0 siblings, 3 replies; 90+ messages in thread
From: Jan Beulich @ 2024-01-09 10:28 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, xen-devel

On 02.01.2024 10:51, Carlo Nonato wrote:
> This commit adds a new memory page allocator that implements the cache
> coloring mechanism. The allocation algorithm enforces equal frequency
> distribution of cache partitions, following the coloring configuration of a
> domain. This allows an even utilization of cache sets for every domain.
> 
> Pages are stored in a color-indexed array of lists. Those lists are filled
> by a simple init function which computes the color of each page.
> When a domain requests a page, the allocator extract the page from the list
> with the maximum number of free pages between those that the domain can
> access, given its coloring configuration.
> 
> The allocator can only handle requests of order-0 pages. This allows for
> easier implementation and since cache coloring targets only embedded systems,
> it's assumed not to be a major problem.

I'm curious about the specific properties of embedded systems that makes
the performance implications of deeper page walks less of an issue for
them.

Nothing is said about address-constrained allocations. Are such entirely
of no interest to domains on Arm, not even to Dom0 (e.g. for filling
Linux'es swiotlb)? Certainly alloc_color_heap_page() should at least
fail when it can't satisfy the passed in memflags.

> ---
> v5:
> - Carlo Nonato as the new author
> - the colored allocator balances color usage for each domain and it searches
>   linearly only in the number of colors (FIXME removed)

While this addresses earlier concerns, meanwhile NUMA work has also
been progressing. What's the plan of interaction of coloring with it?

> --- a/xen/arch/Kconfig
> +++ b/xen/arch/Kconfig
> @@ -47,3 +47,15 @@ config NR_LLC_COLORS
>  	  bound. The runtime value is autocomputed or manually set via cmdline.
>  	  The default value corresponds to an 8 MiB 16-ways LLC, which should be
>  	  more than what needed in the general case.
> +
> +config BUDDY_ALLOCATOR_SIZE
> +	int "Buddy allocator reserved memory size (MiB)"
> +	default "64"
> +	depends on LLC_COLORING
> +	help
> +	  Amount of memory reserved for the buddy allocator to work alongside
> +	  the colored one. The colored allocator is meant as an alternative to
> +	  the buddy allocator because its allocation policy is by definition
> +	  incompatible with the generic one. Since the Xen heap is not colored
> +	  yet, we need to support the coexistence of the two allocators and some
> +	  memory must be left for the buddy one.

Imo help text should be about the specific option, not general
documentation. How about

	  Amount of memory reserved for the buddy allocator, to serve Xen's
	  heap, to work alongside the colored one.

or some such?

> --- a/xen/arch/arm/llc-coloring.c
> +++ b/xen/arch/arm/llc-coloring.c
> @@ -30,6 +30,9 @@ static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
>  static unsigned int __ro_after_init dom0_colors[CONFIG_NR_LLC_COLORS];
>  static unsigned int __ro_after_init dom0_num_colors;
>  
> +#define mfn_color_mask              (nr_colors - 1)

This is used solely ...

> +#define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)

... here, and this one in turn is used solely ...

> @@ -312,6 +315,16 @@ int domain_set_llc_colors_from_str(struct domain *d, const char *str)
>      return domain_check_colors(d);
>  }
>  
> +unsigned int page_to_llc_color(const struct page_info *pg)
> +{
> +    return mfn_to_color(page_to_mfn(pg));
> +}

... here. What's the point in having those (private) macros?

> @@ -1946,6 +1951,162 @@ static unsigned long avail_heap_pages(
>      return free_pages;
>  }
>  
> +/*************************
> + * COLORED SIDE-ALLOCATOR
> + *
> + * Pages are grouped by LLC color in lists which are globally referred to as the
> + * color heap. Lists are populated in end_boot_allocator().
> + * After initialization there will be N lists where N is the number of
> + * available colors on the platform.
> + */
> +static struct page_list_head *__ro_after_init _color_heap;
> +static unsigned long *__ro_after_init free_colored_pages;

It's "just" two pointers, but still - what use are they when ...

> +/* Memory required for buddy allocator to work with colored one */
> +#ifdef CONFIG_LLC_COLORING

... this isn't defined?

> +static unsigned long __initdata buddy_alloc_size =
> +    MB(CONFIG_BUDDY_ALLOCATOR_SIZE);
> +size_param("buddy-alloc-size", buddy_alloc_size);
> +
> +#define domain_num_llc_colors(d) ((d)->num_llc_colors)
> +#define domain_llc_color(d, i)   ((d)->llc_colors[(i)])

Nit: No need to parenthesize i when used like this.

> +#else
> +static unsigned long __initdata buddy_alloc_size;
> +
> +#define domain_num_llc_colors(d) 0
> +#define domain_llc_color(d, i)   0
> +#define page_to_llc_color(p)     0
> +#define get_nr_llc_colors()      0
> +#endif
> +
> +#define color_heap(color) (&_color_heap[color])
> +
> +void free_color_heap_page(struct page_info *pg, bool need_scrub)

Likely applicable further down as well - this is dead code when
!CONFIG_LLC_COLORING. Besides me, Misra also won't like this. The
function also looks to want to be static, at which point DCE would
apparently take care of removing it (and others, and then hopefully
also the two static variables commented on above).

> +struct page_info *alloc_color_heap_page(unsigned int memflags, struct domain *d)

I don't think d is written through in the function, so it wants to
be pointer-to-const.

> +void __init init_color_heap_pages(struct page_info *pg, unsigned long nr_pages)
> +{
> +    unsigned int i;
> +    bool need_scrub = (system_state < SYS_STATE_active &&

Can this part of the condition be false, seeing we're in an __init
function?

> +                       opt_bootscrub == BOOTSCRUB_IDLE);
> +
> +    if ( buddy_alloc_size )
> +    {
> +        unsigned long buddy_pages = min(PFN_DOWN(buddy_alloc_size), nr_pages);
> +
> +        init_heap_pages(pg, buddy_pages);
> +        nr_pages -= buddy_pages;
> +        buddy_alloc_size -= buddy_pages << PAGE_SHIFT;
> +        pg += buddy_pages;
> +    }

So whatever is passed into this function first is going to fill the
Xen heap, without regard to address. I expect you're sure this won't
cause issues on Arm. On x86 certain constraints exist which would
require lower address ranges to be preferred.

> +void dump_color_heap(void)
> +{
> +    unsigned int color;
> +
> +    printk("Dumping color heap info\n");
> +    for ( color = 0; color < get_nr_llc_colors(); color++ )
> +        if ( free_colored_pages[color] > 0 )
> +            printk("Color heap[%u]: %lu pages\n",
> +                   color, free_colored_pages[color]);
> +}

What's a typical range of number of colors on a system? I expect more
than 9, but I'm not sure about a reasonable upper bound. For the
output to be easy to consume, [%u] may want to become at least [%2u].

Jan


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

* Re: [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-09 10:28   ` Jan Beulich
@ 2024-01-09 10:33     ` Jan Beulich
  2024-01-10  0:37       ` Stefano Stabellini
  2024-01-18 14:27       ` Carlo Nonato
  2024-01-10  0:46     ` Stefano Stabellini
  2024-01-15 11:07     ` Carlo Nonato
  2 siblings, 2 replies; 90+ messages in thread
From: Jan Beulich @ 2024-01-09 10:33 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, xen-devel

On 09.01.2024 11:28, Jan Beulich wrote:
> On 02.01.2024 10:51, Carlo Nonato wrote:
>> v5:
>> - Carlo Nonato as the new author
>> - the colored allocator balances color usage for each domain and it searches
>>   linearly only in the number of colors (FIXME removed)
> 
> While this addresses earlier concerns, meanwhile NUMA work has also
> been progressing. What's the plan of interaction of coloring with it?

Thinking of interactions - what about static memory? Is coloring incompatible
with that? If so, should the two features be excluded to both be used at the
same time?

Jan


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

* Re: [PATCH v5 07/13] xen/page_alloc: introduce init_free_page_fields() helper
  2024-01-02  9:51 ` [PATCH v5 07/13] xen/page_alloc: introduce init_free_page_fields() helper Carlo Nonato
@ 2024-01-09 10:36   ` Jan Beulich
  2024-01-12  9:43     ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Jan Beulich @ 2024-01-09 10:36 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Marco Solieri, xen-devel

On 02.01.2024 10:51, Carlo Nonato wrote:
> Introduce a new helper to initialize fields that have different uses for
> free pages.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>

I might in principle ack this change, but what's the deal with this 2nd
S-o-b? The typical expectation is for yours to be last, and the 1st one
being the original author's (which generally means you can't be the
original author in such a case, yet the absence of a From: suggests
you are).

Jan


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

* Re: [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-09 10:33     ` Jan Beulich
@ 2024-01-10  0:37       ` Stefano Stabellini
  2024-01-18 14:27       ` Carlo Nonato
  1 sibling, 0 replies; 90+ messages in thread
From: Stefano Stabellini @ 2024-01-10  0:37 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Andrew Cooper, George Dunlap,
	Wei Liu, Marco Solieri, xen-devel

On Tue, 9 Jan 2024, Jan Beulich wrote:
> On 09.01.2024 11:28, Jan Beulich wrote:
> > On 02.01.2024 10:51, Carlo Nonato wrote:
> >> v5:
> >> - Carlo Nonato as the new author
> >> - the colored allocator balances color usage for each domain and it searches
> >>   linearly only in the number of colors (FIXME removed)
> > 
> > While this addresses earlier concerns, meanwhile NUMA work has also
> > been progressing. What's the plan of interaction of coloring with it?
> 
> Thinking of interactions - what about static memory? Is coloring incompatible
> with that? If so, should the two features be excluded to both be used at the
> same time?

Yes the two features are incompatible. It makes sense to reject attempts
to enable both at the same time.


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

* Re: [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-09 10:28   ` Jan Beulich
  2024-01-09 10:33     ` Jan Beulich
@ 2024-01-10  0:46     ` Stefano Stabellini
  2024-01-10  9:10       ` Jan Beulich
  2024-01-15 11:07     ` Carlo Nonato
  2 siblings, 1 reply; 90+ messages in thread
From: Stefano Stabellini @ 2024-01-10  0:46 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Carlo Nonato, Stefano Stabellini, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Andrew Cooper, George Dunlap,
	Wei Liu, Marco Solieri, xen-devel

On Tue, 9 Jan 2024, Jan Beulich wrote:
> On 02.01.2024 10:51, Carlo Nonato wrote:
> > This commit adds a new memory page allocator that implements the cache
> > coloring mechanism. The allocation algorithm enforces equal frequency
> > distribution of cache partitions, following the coloring configuration of a
> > domain. This allows an even utilization of cache sets for every domain.
> > 
> > Pages are stored in a color-indexed array of lists. Those lists are filled
> > by a simple init function which computes the color of each page.
> > When a domain requests a page, the allocator extract the page from the list
> > with the maximum number of free pages between those that the domain can
> > access, given its coloring configuration.
> > 
> > The allocator can only handle requests of order-0 pages. This allows for
> > easier implementation and since cache coloring targets only embedded systems,
> > it's assumed not to be a major problem.
> 
> I'm curious about the specific properties of embedded systems that makes
> the performance implications of deeper page walks less of an issue for
> them.

I think Carlo meant to say that embedded systems tend to have a smaller
amount of RAM (our boards today have 4-8GB of total memory). So higher
level allocations (2MB/1GB) might not be possible.

Also, domains that care about interrupt latency tend to be RTOSes (e.g.
Zephyr, FreeRTOS) and RTOSes are happy to run with less than 1MB of
total memory available. This is so true that I vaguely remember hitting
a bug in xl/libxl when I tried to create a domain with 128KB of memory. 


> Nothing is said about address-constrained allocations. Are such entirely
> of no interest to domains on Arm, not even to Dom0 (e.g. for filling
> Linux'es swiotlb)?

Cache coloring is useful if you can use an IOMMU with all the
dma-capable devices. If that is not the case, then not even Dom0 would
be able to boot with cache coloring enabled (because it wouldn't be 1:1
mapped).

On ARM we only support booting Dom0 1:1 mapped, or not-1:1-mapped but
relying on the IOMMU.


> Certainly alloc_color_heap_page() should at least fail when it can't
> satisfy the passed in memflags.

[...]


> > +void dump_color_heap(void)
> > +{
> > +    unsigned int color;
> > +
> > +    printk("Dumping color heap info\n");
> > +    for ( color = 0; color < get_nr_llc_colors(); color++ )
> > +        if ( free_colored_pages[color] > 0 )
> > +            printk("Color heap[%u]: %lu pages\n",
> > +                   color, free_colored_pages[color]);
> > +}
> 
> What's a typical range of number of colors on a system? I expect more
> than 9, but I'm not sure about a reasonable upper bound. For the
> output to be easy to consume, [%u] may want to become at least [%2u].

16 colors on our boards


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

* Re: [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-10  0:46     ` Stefano Stabellini
@ 2024-01-10  9:10       ` Jan Beulich
  2024-01-11 23:25         ` Stefano Stabellini
  0 siblings, 1 reply; 90+ messages in thread
From: Jan Beulich @ 2024-01-10  9:10 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Carlo Nonato, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, xen-devel

On 10.01.2024 01:46, Stefano Stabellini wrote:
> On Tue, 9 Jan 2024, Jan Beulich wrote:
>> On 02.01.2024 10:51, Carlo Nonato wrote:
>>> This commit adds a new memory page allocator that implements the cache
>>> coloring mechanism. The allocation algorithm enforces equal frequency
>>> distribution of cache partitions, following the coloring configuration of a
>>> domain. This allows an even utilization of cache sets for every domain.
>>>
>>> Pages are stored in a color-indexed array of lists. Those lists are filled
>>> by a simple init function which computes the color of each page.
>>> When a domain requests a page, the allocator extract the page from the list
>>> with the maximum number of free pages between those that the domain can
>>> access, given its coloring configuration.
>>>
>>> The allocator can only handle requests of order-0 pages. This allows for
>>> easier implementation and since cache coloring targets only embedded systems,
>>> it's assumed not to be a major problem.
>>
>> I'm curious about the specific properties of embedded systems that makes
>> the performance implications of deeper page walks less of an issue for
>> them.
> 
> I think Carlo meant to say that embedded systems tend to have a smaller
> amount of RAM (our boards today have 4-8GB of total memory). So higher
> level allocations (2MB/1GB) might not be possible.
> 
> Also, domains that care about interrupt latency tend to be RTOSes (e.g.
> Zephyr, FreeRTOS) and RTOSes are happy to run with less than 1MB of
> total memory available. This is so true that I vaguely remember hitting
> a bug in xl/libxl when I tried to create a domain with 128KB of memory. 
> 
> 
>> Nothing is said about address-constrained allocations. Are such entirely
>> of no interest to domains on Arm, not even to Dom0 (e.g. for filling
>> Linux'es swiotlb)?
> 
> Cache coloring is useful if you can use an IOMMU with all the
> dma-capable devices. If that is not the case, then not even Dom0 would
> be able to boot with cache coloring enabled (because it wouldn't be 1:1
> mapped).
> 
> On ARM we only support booting Dom0 1:1 mapped, or not-1:1-mapped but
> relying on the IOMMU.

So another constraint to be enforced both at the Kconfig level and at
runtime? That said, Linux'es swiotlb allocation can't know whether an
IOMMU is in use by Xen. If something like that was done in a Dom0, the
respective allocations still wouldn't really work correctly (and the
kernel may or may not choke on this).

Jan


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

* Re: [PATCH v5 01/13] xen/common: add cache coloring common code
  2024-01-08 16:53   ` Jan Beulich
@ 2024-01-11 10:10     ` Carlo Nonato
  2024-01-11 10:16       ` Jan Beulich
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-11 10:10 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Marco Solieri, xen-devel

Hi Jan,

On Mon, Jan 8, 2024 at 5:53 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 02.01.2024 10:51, Carlo Nonato wrote:
> > This commit adds the Last Level Cache (LLC) coloring common header, Kconfig
> > options and functions. Since this is an arch specific feature, actual
> > implementation is postponed to later patches and Kconfig options are placed
> > under xen/arch.
>
> As a general remark / nit: "This commit", "this patch", or alike aren't
> well suited for descriptions.
>
> > --- a/xen/arch/Kconfig
> > +++ b/xen/arch/Kconfig
> > @@ -31,3 +31,19 @@ config NR_NUMA_NODES
> >         associated with multiple-nodes management. It is the upper bound of
> >         the number of NUMA nodes that the scheduler, memory allocation and
> >         other NUMA-aware components can handle.
> > +
> > +config LLC_COLORING
> > +     bool "Last Level Cache (LLC) coloring" if EXPERT
> > +     depends on HAS_LLC_COLORING
> > +
> > +config NR_LLC_COLORS
> > +     int "Maximum number of LLC colors"
> > +     default 128
>
> What if I set to value to 0? Or to an unreasonably large one? You don't
> bound the value range at all.

I can reintroduce the range (it was there in previous versions). I just don't
know what numbers to put.
range 2 1024 seems reasonable since having 1 color only actually lowers
performances because of the obvious sharing of resources. 1024 are the colors
that can fit into a standard 4KiB page. It's big enough for currently
supported hardware that normally has 16 or 32 colors.

> > --- a/xen/common/domain.c
> > +++ b/xen/common/domain.c
> > @@ -7,6 +7,7 @@
> >  #include <xen/compat.h>
> >  #include <xen/init.h>
> >  #include <xen/lib.h>
> > +#include <xen/llc-coloring.h>
> >  #include <xen/ctype.h>
> >  #include <xen/err.h>
> >  #include <xen/param.h>
> > @@ -1144,6 +1145,9 @@ static void cf_check complete_domain_destroy(struct rcu_head *head)
> >      struct vcpu *v;
> >      int i;
> >
> > +    if ( is_domain_llc_colored(d) )
> > +        domain_llc_coloring_free(d);
>
> Would be nice if the freeing function could be called unconditionally,
> being a no-op for non-colored domains.

Ok.

> Further - is it really necessary to do this freeing this late?

No, I can move it in domain_destroy().

> > --- a/xen/common/keyhandler.c
> > +++ b/xen/common/keyhandler.c
> > @@ -6,6 +6,7 @@
> >  #include <xen/debugger.h>
> >  #include <xen/delay.h>
> >  #include <xen/keyhandler.h>
> > +#include <xen/llc-coloring.h>
> >  #include <xen/param.h>
> >  #include <xen/shutdown.h>
> >  #include <xen/event.h>
> > @@ -307,6 +308,9 @@ static void cf_check dump_domains(unsigned char key)
> >
> >          arch_dump_domain_info(d);
> >
> > +        if ( is_domain_llc_colored(d) )
> > +            domain_dump_llc_colors(d);
>
> I'm less concerned of the conditional here, but along the lines of the
> comment above, it could of course again be the function that simply is
> a no-op for non-colored domains.

Ok.

> > --- /dev/null
> > +++ b/xen/include/xen/llc-coloring.h
> > @@ -0,0 +1,46 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Last Level Cache (LLC) coloring common header
> > + *
> > + * Copyright (C) 2022 Xilinx Inc.
> > + *
> > + * Authors:
> > + *    Carlo Nonato <carlo.nonato@minervasys.tech>
> > + */
> > +#ifndef __COLORING_H__
> > +#define __COLORING_H__
> > +
> > +#include <xen/sched.h>
> > +#include <public/domctl.h>
> > +
> > +#ifdef CONFIG_HAS_LLC_COLORING
>
> Why does this matter here? IOW why ...
>
> > +#include <asm/llc-coloring.h>
> > +
> > +#ifdef CONFIG_LLC_COLORING
>
> ... is it not just this which is checked?
>
> > +extern bool llc_coloring_enabled;
> > +#define llc_coloring_enabled (llc_coloring_enabled)
> > +#endif
> > +
> > +#endif
> > +
> > +#ifndef llc_coloring_enabled
> > +#define llc_coloring_enabled (false)
> > +#endif
>
> +1 to the question Julien has raised here.

Yes this whole block can be better structured.

> > --- a/xen/include/xen/sched.h
> > +++ b/xen/include/xen/sched.h
> > @@ -626,6 +626,11 @@ struct domain
> >
> >      /* Holding CDF_* constant. Internal flags for domain creation. */
> >      unsigned int cdf;
> > +
> > +#ifdef CONFIG_LLC_COLORING
> > +    unsigned int *llc_colors;
>
> Can the color values change over the lifetime of a domain? If not,
> it may be prudent to have this be pointer-to-const.

Can I free a pointer-to-const array?

> Jan
>
> > +    unsigned int num_llc_colors;
> > +#endif
> >  };
> >
> >  static inline struct page_list_head *page_to_list(
>

Thanks.


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

* Re: [PATCH v5 01/13] xen/common: add cache coloring common code
  2024-01-11 10:10     ` Carlo Nonato
@ 2024-01-11 10:16       ` Jan Beulich
  0 siblings, 0 replies; 90+ messages in thread
From: Jan Beulich @ 2024-01-11 10:16 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Marco Solieri, xen-devel

On 11.01.2024 11:10, Carlo Nonato wrote:
> On Mon, Jan 8, 2024 at 5:53 PM Jan Beulich <jbeulich@suse.com> wrote:
>> On 02.01.2024 10:51, Carlo Nonato wrote:
>>> --- a/xen/include/xen/sched.h
>>> +++ b/xen/include/xen/sched.h
>>> @@ -626,6 +626,11 @@ struct domain
>>>
>>>      /* Holding CDF_* constant. Internal flags for domain creation. */
>>>      unsigned int cdf;
>>> +
>>> +#ifdef CONFIG_LLC_COLORING
>>> +    unsigned int *llc_colors;
>>
>> Can the color values change over the lifetime of a domain? If not,
>> it may be prudent to have this be pointer-to-const.
> 
> Can I free a pointer-to-const array?

Well, you certainly can by using a cast. Avoiding the need for such call-
site casts is why I've been advocating to make xfree() / vfree() match e.g.
vunmap() / _vfree() in this regard. Yet other opinions are that the const
there ought to be dropped (without me really following the reasoning) ...

There's also the option of circumventing the need for a cast by doing

    xfree(__va(__pa(ptr)));

Jan


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

* Re: [PATCH v5 02/13] xen/arm: add cache coloring initialization
  2024-01-05 16:34     ` Carlo Nonato
  2024-01-05 17:44       ` Julien Grall
@ 2024-01-11 10:17       ` Carlo Nonato
  2024-01-11 10:44         ` Julien Grall
  1 sibling, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-11 10:17 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien,

> > > +bool __init llc_coloring_init(void)
> > > +{
> > > +    if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
> > > +    {
> > > +        printk(XENLOG_ERR
> > > +               "Probed LLC way size is 0 and no custom value provided\n");
> > > +        return false;
> > > +    }
> > > +
> > > +    /*
> > > +     * The maximum number of colors must be a power of 2 in order to correctly
> > > +     * map them to bits of an address, so also the LLC way size must be so.
> > > +     */
> > > +    if ( llc_way_size & (llc_way_size - 1) )
> > > +    {
> > > +        printk(XENLOG_WARNING "LLC way size (%u) isn't a power of 2.\n",
> > > +               llc_way_size);
> > > +        llc_way_size = 1U << flsl(llc_way_size);
> > > +        printk(XENLOG_WARNING
> > > +               "Using %u instead. Performances will be suboptimal\n",
> > > +               llc_way_size);
> > > +    }
> > > +
> > > +    nr_colors = llc_way_size >> PAGE_SHIFT;
> > > +
> > > +    if ( nr_colors < 2 || nr_colors > CONFIG_NR_LLC_COLORS )
> >
> > I didn't find any documentation explaining why we need at least two
> > colors. I guess you want to make sure that there is a color for Xen and
> > domain. But I wonder what could wrong with just one color (other than
> > been pointless)?
>
> Yes, it would just be pointless. I'll change it to 1.

Just wanted to correct myself here. Having just a single color introduces a
clear sharing of the cache between Xen and domains. So it's not just
pointless, but also inefficient. I would discourage such a configuration, so I
plan to better describe this with a range in the Kconfig option (see
discussion in #1).

Thanks


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

* Re: [PATCH v5 02/13] xen/arm: add cache coloring initialization
  2024-01-11 10:17       ` Carlo Nonato
@ 2024-01-11 10:44         ` Julien Grall
  2024-01-15 11:05           ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-11 10:44 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri



On 11/01/2024 10:17, Carlo Nonato wrote:
> Hi Julien,

Hi Carlo,

>>>> +bool __init llc_coloring_init(void)
>>>> +{
>>>> +    if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
>>>> +    {
>>>> +        printk(XENLOG_ERR
>>>> +               "Probed LLC way size is 0 and no custom value provided\n");
>>>> +        return false;
>>>> +    }
>>>> +
>>>> +    /*
>>>> +     * The maximum number of colors must be a power of 2 in order to correctly
>>>> +     * map them to bits of an address, so also the LLC way size must be so.
>>>> +     */
>>>> +    if ( llc_way_size & (llc_way_size - 1) )
>>>> +    {
>>>> +        printk(XENLOG_WARNING "LLC way size (%u) isn't a power of 2.\n",
>>>> +               llc_way_size);
>>>> +        llc_way_size = 1U << flsl(llc_way_size);
>>>> +        printk(XENLOG_WARNING
>>>> +               "Using %u instead. Performances will be suboptimal\n",
>>>> +               llc_way_size);
>>>> +    }
>>>> +
>>>> +    nr_colors = llc_way_size >> PAGE_SHIFT;
>>>> +
>>>> +    if ( nr_colors < 2 || nr_colors > CONFIG_NR_LLC_COLORS )
>>>
>>> I didn't find any documentation explaining why we need at least two
>>> colors. I guess you want to make sure that there is a color for Xen and
>>> domain. But I wonder what could wrong with just one color (other than
>>> been pointless)?
>>
>> Yes, it would just be pointless. I'll change it to 1.
> 
> Just wanted to correct myself here. Having just a single color introduces a
> clear sharing of the cache between Xen and domains. So it's not just
> pointless, but also inefficient. I would discourage such a configuration, so I
> plan to better describe this with a range in the Kconfig option (see
> discussion in #1).

I understand this could be inneficient. But you are also allowing the 
user to not specify the color configuration (at least for dom0less 
domain). So the colors would end up to shared with everyone (including Xen).

I don't particularly mind which way you want to go, but I think we need 
some coherency. If we want to avoid innefficiency, then we should 
prevent all the setups.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-10  9:10       ` Jan Beulich
@ 2024-01-11 23:25         ` Stefano Stabellini
  0 siblings, 0 replies; 90+ messages in thread
From: Stefano Stabellini @ 2024-01-11 23:25 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Carlo Nonato, Julien Grall, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Andrew Cooper, George Dunlap,
	Wei Liu, Marco Solieri, xen-devel

On Wed, 10 Jan 2024, Jan Beulich wrote:
> On 10.01.2024 01:46, Stefano Stabellini wrote:
> > On Tue, 9 Jan 2024, Jan Beulich wrote:
> >> On 02.01.2024 10:51, Carlo Nonato wrote:
> >>> This commit adds a new memory page allocator that implements the cache
> >>> coloring mechanism. The allocation algorithm enforces equal frequency
> >>> distribution of cache partitions, following the coloring configuration of a
> >>> domain. This allows an even utilization of cache sets for every domain.
> >>>
> >>> Pages are stored in a color-indexed array of lists. Those lists are filled
> >>> by a simple init function which computes the color of each page.
> >>> When a domain requests a page, the allocator extract the page from the list
> >>> with the maximum number of free pages between those that the domain can
> >>> access, given its coloring configuration.
> >>>
> >>> The allocator can only handle requests of order-0 pages. This allows for
> >>> easier implementation and since cache coloring targets only embedded systems,
> >>> it's assumed not to be a major problem.
> >>
> >> I'm curious about the specific properties of embedded systems that makes
> >> the performance implications of deeper page walks less of an issue for
> >> them.
> > 
> > I think Carlo meant to say that embedded systems tend to have a smaller
> > amount of RAM (our boards today have 4-8GB of total memory). So higher
> > level allocations (2MB/1GB) might not be possible.
> > 
> > Also, domains that care about interrupt latency tend to be RTOSes (e.g.
> > Zephyr, FreeRTOS) and RTOSes are happy to run with less than 1MB of
> > total memory available. This is so true that I vaguely remember hitting
> > a bug in xl/libxl when I tried to create a domain with 128KB of memory. 
> > 
> > 
> >> Nothing is said about address-constrained allocations. Are such entirely
> >> of no interest to domains on Arm, not even to Dom0 (e.g. for filling
> >> Linux'es swiotlb)?
> > 
> > Cache coloring is useful if you can use an IOMMU with all the
> > dma-capable devices. If that is not the case, then not even Dom0 would
> > be able to boot with cache coloring enabled (because it wouldn't be 1:1
> > mapped).
> > 
> > On ARM we only support booting Dom0 1:1 mapped, or not-1:1-mapped but
> > relying on the IOMMU.
> 
> So another constraint to be enforced both at the Kconfig level and at
> runtime?

Yeah potentially


> That said, Linux'es swiotlb allocation can't know whether an
> IOMMU is in use by Xen.

Well, not exactly but we have XENFEAT_direct_mapped and
XENFEAT_not_direct_mapped, that is how normally the kernel knows how to
behave


> If something like that was done in a Dom0, the
> respective allocations still wouldn't really work correctly (and the
> kernel may or may not choke on this).
 


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

* Re: [PATCH v5 07/13] xen/page_alloc: introduce init_free_page_fields() helper
  2024-01-09 10:36   ` Jan Beulich
@ 2024-01-12  9:43     ` Carlo Nonato
  0 siblings, 0 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-12  9:43 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, George Dunlap, Julien Grall, Stefano Stabellini,
	Wei Liu, Marco Solieri, xen-devel

Hi Jan,

On Tue, Jan 9, 2024 at 11:36 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 02.01.2024 10:51, Carlo Nonato wrote:
> > Introduce a new helper to initialize fields that have different uses for
> > free pages.
> >
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
>
> I might in principle ack this change, but what's the deal with this 2nd
> S-o-b? The typical expectation is for yours to be last, and the 1st one
> being the original author's (which generally means you can't be the
> original author in such a case, yet the absence of a From: suggests
> you are).

You're right. I mistakenly copied it from other patches.
I did the same in #10. Will remove Marco Solieri from those.
But there are some patches where we are both authors, so I will leave both
Signed-off-by.

Thanks.

> Jan


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

* Re: [PATCH v5 08/13] xen/page_alloc: introduce preserved page flags macro
  2024-01-08 17:08   ` Jan Beulich
@ 2024-01-12 10:01     ` Carlo Nonato
  2024-01-12 10:22       ` Jan Beulich
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-12 10:01 UTC (permalink / raw)
  To: Jan Beulich
  Cc: xen-devel, Andrew Cooper, George Dunlap, Julien Grall,
	Stefano Stabellini, Wei Liu, Marco Solieri

Hi Jan,

On Mon, Jan 8, 2024 at 6:08 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 02.01.2024 10:51, Carlo Nonato wrote:
> > PGC_static and PGC_extra are flags that needs to be preserved when assigning
> > a page. Define a new macro that groups those flags and use it instead of
> > or'ing every time.
> >
> > The new macro is used also in free_heap_pages() allowing future commits to
> > extended it with other flags that must stop merging, as it now works for
> > PGC_static. PGC_extra is no harm here since it's only ever being set on
> > allocated pages.
>
> Is it? I can't see where free_domheap_pages() would clear it before calling
> free_heap_pages(). Or wait, that may happen in mark_page_free(), but then
> PGC_static would be cleared there, too. I must be missing something.
>
> > --- a/xen/common/page_alloc.c
> > +++ b/xen/common/page_alloc.c
> > @@ -158,6 +158,8 @@
> >  #define PGC_static 0
> >  #endif
> >
> > +#define preserved_flags (PGC_extra | PGC_static)
>
> I think this wants to (a) have a PGC_ prefix and (b) as a #define be all
> capitals.
>
> > @@ -1504,7 +1506,7 @@ static void free_heap_pages(
> >              /* Merge with predecessor block? */
> >              if ( !mfn_valid(page_to_mfn(predecessor)) ||
> >                   !page_state_is(predecessor, free) ||
> > -                 (predecessor->count_info & PGC_static) ||
> > +                 (predecessor->count_info & preserved_flags) ||
> >                   (PFN_ORDER(predecessor) != order) ||
> >                   (page_to_nid(predecessor) != node) )
> >                  break;
> > @@ -1528,7 +1530,7 @@ static void free_heap_pages(
> >              /* Merge with successor block? */
> >              if ( !mfn_valid(page_to_mfn(successor)) ||
> >                   !page_state_is(successor, free) ||
> > -                 (successor->count_info & PGC_static) ||
> > +                 (successor->count_info & preserved_flags) ||
> >                   (PFN_ORDER(successor) != order) ||
> >                   (page_to_nid(successor) != node) )
> >                  break;
>
> Irrespective of the comment at the top, this looks like an abuse of the
> new constant: There's nothing inherently making preserved flags also
> suppress merging (assuming it was properly checked that both sided have
> the same flags set/clear).

Sorry, I may have misinterpreted your comments on the previous version of the
series (I know it was a really long time ago)

https://patchew.org/Xen/20230123154735.74832-1-carlo.nonato@minervasys.tech/20230123154735.74832-8-carlo.nonato@minervasys.tech/#c843b031-52f7-056d-e8c0-75fe9c426343@suse.com

Anyway, would the solution here be to have two distinct #define? One for
suppress merging and the other for preserved flags. This would probably also
remove any confusion with the usage of PGC_extra.

Thanks.

> Jan


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

* Re: [PATCH v5 08/13] xen/page_alloc: introduce preserved page flags macro
  2024-01-12 10:01     ` Carlo Nonato
@ 2024-01-12 10:22       ` Jan Beulich
  0 siblings, 0 replies; 90+ messages in thread
From: Jan Beulich @ 2024-01-12 10:22 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Andrew Cooper, George Dunlap, Julien Grall,
	Stefano Stabellini, Wei Liu, Marco Solieri

On 12.01.2024 11:01, Carlo Nonato wrote:
> On Mon, Jan 8, 2024 at 6:08 PM Jan Beulich <jbeulich@suse.com> wrote:
>> On 02.01.2024 10:51, Carlo Nonato wrote:
>>> PGC_static and PGC_extra are flags that needs to be preserved when assigning
>>> a page. Define a new macro that groups those flags and use it instead of
>>> or'ing every time.
>>>
>>> The new macro is used also in free_heap_pages() allowing future commits to
>>> extended it with other flags that must stop merging, as it now works for
>>> PGC_static. PGC_extra is no harm here since it's only ever being set on
>>> allocated pages.
>>
>> Is it? I can't see where free_domheap_pages() would clear it before calling
>> free_heap_pages(). Or wait, that may happen in mark_page_free(), but then
>> PGC_static would be cleared there, too. I must be missing something.
>>
>>> --- a/xen/common/page_alloc.c
>>> +++ b/xen/common/page_alloc.c
>>> @@ -158,6 +158,8 @@
>>>  #define PGC_static 0
>>>  #endif
>>>
>>> +#define preserved_flags (PGC_extra | PGC_static)
>>
>> I think this wants to (a) have a PGC_ prefix and (b) as a #define be all
>> capitals.
>>
>>> @@ -1504,7 +1506,7 @@ static void free_heap_pages(
>>>              /* Merge with predecessor block? */
>>>              if ( !mfn_valid(page_to_mfn(predecessor)) ||
>>>                   !page_state_is(predecessor, free) ||
>>> -                 (predecessor->count_info & PGC_static) ||
>>> +                 (predecessor->count_info & preserved_flags) ||
>>>                   (PFN_ORDER(predecessor) != order) ||
>>>                   (page_to_nid(predecessor) != node) )
>>>                  break;
>>> @@ -1528,7 +1530,7 @@ static void free_heap_pages(
>>>              /* Merge with successor block? */
>>>              if ( !mfn_valid(page_to_mfn(successor)) ||
>>>                   !page_state_is(successor, free) ||
>>> -                 (successor->count_info & PGC_static) ||
>>> +                 (successor->count_info & preserved_flags) ||
>>>                   (PFN_ORDER(successor) != order) ||
>>>                   (page_to_nid(successor) != node) )
>>>                  break;
>>
>> Irrespective of the comment at the top, this looks like an abuse of the
>> new constant: There's nothing inherently making preserved flags also
>> suppress merging (assuming it was properly checked that both sided have
>> the same flags set/clear).
> 
> Sorry, I may have misinterpreted your comments on the previous version of the
> series (I know it was a really long time ago)
> 
> https://patchew.org/Xen/20230123154735.74832-1-carlo.nonato@minervasys.tech/20230123154735.74832-8-carlo.nonato@minervasys.tech/#c843b031-52f7-056d-e8c0-75fe9c426343@suse.com
> 
> Anyway, would the solution here be to have two distinct #define? One for
> suppress merging and the other for preserved flags. This would probably also
> remove any confusion with the usage of PGC_extra.

That's one way to deal with this. Another would be to refine the above
checks, such that both buddies' preserved flags are actually compared,
and merging be suppressed if they're different. Then going with a single
#define would imo be quite okay.

Jan


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-05 19:12   ` Julien Grall
@ 2024-01-13 17:07     ` Carlo Nonato
  2024-01-14 19:22       ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-13 17:07 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Julien,

On Fri, Jan 5, 2024 at 8:12 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 02/01/2024 09:51, Carlo Nonato wrote:
> > This commit adds the cache coloring support for Xen own physical space.
> >
> > It extends the implementation of setup_pagetables() to make use of Xen
> > cache coloring configuration. Page tables construction is essentially the
> > same except for the fact that PTEs point to a new temporary mapped,
> > physically colored space.
> >
> > The temporary mapping is also used to relocate Xen to the new physical
> > space starting at the address taken from the old get_xen_paddr() function
> > which is brought back for the occasion.
> > The temporary mapping is finally converted to a mapping of the "old"
> > (meaning the original physical space) Xen code, so that the boot CPU can
> > actually address the variables and functions used by secondary CPUs until
> > they enable the MMU. This happens when the boot CPU needs to bring up other
> > CPUs (psci.c and smpboot.c) and when the TTBR value is passed to them
> > (prepare_secondary_mm()).
> >
> > Finally, since the alternative framework needs to remap the Xen text and
> > inittext sections, this operation must be done in a coloring-aware way.
> > The function xen_remap_colored() is introduced for that.
> >
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > ---
> > v5:
> > - FIXME: consider_modules copy pasted since it got moved
> > v4:
> > - removed set_value_for_secondary() because it was wrongly cleaning cache
> > - relocate_xen() now calls switch_ttbr_id()
> > ---
> >   xen/arch/arm/alternative.c              |   9 +-
> >   xen/arch/arm/arm64/mmu/head.S           |  48 +++++++
> >   xen/arch/arm/arm64/mmu/mm.c             |  26 +++-
> >   xen/arch/arm/include/asm/llc-coloring.h |  16 +++
> >   xen/arch/arm/include/asm/mm.h           |   7 +-
> >   xen/arch/arm/llc-coloring.c             |  44 +++++++
> >   xen/arch/arm/mmu/setup.c                |  82 +++++++++++-
> >   xen/arch/arm/mmu/smpboot.c              |  11 +-
> >   xen/arch/arm/psci.c                     |   9 +-
> >   xen/arch/arm/setup.c                    | 165 +++++++++++++++++++++++-
> >   xen/arch/arm/smpboot.c                  |   9 +-
>
> This patch has is touching a lot of different components. I think this
> want to be split in more smaller chunk. It would also be help to mention
> what code has been copied from previous Xen. For instance,
> relocate_xen() is clearly a copy of f60658c6ae47.
>
> >   11 files changed, 406 insertions(+), 20 deletions(-)
> >
> > diff --git a/xen/arch/arm/alternative.c b/xen/arch/arm/alternative.c
> > index 016e66978b..54cbc2afad 100644
> > --- a/xen/arch/arm/alternative.c
> > +++ b/xen/arch/arm/alternative.c
> > @@ -9,6 +9,7 @@
> >   #include <xen/init.h>
> >   #include <xen/types.h>
> >   #include <xen/kernel.h>
> > +#include <xen/llc-coloring.h>
> >   #include <xen/mm.h>
> >   #include <xen/vmap.h>
> >   #include <xen/smp.h>
> > @@ -209,8 +210,12 @@ void __init apply_alternatives_all(void)
> >        * The text and inittext section are read-only. So re-map Xen to
> >        * be able to patch the code.
> >        */
> > -    xenmap = __vmap(&xen_mfn, 1U << xen_order, 1, 1, PAGE_HYPERVISOR,
> > -                    VMAP_DEFAULT);
> > +    if ( llc_coloring_enabled )
> > +        xenmap = xen_remap_colored(xen_mfn, xen_size);
> > +    else
> > +        xenmap = __vmap(&xen_mfn, 1U << xen_order, 1, 1, PAGE_HYPERVISOR,
> > +                        VMAP_DEFAULT);
> > +
> >       /* Re-mapping Xen is not expected to fail during boot. */
> >       BUG_ON(!xenmap);
> >
> > diff --git a/xen/arch/arm/arm64/mmu/head.S b/xen/arch/arm/arm64/mmu/head.S
> > index 10774f30e4..6f0cc72897 100644
> > --- a/xen/arch/arm/arm64/mmu/head.S
> > +++ b/xen/arch/arm/arm64/mmu/head.S
> > @@ -419,6 +419,54 @@ fail:   PRINT("- Boot failed -\r\n")
> >           b     1b
> >   ENDPROC(fail)
> >
> > +/* Copy Xen to new location and switch TTBR
> > + * x0    ttbr
> > + * x1    source address
> > + * x2    destination address
> > + * x3    length
> > + *
> > + * Source and destination must be word aligned, length is rounded up
> > + * to a 16 byte boundary.
> > + *
> > + * MUST BE VERY CAREFUL when saving things to RAM over the copy */
>
> If you plan to re-introduce code, then please at least make sure it
> match the coding style. For comments, it should be:
>
> /*
>   * Foo
>   * Bar
>   */
>
> > +ENTRY(relocate_xen)
> > +        /* Copy 16 bytes at a time using:
> > +         *   x9: counter
> > +         *   x10: data
> > +         *   x11: data
> > +         *   x12: source
> > +         *   x13: destination
> > +         */
> > +        mov     x9, x3
> > +        mov     x12, x1
> > +        mov     x13, x2
> > +
> > +1:      ldp     x10, x11, [x12], #16
> > +        stp     x10, x11, [x13], #16
> > +
> > +        subs    x9, x9, #16
> > +        bgt     1b
> > +
> > +        /* Flush destination from dcache using:
>
> I would explain why you need the flush. AFAICT, this is because you want
> the data to be visible to the instruction cache. I would also point out
> that you need the instruction cache flush in switch_ttbr_id() where the
> sentence "This should not be necessary ..." should be now reworked
> (AFAIK it is mandatory for cache coloring).
>
> > +         * x9: counter
> > +         * x10: step
> > +         * x11: vaddr
> > +         */
> > +        dsb   sy        /* So the CPU issues all writes to the range */
> > +
> > +        mov   x9, x3
> > +        ldr   x10, =dcache_line_bytes /* x10 := step */
> > +        ldr   x10, [x10]
> > +        mov   x11, x2
> > +
> > +1:      dc    cvac, x11
> > +
> > +        add   x11, x11, x10
> > +        subs  x9, x9, x10
> > +        bgt   1b
> > +
>
> I would add a comment here explaining you are relying on the dsb/isb in
> switch_ttbr_id().
>
> > +        b switch_ttbr_id
> > +
> >   /*
> >    * Switch TTBR
> >    *
> > diff --git a/xen/arch/arm/arm64/mmu/mm.c b/xen/arch/arm/arm64/mmu/mm.c
> > index d2651c9486..5a26d64ab7 100644
> > --- a/xen/arch/arm/arm64/mmu/mm.c
> > +++ b/xen/arch/arm/arm64/mmu/mm.c
> > @@ -1,6 +1,7 @@
> >   /* SPDX-License-Identifier: GPL-2.0 */
> >
> >   #include <xen/init.h>
> > +#include <xen/llc-coloring.h>
> >   #include <xen/mm.h>
> >   #include <xen/pfn.h>
> >
> > @@ -125,27 +126,44 @@ void update_identity_mapping(bool enable)
> >   }
> >
> >   extern void switch_ttbr_id(uint64_t ttbr);
> > +extern void relocate_xen(uint64_t ttbr, void *src, void *dst, size_t len);
> >
> >   typedef void (switch_ttbr_fn)(uint64_t ttbr);
> > +typedef void (relocate_xen_fn)(uint64_t ttbr, void *src, void *dst, size_t len);
> >
> >   void __init switch_ttbr(uint64_t ttbr)
> >   {
> > -    vaddr_t id_addr = virt_to_maddr(switch_ttbr_id);
> > -    switch_ttbr_fn *fn = (switch_ttbr_fn *)id_addr;
> > +    vaddr_t vaddr, id_addr;
> >       lpae_t pte;
> >
> > +    if ( llc_coloring_enabled )
> > +        vaddr = (vaddr_t)relocate_xen;
> > +    else
> > +        vaddr = (vaddr_t)switch_ttbr_id;
> > +
> > +    id_addr = virt_to_maddr(vaddr);
> > +
> >       /* Enable the identity mapping in the boot page tables */
> >       update_identity_mapping(true);
> >
> >       /* Enable the identity mapping in the runtime page tables */
> > -    pte = pte_of_xenaddr((vaddr_t)switch_ttbr_id);
> > +    pte = pte_of_xenaddr(vaddr);
> >       pte.pt.table = 1;
> >       pte.pt.xn = 0;
> >       pte.pt.ro = 1;
> >       write_pte(&xen_third_id[third_table_offset(id_addr)], pte);
> >
> >       /* Switch TTBR */
> > -    fn(ttbr);
> > +    if ( llc_coloring_enabled )
> > +    {
> > +        relocate_xen_fn *fn = (relocate_xen_fn *)id_addr;
>
> Coding style: We tend to add a new line after variable declaration.
>
> > +        fn(ttbr, _start, (void *)BOOT_RELOC_VIRT_START, _end - _start);
> > +    }
> > +    else
> > +    {
> > +        switch_ttbr_fn *fn = (switch_ttbr_fn *)id_addr;
>
> Ditto for the coding style.
>
> > +        fn(ttbr);
> > +    }
> >
> >       /*
> >        * Disable the identity mapping in the runtime page tables.
> > diff --git a/xen/arch/arm/include/asm/llc-coloring.h b/xen/arch/arm/include/asm/llc-coloring.h
> > index 5f9b0a8121..4d6071e50b 100644
> > --- a/xen/arch/arm/include/asm/llc-coloring.h
> > +++ b/xen/arch/arm/include/asm/llc-coloring.h
> > @@ -12,11 +12,27 @@
> >   #define __ASM_ARM_COLORING_H__
> >
> >   #include <xen/init.h>
> > +#include <xen/mm-frame.h>
> > +
> > +/**
> > + * Iterate over each Xen mfn in the colored space.
> > + * @mfn:    the current mfn. The first non colored mfn must be provided as the
> > + *          starting point.
> > + * @i:      loop index.
> > + */
> > +#define for_each_xen_colored_mfn(mfn, i)        \
> > +    for ( i = 0, mfn = xen_colored_mfn(mfn);    \
> > +          i < (_end - _start) >> PAGE_SHIFT;    \
> > +          i++, mfn = xen_colored_mfn(mfn_add(mfn, 1)) )
> >
> >   bool __init llc_coloring_init(void);
> >   int dom0_set_llc_colors(struct domain *d);
> >   int domain_set_llc_colors_from_str(struct domain *d, const char *str);
> >
> > +paddr_t xen_colored_map_size(paddr_t size);
> > +mfn_t xen_colored_mfn(mfn_t mfn);
> > +void *xen_remap_colored(mfn_t xen_fn, paddr_t xen_size);
> > +
> >   #endif /* __ASM_ARM_COLORING_H__ */
> >
> >   /*
> > diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
> > index 1829c559d6..311f092cf2 100644
> > --- a/xen/arch/arm/include/asm/mm.h
> > +++ b/xen/arch/arm/include/asm/mm.h
> > @@ -203,12 +203,17 @@ extern unsigned long frametable_base_pdx;
> >
> >   #define PDX_GROUP_SHIFT SECOND_SHIFT
> >
> > +#define virt_to_reloc_virt(virt) \
> > +    (((vaddr_t)virt) - XEN_VIRT_START + BOOT_RELOC_VIRT_START)
> > +
> >   /* Boot-time pagetable setup */
> > -extern void setup_pagetables(unsigned long boot_phys_offset);
> > +extern void setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr);
> >   /* Map FDT in boot pagetable */
> >   extern void *early_fdt_map(paddr_t fdt_paddr);
> >   /* Remove early mappings */
> >   extern void remove_early_mappings(void);
> > +/* Remove early LLC coloring mappings */
> > +extern void remove_llc_coloring_mappings(void);
> >   /* Prepare the memory subystem to bring-up the given secondary CPU */
> >   extern int prepare_secondary_mm(int cpu);
> >   /* Map a frame table to cover physical addresses ps through pe */
> > diff --git a/xen/arch/arm/llc-coloring.c b/xen/arch/arm/llc-coloring.c
> > index 99ea69ad39..f434efc45b 100644
> > --- a/xen/arch/arm/llc-coloring.c
> > +++ b/xen/arch/arm/llc-coloring.c
> > @@ -14,6 +14,7 @@
> >   #include <xen/llc-coloring.h>
> >   #include <xen/param.h>
> >   #include <xen/types.h>
> > +#include <xen/vmap.h>
> >
> >   #include <asm/processor.h>
> >   #include <asm/sysregs.h>
> > @@ -38,6 +39,7 @@ static unsigned int __ro_after_init xen_num_colors;
> >
> >   #define mfn_color_mask              (nr_colors - 1)
> >   #define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
> > +#define mfn_set_color(mfn, color)   ((mfn_x(mfn) & ~mfn_color_mask) | (color))
> >
> >   /*
> >    * Parse the coloring configuration given in the buf string, following the
> > @@ -354,6 +356,48 @@ unsigned int get_nr_llc_colors(void)
> >       return nr_colors;
> >   }
> >
> > +paddr_t xen_colored_map_size(paddr_t size)
> > +{
> > +    return ROUNDUP(size * nr_colors, XEN_PADDR_ALIGN);
> > +}
> > + > +mfn_t xen_colored_mfn(mfn_t mfn)
>
> Is this going to be used outside of boot? If not, then please add
> __init. If yes, then can you point me where?
>
> > +{
> > +    unsigned int i, color = mfn_to_color(mfn);
> > +
> > +    for( i = 0; i < xen_num_colors; i++ )
> > +    {
> > +        if ( color == xen_colors[i] )
> > +            return mfn;
> > +        else if ( color < xen_colors[i] )
> > +            return mfn_set_color(mfn, xen_colors[i]);
> > +    }
> > +
> > +    /* Jump to next color space (nr_colors mfns) and use the first color */
> > +    return mfn_set_color(mfn_add(mfn, nr_colors), xen_colors[0]);
> > +}
> > +
> > +void *xen_remap_colored(mfn_t xen_mfn, paddr_t xen_size)
>
> I think this function can be __init.
>
> > +{
> > +    unsigned int i;
> > +    void *xenmap;
> > +    mfn_t *xen_colored_mfns;
> > +
> > +    xen_colored_mfns = xmalloc_array(mfn_t, xen_size >> PAGE_SHIFT);
> > +    if ( !xen_colored_mfns )
> > +        panic("Can't allocate LLC colored MFNs\n");
> Let's try to limit the number of panic(). In this case, I think you
> should return NULL and let the caller decide.
>
> > +
> > +    for_each_xen_colored_mfn( xen_mfn, i )
> > +    {
> > +        xen_colored_mfns[i] = xen_mfn;
> > +    }
> > +
> > +    xenmap = vmap(xen_colored_mfns, xen_size >> PAGE_SHIFT);
> > +    xfree(xen_colored_mfns);
> > +
> > +    return xenmap;
> > +}
> > +
> >   /*
> >    * Local variables:
> >    * mode: C
> > diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
> > index 37b6d230ad..66b674eeab 100644
> > --- a/xen/arch/arm/mmu/setup.c
> > +++ b/xen/arch/arm/mmu/setup.c
> > @@ -7,6 +7,7 @@
> >
> >   #include <xen/init.h>
> >   #include <xen/libfdt/libfdt.h>
> > +#include <xen/llc-coloring.h>
> >   #include <xen/sizes.h>
> >   #include <xen/vmap.h>
> >
> > @@ -39,6 +40,10 @@ DEFINE_PER_CPU(lpae_t *, xen_pgtable);
> >   static DEFINE_PAGE_TABLE(cpu0_pgtable);
> >   #endif
> >
> > +#ifdef CONFIG_LLC_COLORING
> > +static DEFINE_PAGE_TABLE(xen_colored_temp);
> > +#endif
>
> Does this actually need to be static?

Why it shouldn't be static? I don't want to access it from another file.

> And if yes, then is it necessary
> to be kept the boot as completed?

Nope. __initdata?

> Also, this is not going to be enough to cover Xen. See above.
>
>
> > +
> >   /* Common pagetable leaves */
> >   /* Second level page table used to cover Xen virtual address space */
> >   static DEFINE_PAGE_TABLE(xen_second);
> > @@ -130,7 +135,12 @@ static void __init __maybe_unused build_assertions(void)
> >
> >   lpae_t __init pte_of_xenaddr(vaddr_t va)
> >   {
> > -    paddr_t ma = va + phys_offset;
> > +    paddr_t ma;
> > +
> > +    if ( llc_coloring_enabled )
> > +        ma = virt_to_maddr(virt_to_reloc_virt(va));
> > +    else
> > +        ma = va + phys_offset;
> >
> >       return mfn_to_xen_entry(maddr_to_mfn(ma), MT_NORMAL);
> >   }
> > @@ -216,11 +226,55 @@ static void xen_pt_enforce_wnx(void)
> >       flush_xen_tlb_local();
> >   }
> >
> > +#ifdef CONFIG_LLC_COLORING
> > +static void __init create_llc_coloring_mappings(paddr_t xen_paddr)
> > +{
> > +    lpae_t pte;
> > +    unsigned int i;
> > +    mfn_t mfn = maddr_to_mfn(xen_paddr);
> > +
> > +    for_each_xen_colored_mfn( mfn, i )
> > +    {
> > +        pte = mfn_to_xen_entry(mfn, MT_NORMAL);
> > +        pte.pt.table = 1; /* level 3 mappings always have this bit set */
> > +        xen_colored_temp[i] = pte;
> > +    }
> > +
> > +    pte = mfn_to_xen_entry(virt_to_mfn(xen_colored_temp), MT_NORMAL);
> > +    pte.pt.table = 1;
> > +    write_pte(&boot_second[second_table_offset(BOOT_RELOC_VIRT_START)], pte);
> > +}
> > +
> > +void __init remove_llc_coloring_mappings(void)
> > +{
> > +    int rc;
> > +
> > +    /* destroy the _PAGE_BLOCK mapping */
> > +    rc = modify_xen_mappings(BOOT_RELOC_VIRT_START,
> > +                             BOOT_RELOC_VIRT_START + SZ_2M,
>
> See above, Xen can now be bigger than 2MB. The limit is 8MB and could
> change in the future.
>
> > +                             _PAGE_BLOCK);
> > +    BUG_ON(rc);
> > +}
> > +#else
> > +static void __init create_llc_coloring_mappings(paddr_t xen_paddr) {}
> > +void __init remove_llc_coloring_mappings(void) {}
>
> Both should never be called when !CONFIG_LCC_COLORING, correct? If so,
> then please add ASSERT_UNREACHABLE() in their body.
>
> > +#endif /* CONFIG_LLC_COLORING */
> > +
> >   /*
> > - * Boot-time pagetable setup.
> > + * Boot-time pagetable setup with coloring support
> >    * Changes here may need matching changes in head.S
> > + *
> > + * The coloring support consists of:
> > + * - Create a temporary colored mapping that conforms to Xen color selection.
> > + * - pte_of_xenaddr takes care of translating the virtual addresses to the
> > + *   new colored physical space and the returns the pte, so that the page table
> > + *   initialization can remain the same.
> > + * - Copy Xen to the new colored physical space by exploiting the temporary
> > + *   mapping.
> > + * - Update TTBR0_EL2 with the new root page table address.
> >    */
> > -void __init setup_pagetables(unsigned long boot_phys_offset)
> > +
> > +void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
> >   {
> >       uint64_t ttbr;
> >       lpae_t pte, *p;
> > @@ -228,6 +282,9 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
> >
> >       phys_offset = boot_phys_offset;
> >
> > +    if ( llc_coloring_enabled )
> > +        create_llc_coloring_mappings(xen_paddr);
> > +
> >       arch_setup_page_tables();
> >
> >   #ifdef CONFIG_ARM_64
> > @@ -281,10 +338,13 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
> >       pte.pt.table = 1;
> >       xen_second[second_table_offset(FIXMAP_ADDR(0))] = pte;
> >
> > +    if ( llc_coloring_enabled )
> > +        ttbr = virt_to_maddr(virt_to_reloc_virt(xen_pgtable));
>
> xen_pgtable is only valid for Arm64. But rather than ifdef-ing. I would
> consder to move...
>
> > +    else
> >   #ifdef CONFIG_ARM_64
> > -    ttbr = (uintptr_t) xen_pgtable + phys_offset;
> > +        ttbr = (uintptr_t) xen_pgtable + phys_offset;
> >   #else
> > -    ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
> > +        ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
> >   #endif
> >
> >       switch_ttbr(ttbr);
> > @@ -294,6 +354,18 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
> >   #ifdef CONFIG_ARM_32
> >       per_cpu(xen_pgtable, 0) = cpu0_pgtable;
> >   #endif
>
> .. these two lines before hand so you can use THIS_CPU_PGTABLE.
>
> > +
> > +    /*
>
> Coding style: It looks like you have one space too much before /*.
>
> > +    * Keep original Xen memory mapped because secondary CPUs still point to it
> > +    * and a few variables needs to be accessed by the master CPU in order to
> > +    * let them boot. This mapping will also replace the one created at the
> > +    * beginning of setup_pagetables.
> > +    */
>
> It feels wrong to keep the full Xen (even temporarily) just for CPU
> bring-up. But I don't think this is necessary. The secondary CPUs
> outside of code in head.S, secondary CPU should only need to access to
> init_ttbr and smp_cpu_up.
>
> The last one is already questionable because the CPU should never wait
> in Xen. Instead they would be held somewhere else. But that's separate
> issue.
>
> Anyway, if you move init_ttbr and smp_cpu_up in the identity mapped
> area, then you will not need to copy of Xen. Instead, secondary CPUs
> should be able to jump to the new Xen directly.

So to recap:

1) How to move variables in the identity map area?
__attribute__((section(".text.idmap"))) triggers some warning when assembling.

Warning: setting incorrect section attributes for .text.idmap

2) If I'm not mistaken the identity mapping is read only (PAGE_HYPERVISOR_RX)
and forcing it to be PAGE_HYPERVISOR_RW breaks something else.

3) To access the identity mapping area I would need some accessor that takes
an address and returns it + phys_offset, or is there a better way to do it?

4) Maybe I misinterpreted the above comment, but I would still need to copy
Xen in the physically colored space. What I can drop is the temporary virtual
space used to access the "old" variables.

5) The identity mapping at runtime, at the moment, is pointing to the new
colored space because of how pte_of_xenaddr is implemented. This means that if
I want to use it to access the old variables, I would need to keep it a real
identity mapping, right?

> This will also avoid to spread cache coloring changes in every Xen
> components.

Maybe I'm missing something, but even with this identity mapping "shortcut" I
would still need to touch the same amount of files, for example when init_ttbr
or smp_up_cpu are accessed, they would need to use identity virtual addresses.

> > +    if ( llc_coloring_enabled )
> > +        map_pages_to_xen(BOOT_RELOC_VIRT_START,
> > +                         maddr_to_mfn(XEN_VIRT_START + phys_offset),
> > +                         SZ_2M >> PAGE_SHIFT, PAGE_HYPERVISOR_RW | _PAGE_BLOCK);
> > +
> >   }
> >
> >   void *__init arch_vmap_virt_end(void)
> > diff --git a/xen/arch/arm/mmu/smpboot.c b/xen/arch/arm/mmu/smpboot.c
> > index b6fc0aae07..a69183ec88 100644
> > --- a/xen/arch/arm/mmu/smpboot.c
> > +++ b/xen/arch/arm/mmu/smpboot.c
> > @@ -6,6 +6,7 @@
> >    */
> >
> >   #include <xen/domain_page.h>
> > +#include <xen/llc-coloring.h>
> >
> >   #include <asm/setup.h>
> >
> > @@ -71,14 +72,20 @@ static void clear_boot_pagetables(void)
> >   #ifdef CONFIG_ARM_64
> >   int prepare_secondary_mm(int cpu)
> >   {
> > +    uint64_t *init_ttbr_addr = &init_ttbr;
> > +
> >       clear_boot_pagetables();
> >
> > +    if ( llc_coloring_enabled )
> > +        init_ttbr_addr = (uint64_t *)virt_to_reloc_virt(&init_ttbr);
> > +
> >       /*
> >        * Set init_ttbr for this CPU coming up. All CPUs share a single setof
> >        * pagetables, but rewrite it each time for consistency with 32 bit.
> >        */
> > -    init_ttbr = virt_to_maddr(xen_pgtable);
> > -    clean_dcache(init_ttbr);
> > +    *init_ttbr_addr = virt_to_maddr(xen_pgtable);
> > +    clean_dcache(*init_ttbr_addr);
> > +
> >       return 0;
> >   }
> >   #else
> > diff --git a/xen/arch/arm/psci.c b/xen/arch/arm/psci.c
> > index 695d2fa1f1..23e298c477 100644
> > --- a/xen/arch/arm/psci.c
> > +++ b/xen/arch/arm/psci.c
> > @@ -11,6 +11,7 @@
> >
> >   #include <xen/types.h>
> >   #include <xen/init.h>
> > +#include <xen/llc-coloring.h>
> >   #include <xen/mm.h>
> >   #include <xen/smp.h>
> >   #include <asm/cpufeature.h>
> > @@ -39,9 +40,13 @@ static uint32_t psci_cpu_on_nr;
> >   int call_psci_cpu_on(int cpu)
> >   {
> >       struct arm_smccc_res res;
> > +    vaddr_t init_secondary_addr = (vaddr_t)init_secondary;
> >
> > -    arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu), __pa(init_secondary),
> > -                  &res);
> > +    if ( llc_coloring_enabled )
> > +        init_secondary_addr = virt_to_reloc_virt(init_secondary);
> > +
> > +    arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu),
> > +                  __pa(init_secondary_addr), &res);
> >
> >       return PSCI_RET(res);
> >   }
>
> [...]
>
> > +#ifdef CONFIG_LLC_COLORING
> > +/**
> > + * get_xen_paddr - get physical address to relocate Xen to
> > + *
> > + * Xen is relocated to as near to the top of RAM as possible and
> > + * aligned to a XEN_PADDR_ALIGN boundary.
> > + */
> > +static paddr_t __init get_xen_paddr(uint32_t xen_size)
> > +{
> > +    struct meminfo *mi = &bootinfo.mem;
> > +    paddr_t min_size;
> > +    paddr_t paddr = 0;
> > +    int i;
> > +
> > +    min_size = (xen_size + (XEN_PADDR_ALIGN-1)) & ~(XEN_PADDR_ALIGN-1);
> > +
> > +    /* Find the highest bank with enough space. */
> > +    for ( i = 0; i < mi->nr_banks; i++ )
> > +    {
> > +        const struct membank *bank = &mi->bank[i];
> > +        paddr_t s, e;
> > +
> > +        if ( bank->size >= min_size )
> > +        {
> > +            e = consider_modules(bank->start, bank->start + bank->size,
> > +                                 min_size, XEN_PADDR_ALIGN, 0);
> > +            if ( !e )
> > +                continue;
> > +
> > +#ifdef CONFIG_ARM_32
> > +            /* Xen must be under 4GB */
> > +            if ( e > 0x100000000ULL )
> > +                e = 0x100000000ULL;
> > +            if ( e < bank->start )
> > +                continue;
> > +#endif
> > +
> > +            s = e - min_size;
> > +
> > +            if ( s > paddr )
> > +                paddr = s;
> > +        }
> > +    }
> > +
> > +    if ( !paddr )
> > +        panic("Not enough memory to relocate Xen\n");
> > +
> > +    printk("Placing Xen at 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
> > +           paddr, paddr + min_size);
> > +
> > +    return paddr;
> > +}
> > +#else
> > +static paddr_t __init get_xen_paddr(uint32_t xen_size) { return 0; }
> > +#endif
> > +
> >   void __init init_pdx(void)
> >   {
> >       paddr_t bank_start, bank_size, bank_end;
> > @@ -724,8 +874,6 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
> >       /* Initialize traps early allow us to get backtrace when an error occurred */
> >       init_traps();
> >
> > -    setup_pagetables(boot_phys_offset);
> > -
> >       smp_clear_cpu_maps();
> >
> >       device_tree_flattened = early_fdt_map(fdt_paddr);
> > @@ -751,8 +899,13 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
> >       {
> >           if ( !llc_coloring_init() )
> >               panic("Xen LLC coloring support: setup failed\n");
> > +        xen_bootmodule->size = xen_colored_map_size(_end - _start);
> > +        xen_bootmodule->start = get_xen_paddr(xen_bootmodule->size);
>
> As you update xen_bootmodule, wouldn't this mean that the non-relocated
> Xen would could be passed to the bootallocator?

Yes that should be memory that in the end would not be needed so it must
return to the boot-allocator (if that's what you mean). But how to do
that?

> >       } >
> > +    setup_pagetables(boot_phys_offset, xen_bootmodule->start);
>
> The new placement of setup_pagetables() deserve an explanation.
>
> > +    device_tree_flattened = early_fdt_map(fdt_paddr);
> > +
> >       setup_mm();
> >
> >       /* Parse the ACPI tables for possible boot-time configuration */
> > @@ -867,6 +1020,14 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
> >
> >       setup_virt_paging();
> >
> > +    /*
> > +     * The removal is done earlier than discard_initial_modules beacuse the
>
> Typo: s/beacuase/because/
>
> > +     * livepatch init uses a virtual address equal to BOOT_RELOC_VIRT_START.
> > +     * Remove LLC coloring mappings to expose a clear state to the livepatch
> > +     * module.
> > +     */
> > +    if ( llc_coloring_enabled )
> > +        remove_llc_coloring_mappings();
> >       do_initcalls();
> >
> >       /*
> > diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
> > index 7110bc11fc..7ed7357d58 100644
> > --- a/xen/arch/arm/smpboot.c
> > +++ b/xen/arch/arm/smpboot.c
> > @@ -14,6 +14,7 @@
> >   #include <xen/domain_page.h>
> >   #include <xen/errno.h>
> >   #include <xen/init.h>
> > +#include <xen/llc-coloring.h>
> >   #include <xen/mm.h>
> >   #include <xen/param.h>
> >   #include <xen/sched.h>
> > @@ -444,6 +445,7 @@ int __cpu_up(unsigned int cpu)
> >   {
> >       int rc;
> >       s_time_t deadline;
> > +    unsigned long *smp_up_cpu_addr = &smp_up_cpu;
> >
> >       printk("Bringing up CPU%d\n", cpu);
> >
> > @@ -459,9 +461,12 @@ int __cpu_up(unsigned int cpu)
> >       /* Tell the remote CPU what its logical CPU ID is. */
> >       init_data.cpuid = cpu;
> >
> > +    if ( llc_coloring_enabled )
> > +        smp_up_cpu_addr = (unsigned long *)virt_to_reloc_virt(&smp_up_cpu);
> > +
> >       /* Open the gate for this CPU */
> > -    smp_up_cpu = cpu_logical_map(cpu);
> > -    clean_dcache(smp_up_cpu);
> > +    *smp_up_cpu_addr = cpu_logical_map(cpu);
> > +    clean_dcache(*smp_up_cpu_addr);
> >
> >       rc = arch_cpu_up(cpu);
> >
>
> Cheers,
>
> --
> Julien Grall

Thanks.


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-13 17:07     ` Carlo Nonato
@ 2024-01-14 19:22       ` Julien Grall
  2024-01-15 10:11         ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-14 19:22 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Carlo,

On 13/01/2024 17:07, Carlo Nonato wrote:
>>> diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
>>> index 37b6d230ad..66b674eeab 100644
>>> --- a/xen/arch/arm/mmu/setup.c
>>> +++ b/xen/arch/arm/mmu/setup.c
>>> @@ -7,6 +7,7 @@
>>>
>>>    #include <xen/init.h>
>>>    #include <xen/libfdt/libfdt.h>
>>> +#include <xen/llc-coloring.h>
>>>    #include <xen/sizes.h>
>>>    #include <xen/vmap.h>
>>>
>>> @@ -39,6 +40,10 @@ DEFINE_PER_CPU(lpae_t *, xen_pgtable);
>>>    static DEFINE_PAGE_TABLE(cpu0_pgtable);
>>>    #endif
>>>
>>> +#ifdef CONFIG_LLC_COLORING
>>> +static DEFINE_PAGE_TABLE(xen_colored_temp);
>>> +#endif
>>
>> Does this actually need to be static?
> 
> Why it shouldn't be static? I don't want to access it from another file.

My question was whether this could be allocated dynamically (or possibly 
re-use an existing set of page tables). In particular with the fact that 
we will need more than 1 page to cover the whole Xen binary.

Looking at the use xen_colored_temp. This is pretty much the same as 
xen_map[i] but with different permissions. So what you could do is 
preparing xen_map[i] with very permissive permissions (i.e. RWX) and 
then enforcing the permission once the TTBR has been switched.

Something like that (tested without cache coloring):

diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
index a3a263a5d94b..f7ac5cabf92c 100644
--- a/xen/arch/arm/mmu/setup.c
+++ b/xen/arch/arm/mmu/setup.c
@@ -306,7 +306,11 @@ void __init setup_pagetables(unsigned long 
boot_phys_offset, paddr_t xen_paddr)
      p[0].pt.table = 1;
      p[0].pt.xn = 0;

-    /* Break up the Xen mapping into pages and protect them separately. */
+    /*
+     * Break up the Xen mapping into pages. We will protect the
+     * permissions later in order to allow xen_xenmap to be used for
+     * when relocating Xen.
+     */
      for ( i = 0; i < XEN_NR_ENTRIES(3); i++ )
      {
          vaddr_t va = XEN_VIRT_START + (i << PAGE_SHIFT);
@@ -315,13 +319,7 @@ void __init setup_pagetables(unsigned long 
boot_phys_offset, paddr_t xen_paddr)
              break;
          pte = pte_of_xenaddr(va);
          pte.pt.table = 1; /* third level mappings always have this bit 
set */
-        if ( is_kernel_text(va) || is_kernel_inittext(va) )
-        {
-            pte.pt.xn = 0;
-            pte.pt.ro = 1;
-        }
-        if ( is_kernel_rodata(va) )
-            pte.pt.ro = 1;
+        pte.pt.xn = 0; /* Permissions will be enforced later. Allow 
execution */
          xen_xenmap[i] = pte;
      }

@@ -352,6 +350,37 @@ void __init setup_pagetables(unsigned long 
boot_phys_offset, paddr_t xen_paddr)

      switch_ttbr(ttbr);

+    /* Protect Xen */
+    for ( i = 0; i < XEN_NR_ENTRIES(3); i++ )
+    {
+        vaddr_t va = XEN_VIRT_START + (i << PAGE_SHIFT);
+        lpae_t *entry = xen_xenmap + i;
+
+        if ( !is_kernel(va) )
+            break;
+
+        pte = read_atomic(entry);
+
+        if ( is_kernel_text(va) || is_kernel_inittext(va) )
+        {
+            pte.pt.xn = 0;
+            pte.pt.ro = 1;
+        } else if ( is_kernel_rodata(va) ) {
+            pte.pt.ro = 1;
+            pte.pt.xn = 1;
+        } else {
+            pte.pt.xn = 1;
+            pte.pt.ro = 0;
+        }
+
+        write_pte(entry, pte);
+    }
+
+    /*
+     * We modified live page-tables. Ensure the TBLs are invalidated
+     * before setting enforcing the WnX permissions.
+     */
+    flush_xen_tlb_local();
      xen_pt_enforce_wnx();

  #ifdef CONFIG_ARM_32

> 
>> And if yes, then is it necessary
>> to be kept the boot as completed?
> 
> Nope. __initdata?

Yes.

[...]

>> It feels wrong to keep the full Xen (even temporarily) just for CPU
>> bring-up. But I don't think this is necessary. The secondary CPUs
>> outside of code in head.S, secondary CPU should only need to access to
>> init_ttbr and smp_cpu_up.
>>
>> The last one is already questionable because the CPU should never wait
>> in Xen. Instead they would be held somewhere else. But that's separate
>> issue.
>>
>> Anyway, if you move init_ttbr and smp_cpu_up in the identity mapped
>> area, then you will not need to copy of Xen. Instead, secondary CPUs
>> should be able to jump to the new Xen directly.
> 
> So to recap:
> 
> 1) How to move variables in the identity map area?
> __attribute__((section(".text.idmap"))) triggers some warning when assembling.
> 
> Warning: setting incorrect section attributes for .text.idmap
> 
> 2) If I'm not mistaken the identity mapping is read only (PAGE_HYPERVISOR_RX)
> and forcing it to be PAGE_HYPERVISOR_RW breaks something else.
The warning above has nothing to do with the attributes used in the 
page-tables. It is telling you have multiple .text.idmap section with 
different attributes.

There are a couple of ways to solve it:
    1. Define init_ttbr in head.S
    2. Use a different section (e.g. .data.idmap) and add it in the linker.

Note that this means the init_ttbr cannot be written directly. But you 
can solve this problem by re-mapping the address.

> 
> 3) To access the identity mapping area I would need some accessor that takes
> an address and returns it + phys_offset, or is there a better way to do it?

I am not sure I understand what you mean. Can you clarify?


> 
> 4) Maybe I misinterpreted the above comment, but I would still need to copy
> Xen in the physically colored space. What I can drop is the temporary virtual
> space used to access the "old" variables.

Correct.

> 
> 5) The identity mapping at runtime, at the moment, is pointing to the new
> colored space because of how pte_of_xenaddr is implemented. This means that if
> I want to use it to access the old variables, I would need to keep it a real
> identity mapping, right?

Why would you need to access the old variables?

>> This will also avoid to spread cache coloring changes in every Xen
>> components.
> 
> Maybe I'm missing something, but even with this identity mapping "shortcut" I
> would still need to touch the same amount of files, for example when init_ttbr
> or smp_up_cpu are accessed, they would need to use identity virtual addresses.

My point was not related to the amount of files you are touching. But 
the number of ...

> 
>>> +    if ( llc_coloring_enabled )

... if ( llc_coloring_enabled ) you sprinkle in Xen. I would really like 
to reduce to the strict minimum. Also...

[...]

>>> @@ -751,8 +899,13 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
>>>        {
>>>            if ( !llc_coloring_init() )
>>>                panic("Xen LLC coloring support: setup failed\n");
>>> +        xen_bootmodule->size = xen_colored_map_size(_end - _start);
>>> +        xen_bootmodule->start = get_xen_paddr(xen_bootmodule->size);
>>
>> As you update xen_bootmodule, wouldn't this mean that the non-relocated >> Xen would could be passed to the bootallocator?

... as I wrote ealier your current approach seems to have a flaw. As you 
overwrite xen_bootmodule->{start, size}. setup_mm() will end up to add 
the old Xen region to the boot allocator. This is before any secondary 
CPUs are booted up.

IOW, the allocator may provide some memory from the old Xen and nothing 
good will happen from that.

The only way to solve it is to add another module. So the memory is 
skipped by setup_mm(). However see below.

> 
> Yes that should be memory that in the end would not be needed so it must
> return to the boot-allocator (if that's what you mean). But how to do
> that?

You can't really discard the old temporary Xen. This may work today 
because we don't support CPU hotplug or suspend/resume. But there was 
some series on the ML to enable it and I don't see any reason why 
someone would not want to use the features with cache coloring.

So the old temporary Xen would have to be kept around forever. This is 
up to 8MB of memory wasted.

The right approach is to have the secondary CPU boot code (including the 
variables it is using) fitting in the same page (or possibly multiple so 
long this is small and physically contiguous). With that it doesn't 
matter where is the trampoline, it could stay at the old place, but we 
would only waste a few pages rather than up 8MB as it is today.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-14 19:22       ` Julien Grall
@ 2024-01-15 10:11         ` Carlo Nonato
  2024-01-15 11:18           ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-15 10:11 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Julien,

On Sun, Jan 14, 2024 at 8:22 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 13/01/2024 17:07, Carlo Nonato wrote:
> >>> diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
> >>> index 37b6d230ad..66b674eeab 100644
> >>> --- a/xen/arch/arm/mmu/setup.c
> >>> +++ b/xen/arch/arm/mmu/setup.c
> >>> @@ -7,6 +7,7 @@
> >>>
> >>>    #include <xen/init.h>
> >>>    #include <xen/libfdt/libfdt.h>
> >>> +#include <xen/llc-coloring.h>
> >>>    #include <xen/sizes.h>
> >>>    #include <xen/vmap.h>
> >>>
> >>> @@ -39,6 +40,10 @@ DEFINE_PER_CPU(lpae_t *, xen_pgtable);
> >>>    static DEFINE_PAGE_TABLE(cpu0_pgtable);
> >>>    #endif
> >>>
> >>> +#ifdef CONFIG_LLC_COLORING
> >>> +static DEFINE_PAGE_TABLE(xen_colored_temp);
> >>> +#endif
> >>
> >> Does this actually need to be static?
> >
> > Why it shouldn't be static? I don't want to access it from another file.
>
> My question was whether this could be allocated dynamically (or possibly
> re-use an existing set of page tables). In particular with the fact that
> we will need more than 1 page to cover the whole Xen binary.
>
> Looking at the use xen_colored_temp. This is pretty much the same as
> xen_map[i] but with different permissions. So what you could do is
> preparing xen_map[i] with very permissive permissions (i.e. RWX) and
> then enforcing the permission once the TTBR has been switched.
>
> Something like that (tested without cache coloring):
>
> diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
> index a3a263a5d94b..f7ac5cabf92c 100644
> --- a/xen/arch/arm/mmu/setup.c
> +++ b/xen/arch/arm/mmu/setup.c
> @@ -306,7 +306,11 @@ void __init setup_pagetables(unsigned long
> boot_phys_offset, paddr_t xen_paddr)
>       p[0].pt.table = 1;
>       p[0].pt.xn = 0;
>
> -    /* Break up the Xen mapping into pages and protect them separately. */
> +    /*
> +     * Break up the Xen mapping into pages. We will protect the
> +     * permissions later in order to allow xen_xenmap to be used for
> +     * when relocating Xen.
> +     */
>       for ( i = 0; i < XEN_NR_ENTRIES(3); i++ )
>       {
>           vaddr_t va = XEN_VIRT_START + (i << PAGE_SHIFT);
> @@ -315,13 +319,7 @@ void __init setup_pagetables(unsigned long
> boot_phys_offset, paddr_t xen_paddr)
>               break;
>           pte = pte_of_xenaddr(va);
>           pte.pt.table = 1; /* third level mappings always have this bit
> set */
> -        if ( is_kernel_text(va) || is_kernel_inittext(va) )
> -        {
> -            pte.pt.xn = 0;
> -            pte.pt.ro = 1;
> -        }
> -        if ( is_kernel_rodata(va) )
> -            pte.pt.ro = 1;
> +        pte.pt.xn = 0; /* Permissions will be enforced later. Allow
> execution */
>           xen_xenmap[i] = pte;
>       }
>
> @@ -352,6 +350,37 @@ void __init setup_pagetables(unsigned long
> boot_phys_offset, paddr_t xen_paddr)
>
>       switch_ttbr(ttbr);
>
> +    /* Protect Xen */
> +    for ( i = 0; i < XEN_NR_ENTRIES(3); i++ )
> +    {
> +        vaddr_t va = XEN_VIRT_START + (i << PAGE_SHIFT);
> +        lpae_t *entry = xen_xenmap + i;
> +
> +        if ( !is_kernel(va) )
> +            break;
> +
> +        pte = read_atomic(entry);
> +
> +        if ( is_kernel_text(va) || is_kernel_inittext(va) )
> +        {
> +            pte.pt.xn = 0;
> +            pte.pt.ro = 1;
> +        } else if ( is_kernel_rodata(va) ) {
> +            pte.pt.ro = 1;
> +            pte.pt.xn = 1;
> +        } else {
> +            pte.pt.xn = 1;
> +            pte.pt.ro = 0;
> +        }
> +
> +        write_pte(entry, pte);
> +    }
> +
> +    /*
> +     * We modified live page-tables. Ensure the TBLs are invalidated
> +     * before setting enforcing the WnX permissions.
> +     */
> +    flush_xen_tlb_local();
>       xen_pt_enforce_wnx();
>
>   #ifdef CONFIG_ARM_32

I understand what you're talking about, and it seems reasonable to get rid of
xen_colored_temp[] and create_llc_coloring_mappings() since in the end they
serve the purpose of mapping the physically colored space that is already
mapped using xen_xenmap[] pagetables.
What I don't understand is then how to copy/relocate Xen since I don't have a
destination virtual space anymore to use in relocate_xen().

> >
> >> And if yes, then is it necessary
> >> to be kept the boot as completed?
> >
> > Nope. __initdata?
>
> Yes.
>
> [...]
>
> >> It feels wrong to keep the full Xen (even temporarily) just for CPU
> >> bring-up. But I don't think this is necessary. The secondary CPUs
> >> outside of code in head.S, secondary CPU should only need to access to
> >> init_ttbr and smp_cpu_up.
> >>
> >> The last one is already questionable because the CPU should never wait
> >> in Xen. Instead they would be held somewhere else. But that's separate
> >> issue.
> >>
> >> Anyway, if you move init_ttbr and smp_cpu_up in the identity mapped
> >> area, then you will not need to copy of Xen. Instead, secondary CPUs
> >> should be able to jump to the new Xen directly.
> >
> > So to recap:
> >
> > 1) How to move variables in the identity map area?
> > __attribute__((section(".text.idmap"))) triggers some warning when assembling.
> >
> > Warning: setting incorrect section attributes for .text.idmap
> >
> > 2) If I'm not mistaken the identity mapping is read only (PAGE_HYPERVISOR_RX)
> > and forcing it to be PAGE_HYPERVISOR_RW breaks something else.
> The warning above has nothing to do with the attributes used in the
> page-tables. It is telling you have multiple .text.idmap section with
> different attributes.
>
> There are a couple of ways to solve it:
>     1. Define init_ttbr in head.S
>     2. Use a different section (e.g. .data.idmap) and add it in the linker.

First one seems the easiest.

> Note that this means the init_ttbr cannot be written directly. But you
> can solve this problem by re-mapping the address.

How to remap a single address?
And if moving init_ttbr in the identity-mapped area means that it's no longer
writable, so that I need to remap it, why moving it in that area in the first
place. Again I think I'm missing something.

> >
> > 3) To access the identity mapping area I would need some accessor that takes
> > an address and returns it + phys_offset, or is there a better way to do it?
>
> I am not sure I understand what you mean. Can you clarify?

In my idea, I would use the identity mapping to access the "old" variables,
where "old" means non physically colored. init_ttbr is an example. When
Xen it's copied on the new physical space, init_ttbr is copied with it and
if the boot cpu modifies this variable, it's actually touching the colored
one and not the old one. This means that secondary CPUs that still haven't
jumped to the new space, won't be able to see the new value and will never
go online.
So to access this "old" init_ttbr variable I need it's identity address,
which is its current virtual address + some physical offset. I was asking
you if this is the right approach to use the identity mapping.

> >
> > 4) Maybe I misinterpreted the above comment, but I would still need to copy
> > Xen in the physically colored space. What I can drop is the temporary virtual
> > space used to access the "old" variables.
>
> Correct.
>
> >
> > 5) The identity mapping at runtime, at the moment, is pointing to the new
> > colored space because of how pte_of_xenaddr is implemented. This means that if
> > I want to use it to access the old variables, I would need to keep it a real
> > identity mapping, right?
>
> Why would you need to access the old variables?

I hope the above comment is clear enough to answer this point.

> >> This will also avoid to spread cache coloring changes in every Xen
> >> components.
> >
> > Maybe I'm missing something, but even with this identity mapping "shortcut" I
> > would still need to touch the same amount of files, for example when init_ttbr
> > or smp_up_cpu are accessed, they would need to use identity virtual addresses.
>
> My point was not related to the amount of files you are touching. But
> the number of ...
>
> >
> >>> +    if ( llc_coloring_enabled )
>
> ... if ( llc_coloring_enabled ) you sprinkle in Xen. I would really like
> to reduce to the strict minimum. Also...
>
> [...]
>
> >>> @@ -751,8 +899,13 @@ void asmlinkage __init start_xen(unsigned long boot_phys_offset,
> >>>        {
> >>>            if ( !llc_coloring_init() )
> >>>                panic("Xen LLC coloring support: setup failed\n");
> >>> +        xen_bootmodule->size = xen_colored_map_size(_end - _start);
> >>> +        xen_bootmodule->start = get_xen_paddr(xen_bootmodule->size);
> >>
> >> As you update xen_bootmodule, wouldn't this mean that the non-relocated >> Xen would could be passed to the bootallocator?
>
> ... as I wrote ealier your current approach seems to have a flaw. As you
> overwrite xen_bootmodule->{start, size}. setup_mm() will end up to add
> the old Xen region to the boot allocator. This is before any secondary
> CPUs are booted up.
>
> IOW, the allocator may provide some memory from the old Xen and nothing
> good will happen from that.
>
> The only way to solve it is to add another module. So the memory is
> skipped by setup_mm(). However see below.
>
> >
> > Yes that should be memory that in the end would not be needed so it must
> > return to the boot-allocator (if that's what you mean). But how to do
> > that?
>
> You can't really discard the old temporary Xen. This may work today
> because we don't support CPU hotplug or suspend/resume. But there was
> some series on the ML to enable it and I don't see any reason why
> someone would not want to use the features with cache coloring.
>
> So the old temporary Xen would have to be kept around forever. This is
> up to 8MB of memory wasted.
>
> The right approach is to have the secondary CPU boot code (including the
> variables it is using) fitting in the same page (or possibly multiple so
> long this is small and physically contiguous). With that it doesn't
> matter where is the trampoline, it could stay at the old place, but we
> would only waste a few pages rather than up 8MB as it is today.

So what are you suggesting is to create a new section in the linker script
for the trampoline code and data, then in setup_mm() we would skip this
memory? Am I following you correctly? Sorry those topics are a little out
of my preparation as you probably already guessed.

> Cheers,
>
> --
> Julien Grall

Thanks.


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

* Re: [PATCH v5 02/13] xen/arm: add cache coloring initialization
  2024-01-11 10:44         ` Julien Grall
@ 2024-01-15 11:05           ` Carlo Nonato
  0 siblings, 0 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-15 11:05 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Jan Beulich,
	Wei Liu, Marco Solieri

Hi Julien,

On Thu, Jan 11, 2024 at 11:44 AM Julien Grall <julien@xen.org> wrote:
> On 11/01/2024 10:17, Carlo Nonato wrote:
> > Hi Julien,
>
> Hi Carlo,
>
> >>>> +bool __init llc_coloring_init(void)
> >>>> +{
> >>>> +    if ( !llc_way_size && !(llc_way_size = get_llc_way_size()) )
> >>>> +    {
> >>>> +        printk(XENLOG_ERR
> >>>> +               "Probed LLC way size is 0 and no custom value provided\n");
> >>>> +        return false;
> >>>> +    }
> >>>> +
> >>>> +    /*
> >>>> +     * The maximum number of colors must be a power of 2 in order to correctly
> >>>> +     * map them to bits of an address, so also the LLC way size must be so.
> >>>> +     */
> >>>> +    if ( llc_way_size & (llc_way_size - 1) )
> >>>> +    {
> >>>> +        printk(XENLOG_WARNING "LLC way size (%u) isn't a power of 2.\n",
> >>>> +               llc_way_size);
> >>>> +        llc_way_size = 1U << flsl(llc_way_size);
> >>>> +        printk(XENLOG_WARNING
> >>>> +               "Using %u instead. Performances will be suboptimal\n",
> >>>> +               llc_way_size);
> >>>> +    }
> >>>> +
> >>>> +    nr_colors = llc_way_size >> PAGE_SHIFT;
> >>>> +
> >>>> +    if ( nr_colors < 2 || nr_colors > CONFIG_NR_LLC_COLORS )
> >>>
> >>> I didn't find any documentation explaining why we need at least two
> >>> colors. I guess you want to make sure that there is a color for Xen and
> >>> domain. But I wonder what could wrong with just one color (other than
> >>> been pointless)?
> >>
> >> Yes, it would just be pointless. I'll change it to 1.
> >
> > Just wanted to correct myself here. Having just a single color introduces a
> > clear sharing of the cache between Xen and domains. So it's not just
> > pointless, but also inefficient. I would discourage such a configuration, so I
> > plan to better describe this with a range in the Kconfig option (see
> > discussion in #1).
>
> I understand this could be inneficient. But you are also allowing the
> user to not specify the color configuration (at least for dom0less
> domain). So the colors would end up to shared with everyone (including Xen).
>
> I don't particularly mind which way you want to go, but I think we need
> some coherency. If we want to avoid innefficiency, then we should
> prevent all the setups.

I definitely don't want to check for overlapping configurations since that
could also be a desired setup, but I do want sane defaults. You found some
inchoerency there cause Xen and the domains share one color. Maybe the best
solution would be to have a default configuration for domains that doesn't
overlap with the Xen one.

Back to the original point, having a single color for the whole platform is
just stupid, not only pointless. It defeats completely the coloring idea.
On the other hand the default configuration is something that could have an
application (still pretty "basic").

In patch #5 (dom0less) there is some contradiction where Xen panics when no
configuration is provided. I also misuderstood your comment on that patch
and it can't actually panic in that case, but instead use the default
configuration.

Thanks.

> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-09 10:28   ` Jan Beulich
  2024-01-09 10:33     ` Jan Beulich
  2024-01-10  0:46     ` Stefano Stabellini
@ 2024-01-15 11:07     ` Carlo Nonato
  2 siblings, 0 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-15 11:07 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, xen-devel

Hi Jan,

On Tue, Jan 9, 2024 at 11:28 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 02.01.2024 10:51, Carlo Nonato wrote:
> > This commit adds a new memory page allocator that implements the cache
> > coloring mechanism. The allocation algorithm enforces equal frequency
> > distribution of cache partitions, following the coloring configuration of a
> > domain. This allows an even utilization of cache sets for every domain.
> >
> > Pages are stored in a color-indexed array of lists. Those lists are filled
> > by a simple init function which computes the color of each page.
> > When a domain requests a page, the allocator extract the page from the list
> > with the maximum number of free pages between those that the domain can
> > access, given its coloring configuration.
> >
> > The allocator can only handle requests of order-0 pages. This allows for
> > easier implementation and since cache coloring targets only embedded systems,
> > it's assumed not to be a major problem.
>
> I'm curious about the specific properties of embedded systems that makes
> the performance implications of deeper page walks less of an issue for
> them.
>
> Nothing is said about address-constrained allocations. Are such entirely
> of no interest to domains on Arm, not even to Dom0 (e.g. for filling
> Linux'es swiotlb)? Certainly alloc_color_heap_page() should at least
> fail when it can't satisfy the passed in memflags.
>
> > ---
> > v5:
> > - Carlo Nonato as the new author
> > - the colored allocator balances color usage for each domain and it searches
> >   linearly only in the number of colors (FIXME removed)
>
> While this addresses earlier concerns, meanwhile NUMA work has also
> been progressing. What's the plan of interaction of coloring with it?
>
> > --- a/xen/arch/Kconfig
> > +++ b/xen/arch/Kconfig
> > @@ -47,3 +47,15 @@ config NR_LLC_COLORS
> >         bound. The runtime value is autocomputed or manually set via cmdline.
> >         The default value corresponds to an 8 MiB 16-ways LLC, which should be
> >         more than what needed in the general case.
> > +
> > +config BUDDY_ALLOCATOR_SIZE
> > +     int "Buddy allocator reserved memory size (MiB)"
> > +     default "64"
> > +     depends on LLC_COLORING
> > +     help
> > +       Amount of memory reserved for the buddy allocator to work alongside
> > +       the colored one. The colored allocator is meant as an alternative to
> > +       the buddy allocator because its allocation policy is by definition
> > +       incompatible with the generic one. Since the Xen heap is not colored
> > +       yet, we need to support the coexistence of the two allocators and some
> > +       memory must be left for the buddy one.
>
> Imo help text should be about the specific option, not general
> documentation. How about
>
>           Amount of memory reserved for the buddy allocator, to serve Xen's
>           heap, to work alongside the colored one.
>
> or some such?
>
> > --- a/xen/arch/arm/llc-coloring.c
> > +++ b/xen/arch/arm/llc-coloring.c
> > @@ -30,6 +30,9 @@ static unsigned int __ro_after_init nr_colors = CONFIG_NR_LLC_COLORS;
> >  static unsigned int __ro_after_init dom0_colors[CONFIG_NR_LLC_COLORS];
> >  static unsigned int __ro_after_init dom0_num_colors;
> >
> > +#define mfn_color_mask              (nr_colors - 1)
>
> This is used solely ...
>
> > +#define mfn_to_color(mfn)           (mfn_x(mfn) & mfn_color_mask)
>
> ... here, and this one in turn is used solely ...
>
> > @@ -312,6 +315,16 @@ int domain_set_llc_colors_from_str(struct domain *d, const char *str)
> >      return domain_check_colors(d);
> >  }
> >
> > +unsigned int page_to_llc_color(const struct page_info *pg)
> > +{
> > +    return mfn_to_color(page_to_mfn(pg));
> > +}
>
> ... here. What's the point in having those (private) macros?

They will be used in later patches (#13).

> > @@ -1946,6 +1951,162 @@ static unsigned long avail_heap_pages(
> >      return free_pages;
> >  }
> >
> > +/*************************
> > + * COLORED SIDE-ALLOCATOR
> > + *
> > + * Pages are grouped by LLC color in lists which are globally referred to as the
> > + * color heap. Lists are populated in end_boot_allocator().
> > + * After initialization there will be N lists where N is the number of
> > + * available colors on the platform.
> > + */
> > +static struct page_list_head *__ro_after_init _color_heap;
> > +static unsigned long *__ro_after_init free_colored_pages;
>
> It's "just" two pointers, but still - what use are they when ...
>
> > +/* Memory required for buddy allocator to work with colored one */
> > +#ifdef CONFIG_LLC_COLORING
>
> ... this isn't defined?
>
> > +static unsigned long __initdata buddy_alloc_size =
> > +    MB(CONFIG_BUDDY_ALLOCATOR_SIZE);
> > +size_param("buddy-alloc-size", buddy_alloc_size);
> > +
> > +#define domain_num_llc_colors(d) ((d)->num_llc_colors)
> > +#define domain_llc_color(d, i)   ((d)->llc_colors[(i)])
>
> Nit: No need to parenthesize i when used like this.
>
> > +#else
> > +static unsigned long __initdata buddy_alloc_size;
> > +
> > +#define domain_num_llc_colors(d) 0
> > +#define domain_llc_color(d, i)   0
> > +#define page_to_llc_color(p)     0
> > +#define get_nr_llc_colors()      0
> > +#endif
> > +
> > +#define color_heap(color) (&_color_heap[color])
> > +
> > +void free_color_heap_page(struct page_info *pg, bool need_scrub)
>
> Likely applicable further down as well - this is dead code when
> !CONFIG_LLC_COLORING. Besides me, Misra also won't like this. The
> function also looks to want to be static, at which point DCE would
> apparently take care of removing it (and others, and then hopefully
> also the two static variables commented on above).
>
> > +struct page_info *alloc_color_heap_page(unsigned int memflags, struct domain *d)
>
> I don't think d is written through in the function, so it wants to
> be pointer-to-const.
>
> > +void __init init_color_heap_pages(struct page_info *pg, unsigned long nr_pages)
> > +{
> > +    unsigned int i;
> > +    bool need_scrub = (system_state < SYS_STATE_active &&
>
> Can this part of the condition be false, seeing we're in an __init
> function?

Nope. I'll drop it.

> > +                       opt_bootscrub == BOOTSCRUB_IDLE);
> > +
> > +    if ( buddy_alloc_size )
> > +    {
> > +        unsigned long buddy_pages = min(PFN_DOWN(buddy_alloc_size), nr_pages);
> > +
> > +        init_heap_pages(pg, buddy_pages);
> > +        nr_pages -= buddy_pages;
> > +        buddy_alloc_size -= buddy_pages << PAGE_SHIFT;
> > +        pg += buddy_pages;
> > +    }
>
> So whatever is passed into this function first is going to fill the
> Xen heap, without regard to address. I expect you're sure this won't
> cause issues on Arm. On x86 certain constraints exist which would
> require lower address ranges to be preferred.
>
> > +void dump_color_heap(void)
> > +{
> > +    unsigned int color;
> > +
> > +    printk("Dumping color heap info\n");
> > +    for ( color = 0; color < get_nr_llc_colors(); color++ )
> > +        if ( free_colored_pages[color] > 0 )
> > +            printk("Color heap[%u]: %lu pages\n",
> > +                   color, free_colored_pages[color]);
> > +}
>
> What's a typical range of number of colors on a system? I expect more
> than 9, but I'm not sure about a reasonable upper bound. For the
> output to be easy to consume, [%u] may want to become at least [%2u].

16 or 32 colors are pretty typical. In the past we set an upper bound at
128 colors.

Thanks.

> Jan


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-15 10:11         ` Carlo Nonato
@ 2024-01-15 11:18           ` Julien Grall
  2024-01-15 15:43             ` Carlo Nonato
  0 siblings, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-15 11:18 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri



On 15/01/2024 10:11, Carlo Nonato wrote:
> Hi Julien,

Hi Carlo,

> On Sun, Jan 14, 2024 at 8:22 PM Julien Grall <julien@xen.org> wrote:
>>
>> Hi Carlo,
>>
>> On 13/01/2024 17:07, Carlo Nonato wrote:
>>>>> diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
>>>>> index 37b6d230ad..66b674eeab 100644
>>>>> --- a/xen/arch/arm/mmu/setup.c
>>>>> +++ b/xen/arch/arm/mmu/setup.c
>>>>> @@ -7,6 +7,7 @@
>>>>>
>>>>>     #include <xen/init.h>
>>>>>     #include <xen/libfdt/libfdt.h>
>>>>> +#include <xen/llc-coloring.h>
>>>>>     #include <xen/sizes.h>
>>>>>     #include <xen/vmap.h>
>>>>>
>>>>> @@ -39,6 +40,10 @@ DEFINE_PER_CPU(lpae_t *, xen_pgtable);
>>>>>     static DEFINE_PAGE_TABLE(cpu0_pgtable);
>>>>>     #endif
>>>>>
>>>>> +#ifdef CONFIG_LLC_COLORING
>>>>> +static DEFINE_PAGE_TABLE(xen_colored_temp);
>>>>> +#endif
>>>>
>>>> Does this actually need to be static?
>>>
>>> Why it shouldn't be static? I don't want to access it from another file.
>>
>> My question was whether this could be allocated dynamically (or possibly
>> re-use an existing set of page tables). In particular with the fact that
>> we will need more than 1 page to cover the whole Xen binary.
>>
>> Looking at the use xen_colored_temp. This is pretty much the same as
>> xen_map[i] but with different permissions. So what you could do is
>> preparing xen_map[i] with very permissive permissions (i.e. RWX) and
>> then enforcing the permission once the TTBR has been switched.
>>
>> Something like that (tested without cache coloring):
>>
>> diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
>> index a3a263a5d94b..f7ac5cabf92c 100644
>> --- a/xen/arch/arm/mmu/setup.c
>> +++ b/xen/arch/arm/mmu/setup.c
>> @@ -306,7 +306,11 @@ void __init setup_pagetables(unsigned long
>> boot_phys_offset, paddr_t xen_paddr)
>>        p[0].pt.table = 1;
>>        p[0].pt.xn = 0;
>>
>> -    /* Break up the Xen mapping into pages and protect them separately. */
>> +    /*
>> +     * Break up the Xen mapping into pages. We will protect the
>> +     * permissions later in order to allow xen_xenmap to be used for
>> +     * when relocating Xen.
>> +     */
>>        for ( i = 0; i < XEN_NR_ENTRIES(3); i++ )
>>        {
>>            vaddr_t va = XEN_VIRT_START + (i << PAGE_SHIFT);
>> @@ -315,13 +319,7 @@ void __init setup_pagetables(unsigned long
>> boot_phys_offset, paddr_t xen_paddr)
>>                break;
>>            pte = pte_of_xenaddr(va);
>>            pte.pt.table = 1; /* third level mappings always have this bit
>> set */
>> -        if ( is_kernel_text(va) || is_kernel_inittext(va) )
>> -        {
>> -            pte.pt.xn = 0;
>> -            pte.pt.ro = 1;
>> -        }
>> -        if ( is_kernel_rodata(va) )
>> -            pte.pt.ro = 1;
>> +        pte.pt.xn = 0; /* Permissions will be enforced later. Allow
>> execution */
>>            xen_xenmap[i] = pte;
>>        }
>>
>> @@ -352,6 +350,37 @@ void __init setup_pagetables(unsigned long
>> boot_phys_offset, paddr_t xen_paddr)
>>
>>        switch_ttbr(ttbr);
>>
>> +    /* Protect Xen */
>> +    for ( i = 0; i < XEN_NR_ENTRIES(3); i++ )
>> +    {
>> +        vaddr_t va = XEN_VIRT_START + (i << PAGE_SHIFT);
>> +        lpae_t *entry = xen_xenmap + i;
>> +
>> +        if ( !is_kernel(va) )
>> +            break;
>> +
>> +        pte = read_atomic(entry);
>> +
>> +        if ( is_kernel_text(va) || is_kernel_inittext(va) )
>> +        {
>> +            pte.pt.xn = 0;
>> +            pte.pt.ro = 1;
>> +        } else if ( is_kernel_rodata(va) ) {
>> +            pte.pt.ro = 1;
>> +            pte.pt.xn = 1;
>> +        } else {
>> +            pte.pt.xn = 1;
>> +            pte.pt.ro = 0;
>> +        }
>> +
>> +        write_pte(entry, pte);
>> +    }
>> +
>> +    /*
>> +     * We modified live page-tables. Ensure the TBLs are invalidated
>> +     * before setting enforcing the WnX permissions.
>> +     */
>> +    flush_xen_tlb_local();
>>        xen_pt_enforce_wnx();
>>
>>    #ifdef CONFIG_ARM_32
> 
> I understand what you're talking about, and it seems reasonable to get rid of
> xen_colored_temp[] and create_llc_coloring_mappings() since in the end they
> serve the purpose of mapping the physically colored space that is already
> mapped using xen_xenmap[] pagetables.
> What I don't understand is then how to copy/relocate Xen since I don't have a
> destination virtual space anymore to use in relocate_xen().

You will need to link xen_xenmap[] in boot_second[...] as well. With 
that, you will be able to access the new Xen through the temporary area.

[...]

>> Note that this means the init_ttbr cannot be written directly. But you
>> can solve this problem by re-mapping the address.
> 
> How to remap a single address?

You should be able to use map_domain_page() to map the page where 
init_ttbr is.

> And if moving init_ttbr in the identity-mapped area means that it's no longer
> writable, so that I need to remap it, why moving it in that area in the first
> place. Again I think I'm missing something.

The goal is to have everything used (code, data) before the MMU is 
turned on residing in a single page. So secondary CPUs can directly jump 
to the colored Xen without any trouble.

>>>
>>> 3) To access the identity mapping area I would need some accessor that takes
>>> an address and returns it + phys_offset, or is there a better way to do it?
>>
>> I am not sure I understand what you mean. Can you clarify?
> 
> In my idea, I would use the identity mapping to access the "old" variables,
> where "old" means non physically colored. init_ttbr is an example. When
> Xen it's copied on the new physical space, init_ttbr is copied with it and
> if the boot cpu modifies this variable, it's actually touching the colored
> one and not the old one. This means that secondary CPUs that still haven't
> jumped to the new space, won't be able to see the new value and will never
> go online.
> So to access this "old" init_ttbr variable I need it's identity address,
> which is its current virtual address + some physical offset. I was asking
> you if this is the right approach to use the identity mapping.

Secondary CPUs would directly start on the colored Xen. So they will be 
able to access the "new" init_ttbr & co.

[...]

>> ... as I wrote ealier your current approach seems to have a flaw. As you
>> overwrite xen_bootmodule->{start, size}. setup_mm() will end up to add
>> the old Xen region to the boot allocator. This is before any secondary
>> CPUs are booted up.
>>
>> IOW, the allocator may provide some memory from the old Xen and nothing
>> good will happen from that.
>>
>> The only way to solve it is to add another module. So the memory is
>> skipped by setup_mm(). However see below.
>>
>>>
>>> Yes that should be memory that in the end would not be needed so it must
>>> return to the boot-allocator (if that's what you mean). But how to do
>>> that?
>>
>> You can't really discard the old temporary Xen. This may work today
>> because we don't support CPU hotplug or suspend/resume. But there was
>> some series on the ML to enable it and I don't see any reason why
>> someone would not want to use the features with cache coloring.
>>
>> So the old temporary Xen would have to be kept around forever. This is
>> up to 8MB of memory wasted.
>>
>> The right approach is to have the secondary CPU boot code (including the
>> variables it is using) fitting in the same page (or possibly multiple so
>> long this is small and physically contiguous). With that it doesn't
>> matter where is the trampoline, it could stay at the old place, but we
>> would only waste a few pages rather than up 8MB as it is today.
> 
> So what are you suggesting is to create a new section in the linker script
> for the trampoline code and data,

We already have a section for that in place (see .idmap.*) which happens 
to be at the beginning of Xen. Right now, the section is in text. Which 
is why it is read-only executable.

> then in setup_mm() we would skip this
> memory?

We should not need this. Secondary boot CPUs should boot direclty on the 
colored Xen.

> Am I following you correctly? Sorry those topics are a little out
> of my preparation as you probably already guessed.

No worries. I am happy to go in as much details as necessary. I can also 
attempt to write a patch if that helps. (unless someone else in the Arm 
maintainers want to give a try).

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-15 11:18           ` Julien Grall
@ 2024-01-15 15:43             ` Carlo Nonato
  2024-01-15 16:16               ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-15 15:43 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Julien,

On Mon, Jan 15, 2024 at 12:18 PM Julien Grall <julien@xen.org> wrote:
> On 15/01/2024 10:11, Carlo Nonato wrote:
> > Hi Julien,
>
> Hi Carlo,
>
> > On Sun, Jan 14, 2024 at 8:22 PM Julien Grall <julien@xen.org> wrote:
> >>
> >> Hi Carlo,
> >>
> >> On 13/01/2024 17:07, Carlo Nonato wrote:
> >>>>> diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
> >>>>> index 37b6d230ad..66b674eeab 100644
> >>>>> --- a/xen/arch/arm/mmu/setup.c
> >>>>> +++ b/xen/arch/arm/mmu/setup.c
> >>>>> @@ -7,6 +7,7 @@
> >>>>>
> >>>>>     #include <xen/init.h>
> >>>>>     #include <xen/libfdt/libfdt.h>
> >>>>> +#include <xen/llc-coloring.h>
> >>>>>     #include <xen/sizes.h>
> >>>>>     #include <xen/vmap.h>
> >>>>>
> >>>>> @@ -39,6 +40,10 @@ DEFINE_PER_CPU(lpae_t *, xen_pgtable);
> >>>>>     static DEFINE_PAGE_TABLE(cpu0_pgtable);
> >>>>>     #endif
> >>>>>
> >>>>> +#ifdef CONFIG_LLC_COLORING
> >>>>> +static DEFINE_PAGE_TABLE(xen_colored_temp);
> >>>>> +#endif
> >>>>
> >>>> Does this actually need to be static?
> >>>
> >>> Why it shouldn't be static? I don't want to access it from another file.
> >>
> >> My question was whether this could be allocated dynamically (or possibly
> >> re-use an existing set of page tables). In particular with the fact that
> >> we will need more than 1 page to cover the whole Xen binary.
> >>
> >> Looking at the use xen_colored_temp. This is pretty much the same as
> >> xen_map[i] but with different permissions. So what you could do is
> >> preparing xen_map[i] with very permissive permissions (i.e. RWX) and
> >> then enforcing the permission once the TTBR has been switched.
> >>
> >> Something like that (tested without cache coloring):
> >>
> >> diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
> >> index a3a263a5d94b..f7ac5cabf92c 100644
> >> --- a/xen/arch/arm/mmu/setup.c
> >> +++ b/xen/arch/arm/mmu/setup.c
> >> @@ -306,7 +306,11 @@ void __init setup_pagetables(unsigned long
> >> boot_phys_offset, paddr_t xen_paddr)
> >>        p[0].pt.table = 1;
> >>        p[0].pt.xn = 0;
> >>
> >> -    /* Break up the Xen mapping into pages and protect them separately. */
> >> +    /*
> >> +     * Break up the Xen mapping into pages. We will protect the
> >> +     * permissions later in order to allow xen_xenmap to be used for
> >> +     * when relocating Xen.
> >> +     */
> >>        for ( i = 0; i < XEN_NR_ENTRIES(3); i++ )
> >>        {
> >>            vaddr_t va = XEN_VIRT_START + (i << PAGE_SHIFT);
> >> @@ -315,13 +319,7 @@ void __init setup_pagetables(unsigned long
> >> boot_phys_offset, paddr_t xen_paddr)
> >>                break;
> >>            pte = pte_of_xenaddr(va);
> >>            pte.pt.table = 1; /* third level mappings always have this bit
> >> set */
> >> -        if ( is_kernel_text(va) || is_kernel_inittext(va) )
> >> -        {
> >> -            pte.pt.xn = 0;
> >> -            pte.pt.ro = 1;
> >> -        }
> >> -        if ( is_kernel_rodata(va) )
> >> -            pte.pt.ro = 1;
> >> +        pte.pt.xn = 0; /* Permissions will be enforced later. Allow
> >> execution */
> >>            xen_xenmap[i] = pte;
> >>        }
> >>
> >> @@ -352,6 +350,37 @@ void __init setup_pagetables(unsigned long
> >> boot_phys_offset, paddr_t xen_paddr)
> >>
> >>        switch_ttbr(ttbr);
> >>
> >> +    /* Protect Xen */
> >> +    for ( i = 0; i < XEN_NR_ENTRIES(3); i++ )
> >> +    {
> >> +        vaddr_t va = XEN_VIRT_START + (i << PAGE_SHIFT);
> >> +        lpae_t *entry = xen_xenmap + i;
> >> +
> >> +        if ( !is_kernel(va) )
> >> +            break;
> >> +
> >> +        pte = read_atomic(entry);
> >> +
> >> +        if ( is_kernel_text(va) || is_kernel_inittext(va) )
> >> +        {
> >> +            pte.pt.xn = 0;
> >> +            pte.pt.ro = 1;
> >> +        } else if ( is_kernel_rodata(va) ) {
> >> +            pte.pt.ro = 1;
> >> +            pte.pt.xn = 1;
> >> +        } else {
> >> +            pte.pt.xn = 1;
> >> +            pte.pt.ro = 0;
> >> +        }
> >> +
> >> +        write_pte(entry, pte);
> >> +    }
> >> +
> >> +    /*
> >> +     * We modified live page-tables. Ensure the TBLs are invalidated
> >> +     * before setting enforcing the WnX permissions.
> >> +     */
> >> +    flush_xen_tlb_local();
> >>        xen_pt_enforce_wnx();
> >>
> >>    #ifdef CONFIG_ARM_32
> >
> > I understand what you're talking about, and it seems reasonable to get rid of
> > xen_colored_temp[] and create_llc_coloring_mappings() since in the end they
> > serve the purpose of mapping the physically colored space that is already
> > mapped using xen_xenmap[] pagetables.
> > What I don't understand is then how to copy/relocate Xen since I don't have a
> > destination virtual space anymore to use in relocate_xen().
>
> You will need to link xen_xenmap[] in boot_second[...] as well. With
> that, you will be able to access the new Xen through the temporary area.

Wouldn't it result in overwriting the current virtual space mapping?
boot_second is the live page table and if I link xen_xenmap[] then
XEN_VIRT_START would point to the new colored space which is still empty at
this stage...

> [...]
>
> >> Note that this means the init_ttbr cannot be written directly. But you
> >> can solve this problem by re-mapping the address.
> >
> > How to remap a single address?
>
> You should be able to use map_domain_page() to map the page where
> init_ttbr is.
>
> > And if moving init_ttbr in the identity-mapped area means that it's no longer
> > writable, so that I need to remap it, why moving it in that area in the first
> > place. Again I think I'm missing something.
>
> The goal is to have everything used (code, data) before the MMU is
> turned on residing in a single page. So secondary CPUs can directly jump
> to the colored Xen without any trouble.

This is what confuses me. Why having everything on a single page makes
secondary cpus able to jump directly to colored Xen? (also see below)

> >>>
> >>> 3) To access the identity mapping area I would need some accessor that takes
> >>> an address and returns it + phys_offset, or is there a better way to do it?
> >>
> >> I am not sure I understand what you mean. Can you clarify?
> >
> > In my idea, I would use the identity mapping to access the "old" variables,
> > where "old" means non physically colored. init_ttbr is an example. When
> > Xen it's copied on the new physical space, init_ttbr is copied with it and
> > if the boot cpu modifies this variable, it's actually touching the colored
> > one and not the old one. This means that secondary CPUs that still haven't
> > jumped to the new space, won't be able to see the new value and will never
> > go online.
> > So to access this "old" init_ttbr variable I need it's identity address,
> > which is its current virtual address + some physical offset. I was asking
> > you if this is the right approach to use the identity mapping.
>
> Secondary CPUs would directly start on the colored Xen. So they will be
> able to access the "new" init_ttbr & co.

How can this be true? I mean, in call_psci_cpu_on() I can start those CPUs in
the colored space, but they still use the boot_* pagetables and there I can't
easily link the new colored space, or, at least, I'm not succeding in doing
that. What I tried at the moment is to link xen_xenmap in boot_second after
switch_ttbr because of the problem I described above. But then secondary
CPUs never go online...

> [...]
>
> >> ... as I wrote ealier your current approach seems to have a flaw. As you
> >> overwrite xen_bootmodule->{start, size}. setup_mm() will end up to add
> >> the old Xen region to the boot allocator. This is before any secondary
> >> CPUs are booted up.
> >>
> >> IOW, the allocator may provide some memory from the old Xen and nothing
> >> good will happen from that.
> >>
> >> The only way to solve it is to add another module. So the memory is
> >> skipped by setup_mm(). However see below.
> >>
> >>>
> >>> Yes that should be memory that in the end would not be needed so it must
> >>> return to the boot-allocator (if that's what you mean). But how to do
> >>> that?
> >>
> >> You can't really discard the old temporary Xen. This may work today
> >> because we don't support CPU hotplug or suspend/resume. But there was
> >> some series on the ML to enable it and I don't see any reason why
> >> someone would not want to use the features with cache coloring.
> >>
> >> So the old temporary Xen would have to be kept around forever. This is
> >> up to 8MB of memory wasted.
> >>
> >> The right approach is to have the secondary CPU boot code (including the
> >> variables it is using) fitting in the same page (or possibly multiple so
> >> long this is small and physically contiguous). With that it doesn't
> >> matter where is the trampoline, it could stay at the old place, but we
> >> would only waste a few pages rather than up 8MB as it is today.
> >
> > So what are you suggesting is to create a new section in the linker script
> > for the trampoline code and data,
>
> We already have a section for that in place (see .idmap.*) which happens
> to be at the beginning of Xen. Right now, the section is in text. Which
> is why it is read-only executable.
>
> > then in setup_mm() we would skip this
> > memory?
>
> We should not need this. Secondary boot CPUs should boot direclty on the
> colored Xen.
>
> > Am I following you correctly? Sorry those topics are a little out
> > of my preparation as you probably already guessed.
>
> No worries. I am happy to go in as much details as necessary. I can also
> attempt to write a patch if that helps. (unless someone else in the Arm
> maintainers want to give a try).

Yes this would help. Thanks.

>
> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-15 15:43             ` Carlo Nonato
@ 2024-01-15 16:16               ` Julien Grall
  2024-01-16  9:00                 ` Carlo Nonato
  2024-01-16 11:58                 ` Julien Grall
  0 siblings, 2 replies; 90+ messages in thread
From: Julien Grall @ 2024-01-15 16:16 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri



On 15/01/2024 15:43, Carlo Nonato wrote:
> Hi Julien,

Hi Carlo,

> On Mon, Jan 15, 2024 at 12:18 PM Julien Grall <julien@xen.org> wrote:
>> On 15/01/2024 10:11, Carlo Nonato wrote:
>>> I understand what you're talking about, and it seems reasonable to get rid of
>>> xen_colored_temp[] and create_llc_coloring_mappings() since in the end they
>>> serve the purpose of mapping the physically colored space that is already
>>> mapped using xen_xenmap[] pagetables.
>>> What I don't understand is then how to copy/relocate Xen since I don't have a
>>> destination virtual space anymore to use in relocate_xen().
>>
>> You will need to link xen_xenmap[] in boot_second[...] as well. With
>> that, you will be able to access the new Xen through the temporary area.
> 
> Wouldn't it result in overwriting the current virtual space mapping?
> boot_second is the live page table and if I link xen_xenmap[] then
> XEN_VIRT_START would point to the new colored space which is still empty at
> this stage...

If you link at XEN_VIRT_START then yes. But you could link at 
BOOT_RELOC_VIRT_START like you already do today.

> 
>> [...]
>>
>>>> Note that this means the init_ttbr cannot be written directly. But you
>>>> can solve this problem by re-mapping the address.
>>>
>>> How to remap a single address?
>>
>> You should be able to use map_domain_page() to map the page where
>> init_ttbr is.
>>
>>> And if moving init_ttbr in the identity-mapped area means that it's no longer
>>> writable, so that I need to remap it, why moving it in that area in the first
>>> place. Again I think I'm missing something.
>>
>> The goal is to have everything used (code, data) before the MMU is
>> turned on residing in a single page. So secondary CPUs can directly jump
>> to the colored Xen without any trouble.
> 
> This is what confuses me. Why having everything on a single page makes
> secondary cpus able to jump directly to colored Xen? (also see below)

Because the code running with the MMU off can access easily access 
everything.

> 
>>>>>
>>>>> 3) To access the identity mapping area I would need some accessor that takes
>>>>> an address and returns it + phys_offset, or is there a better way to do it?
>>>>
>>>> I am not sure I understand what you mean. Can you clarify?
>>>
>>> In my idea, I would use the identity mapping to access the "old" variables,
>>> where "old" means non physically colored. init_ttbr is an example. When
>>> Xen it's copied on the new physical space, init_ttbr is copied with it and
>>> if the boot cpu modifies this variable, it's actually touching the colored
>>> one and not the old one. This means that secondary CPUs that still haven't
>>> jumped to the new space, won't be able to see the new value and will never
>>> go online.
>>> So to access this "old" init_ttbr variable I need it's identity address,
>>> which is its current virtual address + some physical offset. I was asking
>>> you if this is the right approach to use the identity mapping.
>>
>> Secondary CPUs would directly start on the colored Xen. So they will be
>> able to access the "new" init_ttbr & co.
> 
> How can this be true? I mean, in call_psci_cpu_on() I can start those CPUs in
> the colored space, but they still use the boot_* pagetables

Are you looking at the 64-bit or 32-bit code? For 64-bit, staging is not 
using boot_* pagetable anymore for secondary CPUs. Instead, they 
directly jump to the runtime page-tables.

> and there I can't
> easily link the new colored space, or, at least, I'm not succeding in doing
> that. What I tried at the moment is to link xen_xenmap in boot_second after
> switch_ttbr because of the problem I described above. But then secondary
> CPUs never go online...

It would be helpful if you share some code.

> 
>> [...]
>>
>>>> ... as I wrote ealier your current approach seems to have a flaw. As you
>>>> overwrite xen_bootmodule->{start, size}. setup_mm() will end up to add
>>>> the old Xen region to the boot allocator. This is before any secondary
>>>> CPUs are booted up.
>>>>
>>>> IOW, the allocator may provide some memory from the old Xen and nothing
>>>> good will happen from that.
>>>>
>>>> The only way to solve it is to add another module. So the memory is
>>>> skipped by setup_mm(). However see below.
>>>>
>>>>>
>>>>> Yes that should be memory that in the end would not be needed so it must
>>>>> return to the boot-allocator (if that's what you mean). But how to do
>>>>> that?
>>>>
>>>> You can't really discard the old temporary Xen. This may work today
>>>> because we don't support CPU hotplug or suspend/resume. But there was
>>>> some series on the ML to enable it and I don't see any reason why
>>>> someone would not want to use the features with cache coloring.
>>>>
>>>> So the old temporary Xen would have to be kept around forever. This is
>>>> up to 8MB of memory wasted.
>>>>
>>>> The right approach is to have the secondary CPU boot code (including the
>>>> variables it is using) fitting in the same page (or possibly multiple so
>>>> long this is small and physically contiguous). With that it doesn't
>>>> matter where is the trampoline, it could stay at the old place, but we
>>>> would only waste a few pages rather than up 8MB as it is today.
>>>
>>> So what are you suggesting is to create a new section in the linker script
>>> for the trampoline code and data,
>>
>> We already have a section for that in place (see .idmap.*) which happens
>> to be at the beginning of Xen. Right now, the section is in text. Which
>> is why it is read-only executable.
>>
>>> then in setup_mm() we would skip this
>>> memory?
>>
>> We should not need this. Secondary boot CPUs should boot direclty on the
>> colored Xen.
>>
>>> Am I following you correctly? Sorry those topics are a little out
>>> of my preparation as you probably already guessed.
>>
>> No worries. I am happy to go in as much details as necessary. I can also
>> attempt to write a patch if that helps. (unless someone else in the Arm
>> maintainers want to give a try).
> 
> Yes this would help. Thanks.

I will try to have a look this evening. If I can't, it may have to wait 
a couple of weeks unless someone has time before hand.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-15 16:16               ` Julien Grall
@ 2024-01-16  9:00                 ` Carlo Nonato
  2024-01-16 11:58                 ` Julien Grall
  1 sibling, 0 replies; 90+ messages in thread
From: Carlo Nonato @ 2024-01-16  9:00 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Julien,

On Mon, Jan 15, 2024 at 5:16 PM Julien Grall <julien@xen.org> wrote:
> On 15/01/2024 15:43, Carlo Nonato wrote:
> > Hi Julien,
>
> Hi Carlo,
>
> > On Mon, Jan 15, 2024 at 12:18 PM Julien Grall <julien@xen.org> wrote:
> >> On 15/01/2024 10:11, Carlo Nonato wrote:
> >>> I understand what you're talking about, and it seems reasonable to get rid of
> >>> xen_colored_temp[] and create_llc_coloring_mappings() since in the end they
> >>> serve the purpose of mapping the physically colored space that is already
> >>> mapped using xen_xenmap[] pagetables.
> >>> What I don't understand is then how to copy/relocate Xen since I don't have a
> >>> destination virtual space anymore to use in relocate_xen().
> >>
> >> You will need to link xen_xenmap[] in boot_second[...] as well. With
> >> that, you will be able to access the new Xen through the temporary area.
> >
> > Wouldn't it result in overwriting the current virtual space mapping?
> > boot_second is the live page table and if I link xen_xenmap[] then
> > XEN_VIRT_START would point to the new colored space which is still empty at
> > this stage...
>
> If you link at XEN_VIRT_START then yes. But you could link at
> BOOT_RELOC_VIRT_START like you already do today.

Ok I think I got it.

> >
> >> [...]
> >>
> >>>> Note that this means the init_ttbr cannot be written directly. But you
> >>>> can solve this problem by re-mapping the address.
> >>>
> >>> How to remap a single address?
> >>
> >> You should be able to use map_domain_page() to map the page where
> >> init_ttbr is.
> >>
> >>> And if moving init_ttbr in the identity-mapped area means that it's no longer
> >>> writable, so that I need to remap it, why moving it in that area in the first
> >>> place. Again I think I'm missing something.
> >>
> >> The goal is to have everything used (code, data) before the MMU is
> >> turned on residing in a single page. So secondary CPUs can directly jump
> >> to the colored Xen without any trouble.
> >
> > This is what confuses me. Why having everything on a single page makes
> > secondary cpus able to jump directly to colored Xen? (also see below)
>
> Because the code running with the MMU off can access easily access
> everything.

This was what I got wrong. Now it's clear.

> >
> >>>>>
> >>>>> 3) To access the identity mapping area I would need some accessor that takes
> >>>>> an address and returns it + phys_offset, or is there a better way to do it?
> >>>>
> >>>> I am not sure I understand what you mean. Can you clarify?
> >>>
> >>> In my idea, I would use the identity mapping to access the "old" variables,
> >>> where "old" means non physically colored. init_ttbr is an example. When
> >>> Xen it's copied on the new physical space, init_ttbr is copied with it and
> >>> if the boot cpu modifies this variable, it's actually touching the colored
> >>> one and not the old one. This means that secondary CPUs that still haven't
> >>> jumped to the new space, won't be able to see the new value and will never
> >>> go online.
> >>> So to access this "old" init_ttbr variable I need it's identity address,
> >>> which is its current virtual address + some physical offset. I was asking
> >>> you if this is the right approach to use the identity mapping.
> >>
> >> Secondary CPUs would directly start on the colored Xen. So they will be
> >> able to access the "new" init_ttbr & co.
> >
> > How can this be true? I mean, in call_psci_cpu_on() I can start those CPUs in
> > the colored space, but they still use the boot_* pagetables
>
> Are you looking at the 64-bit or 32-bit code? For 64-bit, staging is not
> using boot_* pagetable anymore for secondary CPUs. Instead, they
> directly jump to the runtime page-tables.

Again, my fault. Got it.

> > and there I can't
> > easily link the new colored space, or, at least, I'm not succeding in doing
> > that. What I tried at the moment is to link xen_xenmap in boot_second after
> > switch_ttbr because of the problem I described above. But then secondary
> > CPUs never go online...
>
> It would be helpful if you share some code.

Given the newfound knowledge, I'll think I can get further.

Thanks.

> >
> >> [...]
> >>
> >>>> ... as I wrote ealier your current approach seems to have a flaw. As you
> >>>> overwrite xen_bootmodule->{start, size}. setup_mm() will end up to add
> >>>> the old Xen region to the boot allocator. This is before any secondary
> >>>> CPUs are booted up.
> >>>>
> >>>> IOW, the allocator may provide some memory from the old Xen and nothing
> >>>> good will happen from that.
> >>>>
> >>>> The only way to solve it is to add another module. So the memory is
> >>>> skipped by setup_mm(). However see below.
> >>>>
> >>>>>
> >>>>> Yes that should be memory that in the end would not be needed so it must
> >>>>> return to the boot-allocator (if that's what you mean). But how to do
> >>>>> that?
> >>>>
> >>>> You can't really discard the old temporary Xen. This may work today
> >>>> because we don't support CPU hotplug or suspend/resume. But there was
> >>>> some series on the ML to enable it and I don't see any reason why
> >>>> someone would not want to use the features with cache coloring.
> >>>>
> >>>> So the old temporary Xen would have to be kept around forever. This is
> >>>> up to 8MB of memory wasted.
> >>>>
> >>>> The right approach is to have the secondary CPU boot code (including the
> >>>> variables it is using) fitting in the same page (or possibly multiple so
> >>>> long this is small and physically contiguous). With that it doesn't
> >>>> matter where is the trampoline, it could stay at the old place, but we
> >>>> would only waste a few pages rather than up 8MB as it is today.
> >>>
> >>> So what are you suggesting is to create a new section in the linker script
> >>> for the trampoline code and data,
> >>
> >> We already have a section for that in place (see .idmap.*) which happens
> >> to be at the beginning of Xen. Right now, the section is in text. Which
> >> is why it is read-only executable.
> >>
> >>> then in setup_mm() we would skip this
> >>> memory?
> >>
> >> We should not need this. Secondary boot CPUs should boot direclty on the
> >> colored Xen.
> >>
> >>> Am I following you correctly? Sorry those topics are a little out
> >>> of my preparation as you probably already guessed.
> >>
> >> No worries. I am happy to go in as much details as necessary. I can also
> >> attempt to write a patch if that helps. (unless someone else in the Arm
> >> maintainers want to give a try).
> >
> > Yes this would help. Thanks.
>
> I will try to have a look this evening. If I can't, it may have to wait
> a couple of weeks unless someone has time before hand.
>
> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-15 16:16               ` Julien Grall
  2024-01-16  9:00                 ` Carlo Nonato
@ 2024-01-16 11:58                 ` Julien Grall
  2024-01-17 17:38                   ` Carlo Nonato
  1 sibling, 1 reply; 90+ messages in thread
From: Julien Grall @ 2024-01-16 11:58 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi,

On 15/01/2024 16:16, Julien Grall wrote:
> On 15/01/2024 15:43, Carlo Nonato wrote:
>> Hi Julien,
> 
> Hi Carlo,
> 
>> On Mon, Jan 15, 2024 at 12:18 PM Julien Grall <julien@xen.org> wrote:
>>> On 15/01/2024 10:11, Carlo Nonato wrote:
>>>> I understand what you're talking about, and it seems reasonable to 
>>>> get rid of
>>>> xen_colored_temp[] and create_llc_coloring_mappings() since in the 
>>>> end they
>>>> serve the purpose of mapping the physically colored space that is 
>>>> already
>>>> mapped using xen_xenmap[] pagetables.
>>>> What I don't understand is then how to copy/relocate Xen since I 
>>>> don't have a
>>>> destination virtual space anymore to use in relocate_xen().
>>>
>>> You will need to link xen_xenmap[] in boot_second[...] as well. With
>>> that, you will be able to access the new Xen through the temporary area.
>>
>> Wouldn't it result in overwriting the current virtual space mapping?
>> boot_second is the live page table and if I link xen_xenmap[] then
>> XEN_VIRT_START would point to the new colored space which is still 
>> empty at
>> this stage...
> 
> If you link at XEN_VIRT_START then yes. But you could link at 
> BOOT_RELOC_VIRT_START like you already do today.
> 
>>
>>> [...]
>>>
>>>>> Note that this means the init_ttbr cannot be written directly. But you
>>>>> can solve this problem by re-mapping the address.
>>>>
>>>> How to remap a single address?
>>>
>>> You should be able to use map_domain_page() to map the page where
>>> init_ttbr is.
>>>
>>>> And if moving init_ttbr in the identity-mapped area means that it's 
>>>> no longer
>>>> writable, so that I need to remap it, why moving it in that area in 
>>>> the first
>>>> place. Again I think I'm missing something.
>>>
>>> The goal is to have everything used (code, data) before the MMU is
>>> turned on residing in a single page. So secondary CPUs can directly jump
>>> to the colored Xen without any trouble.
>>
>> This is what confuses me. Why having everything on a single page makes
>> secondary cpus able to jump directly to colored Xen? (also see below)
> 
> Because the code running with the MMU off can access easily access 
> everything.
> 
>>
>>>>>>
>>>>>> 3) To access the identity mapping area I would need some accessor 
>>>>>> that takes
>>>>>> an address and returns it + phys_offset, or is there a better way 
>>>>>> to do it?
>>>>>
>>>>> I am not sure I understand what you mean. Can you clarify?
>>>>
>>>> In my idea, I would use the identity mapping to access the "old" 
>>>> variables,
>>>> where "old" means non physically colored. init_ttbr is an example. When
>>>> Xen it's copied on the new physical space, init_ttbr is copied with 
>>>> it and
>>>> if the boot cpu modifies this variable, it's actually touching the 
>>>> colored
>>>> one and not the old one. This means that secondary CPUs that still 
>>>> haven't
>>>> jumped to the new space, won't be able to see the new value and will 
>>>> never
>>>> go online.
>>>> So to access this "old" init_ttbr variable I need it's identity 
>>>> address,
>>>> which is its current virtual address + some physical offset. I was 
>>>> asking
>>>> you if this is the right approach to use the identity mapping.
>>>
>>> Secondary CPUs would directly start on the colored Xen. So they will be
>>> able to access the "new" init_ttbr & co.
>>
>> How can this be true? I mean, in call_psci_cpu_on() I can start those 
>> CPUs in
>> the colored space, but they still use the boot_* pagetables
> 
> Are you looking at the 64-bit or 32-bit code? For 64-bit, staging is not 
> using boot_* pagetable anymore for secondary CPUs. Instead, they 
> directly jump to the runtime page-tables.
> 
>> and there I can't
>> easily link the new colored space, or, at least, I'm not succeding in 
>> doing
>> that. What I tried at the moment is to link xen_xenmap in boot_second 
>> after
>> switch_ttbr because of the problem I described above. But then secondary
>> CPUs never go online...
> 
> It would be helpful if you share some code.
> 
>>
>>> [...]
>>>
>>>>> ... as I wrote ealier your current approach seems to have a flaw. 
>>>>> As you
>>>>> overwrite xen_bootmodule->{start, size}. setup_mm() will end up to add
>>>>> the old Xen region to the boot allocator. This is before any secondary
>>>>> CPUs are booted up.
>>>>>
>>>>> IOW, the allocator may provide some memory from the old Xen and 
>>>>> nothing
>>>>> good will happen from that.
>>>>>
>>>>> The only way to solve it is to add another module. So the memory is
>>>>> skipped by setup_mm(). However see below.
>>>>>
>>>>>>
>>>>>> Yes that should be memory that in the end would not be needed so 
>>>>>> it must
>>>>>> return to the boot-allocator (if that's what you mean). But how to do
>>>>>> that?
>>>>>
>>>>> You can't really discard the old temporary Xen. This may work today
>>>>> because we don't support CPU hotplug or suspend/resume. But there was
>>>>> some series on the ML to enable it and I don't see any reason why
>>>>> someone would not want to use the features with cache coloring.
>>>>>
>>>>> So the old temporary Xen would have to be kept around forever. This is
>>>>> up to 8MB of memory wasted.
>>>>>
>>>>> The right approach is to have the secondary CPU boot code 
>>>>> (including the
>>>>> variables it is using) fitting in the same page (or possibly 
>>>>> multiple so
>>>>> long this is small and physically contiguous). With that it doesn't
>>>>> matter where is the trampoline, it could stay at the old place, but we
>>>>> would only waste a few pages rather than up 8MB as it is today.
>>>>
>>>> So what are you suggesting is to create a new section in the linker 
>>>> script
>>>> for the trampoline code and data,
>>>
>>> We already have a section for that in place (see .idmap.*) which happens
>>> to be at the beginning of Xen. Right now, the section is in text. Which
>>> is why it is read-only executable.
>>>
>>>> then in setup_mm() we would skip this
>>>> memory?
>>>
>>> We should not need this. Secondary boot CPUs should boot direclty on the
>>> colored Xen.
>>>
>>>> Am I following you correctly? Sorry those topics are a little out
>>>> of my preparation as you probably already guessed.
>>>
>>> No worries. I am happy to go in as much details as necessary. I can also
>>> attempt to write a patch if that helps. (unless someone else in the Arm
>>> maintainers want to give a try).
>>
>> Yes this would help. Thanks.
> 
> I will try to have a look this evening. If I can't, it may have to wait 
> a couple of weeks unless someone has time before hand.

Series sent [1]. This is not fully complete for cache coloring. You will 
need to modify the identity functions to take into account that the 
identity map will be different.

You will also want to check the new identity map area is still below 
(see the check in prepare_boot_identity_mapping()).

Cheers,

[1] https://lore.kernel.org/xen-devel/20240116115509.77545-1-julien@xen.org/

-- 
Julien Grall


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-16 11:58                 ` Julien Grall
@ 2024-01-17 17:38                   ` Carlo Nonato
  2024-01-18  9:29                     ` Julien Grall
  0 siblings, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-17 17:38 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Julien,

On Tue, Jan 16, 2024 at 12:59 PM Julien Grall <julien@xen.org> wrote:
>
> Hi,
>
> On 15/01/2024 16:16, Julien Grall wrote:
> > On 15/01/2024 15:43, Carlo Nonato wrote:
> >> Hi Julien,
> >
> > Hi Carlo,
> >
> >> On Mon, Jan 15, 2024 at 12:18 PM Julien Grall <julien@xen.org> wrote:
> >>> On 15/01/2024 10:11, Carlo Nonato wrote:
> >>>> I understand what you're talking about, and it seems reasonable to
> >>>> get rid of
> >>>> xen_colored_temp[] and create_llc_coloring_mappings() since in the
> >>>> end they
> >>>> serve the purpose of mapping the physically colored space that is
> >>>> already
> >>>> mapped using xen_xenmap[] pagetables.
> >>>> What I don't understand is then how to copy/relocate Xen since I
> >>>> don't have a
> >>>> destination virtual space anymore to use in relocate_xen().
> >>>
> >>> You will need to link xen_xenmap[] in boot_second[...] as well. With
> >>> that, you will be able to access the new Xen through the temporary area.
> >>
> >> Wouldn't it result in overwriting the current virtual space mapping?
> >> boot_second is the live page table and if I link xen_xenmap[] then
> >> XEN_VIRT_START would point to the new colored space which is still
> >> empty at
> >> this stage...
> >
> > If you link at XEN_VIRT_START then yes. But you could link at
> > BOOT_RELOC_VIRT_START like you already do today.
> >
> >>
> >>> [...]
> >>>
> >>>>> Note that this means the init_ttbr cannot be written directly. But you
> >>>>> can solve this problem by re-mapping the address.
> >>>>
> >>>> How to remap a single address?
> >>>
> >>> You should be able to use map_domain_page() to map the page where
> >>> init_ttbr is.
> >>>
> >>>> And if moving init_ttbr in the identity-mapped area means that it's
> >>>> no longer
> >>>> writable, so that I need to remap it, why moving it in that area in
> >>>> the first
> >>>> place. Again I think I'm missing something.
> >>>
> >>> The goal is to have everything used (code, data) before the MMU is
> >>> turned on residing in a single page. So secondary CPUs can directly jump
> >>> to the colored Xen without any trouble.
> >>
> >> This is what confuses me. Why having everything on a single page makes
> >> secondary cpus able to jump directly to colored Xen? (also see below)
> >
> > Because the code running with the MMU off can access easily access
> > everything.
> >
> >>
> >>>>>>
> >>>>>> 3) To access the identity mapping area I would need some accessor
> >>>>>> that takes
> >>>>>> an address and returns it + phys_offset, or is there a better way
> >>>>>> to do it?
> >>>>>
> >>>>> I am not sure I understand what you mean. Can you clarify?
> >>>>
> >>>> In my idea, I would use the identity mapping to access the "old"
> >>>> variables,
> >>>> where "old" means non physically colored. init_ttbr is an example. When
> >>>> Xen it's copied on the new physical space, init_ttbr is copied with
> >>>> it and
> >>>> if the boot cpu modifies this variable, it's actually touching the
> >>>> colored
> >>>> one and not the old one. This means that secondary CPUs that still
> >>>> haven't
> >>>> jumped to the new space, won't be able to see the new value and will
> >>>> never
> >>>> go online.
> >>>> So to access this "old" init_ttbr variable I need it's identity
> >>>> address,
> >>>> which is its current virtual address + some physical offset. I was
> >>>> asking
> >>>> you if this is the right approach to use the identity mapping.
> >>>
> >>> Secondary CPUs would directly start on the colored Xen. So they will be
> >>> able to access the "new" init_ttbr & co.
> >>
> >> How can this be true? I mean, in call_psci_cpu_on() I can start those
> >> CPUs in
> >> the colored space, but they still use the boot_* pagetables
> >
> > Are you looking at the 64-bit or 32-bit code? For 64-bit, staging is not
> > using boot_* pagetable anymore for secondary CPUs. Instead, they
> > directly jump to the runtime page-tables.
> >
> >> and there I can't
> >> easily link the new colored space, or, at least, I'm not succeding in
> >> doing
> >> that. What I tried at the moment is to link xen_xenmap in boot_second
> >> after
> >> switch_ttbr because of the problem I described above. But then secondary
> >> CPUs never go online...
> >
> > It would be helpful if you share some code.
> >
> >>
> >>> [...]
> >>>
> >>>>> ... as I wrote ealier your current approach seems to have a flaw.
> >>>>> As you
> >>>>> overwrite xen_bootmodule->{start, size}. setup_mm() will end up to add
> >>>>> the old Xen region to the boot allocator. This is before any secondary
> >>>>> CPUs are booted up.
> >>>>>
> >>>>> IOW, the allocator may provide some memory from the old Xen and
> >>>>> nothing
> >>>>> good will happen from that.
> >>>>>
> >>>>> The only way to solve it is to add another module. So the memory is
> >>>>> skipped by setup_mm(). However see below.
> >>>>>
> >>>>>>
> >>>>>> Yes that should be memory that in the end would not be needed so
> >>>>>> it must
> >>>>>> return to the boot-allocator (if that's what you mean). But how to do
> >>>>>> that?
> >>>>>
> >>>>> You can't really discard the old temporary Xen. This may work today
> >>>>> because we don't support CPU hotplug or suspend/resume. But there was
> >>>>> some series on the ML to enable it and I don't see any reason why
> >>>>> someone would not want to use the features with cache coloring.
> >>>>>
> >>>>> So the old temporary Xen would have to be kept around forever. This is
> >>>>> up to 8MB of memory wasted.
> >>>>>
> >>>>> The right approach is to have the secondary CPU boot code
> >>>>> (including the
> >>>>> variables it is using) fitting in the same page (or possibly
> >>>>> multiple so
> >>>>> long this is small and physically contiguous). With that it doesn't
> >>>>> matter where is the trampoline, it could stay at the old place, but we
> >>>>> would only waste a few pages rather than up 8MB as it is today.
> >>>>
> >>>> So what are you suggesting is to create a new section in the linker
> >>>> script
> >>>> for the trampoline code and data,
> >>>
> >>> We already have a section for that in place (see .idmap.*) which happens
> >>> to be at the beginning of Xen. Right now, the section is in text. Which
> >>> is why it is read-only executable.
> >>>
> >>>> then in setup_mm() we would skip this
> >>>> memory?
> >>>
> >>> We should not need this. Secondary boot CPUs should boot direclty on the
> >>> colored Xen.
> >>>
> >>>> Am I following you correctly? Sorry those topics are a little out
> >>>> of my preparation as you probably already guessed.
> >>>
> >>> No worries. I am happy to go in as much details as necessary. I can also
> >>> attempt to write a patch if that helps. (unless someone else in the Arm
> >>> maintainers want to give a try).
> >>
> >> Yes this would help. Thanks.
> >
> > I will try to have a look this evening. If I can't, it may have to wait
> > a couple of weeks unless someone has time before hand.
>
> Series sent [1]. This is not fully complete for cache coloring. You will
> need to modify the identity functions to take into account that the
> identity map will be different.
>
> You will also want to check the new identity map area is still below
> (see the check in prepare_boot_identity_mapping()).
>
> Cheers,
>
> [1] https://lore.kernel.org/xen-devel/20240116115509.77545-1-julien@xen.org/

Thank you very much for your help. I succeeded in applying your patches and
reworking setup_pagetables() as we discussed previously. I dropped
xen_colored_temp[], the temporary mapping at the end of setup_pagetables()
and remove_llc_coloring_mappings().

Now, what to do with your patches? Will you push those before this series?

I still have a few other minor problems to face in other patches of my series,
but then I should be ready for v6.

> --
> Julien Grall

Thanks.


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

* Re: [PATCH v5 13/13] xen/arm: add cache coloring support for Xen
  2024-01-17 17:38                   ` Carlo Nonato
@ 2024-01-18  9:29                     ` Julien Grall
  0 siblings, 0 replies; 90+ messages in thread
From: Julien Grall @ 2024-01-18  9:29 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Marco Solieri

Hi Carlo,

On 17/01/2024 17:38, Carlo Nonato wrote:
> On Tue, Jan 16, 2024 at 12:59 PM Julien Grall <julien@xen.org> wrote:
>>
>> Hi,
>>
>> On 15/01/2024 16:16, Julien Grall wrote:
>>> On 15/01/2024 15:43, Carlo Nonato wrote:
>>>> Hi Julien,
>>>
>>> Hi Carlo,
>>>
>>>> On Mon, Jan 15, 2024 at 12:18 PM Julien Grall <julien@xen.org> wrote:
>>>>> On 15/01/2024 10:11, Carlo Nonato wrote:
>>>>>> I understand what you're talking about, and it seems reasonable to
>>>>>> get rid of
>>>>>> xen_colored_temp[] and create_llc_coloring_mappings() since in the
>>>>>> end they
>>>>>> serve the purpose of mapping the physically colored space that is
>>>>>> already
>>>>>> mapped using xen_xenmap[] pagetables.
>>>>>> What I don't understand is then how to copy/relocate Xen since I
>>>>>> don't have a
>>>>>> destination virtual space anymore to use in relocate_xen().
>>>>>
>>>>> You will need to link xen_xenmap[] in boot_second[...] as well. With
>>>>> that, you will be able to access the new Xen through the temporary area.
>>>>
>>>> Wouldn't it result in overwriting the current virtual space mapping?
>>>> boot_second is the live page table and if I link xen_xenmap[] then
>>>> XEN_VIRT_START would point to the new colored space which is still
>>>> empty at
>>>> this stage...
>>>
>>> If you link at XEN_VIRT_START then yes. But you could link at
>>> BOOT_RELOC_VIRT_START like you already do today.
>>>
>>>>
>>>>> [...]
>>>>>
>>>>>>> Note that this means the init_ttbr cannot be written directly. But you
>>>>>>> can solve this problem by re-mapping the address.
>>>>>>
>>>>>> How to remap a single address?
>>>>>
>>>>> You should be able to use map_domain_page() to map the page where
>>>>> init_ttbr is.
>>>>>
>>>>>> And if moving init_ttbr in the identity-mapped area means that it's
>>>>>> no longer
>>>>>> writable, so that I need to remap it, why moving it in that area in
>>>>>> the first
>>>>>> place. Again I think I'm missing something.
>>>>>
>>>>> The goal is to have everything used (code, data) before the MMU is
>>>>> turned on residing in a single page. So secondary CPUs can directly jump
>>>>> to the colored Xen without any trouble.
>>>>
>>>> This is what confuses me. Why having everything on a single page makes
>>>> secondary cpus able to jump directly to colored Xen? (also see below)
>>>
>>> Because the code running with the MMU off can access easily access
>>> everything.
>>>
>>>>
>>>>>>>>
>>>>>>>> 3) To access the identity mapping area I would need some accessor
>>>>>>>> that takes
>>>>>>>> an address and returns it + phys_offset, or is there a better way
>>>>>>>> to do it?
>>>>>>>
>>>>>>> I am not sure I understand what you mean. Can you clarify?
>>>>>>
>>>>>> In my idea, I would use the identity mapping to access the "old"
>>>>>> variables,
>>>>>> where "old" means non physically colored. init_ttbr is an example. When
>>>>>> Xen it's copied on the new physical space, init_ttbr is copied with
>>>>>> it and
>>>>>> if the boot cpu modifies this variable, it's actually touching the
>>>>>> colored
>>>>>> one and not the old one. This means that secondary CPUs that still
>>>>>> haven't
>>>>>> jumped to the new space, won't be able to see the new value and will
>>>>>> never
>>>>>> go online.
>>>>>> So to access this "old" init_ttbr variable I need it's identity
>>>>>> address,
>>>>>> which is its current virtual address + some physical offset. I was
>>>>>> asking
>>>>>> you if this is the right approach to use the identity mapping.
>>>>>
>>>>> Secondary CPUs would directly start on the colored Xen. So they will be
>>>>> able to access the "new" init_ttbr & co.
>>>>
>>>> How can this be true? I mean, in call_psci_cpu_on() I can start those
>>>> CPUs in
>>>> the colored space, but they still use the boot_* pagetables
>>>
>>> Are you looking at the 64-bit or 32-bit code? For 64-bit, staging is not
>>> using boot_* pagetable anymore for secondary CPUs. Instead, they
>>> directly jump to the runtime page-tables.
>>>
>>>> and there I can't
>>>> easily link the new colored space, or, at least, I'm not succeding in
>>>> doing
>>>> that. What I tried at the moment is to link xen_xenmap in boot_second
>>>> after
>>>> switch_ttbr because of the problem I described above. But then secondary
>>>> CPUs never go online...
>>>
>>> It would be helpful if you share some code.
>>>
>>>>
>>>>> [...]
>>>>>
>>>>>>> ... as I wrote ealier your current approach seems to have a flaw.
>>>>>>> As you
>>>>>>> overwrite xen_bootmodule->{start, size}. setup_mm() will end up to add
>>>>>>> the old Xen region to the boot allocator. This is before any secondary
>>>>>>> CPUs are booted up.
>>>>>>>
>>>>>>> IOW, the allocator may provide some memory from the old Xen and
>>>>>>> nothing
>>>>>>> good will happen from that.
>>>>>>>
>>>>>>> The only way to solve it is to add another module. So the memory is
>>>>>>> skipped by setup_mm(). However see below.
>>>>>>>
>>>>>>>>
>>>>>>>> Yes that should be memory that in the end would not be needed so
>>>>>>>> it must
>>>>>>>> return to the boot-allocator (if that's what you mean). But how to do
>>>>>>>> that?
>>>>>>>
>>>>>>> You can't really discard the old temporary Xen. This may work today
>>>>>>> because we don't support CPU hotplug or suspend/resume. But there was
>>>>>>> some series on the ML to enable it and I don't see any reason why
>>>>>>> someone would not want to use the features with cache coloring.
>>>>>>>
>>>>>>> So the old temporary Xen would have to be kept around forever. This is
>>>>>>> up to 8MB of memory wasted.
>>>>>>>
>>>>>>> The right approach is to have the secondary CPU boot code
>>>>>>> (including the
>>>>>>> variables it is using) fitting in the same page (or possibly
>>>>>>> multiple so
>>>>>>> long this is small and physically contiguous). With that it doesn't
>>>>>>> matter where is the trampoline, it could stay at the old place, but we
>>>>>>> would only waste a few pages rather than up 8MB as it is today.
>>>>>>
>>>>>> So what are you suggesting is to create a new section in the linker
>>>>>> script
>>>>>> for the trampoline code and data,
>>>>>
>>>>> We already have a section for that in place (see .idmap.*) which happens
>>>>> to be at the beginning of Xen. Right now, the section is in text. Which
>>>>> is why it is read-only executable.
>>>>>
>>>>>> then in setup_mm() we would skip this
>>>>>> memory?
>>>>>
>>>>> We should not need this. Secondary boot CPUs should boot direclty on the
>>>>> colored Xen.
>>>>>
>>>>>> Am I following you correctly? Sorry those topics are a little out
>>>>>> of my preparation as you probably already guessed.
>>>>>
>>>>> No worries. I am happy to go in as much details as necessary. I can also
>>>>> attempt to write a patch if that helps. (unless someone else in the Arm
>>>>> maintainers want to give a try).
>>>>
>>>> Yes this would help. Thanks.
>>>
>>> I will try to have a look this evening. If I can't, it may have to wait
>>> a couple of weeks unless someone has time before hand.
>>
>> Series sent [1]. This is not fully complete for cache coloring. You will
>> need to modify the identity functions to take into account that the
>> identity map will be different.
>>
>> You will also want to check the new identity map area is still below
>> (see the check in prepare_boot_identity_mapping()).
>>
>> Cheers,
>>
>> [1] https://lore.kernel.org/xen-devel/20240116115509.77545-1-julien@xen.org/
> 
> Thank you very much for your help. I succeeded in applying your patches and
> reworking setup_pagetables() as we discussed previously. I dropped
> xen_colored_temp[], the temporary mapping at the end of setup_pagetables()
> and remove_llc_coloring_mappings().
> 
> Now, what to do with your patches? Will you push those before this series?

Michal reviewed the patches. I still want to give an opportunity for the 
other Arm maintainers to reply, so I plan to commit the patches early 
next week. You can then rebase your code on top.

If your v6 is ready earlier, you could apply the first 3 patches of the 
series (patch #4 is just for testing) and send your work. If you plan to 
do that, then please mention it in the cover letter (better if you can 
even provide a branch with everything applied).

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-09 10:33     ` Jan Beulich
  2024-01-10  0:37       ` Stefano Stabellini
@ 2024-01-18 14:27       ` Carlo Nonato
  2024-01-23 11:47         ` Julien Grall
  1 sibling, 1 reply; 90+ messages in thread
From: Carlo Nonato @ 2024-01-18 14:27 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, xen-devel

Hi Jan,

On Tue, Jan 9, 2024 at 11:33 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 09.01.2024 11:28, Jan Beulich wrote:
> > On 02.01.2024 10:51, Carlo Nonato wrote:
> >> v5:
> >> - Carlo Nonato as the new author
> >> - the colored allocator balances color usage for each domain and it searches
> >>   linearly only in the number of colors (FIXME removed)
> >
> > While this addresses earlier concerns, meanwhile NUMA work has also
> > been progressing. What's the plan of interaction of coloring with it?
>
> Thinking of interactions - what about static memory? Is coloring incompatible
> with that? If so, should the two features be excluded to both be used at the
> same time?

This was done in one of the earlier revisions. Then it was dropped because
we thought that it would have been better to have a binary that supported both
static memory and coloring. The only checks are done at runtime.

> Jan

Thanks.


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

* Re: [PATCH v5 09/13] xen: add cache coloring allocator for domains
  2024-01-18 14:27       ` Carlo Nonato
@ 2024-01-23 11:47         ` Julien Grall
  0 siblings, 0 replies; 90+ messages in thread
From: Julien Grall @ 2024-01-23 11:47 UTC (permalink / raw)
  To: Carlo Nonato, Jan Beulich
  Cc: Stefano Stabellini, Bertrand Marquis, Michal Orzel,
	Volodymyr Babchuk, Andrew Cooper, George Dunlap, Wei Liu,
	Marco Solieri, xen-devel

Hi Carlo,

On 18/01/2024 14:27, Carlo Nonato wrote:
> On Tue, Jan 9, 2024 at 11:33 AM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 09.01.2024 11:28, Jan Beulich wrote:
>>> On 02.01.2024 10:51, Carlo Nonato wrote:
>>>> v5:
>>>> - Carlo Nonato as the new author
>>>> - the colored allocator balances color usage for each domain and it searches
>>>>    linearly only in the number of colors (FIXME removed)
>>>
>>> While this addresses earlier concerns, meanwhile NUMA work has also
>>> been progressing. What's the plan of interaction of coloring with it?
>>
>> Thinking of interactions - what about static memory? Is coloring incompatible
>> with that? If so, should the two features be excluded to both be used at the
>> same time?
> 
> This was done in one of the earlier revisions. Then it was dropped because
> we thought that it would have been better to have a binary that supported both
> static memory and coloring. The only checks are done at runtime.

I actually prefer the runtime checks if they are not too complicated. 
This would allow distro to ship a generic Xen where user can play with 
various (incompatible) configuration without any rebuild.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 01/13] xen/common: add cache coloring common code
  2024-01-05 16:32       ` Carlo Nonato
@ 2024-01-25 18:26         ` Julien Grall
  0 siblings, 0 replies; 90+ messages in thread
From: Julien Grall @ 2024-01-25 18:26 UTC (permalink / raw)
  To: Carlo Nonato, Stefano Stabellini
  Cc: xen-devel, Andrew Cooper, George Dunlap, Jan Beulich, Wei Liu,
	Marco Solieri

Hi Carlo,

On 05/01/2024 16:32, Carlo Nonato wrote:
> Hi Stefano, Julien,
> 
> On Thu, Jan 4, 2024 at 10:43 PM Stefano Stabellini
> <sstabellini@kernel.org> wrote:
>>
>> On Thu, 4 Jan 2024, Julien Grall wrote:
>>> Hi,
>>>
>>> On 02/01/2024 09:51, Carlo Nonato wrote:
>>>> This commit adds the Last Level Cache (LLC) coloring common header, Kconfig
>>>> options and functions. Since this is an arch specific feature, actual
>>>> implementation is postponed to later patches and Kconfig options are placed
>>>> under xen/arch.
>>>>
>>>> LLC colors are a property of the domain, so the domain struct has to be
>>>> extended.
>>>>
>>>> Based on original work from: Luca Miccio <lucmiccio@gmail.com>
>>>>
>>>> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
>>>> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
>>>> ---
>>>> v5:
>>>> - used - instead of _ for filenames
>>>> - removed domain_create_llc_colored()
>>>> - removed stub functions
>>>> - coloring domain fields are now #ifdef protected
>>>> v4:
>>>> - Kconfig options moved to xen/arch
>>>> - removed range for CONFIG_NR_LLC_COLORS
>>>> - added "llc_coloring_enabled" global to later implement the boot-time
>>>>     switch
>>>> - added domain_create_llc_colored() to be able to pass colors
>>>> - added is_domain_llc_colored() macro
>>>> ---
>>>>    xen/arch/Kconfig               | 16 ++++++++++++
>>>>    xen/common/Kconfig             |  3 +++
>>>>    xen/common/domain.c            |  4 +++
>>>>    xen/common/keyhandler.c        |  4 +++
>>>>    xen/include/xen/llc-coloring.h | 46 ++++++++++++++++++++++++++++++++++
>>>>    xen/include/xen/sched.h        |  5 ++++
>>>>    6 files changed, 78 insertions(+)
>>>>    create mode 100644 xen/include/xen/llc-coloring.h
>>>>
>>>> diff --git a/xen/arch/Kconfig b/xen/arch/Kconfig
>>>> index 67ba38f32f..aad7e9da38 100644
>>>> --- a/xen/arch/Kconfig
>>>> +++ b/xen/arch/Kconfig
>>>> @@ -31,3 +31,19 @@ config NR_NUMA_NODES
>>>>        associated with multiple-nodes management. It is the upper bound of
>>>>        the number of NUMA nodes that the scheduler, memory allocation and
>>>>        other NUMA-aware components can handle.
>>>> +
>>>> +config LLC_COLORING
>>>> +   bool "Last Level Cache (LLC) coloring" if EXPERT
>>>
>>> While look at the rest of the series, I noticed that SUPPORT.md is not
>>> updated. Can this be done?
>>>
>>> I think the feature should be in experimental for now. We can decide to switch
>>> to tech preview before Xen 4.19 is out and the support is completed.
>>>
>>> Stefano, what do you think?
>>
>> That's reasonable
> 
> I would put it under "Resource management" features. Are you ok with it?

I think this wants to go under "## Memory Management". The section 
"Resource management" seems to be more related to the scheduler.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH v5 12/13] xen/arm: add Xen cache colors command line parameter
  2024-01-05 23:09     ` Stefano Stabellini
@ 2024-01-25 18:28       ` Julien Grall
  0 siblings, 0 replies; 90+ messages in thread
From: Julien Grall @ 2024-01-25 18:28 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Carlo Nonato, xen-devel, Luca Miccio, Andrew Cooper,
	George Dunlap, Jan Beulich, Wei Liu, Bertrand Marquis,
	Michal Orzel, Volodymyr Babchuk, Marco Solieri

Hi Stefano,

On 05/01/2024 23:09, Stefano Stabellini wrote:
> On Fri, 5 Jan 2024, Julien Grall wrote:
>> Hi,
>>
>> On 02/01/2024 09:51, Carlo Nonato wrote:
>>> From: Luca Miccio <lucmiccio@gmail.com>
>>>
>>> This commit adds a new command line parameter to configure Xen cache colors.
>>> These colors can be dumped with the cache coloring info debug-key.
>>>
>>> By default, Xen uses the first color.
>>> Benchmarking the VM interrupt response time provides an estimation of
>>> LLC usage by Xen's most latency-critical runtime task. Results on Arm
>>> Cortex-A53 on Xilinx Zynq UltraScale+ XCZU9EG show that one color, which
>>> reserves 64 KiB of L2, is enough to attain best responsiveness.
>>
>> Would you be able to share some numbers? This is quite helpful if in the
>> future we need to revise the default.
> 
> Here are the numbers for Xen 1 color vs Xen 2 colors.
> 
> We are measuring IRQ lantecy using a baremetal app (a unikernel) that
> has 0.5 us latency on native without interference.
> 
> Running the same application on Xen with 3 interference agents (3 other
> VMs that keep thrashing the cache):
> 
> - Xen 1 color latency:  3.1 us
> - Xen 2 color2 latency: 3.1 us

Thanks for sharing the numbers. Would it be possible to include them in 
the commit message?

Cheers,

-- 
Julien Grall


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

end of thread, other threads:[~2024-01-25 18:28 UTC | newest]

Thread overview: 90+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-02  9:51 [PATCH v5 00/13] Arm cache coloring Carlo Nonato
2024-01-02  9:51 ` [PATCH v5 01/13] xen/common: add cache coloring common code Carlo Nonato
2024-01-04 18:39   ` Julien Grall
2024-01-04 19:59   ` Julien Grall
2024-01-04 21:43     ` Stefano Stabellini
2024-01-05 16:32       ` Carlo Nonato
2024-01-25 18:26         ` Julien Grall
2024-01-08 16:53   ` Jan Beulich
2024-01-11 10:10     ` Carlo Nonato
2024-01-11 10:16       ` Jan Beulich
2024-01-02  9:51 ` [PATCH v5 02/13] xen/arm: add cache coloring initialization Carlo Nonato
2024-01-04 19:24   ` Julien Grall
2024-01-05 16:34     ` Carlo Nonato
2024-01-05 17:44       ` Julien Grall
2024-01-11 10:17       ` Carlo Nonato
2024-01-11 10:44         ` Julien Grall
2024-01-15 11:05           ` Carlo Nonato
2024-01-02  9:51 ` [PATCH v5 03/13] xen/arm: add Dom0 cache coloring support Carlo Nonato
2024-01-04 19:54   ` Julien Grall
2024-01-05 16:52     ` Carlo Nonato
2024-01-05 17:50       ` Julien Grall
2024-01-08 10:06         ` Carlo Nonato
2024-01-08 10:25           ` Julien Grall
2024-01-08 11:04             ` Carlo Nonato
2024-01-08 11:44               ` Julien Grall
2024-01-08 11:55                 ` Carlo Nonato
2024-01-02  9:51 ` [PATCH v5 04/13] xen: extend domctl interface for cache coloring Carlo Nonato
2024-01-05 17:26   ` Julien Grall
2024-01-08 10:27     ` Carlo Nonato
2024-01-08 11:00       ` Julien Grall
2024-01-08 11:19         ` Carlo Nonato
2024-01-08 11:35           ` Julien Grall
2024-01-08 15:18             ` Carlo Nonato
2024-01-08 15:31               ` Julien Grall
2024-01-08 16:31                 ` Carlo Nonato
2024-01-08 16:40                   ` Jan Beulich
2024-01-08 16:50                     ` Carlo Nonato
2024-01-08 21:21                       ` Stefano Stabellini
2024-01-09  9:34                         ` Jan Beulich
2024-01-08 16:49                   ` Julien Grall
2024-01-08  8:43   ` Jan Beulich
2024-01-08 11:22     ` Carlo Nonato
2024-01-02  9:51 ` [PATCH v5 05/13] tools: add support for cache coloring configuration Carlo Nonato
2024-01-02  9:51 ` [PATCH v5 06/13] xen/arm: add support for cache coloring configuration via device-tree Carlo Nonato
2024-01-05 17:38   ` Julien Grall
2024-01-08 11:26     ` Carlo Nonato
2024-01-02  9:51 ` [PATCH v5 07/13] xen/page_alloc: introduce init_free_page_fields() helper Carlo Nonato
2024-01-09 10:36   ` Jan Beulich
2024-01-12  9:43     ` Carlo Nonato
2024-01-02  9:51 ` [PATCH v5 08/13] xen/page_alloc: introduce preserved page flags macro Carlo Nonato
2024-01-08 17:08   ` Jan Beulich
2024-01-12 10:01     ` Carlo Nonato
2024-01-12 10:22       ` Jan Beulich
2024-01-02  9:51 ` [PATCH v5 09/13] xen: add cache coloring allocator for domains Carlo Nonato
2024-01-09 10:28   ` Jan Beulich
2024-01-09 10:33     ` Jan Beulich
2024-01-10  0:37       ` Stefano Stabellini
2024-01-18 14:27       ` Carlo Nonato
2024-01-23 11:47         ` Julien Grall
2024-01-10  0:46     ` Stefano Stabellini
2024-01-10  9:10       ` Jan Beulich
2024-01-11 23:25         ` Stefano Stabellini
2024-01-15 11:07     ` Carlo Nonato
2024-01-02  9:51 ` [PATCH v5 10/13] xen/arm: use domain memory to allocate p2m page tables Carlo Nonato
2024-01-05 17:54   ` Julien Grall
2024-01-02  9:51 ` [PATCH v5 11/13] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START" Carlo Nonato
2024-01-05 18:20   ` Julien Grall
2024-01-08 11:28     ` Carlo Nonato
2024-01-02  9:51 ` [PATCH v5 12/13] xen/arm: add Xen cache colors command line parameter Carlo Nonato
2024-01-05 18:00   ` Julien Grall
2024-01-05 23:09     ` Stefano Stabellini
2024-01-25 18:28       ` Julien Grall
2024-01-02  9:51 ` [PATCH v5 13/13] xen/arm: add cache coloring support for Xen Carlo Nonato
2024-01-05 19:12   ` Julien Grall
2024-01-13 17:07     ` Carlo Nonato
2024-01-14 19:22       ` Julien Grall
2024-01-15 10:11         ` Carlo Nonato
2024-01-15 11:18           ` Julien Grall
2024-01-15 15:43             ` Carlo Nonato
2024-01-15 16:16               ` Julien Grall
2024-01-16  9:00                 ` Carlo Nonato
2024-01-16 11:58                 ` Julien Grall
2024-01-17 17:38                   ` Carlo Nonato
2024-01-18  9:29                     ` Julien Grall
2024-01-03 13:34 ` [PATCH v5 00/13] Arm cache coloring Michal Orzel
2024-01-04  0:05   ` Stefano Stabellini
2024-01-04  1:55     ` Stefano Stabellini
2024-01-04  9:37       ` Carlo Nonato
2024-01-04 10:19         ` Michal Orzel
2024-01-04 17:56           ` Stefano Stabellini

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.