All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] Arm cache coloring
@ 2022-08-26 12:50 Carlo Nonato
  2022-08-26 12:51 ` [PATCH 01/12] xen/arm: add cache coloring initialization Carlo Nonato
                   ` (14 more replies)
  0 siblings, 15 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:50 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato

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 solution has been tested in several scenarios, including Xilinx Zynq
MPSoCs.

Overview of implementation and commits structure
------------------------------------------------

- [1-3] Coloring initialization, cache layout auto-probing and coloring
  data for domains are added.
- [4-5] xl and Device Tree support for coloring is addedd.
- [6-7] A new page allocator for domain memory that implement the cache
  coloring mechanism is introduced.
- [8-12] Coloring support is added for Xen .text region.

Changes in v2
-------------

Lot of things changed between the two versions, mainly I tried to follow
all the comments left by the maintainers after the previous version review.
Here is a brief list of the major points (even if, imho, it's easier to
repeat all the review process):

 - One of the easiest change to spot is the reduced number of patches in the
   series. A lot of problems of bad splitting of commits where present before
   (documentation only in last commits, functionalities firstly introduced
   and later used in other commits, etc).
 - Definition of LLC (Last Level Cache) as the place where coloring applies
   should be more consistent throughout all the series (documentation and
   cache layout auto-probing code).
 - Kconfig option to let configure the maximum number of cache colors.
 - Only one kind of syntax to specify color configurations.
 - Only arrays to store colors (no more need for bitmaps).
 - No more limitations on the max number of colors (previously, because of
   a static assert failure, it was limited to 64).
 - Kconfig option to let configure the buddy allocator reserved size.
 - Removed the duplicated version of setup_pagetables.
 - No more need to expose vm_alloc function as non-static.

Open points and possible problems
---------------------------------

- The way xl passes user space memory to Xen it's adapted from various 
  points of the xl code itself (e.g. xc_domain_node_setaffinity) and it
  works, but it really needs attention from expert maintainers since 
  I'm not completely sure this is the correct way of doing things.
- We still need to bring back the relocation feature (part of) in order
  to move Xen memory to a colored space where the hypervisor could be
  isolated from VMs interference (see the revert commit #10 and the
  get_xen_paddr function in #12).
- Revert commits #8 and #9 are needed because coloring has the command
  line parsing as a prerequisite for its initialization and
  setup_pagetables must be called after it in order to color the Xen
  mapping. The DTB mapping is then added to the boot page tables instead
  of the Xen ones. Probably the way this is done is a bit simplistic.
  Looking forward for comments on the subject.
- A temporary mapping of the old Xen code (old here means non-colored)
  is used to reach variables in the old physical space so that secondary
  CPUs can boot. There were some comments in the previous version on that
  because the mapping is available for all the CPUs while only CPU0 is
  the one supposed to access it. I'm not sure how to temporarily mapping
  things only for the master CPU.
- A lot of #ifdef for cache coloring are introduced because I prefer to
  define functions only if they are actually needed. Let me know if you
  prefer a different approach.
- Julien posted an RFC to address a problem with the switch_ttbr function.
  For the moment I haven't considered it since it's still a work in progress.

Acknowledgements
----------------

This work is sponsored by Xilinx Inc., and supported by University of
Modena and Reggio Emilia and Minerva Systems.


Carlo Nonato (10):
  xen/arm: add cache coloring initialization
  xen/arm: add cache coloring initialization for domains
  xen/arm: dump cache colors in domain info debug-key
  tools/xl: add support for cache coloring configuration
  xen/arm: add support for cache coloring configuration via device-tree
  xen/common: add cache coloring allocator for domains
  xen/common: add colored heap info debug-key
  Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START"
  xen/arm: add Xen cache colors command line parameter
  xen/arm: add cache coloring support for Xen

Luca Miccio (2):
  Revert "xen/arm: setup: Add Xen as boot module before printing all
    boot modules"
  Revert "xen/arm: mm: Initialize page-tables earlier"

 docs/man/xl.cfg.5.pod.in              |  10 +
 docs/misc/arm/cache-coloring.rst      | 201 ++++++++++++++
 docs/misc/arm/device-tree/booting.txt |   4 +
 docs/misc/xen-command-line.pandoc     |  45 ++++
 tools/libs/light/libxl_create.c       |  12 +
 tools/libs/light/libxl_types.idl      |   1 +
 tools/xl/xl_parse.c                   |  52 +++-
 xen/arch/arm/Kconfig                  |  28 ++
 xen/arch/arm/Makefile                 |   1 +
 xen/arch/arm/alternative.c            |   5 +
 xen/arch/arm/coloring.c               | 367 ++++++++++++++++++++++++++
 xen/arch/arm/domain.c                 |  14 +
 xen/arch/arm/domain_build.c           |  22 +-
 xen/arch/arm/include/asm/coloring.h   |  60 +++++
 xen/arch/arm/include/asm/config.h     |   4 +-
 xen/arch/arm/include/asm/domain.h     |   4 +
 xen/arch/arm/include/asm/mm.h         |  22 +-
 xen/arch/arm/include/asm/processor.h  |  16 ++
 xen/arch/arm/mm.c                     | 144 ++++++++--
 xen/arch/arm/psci.c                   |   4 +-
 xen/arch/arm/setup.c                  |  90 ++++++-
 xen/arch/arm/smpboot.c                |   3 +-
 xen/arch/arm/xen.lds.S                |   2 +-
 xen/common/page_alloc.c               | 237 ++++++++++++++++-
 xen/common/vmap.c                     |  25 ++
 xen/include/public/arch-arm.h         |   8 +
 xen/include/xen/vmap.h                |   4 +
 27 files changed, 1333 insertions(+), 52 deletions(-)
 create mode 100644 docs/misc/arm/cache-coloring.rst
 create mode 100644 xen/arch/arm/coloring.c
 create mode 100644 xen/arch/arm/include/asm/coloring.h

-- 
2.34.1



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

* [PATCH 01/12] xen/arm: add cache coloring initialization
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-09-26  6:20   ` Wei Chen
  2022-10-21 17:14   ` Julien Grall
  2022-08-26 12:51 ` [PATCH 02/12] xen/arm: add cache coloring initialization for domains Carlo Nonato
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

This commit adds the cache coloring support initialization, Kconfig options,
command line parameters and the initial documentation.
The initialization consists of an auto probing of the cache layout
necessary to retrieve the LLC way size which is used to compute the
number of available colors. The Dom0 colors are then initialized with default
colors (all available ones) if not provided from the command line, and
they are checked for bad configuration.

It also adds a debug-key to dump general cache coloring info.
This includes LLC way size, total available colors and the mask used to
extract colors from physical addresses.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 docs/misc/arm/cache-coloring.rst     | 112 ++++++++++++++
 docs/misc/xen-command-line.pandoc    |  22 +++
 xen/arch/arm/Kconfig                 |  16 ++
 xen/arch/arm/Makefile                |   1 +
 xen/arch/arm/coloring.c              | 222 +++++++++++++++++++++++++++
 xen/arch/arm/include/asm/coloring.h  |  31 ++++
 xen/arch/arm/include/asm/processor.h |  16 ++
 xen/arch/arm/setup.c                 |   8 +
 8 files changed, 428 insertions(+)
 create mode 100644 docs/misc/arm/cache-coloring.rst
 create mode 100644 xen/arch/arm/coloring.c
 create mode 100644 xen/arch/arm/include/asm/coloring.h

diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
new file mode 100644
index 0000000000..c7adcb0f1f
--- /dev/null
+++ b/docs/misc/arm/cache-coloring.rst
@@ -0,0 +1,112 @@
+Xen cache coloring user guide
+=============================
+
+The cache coloring support in Xen allows to reserve Last Level Cache (LLC)
+partition for Dom0, DomUs and Xen itself. Currently only ARM64 is supported.
+
+In order to enable and use it, few steps are needed.
+
+- Enable cache coloring in Xen configuration file.
+
+        CONFIG_CACHE_COLORING=y
+- If needed, change the maximum number of colors in Xen configuration file
+  (refer to menuconfig help for value meaning and when it should be changed).
+
+        CONFIG_MAX_CACHE_COLORS=<n>
+- Assign colors to Dom0 using the `Color selection format`_ (see
+  `Coloring parameters`_ for more documentation pointers).
+
+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.
+
+.. raw:: html
+
+    <pre>
+                            Region j            Region j+1
+                .....................   ............
+                .                     . .
+                .                       .
+            _ _ _______________ _ _____________________ _ _
+                |     |     |     |     |     |     |
+                | c_0 | c_1 |     | c_n | c_0 | c_1 |
+           _ _ _|_____|_____|_ _ _|_____|_____|_____|_ _ _
+                    :                       :
+                    :                       :...         ... .
+                    :                            color 0
+                    :...........................         ... .
+                                                :
+          . . ..................................:
+    </pre>
+
+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
+a 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 to the user to overcome failing situations
+or for debugging/testing purposes. See `Coloring parameters`_ section for more
+information on that.
+
+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]                               |
++---------------------+-----------------------------------+
+
+Coloring parameters
+*******************
+
+LLC way size (as previously discussed) and Dom0 colors can be set using the
+appropriate command line parameters. See the relevant documentation in
+"docs/misc/xen-command-line.pandoc".
\ No newline at end of file
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 9a79385a37..910ebeb2eb 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -889,6 +889,14 @@ Controls for the dom0 IOMMU setup.
 
     Incorrect use of this option may result in a malfunctioning system.
 
+### dom0-colors (arm64)
+> `= List of [ <integer> | <integer>-<integer> ]`
+
+> Default: `All available colors`
+
+Specify dom0 color configuration. If the parameter is not set, all available
+colors are chosen and the user is warned on Xen's serial console.
+
 ### dom0_ioports_disable (x86)
 > `= List of <hex>-<hex>`
 
@@ -1631,6 +1639,20 @@ 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-way-size (arm64)
+> `= <size>`
+
+> Default: `Obtained from the hardware`
+
+Specify the way size of the Last Level Cache. This parameter is only useful with
+cache coloring support enabled. It is an optional, expert-only parameter and it
+is used to calculate the number of available 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.
+
 ### loglvl
 > `= <level>[/<rate-limited level>]` where level is `none | error | warning | info | debug | all`
 
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 33e004d702..8acff9682c 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -131,6 +131,22 @@ config ARM64_BTI
 	  Branch Target Identification support.
 	  This feature is not supported in Xen.
 
+config CACHE_COLORING
+	bool "Last Level Cache (LLC) coloring" if EXPERT
+	default n
+	depends on ARM_64
+
+config MAX_CACHE_COLORS
+	int "Maximum number of cache colors"
+	default 128
+	range 0 65536
+	depends on CACHE_COLORING
+	help
+	  This config value is an upper bound for the actual number of cache colors
+	  supported by the architecture. Xen preallocates this amount of cache
+	  colors at boot. Note that if, at any time, a color configuration with more
+	  colors than the maximum will be employed an error will be produced.
+
 config TEE
 	bool "Enable TEE mediators support (UNSUPPORTED)" if UNSUPPORTED
 	default n
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 4d076b278b..12940ba761 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_SBSA_VUART_CONSOLE) += vpl011.o
 obj-y += vsmc.o
 obj-y += vpsci.o
 obj-y += vuart.o
+obj-$(CONFIG_CACHE_COLORING) += coloring.o
 
 extra-y += xen.lds
 
diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
new file mode 100644
index 0000000000..c010ebc01b
--- /dev/null
+++ b/xen/arch/arm/coloring.c
@@ -0,0 +1,222 @@
+/*
+ * xen/arch/arm/coloring.c
+ *
+ * Coloring support for ARM
+ *
+ * Copyright (C) 2019 Xilinx Inc.
+ *
+ * Authors:
+ *    Luca Miccio <lucmiccio@gmail.com>
+ *    Carlo Nonato <carlo.nonato@minervasys.tech>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <xen/errno.h>
+#include <xen/keyhandler.h>
+#include <xen/param.h>
+#include <xen/types.h>
+
+#include <asm/coloring.h>
+#include <asm/processor.h>
+#include <asm/sysregs.h>
+
+/* Size of a LLC way */
+static unsigned int llc_way_size;
+/* Number of colors available in the LLC */
+static unsigned int max_colors;
+/* Mask to retrieve coloring relevant bits */
+static uint64_t addr_col_mask;
+
+#define addr_to_color(addr) (((addr) & addr_col_mask) >> PAGE_SHIFT)
+#define addr_set_color(addr, color) (((addr) & ~addr_col_mask) \
+                                     | ((color) << PAGE_SHIFT))
+
+static unsigned int dom0_colors[CONFIG_MAX_CACHE_COLORS];
+static unsigned int 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;
+
+    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 ||
+                 *num_colors + end - start >= CONFIG_MAX_CACHE_COLORS )
+                return -EINVAL;
+            for ( color = start; color <= end; color++ )
+                colors[(*num_colors)++] = color;
+        }
+        else
+            s++;
+    }
+
+    return *s ? -EINVAL : 0;
+}
+
+size_param("llc-way-size", llc_way_size);
+
+static int __init parse_dom0_colors(const char *s)
+{
+    return parse_color_config(s, dom0_colors, &dom0_num_colors);
+}
+custom_param("dom0-colors", parse_dom0_colors);
+
+/* Return the LLC way size by probing the hardware */
+static unsigned int 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 bool check_colors(unsigned int *colors, unsigned int num_colors)
+{
+    int i;
+
+    if ( num_colors > max_colors )
+        return false;
+
+    for ( i = 0; i < num_colors; i++ )
+        if ( colors[i] >= max_colors )
+            return false;
+
+    return true;
+}
+
+static unsigned int set_default_domain_colors(unsigned int *colors)
+{
+    unsigned int i;
+
+    if ( !colors )
+        return 0;
+
+    for ( i = 0; i < max_colors; i++ )
+        colors[i] = i;
+    return max_colors;
+}
+
+static void dump_coloring_info(unsigned char key)
+{
+    printk("'%c' pressed -> dumping coloring general info\n", key);
+    printk("LLC way size: %u KiB\n", llc_way_size >> 10);
+    printk("Number of LLC colors supported: %u\n", max_colors);
+    printk("Address color mask: 0x%lx\n", addr_col_mask);
+}
+
+bool __init 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;
+    }
+
+    max_colors = llc_way_size / PAGE_SIZE;
+    /* The maximum number of colors must be a power of 2 in order to correctly
+       map colors to bits of an address. */
+    ASSERT((max_colors & (max_colors - 1)) == 0);
+    addr_col_mask = (max_colors - 1) << PAGE_SHIFT;
+
+    if ( !dom0_num_colors )
+    {
+        printk(XENLOG_WARNING
+               "Dom0 color config not found. Using default (all colors)\n");
+        dom0_num_colors = set_default_domain_colors(dom0_colors);
+    }
+
+    if ( !check_colors(dom0_colors, dom0_num_colors) )
+    {
+        printk(XENLOG_ERR "Bad color config for Dom0\n");
+        return false;
+    }
+
+    register_keyhandler('K', dump_coloring_info, "dump coloring info", 1);
+
+    return true;
+}
+
+/*
+ * 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/coloring.h b/xen/arch/arm/include/asm/coloring.h
new file mode 100644
index 0000000000..dd7eff5f07
--- /dev/null
+++ b/xen/arch/arm/include/asm/coloring.h
@@ -0,0 +1,31 @@
+/*
+ * xen/arm/include/asm/coloring.h
+ *
+ * Coloring support for ARM
+ *
+ * Copyright (C) 2019 Xilinx Inc.
+ *
+ * Authors:
+ *    Luca Miccio <lucmiccio@gmail.com>
+ *    Carlo Nonato <carlo.nonato@minervasys.tech>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ARM_COLORING_H__
+#define __ASM_ARM_COLORING_H__
+
+#include <xen/init.h>
+
+bool __init coloring_init(void);
+
+#endif /* !__ASM_ARM_COLORING_H__ */
diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h
index 1dd81d7d52..85ff0caf1e 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            0x7
+#define CCSIDR_NUMSETS_SHIFT            13
+#define CCSIDR_NUMSETS_MASK             0x3FFF
+#define CCSIDR_NUMSETS_SHIFT_FEAT_CCIDX 32
+#define CCSIDR_NUMSETS_MASK_FEAT_CCIDX  0xFFFFFF
+
+/* CCSELR Cache Size Selection Register */
+#define CCSELR_LEVEL_MASK  0x7
+#define CCSELR_LEVEL_SHIFT 1
+
+/* CLIDR Cache Level ID Register */
+#define CLIDR_CTYPEn_SHIFT(n) (3 * (n - 1))
+#define CLIDR_CTYPEn_MASK     0x7
+#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/setup.c b/xen/arch/arm/setup.c
index 500307edc0..c02f21c0e6 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -53,6 +53,9 @@
 #include <asm/setup.h>
 #include <xsm/xsm.h>
 #include <asm/acpi.h>
+#ifdef CONFIG_CACHE_COLORING
+#include <asm/coloring.h>
+#endif
 
 struct bootinfo __initdata bootinfo;
 
@@ -930,6 +933,11 @@ void __init start_xen(unsigned long boot_phys_offset,
     printk("Command line: %s\n", cmdline);
     cmdline_parse(cmdline);
 
+#ifdef CONFIG_CACHE_COLORING
+    if ( !coloring_init() )
+        panic("Xen Coloring support: setup failed\n");
+#endif
+
     setup_mm();
 
     /* Parse the ACPI tables for possible boot-time configuration */
-- 
2.34.1



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

* [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
  2022-08-26 12:51 ` [PATCH 01/12] xen/arm: add cache coloring initialization Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-09-26  6:39   ` Wei Chen
                     ` (2 more replies)
  2022-08-26 12:51 ` [PATCH 03/12] xen/arm: dump cache colors in domain info debug-key Carlo Nonato
                   ` (12 subsequent siblings)
  14 siblings, 3 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

This commit adds array pointers to domains as well as to the hypercall
and configuration structure employed in domain creation. The latter is used
both by the toolstack and by Xen itself to pass configuration data to the
domain creation function, so the XEN_GUEST_HANDLE macro must be adopted to be
able to access guest memory in the first case. This implies special care for
the copy of the configuration data into the domain data, meaning that a
discrimination variable for the two possible code paths (coming from Xen or
from the toolstack) is needed.

The initialization and free functions for colored domains are also added.
The former is responsible for allocating and populating the color array
of the domain and it also checks for configuration issues. One of those
issues is enabling both coloring and directmap for the domain because they
contradicts one another. Since that, Dom0 must not be created with the
directmap flag.
The latter instead frees allocated memory.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 docs/misc/arm/cache-coloring.rst    |  7 ++--
 xen/arch/arm/coloring.c             | 56 +++++++++++++++++++++++++++++
 xen/arch/arm/domain.c               | 11 ++++++
 xen/arch/arm/domain_build.c         | 13 +++++--
 xen/arch/arm/include/asm/coloring.h |  7 ++++
 xen/arch/arm/include/asm/domain.h   |  4 +++
 xen/include/public/arch-arm.h       |  8 +++++
 7 files changed, 102 insertions(+), 4 deletions(-)

diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
index c7adcb0f1f..345d97cb56 100644
--- a/docs/misc/arm/cache-coloring.rst
+++ b/docs/misc/arm/cache-coloring.rst
@@ -13,7 +13,7 @@ In order to enable and use it, few steps are needed.
   (refer to menuconfig help for value meaning and when it should be changed).
 
         CONFIG_MAX_CACHE_COLORS=<n>
-- Assign colors to Dom0 using the `Color selection format`_ (see
+- Assign colors to domains using the `Color selection format`_ (see
   `Coloring parameters`_ for more documentation pointers).
 
 Background
@@ -109,4 +109,7 @@ Coloring parameters
 
 LLC way size (as previously discussed) and Dom0 colors can be set using the
 appropriate command line parameters. See the relevant documentation in
-"docs/misc/xen-command-line.pandoc".
\ No newline at end of file
+"docs/misc/xen-command-line.pandoc".
+
+Note that if no color configuration is provided for domains, they fallback to
+the default one, which corresponds simply to all available colors.
\ No newline at end of file
diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
index c010ebc01b..2b37cda067 100644
--- a/xen/arch/arm/coloring.c
+++ b/xen/arch/arm/coloring.c
@@ -22,6 +22,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <xen/errno.h>
+#include <xen/guest_access.h>
 #include <xen/keyhandler.h>
 #include <xen/param.h>
 #include <xen/types.h>
@@ -211,6 +212,61 @@ bool __init coloring_init(void)
     return true;
 }
 
+int domain_coloring_init(struct domain *d,
+                         const struct xen_arch_domainconfig *config)
+{
+    if ( is_domain_direct_mapped(d) )
+    {
+        printk(XENLOG_ERR
+               "Can't enable coloring and directmap at the same time for %pd\n",
+               d);
+        return -EINVAL;
+    }
+
+    if ( is_hardware_domain(d) )
+    {
+        d->arch.colors = dom0_colors;
+        d->arch.num_colors = dom0_num_colors;
+    }
+    else if ( config->num_colors == 0 )
+    {
+        printk(XENLOG_WARNING
+               "Color config not found for %pd. Using default\n", d);
+        d->arch.colors = xzalloc_array(unsigned int, max_colors);
+        d->arch.num_colors = set_default_domain_colors(d->arch.colors);
+    }
+    else
+    {
+        d->arch.colors = xzalloc_array(unsigned int, config->num_colors);
+        d->arch.num_colors = config->num_colors;
+        if ( config->from_guest )
+            copy_from_guest(d->arch.colors, config->colors, config->num_colors);
+        else
+            memcpy(d->arch.colors, config->colors.p,
+                   sizeof(unsigned int) * config->num_colors);
+    }
+
+    if ( !d->arch.colors )
+    {
+        printk(XENLOG_ERR "Colors allocation failed for %pd\n", d);
+        return -ENOMEM;
+    }
+
+    if ( !check_colors(d->arch.colors, d->arch.num_colors) )
+    {
+        printk(XENLOG_ERR "Bad color config for %pd\n", d);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+void domain_coloring_free(struct domain *d)
+{
+    if ( !is_hardware_domain(d) )
+        xfree(d->arch.colors);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 2d6253181a..c6fa8adc99 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -23,6 +23,9 @@
 #include <xen/wait.h>
 
 #include <asm/alternative.h>
+#ifdef CONFIG_CACHE_COLORING
+#include <asm/coloring.h>
+#endif
 #include <asm/cpuerrata.h>
 #include <asm/cpufeature.h>
 #include <asm/current.h>
@@ -712,6 +715,11 @@ int arch_domain_create(struct domain *d,
     ioreq_domain_init(d);
 #endif
 
+#ifdef CONFIG_CACHE_COLORING
+    if ( (rc = domain_coloring_init(d, &config->arch)) )
+        goto fail;
+#endif
+
     /* p2m_init relies on some value initialized by the IOMMU subsystem */
     if ( (rc = iommu_domain_init(d, config->iommu_opts)) != 0 )
         goto fail;
@@ -807,6 +815,9 @@ void arch_domain_destroy(struct domain *d)
                        get_order_from_bytes(d->arch.efi_acpi_len));
 #endif
     domain_io_free(d);
+#ifdef CONFIG_CACHE_COLORING
+    domain_coloring_free(d);
+#endif
 }
 
 void arch_domain_shutdown(struct domain *d)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 3fd1186b53..4d4cb692fc 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -33,6 +33,12 @@
 #include <xen/grant_table.h>
 #include <xen/serial.h>
 
+#ifdef CONFIG_CACHE_COLORING
+#define XEN_DOM0_CREATE_FLAGS CDF_privileged
+#else
+#define XEN_DOM0_CREATE_FLAGS CDF_privileged | CDF_directmap
+#endif
+
 static unsigned int __initdata opt_dom0_max_vcpus;
 integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
 
@@ -3399,7 +3405,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_ENABLED(CONFIG_CACHE_COLORING) )
+        allocate_memory(d, &kinfo);
+    else
+        allocate_memory_11(d, &kinfo);
     find_gnttab_region(d, &kinfo);
 
     /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
@@ -3455,7 +3464,7 @@ void __init create_dom0(void)
     if ( iommu_enabled )
         dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu;
 
-    dom0 = domain_create(0, &dom0_cfg, CDF_privileged | CDF_directmap);
+    dom0 = domain_create(0, &dom0_cfg, XEN_DOM0_CREATE_FLAGS);
     if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
         panic("Error creating domain 0\n");
 
diff --git a/xen/arch/arm/include/asm/coloring.h b/xen/arch/arm/include/asm/coloring.h
index dd7eff5f07..60c8b1f079 100644
--- a/xen/arch/arm/include/asm/coloring.h
+++ b/xen/arch/arm/include/asm/coloring.h
@@ -25,7 +25,14 @@
 #define __ASM_ARM_COLORING_H__
 
 #include <xen/init.h>
+#include <xen/sched.h>
+
+#include <public/arch-arm.h>
 
 bool __init coloring_init(void);
 
+int domain_coloring_init(struct domain *d,
+                         const struct xen_arch_domainconfig *config);
+void domain_coloring_free(struct domain *d);
+
 #endif /* !__ASM_ARM_COLORING_H__ */
diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
index 26a8348eed..291f7c375d 100644
--- a/xen/arch/arm/include/asm/domain.h
+++ b/xen/arch/arm/include/asm/domain.h
@@ -58,6 +58,10 @@ struct arch_domain
 #ifdef CONFIG_ARM_64
     enum domain_type type;
 #endif
+#ifdef CONFIG_CACHE_COLORING
+    unsigned int *colors;
+    unsigned int num_colors;
+#endif
 
     /* Virtual MMU */
     struct p2m_domain p2m;
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index c8b6058d3a..adf843a7a1 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -314,6 +314,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
 #define XEN_DOMCTL_CONFIG_TEE_NONE      0
 #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
 
+__DEFINE_XEN_GUEST_HANDLE(color_t, unsigned int);
+
 struct xen_arch_domainconfig {
     /* IN/OUT */
     uint8_t gic_version;
@@ -335,6 +337,12 @@ struct xen_arch_domainconfig {
      *
      */
     uint32_t clock_frequency;
+    /* IN */
+    uint8_t from_guest;
+    /* IN */
+    uint16_t num_colors;
+    /* IN */
+    XEN_GUEST_HANDLE(color_t) colors;
 };
 #endif /* __XEN__ || __XEN_TOOLS__ */
 
-- 
2.34.1



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

* [PATCH 03/12] xen/arm: dump cache colors in domain info debug-key
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
  2022-08-26 12:51 ` [PATCH 01/12] xen/arm: add cache coloring initialization Carlo Nonato
  2022-08-26 12:51 ` [PATCH 02/12] xen/arm: add cache coloring initialization for domains Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-08-26 12:51 ` [PATCH 04/12] tools/xl: add support for cache coloring configuration Carlo Nonato
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

This commit adds cache colors to the information dumped with the domain info
debug-key.

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

diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
index 2b37cda067..40a07617cc 100644
--- a/xen/arch/arm/coloring.c
+++ b/xen/arch/arm/coloring.c
@@ -171,6 +171,16 @@ static unsigned int set_default_domain_colors(unsigned int *colors)
     return max_colors;
 }
 
+static void print_colors(unsigned int *colors, unsigned int num_colors)
+{
+    unsigned int i;
+
+    printk("[ ");
+    for ( i = 0; i < num_colors; i++ )
+        printk("%u ", colors[i]);
+    printk("]\n");
+}
+
 static void dump_coloring_info(unsigned char key)
 {
     printk("'%c' pressed -> dumping coloring general info\n", key);
@@ -267,6 +277,12 @@ void domain_coloring_free(struct domain *d)
         xfree(d->arch.colors);
 }
 
+void domain_dump_coloring_info(struct domain *d)
+{
+    printk("Domain %pd has %u colors: ", d, d->arch.num_colors);
+    print_colors(d->arch.colors, d->arch.num_colors);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index c6fa8adc99..bca418e374 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -1087,6 +1087,9 @@ int domain_relinquish_resources(struct domain *d)
 void arch_dump_domain_info(struct domain *d)
 {
     p2m_dump_info(d);
+#ifdef CONFIG_CACHE_COLORING
+    domain_dump_coloring_info(d);
+#endif
 }
 
 
diff --git a/xen/arch/arm/include/asm/coloring.h b/xen/arch/arm/include/asm/coloring.h
index 60c8b1f079..967031ae04 100644
--- a/xen/arch/arm/include/asm/coloring.h
+++ b/xen/arch/arm/include/asm/coloring.h
@@ -34,5 +34,6 @@ bool __init coloring_init(void);
 int domain_coloring_init(struct domain *d,
                          const struct xen_arch_domainconfig *config);
 void domain_coloring_free(struct domain *d);
+void domain_dump_coloring_info(struct domain *d);
 
 #endif /* !__ASM_ARM_COLORING_H__ */
-- 
2.34.1



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

* [PATCH 04/12] tools/xl: add support for cache coloring configuration
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (2 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 03/12] xen/arm: dump cache colors in domain info debug-key Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-10-21 18:09   ` Julien Grall
  2022-08-26 12:51 ` [PATCH 05/12] xen/arm: add support for cache coloring configuration via device-tree Carlo Nonato
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

Add a new "colors" parameter that defines the 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.
Also documentation is added.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 docs/man/xl.cfg.5.pod.in         | 10 ++++++
 tools/libs/light/libxl_create.c  | 12 ++++++++
 tools/libs/light/libxl_types.idl |  1 +
 tools/xl/xl_parse.c              | 52 ++++++++++++++++++++++++++++++--
 4 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index b2901e04cf..5f53cec8bf 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -2880,6 +2880,16 @@ Currently, only the "sbsa_uart" model is supported for ARM.
 
 =back
 
+=over 4
+
+=item B<colors=[ "COLORS_RANGE", "COLORS_RANGE", ...]>
+
+Specify the LLC color configuration for the guest. B<COLORS_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/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c
index b9dd2deedf..94c511912c 100644
--- a/tools/libs/light/libxl_create.c
+++ b/tools/libs/light/libxl_create.c
@@ -615,6 +615,7 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
     struct xs_permissions rwperm[1];
     struct xs_permissions noperm[1];
     xs_transaction_t t = 0;
+    DECLARE_HYPERCALL_BUFFER(unsigned int, colors);
 
     /* convenience aliases */
     libxl_domain_create_info *info = &d_config->c_info;
@@ -676,6 +677,16 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
             goto out;
         }
 
+        if (d_config->b_info.num_colors) {
+            size_t bytes = sizeof(unsigned int) * d_config->b_info.num_colors;
+            colors = xc_hypercall_buffer_alloc(ctx->xch, colors, bytes);
+            memcpy(colors, d_config->b_info.colors, bytes);
+            set_xen_guest_handle(create.arch.colors, colors);
+            create.arch.num_colors = d_config->b_info.num_colors;
+            create.arch.from_guest = 1;
+            LOG(DEBUG, "Setup %u domain colors", d_config->b_info.num_colors);
+        }
+
         for (;;) {
             uint32_t local_domid;
             bool recent;
@@ -922,6 +933,7 @@ retry_transaction:
     rc = 0;
  out:
     if (t) xs_transaction_end(ctx->xsh, t, 1);
+    if (colors) xc_hypercall_buffer_free(ctx->xch, colors);
     return rc;
 }
 
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index d634f304cd..642173af1a 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -557,6 +557,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")),
+    ("colors",           Array(uint32, "num_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 1b5381cef0..7f8fbbfb4c 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -1220,8 +1220,9 @@ 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;
-    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian, num_mca_caps;
+                   *mca_caps, *colors;
+    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian, num_mca_caps,
+        num_colors;
     int pci_power_mgmt = 0;
     int pci_msitranslate = 0;
     int pci_permissive = 0;
@@ -1370,6 +1371,53 @@ 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, "colors", &colors, &num_colors, 0)) {
+        int k, p, cur_index;
+
+        b_info->num_colors = 0;
+        /* Get number of colors based on ranges */
+        for (i = 0; i < num_colors; i++) {
+            uint32_t start = 0, end = 0;
+
+            buf = xlu_cfg_get_listitem(colors, i);
+            if (!buf) {
+                fprintf(stderr,
+                    "xl: Unable to get element %d in colors range list\n", i);
+                exit(1);
+            }
+
+            if (sscanf(buf, "%u-%u", &start, &end) != 2) {
+                if (sscanf(buf, "%u", &start) != 1) {
+                    fprintf(stderr, "xl: Invalid color range: %s\n", buf);
+                    exit(1);
+                }
+                end = start;
+            }
+            else if (start > end) {
+                fprintf(stderr,
+                        "xl: Start color is greater than end color: %s\n", buf);
+                exit(1);
+            }
+
+            /* Check for overlaps */
+            for (k = start; k <= end; k++) {
+                for (p = 0; p < b_info->num_colors; p++)
+                    if (b_info->colors[p] == k) {
+                        fprintf(stderr, "xl: Overlapped ranges not allowed\n");
+                        exit(1);
+                    }
+            }
+
+            cur_index = b_info->num_colors;
+            b_info->num_colors += (end - start) + 1;
+            b_info->colors = (uint32_t *)realloc(b_info->colors,
+                                sizeof(*b_info->colors) * b_info->num_colors);
+
+            for (k = start; k <= end; k++)
+                b_info->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] 60+ messages in thread

* [PATCH 05/12] xen/arm: add support for cache coloring configuration via device-tree
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (3 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 04/12] tools/xl: add support for cache coloring configuration Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-08-26 12:51 ` [PATCH 06/12] xen/common: add cache coloring allocator for domains Carlo Nonato
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

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

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 docs/misc/arm/cache-coloring.rst      | 45 +++++++++++++++++++++++++++
 docs/misc/arm/device-tree/booting.txt |  4 +++
 xen/arch/arm/coloring.c               | 17 ++++++++++
 xen/arch/arm/domain_build.c           |  9 ++++++
 xen/arch/arm/include/asm/coloring.h   |  3 ++
 5 files changed, 78 insertions(+)

diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
index 345d97cb56..763acd2d3f 100644
--- a/docs/misc/arm/cache-coloring.rst
+++ b/docs/misc/arm/cache-coloring.rst
@@ -111,5 +111,50 @@ LLC way size (as previously discussed) and Dom0 colors can be set using the
 appropriate command line parameters. See the relevant documentation in
 "docs/misc/xen-command-line.pandoc".
 
+DomUs colors can be set either in the xl configuration file (relative
+documentation at "docs/man/xl.cfg.pod.5.in") or via Device Tree, also for
+Dom0less configurations, as in the following example:
+
+.. raw:: html
+
+    <pre>
+        xen,xen-bootargs = "console=dtuart dtuart=serial0 dom0_mem=1G dom0_max_vcpus=1 sched=null llc-way-size=64K xen-colors=0-1 dom0-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>;
+            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>;
+            };
+        };
+    </pre>
+
+Please refer to the relative documentation in
+"docs/misc/arm/device-tree/booting.txt".
+
 Note that if no color configuration is provided for domains, they fallback to
 the default one, which corresponds simply to all available colors.
\ No newline at end of file
diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
index 98253414b8..82e8dd89c8 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.
 
+- colors
+    A string specifying the 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/coloring.c b/xen/arch/arm/coloring.c
index 40a07617cc..87e20b952e 100644
--- a/xen/arch/arm/coloring.c
+++ b/xen/arch/arm/coloring.c
@@ -252,8 +252,11 @@ int domain_coloring_init(struct domain *d,
         if ( config->from_guest )
             copy_from_guest(d->arch.colors, config->colors, config->num_colors);
         else
+        {
             memcpy(d->arch.colors, config->colors.p,
                    sizeof(unsigned int) * config->num_colors);
+            xfree(config->colors.p);
+        }
     }
 
     if ( !d->arch.colors )
@@ -283,6 +286,20 @@ void domain_dump_coloring_info(struct domain *d)
     print_colors(d->arch.colors, d->arch.num_colors);
 }
 
+void prepare_color_domain_config(struct xen_arch_domainconfig *config,
+                                 const char *colors_str)
+{
+    unsigned int num;
+
+    config->colors.p = xzalloc_array(unsigned int, max_colors);
+    if ( !config->colors.p )
+        panic("Unable to allocate cache colors\n");
+
+    if ( parse_color_config(colors_str, config->colors.p, &num) )
+        panic("Error parsing the color configuration\n");
+    config->num_colors = (uint16_t)num;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 4d4cb692fc..979b9c8906 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -34,6 +34,7 @@
 #include <xen/serial.h>
 
 #ifdef CONFIG_CACHE_COLORING
+#include <asm/coloring.h>
 #define XEN_DOM0_CREATE_FLAGS CDF_privileged
 #else
 #define XEN_DOM0_CREATE_FLAGS CDF_privileged | CDF_directmap
@@ -3275,6 +3276,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 * __maybe_unused colors_str;
 
     BUG_ON(chosen == NULL);
     dt_for_each_child_node(chosen, node)
@@ -3354,6 +3356,13 @@ void __init create_domUs(void)
             d_cfg.cpupool_id = pool_id;
         }
 
+#ifdef CONFIG_CACHE_COLORING
+        if ( dt_find_property(node, "xen,static-mem", NULL) )
+            panic("static-mem is not valid when cache coloring is enabled\n");
+        if ( !dt_property_read_string(node, "colors", &colors_str) )
+            prepare_color_domain_config(&d_cfg.arch, colors_str);
+#endif
+
         /*
          * The variable max_init_domid is initialized with zero, so here it's
          * very important to use the pre-increment operator to call
diff --git a/xen/arch/arm/include/asm/coloring.h b/xen/arch/arm/include/asm/coloring.h
index 967031ae04..b7fa323870 100644
--- a/xen/arch/arm/include/asm/coloring.h
+++ b/xen/arch/arm/include/asm/coloring.h
@@ -36,4 +36,7 @@ int domain_coloring_init(struct domain *d,
 void domain_coloring_free(struct domain *d);
 void domain_dump_coloring_info(struct domain *d);
 
+void prepare_color_domain_config(struct xen_arch_domainconfig *config,
+                                 const char *colors_str);
+
 #endif /* !__ASM_ARM_COLORING_H__ */
-- 
2.34.1



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

* [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (4 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 05/12] xen/arm: add support for cache coloring configuration via device-tree Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-09-15 13:13   ` Jan Beulich
  2022-10-17  7:06   ` Michal Orzel
  2022-08-26 12:51 ` [PATCH 07/12] xen/common: add colored heap info debug-key Carlo Nonato
                   ` (8 subsequent siblings)
  14 siblings, 2 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

This commit adds a new memory page allocator that implements the cache
coloring mechanism. The allocation algorithm follows the given color
configuration of the domain and maximizes contiguity in the page selection.

Pages are stored in a color-indexed data structure of lists, sorted by their
machine addresses, that are collectively called the colored heap. A simple
initialization function computes the color of any available page and inserts
it in the corresponding list. When a domain requests a page, the allocator
takes one from the subset of lists whose colors equals the domain
configuration. It chooses the page with the highest machine address such that
contiguous pages are sequentially allocated, if this is made possible by a
color assignment which includes adjacent colors.

The allocator can handle only requests with order equals to 0 since the
single color granularity is represented in memory by one page.

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.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 docs/misc/arm/cache-coloring.rst    |  43 +++++-
 docs/misc/xen-command-line.pandoc   |  14 ++
 xen/arch/arm/Kconfig                |  12 ++
 xen/arch/arm/coloring.c             |  10 ++
 xen/arch/arm/include/asm/coloring.h |   6 +
 xen/arch/arm/include/asm/mm.h       |   3 +
 xen/common/page_alloc.c             | 213 ++++++++++++++++++++++++++--
 7 files changed, 290 insertions(+), 11 deletions(-)

diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
index 763acd2d3f..5f9132e525 100644
--- a/docs/misc/arm/cache-coloring.rst
+++ b/docs/misc/arm/cache-coloring.rst
@@ -13,6 +13,9 @@ In order to enable and use it, few steps are needed.
   (refer to menuconfig help for value meaning and when it should be changed).
 
         CONFIG_MAX_CACHE_COLORS=<n>
+- If needed, change the amount of memory reserved for the buddy allocator either
+  from the Xen configuration file, via the CONFIG_BUDDY_ALLOCATOR_SIZE value,
+  or with the command line option. See `Colored allocator and buddy allocator`.
 - Assign colors to domains using the `Color selection format`_ (see
   `Coloring parameters`_ for more documentation pointers).
 
@@ -157,4 +160,42 @@ Please refer to the relative documentation in
 "docs/misc/arm/device-tree/booting.txt".
 
 Note that if no color configuration is provided for domains, they fallback to
-the default one, which corresponds simply to all available colors.
\ No newline at end of file
+the default one, which corresponds simply to all available colors.
+
+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 systems is not colored yet, we need to support the coexistence of
+the two allocators and some memory must be left for the buddy one.
+The buddy allocator memory can be reserved from the Xen configuration file or
+with the help of a command-line option.
+
+Known issues and limitations
+****************************
+
+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 a order-1 page, four colors correspond to
+a order-2 pages, etc.
+
+Fail to boot colored DomUs with large memory size
+#################################################
+
+If the Linux kernel used for Dom0 does not contain the upstream commit
+3941552aec1e04d63999988a057ae09a1c56ebeb and uses the hypercall buffer device,
+colored DomUs with memory size larger then 127 MB cannot be created. This is
+caused by the default limit of this buffer of 64 pages. The solution is to
+manually apply the above patch, or to check if there is an updated version of
+the kernel in use for Dom0 that contains this change.
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 910ebeb2eb..4e85c4dfe4 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -299,6 +299,20 @@ can be maintained with the pv-shim mechanism.
     cause Xen not to use Indirect Branch Tracking even when support is
     available in hardware.
 
+### 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 cache 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.
+
 ### clocksource (x86)
 > `= pit | hpet | acpi | tsc`
 
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 8acff9682c..abce4bfc25 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -147,6 +147,18 @@ config MAX_CACHE_COLORS
 	  colors at boot. Note that if, at any time, a color configuration with more
 	  colors than the maximum will be employed an error will be produced.
 
+config BUDDY_ALLOCATOR_SIZE
+	string "Buddy allocator reserved memory size" if CACHE_COLORING
+	default "64M" if CACHE_COLORING
+	default "0M" if !CACHE_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 systems is not
+	  colored yet, we need to support the coexistence of the two allocators and
+	  some memory must be left for the buddy one.
+
 config TEE
 	bool "Enable TEE mediators support (UNSUPPORTED)" if UNSUPPORTED
 	default n
diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
index 87e20b952e..3fb86043d1 100644
--- a/xen/arch/arm/coloring.c
+++ b/xen/arch/arm/coloring.c
@@ -300,6 +300,16 @@ void prepare_color_domain_config(struct xen_arch_domainconfig *config,
     config->num_colors = (uint16_t)num;
 }
 
+unsigned int page_to_color(struct page_info *pg)
+{
+    return addr_to_color(page_to_maddr(pg));
+}
+
+unsigned int get_max_colors(void)
+{
+    return max_colors;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/include/asm/coloring.h b/xen/arch/arm/include/asm/coloring.h
index b7fa323870..0982bc9853 100644
--- a/xen/arch/arm/include/asm/coloring.h
+++ b/xen/arch/arm/include/asm/coloring.h
@@ -29,6 +29,8 @@
 
 #include <public/arch-arm.h>
 
+struct page_info;
+
 bool __init coloring_init(void);
 
 int domain_coloring_init(struct domain *d,
@@ -39,4 +41,8 @@ void domain_dump_coloring_info(struct domain *d);
 void prepare_color_domain_config(struct xen_arch_domainconfig *config,
                                  const char *colors_str);
 
+unsigned int page_to_color(struct page_info *pg);
+
+unsigned int get_max_colors(void);
+
 #endif /* !__ASM_ARM_COLORING_H__ */
diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
index da25251cda..a59fc3791a 100644
--- a/xen/arch/arm/include/asm/mm.h
+++ b/xen/arch/arm/include/asm/mm.h
@@ -143,6 +143,9 @@ struct page_info
 #define PGC_count_width   PG_shift(10)
 #define PGC_count_mask    ((1UL<<PGC_count_width)-1)
 
+#define _PGC_colored      PG_shift(11)
+#define PGC_colored       PG_mask(1, 11)
+
 /*
  * Page needs to be scrubbed. Since this bit can only be set on a page that is
  * free (i.e. in PGC_state_free) we can reuse PGC_allocated bit.
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index bfd4150be7..4ae3cfe9a7 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -150,6 +150,9 @@
 #define p2m_pod_offline_or_broken_hit(pg) 0
 #define p2m_pod_offline_or_broken_replace(pg) BUG_ON(pg != NULL)
 #endif
+#ifdef CONFIG_CACHE_COLORING
+#include <asm/coloring.h>
+#endif
 
 #ifndef PGC_static
 #define PGC_static 0
@@ -231,6 +234,9 @@ static bool __read_mostly scrub_debug;
 #define scrub_debug    false
 #endif
 
+/* Memory required for buddy allocator to work with colored one */
+static unsigned long __initdata buddy_alloc_size;
+
 /*
  * Bit width of the DMA heap -- used to override NUMA-node-first.
  * allocation strategy, which can otherwise exhaust low memory.
@@ -440,7 +446,172 @@ mfn_t __init alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
     BUG();
 }
 
+static DEFINE_SPINLOCK(heap_lock);
 
+/* 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);
+}
+
+static bool is_page_colored(struct page_info *pg)
+{
+    return pg->count_info & PGC_colored;
+}
+
+#ifdef CONFIG_CACHE_COLORING
+/*************************
+ * COLORED SIDE-ALLOCATOR
+ *
+ * Pages are stored by their color in separate lists. Each list defines a color
+ * and it is initialized during end_boot_allocator, where each page's color
+ * is calculated and the page itself is put in the correct list.
+ * After initialization there will be N lists where N is the number of maximum
+ * available colors on the platform.
+ */
+typedef struct page_list_head colored_pages_t;
+static colored_pages_t __ro_after_init *color_heap;
+
+#define colored_pages(color) &color_heap[(color)]
+
+static void color_heap_insert_page(struct page_info *pg)
+{
+    struct page_info *pos;
+    struct page_list_head *head = colored_pages(page_to_color(pg));
+
+    pg->count_info |= PGC_colored;
+
+    /* Insert page in list in ascending machine address order */
+    page_list_for_each( pos, head )
+    {
+        if ( page_to_maddr(pos) < page_to_maddr(pg) )
+        {
+            head = &pos->list;
+            break;
+        }
+    }
+
+    page_list_add_tail(pg, head);
+}
+
+static void color_heap_remove_page(struct page_info *pg)
+{
+    page_list_del(pg, colored_pages(page_to_color(pg)));
+}
+
+static void __init init_col_heap_pages(struct page_info *pg,
+                                       unsigned long nr_pages)
+{
+    unsigned int i;
+
+    if ( !color_heap )
+    {
+        unsigned int max_colors = get_max_colors();
+        color_heap = xmalloc_array(colored_pages_t, max_colors);
+        BUG_ON(!color_heap);
+
+        for ( i = 0; i < max_colors; i++ )
+            INIT_PAGE_LIST_HEAD(colored_pages(i));
+
+        if ( !buddy_alloc_size )
+            buddy_alloc_size = parse_size_and_unit(CONFIG_BUDDY_ALLOCATOR_SIZE,
+                                                   NULL);
+    }
+
+    printk(XENLOG_INFO "Init color heap with %lu pages\n", nr_pages);
+    printk(XENLOG_INFO "Paging starting from: 0x%"PRIx64"\n",
+           page_to_maddr(pg));
+
+    for ( i = 0; i < nr_pages; i++ )
+        color_heap_insert_page(pg++);
+}
+
+/* Alloc one page based on domain color configuration */
+static struct page_info *alloc_col_heap_page(unsigned int memflags,
+                                             const unsigned int *colors,
+                                             unsigned int num_colors)
+{
+    struct page_info *pg = NULL;
+    unsigned int i;
+    bool need_tlbflush = false;
+    uint32_t tlbflush_timestamp = 0;
+
+    spin_lock(&heap_lock);
+
+    for ( i = 0; i < num_colors; i++ )
+    {
+        struct page_info *tmp;
+
+        if ( page_list_empty(colored_pages(colors[i])) )
+            continue;
+
+        tmp = page_list_first(colored_pages(colors[i]));
+        if ( !pg || page_to_maddr(tmp) > page_to_maddr(pg) )
+            pg = tmp;
+    }
+
+    if ( !pg )
+    {
+        spin_unlock(&heap_lock);
+        return NULL;
+    }
+
+    pg->count_info = PGC_state_inuse;
+
+    if ( !(memflags & MEMF_no_tlbflush) )
+        accumulate_tlbflush(&need_tlbflush, pg, &tlbflush_timestamp);
+
+    init_free_page_fields(pg);
+    flush_page_to_ram(mfn_x(page_to_mfn(pg)),
+                      !(memflags & MEMF_no_icache_flush));
+    color_heap_remove_page(pg);
+
+    spin_unlock(&heap_lock);
+
+    if ( need_tlbflush )
+        filtered_flush_tlb_mask(tlbflush_timestamp);
+
+    return pg;
+}
+
+static void free_col_domheap_page(struct page_info *pg)
+{
+    pg->count_info = PGC_state_free;
+    page_set_owner(pg, NULL);
+    color_heap_insert_page(pg);
+}
+
+static struct page_info *alloc_col_domheap_page(struct domain *d,
+                                                unsigned int memflags)
+{
+    struct page_info *pg;
+
+    ASSERT(!in_irq());
+
+    pg = alloc_col_heap_page(memflags, d->arch.colors, d->arch.num_colors);
+    if ( !pg )
+    {
+        printk(XENLOG_ERR "Colored page is null for domain %pd\n", d);
+        return NULL;
+    }
+
+    if ( d && !(memflags & MEMF_no_owner) && assign_page(pg, 0, d, memflags) )
+    {
+        free_col_domheap_page(pg);
+        return NULL;
+    }
+
+    return pg;
+}
+
+size_param("buddy-alloc-size", buddy_alloc_size);
+#else
+static void free_col_domheap_page(struct page_info *pg)
+{
+    return;
+}
+#endif /* CONFIG_CACHE_COLORING */
 
 /*************************
  * BINARY BUDDY ALLOCATOR
@@ -462,7 +633,6 @@ static unsigned long node_need_scrub[MAX_NUMNODES];
 static unsigned long *avail[MAX_NUMNODES];
 static long total_avail_pages;
 
-static DEFINE_SPINLOCK(heap_lock);
 static long outstanding_claims; /* total outstanding claims by all domains */
 
 unsigned long domain_adjust_tot_pages(struct domain *d, long pages)
@@ -1027,10 +1197,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);
@@ -1926,6 +2093,7 @@ static unsigned long avail_heap_pages(
 void __init end_boot_allocator(void)
 {
     unsigned int i;
+    unsigned long buddy_pages = PFN_DOWN(buddy_alloc_size);
 
     /* Pages that are free now go to the domain sub-allocator. */
     for ( i = 0; i < nr_bootmem_regions; i++ )
@@ -1939,11 +2107,24 @@ void __init end_boot_allocator(void)
             break;
         }
     }
-    for ( i = nr_bootmem_regions; i-- > 0; )
+
+    for ( i = 0; i < nr_bootmem_regions; i++ )
     {
         struct bootmem_region *r = &bootmem_region_list[i];
+
+        if ( buddy_pages && (r->s < r->e) )
+        {
+            unsigned long pages = MIN(r->e - r->s, buddy_pages);
+            init_heap_pages(mfn_to_page(_mfn(r->s)), pages);
+            r->s += pages;
+            buddy_pages -= pages;
+        }
         if ( r->s < r->e )
+#ifdef CONFIG_CACHE_COLORING
+            init_col_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);
+#endif
     }
     nr_bootmem_regions = 0;
 
@@ -2429,6 +2610,17 @@ struct page_info *alloc_domheap_pages(
 
     ASSERT_ALLOC_CONTEXT();
 
+#ifdef CONFIG_CACHE_COLORING
+    /* Only domains are supported for coloring */
+    if ( d )
+    {
+        /* Colored allocation must be done on 0 order */
+        if ( order )
+            return NULL;
+        return alloc_col_domheap_page(d, memflags);
+    }
+#endif
+
     bits = domain_clamp_alloc_bitsize(memflags & MEMF_no_owner ? NULL : d,
                                       bits ? : (BITS_PER_LONG+PAGE_SHIFT));
 
@@ -2546,7 +2738,10 @@ void free_domheap_pages(struct page_info *pg, unsigned int order)
             scrub = 1;
         }
 
-        free_heap_pages(pg, order, scrub);
+        if ( is_page_colored(pg) )
+            free_col_domheap_page(pg);
+        else
+            free_heap_pages(pg, order, scrub);
     }
 
     if ( drop_dom_ref )
@@ -2759,9 +2954,7 @@ static struct page_info * __init acquire_staticmem_pages(mfn_t smfn,
          * 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] 60+ messages in thread

* [PATCH 07/12] xen/common: add colored heap info debug-key
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (5 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 06/12] xen/common: add cache coloring allocator for domains Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-08-26 14:13   ` Jan Beulich
  2022-08-26 12:51 ` [PATCH 08/12] Revert "xen/arm: setup: Add Xen as boot module before printing all boot modules" Carlo Nonato
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

This commit adds a debug-key to let the user inspect the colored heap
information. The number of pages stored for each available color is dumped.

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

diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 4ae3cfe9a7..be6bb2b9a1 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -605,6 +605,27 @@ static struct page_info *alloc_col_domheap_page(struct domain *d,
     return pg;
 }
 
+static void dump_col_heap(unsigned char key)
+{
+    struct page_info *pg;
+    unsigned long pages;
+    unsigned int color;
+
+    printk("'%c' pressed -> dumping coloring heap info\n", key);
+
+    for ( color = 0; color < get_max_colors(); color++ )
+    {
+        printk("Heap[%u]: ", color);
+        pages = 0;
+        page_list_for_each( pg, colored_pages(color) )
+        {
+            BUG_ON(!(page_to_color(pg) == color));
+            pages++;
+        }
+        printk("%lu pages\n", pages);
+    }
+}
+
 size_param("buddy-alloc-size", buddy_alloc_size);
 #else
 static void free_col_domheap_page(struct page_info *pg)
@@ -2853,6 +2874,9 @@ static void cf_check dump_heap(unsigned char key)
 static __init int cf_check register_heap_trigger(void)
 {
     register_keyhandler('H', dump_heap, "dump heap info", 1);
+#ifdef CONFIG_CACHE_COLORING
+    register_keyhandler('k', dump_col_heap, "dump coloring heap info", 1);
+#endif
     return 0;
 }
 __initcall(register_heap_trigger);
-- 
2.34.1



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

* [PATCH 08/12] Revert "xen/arm: setup: Add Xen as boot module before printing all boot modules"
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (6 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 07/12] xen/common: add colored heap info debug-key Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-09-10 14:01   ` Julien Grall
  2022-08-26 12:51 ` [PATCH 09/12] Revert "xen/arm: mm: Initialize page-tables earlier" Carlo Nonato
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

From: Luca Miccio <lucmiccio@gmail.com>

This reverts commit 48fb2a9deba11ee48dde21c5c1aa93b4d4e1043b.

The cache coloring support has the command line parsing as a prerequisite
because of the color configurations passed in this way. Also, the Xen boot
module will be placed at an address that depends on the coloring
initialization. This commit moves the Xen boot module after the coloring
initialization to allow the order of operations previously described to
take place.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 xen/arch/arm/setup.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index c02f21c0e6..611c93ad7d 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -921,12 +921,6 @@ void __init start_xen(unsigned long boot_phys_offset,
               "Please check your bootloader.\n",
               fdt_paddr);
 
-    /* Register Xen's load address as a boot module. */
-    xen_bootmodule = add_boot_module(BOOTMOD_XEN,
-                             (paddr_t)(uintptr_t)(_start + boot_phys_offset),
-                             (paddr_t)(uintptr_t)(_end - _start), false);
-    BUG_ON(!xen_bootmodule);
-
     fdt_size = boot_fdt_info(device_tree_flattened, fdt_paddr);
 
     cmdline = boot_fdt_cmdline(device_tree_flattened);
@@ -938,6 +932,12 @@ void __init start_xen(unsigned long boot_phys_offset,
         panic("Xen Coloring support: setup failed\n");
 #endif
 
+    /* Register Xen's load address as a boot module. */
+    xen_bootmodule = add_boot_module(BOOTMOD_XEN,
+                             (paddr_t)(uintptr_t)(_start + boot_phys_offset),
+                             (paddr_t)(uintptr_t)(_end - _start + 1), false);
+    BUG_ON(!xen_bootmodule);
+
     setup_mm();
 
     /* Parse the ACPI tables for possible boot-time configuration */
-- 
2.34.1



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

* [PATCH 09/12] Revert "xen/arm: mm: Initialize page-tables earlier"
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (7 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 08/12] Revert "xen/arm: setup: Add Xen as boot module before printing all boot modules" Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-09-10 14:28   ` Julien Grall
  2022-08-26 12:51 ` [PATCH 10/12] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START" Carlo Nonato
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

From: Luca Miccio <lucmiccio@gmail.com>

This reverts commit 3a5d341681af650825bbe3bee9be5d187da35080.

The cache coloring support will be configurable within the Xen command line,
but it will be initialized before the page-tables; this is necessary
for coloring the hypervisor itself beacuse we will create a specific
mapping for it that could be configured using some command line options.
In order to parse all the needed information from the device tree, we
need to revert the above commit and restore the previous order for
page-tables initialization.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 xen/arch/arm/mm.c    | 33 ++++++++++++++++++++-------------
 xen/arch/arm/setup.c |  4 ++--
 2 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index b42cddb1b4..1afa02b4af 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -368,6 +368,17 @@ static inline lpae_t pte_of_xenaddr(vaddr_t va)
     return mfn_to_xen_entry(maddr_to_mfn(ma), MT_NORMAL);
 }
 
+static void __init create_boot_mappings(unsigned long virt_offset,
+                                        mfn_t base_mfn)
+{
+    lpae_t pte;
+
+    pte = mfn_to_xen_entry(base_mfn, MT_NORMAL);
+    write_pte(&boot_second[second_table_offset(virt_offset)], pte);
+    flush_xen_tlb_local();
+}
+
+/* Map the FDT in the early boot page table */
 void * __init early_fdt_map(paddr_t fdt_paddr)
 {
     /* We are using 2MB superpage for mapping the FDT */
@@ -375,7 +386,6 @@ void * __init early_fdt_map(paddr_t fdt_paddr)
     paddr_t offset;
     void *fdt_virt;
     uint32_t size;
-    int rc;
 
     /*
      * Check whether the physical FDT address is set and meets the minimum
@@ -391,12 +401,7 @@ void * __init early_fdt_map(paddr_t fdt_paddr)
     /* The FDT is mapped using 2MB superpage */
     BUILD_BUG_ON(BOOT_FDT_VIRT_START % SZ_2M);
 
-    rc = map_pages_to_xen(BOOT_FDT_VIRT_START, maddr_to_mfn(base_paddr),
-                          SZ_2M >> PAGE_SHIFT,
-                          PAGE_HYPERVISOR_RO | _PAGE_BLOCK);
-    if ( rc )
-        panic("Unable to map the device-tree.\n");
-
+    create_boot_mappings(BOOT_FDT_VIRT_START, maddr_to_mfn(base_paddr));
 
     offset = fdt_paddr % SECOND_SIZE;
     fdt_virt = (void *)BOOT_FDT_VIRT_START + offset;
@@ -410,12 +415,8 @@ void * __init early_fdt_map(paddr_t fdt_paddr)
 
     if ( (offset + size) > SZ_2M )
     {
-        rc = map_pages_to_xen(BOOT_FDT_VIRT_START + SZ_2M,
-                              maddr_to_mfn(base_paddr + SZ_2M),
-                              SZ_2M >> PAGE_SHIFT,
-                              PAGE_HYPERVISOR_RO | _PAGE_BLOCK);
-        if ( rc )
-            panic("Unable to map the device-tree\n");
+        create_boot_mappings(BOOT_FDT_VIRT_START + SZ_2M,
+                             maddr_to_mfn(base_paddr + SZ_2M));
     }
 
     return fdt_virt;
@@ -514,6 +515,12 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
     pte.pt.table = 1;
     xen_second[second_table_offset(FIXMAP_ADDR(0))] = pte;
 
+    /* ... DTB */
+    pte = boot_second[second_table_offset(BOOT_FDT_VIRT_START)];
+    xen_second[second_table_offset(BOOT_FDT_VIRT_START)] = pte;
+    pte = boot_second[second_table_offset(BOOT_FDT_VIRT_START + SZ_2M)];
+    xen_second[second_table_offset(BOOT_FDT_VIRT_START + SZ_2M)] = pte;
+
 #ifdef CONFIG_ARM_64
     ttbr = (uintptr_t) xen_pgtable + phys_offset;
 #else
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 611c93ad7d..bdfc05bf61 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -910,8 +910,6 @@ void __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);
@@ -938,6 +936,8 @@ void __init start_xen(unsigned long boot_phys_offset,
                              (paddr_t)(uintptr_t)(_end - _start + 1), false);
     BUG_ON(!xen_bootmodule);
 
+    setup_pagetables(boot_phys_offset);
+
     setup_mm();
 
     /* Parse the ACPI tables for possible boot-time configuration */
-- 
2.34.1



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

* [PATCH 10/12] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START"
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (8 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 09/12] Revert "xen/arm: mm: Initialize page-tables earlier" Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-08-26 12:51 ` [PATCH 11/12] xen/arm: add Xen cache colors command line parameter Carlo Nonato
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato

This reverts commit 0c18fb76323bfb13615b6f13c98767face2d8097.

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.
---
 xen/arch/arm/include/asm/config.h | 4 +++-
 xen/arch/arm/mm.c                 | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/include/asm/config.h b/xen/arch/arm/include/asm/config.h
index 2fafb9f228..c8c1095d70 100644
--- a/xen/arch/arm/include/asm/config.h
+++ b/xen/arch/arm/include/asm/config.h
@@ -77,7 +77,8 @@
  *   2M -   4M   Xen text, data, bss
  *   4M -   6M   Fixmap: special-purpose 4K mapping slots
  *   6M -  10M   Early boot mapping of FDT
- *   10M - 12M   Livepatch vmap (if compiled in)
+ *   10M - 12M   Early relocation address (used when relocating Xen)
+ *               and later for livepatch vmap (if compiled in)
  *
  * ARM32 layout:
  *   0  -  12M   <COMMON>
@@ -113,6 +114,7 @@
 #define BOOT_FDT_VIRT_START    _AT(vaddr_t,0x00600000)
 #define BOOT_FDT_VIRT_SIZE     _AT(vaddr_t, MB(4))
 
+#define BOOT_RELOC_VIRT_START  _AT(vaddr_t,0x00a00000)
 #ifdef CONFIG_LIVEPATCH
 #define LIVEPATCH_VMAP_START   _AT(vaddr_t,0x00a00000)
 #define LIVEPATCH_VMAP_SIZE    _AT(vaddr_t, MB(2))
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 1afa02b4af..efc0dd75d1 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -154,6 +154,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] 60+ messages in thread

* [PATCH 11/12] xen/arm: add Xen cache colors command line parameter
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (9 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 10/12] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START" Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-08-26 12:51 ` [PATCH 12/12] xen/arm: add cache coloring support for Xen Carlo Nonato
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, Marco Solieri

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: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 docs/misc/arm/cache-coloring.rst  |  8 ++++----
 docs/misc/xen-command-line.pandoc |  9 +++++++++
 xen/arch/arm/coloring.c           | 30 ++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
index 5f9132e525..f347245093 100644
--- a/docs/misc/arm/cache-coloring.rst
+++ b/docs/misc/arm/cache-coloring.rst
@@ -16,8 +16,8 @@ In order to enable and use it, few steps are needed.
 - If needed, change the amount of memory reserved for the buddy allocator either
   from the Xen configuration file, via the CONFIG_BUDDY_ALLOCATOR_SIZE value,
   or with the command line option. See `Colored allocator and buddy allocator`.
-- Assign colors to domains using the `Color selection format`_ (see
-  `Coloring parameters`_ for more documentation pointers).
+- Assign colors to each memory pool (Xen, Dom0/DomUs) using the
+  `Color selection format`_ for `Coloring parameters`_ configuration.
 
 Background
 **********
@@ -110,8 +110,8 @@ Examples:
 Coloring parameters
 *******************
 
-LLC way size (as previously discussed) and Dom0 colors can be set using the
-appropriate command line parameters. See the relevant documentation in
+LLC way size (as previously discussed), Xen colors and Dom0 colors can be set
+using the appropriate command line parameters. See the relevant documentation in
 "docs/misc/xen-command-line.pandoc".
 
 DomUs colors can be set either in the xl configuration file (relative
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 4e85c4dfe4..3b4f7d54a7 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -2736,6 +2736,15 @@ In the case that x2apic is in use, this option switches between physical and
 clustered mode.  The default, given no hint from the **FADT**, is cluster
 mode.
 
+### xen-colors (arm64)
+> `= List of [ <integer> | <integer>-<integer> ]`
+
+> Default: `0: the lowermost color`
+
+Specify Xen color configuration.
+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/coloring.c b/xen/arch/arm/coloring.c
index 3fb86043d1..7ae4095dba 100644
--- a/xen/arch/arm/coloring.c
+++ b/xen/arch/arm/coloring.c
@@ -31,6 +31,10 @@
 #include <asm/processor.h>
 #include <asm/sysregs.h>
 
+/* By default Xen uses the lowestmost color */
+#define XEN_DEFAULT_COLOR       0
+#define XEN_DEFAULT_NUM_COLORS  1
+
 /* Size of a LLC way */
 static unsigned int llc_way_size;
 /* Number of colors available in the LLC */
@@ -42,6 +46,9 @@ static uint64_t addr_col_mask;
 #define addr_set_color(addr, color) (((addr) & ~addr_col_mask) \
                                      | ((color) << PAGE_SHIFT))
 
+static unsigned int xen_colors[CONFIG_MAX_CACHE_COLORS];
+static unsigned int xen_num_colors;
+
 static unsigned int dom0_colors[CONFIG_MAX_CACHE_COLORS];
 static unsigned int dom0_num_colors;
 
@@ -93,6 +100,12 @@ static int parse_color_config(const char *buf, unsigned int *colors,
 
 size_param("llc-way-size", llc_way_size);
 
+static int __init parse_xen_colors(const char *s)
+{
+    return parse_color_config(s, xen_colors, &xen_num_colors);
+}
+custom_param("xen-colors", parse_xen_colors);
+
 static int __init parse_dom0_colors(const char *s)
 {
     return parse_color_config(s, dom0_colors, &dom0_num_colors);
@@ -187,6 +200,8 @@ static void dump_coloring_info(unsigned char key)
     printk("LLC way size: %u KiB\n", llc_way_size >> 10);
     printk("Number of LLC colors supported: %u\n", max_colors);
     printk("Address color mask: 0x%lx\n", addr_col_mask);
+    printk("Xen colors: ");
+    print_colors(xen_colors, xen_num_colors);
 }
 
 bool __init coloring_init(void)
@@ -204,6 +219,21 @@ bool __init coloring_init(void)
     ASSERT((max_colors & (max_colors - 1)) == 0);
     addr_col_mask = (max_colors - 1) << PAGE_SHIFT;
 
+    if ( !xen_num_colors )
+    {
+        printk(XENLOG_WARNING
+               "Xen 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 color config for Xen\n");
+        return false;
+    }
+
     if ( !dom0_num_colors )
     {
         printk(XENLOG_WARNING
-- 
2.34.1



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

* [PATCH 12/12] xen/arm: add cache coloring support for Xen
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (10 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 11/12] xen/arm: add Xen cache colors command line parameter Carlo Nonato
@ 2022-08-26 12:51 ` Carlo Nonato
  2022-09-10 15:22   ` Julien Grall
  2022-09-15 13:25   ` Jan Beulich
  2022-09-10 15:12 ` [PATCH 00/12] Arm cache coloring Julien Grall
                   ` (2 subsequent siblings)
  14 siblings, 2 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 12:51 UTC (permalink / raw)
  To: xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Carlo Nonato, 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 the physical addresses, in case of cache coloring,
are taken from the translation of a new, temporary, virtual space that is
physically colored.

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.
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
(init_secondary_pagetables).

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 __vmap_colored is introduced for that. It actually is really
similar to the original __vmap, with the exception that it doesn't take for
granted that the physical memory is contiguous.

Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
---
 xen/arch/arm/alternative.c          |   5 ++
 xen/arch/arm/coloring.c             |  16 ++++
 xen/arch/arm/include/asm/coloring.h |  12 +++
 xen/arch/arm/include/asm/mm.h       |  19 ++++-
 xen/arch/arm/mm.c                   | 118 +++++++++++++++++++++++++---
 xen/arch/arm/psci.c                 |   4 +-
 xen/arch/arm/setup.c                |  74 +++++++++++++++--
 xen/arch/arm/smpboot.c              |   3 +-
 xen/arch/arm/xen.lds.S              |   2 +-
 xen/common/vmap.c                   |  25 ++++++
 xen/include/xen/vmap.h              |   4 +
 11 files changed, 258 insertions(+), 24 deletions(-)

diff --git a/xen/arch/arm/alternative.c b/xen/arch/arm/alternative.c
index f03cd943c6..fcecd3fec8 100644
--- a/xen/arch/arm/alternative.c
+++ b/xen/arch/arm/alternative.c
@@ -220,8 +220,13 @@ 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.
      */
+#ifdef CONFIG_CACHE_COLORING
+    xenmap = __vmap_colored(&xen_mfn, 1U << xen_order, 1, PAGE_HYPERVISOR,
+                            VMAP_DEFAULT);
+#else
     xenmap = __vmap(&xen_mfn, 1U << xen_order, 1, 1, PAGE_HYPERVISOR,
                     VMAP_DEFAULT);
+#endif
     /* Re-mapping Xen is not expected to fail during boot. */
     BUG_ON(!xenmap);
 
diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
index 7ae4095dba..946b21b826 100644
--- a/xen/arch/arm/coloring.c
+++ b/xen/arch/arm/coloring.c
@@ -340,6 +340,22 @@ unsigned int get_max_colors(void)
     return max_colors;
 }
 
+paddr_t next_xen_colored(paddr_t phys)
+{
+    unsigned int i, color = addr_to_color(phys);
+
+    for( i = 0; i < xen_num_colors; i++ )
+    {
+        if ( color == xen_colors[i] )
+            return phys;
+        else if ( color < xen_colors[i] )
+            return addr_set_color(phys, xen_colors[i]);
+    }
+
+    /* Jump to next color space (llc_way_size bytes) and use the first color */
+    return addr_set_color(phys + llc_way_size, xen_colors[0]);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/include/asm/coloring.h b/xen/arch/arm/include/asm/coloring.h
index 0982bc9853..374fef9278 100644
--- a/xen/arch/arm/include/asm/coloring.h
+++ b/xen/arch/arm/include/asm/coloring.h
@@ -25,10 +25,20 @@
 #define __ASM_ARM_COLORING_H__
 
 #include <xen/init.h>
+#include <xen/lib.h>
 #include <xen/sched.h>
 
 #include <public/arch-arm.h>
 
+/*
+ * Amount of memory that we need to map in order to color Xen. The value
+ * depends on the maximum number of available colors of the hardware. The
+ * memory size is pessimistically calculated assuming only one color is used,
+ * which means that any pages belonging to any other color has to be skipped.
+ */
+#define XEN_COLOR_MAP_SIZE \
+    ROUNDUP((_end - _start) * get_max_colors(), XEN_PADDR_ALIGN)
+
 struct page_info;
 
 bool __init coloring_init(void);
@@ -45,4 +55,6 @@ unsigned int page_to_color(struct page_info *pg);
 
 unsigned int get_max_colors(void);
 
+paddr_t next_xen_colored(paddr_t phys);
+
 #endif /* !__ASM_ARM_COLORING_H__ */
diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
index a59fc3791a..00351ee014 100644
--- a/xen/arch/arm/include/asm/mm.h
+++ b/xen/arch/arm/include/asm/mm.h
@@ -192,11 +192,15 @@ extern unsigned long total_pages;
 #define PDX_GROUP_SHIFT SECOND_SHIFT
 
 /* 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);
+#ifdef CONFIG_CACHE_COLORING
+/* Remove early coloring mappings */
+extern void remove_coloring_mappings(void);
+#endif
 /* Allocate and initialise pagetables for a secondary CPU. Sets init_ttbr to the
  * new page table */
 extern int init_secondary_pagetables(int cpu);
@@ -398,6 +402,19 @@ static inline void page_set_xenheap_gfn(struct page_info *p, gfn_t gfn)
     } while ( (y = cmpxchg(&p->u.inuse.type_info, x, nx)) != x );
 }
 
+#ifdef CONFIG_CACHE_COLORING
+#define virt_boot_xen(virt)\
+    (vaddr_t)(virt - XEN_VIRT_START + BOOT_RELOC_VIRT_START)
+#define set_value_for_secondary(var, val) \
+    *(typeof(var) *)(virt_boot_xen((vaddr_t)&var)) = val; \
+    clean_dcache(var);
+#else
+#define virt_boot_xen(virt) virt
+#define set_value_for_secondary(var, val) \
+    var = val;
+    clean_dcache(var);
+#endif
+
 #endif /*  __ARCH_ARM_MM__ */
 /*
  * Local variables:
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index efc0dd75d1..951e1796af 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -33,6 +33,9 @@
 
 #include <xsm/xsm.h>
 
+#ifdef CONFIG_CACHE_COLORING
+#include <asm/coloring.h>
+#endif
 #include <asm/fixmap.h>
 #include <asm/setup.h>
 
@@ -105,6 +108,9 @@ DEFINE_BOOT_PAGE_TABLE(boot_third);
 static DEFINE_PAGE_TABLE(xen_pgtable);
 static DEFINE_PAGE_TABLE(xen_first);
 #define THIS_CPU_PGTABLE xen_pgtable
+#ifdef CONFIG_CACHE_COLORING
+static DEFINE_PAGE_TABLE(xen_colored_temp);
+#endif
 #else
 #define HYP_PT_ROOT_LEVEL 1
 /* Per-CPU pagetable pages */
@@ -362,13 +368,6 @@ void flush_page_to_ram(unsigned long mfn, bool sync_icache)
         invalidate_icache();
 }
 
-static inline lpae_t pte_of_xenaddr(vaddr_t va)
-{
-    paddr_t ma = va + phys_offset;
-
-    return mfn_to_xen_entry(maddr_to_mfn(ma), MT_NORMAL);
-}
-
 static void __init create_boot_mappings(unsigned long virt_offset,
                                         mfn_t base_mfn)
 {
@@ -460,9 +459,79 @@ static void clear_table(void *table)
     clean_and_invalidate_dcache_va_range(table, PAGE_SIZE);
 }
 
-/* Boot-time pagetable setup.
- * Changes here may need matching changes in head.S */
-void __init setup_pagetables(unsigned long boot_phys_offset)
+#ifdef CONFIG_CACHE_COLORING
+/*
+ * Translate a Xen (.text) virtual address to the colored physical one
+ * depending on the hypervisor configuration.
+ * N.B: this function must be used only when migrating from non colored to
+ * colored pagetables since it assumes to have the temporary mappings created
+ * during setup_pagetables that starts from BOOT_RELOC_VIRT_START.
+ * After the migration we have to use virt_to_maddr.
+ */
+static paddr_t virt_to_maddr_colored(vaddr_t virt)
+{
+    unsigned int va_offset;
+
+    va_offset = virt - XEN_VIRT_START;
+    return __pa(BOOT_RELOC_VIRT_START + va_offset);
+}
+
+static void __init create_coloring_temp_mappings(paddr_t xen_paddr)
+{
+    lpae_t pte;
+    unsigned int i;
+
+    for ( i = 0; i < (_end - _start) / PAGE_SIZE; i++ )
+    {
+        xen_paddr = next_xen_colored(xen_paddr);
+        pte = mfn_to_xen_entry(maddr_to_mfn(xen_paddr), MT_NORMAL);
+        pte.pt.table = 1; /* level 3 mappings always have this bit set */
+        xen_colored_temp[i] = pte;
+        xen_paddr += PAGE_SIZE;
+    }
+
+    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_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);
+}
+#endif /* !CONFIG_CACHE_COLORING */
+
+static inline lpae_t pte_of_xenaddr(vaddr_t va)
+{
+#ifdef CONFIG_CACHE_COLORING
+    paddr_t ma = virt_to_maddr_colored(va);
+#else
+    paddr_t ma = va + phys_offset;
+#endif
+
+    return mfn_to_xen_entry(maddr_to_mfn(ma), MT_NORMAL);
+}
+
+/*
+ * 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, paddr_t xen_paddr)
 {
     uint64_t ttbr;
     lpae_t pte, *p;
@@ -470,6 +539,10 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
 
     phys_offset = boot_phys_offset;
 
+#ifdef CONFIG_CACHE_COLORING
+    create_coloring_temp_mappings(xen_paddr);
+#endif
+
 #ifdef CONFIG_ARM_64
     p = (void *) xen_pgtable;
     p[0] = pte_of_xenaddr((uintptr_t)xen_first);
@@ -522,7 +595,14 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
     pte = boot_second[second_table_offset(BOOT_FDT_VIRT_START + SZ_2M)];
     xen_second[second_table_offset(BOOT_FDT_VIRT_START + SZ_2M)] = pte;
 
-#ifdef CONFIG_ARM_64
+#ifdef CONFIG_CACHE_COLORING
+    /* Copy Xen to the new location */
+    memcpy((void *)BOOT_RELOC_VIRT_START, (const void *)XEN_VIRT_START,
+           (_end - _start));
+    clean_dcache_va_range((void *)BOOT_RELOC_VIRT_START, (_end - _start));
+
+    ttbr = virt_to_maddr_colored((vaddr_t)xen_pgtable);
+#elif CONFIG_ARM_64
     ttbr = (uintptr_t) xen_pgtable + phys_offset;
 #else
     ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
@@ -530,6 +610,18 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
 
     switch_ttbr(ttbr);
 
+#ifdef CONFIG_CACHE_COLORING
+    /*
+     * 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.
+     */
+    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);
+#endif
+
     xen_pt_enforce_wnx();
 
 #ifdef CONFIG_ARM_32
@@ -559,8 +651,8 @@ int init_secondary_pagetables(int cpu)
 
     /* 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 = (uintptr_t) xen_pgtable + phys_offset;
-    clean_dcache(init_ttbr);
+    set_value_for_secondary(init_ttbr, virt_to_maddr(xen_pgtable));
+
     return 0;
 }
 #else
diff --git a/xen/arch/arm/psci.c b/xen/arch/arm/psci.c
index 0c90c2305c..d25325d28f 100644
--- a/xen/arch/arm/psci.c
+++ b/xen/arch/arm/psci.c
@@ -49,8 +49,8 @@ int call_psci_cpu_on(int cpu)
 {
     struct arm_smccc_res res;
 
-    arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu), __pa(init_secondary),
-                  &res);
+    arm_smccc_smc(psci_cpu_on_nr, cpu_logical_map(cpu),
+                  __pa(virt_boot_xen((vaddr_t)init_secondary)), &res);
 
     return PSCI_RET(res);
 }
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index bdfc05bf61..4917ac84ab 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -453,7 +453,7 @@ static void * __init relocate_fdt(paddr_t dtb_paddr, size_t dtb_size)
     return fdt;
 }
 
-#ifdef CONFIG_ARM_32
+#if defined (CONFIG_ARM_32) || (CONFIG_CACHE_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
@@ -581,6 +581,60 @@ static paddr_t __init next_module(paddr_t s, paddr_t *end)
     return lowest;
 }
 
+#ifdef CONFIG_CACHE_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;
+}
+#endif
+
 static void __init init_pdx(void)
 {
     paddr_t bank_start, bank_size, bank_end;
@@ -900,6 +954,8 @@ void __init start_xen(unsigned long boot_phys_offset,
     struct bootmodule *xen_bootmodule;
     struct domain *d;
     int rc, i;
+    paddr_t xen_paddr = (paddr_t)(uintptr_t)(_start + boot_phys_offset);
+    paddr_t xen_size = (paddr_t)(uintptr_t)(_end - _start + 1);
 
     dcache_line_bytes = read_dcache_line_bytes();
 
@@ -928,15 +984,15 @@ void __init start_xen(unsigned long boot_phys_offset,
 #ifdef CONFIG_CACHE_COLORING
     if ( !coloring_init() )
         panic("Xen Coloring support: setup failed\n");
+    xen_size = XEN_COLOR_MAP_SIZE;
+    xen_paddr = get_xen_paddr((uint32_t)xen_size);
 #endif
 
     /* Register Xen's load address as a boot module. */
-    xen_bootmodule = add_boot_module(BOOTMOD_XEN,
-                             (paddr_t)(uintptr_t)(_start + boot_phys_offset),
-                             (paddr_t)(uintptr_t)(_end - _start + 1), false);
+    xen_bootmodule = add_boot_module(BOOTMOD_XEN, xen_paddr, xen_size, false);
     BUG_ON(!xen_bootmodule);
 
-    setup_pagetables(boot_phys_offset);
+    setup_pagetables(boot_phys_offset, xen_paddr);
 
     setup_mm();
 
@@ -1052,6 +1108,14 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     setup_virt_paging();
 
+#ifdef CONFIG_CACHE_COLORING
+    /*
+     * The removal is done earlier than discard_initial_modules beacuse the
+     * livepatch init uses a virtual address equal to BOOT_RELOC_VIRT_START.
+     * Remove coloring mappings to expose a clear state to the livepatch module.
+     */
+    remove_coloring_mappings();
+#endif
     do_initcalls();
 
     /*
diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
index f7bda3a18b..e7166ad79b 100644
--- a/xen/arch/arm/smpboot.c
+++ b/xen/arch/arm/smpboot.c
@@ -470,8 +470,7 @@ int __cpu_up(unsigned int cpu)
     init_data.cpuid = cpu;
 
     /* Open the gate for this CPU */
-    smp_up_cpu = cpu_logical_map(cpu);
-    clean_dcache(smp_up_cpu);
+    set_value_for_secondary(smp_up_cpu, cpu_logical_map(cpu));
 
     rc = arch_cpu_up(cpu);
 
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index 1e986e211f..4cdead1c4f 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -203,7 +203,7 @@ SECTIONS
        . = ALIGN(POINTER_ALIGN);
        __bss_end = .;
   } :text
-  _end = . ;
+  _end = ALIGN(PAGE_SIZE);
 
   /* Section for the device tree blob (if any). */
   .dtb : { *(.dtb) } :text
diff --git a/xen/common/vmap.c b/xen/common/vmap.c
index 4fd6b3067e..58818ddfe1 100644
--- a/xen/common/vmap.c
+++ b/xen/common/vmap.c
@@ -8,6 +8,9 @@
 #include <xen/types.h>
 #include <xen/vmap.h>
 #include <asm/page.h>
+#ifdef CONFIG_CACHE_COLORING
+#include <asm/coloring.h>
+#endif
 
 static DEFINE_SPINLOCK(vm_lock);
 static void *__read_mostly vm_base[VMAP_REGION_NR];
@@ -218,6 +221,28 @@ void *__vmap(const mfn_t *mfn, unsigned int granularity,
     return va;
 }
 
+#ifdef CONFIG_CACHE_COLORING
+void * __vmap_colored(const mfn_t *mfn, unsigned int nr, unsigned int align,
+                      unsigned int flags, enum vmap_region type)
+{
+    void *va = vm_alloc(nr, align, type);
+    unsigned long cur = (unsigned long)va;
+    paddr_t pa = mfn_to_maddr(*mfn);
+
+    for ( ; va && nr-- ; cur += PAGE_SIZE )
+    {
+        pa = next_xen_colored(pa);
+        if ( map_pages_to_xen(cur, maddr_to_mfn(pa), 1, flags) )
+        {
+            vunmap(va);
+            return NULL;
+        }
+        pa += PAGE_SIZE;
+    }
+    return va;
+}
+#endif
+
 void *vmap(const mfn_t *mfn, unsigned int nr)
 {
     return __vmap(mfn, 1, nr, 1, PAGE_HYPERVISOR, VMAP_DEFAULT);
diff --git a/xen/include/xen/vmap.h b/xen/include/xen/vmap.h
index b0f7632e89..9bdc9db70b 100644
--- a/xen/include/xen/vmap.h
+++ b/xen/include/xen/vmap.h
@@ -14,6 +14,10 @@ void vm_init_type(enum vmap_region type, void *start, void *end);
 
 void *__vmap(const mfn_t *mfn, unsigned int granularity, unsigned int nr,
              unsigned int align, unsigned int flags, enum vmap_region);
+#ifdef CONFIG_CACHE_COLORING
+void *__vmap_colored(const mfn_t *mfn, unsigned int nr, unsigned int align,
+                     unsigned int flags, enum vmap_region);
+#endif
 void *vmap(const mfn_t *mfn, unsigned int nr);
 void vunmap(const void *);
 
-- 
2.34.1



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

* Re: [PATCH 07/12] xen/common: add colored heap info debug-key
  2022-08-26 12:51 ` [PATCH 07/12] xen/common: add colored heap info debug-key Carlo Nonato
@ 2022-08-26 14:13   ` Jan Beulich
  2022-08-26 16:04     ` Carlo Nonato
  0 siblings, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2022-08-26 14:13 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 26.08.2022 14:51, Carlo Nonato wrote:
> --- a/xen/common/page_alloc.c
> +++ b/xen/common/page_alloc.c
> @@ -605,6 +605,27 @@ static struct page_info *alloc_col_domheap_page(struct domain *d,
>      return pg;
>  }
>  
> +static void dump_col_heap(unsigned char key)
> +{
> +    struct page_info *pg;

const and perhaps move into the loop's scope?

> +    unsigned long pages;
> +    unsigned int color;
> +
> +    printk("'%c' pressed -> dumping coloring heap info\n", key);
> +
> +    for ( color = 0; color < get_max_colors(); color++ )
> +    {
> +        printk("Heap[%u]: ", color);
> +        pages = 0;
> +        page_list_for_each( pg, colored_pages(color) )
> +        {
> +            BUG_ON(!(page_to_color(pg) == color));
> +            pages++;
> +        }

This is a very inefficient way for obtaining a count. On a large
system this loop is liable to take excessively long. I'm inclined
to say that even adding a call to process_pending_softirqs() isn't
going to make this work reasonably.

I'm also not convinced of having BUG_ON() in keyhandler functions
which are supposed to only dump state.

> @@ -2853,6 +2874,9 @@ static void cf_check dump_heap(unsigned char key)
>  static __init int cf_check register_heap_trigger(void)
>  {
>      register_keyhandler('H', dump_heap, "dump heap info", 1);
> +#ifdef CONFIG_CACHE_COLORING
> +    register_keyhandler('k', dump_col_heap, "dump coloring heap info", 1);
> +#endif

I question the consuming of a separate key for this purpose: What's
wrong with adding the functionality to dump_heap()?

Jan


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

* Re: [PATCH 07/12] xen/common: add colored heap info debug-key
  2022-08-26 14:13   ` Jan Beulich
@ 2022-08-26 16:04     ` Carlo Nonato
  0 siblings, 0 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-08-26 16:04 UTC (permalink / raw)
  To: Jan Beulich
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

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

On Fri, Aug 26, 2022 at 4:13 PM Jan Beulich <jbeulich@suse.com> wrote:

> On 26.08.2022 14:51, Carlo Nonato wrote:
> > --- a/xen/common/page_alloc.c
> > +++ b/xen/common/page_alloc.c
> > @@ -605,6 +605,27 @@ static struct page_info
> *alloc_col_domheap_page(struct domain *d,
> >      return pg;
> >  }
> >
> > +static void dump_col_heap(unsigned char key)
> > +{
> > +    struct page_info *pg;
>
> const and perhaps move into the loop's scope?
>
> > +    unsigned long pages;
> > +    unsigned int color;
> > +
> > +    printk("'%c' pressed -> dumping coloring heap info\n", key);
> > +
> > +    for ( color = 0; color < get_max_colors(); color++ )
> > +    {
> > +        printk("Heap[%u]: ", color);
> > +        pages = 0;
> > +        page_list_for_each( pg, colored_pages(color) )
> > +        {
> > +            BUG_ON(!(page_to_color(pg) == color));
> > +            pages++;
> > +        }
>
> This is a very inefficient way for obtaining a count. On a large
> system this loop is liable to take excessively long. I'm inclined
> to say that even adding a call to process_pending_softirqs() isn't
> going to make this work reasonably.
>

We can definitely add a dynamic array of counters that get updated when
inserting a page in the colored heap so that we don't need to compute
anything here.

I'm also not convinced of having BUG_ON() in keyhandler functions
> which are supposed to only dump state.


You're right. I'll remove that.

> @@ -2853,6 +2874,9 @@ static void cf_check dump_heap(unsigned char key)
> >  static __init int cf_check register_heap_trigger(void)
> >  {
> >      register_keyhandler('H', dump_heap, "dump heap info", 1);
> > +#ifdef CONFIG_CACHE_COLORING
> > +    register_keyhandler('k', dump_col_heap, "dump coloring heap info",
> 1);
> > +#endif
>
> I question the consuming of a separate key for this purpose: What's
> wrong with adding the functionality to dump_heap()?
>

We didn't want to weigh on that functionality so much, but probably
having a separate key is even worse. If it's not a problem I'll merge
it in the dump_heap() function.

Thanks.

- Carlo Nonato

[-- Attachment #2: Type: text/html, Size: 3207 bytes --]

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

* Re: [PATCH 08/12] Revert "xen/arm: setup: Add Xen as boot module before printing all boot modules"
  2022-08-26 12:51 ` [PATCH 08/12] Revert "xen/arm: setup: Add Xen as boot module before printing all boot modules" Carlo Nonato
@ 2022-09-10 14:01   ` Julien Grall
  2022-09-12 13:54     ` Carlo Nonato
  0 siblings, 1 reply; 60+ messages in thread
From: Julien Grall @ 2022-09-10 14:01 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi,

On 26/08/2022 13:51, Carlo Nonato wrote:
> From: Luca Miccio <lucmiccio@gmail.com>
> 
> This reverts commit 48fb2a9deba11ee48dde21c5c1aa93b4d4e1043b.
> 
> The cache coloring support has the command line parsing as a prerequisite
> because of the color configurations passed in this way. Also, the Xen boot
> module will be placed at an address that depends on the coloring
> initialization. This commit moves the Xen boot module after the coloring
> initialization to allow the order of operations previously described to
> take place.

The commit you revert was created in order to print the position of Xen 
on the console. So while I understand your aim, you are (temporarily?) 
not printing Xen address anymore.

Therefore your commit message, should contain some words explaining why 
this is fine and how this problem will be addressed.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 09/12] Revert "xen/arm: mm: Initialize page-tables earlier"
  2022-08-26 12:51 ` [PATCH 09/12] Revert "xen/arm: mm: Initialize page-tables earlier" Carlo Nonato
@ 2022-09-10 14:28   ` Julien Grall
  2022-09-12 13:59     ` Carlo Nonato
  0 siblings, 1 reply; 60+ messages in thread
From: Julien Grall @ 2022-09-10 14:28 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Carlo,

On 26/08/2022 13:51, Carlo Nonato wrote:
> From: Luca Miccio <lucmiccio@gmail.com>
> 
> This reverts commit 3a5d341681af650825bbe3bee9be5d187da35080.

Usually, this indicates that this was a clean revert. IOW, there was no 
clash or modification necessary. Looking at the diff below, this doesn't 
look to be the case because you are also reverting f8c818848fa6 
"xen/arm: mm: Re-implement early_fdt_map() using map_pages_to_xen()" 
and introduce a new version of create_boot_mappings().

So I think the commit message/title should be reworded to explain this 
is not a clean revert and what extra changes were made.

But see below about re-introducing create_boot_mapping().

> 
> The cache coloring support will be configurable within the Xen command line,
> but it will be initialized before the page-tables; this is necessary
> for coloring the hypervisor itself beacuse we will create a specific
> mapping for it that could be configured using some command line options.
> In order to parse all the needed information from the device tree, we
> need to revert the above commit and restore the previous order for
> page-tables initialization.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
>   xen/arch/arm/mm.c    | 33 ++++++++++++++++++++-------------
>   xen/arch/arm/setup.c |  4 ++--
>   2 files changed, 22 insertions(+), 15 deletions(-)
> 
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index b42cddb1b4..1afa02b4af 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -368,6 +368,17 @@ static inline lpae_t pte_of_xenaddr(vaddr_t va)
>       return mfn_to_xen_entry(maddr_to_mfn(ma), MT_NORMAL);
>   }
>   
> +static void __init create_boot_mappings(unsigned long virt_offset,
> +                                        mfn_t base_mfn)
> +{
> +    lpae_t pte;
> +
> +    pte = mfn_to_xen_entry(base_mfn, MT_NORMAL);
> +    write_pte(&boot_second[second_table_offset(virt_offset)], pte);
> +    flush_xen_tlb_local();
> +}
Please don't introduce a new function that create mappings. All mappings 
should be done using map_pages_to_xen(). Looking at the implementation, 
it should be usable with the following diff:

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index c81c706c8b23..78afb8eb0ec1 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -1104,7 +1104,7 @@ static int xen_pt_update(unsigned long virt,
       *
       * XXX: Add a check.
       */
-    const mfn_t root = virt_to_mfn(THIS_CPU_PGTABLE);
+    const mfn_t root = maddr_to_mfn(READ_SYSREG64(TTBR0_EL2));

      /*
       * The hardware was configured to forbid mapping both writeable and

With that there is no change required in early_fdt_map() and ...

>   
> +    /* ... DTB */
> +    pte = boot_second[second_table_offset(BOOT_FDT_VIRT_START)];
> +    xen_second[second_table_offset(BOOT_FDT_VIRT_START)] = pte;
> +    pte = boot_second[second_table_offset(BOOT_FDT_VIRT_START + SZ_2M)];
> +    xen_second[second_table_offset(BOOT_FDT_VIRT_START + SZ_2M)] = pte;
> +

... rather than copying the 2 entries, you could call early_fdt_map() 
after the switch. The advantage is it will avoid to hardoded more 
page-table entries.

As part of my switch_ttbr() rework, I am planning to re-introduce 
relocation (at least for testing). So I will include the changes I 
mention above in my series.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 00/12] Arm cache coloring
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (11 preceding siblings ...)
  2022-08-26 12:51 ` [PATCH 12/12] xen/arm: add cache coloring support for Xen Carlo Nonato
@ 2022-09-10 15:12 ` Julien Grall
  2022-09-12 13:24   ` Carlo Nonato
  2022-09-15 13:29 ` Jan Beulich
  2022-10-22 15:13 ` Julien Grall
  14 siblings, 1 reply; 60+ messages in thread
From: Julien Grall @ 2022-09-10 15:12 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio

Hi Carlo,

On 26/08/2022 13:50, 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 solution has been tested in several scenarios, including Xilinx Zynq
> MPSoCs.
> 
> Overview of implementation and commits structure
> ------------------------------------------------
> 
> - [1-3] Coloring initialization, cache layout auto-probing and coloring
>    data for domains are added.
> - [4-5] xl and Device Tree support for coloring is addedd.
> - [6-7] A new page allocator for domain memory that implement the cache
>    coloring mechanism is introduced.
> - [8-12] Coloring support is added for Xen .text region.
> 
> Changes in v2
> -------------
> 
> Lot of things changed between the two versions, mainly I tried to follow
> all the comments left by the maintainers after the previous version review.
> Here is a brief list of the major points (even if, imho, it's easier to
> repeat all the review process):

The series doesn't build on Arm64 without cache coloring. Please make 
sure to compile and check that Xen still boot on system after your 
series with cache coloring disabled.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 12/12] xen/arm: add cache coloring support for Xen
  2022-08-26 12:51 ` [PATCH 12/12] xen/arm: add cache coloring support for Xen Carlo Nonato
@ 2022-09-10 15:22   ` Julien Grall
  2022-09-10 15:23     ` Julien Grall
  2022-09-15 13:25   ` Jan Beulich
  1 sibling, 1 reply; 60+ messages in thread
From: Julien Grall @ 2022-09-10 15:22 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Carlo,

I haven't fully reviewed the patch yet. Just point out a couple of 
things I noticed while looking how you dealt with the relocation (I need 
some code to test my series :)).

On 26/08/2022 13:51, Carlo Nonato wrote:
> -#ifdef CONFIG_ARM_64
> +#ifdef CONFIG_CACHE_COLORING
> +    /* Copy Xen to the new location */
> +    memcpy((void *)BOOT_RELOC_VIRT_START, (const void *)XEN_VIRT_START,
> +           (_end - _start));

If I am not mistaken, at this point, Xen will still be using the stack 
that is part of Xen binary (see cpu0_boot_stack). However, until the 
point switch_ttbr() is called the stack can still be used. In particular...

> +    clean_dcache_va_range((void *)BOOT_RELOC_VIRT_START, (_end - _start)); > +
> +    ttbr = virt_to_maddr_colored((vaddr_t)xen_pgtable);
> +#elif CONFIG_ARM_64
>       ttbr = (uintptr_t) xen_pgtable + phys_offset;
>   #else
>       ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
> @@ -530,6 +610,18 @@ void __init setup_pagetables(unsigned long boot_phys_offset)
>   

... the compiler may need to save some information on the stack. And then...

>       switch_ttbr(ttbr);

... restore it after switch_ttbr(). Xen will be using a different stack 
(same virtual address but different physical address) so the wrong value 
will be loaded.

I am not aware of any guaranteed from the AAPCS{32, 64} that this can 
point (please provide a pointer if I am wrong). So I think we either 
want to copy the new Xen to the correct position in the assembly.

This means we would want to revive partially f60658c6ae47 "xen/arm: Stop 
relocating Xen".

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 12/12] xen/arm: add cache coloring support for Xen
  2022-09-10 15:22   ` Julien Grall
@ 2022-09-10 15:23     ` Julien Grall
  0 siblings, 0 replies; 60+ messages in thread
From: Julien Grall @ 2022-09-10 15:23 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri



On 10/09/2022 16:22, Julien Grall wrote:
> Hi Carlo,
> 
> I haven't fully reviewed the patch yet. Just point out a couple of 
> things I noticed while looking how you dealt with the relocation (I need 
> some code to test my series :)).
> 
> On 26/08/2022 13:51, Carlo Nonato wrote:
>> -#ifdef CONFIG_ARM_64
>> +#ifdef CONFIG_CACHE_COLORING
>> +    /* Copy Xen to the new location */
>> +    memcpy((void *)BOOT_RELOC_VIRT_START, (const void *)XEN_VIRT_START,
>> +           (_end - _start));
> 
> If I am not mistaken, at this point, Xen will still be using the stack 
> that is part of Xen binary (see cpu0_boot_stack). However, until the 
> point switch_ttbr() is called the stack can still be used. In particular...
> 
>> +    clean_dcache_va_range((void *)BOOT_RELOC_VIRT_START, (_end - 
>> _start)); > +
>> +    ttbr = virt_to_maddr_colored((vaddr_t)xen_pgtable);
>> +#elif CONFIG_ARM_64
>>       ttbr = (uintptr_t) xen_pgtable + phys_offset;
>>   #else
>>       ttbr = (uintptr_t) cpu0_pgtable + phys_offset;
>> @@ -530,6 +610,18 @@ void __init setup_pagetables(unsigned long 
>> boot_phys_offset)
> 
> ... the compiler may need to save some information on the stack. And 
> then...
> 
>>       switch_ttbr(ttbr);
> 
> ... restore it after switch_ttbr(). Xen will be using a different stack 
> (same virtual address but different physical address) so the wrong value 
> will be loaded.
> 
> I am not aware of any guaranteed from the AAPCS{32, 64} that this can 
> point (please provide a pointer if I am wrong). So I think we either 

s/point/not happen/

> want to copy the new Xen to the correct position in the assembly.
> 
> This means we would want to revive partially f60658c6ae47 "xen/arm: Stop 
> relocating Xen".
> 
> Cheers,
> 

-- 
Julien Grall


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

* Re: [PATCH 00/12] Arm cache coloring
  2022-09-10 15:12 ` [PATCH 00/12] Arm cache coloring Julien Grall
@ 2022-09-12 13:24   ` Carlo Nonato
  0 siblings, 0 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-09-12 13:24 UTC (permalink / raw)
  To: Julien Grall, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio

Hi Julien,

On Sat, Sep 10, 2022 at 5:12 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 26/08/2022 13:50, 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 solution has been tested in several scenarios, including Xilinx Zynq
> > MPSoCs.
> >
> > Overview of implementation and commits structure
> > ------------------------------------------------
> >
> > - [1-3] Coloring initialization, cache layout auto-probing and coloring
> >    data for domains are added.
> > - [4-5] xl and Device Tree support for coloring is addedd.
> > - [6-7] A new page allocator for domain memory that implement the cache
> >    coloring mechanism is introduced.
> > - [8-12] Coloring support is added for Xen .text region.
> >
> > Changes in v2
> > -------------
> >
> > Lot of things changed between the two versions, mainly I tried to follow
> > all the comments left by the maintainers after the previous version review.
> > Here is a brief list of the major points (even if, imho, it's easier to
> > repeat all the review process):
>
> The series doesn't build on Arm64 without cache coloring. Please make
> sure to compile and check that Xen still boot on system after your
> series with cache coloring disabled.

I'm sorry for that. Tested multiple times, but probably missed it after some
last minute change. The following diff fixes it.

diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
index 00351ee014..6abe2fdef7 100644
--- a/xen/arch/arm/include/asm/mm.h
+++ b/xen/arch/arm/include/asm/mm.h
@@ -411,7 +411,7 @@ static inline void page_set_xenheap_gfn(struct
page_info *p, gfn_t gfn)
 #else
 #define virt_boot_xen(virt) virt
 #define set_value_for_secondary(var, val) \
-    var = val;
+    var = val; \
     clean_dcache(var);
 #endif

>
> Cheers,
>
> --
> Julien Grall

Thanks.

- Carlo Nonato


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

* Re: [PATCH 08/12] Revert "xen/arm: setup: Add Xen as boot module before printing all boot modules"
  2022-09-10 14:01   ` Julien Grall
@ 2022-09-12 13:54     ` Carlo Nonato
  2022-10-21 16:52       ` Julien Grall
  0 siblings, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-09-12 13:54 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, andrew.cooper3, george.dunlap, jbeulich,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Marco Solieri

Hi Julien,

On Sat, Sep 10, 2022 at 4:01 PM Julien Grall <julien@xen.org> wrote:
>
> Hi,
>
> On 26/08/2022 13:51, Carlo Nonato wrote:
> > From: Luca Miccio <lucmiccio@gmail.com>
> >
> > This reverts commit 48fb2a9deba11ee48dde21c5c1aa93b4d4e1043b.
> >
> > The cache coloring support has the command line parsing as a prerequisite
> > because of the color configurations passed in this way. Also, the Xen boot
> > module will be placed at an address that depends on the coloring
> > initialization. This commit moves the Xen boot module after the coloring
> > initialization to allow the order of operations previously described to
> > take place.
>
> The commit you revert was created in order to print the position of Xen
> on the console. So while I understand your aim, you are (temporarily?)
> not printing Xen address anymore.

Yes. The address will be printed by the get_xen_paddr() function in later
patches, but only when coloring is enabled.
So I probably need to find a way to print it regardless of the configuration.
Do you have any suggestions? Is it ok to add the print to this very patch
explaining why I added that (since it would edit the clean revert)?

>
> Therefore your commit message, should contain some words explaining why
> this is fine and how this problem will be addressed.
>
> Cheers,
>
> --
> Julien Grall


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

* Re: [PATCH 09/12] Revert "xen/arm: mm: Initialize page-tables earlier"
  2022-09-10 14:28   ` Julien Grall
@ 2022-09-12 13:59     ` Carlo Nonato
  0 siblings, 0 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-09-12 13:59 UTC (permalink / raw)
  To: Julien Grall, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Julien,

On Sat, Sep 10, 2022 at 4:29 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 26/08/2022 13:51, Carlo Nonato wrote:
> > From: Luca Miccio <lucmiccio@gmail.com>
> >
> > This reverts commit 3a5d341681af650825bbe3bee9be5d187da35080.
>
> Usually, this indicates that this was a clean revert. IOW, there was no
> clash or modification necessary. Looking at the diff below, this doesn't
> look to be the case because you are also reverting f8c818848fa6
> "xen/arm: mm: Re-implement early_fdt_map() using map_pages_to_xen()"
> and introduce a new version of create_boot_mappings().
>
> So I think the commit message/title should be reworded to explain this
> is not a clean revert and what extra changes were made.
>
> But see below about re-introducing create_boot_mapping().
>
> >
> > The cache coloring support will be configurable within the Xen command line,
> > but it will be initialized before the page-tables; this is necessary
> > for coloring the hypervisor itself beacuse we will create a specific
> > mapping for it that could be configured using some command line options.
> > In order to parse all the needed information from the device tree, we
> > need to revert the above commit and restore the previous order for
> > page-tables initialization.
> >
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > ---
> >   xen/arch/arm/mm.c    | 33 ++++++++++++++++++++-------------
> >   xen/arch/arm/setup.c |  4 ++--
> >   2 files changed, 22 insertions(+), 15 deletions(-)
> >
> > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> > index b42cddb1b4..1afa02b4af 100644
> > --- a/xen/arch/arm/mm.c
> > +++ b/xen/arch/arm/mm.c
> > @@ -368,6 +368,17 @@ static inline lpae_t pte_of_xenaddr(vaddr_t va)
> >       return mfn_to_xen_entry(maddr_to_mfn(ma), MT_NORMAL);
> >   }
> >
> > +static void __init create_boot_mappings(unsigned long virt_offset,
> > +                                        mfn_t base_mfn)
> > +{
> > +    lpae_t pte;
> > +
> > +    pte = mfn_to_xen_entry(base_mfn, MT_NORMAL);
> > +    write_pte(&boot_second[second_table_offset(virt_offset)], pte);
> > +    flush_xen_tlb_local();
> > +}
> Please don't introduce a new function that create mappings. All mappings
> should be done using map_pages_to_xen(). Looking at the implementation,
> it should be usable with the following diff:
>
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index c81c706c8b23..78afb8eb0ec1 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -1104,7 +1104,7 @@ static int xen_pt_update(unsigned long virt,
>        *
>        * XXX: Add a check.
>        */
> -    const mfn_t root = virt_to_mfn(THIS_CPU_PGTABLE);
> +    const mfn_t root = maddr_to_mfn(READ_SYSREG64(TTBR0_EL2));
>
>       /*
>        * The hardware was configured to forbid mapping both writeable and
>
> With that there is no change required in early_fdt_map() and ...
>
> >
> > +    /* ... DTB */
> > +    pte = boot_second[second_table_offset(BOOT_FDT_VIRT_START)];
> > +    xen_second[second_table_offset(BOOT_FDT_VIRT_START)] = pte;
> > +    pte = boot_second[second_table_offset(BOOT_FDT_VIRT_START + SZ_2M)];
> > +    xen_second[second_table_offset(BOOT_FDT_VIRT_START + SZ_2M)] = pte;
> > +
>
> ... rather than copying the 2 entries, you could call early_fdt_map()
> after the switch. The advantage is it will avoid to hardoded more
> page-table entries.

Thanks for the diff and the suggestions. I just tested it and it works
properly! Nice.

>
> As part of my switch_ttbr() rework, I am planning to re-introduce
> relocation (at least for testing). So I will include the changes I
> mention above in my series.
>
> Cheers,
>
> --
> Julien Grall

Thanks.

- Carlo Nonato


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-08-26 12:51 ` [PATCH 06/12] xen/common: add cache coloring allocator for domains Carlo Nonato
@ 2022-09-15 13:13   ` Jan Beulich
  2022-09-16 16:05     ` Carlo Nonato
  2022-10-17  7:06   ` Michal Orzel
  1 sibling, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2022-09-15 13:13 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 26.08.2022 14:51, Carlo Nonato wrote:
> This commit adds a new memory page allocator that implements the cache
> coloring mechanism. The allocation algorithm follows the given color
> configuration of the domain and maximizes contiguity in the page selection.
> 
> Pages are stored in a color-indexed data structure of lists, sorted by their
> machine addresses, that are collectively called the colored heap. A simple
> initialization function computes the color of any available page and inserts
> it in the corresponding list. When a domain requests a page, the allocator
> takes one from the subset of lists whose colors equals the domain
> configuration. It chooses the page with the highest machine address such that
> contiguous pages are sequentially allocated, if this is made possible by a
> color assignment which includes adjacent colors.
> 
> The allocator can handle only requests with order equals to 0 since the
> single color granularity is represented in memory by one page.

In the earlier paragraph you talk about contiguous pages using contiguous
colors. This paragraph then appears to say the opposite, i.e. that
contiguous multi-page allocations aren't possible. Which of the two is it?

> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -147,6 +147,18 @@ config MAX_CACHE_COLORS
>  	  colors at boot. Note that if, at any time, a color configuration with more
>  	  colors than the maximum will be employed an error will be produced.
>  
> +config BUDDY_ALLOCATOR_SIZE
> +	string "Buddy allocator reserved memory size" if CACHE_COLORING
> +	default "64M" if CACHE_COLORING
> +	default "0M" if !CACHE_COLORING

I don't understand the purpose of this last line, nor the two earlier
"if". Why not simply

config BUDDY_ALLOCATOR_SIZE
	string "Buddy allocator reserved memory size"
	depend on CACHE_COLORING
	default "64M"

? Also does this really need to be a string, rather than a number (which
then doesn't need parsing) with e.g. MiB granularity?

Finally - how much of this is really Arm-specific? Shouldn't this be a
common config option, perhaps merely restricted to Arm by the top level
option (CACHE_COLORING?) depending on a further HAS_CACHE_COLORING,
which only Arm would select?

> --- a/xen/arch/arm/coloring.c
> +++ b/xen/arch/arm/coloring.c
> @@ -300,6 +300,16 @@ void prepare_color_domain_config(struct xen_arch_domainconfig *config,
>      config->num_colors = (uint16_t)num;
>  }
>  
> +unsigned int page_to_color(struct page_info *pg)

The parameter will want to be pointer-to-const and I wonder whether ...

> +{
> +    return addr_to_color(page_to_maddr(pg));
> +}

... the function as a whole wouldn't be a good candidate for being an
inline one (requiring addr_to_color() to be available in outside of
this file, of course).

> --- a/xen/arch/arm/include/asm/mm.h
> +++ b/xen/arch/arm/include/asm/mm.h
> @@ -143,6 +143,9 @@ struct page_info
>  #define PGC_count_width   PG_shift(10)
>  #define PGC_count_mask    ((1UL<<PGC_count_width)-1)
>  
> +#define _PGC_colored      PG_shift(11)
> +#define PGC_colored       PG_mask(1, 11)

I don't think this can work - you can't use bits already covered by
the count. You'll need to shift up PGC_count_{width,mask} by one and
insert your bit between PGC_extra and that. Or you could use one of
the lower unused ones, between PGC_static and PGC_broken.

> --- a/xen/common/page_alloc.c
> +++ b/xen/common/page_alloc.c
> @@ -150,6 +150,9 @@
>  #define p2m_pod_offline_or_broken_hit(pg) 0
>  #define p2m_pod_offline_or_broken_replace(pg) BUG_ON(pg != NULL)
>  #endif
> +#ifdef CONFIG_CACHE_COLORING
> +#include <asm/coloring.h>
> +#endif
>  
>  #ifndef PGC_static
>  #define PGC_static 0
> @@ -231,6 +234,9 @@ static bool __read_mostly scrub_debug;
>  #define scrub_debug    false
>  #endif
>  
> +/* Memory required for buddy allocator to work with colored one */
> +static unsigned long __initdata buddy_alloc_size;
> +
>  /*
>   * Bit width of the DMA heap -- used to override NUMA-node-first.
>   * allocation strategy, which can otherwise exhaust low memory.
> @@ -440,7 +446,172 @@ mfn_t __init alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
>      BUG();
>  }
>  
> +static DEFINE_SPINLOCK(heap_lock);
>  
> +/* 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);
> +}
> +
> +static bool is_page_colored(struct page_info *pg)
> +{
> +    return pg->count_info & PGC_colored;
> +}
> +
> +#ifdef CONFIG_CACHE_COLORING
> +/*************************
> + * COLORED SIDE-ALLOCATOR
> + *
> + * Pages are stored by their color in separate lists. Each list defines a color
> + * and it is initialized during end_boot_allocator, where each page's color
> + * is calculated and the page itself is put in the correct list.
> + * After initialization there will be N lists where N is the number of maximum
> + * available colors on the platform.
> + */

Nit: Perhaps either "maximum number of colors" or "number of available
colors"?

> +typedef struct page_list_head colored_pages_t;
> +static colored_pages_t __ro_after_init *color_heap;

Please place the attribute at its canonical slot:

static colored_pages_t *__ro_after_init color_heap;

It applies to the variable, not to the pointed-to type.

> +#define colored_pages(color) &color_heap[(color)]

The parentheses want to move:

#define colored_pages(color) (&color_heap[color])

> +static void color_heap_insert_page(struct page_info *pg)
> +{
> +    struct page_info *pos;
> +    struct page_list_head *head = colored_pages(page_to_color(pg));
> +
> +    pg->count_info |= PGC_colored;

The function isn't marked __init, so runtime correctness as to the
(non-atomic) update here wants clarifying.

> +    /* Insert page in list in ascending machine address order */

Isn't is descending order that you actually use, also seeing that
you take the first page of a list when allocating (further down)?

> +    page_list_for_each( pos, head )
> +    {
> +        if ( page_to_maddr(pos) < page_to_maddr(pg) )
> +        {
> +            head = &pos->list;
> +            break;
> +        }
> +    }

Wait - a linear search for every single page insertion? How well
is that going to perform on a multi-terabyte system?

> +    page_list_add_tail(pg, head);

page_list_head and page_list_entry are generally different things,
so I'm afraid this isn't correct in the common case, and you're
getting away with it only because only Arm currently enables this
code.

> +}
> +
> +static void color_heap_remove_page(struct page_info *pg)
> +{
> +    page_list_del(pg, colored_pages(page_to_color(pg)));
> +}
> +
> +static void __init init_col_heap_pages(struct page_info *pg,
> +                                       unsigned long nr_pages)
> +{
> +    unsigned int i;
> +
> +    if ( !color_heap )
> +    {
> +        unsigned int max_colors = get_max_colors();
> +        color_heap = xmalloc_array(colored_pages_t, max_colors);

Nit: Please always have a blank line between declaration(s) and
statement(s).

> +        BUG_ON(!color_heap);
> +
> +        for ( i = 0; i < max_colors; i++ )
> +            INIT_PAGE_LIST_HEAD(colored_pages(i));
> +
> +        if ( !buddy_alloc_size )
> +            buddy_alloc_size = parse_size_and_unit(CONFIG_BUDDY_ALLOCATOR_SIZE,
> +                                                   NULL);
> +    }
> +
> +    printk(XENLOG_INFO "Init color heap with %lu pages\n", nr_pages);
> +    printk(XENLOG_INFO "Paging starting from: 0x%"PRIx64"\n",
> +           page_to_maddr(pg));

"Paging"? And please prefer %# over 0x% for hex formatting, as we do
elsewhere.

> +    for ( i = 0; i < nr_pages; i++ )
> +        color_heap_insert_page(pg++);
> +}
> +
> +/* Alloc one page based on domain color configuration */
> +static struct page_info *alloc_col_heap_page(unsigned int memflags,
> +                                             const unsigned int *colors,
> +                                             unsigned int num_colors)

Array instead of pointer notation would better reflect the purpose.

> +{
> +    struct page_info *pg = NULL;
> +    unsigned int i;
> +    bool need_tlbflush = false;
> +    uint32_t tlbflush_timestamp = 0;
> +
> +    spin_lock(&heap_lock);
> +
> +    for ( i = 0; i < num_colors; i++ )
> +    {
> +        struct page_info *tmp;
> +
> +        if ( page_list_empty(colored_pages(colors[i])) )
> +            continue;
> +
> +        tmp = page_list_first(colored_pages(colors[i]));
> +        if ( !pg || page_to_maddr(tmp) > page_to_maddr(pg) )
> +            pg = tmp;
> +    }
> +
> +    if ( !pg )
> +    {
> +        spin_unlock(&heap_lock);
> +        return NULL;
> +    }
> +
> +    pg->count_info = PGC_state_inuse;

Aren't you losing PGC_colored here?

> +static struct page_info *alloc_col_domheap_page(struct domain *d,
> +                                                unsigned int memflags)
> +{
> +    struct page_info *pg;
> +
> +    ASSERT(!in_irq());

ASSERT_ALLOC_CONTEXT()? Albeit that's redundant then with the sole caller.

> +#else
> +static void free_col_domheap_page(struct page_info *pg)
> +{
> +    return;
> +}

No need for "return" here.

> @@ -1939,11 +2107,24 @@ void __init end_boot_allocator(void)
>              break;
>          }
>      }
> -    for ( i = nr_bootmem_regions; i-- > 0; )
> +
> +    for ( i = 0; i < nr_bootmem_regions; i++ )

I'm afraid you can't simply go and invert the direction this loop works
without any justification. It's not even clear why you need to work
forwards in the colored case.

Jan


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

* Re: [PATCH 12/12] xen/arm: add cache coloring support for Xen
  2022-08-26 12:51 ` [PATCH 12/12] xen/arm: add cache coloring support for Xen Carlo Nonato
  2022-09-10 15:22   ` Julien Grall
@ 2022-09-15 13:25   ` Jan Beulich
  2022-09-16 16:07     ` Carlo Nonato
  1 sibling, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2022-09-15 13:25 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 26.08.2022 14:51, Carlo Nonato wrote:
> --- a/xen/common/vmap.c
> +++ b/xen/common/vmap.c
> @@ -8,6 +8,9 @@
>  #include <xen/types.h>
>  #include <xen/vmap.h>
>  #include <asm/page.h>
> +#ifdef CONFIG_CACHE_COLORING
> +#include <asm/coloring.h>
> +#endif

Even independent of my earlier question towards more code becoming common,
I think there will want to be a xen/coloring.h which takes care of this
abstraction, requiring such #ifdef in just a single place.

> @@ -218,6 +221,28 @@ void *__vmap(const mfn_t *mfn, unsigned int granularity,
>      return va;
>  }
>  
> +#ifdef CONFIG_CACHE_COLORING
> +void * __vmap_colored(const mfn_t *mfn, unsigned int nr, unsigned int align,
> +                      unsigned int flags, enum vmap_region type)

Please no new functions with double underscores as prefix. Only static
symbol names may start with an underscore, and then also only with a
single one.

> +{
> +    void *va = vm_alloc(nr, align, type);
> +    unsigned long cur = (unsigned long)va;
> +    paddr_t pa = mfn_to_maddr(*mfn);
> +
> +    for ( ; va && nr-- ; cur += PAGE_SIZE )
> +    {
> +        pa = next_xen_colored(pa);

This may alter the address, yet the caller expects that the original
address be mapped. I must be missing something?

> +        if ( map_pages_to_xen(cur, maddr_to_mfn(pa), 1, flags) )
> +        {
> +            vunmap(va);
> +            return NULL;
> +        }
> +        pa += PAGE_SIZE;
> +    }
> +    return va;
> +}

Afaics you only consume the first slot of *mfn. What about the other
(nr - 1) ones? And compared to __vmap() there's no "granularity"
parameter, which is what controls the mapping of multiple contiguous
pages.

> --- a/xen/include/xen/vmap.h
> +++ b/xen/include/xen/vmap.h
> @@ -14,6 +14,10 @@ void vm_init_type(enum vmap_region type, void *start, void *end);
>  
>  void *__vmap(const mfn_t *mfn, unsigned int granularity, unsigned int nr,
>               unsigned int align, unsigned int flags, enum vmap_region);
> +#ifdef CONFIG_CACHE_COLORING
> +void *__vmap_colored(const mfn_t *mfn, unsigned int nr, unsigned int align,
> +                     unsigned int flags, enum vmap_region);
> +#endif

I don't think such a declaration really needs putting inside #ifdef.

Jan


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

* Re: [PATCH 00/12] Arm cache coloring
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (12 preceding siblings ...)
  2022-09-10 15:12 ` [PATCH 00/12] Arm cache coloring Julien Grall
@ 2022-09-15 13:29 ` Jan Beulich
  2022-09-15 14:52   ` Marco Solieri
  2022-09-15 18:15   ` Stefano Stabellini
  2022-10-22 15:13 ` Julien Grall
  14 siblings, 2 replies; 60+ messages in thread
From: Jan Beulich @ 2022-09-15 13:29 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, xen-devel

On 26.08.2022 14:50, 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 solution has been tested in several scenarios, including Xilinx Zynq
> MPSoCs.

Having looked at the non-Arm-specific parts of this I have one basic
question: Wouldn't it be possible to avoid the addition of entirely
new logic by treating the current model as just using a single color,
therefore merely becoming a special case of what you want?

Plus an advanced question: In how far does this interoperate with
static allocation, which again is (for now) an Arm-only feature?
Your reference to dom0less above doesn't cover this afaict.

Jan


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

* Re: [PATCH 00/12] Arm cache coloring
  2022-09-15 13:29 ` Jan Beulich
@ 2022-09-15 14:52   ` Marco Solieri
  2022-09-15 18:15   ` Stefano Stabellini
  1 sibling, 0 replies; 60+ messages in thread
From: Marco Solieri @ 2022-09-15 14:52 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Carlo Nonato, andrew.cooper3, george.dunlap, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	xen-devel

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

Hi Jan,

On Thu, Sep 15, 2022 at 03:29:08PM +0200, Jan Beulich wrote:
> On 26.08.2022 14:50, 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 solution has been tested in several scenarios, including Xilinx Zynq
> > MPSoCs.
> 
> Having looked at the non-Arm-specific parts of this I have one basic
> question: Wouldn't it be possible to avoid the addition of entirely
> new logic by treating the current model as just using a single color,
> therefore merely becoming a special case of what you want?

Nice question.  Thanks!

In principle, you are quite right: monochrome is just a degenerate
choice of colouring---the colouring implementation with a single colour
allows assigning all the available pages, exactly as it happens with the
ordinary allocator.  The difference lies in the allocation algorithm.

In practice, that would be quite inefficient.  This is because the
allocation logic used by the coloured allocator is quite simpler, since
it operates with lists, instead of binary trees.  Now, upgrading the
logic of the coloured allocator would be an overkill because lowering
the complexity of insertion/removal operations from linear to
logarithmic does not change much, since in the real world, the longest
sequence of physically contiguous pages that may be assigned is
max_colours - 1.

Cheers.

-- 
Marco Solieri, Ph.D.
CEO & Founder
Tel: +39-059-205-5182 -- Mobile: +39-349-678-66-65 -- OpenPGP: 0x75822E7E

Minerva Systems SRL -- https://www.minervasys.tech
Via Campi 213/B, 41125, Modena, Italy -- PIVA/CF 03996890368

~~>
Discover how to easily optimise complex embedded solutions
for high-performance, safety and predictability. Together.

> Plus an advanced question: In how far does this interoperate with
> static allocation, which again is (for now) an Arm-only feature?
> Your reference to dom0less above doesn't cover this afaict.
> 
> Jan

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

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

* Re: [PATCH 00/12] Arm cache coloring
  2022-09-15 13:29 ` Jan Beulich
  2022-09-15 14:52   ` Marco Solieri
@ 2022-09-15 18:15   ` Stefano Stabellini
  1 sibling, 0 replies; 60+ messages in thread
From: Stefano Stabellini @ 2022-09-15 18:15 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Carlo Nonato, andrew.cooper3, george.dunlap, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	xen-devel

On Thu, 15 Sep 2022, Jan Beulich wrote:
> Plus an advanced question: In how far does this interoperate with
> static allocation, which again is (for now) an Arm-only feature?
> Your reference to dom0less above doesn't cover this afaict.

I take you are referring to static-mem, the static memory ranges for
dom0less domUs described in docs/misc/arm/device-tree/booting.txt.

static-mem doesn't interoperate with cache coloring: each static range
would span across multiple colors. You have to choose either feature,
using both at the same time doesn't make sense.

Cheers,

Stefano


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-09-15 13:13   ` Jan Beulich
@ 2022-09-16 16:05     ` Carlo Nonato
  2022-09-19  6:26       ` Jan Beulich
  0 siblings, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-09-16 16:05 UTC (permalink / raw)
  To: Jan Beulich, xen-devel
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Jan,

On Thu, Sep 15, 2022 at 3:13 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 26.08.2022 14:51, Carlo Nonato wrote:
> > This commit adds a new memory page allocator that implements the cache
> > coloring mechanism. The allocation algorithm follows the given color
> > configuration of the domain and maximizes contiguity in the page selection.
> >
> > Pages are stored in a color-indexed data structure of lists, sorted by their
> > machine addresses, that are collectively called the colored heap. A simple
> > initialization function computes the color of any available page and inserts
> > it in the corresponding list. When a domain requests a page, the allocator
> > takes one from the subset of lists whose colors equals the domain
> > configuration. It chooses the page with the highest machine address such that
> > contiguous pages are sequentially allocated, if this is made possible by a
> > color assignment which includes adjacent colors.
> >
> > The allocator can handle only requests with order equals to 0 since the
> > single color granularity is represented in memory by one page.
>
> In the earlier paragraph you talk about contiguous pages using contiguous
> colors. This paragraph then appears to say the opposite, i.e. that
> contiguous multi-page allocations aren't possible. Which of the two is it?

Here there's a little confusion, you're right. Probably it's better explained
in the documentation that comes with this very patch: with a contiguous
colors assignment, we *could* allocate contiguous pages using the "order"
parameter greater than 0, but as a first implementation we simply decided not
to care for such cases and force the order-0 pages only.
However if two order-0 pages are requested subsequently, the allocator tries
to allocate them using different colors so that the cache is used more
efficiently and this is what I meant with "maximizes contiguity".

> > --- a/xen/arch/arm/Kconfig
> > +++ b/xen/arch/arm/Kconfig
> > @@ -147,6 +147,18 @@ config MAX_CACHE_COLORS
> >         colors at boot. Note that if, at any time, a color configuration with more
> >         colors than the maximum will be employed an error will be produced.
> >
> > +config BUDDY_ALLOCATOR_SIZE
> > +     string "Buddy allocator reserved memory size" if CACHE_COLORING
> > +     default "64M" if CACHE_COLORING
> > +     default "0M" if !CACHE_COLORING
>
> I don't understand the purpose of this last line, nor the two earlier
> "if". Why not simply
>
> config BUDDY_ALLOCATOR_SIZE
>         string "Buddy allocator reserved memory size"
>         depend on CACHE_COLORING
>         default "64M"

This was just to have a value for the config option even with cache coloring
disabled. All those ifs emulate the "depends on" keyword, but let the
CONFIG_BUDDY_ALLOCATOR_SIZE takes "0M" when coloring is disabled. With just
the "depends on" the macro isn't defined at all. I know that this can be
handled with some simple #ifdef, but I found this way to be more elegant.
Not an expert here so if you prefer the other way or a whole different one
(more readable/better fitted) please let me know.

> ? Also does this really need to be a string, rather than a number (which
> then doesn't need parsing) with e.g. MiB granularity?

Yeah it's easier like you said. I don't think there's a need for a < 1 MiB
value.

> Finally - how much of this is really Arm-specific? Shouldn't this be a
> common config option, perhaps merely restricted to Arm by the top level
> option (CACHE_COLORING?) depending on a further HAS_CACHE_COLORING,
> which only Arm would select?

I'm sorry, but I don't understand your suggestion. BUDDY_ALLOCATOR_SIZE
is Arm specific because CACHE_COLORING is. In fact it depends only on this
last config value and not on Arm config directly. Why should someone limit
the buddy allocator when coloring isn't enabled?
I've lost you on the HAS_CACHE_COLORING. Why should Arm config select this
one? Cache coloring must remain optional. I'm probably missing something.

> > --- a/xen/arch/arm/coloring.c
> > +++ b/xen/arch/arm/coloring.c
> > @@ -300,6 +300,16 @@ void prepare_color_domain_config(struct xen_arch_domainconfig *config,
> >      config->num_colors = (uint16_t)num;
> >  }
> >
> > +unsigned int page_to_color(struct page_info *pg)
>
> The parameter will want to be pointer-to-const and I wonder whether ...
>
> > +{
> > +    return addr_to_color(page_to_maddr(pg));
> > +}
>
> ... the function as a whole wouldn't be a good candidate for being an
> inline one (requiring addr_to_color() to be available in outside of
> this file, of course).

You mean defining it as static inline in the coloring.h header?

> > --- a/xen/arch/arm/include/asm/mm.h
> > +++ b/xen/arch/arm/include/asm/mm.h
> > @@ -143,6 +143,9 @@ struct page_info
> >  #define PGC_count_width   PG_shift(10)
> >  #define PGC_count_mask    ((1UL<<PGC_count_width)-1)
> >
> > +#define _PGC_colored      PG_shift(11)
> > +#define PGC_colored       PG_mask(1, 11)
>
> I don't think this can work - you can't use bits already covered by
> the count. You'll need to shift up PGC_count_{width,mask} by one and
> insert your bit between PGC_extra and that. Or you could use one of
> the lower unused ones, between PGC_static and PGC_broken.

Yes you're right. I misinterpreted those values. Shame on me.

> > --- a/xen/common/page_alloc.c
> > +++ b/xen/common/page_alloc.c
> > @@ -150,6 +150,9 @@
> >  #define p2m_pod_offline_or_broken_hit(pg) 0
> >  #define p2m_pod_offline_or_broken_replace(pg) BUG_ON(pg != NULL)
> >  #endif
> > +#ifdef CONFIG_CACHE_COLORING
> > +#include <asm/coloring.h>
> > +#endif
> >
> >  #ifndef PGC_static
> >  #define PGC_static 0
> > @@ -231,6 +234,9 @@ static bool __read_mostly scrub_debug;
> >  #define scrub_debug    false
> >  #endif
> >
> > +/* Memory required for buddy allocator to work with colored one */
> > +static unsigned long __initdata buddy_alloc_size;
> > +
> >  /*
> >   * Bit width of the DMA heap -- used to override NUMA-node-first.
> >   * allocation strategy, which can otherwise exhaust low memory.
> > @@ -440,7 +446,172 @@ mfn_t __init alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
> >      BUG();
> >  }
> >
> > +static DEFINE_SPINLOCK(heap_lock);
> >
> > +/* 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);
> > +}
> > +
> > +static bool is_page_colored(struct page_info *pg)
> > +{
> > +    return pg->count_info & PGC_colored;
> > +}
> > +
> > +#ifdef CONFIG_CACHE_COLORING
> > +/*************************
> > + * COLORED SIDE-ALLOCATOR
> > + *
> > + * Pages are stored by their color in separate lists. Each list defines a color
> > + * and it is initialized during end_boot_allocator, where each page's color
> > + * is calculated and the page itself is put in the correct list.
> > + * After initialization there will be N lists where N is the number of maximum
> > + * available colors on the platform.
> > + */
>
> Nit: Perhaps either "maximum number of colors" or "number of available
> colors"?
>
> > +typedef struct page_list_head colored_pages_t;
> > +static colored_pages_t __ro_after_init *color_heap;
>
> Please place the attribute at its canonical slot:
>
> static colored_pages_t *__ro_after_init color_heap;
>
> It applies to the variable, not to the pointed-to type.
>
> > +#define colored_pages(color) &color_heap[(color)]
>
> The parentheses want to move:
>
> #define colored_pages(color) (&color_heap[color])
>
> > +static void color_heap_insert_page(struct page_info *pg)
> > +{
> > +    struct page_info *pos;
> > +    struct page_list_head *head = colored_pages(page_to_color(pg));
> > +
> > +    pg->count_info |= PGC_colored;
>
> The function isn't marked __init, so runtime correctness as to the
> (non-atomic) update here wants clarifying.

Yes. I need to check and probably add a spin lock for the color heap.

> > +    /* Insert page in list in ascending machine address order */
>
> Isn't is descending order that you actually use, also seeing that
> you take the first page of a list when allocating (further down)?

Yes you're right. Forgot to change the comment.

> > +    page_list_for_each( pos, head )
> > +    {
> > +        if ( page_to_maddr(pos) < page_to_maddr(pg) )
> > +        {
> > +            head = &pos->list;
> > +            break;
> > +        }
> > +    }
>
> Wait - a linear search for every single page insertion? How well
> is that going to perform on a multi-terabyte system?

For our test cases (embedded systems) the linear search is good enough.
I agree with you that in the general case this is bad (even though the main
targets are indeed embedded systems).
Are there any already available data structures that we can exploit to get
better performances?

> > +    page_list_add_tail(pg, head);
>
> page_list_head and page_list_entry are generally different things,
> so I'm afraid this isn't correct in the common case, and you're
> getting away with it only because only Arm currently enables this
> code.

So how to insert in the middle of the list?

>
> > +}
> > +
> > +static void color_heap_remove_page(struct page_info *pg)
> > +{
> > +    page_list_del(pg, colored_pages(page_to_color(pg)));
> > +}
> > +
> > +static void __init init_col_heap_pages(struct page_info *pg,
> > +                                       unsigned long nr_pages)
> > +{
> > +    unsigned int i;
> > +
> > +    if ( !color_heap )
> > +    {
> > +        unsigned int max_colors = get_max_colors();
> > +        color_heap = xmalloc_array(colored_pages_t, max_colors);
>
> Nit: Please always have a blank line between declaration(s) and
> statement(s).
>
> > +        BUG_ON(!color_heap);
> > +
> > +        for ( i = 0; i < max_colors; i++ )
> > +            INIT_PAGE_LIST_HEAD(colored_pages(i));
> > +
> > +        if ( !buddy_alloc_size )
> > +            buddy_alloc_size = parse_size_and_unit(CONFIG_BUDDY_ALLOCATOR_SIZE,
> > +                                                   NULL);
> > +    }
> > +
> > +    printk(XENLOG_INFO "Init color heap with %lu pages\n", nr_pages);
> > +    printk(XENLOG_INFO "Paging starting from: 0x%"PRIx64"\n",
> > +           page_to_maddr(pg));
>
> "Paging"? And please prefer %# over 0x% for hex formatting, as we do
> elsewhere.
>
> > +    for ( i = 0; i < nr_pages; i++ )
> > +        color_heap_insert_page(pg++);
> > +}
> > +
> > +/* Alloc one page based on domain color configuration */
> > +static struct page_info *alloc_col_heap_page(unsigned int memflags,
> > +                                             const unsigned int *colors,
> > +                                             unsigned int num_colors)
>
> Array instead of pointer notation would better reflect the purpose.
>
> > +{
> > +    struct page_info *pg = NULL;
> > +    unsigned int i;
> > +    bool need_tlbflush = false;
> > +    uint32_t tlbflush_timestamp = 0;
> > +
> > +    spin_lock(&heap_lock);
> > +
> > +    for ( i = 0; i < num_colors; i++ )
> > +    {
> > +        struct page_info *tmp;
> > +
> > +        if ( page_list_empty(colored_pages(colors[i])) )
> > +            continue;
> > +
> > +        tmp = page_list_first(colored_pages(colors[i]));
> > +        if ( !pg || page_to_maddr(tmp) > page_to_maddr(pg) )
> > +            pg = tmp;
> > +    }
> > +
> > +    if ( !pg )
> > +    {
> > +        spin_unlock(&heap_lock);
> > +        return NULL;
> > +    }
> > +
> > +    pg->count_info = PGC_state_inuse;
>
> Aren't you losing PGC_colored here?

Right. Pretty nasty bug you found.

> > +static struct page_info *alloc_col_domheap_page(struct domain *d,
> > +                                                unsigned int memflags)
> > +{
> > +    struct page_info *pg;
> > +
> > +    ASSERT(!in_irq());
>
> ASSERT_ALLOC_CONTEXT()? Albeit that's redundant then with the sole caller.
>
> > +#else
> > +static void free_col_domheap_page(struct page_info *pg)
> > +{
> > +    return;
> > +}
>
> No need for "return" here.
>
> > @@ -1939,11 +2107,24 @@ void __init end_boot_allocator(void)
> >              break;
> >          }
> >      }
> > -    for ( i = nr_bootmem_regions; i-- > 0; )
> > +
> > +    for ( i = 0; i < nr_bootmem_regions; i++ )
>
> I'm afraid you can't simply go and invert the direction this loop works
> without any justification. It's not even clear why you need to work
> forwards in the colored case.

The order was inverted because I'm assuming bootmem regions are stored in
ascending order (this should be the case looking at bootmem_region_add().
Am I wrong?) and (second assumption) pages taken from each memory region
are sorted in ascending order relatively to their machine address.
This means that color_heap_insert_page() is called (at least during
end_boot_allocator()) with always increasing machine addresses and so the
linear search should be O(1).

> Jan

Thanks.

- Carlo Nonato


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

* Re: [PATCH 12/12] xen/arm: add cache coloring support for Xen
  2022-09-15 13:25   ` Jan Beulich
@ 2022-09-16 16:07     ` Carlo Nonato
  2022-09-19  8:38       ` Jan Beulich
  0 siblings, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-09-16 16:07 UTC (permalink / raw)
  To: Jan Beulich, xen-devel
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Jan,

On Thu, Sep 15, 2022 at 3:25 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 26.08.2022 14:51, Carlo Nonato wrote:
> > --- a/xen/common/vmap.c
> > +++ b/xen/common/vmap.c
> > @@ -8,6 +8,9 @@
> >  #include <xen/types.h>
> >  #include <xen/vmap.h>
> >  #include <asm/page.h>
> > +#ifdef CONFIG_CACHE_COLORING
> > +#include <asm/coloring.h>
> > +#endif
>
> Even independent of my earlier question towards more code becoming common,
> I think there will want to be a xen/coloring.h which takes care of this
> abstraction, requiring such #ifdef in just a single place.
>
> > @@ -218,6 +221,28 @@ void *__vmap(const mfn_t *mfn, unsigned int granularity,
> >      return va;
> >  }
> >
> > +#ifdef CONFIG_CACHE_COLORING
> > +void * __vmap_colored(const mfn_t *mfn, unsigned int nr, unsigned int align,
> > +                      unsigned int flags, enum vmap_region type)
>
> Please no new functions with double underscores as prefix. Only static
> symbol names may start with an underscore, and then also only with a
> single one.
>
> > +{
> > +    void *va = vm_alloc(nr, align, type);
> > +    unsigned long cur = (unsigned long)va;
> > +    paddr_t pa = mfn_to_maddr(*mfn);
> > +
> > +    for ( ; va && nr-- ; cur += PAGE_SIZE )
> > +    {
> > +        pa = next_xen_colored(pa);
>
> This may alter the address, yet the caller expects that the original
> address be mapped. I must be missing something?

If the original address color is assigned to Xen, then next_xen_colored()
simply returns that address. If this isn't the case, then you're right: the
address changes to the correct, colored, one. The caller should expect
this behavior since this is the colored version of vmap, the one that takes
into account the Xen coloring configuration.

> > +        if ( map_pages_to_xen(cur, maddr_to_mfn(pa), 1, flags) )
> > +        {
> > +            vunmap(va);
> > +            return NULL;
> > +        }
> > +        pa += PAGE_SIZE;
> > +    }
> > +    return va;
> > +}
>
> Afaics you only consume the first slot of *mfn. What about the other
> (nr - 1) ones?

Not sure I understood. The first slot is used as the starting point and then
the addr of that mfn plus next_xen_colored() are the mechanism used to select
the next mfns. Probably the first argument of vmap_colored is a bit
misleading.

> And compared to __vmap() there's no "granularity"
> parameter, which is what controls the mapping of multiple contiguous
> pages.

That's because we don't support multiple contiguous pages in the sense that
we only operate on one page at a time (like explained in the
"Known limitations" doc section and elsewhere in those discussions).

> > --- a/xen/include/xen/vmap.h
> > +++ b/xen/include/xen/vmap.h
> > @@ -14,6 +14,10 @@ void vm_init_type(enum vmap_region type, void *start, void *end);
> >
> >  void *__vmap(const mfn_t *mfn, unsigned int granularity, unsigned int nr,
> >               unsigned int align, unsigned int flags, enum vmap_region);
> > +#ifdef CONFIG_CACHE_COLORING
> > +void *__vmap_colored(const mfn_t *mfn, unsigned int nr, unsigned int align,
> > +                     unsigned int flags, enum vmap_region);
> > +#endif
>
> I don't think such a declaration really needs putting inside #ifdef.
>
> Jan

Thanks.

- Carlo Nonato


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-09-16 16:05     ` Carlo Nonato
@ 2022-09-19  6:26       ` Jan Beulich
  2022-09-19 22:42         ` Stefano Stabellini
  2022-10-13  9:47         ` Carlo Nonato
  0 siblings, 2 replies; 60+ messages in thread
From: Jan Beulich @ 2022-09-19  6:26 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 16.09.2022 18:05, Carlo Nonato wrote:
> On Thu, Sep 15, 2022 at 3:13 PM Jan Beulich <jbeulich@suse.com> wrote:
>> On 26.08.2022 14:51, Carlo Nonato wrote:
>>> --- a/xen/arch/arm/Kconfig
>>> +++ b/xen/arch/arm/Kconfig
>>> @@ -147,6 +147,18 @@ config MAX_CACHE_COLORS
>>>         colors at boot. Note that if, at any time, a color configuration with more
>>>         colors than the maximum will be employed an error will be produced.
>>>
>>> +config BUDDY_ALLOCATOR_SIZE
>>> +     string "Buddy allocator reserved memory size" if CACHE_COLORING
>>> +     default "64M" if CACHE_COLORING
>>> +     default "0M" if !CACHE_COLORING
>>
>> I don't understand the purpose of this last line, nor the two earlier
>> "if". Why not simply
>>
>> config BUDDY_ALLOCATOR_SIZE
>>         string "Buddy allocator reserved memory size"
>>         depend on CACHE_COLORING
>>         default "64M"
> 
> This was just to have a value for the config option even with cache coloring
> disabled. All those ifs emulate the "depends on" keyword, but let the
> CONFIG_BUDDY_ALLOCATOR_SIZE takes "0M" when coloring is disabled. With just
> the "depends on" the macro isn't defined at all. I know that this can be
> handled with some simple #ifdef, but I found this way to be more elegant.
> Not an expert here so if you prefer the other way or a whole different one
> (more readable/better fitted) please let me know.

As far as I saw, the sole use was already inside a suitable #ifdef. Hence
yes, I clearly would see "depends on" as the better fit. Please also don't
forget that if later cache coloring would be enabled for another
architecture, that default of zero (pre-recorded in a .config) would get
in the way; one would need to manually change it (and remember to do so).

>> Finally - how much of this is really Arm-specific? Shouldn't this be a
>> common config option, perhaps merely restricted to Arm by the top level
>> option (CACHE_COLORING?) depending on a further HAS_CACHE_COLORING,
>> which only Arm would select?
> 
> I'm sorry, but I don't understand your suggestion. BUDDY_ALLOCATOR_SIZE
> is Arm specific because CACHE_COLORING is. In fact it depends only on this
> last config value and not on Arm config directly. Why should someone limit
> the buddy allocator when coloring isn't enabled?

My comment wasn't on this on setting alone, but on the coloring ones as a
set.

> I've lost you on the HAS_CACHE_COLORING. Why should Arm config select this
> one? Cache coloring must remain optional. I'm probably missing something.

HAS_* settings only express what an arch is capable of; they don't replace
dependent options which actually are user-selectable. (That said, we have
a number where there's no user selection possible, but that's not of
interest here.)

>>> --- a/xen/arch/arm/coloring.c
>>> +++ b/xen/arch/arm/coloring.c
>>> @@ -300,6 +300,16 @@ void prepare_color_domain_config(struct xen_arch_domainconfig *config,
>>>      config->num_colors = (uint16_t)num;
>>>  }
>>>
>>> +unsigned int page_to_color(struct page_info *pg)
>>
>> The parameter will want to be pointer-to-const and I wonder whether ...
>>
>>> +{
>>> +    return addr_to_color(page_to_maddr(pg));
>>> +}
>>
>> ... the function as a whole wouldn't be a good candidate for being an
>> inline one (requiring addr_to_color() to be available in outside of
>> this file, of course).
> 
> You mean defining it as static inline in the coloring.h header?

That would seem preferable for a simple function like this one.

>>> +static void color_heap_insert_page(struct page_info *pg)
>>> +{
>>> +    struct page_info *pos;
>>> +    struct page_list_head *head = colored_pages(page_to_color(pg));
>>> +
>>> +    pg->count_info |= PGC_colored;
>>
>> The function isn't marked __init, so runtime correctness as to the
>> (non-atomic) update here wants clarifying.
> 
> Yes. I need to check and probably add a spin lock for the color heap.

I'm afraid a spin lock won't help. May I suggest you look at some of
the staticmem discussions that had happened, including a similar
topic. (Sorry, I don't have a link at hand to the exact mail.)

>>> +    page_list_for_each( pos, head )
>>> +    {
>>> +        if ( page_to_maddr(pos) < page_to_maddr(pg) )
>>> +        {
>>> +            head = &pos->list;
>>> +            break;
>>> +        }
>>> +    }
>>
>> Wait - a linear search for every single page insertion? How well
>> is that going to perform on a multi-terabyte system?
> 
> For our test cases (embedded systems) the linear search is good enough.
> I agree with you that in the general case this is bad (even though the main
> targets are indeed embedded systems).
> Are there any already available data structures that we can exploit to get
> better performances?

I'm afraid there aren't any that I would see as a good fit here.

>>> +    page_list_add_tail(pg, head);
>>
>> page_list_head and page_list_entry are generally different things,
>> so I'm afraid this isn't correct in the common case, and you're
>> getting away with it only because only Arm currently enables this
>> code.
> 
> So how to insert in the middle of the list?

That likely would require a page_list_*() new helper function. So
far we simply had no need to insert at other than head or tail,
iirc.

>>> @@ -1939,11 +2107,24 @@ void __init end_boot_allocator(void)
>>>              break;
>>>          }
>>>      }
>>> -    for ( i = nr_bootmem_regions; i-- > 0; )
>>> +
>>> +    for ( i = 0; i < nr_bootmem_regions; i++ )
>>
>> I'm afraid you can't simply go and invert the direction this loop works
>> without any justification. It's not even clear why you need to work
>> forwards in the colored case.
> 
> The order was inverted because I'm assuming bootmem regions are stored in
> ascending order (this should be the case looking at bootmem_region_add().
> Am I wrong?) and (second assumption) pages taken from each memory region
> are sorted in ascending order relatively to their machine address.
> This means that color_heap_insert_page() is called (at least during
> end_boot_allocator()) with always increasing machine addresses and so the
> linear search should be O(1).

Indeed that was my guess. Yet the present order of processing is there
for a reason, so you need to both retain it and supply justification
(perhaps by way of a brief comment) why you need alternative code for
your allocator. Even better would of course be if insertion was more
efficient and didn't require the logic here to specifically take care.

Jan


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

* Re: [PATCH 12/12] xen/arm: add cache coloring support for Xen
  2022-09-16 16:07     ` Carlo Nonato
@ 2022-09-19  8:38       ` Jan Beulich
  2022-09-27 14:31         ` Carlo Nonato
  0 siblings, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2022-09-19  8:38 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 16.09.2022 18:07, Carlo Nonato wrote:
> On Thu, Sep 15, 2022 at 3:25 PM Jan Beulich <jbeulich@suse.com> wrote:
>> On 26.08.2022 14:51, Carlo Nonato wrote:
>>> @@ -218,6 +221,28 @@ void *__vmap(const mfn_t *mfn, unsigned int granularity,
>>>      return va;
>>>  }
>>>
>>> +#ifdef CONFIG_CACHE_COLORING
>>> +void * __vmap_colored(const mfn_t *mfn, unsigned int nr, unsigned int align,
>>> +                      unsigned int flags, enum vmap_region type)
>>> +{
>>> +    void *va = vm_alloc(nr, align, type);
>>> +    unsigned long cur = (unsigned long)va;
>>> +    paddr_t pa = mfn_to_maddr(*mfn);
>>> +
>>> +    for ( ; va && nr-- ; cur += PAGE_SIZE )
>>> +    {
>>> +        pa = next_xen_colored(pa);
>>
>> This may alter the address, yet the caller expects that the original
>> address be mapped. I must be missing something?
> 
> If the original address color is assigned to Xen, then next_xen_colored()
> simply returns that address. If this isn't the case, then you're right: the
> address changes to the correct, colored, one. The caller should expect
> this behavior since this is the colored version of vmap, the one that takes
> into account the Xen coloring configuration.

That's (to me at least) very surprising behavior, and hence needs
properly calling out in a code comment at the least.

Personally I'm not convinced of having a function with this behavior,
and instead I think the normal vmap() should do. As long as you're
only allowing for order-0 allocations, that shouldn't be an issue
anyway.

>>> +        if ( map_pages_to_xen(cur, maddr_to_mfn(pa), 1, flags) )
>>> +        {
>>> +            vunmap(va);
>>> +            return NULL;
>>> +        }
>>> +        pa += PAGE_SIZE;
>>> +    }
>>> +    return va;
>>> +}
>>
>> Afaics you only consume the first slot of *mfn. What about the other
>> (nr - 1) ones?
> 
> Not sure I understood. The first slot is used as the starting point and then
> the addr of that mfn plus next_xen_colored() are the mechanism used to select
> the next mfns. Probably the first argument of vmap_colored is a bit
> misleading.

Yes - it shouldn't be an array if it's not used as one.

Jan


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-09-19  6:26       ` Jan Beulich
@ 2022-09-19 22:42         ` Stefano Stabellini
  2022-09-20  7:54           ` Jan Beulich
  2022-10-13  9:47         ` Carlo Nonato
  1 sibling, 1 reply; 60+ messages in thread
From: Stefano Stabellini @ 2022-09-19 22:42 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Carlo Nonato, andrew.cooper3, george.dunlap, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Marco Solieri, xen-devel

On Mon, 19 Sep 2022, Jan Beulich wrote:
> On 16.09.2022 18:05, Carlo Nonato wrote:
> > On Thu, Sep 15, 2022 at 3:13 PM Jan Beulich <jbeulich@suse.com> wrote:
> >> On 26.08.2022 14:51, Carlo Nonato wrote:
> >>> --- a/xen/arch/arm/Kconfig
> >>> +++ b/xen/arch/arm/Kconfig
> >>> @@ -147,6 +147,18 @@ config MAX_CACHE_COLORS
> >>>         colors at boot. Note that if, at any time, a color configuration with more
> >>>         colors than the maximum will be employed an error will be produced.
> >>>
> >>> +config BUDDY_ALLOCATOR_SIZE
> >>> +     string "Buddy allocator reserved memory size" if CACHE_COLORING
> >>> +     default "64M" if CACHE_COLORING
> >>> +     default "0M" if !CACHE_COLORING
> >>
> >> I don't understand the purpose of this last line, nor the two earlier
> >> "if". Why not simply
> >>
> >> config BUDDY_ALLOCATOR_SIZE
> >>         string "Buddy allocator reserved memory size"
> >>         depend on CACHE_COLORING
> >>         default "64M"
> > 
> > This was just to have a value for the config option even with cache coloring
> > disabled. All those ifs emulate the "depends on" keyword, but let the
> > CONFIG_BUDDY_ALLOCATOR_SIZE takes "0M" when coloring is disabled. With just
> > the "depends on" the macro isn't defined at all. I know that this can be
> > handled with some simple #ifdef, but I found this way to be more elegant.
> > Not an expert here so if you prefer the other way or a whole different one
> > (more readable/better fitted) please let me know.
> 
> As far as I saw, the sole use was already inside a suitable #ifdef. Hence
> yes, I clearly would see "depends on" as the better fit. Please also don't
> forget that if later cache coloring would be enabled for another
> architecture, that default of zero (pre-recorded in a .config) would get
> in the way; one would need to manually change it (and remember to do so).
> 
> >> Finally - how much of this is really Arm-specific? Shouldn't this be a
> >> common config option, perhaps merely restricted to Arm by the top level
> >> option (CACHE_COLORING?) depending on a further HAS_CACHE_COLORING,
> >> which only Arm would select?
> > 
> > I'm sorry, but I don't understand your suggestion. BUDDY_ALLOCATOR_SIZE
> > is Arm specific because CACHE_COLORING is. In fact it depends only on this
> > last config value and not on Arm config directly. Why should someone limit
> > the buddy allocator when coloring isn't enabled?
> 
> My comment wasn't on this on setting alone, but on the coloring ones as a
> set.
> 
> > I've lost you on the HAS_CACHE_COLORING. Why should Arm config select this
> > one? Cache coloring must remain optional. I'm probably missing something.
> 
> HAS_* settings only express what an arch is capable of; they don't replace
> dependent options which actually are user-selectable. (That said, we have
> a number where there's no user selection possible, but that's not of
> interest here.)
> 
> >>> --- a/xen/arch/arm/coloring.c
> >>> +++ b/xen/arch/arm/coloring.c
> >>> @@ -300,6 +300,16 @@ void prepare_color_domain_config(struct xen_arch_domainconfig *config,
> >>>      config->num_colors = (uint16_t)num;
> >>>  }
> >>>
> >>> +unsigned int page_to_color(struct page_info *pg)
> >>
> >> The parameter will want to be pointer-to-const and I wonder whether ...
> >>
> >>> +{
> >>> +    return addr_to_color(page_to_maddr(pg));
> >>> +}
> >>
> >> ... the function as a whole wouldn't be a good candidate for being an
> >> inline one (requiring addr_to_color() to be available in outside of
> >> this file, of course).
> > 
> > You mean defining it as static inline in the coloring.h header?
> 
> That would seem preferable for a simple function like this one.
> 
> >>> +static void color_heap_insert_page(struct page_info *pg)
> >>> +{
> >>> +    struct page_info *pos;
> >>> +    struct page_list_head *head = colored_pages(page_to_color(pg));
> >>> +
> >>> +    pg->count_info |= PGC_colored;
> >>
> >> The function isn't marked __init, so runtime correctness as to the
> >> (non-atomic) update here wants clarifying.
> > 
> > Yes. I need to check and probably add a spin lock for the color heap.
> 
> I'm afraid a spin lock won't help. May I suggest you look at some of
> the staticmem discussions that had happened, including a similar
> topic. (Sorry, I don't have a link at hand to the exact mail.)

I searched through the recent staticmem discussions to try to provide a
helpful link for Carlo, but I don't think I managed to find what you had
in mind. I found these two lock-related emails:

https://marc.info/?l=xen-devel&m=165476642832402
https://marc.info/?l=xen-devel&m=165632461420257

If they are not relevant, could you please provide a few more details?


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-09-19 22:42         ` Stefano Stabellini
@ 2022-09-20  7:54           ` Jan Beulich
  0 siblings, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2022-09-20  7:54 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Carlo Nonato, andrew.cooper3, george.dunlap, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Marco Solieri, xen-devel

On 20.09.2022 00:42, Stefano Stabellini wrote:
> On Mon, 19 Sep 2022, Jan Beulich wrote:
>> On 16.09.2022 18:05, Carlo Nonato wrote:
>>> On Thu, Sep 15, 2022 at 3:13 PM Jan Beulich <jbeulich@suse.com> wrote:
>>>> On 26.08.2022 14:51, Carlo Nonato wrote:
>>>>> --- a/xen/arch/arm/Kconfig
>>>>> +++ b/xen/arch/arm/Kconfig
>>>>> @@ -147,6 +147,18 @@ config MAX_CACHE_COLORS
>>>>>         colors at boot. Note that if, at any time, a color configuration with more
>>>>>         colors than the maximum will be employed an error will be produced.
>>>>>
>>>>> +config BUDDY_ALLOCATOR_SIZE
>>>>> +     string "Buddy allocator reserved memory size" if CACHE_COLORING
>>>>> +     default "64M" if CACHE_COLORING
>>>>> +     default "0M" if !CACHE_COLORING
>>>>
>>>> I don't understand the purpose of this last line, nor the two earlier
>>>> "if". Why not simply
>>>>
>>>> config BUDDY_ALLOCATOR_SIZE
>>>>         string "Buddy allocator reserved memory size"
>>>>         depend on CACHE_COLORING
>>>>         default "64M"
>>>
>>> This was just to have a value for the config option even with cache coloring
>>> disabled. All those ifs emulate the "depends on" keyword, but let the
>>> CONFIG_BUDDY_ALLOCATOR_SIZE takes "0M" when coloring is disabled. With just
>>> the "depends on" the macro isn't defined at all. I know that this can be
>>> handled with some simple #ifdef, but I found this way to be more elegant.
>>> Not an expert here so if you prefer the other way or a whole different one
>>> (more readable/better fitted) please let me know.
>>
>> As far as I saw, the sole use was already inside a suitable #ifdef. Hence
>> yes, I clearly would see "depends on" as the better fit. Please also don't
>> forget that if later cache coloring would be enabled for another
>> architecture, that default of zero (pre-recorded in a .config) would get
>> in the way; one would need to manually change it (and remember to do so).
>>
>>>> Finally - how much of this is really Arm-specific? Shouldn't this be a
>>>> common config option, perhaps merely restricted to Arm by the top level
>>>> option (CACHE_COLORING?) depending on a further HAS_CACHE_COLORING,
>>>> which only Arm would select?
>>>
>>> I'm sorry, but I don't understand your suggestion. BUDDY_ALLOCATOR_SIZE
>>> is Arm specific because CACHE_COLORING is. In fact it depends only on this
>>> last config value and not on Arm config directly. Why should someone limit
>>> the buddy allocator when coloring isn't enabled?
>>
>> My comment wasn't on this on setting alone, but on the coloring ones as a
>> set.
>>
>>> I've lost you on the HAS_CACHE_COLORING. Why should Arm config select this
>>> one? Cache coloring must remain optional. I'm probably missing something.
>>
>> HAS_* settings only express what an arch is capable of; they don't replace
>> dependent options which actually are user-selectable. (That said, we have
>> a number where there's no user selection possible, but that's not of
>> interest here.)
>>
>>>>> --- a/xen/arch/arm/coloring.c
>>>>> +++ b/xen/arch/arm/coloring.c
>>>>> @@ -300,6 +300,16 @@ void prepare_color_domain_config(struct xen_arch_domainconfig *config,
>>>>>      config->num_colors = (uint16_t)num;
>>>>>  }
>>>>>
>>>>> +unsigned int page_to_color(struct page_info *pg)
>>>>
>>>> The parameter will want to be pointer-to-const and I wonder whether ...
>>>>
>>>>> +{
>>>>> +    return addr_to_color(page_to_maddr(pg));
>>>>> +}
>>>>
>>>> ... the function as a whole wouldn't be a good candidate for being an
>>>> inline one (requiring addr_to_color() to be available in outside of
>>>> this file, of course).
>>>
>>> You mean defining it as static inline in the coloring.h header?
>>
>> That would seem preferable for a simple function like this one.
>>
>>>>> +static void color_heap_insert_page(struct page_info *pg)
>>>>> +{
>>>>> +    struct page_info *pos;
>>>>> +    struct page_list_head *head = colored_pages(page_to_color(pg));
>>>>> +
>>>>> +    pg->count_info |= PGC_colored;
>>>>
>>>> The function isn't marked __init, so runtime correctness as to the
>>>> (non-atomic) update here wants clarifying.
>>>
>>> Yes. I need to check and probably add a spin lock for the color heap.
>>
>> I'm afraid a spin lock won't help. May I suggest you look at some of
>> the staticmem discussions that had happened, including a similar
>> topic. (Sorry, I don't have a link at hand to the exact mail.)
> 
> I searched through the recent staticmem discussions to try to provide a
> helpful link for Carlo, but I don't think I managed to find what you had
> in mind. I found these two lock-related emails:
> 
> https://marc.info/?l=xen-devel&m=165476642832402
> https://marc.info/?l=xen-devel&m=165632461420257
> 
> If they are not relevant, could you please provide a few more details?

Those aren't the ones. The point is that count_info is a somewhat
odd field: It's not consistently updated under (all the same) lock,
and it's also not consistently updated atomically. Hence new
updates that appear in the code need properly justifying that the
way updates are done there doesn't conflict with any other of the
already existing updates.

Jan


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

* Re: [PATCH 01/12] xen/arm: add cache coloring initialization
  2022-08-26 12:51 ` [PATCH 01/12] xen/arm: add cache coloring initialization Carlo Nonato
@ 2022-09-26  6:20   ` Wei Chen
  2022-09-26  7:42     ` Jan Beulich
  2022-10-21 17:14   ` Julien Grall
  1 sibling, 1 reply; 60+ messages in thread
From: Wei Chen @ 2022-09-26  6:20 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Marco Solieri

Hi Carlo,

On 2022/8/26 20:51, Carlo Nonato wrote:
> This commit adds the cache coloring support initialization, Kconfig options,
> command line parameters and the initial documentation.
> The initialization consists of an auto probing of the cache layout
> necessary to retrieve the LLC way size which is used to compute the
> number of available colors. The Dom0 colors are then initialized with default
> colors (all available ones) if not provided from the command line, and
> they are checked for bad configuration.
> 
> It also adds a debug-key to dump general cache coloring info.
> This includes LLC way size, total available colors and the mask used to
> extract colors from physical addresses.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
>   docs/misc/arm/cache-coloring.rst     | 112 ++++++++++++++
>   docs/misc/xen-command-line.pandoc    |  22 +++
>   xen/arch/arm/Kconfig                 |  16 ++
>   xen/arch/arm/Makefile                |   1 +
>   xen/arch/arm/coloring.c              | 222 +++++++++++++++++++++++++++
>   xen/arch/arm/include/asm/coloring.h  |  31 ++++
>   xen/arch/arm/include/asm/processor.h |  16 ++
>   xen/arch/arm/setup.c                 |   8 +
>   8 files changed, 428 insertions(+)
>   create mode 100644 docs/misc/arm/cache-coloring.rst
>   create mode 100644 xen/arch/arm/coloring.c
>   create mode 100644 xen/arch/arm/include/asm/coloring.h
> 
> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> new file mode 100644
> index 0000000000..c7adcb0f1f
> --- /dev/null
> +++ b/docs/misc/arm/cache-coloring.rst
> @@ -0,0 +1,112 @@
> +Xen cache coloring user guide
> +=============================
> +
> +The cache coloring support in Xen allows to reserve Last Level Cache (LLC)
> +partition for Dom0, DomUs and Xen itself. Currently only ARM64 is supported.
> +
> +In order to enable and use it, few steps are needed.
> +
> +- Enable cache coloring in Xen configuration file.
> +
> +        CONFIG_CACHE_COLORING=y
> +- If needed, change the maximum number of colors in Xen configuration file
> +  (refer to menuconfig help for value meaning and when it should be changed).
> +
> +        CONFIG_MAX_CACHE_COLORS=<n>
> +- Assign colors to Dom0 using the `Color selection format`_ (see
> +  `Coloring parameters`_ for more documentation pointers).
> +
> +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.
> +
> +.. raw:: html
> +
> +    <pre>
> +                            Region j            Region j+1
> +                .....................   ............
> +                .                     . .
> +                .                       .
> +            _ _ _______________ _ _____________________ _ _
> +                |     |     |     |     |     |     |
> +                | c_0 | c_1 |     | c_n | c_0 | c_1 |
> +           _ _ _|_____|_____|_ _ _|_____|_____|_____|_ _ _
> +                    :                       :
> +                    :                       :...         ... .
> +                    :                            color 0
> +                    :...........................         ... .
> +                                                :
> +          . . ..................................:
> +    </pre>
> +
> +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
> +a 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 to the user to overcome failing situations
> +or for debugging/testing purposes. See `Coloring parameters`_ section for more
> +information on that.
> +
> +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]                               |
> ++---------------------+-----------------------------------+
> +
> +Coloring parameters
> +*******************
> +
> +LLC way size (as previously discussed) and Dom0 colors can be set using the
> +appropriate command line parameters. See the relevant documentation in
> +"docs/misc/xen-command-line.pandoc".
> \ No newline at end of file
> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> index 9a79385a37..910ebeb2eb 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -889,6 +889,14 @@ Controls for the dom0 IOMMU setup.
>   
>       Incorrect use of this option may result in a malfunctioning system.
>   
> +### dom0-colors (arm64)
> +> `= List of [ <integer> | <integer>-<integer> ]`
> +
> +> Default: `All available colors`
> +
> +Specify dom0 color configuration. If the parameter is not set, all available
> +colors are chosen and the user is warned on Xen's serial console.
> +
>   ### dom0_ioports_disable (x86)
>   > `= List of <hex>-<hex>`
>   
> @@ -1631,6 +1639,20 @@ 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-way-size (arm64)
> +> `= <size>`
> +
> +> Default: `Obtained from the hardware`
> +
> +Specify the way size of the Last Level Cache. This parameter is only useful with
> +cache coloring support enabled. It is an optional, expert-only parameter and it
> +is used to calculate the number of available 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.
> +
>   ### loglvl
>   > `= <level>[/<rate-limited level>]` where level is `none | error | warning | info | debug | all`
>   
> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> index 33e004d702..8acff9682c 100644
> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -131,6 +131,22 @@ config ARM64_BTI
>   	  Branch Target Identification support.
>   	  This feature is not supported in Xen.
>   
> +config CACHE_COLORING
> +	bool "Last Level Cache (LLC) coloring" if EXPERT
> +	default n
> +	depends on ARM_64
> +
> +config MAX_CACHE_COLORS
> +	int "Maximum number of cache colors"
> +	default 128
> +	range 0 65536

Just curious. Why select 128 as default vaule here? Is it a classic 
implmenntation for Arm64 cache? And the same question for the upper 
bound 65536.

> +	depends on CACHE_COLORING
> +	help
> +	  This config value is an upper bound for the actual number of cache colors
> +	  supported by the architecture. Xen preallocates this amount of cache
> +	  colors at boot. Note that if, at any time, a color configuration with more
> +	  colors than the maximum will be employed an error will be produced.
> +
>   config TEE
>   	bool "Enable TEE mediators support (UNSUPPORTED)" if UNSUPPORTED
>   	default n
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 4d076b278b..12940ba761 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -67,6 +67,7 @@ obj-$(CONFIG_SBSA_VUART_CONSOLE) += vpl011.o
>   obj-y += vsmc.o
>   obj-y += vpsci.o
>   obj-y += vuart.o
> +obj-$(CONFIG_CACHE_COLORING) += coloring.o
>   
>   extra-y += xen.lds
>   
> diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
> new file mode 100644
> index 0000000000..c010ebc01b
> --- /dev/null
> +++ b/xen/arch/arm/coloring.c
> @@ -0,0 +1,222 @@
> +/*
> + * xen/arch/arm/coloring.c
> + *
> + * Coloring support for ARM
> + *
> + * Copyright (C) 2019 Xilinx Inc.
> + *
> + * Authors:
> + *    Luca Miccio <lucmiccio@gmail.com>
> + *    Carlo Nonato <carlo.nonato@minervasys.tech>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <xen/errno.h>
> +#include <xen/keyhandler.h>
> +#include <xen/param.h>
> +#include <xen/types.h>
> +
> +#include <asm/coloring.h>
> +#include <asm/processor.h>
> +#include <asm/sysregs.h>
> +
> +/* Size of a LLC way */
> +static unsigned int llc_way_size;
> +/* Number of colors available in the LLC */
> +static unsigned int max_colors;
> +/* Mask to retrieve coloring relevant bits */
> +static uint64_t addr_col_mask;
> +

Maybe above variables can use __ro_after_init?

> +#define addr_to_color(addr) (((addr) & addr_col_mask) >> PAGE_SHIFT)
> +#define addr_set_color(addr, color) (((addr) & ~addr_col_mask) \
> +                                     | ((color) << PAGE_SHIFT))
> +
> +static unsigned int dom0_colors[CONFIG_MAX_CACHE_COLORS];
> +static unsigned int 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;
> +
> +    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 ||
> +                 *num_colors + end - start >= CONFIG_MAX_CACHE_COLORS )
> +                return -EINVAL;
> +            for ( color = start; color <= end; color++ )
> +                colors[(*num_colors)++] = color;
> +        }
> +        else
> +            s++;
> +    }
> +
> +    return *s ? -EINVAL : 0;
> +}
> +
> +size_param("llc-way-size", llc_way_size);
> +
> +static int __init parse_dom0_colors(const char *s)
> +{
> +    return parse_color_config(s, dom0_colors, &dom0_num_colors);
> +}
> +custom_param("dom0-colors", parse_dom0_colors);
> +
> +/* Return the LLC way size by probing the hardware */
> +static unsigned int 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 bool check_colors(unsigned int *colors, unsigned int num_colors)
> +{
> +    int i;

Can this one be unsigned int? just as you have done in 
set_default_domain_colors.

> +
> +    if ( num_colors > max_colors )
> +        return false;
> +
> +    for ( i = 0; i < num_colors; i++ )
> +        if ( colors[i] >= max_colors )
> +            return false;
> +
> +    return true;
> +}
> +
> +static unsigned int set_default_domain_colors(unsigned int *colors)
> +{
> +    unsigned int i;
> +
> +    if ( !colors )
> +        return 0;
> +
> +    for ( i = 0; i < max_colors; i++ )
> +        colors[i] = i;
> +    return max_colors;
> +}
> +
> +static void dump_coloring_info(unsigned char key)
> +{
> +    printk("'%c' pressed -> dumping coloring general info\n", key);
> +    printk("LLC way size: %u KiB\n", llc_way_size >> 10);
> +    printk("Number of LLC colors supported: %u\n", max_colors);
> +    printk("Address color mask: 0x%lx\n", addr_col_mask);
> +}
> +
> +bool __init 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;
> +    }
> +
> +    max_colors = llc_way_size / PAGE_SIZE;
> +    /* The maximum number of colors must be a power of 2 in order to correctly
> +       map colors to bits of an address. */

The style of this comment might need to be adjusted.

> +    ASSERT((max_colors & (max_colors - 1)) == 0);
> +    addr_col_mask = (max_colors - 1) << PAGE_SHIFT;
> +
> +    if ( !dom0_num_colors )
> +    {
> +        printk(XENLOG_WARNING
> +               "Dom0 color config not found. Using default (all colors)\n");
> +        dom0_num_colors = set_default_domain_colors(dom0_colors);
> +    }
> +
> +    if ( !check_colors(dom0_colors, dom0_num_colors) )
> +    {
> +        printk(XENLOG_ERR "Bad color config for Dom0\n");
> +        return false;
> +    }
> +
> +    register_keyhandler('K', dump_coloring_info, "dump coloring info", 1);
> +
> +    return true;
> +}
> +
> +/*
> + * 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/coloring.h b/xen/arch/arm/include/asm/coloring.h
> new file mode 100644
> index 0000000000..dd7eff5f07
> --- /dev/null
> +++ b/xen/arch/arm/include/asm/coloring.h
> @@ -0,0 +1,31 @@
> +/*
> + * xen/arm/include/asm/coloring.h
> + *
> + * Coloring support for ARM
> + *
> + * Copyright (C) 2019 Xilinx Inc.
> + *
> + * Authors:
> + *    Luca Miccio <lucmiccio@gmail.com>
> + *    Carlo Nonato <carlo.nonato@minervasys.tech>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __ASM_ARM_COLORING_H__
> +#define __ASM_ARM_COLORING_H__
> +
> +#include <xen/init.h>
> +
> +bool __init coloring_init(void);
> +
> +#endif /* !__ASM_ARM_COLORING_H__ */
> diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h
> index 1dd81d7d52..85ff0caf1e 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            0x7
> +#define CCSIDR_NUMSETS_SHIFT            13
> +#define CCSIDR_NUMSETS_MASK             0x3FFF
> +#define CCSIDR_NUMSETS_SHIFT_FEAT_CCIDX 32
> +#define CCSIDR_NUMSETS_MASK_FEAT_CCIDX  0xFFFFFF
> +
> +/* CCSELR Cache Size Selection Register */
> +#define CCSELR_LEVEL_MASK  0x7
> +#define CCSELR_LEVEL_SHIFT 1
> +
> +/* CLIDR Cache Level ID Register */
> +#define CLIDR_CTYPEn_SHIFT(n) (3 * (n - 1))
> +#define CLIDR_CTYPEn_MASK     0x7
> +#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/setup.c b/xen/arch/arm/setup.c
> index 500307edc0..c02f21c0e6 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -53,6 +53,9 @@
>   #include <asm/setup.h>
>   #include <xsm/xsm.h>
>   #include <asm/acpi.h>
> +#ifdef CONFIG_CACHE_COLORING
> +#include <asm/coloring.h>
> +#endif
>   
>   struct bootinfo __initdata bootinfo;
>   
> @@ -930,6 +933,11 @@ void __init start_xen(unsigned long boot_phys_offset,
>       printk("Command line: %s\n", cmdline);
>       cmdline_parse(cmdline);
>   
> +#ifdef CONFIG_CACHE_COLORING
> +    if ( !coloring_init() )
> +        panic("Xen Coloring support: setup failed\n");
> +#endif
> +
>       setup_mm();
>   
>       /* Parse the ACPI tables for possible boot-time configuration */


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-08-26 12:51 ` [PATCH 02/12] xen/arm: add cache coloring initialization for domains Carlo Nonato
@ 2022-09-26  6:39   ` Wei Chen
  2022-09-27 14:31     ` Carlo Nonato
  2022-10-21 17:25     ` Julien Grall
  2022-10-21 18:02   ` Julien Grall
  2022-10-21 18:04   ` Julien Grall
  2 siblings, 2 replies; 60+ messages in thread
From: Wei Chen @ 2022-09-26  6:39 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Marco Solieri



On 2022/8/26 20:51, Carlo Nonato wrote:
> This commit adds array pointers to domains as well as to the hypercall
> and configuration structure employed in domain creation. The latter is used
> both by the toolstack and by Xen itself to pass configuration data to the
> domain creation function, so the XEN_GUEST_HANDLE macro must be adopted to be
> able to access guest memory in the first case. This implies special care for
> the copy of the configuration data into the domain data, meaning that a
> discrimination variable for the two possible code paths (coming from Xen or
> from the toolstack) is needed.
> 
> The initialization and free functions for colored domains are also added.
> The former is responsible for allocating and populating the color array
> of the domain and it also checks for configuration issues. One of those
> issues is enabling both coloring and directmap for the domain because they
> contradicts one another. Since that, Dom0 must not be created with the
> directmap flag.
> The latter instead frees allocated memory.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
>   docs/misc/arm/cache-coloring.rst    |  7 ++--
>   xen/arch/arm/coloring.c             | 56 +++++++++++++++++++++++++++++
>   xen/arch/arm/domain.c               | 11 ++++++
>   xen/arch/arm/domain_build.c         | 13 +++++--
>   xen/arch/arm/include/asm/coloring.h |  7 ++++
>   xen/arch/arm/include/asm/domain.h   |  4 +++
>   xen/include/public/arch-arm.h       |  8 +++++
>   7 files changed, 102 insertions(+), 4 deletions(-)
> 
> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> index c7adcb0f1f..345d97cb56 100644
> --- a/docs/misc/arm/cache-coloring.rst
> +++ b/docs/misc/arm/cache-coloring.rst
> @@ -13,7 +13,7 @@ In order to enable and use it, few steps are needed.
>     (refer to menuconfig help for value meaning and when it should be changed).
>   
>           CONFIG_MAX_CACHE_COLORS=<n>
> -- Assign colors to Dom0 using the `Color selection format`_ (see
> +- Assign colors to domains using the `Color selection format`_ (see
>     `Coloring parameters`_ for more documentation pointers).
>   
>   Background
> @@ -109,4 +109,7 @@ Coloring parameters
>   
>   LLC way size (as previously discussed) and Dom0 colors can be set using the
>   appropriate command line parameters. See the relevant documentation in
> -"docs/misc/xen-command-line.pandoc".
> \ No newline at end of file
> +"docs/misc/xen-command-line.pandoc".
> +
> +Note that if no color configuration is provided for domains, they fallback to
> +the default one, which corresponds simply to all available colors.
> \ No newline at end of file
> diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
> index c010ebc01b..2b37cda067 100644
> --- a/xen/arch/arm/coloring.c
> +++ b/xen/arch/arm/coloring.c
> @@ -22,6 +22,7 @@
>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>    */
>   #include <xen/errno.h>
> +#include <xen/guest_access.h>
>   #include <xen/keyhandler.h>
>   #include <xen/param.h>
>   #include <xen/types.h>
> @@ -211,6 +212,61 @@ bool __init coloring_init(void)
>       return true;
>   }
>   
> +int domain_coloring_init(struct domain *d,
> +                         const struct xen_arch_domainconfig *config)
> +{
> +    if ( is_domain_direct_mapped(d) )
> +    {
> +        printk(XENLOG_ERR
> +               "Can't enable coloring and directmap at the same time for %pd\n",
> +               d);
> +        return -EINVAL;
> +    }
> +
> +    if ( is_hardware_domain(d) )
> +    {
> +        d->arch.colors = dom0_colors;
> +        d->arch.num_colors = dom0_num_colors;
> +    }
> +    else if ( config->num_colors == 0 )
> +    {
> +        printk(XENLOG_WARNING
> +               "Color config not found for %pd. Using default\n", d);
> +        d->arch.colors = xzalloc_array(unsigned int, max_colors);
> +        d->arch.num_colors = set_default_domain_colors(d->arch.colors);
> +    }
> +    else
> +    {
> +        d->arch.colors = xzalloc_array(unsigned int, config->num_colors);
> +        d->arch.num_colors = config->num_colors;
> +        if ( config->from_guest )
> +            copy_from_guest(d->arch.colors, config->colors, config->num_colors);
> +        else
> +            memcpy(d->arch.colors, config->colors.p,
> +                   sizeof(unsigned int) * config->num_colors);
> +    }
> +
> +    if ( !d->arch.colors )
> +    {
> +        printk(XENLOG_ERR "Colors allocation failed for %pd\n", d);
> +        return -ENOMEM;
> +    }
> +
> +    if ( !check_colors(d->arch.colors, d->arch.num_colors) )
> +    {

If we add xfree(d->arch.colors) here for non-hw domains, is it possible 
to make this function have a complete fallback process? And I know 
currently, this is handled in domain_coloring_free.

Cheers,
Wei Chen

> +        printk(XENLOG_ERR "Bad color config for %pd\n", d);
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +void domain_coloring_free(struct domain *d)
> +{
> +    if ( !is_hardware_domain(d) )
> +        xfree(d->arch.colors);
> +}
> +
>   /*
>    * Local variables:
>    * mode: C
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 2d6253181a..c6fa8adc99 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -23,6 +23,9 @@
>   #include <xen/wait.h>
>   
>   #include <asm/alternative.h>
> +#ifdef CONFIG_CACHE_COLORING
> +#include <asm/coloring.h>
> +#endif
>   #include <asm/cpuerrata.h>
>   #include <asm/cpufeature.h>
>   #include <asm/current.h>
> @@ -712,6 +715,11 @@ int arch_domain_create(struct domain *d,
>       ioreq_domain_init(d);
>   #endif
>   
> +#ifdef CONFIG_CACHE_COLORING
> +    if ( (rc = domain_coloring_init(d, &config->arch)) )
> +        goto fail;
> +#endif
> +
>       /* p2m_init relies on some value initialized by the IOMMU subsystem */
>       if ( (rc = iommu_domain_init(d, config->iommu_opts)) != 0 )
>           goto fail;
> @@ -807,6 +815,9 @@ void arch_domain_destroy(struct domain *d)
>                          get_order_from_bytes(d->arch.efi_acpi_len));
>   #endif
>       domain_io_free(d);
> +#ifdef CONFIG_CACHE_COLORING
> +    domain_coloring_free(d);
> +#endif
>   }
>   
>   void arch_domain_shutdown(struct domain *d)
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 3fd1186b53..4d4cb692fc 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -33,6 +33,12 @@
>   #include <xen/grant_table.h>
>   #include <xen/serial.h>
>   
> +#ifdef CONFIG_CACHE_COLORING
> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged
> +#else
> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged | CDF_directmap
> +#endif
> +
>   static unsigned int __initdata opt_dom0_max_vcpus;
>   integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
>   
> @@ -3399,7 +3405,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_ENABLED(CONFIG_CACHE_COLORING) )
> +        allocate_memory(d, &kinfo);
> +    else
> +        allocate_memory_11(d, &kinfo);
>       find_gnttab_region(d, &kinfo);
>   
>       /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
> @@ -3455,7 +3464,7 @@ void __init create_dom0(void)
>       if ( iommu_enabled )
>           dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu;
>   
> -    dom0 = domain_create(0, &dom0_cfg, CDF_privileged | CDF_directmap);
> +    dom0 = domain_create(0, &dom0_cfg, XEN_DOM0_CREATE_FLAGS);
>       if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
>           panic("Error creating domain 0\n");
>   
> diff --git a/xen/arch/arm/include/asm/coloring.h b/xen/arch/arm/include/asm/coloring.h
> index dd7eff5f07..60c8b1f079 100644
> --- a/xen/arch/arm/include/asm/coloring.h
> +++ b/xen/arch/arm/include/asm/coloring.h
> @@ -25,7 +25,14 @@
>   #define __ASM_ARM_COLORING_H__
>   
>   #include <xen/init.h>
> +#include <xen/sched.h>
> +
> +#include <public/arch-arm.h>
>   
>   bool __init coloring_init(void);
>   
> +int domain_coloring_init(struct domain *d,
> +                         const struct xen_arch_domainconfig *config);
> +void domain_coloring_free(struct domain *d);
> +
>   #endif /* !__ASM_ARM_COLORING_H__ */
> diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
> index 26a8348eed..291f7c375d 100644
> --- a/xen/arch/arm/include/asm/domain.h
> +++ b/xen/arch/arm/include/asm/domain.h
> @@ -58,6 +58,10 @@ struct arch_domain
>   #ifdef CONFIG_ARM_64
>       enum domain_type type;
>   #endif
> +#ifdef CONFIG_CACHE_COLORING
> +    unsigned int *colors;
> +    unsigned int num_colors;
> +#endif
>   
>       /* Virtual MMU */
>       struct p2m_domain p2m;
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index c8b6058d3a..adf843a7a1 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -314,6 +314,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
>   #define XEN_DOMCTL_CONFIG_TEE_NONE      0
>   #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
>   
> +__DEFINE_XEN_GUEST_HANDLE(color_t, unsigned int);
> +
>   struct xen_arch_domainconfig {
>       /* IN/OUT */
>       uint8_t gic_version;
> @@ -335,6 +337,12 @@ struct xen_arch_domainconfig {
>        *
>        */
>       uint32_t clock_frequency;
> +    /* IN */
> +    uint8_t from_guest;
> +    /* IN */
> +    uint16_t num_colors;
> +    /* IN */
> +    XEN_GUEST_HANDLE(color_t) colors;
>   };
>   #endif /* __XEN__ || __XEN_TOOLS__ */
>   


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

* Re: [PATCH 01/12] xen/arm: add cache coloring initialization
  2022-09-26  6:20   ` Wei Chen
@ 2022-09-26  7:42     ` Jan Beulich
  2022-09-27 14:31       ` Carlo Nonato
  0 siblings, 1 reply; 60+ messages in thread
From: Jan Beulich @ 2022-09-26  7:42 UTC (permalink / raw)
  To: Wei Chen, Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 26.09.2022 08:20, Wei Chen wrote:
> On 2022/8/26 20:51, Carlo Nonato wrote:
>> --- a/xen/arch/arm/Kconfig
>> +++ b/xen/arch/arm/Kconfig
>> @@ -131,6 +131,22 @@ config ARM64_BTI
>>   	  Branch Target Identification support.
>>   	  This feature is not supported in Xen.
>>   
>> +config CACHE_COLORING
>> +	bool "Last Level Cache (LLC) coloring" if EXPERT
>> +	default n

No need for this line, btw.

>> +	depends on ARM_64
>> +
>> +config MAX_CACHE_COLORS
>> +	int "Maximum number of cache colors"
>> +	default 128
>> +	range 0 65536
> 
> Just curious. Why select 128 as default vaule here? Is it a classic 
> implmenntation for Arm64 cache? And the same question for the upper 
> bound 65536.

Going beyond that: What is the meaning of the user picking 0 here?
And isn't 1 merely mapping to the allocator we have, i.e. the
CACHE_COLORING=n case? IOW shouldn't the lowe bound of the range
be (at least) 2?

Jan


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

* Re: [PATCH 01/12] xen/arm: add cache coloring initialization
  2022-09-26  7:42     ` Jan Beulich
@ 2022-09-27 14:31       ` Carlo Nonato
  0 siblings, 0 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-09-27 14:31 UTC (permalink / raw)
  To: Jan Beulich, Wei Chen, xen-devel
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Jan, Wei

On Mon, Sep 26, 2022 at 9:42 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 26.09.2022 08:20, Wei Chen wrote:
> > On 2022/8/26 20:51, Carlo Nonato wrote:
> >> --- a/xen/arch/arm/Kconfig
> >> +++ b/xen/arch/arm/Kconfig
> >> @@ -131,6 +131,22 @@ config ARM64_BTI
> >>        Branch Target Identification support.
> >>        This feature is not supported in Xen.
> >>
> >> +config CACHE_COLORING
> >> +    bool "Last Level Cache (LLC) coloring" if EXPERT
> >> +    default n
>
> No need for this line, btw.
>
> >> +    depends on ARM_64
> >> +
> >> +config MAX_CACHE_COLORS
> >> +    int "Maximum number of cache colors"
> >> +    default 128
> >> +    range 0 65536
> >
> > Just curious. Why select 128 as default vaule here? Is it a classic
> > implmenntation for Arm64 cache? And the same question for the upper
> > bound 65536.
>
> Going beyond that: What is the meaning of the user picking 0 here?
> And isn't 1 merely mapping to the allocator we have, i.e. the
> CACHE_COLORING=n case? IOW shouldn't the lowe bound of the range
> be (at least) 2?

To answer both: I used "range" for two reasons:
 - to forbid negative numbers.
 - struct xen_arch_domainconfig can't be modified freely since it must
   respect some static build assertions on its size, which means that
   I'm bound to uint16_t for the "num_colors" field (see patch #2).
   Also, looking again at this, the range should end at 65535.
0 and 1 maximum colors aren't really meaningful as Jan said.
65536 is just a "big enough" number that shouldn't be possible to ever
reach (it corresponds, in "common conditions", to 4 GiB of cache. See docs or
below for the formula).
128 is also a high value since using 4 KiB pages and 16-ways cache,
it implies a 128 * 4 KiB * 16 = 8 MiB Last Level Cache.
Remember that this isn't the actual number of colors of the platform. It just
needs to be >= the actual value (which is computed from the probed LLC way
size or the command line provided one).

> Jan

Thanks.

- Carlo Nonato


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-09-26  6:39   ` Wei Chen
@ 2022-09-27 14:31     ` Carlo Nonato
  2022-10-21 17:25     ` Julien Grall
  1 sibling, 0 replies; 60+ messages in thread
From: Carlo Nonato @ 2022-09-27 14:31 UTC (permalink / raw)
  To: Wei Chen, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Marco Solieri

Hi Wei,

On Mon, Sep 26, 2022 at 8:39 AM Wei Chen <Wei.Chen@arm.com> wrote:
> On 2022/8/26 20:51, Carlo Nonato wrote:
> > +int domain_coloring_init(struct domain *d,
> > +                         const struct xen_arch_domainconfig *config)
> > +{
> > +    if ( is_domain_direct_mapped(d) )
> > +    {
> > +        printk(XENLOG_ERR
> > +               "Can't enable coloring and directmap at the same time for %pd\n",
> > +               d);
> > +        return -EINVAL;
> > +    }
> > +
> > +    if ( is_hardware_domain(d) )
> > +    {
> > +        d->arch.colors = dom0_colors;
> > +        d->arch.num_colors = dom0_num_colors;
> > +    }
> > +    else if ( config->num_colors == 0 )
> > +    {
> > +        printk(XENLOG_WARNING
> > +               "Color config not found for %pd. Using default\n", d);
> > +        d->arch.colors = xzalloc_array(unsigned int, max_colors);
> > +        d->arch.num_colors = set_default_domain_colors(d->arch.colors);
> > +    }
> > +    else
> > +    {
> > +        d->arch.colors = xzalloc_array(unsigned int, config->num_colors);
> > +        d->arch.num_colors = config->num_colors;
> > +        if ( config->from_guest )
> > +            copy_from_guest(d->arch.colors, config->colors, config->num_colors);
> > +        else
> > +            memcpy(d->arch.colors, config->colors.p,
> > +                   sizeof(unsigned int) * config->num_colors);
> > +    }
> > +
> > +    if ( !d->arch.colors )
> > +    {
> > +        printk(XENLOG_ERR "Colors allocation failed for %pd\n", d);
> > +        return -ENOMEM;
> > +    }
> > +
> > +    if ( !check_colors(d->arch.colors, d->arch.num_colors) )
> > +    {
>
> If we add xfree(d->arch.colors) here for non-hw domains, is it possible
> to make this function have a complete fallback process? And I know
> currently, this is handled in domain_coloring_free.

Yes, you're right. Added.

> Cheers,
> Wei Chen

Thanks.

- Carlo Nonato


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

* Re: [PATCH 12/12] xen/arm: add cache coloring support for Xen
  2022-09-19  8:38       ` Jan Beulich
@ 2022-09-27 14:31         ` Carlo Nonato
  2022-09-27 15:28           ` Jan Beulich
  0 siblings, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-09-27 14:31 UTC (permalink / raw)
  To: Jan Beulich
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

Hi Jan,

On Mon, Sep 19, 2022 at 10:38 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 16.09.2022 18:07, Carlo Nonato wrote:
> > On Thu, Sep 15, 2022 at 3:25 PM Jan Beulich <jbeulich@suse.com> wrote:
> >> On 26.08.2022 14:51, Carlo Nonato wrote:
> >>> @@ -218,6 +221,28 @@ void *__vmap(const mfn_t *mfn, unsigned int granularity,
> >>>      return va;
> >>>  }
> >>>
> >>> +#ifdef CONFIG_CACHE_COLORING
> >>> +void * __vmap_colored(const mfn_t *mfn, unsigned int nr, unsigned int align,
> >>> +                      unsigned int flags, enum vmap_region type)
> >>> +{
> >>> +    void *va = vm_alloc(nr, align, type);
> >>> +    unsigned long cur = (unsigned long)va;
> >>> +    paddr_t pa = mfn_to_maddr(*mfn);
> >>> +
> >>> +    for ( ; va && nr-- ; cur += PAGE_SIZE )
> >>> +    {
> >>> +        pa = next_xen_colored(pa);
> >>
> >> This may alter the address, yet the caller expects that the original
> >> address be mapped. I must be missing something?
> >
> > If the original address color is assigned to Xen, then next_xen_colored()
> > simply returns that address. If this isn't the case, then you're right: the
> > address changes to the correct, colored, one. The caller should expect
> > this behavior since this is the colored version of vmap, the one that takes
> > into account the Xen coloring configuration.
>
> That's (to me at least) very surprising behavior, and hence needs
> properly calling out in a code comment at the least.
>
> Personally I'm not convinced of having a function with this behavior,
> and instead I think the normal vmap() should do. As long as you're
> only allowing for order-0 allocations, that shouldn't be an issue
> anyway.

You mean creating an array of colored mfns (I mean with a colored machine
address) and passing it to vmap()? Am I understanding you correctly?
This is the only way I can see to use the original vmap() and respect
the coloring configuration at the same time. But isn't it a waste of time
and space to create this array?

> Jan

Thanks.

- Carlo Nonato


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

* Re: [PATCH 12/12] xen/arm: add cache coloring support for Xen
  2022-09-27 14:31         ` Carlo Nonato
@ 2022-09-27 15:28           ` Jan Beulich
  0 siblings, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2022-09-27 15:28 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 27.09.2022 16:31, Carlo Nonato wrote:
> On Mon, Sep 19, 2022 at 10:38 AM Jan Beulich <jbeulich@suse.com> wrote:
>> On 16.09.2022 18:07, Carlo Nonato wrote:
>>> On Thu, Sep 15, 2022 at 3:25 PM Jan Beulich <jbeulich@suse.com> wrote:
>>>> On 26.08.2022 14:51, Carlo Nonato wrote:
>>>>> @@ -218,6 +221,28 @@ void *__vmap(const mfn_t *mfn, unsigned int granularity,
>>>>>      return va;
>>>>>  }
>>>>>
>>>>> +#ifdef CONFIG_CACHE_COLORING
>>>>> +void * __vmap_colored(const mfn_t *mfn, unsigned int nr, unsigned int align,
>>>>> +                      unsigned int flags, enum vmap_region type)
>>>>> +{
>>>>> +    void *va = vm_alloc(nr, align, type);
>>>>> +    unsigned long cur = (unsigned long)va;
>>>>> +    paddr_t pa = mfn_to_maddr(*mfn);
>>>>> +
>>>>> +    for ( ; va && nr-- ; cur += PAGE_SIZE )
>>>>> +    {
>>>>> +        pa = next_xen_colored(pa);
>>>>
>>>> This may alter the address, yet the caller expects that the original
>>>> address be mapped. I must be missing something?
>>>
>>> If the original address color is assigned to Xen, then next_xen_colored()
>>> simply returns that address. If this isn't the case, then you're right: the
>>> address changes to the correct, colored, one. The caller should expect
>>> this behavior since this is the colored version of vmap, the one that takes
>>> into account the Xen coloring configuration.
>>
>> That's (to me at least) very surprising behavior, and hence needs
>> properly calling out in a code comment at the least.
>>
>> Personally I'm not convinced of having a function with this behavior,
>> and instead I think the normal vmap() should do. As long as you're
>> only allowing for order-0 allocations, that shouldn't be an issue
>> anyway.
> 
> You mean creating an array of colored mfns (I mean with a colored machine
> address) and passing it to vmap()? Am I understanding you correctly?

Yes.

> This is the only way I can see to use the original vmap() and respect
> the coloring configuration at the same time. But isn't it a waste of time
> and space to create this array?

Well, that's the price to pay for non-contiguous vmap-s. If the added
function really is just an optimization, I guess this might be acceptable
if actually stated that way in the description. I intentionally say
"might", because I think there's too heavy an implications here (the
caller having done the allocation(s) in a way that matches the function's
behavior).

Jan


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-09-19  6:26       ` Jan Beulich
  2022-09-19 22:42         ` Stefano Stabellini
@ 2022-10-13  9:47         ` Carlo Nonato
  2022-10-13 10:44           ` Jan Beulich
  1 sibling, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-10-13  9:47 UTC (permalink / raw)
  To: Jan Beulich, xen-devel
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Jan


On Mon, Sep 19, 2022 at 8:26 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 16.09.2022 18:05, Carlo Nonato wrote:
> > On Thu, Sep 15, 2022 at 3:13 PM Jan Beulich <jbeulich@suse.com> wrote:
> >> On 26.08.2022 14:51, Carlo Nonato wrote:
> >>> --- a/xen/arch/arm/coloring.c
> >>> +++ b/xen/arch/arm/coloring.c
> >>> @@ -300,6 +300,16 @@ void prepare_color_domain_config(struct xen_arch_domainconfig *config,
> >>>      config->num_colors = (uint16_t)num;
> >>>  }
> >>>
> >>> +unsigned int page_to_color(struct page_info *pg)
> >>
> >> The parameter will want to be pointer-to-const and I wonder whether ...
> >>
> >>> +{
> >>> +    return addr_to_color(page_to_maddr(pg));
> >>> +}
> >>
> >> ... the function as a whole wouldn't be a good candidate for being an
> >> inline one (requiring addr_to_color() to be available in outside of
> >> this file, of course).
> >
> > You mean defining it as static inline in the coloring.h header?
>
> That would seem preferable for a simple function like this one.
>

I didn't want to expose that function since I would also have to expose
the addr_col_mask global variable.
Same goes for get_max_colors(): it exist only for the purpose to restrict
the max_colors variable visibility.

> >>> +    page_list_for_each( pos, head )
> >>> +    {
> >>> +        if ( page_to_maddr(pos) < page_to_maddr(pg) )
> >>> +        {
> >>> +            head = &pos->list;
> >>> +            break;
> >>> +        }
> >>> +    }
> >>
> >> Wait - a linear search for every single page insertion? How well
> >> is that going to perform on a multi-terabyte system?
> >
> > For our test cases (embedded systems) the linear search is good enough.
> > I agree with you that in the general case this is bad (even though the main
> > targets are indeed embedded systems).
> > Are there any already available data structures that we can exploit to get
> > better performances?
>
> I'm afraid there aren't any that I would see as a good fit here.
>

Regarding this I can see three options:
1) We leave it as it is and we warn the user in the docs that cache coloring
   is embedded system specific for the moment since it has, probably, bad
   performances with bigger systems.
2) We use some priority queue implementation to replace the actual lists.
   Red/black trees are available in Xen codebase, but I think I would have
   to change the page_info struct to use them.
   Maybe just a binary heap implemented as an array could be viable, but that
   would require me to implement somewhere the logic for insertion,
   extract-min and other operations.
3) I have a working prototype of a buddy allocator that also makes use of
   coloring information. It isn't an extension of the main one, but rather a
   simpler version. This means that nodes, zones, scrubbing, aren't
   supported, but this is true also for the already submitted colored
   allocator. With this, order > 0 pages can be served (up until
   log2(max_colors)) and insertion is no more linear, but constant instead.

>
> Jan

Thanks

- Carlo Nonato


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-10-13  9:47         ` Carlo Nonato
@ 2022-10-13 10:44           ` Jan Beulich
  0 siblings, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2022-10-13 10:44 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, julien, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 13.10.2022 11:47, Carlo Nonato wrote:
> On Mon, Sep 19, 2022 at 8:26 AM Jan Beulich <jbeulich@suse.com> wrote:
>> On 16.09.2022 18:05, Carlo Nonato wrote:
>>> On Thu, Sep 15, 2022 at 3:13 PM Jan Beulich <jbeulich@suse.com> wrote:
>>>> On 26.08.2022 14:51, Carlo Nonato wrote:
>>>>> --- a/xen/arch/arm/coloring.c
>>>>> +++ b/xen/arch/arm/coloring.c
>>>>> @@ -300,6 +300,16 @@ void prepare_color_domain_config(struct xen_arch_domainconfig *config,
>>>>>      config->num_colors = (uint16_t)num;
>>>>>  }
>>>>>
>>>>> +unsigned int page_to_color(struct page_info *pg)
>>>>
>>>> The parameter will want to be pointer-to-const and I wonder whether ...
>>>>
>>>>> +{
>>>>> +    return addr_to_color(page_to_maddr(pg));
>>>>> +}
>>>>
>>>> ... the function as a whole wouldn't be a good candidate for being an
>>>> inline one (requiring addr_to_color() to be available in outside of
>>>> this file, of course).
>>>
>>> You mean defining it as static inline in the coloring.h header?
>>
>> That would seem preferable for a simple function like this one.
>>
> 
> I didn't want to expose that function since I would also have to expose
> the addr_col_mask global variable.
> Same goes for get_max_colors(): it exist only for the purpose to restrict
> the max_colors variable visibility.

Ah yes, that's a good reason to keep the function out-of-line.

>>>>> +    page_list_for_each( pos, head )
>>>>> +    {
>>>>> +        if ( page_to_maddr(pos) < page_to_maddr(pg) )
>>>>> +        {
>>>>> +            head = &pos->list;
>>>>> +            break;
>>>>> +        }
>>>>> +    }
>>>>
>>>> Wait - a linear search for every single page insertion? How well
>>>> is that going to perform on a multi-terabyte system?
>>>
>>> For our test cases (embedded systems) the linear search is good enough.
>>> I agree with you that in the general case this is bad (even though the main
>>> targets are indeed embedded systems).
>>> Are there any already available data structures that we can exploit to get
>>> better performances?
>>
>> I'm afraid there aren't any that I would see as a good fit here.
>>
> 
> Regarding this I can see three options:
> 1) We leave it as it is and we warn the user in the docs that cache coloring
>    is embedded system specific for the moment since it has, probably, bad
>    performances with bigger systems.

I could live with this as long as it's stated prominently enough, but ...

> 2) We use some priority queue implementation to replace the actual lists.
>    Red/black trees are available in Xen codebase, but I think I would have
>    to change the page_info struct to use them.
>    Maybe just a binary heap implemented as an array could be viable, but that
>    would require me to implement somewhere the logic for insertion,
>    extract-min and other operations.
> 3) I have a working prototype of a buddy allocator that also makes use of
>    coloring information. It isn't an extension of the main one, but rather a
>    simpler version. This means that nodes, zones, scrubbing, aren't
>    supported, but this is true also for the already submitted colored
>    allocator. With this, order > 0 pages can be served (up until
>    log2(max_colors)) and insertion is no more linear, but constant instead.

... this sounds even more promising, not the least because it also eliminates
yet another shortcoming we've talked about already. In fact I would expect
that log2(max_colors) doesn't need to be the limit either, as you'd cycle
back to the first color anyway once you've reached the last one.

Jan


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-08-26 12:51 ` [PATCH 06/12] xen/common: add cache coloring allocator for domains Carlo Nonato
  2022-09-15 13:13   ` Jan Beulich
@ 2022-10-17  7:06   ` Michal Orzel
  2022-10-17  8:44     ` Julien Grall
  1 sibling, 1 reply; 60+ messages in thread
From: Michal Orzel @ 2022-10-17  7:06 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, julien,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Marco Solieri

Hi Carlo,

On 26/08/2022 14:51, Carlo Nonato wrote:

> 
> This commit adds a new memory page allocator that implements the cache
> coloring mechanism. The allocation algorithm follows the given color
> configuration of the domain and maximizes contiguity in the page selection.
> 
> Pages are stored in a color-indexed data structure of lists, sorted by their
> machine addresses, that are collectively called the colored heap. A simple
> initialization function computes the color of any available page and inserts
> it in the corresponding list. When a domain requests a page, the allocator
> takes one from the subset of lists whose colors equals the domain
> configuration. It chooses the page with the highest machine address such that
> contiguous pages are sequentially allocated, if this is made possible by a
> color assignment which includes adjacent colors.
> 
> The allocator can handle only requests with order equals to 0 since the
> single color granularity is represented in memory by one page.
> 
> 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.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
>  docs/misc/arm/cache-coloring.rst    |  43 +++++-
>  docs/misc/xen-command-line.pandoc   |  14 ++
>  xen/arch/arm/Kconfig                |  12 ++
>  xen/arch/arm/coloring.c             |  10 ++
>  xen/arch/arm/include/asm/coloring.h |   6 +
>  xen/arch/arm/include/asm/mm.h       |   3 +
>  xen/common/page_alloc.c             | 213 ++++++++++++++++++++++++++--
>  7 files changed, 290 insertions(+), 11 deletions(-)
> 
> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> index 763acd2d3f..5f9132e525 100644
> --- a/docs/misc/arm/cache-coloring.rst
> +++ b/docs/misc/arm/cache-coloring.rst
> @@ -13,6 +13,9 @@ In order to enable and use it, few steps are needed.
>    (refer to menuconfig help for value meaning and when it should be changed).
> 
>          CONFIG_MAX_CACHE_COLORS=<n>
> +- If needed, change the amount of memory reserved for the buddy allocator either
> +  from the Xen configuration file, via the CONFIG_BUDDY_ALLOCATOR_SIZE value,
> +  or with the command line option. See `Colored allocator and buddy allocator`.
>  - Assign colors to domains using the `Color selection format`_ (see
>    `Coloring parameters`_ for more documentation pointers).
> 
> @@ -157,4 +160,42 @@ Please refer to the relative documentation in
>  "docs/misc/arm/device-tree/booting.txt".
> 
>  Note that if no color configuration is provided for domains, they fallback to
> -the default one, which corresponds simply to all available colors.
> \ No newline at end of file
> +the default one, which corresponds simply to all available colors.
> +
> +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 systems is not colored yet, we need to support the coexistence of
> +the two allocators and some memory must be left for the buddy one.
> +The buddy allocator memory can be reserved from the Xen configuration file or
> +with the help of a command-line option.
> +
> +Known issues and limitations
> +****************************
> +
> +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 a order-1 page, four colors correspond to
> +a order-2 pages, etc.
> +
> +Fail to boot colored DomUs with large memory size
> +#################################################
> +
> +If the Linux kernel used for Dom0 does not contain the upstream commit
> +3941552aec1e04d63999988a057ae09a1c56ebeb and uses the hypercall buffer device,
> +colored DomUs with memory size larger then 127 MB cannot be created. This is
> +caused by the default limit of this buffer of 64 pages. The solution is to
> +manually apply the above patch, or to check if there is an updated version of
> +the kernel in use for Dom0 that contains this change.
> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> index 910ebeb2eb..4e85c4dfe4 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -299,6 +299,20 @@ can be maintained with the pv-shim mechanism.
>      cause Xen not to use Indirect Branch Tracking even when support is
>      available in hardware.
> 
> +### 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 cache 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.
> +
>  ### clocksource (x86)
>  > `= pit | hpet | acpi | tsc`
> 
> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> index 8acff9682c..abce4bfc25 100644
> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -147,6 +147,18 @@ config MAX_CACHE_COLORS
>           colors at boot. Note that if, at any time, a color configuration with more
>           colors than the maximum will be employed an error will be produced.
> 
> +config BUDDY_ALLOCATOR_SIZE
> +       string "Buddy allocator reserved memory size" if CACHE_COLORING
> +       default "64M" if CACHE_COLORING
> +       default "0M" if !CACHE_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 systems is not
> +         colored yet, we need to support the coexistence of the two allocators and
> +         some memory must be left for the buddy one.
> +
>  config TEE
>         bool "Enable TEE mediators support (UNSUPPORTED)" if UNSUPPORTED
>         default n
> diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
> index 87e20b952e..3fb86043d1 100644
> --- a/xen/arch/arm/coloring.c
> +++ b/xen/arch/arm/coloring.c
> @@ -300,6 +300,16 @@ void prepare_color_domain_config(struct xen_arch_domainconfig *config,
>      config->num_colors = (uint16_t)num;
>  }
> 
> +unsigned int page_to_color(struct page_info *pg)
> +{
> +    return addr_to_color(page_to_maddr(pg));
> +}
> +
> +unsigned int get_max_colors(void)
> +{
> +    return max_colors;
> +}
> +
>  /*
>   * Local variables:
>   * mode: C
> diff --git a/xen/arch/arm/include/asm/coloring.h b/xen/arch/arm/include/asm/coloring.h
> index b7fa323870..0982bc9853 100644
> --- a/xen/arch/arm/include/asm/coloring.h
> +++ b/xen/arch/arm/include/asm/coloring.h
> @@ -29,6 +29,8 @@
> 
>  #include <public/arch-arm.h>
> 
> +struct page_info;
> +
>  bool __init coloring_init(void);
> 
>  int domain_coloring_init(struct domain *d,
> @@ -39,4 +41,8 @@ void domain_dump_coloring_info(struct domain *d);
>  void prepare_color_domain_config(struct xen_arch_domainconfig *config,
>                                   const char *colors_str);
> 
> +unsigned int page_to_color(struct page_info *pg);
> +
> +unsigned int get_max_colors(void);
> +
>  #endif /* !__ASM_ARM_COLORING_H__ */
> diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
> index da25251cda..a59fc3791a 100644
> --- a/xen/arch/arm/include/asm/mm.h
> +++ b/xen/arch/arm/include/asm/mm.h
> @@ -143,6 +143,9 @@ struct page_info
>  #define PGC_count_width   PG_shift(10)
>  #define PGC_count_mask    ((1UL<<PGC_count_width)-1)
> 
> +#define _PGC_colored      PG_shift(11)
> +#define PGC_colored       PG_mask(1, 11)
> +
>  /*
>   * Page needs to be scrubbed. Since this bit can only be set on a page that is
>   * free (i.e. in PGC_state_free) we can reuse PGC_allocated bit.
> diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
> index bfd4150be7..4ae3cfe9a7 100644
> --- a/xen/common/page_alloc.c
> +++ b/xen/common/page_alloc.c
> @@ -150,6 +150,9 @@
>  #define p2m_pod_offline_or_broken_hit(pg) 0
>  #define p2m_pod_offline_or_broken_replace(pg) BUG_ON(pg != NULL)
>  #endif
> +#ifdef CONFIG_CACHE_COLORING
> +#include <asm/coloring.h>
> +#endif
> 
>  #ifndef PGC_static
>  #define PGC_static 0
> @@ -231,6 +234,9 @@ static bool __read_mostly scrub_debug;
>  #define scrub_debug    false
>  #endif
> 
> +/* Memory required for buddy allocator to work with colored one */
> +static unsigned long __initdata buddy_alloc_size;
> +
>  /*
>   * Bit width of the DMA heap -- used to override NUMA-node-first.
>   * allocation strategy, which can otherwise exhaust low memory.
> @@ -440,7 +446,172 @@ mfn_t __init alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
>      BUG();
>  }
> 
> +static DEFINE_SPINLOCK(heap_lock);
> 
> +/* 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);
> +}
> +
> +static bool is_page_colored(struct page_info *pg)
> +{
> +    return pg->count_info & PGC_colored;
> +}
> +
> +#ifdef CONFIG_CACHE_COLORING
> +/*************************
> + * COLORED SIDE-ALLOCATOR
> + *
> + * Pages are stored by their color in separate lists. Each list defines a color
> + * and it is initialized during end_boot_allocator, where each page's color
> + * is calculated and the page itself is put in the correct list.
> + * After initialization there will be N lists where N is the number of maximum
> + * available colors on the platform.
> + */
> +typedef struct page_list_head colored_pages_t;
> +static colored_pages_t __ro_after_init *color_heap;
> +
> +#define colored_pages(color) &color_heap[(color)]
> +
> +static void color_heap_insert_page(struct page_info *pg)
> +{
> +    struct page_info *pos;
> +    struct page_list_head *head = colored_pages(page_to_color(pg));
> +
> +    pg->count_info |= PGC_colored;
> +
> +    /* Insert page in list in ascending machine address order */
> +    page_list_for_each( pos, head )
> +    {
> +        if ( page_to_maddr(pos) < page_to_maddr(pg) )
> +        {
> +            head = &pos->list;
> +            break;
> +        }
> +    }
> +
> +    page_list_add_tail(pg, head);
> +}
> +
> +static void color_heap_remove_page(struct page_info *pg)
> +{
> +    page_list_del(pg, colored_pages(page_to_color(pg)));
> +}
> +
> +static void __init init_col_heap_pages(struct page_info *pg,
> +                                       unsigned long nr_pages)
> +{
> +    unsigned int i;
> +
> +    if ( !color_heap )
> +    {
> +        unsigned int max_colors = get_max_colors();
> +        color_heap = xmalloc_array(colored_pages_t, max_colors);
> +        BUG_ON(!color_heap);
> +
> +        for ( i = 0; i < max_colors; i++ )
> +            INIT_PAGE_LIST_HEAD(colored_pages(i));
> +
> +        if ( !buddy_alloc_size )
> +            buddy_alloc_size = parse_size_and_unit(CONFIG_BUDDY_ALLOCATOR_SIZE,
> +                                                   NULL);
> +    }
> +
> +    printk(XENLOG_INFO "Init color heap with %lu pages\n", nr_pages);
> +    printk(XENLOG_INFO "Paging starting from: 0x%"PRIx64"\n",
> +           page_to_maddr(pg));
> +
> +    for ( i = 0; i < nr_pages; i++ )
> +        color_heap_insert_page(pg++);
> +}
> +
> +/* Alloc one page based on domain color configuration */
> +static struct page_info *alloc_col_heap_page(unsigned int memflags,
> +                                             const unsigned int *colors,
> +                                             unsigned int num_colors)
> +{
> +    struct page_info *pg = NULL;
> +    unsigned int i;
> +    bool need_tlbflush = false;
> +    uint32_t tlbflush_timestamp = 0;
> +
> +    spin_lock(&heap_lock);
> +
> +    for ( i = 0; i < num_colors; i++ )
> +    {
> +        struct page_info *tmp;
> +
> +        if ( page_list_empty(colored_pages(colors[i])) )
> +            continue;
> +
> +        tmp = page_list_first(colored_pages(colors[i]));
> +        if ( !pg || page_to_maddr(tmp) > page_to_maddr(pg) )
> +            pg = tmp;
> +    }
> +
> +    if ( !pg )
> +    {
> +        spin_unlock(&heap_lock);
> +        return NULL;
> +    }
> +
> +    pg->count_info = PGC_state_inuse;
> +
> +    if ( !(memflags & MEMF_no_tlbflush) )
> +        accumulate_tlbflush(&need_tlbflush, pg, &tlbflush_timestamp);
> +
> +    init_free_page_fields(pg);
> +    flush_page_to_ram(mfn_x(page_to_mfn(pg)),
> +                      !(memflags & MEMF_no_icache_flush));
> +    color_heap_remove_page(pg);
> +
> +    spin_unlock(&heap_lock);
> +
> +    if ( need_tlbflush )
> +        filtered_flush_tlb_mask(tlbflush_timestamp);
> +
> +    return pg;
> +}
> +
> +static void free_col_domheap_page(struct page_info *pg)
> +{
> +    pg->count_info = PGC_state_free;
> +    page_set_owner(pg, NULL);
> +    color_heap_insert_page(pg);
> +}
> +
> +static struct page_info *alloc_col_domheap_page(struct domain *d,
> +                                                unsigned int memflags)
> +{
> +    struct page_info *pg;
> +
> +    ASSERT(!in_irq());
> +
> +    pg = alloc_col_heap_page(memflags, d->arch.colors, d->arch.num_colors);
> +    if ( !pg )
> +    {
> +        printk(XENLOG_ERR "Colored page is null for domain %pd\n", d);
> +        return NULL;
> +    }
> +
> +    if ( d && !(memflags & MEMF_no_owner) && assign_page(pg, 0, d, memflags) )
> +    {
> +        free_col_domheap_page(pg);
> +        return NULL;
> +    }
> +
> +    return pg;
> +}
> +
> +size_param("buddy-alloc-size", buddy_alloc_size);
> +#else
> +static void free_col_domheap_page(struct page_info *pg)
> +{
> +    return;
> +}
> +#endif /* CONFIG_CACHE_COLORING */
> 
>  /*************************
>   * BINARY BUDDY ALLOCATOR
> @@ -462,7 +633,6 @@ static unsigned long node_need_scrub[MAX_NUMNODES];
>  static unsigned long *avail[MAX_NUMNODES];
>  static long total_avail_pages;
> 
> -static DEFINE_SPINLOCK(heap_lock);
>  static long outstanding_claims; /* total outstanding claims by all domains */
> 
>  unsigned long domain_adjust_tot_pages(struct domain *d, long pages)
> @@ -1027,10 +1197,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);
> @@ -1926,6 +2093,7 @@ static unsigned long avail_heap_pages(
>  void __init end_boot_allocator(void)
>  {
>      unsigned int i;
> +    unsigned long buddy_pages = PFN_DOWN(buddy_alloc_size);
> 
>      /* Pages that are free now go to the domain sub-allocator. */
>      for ( i = 0; i < nr_bootmem_regions; i++ )
> @@ -1939,11 +2107,24 @@ void __init end_boot_allocator(void)
>              break;
>          }
>      }
> -    for ( i = nr_bootmem_regions; i-- > 0; )
> +
> +    for ( i = 0; i < nr_bootmem_regions; i++ )
>      {
>          struct bootmem_region *r = &bootmem_region_list[i];
> +
> +        if ( buddy_pages && (r->s < r->e) )
> +        {
> +            unsigned long pages = MIN(r->e - r->s, buddy_pages);
> +            init_heap_pages(mfn_to_page(_mfn(r->s)), pages);

When cache coloring is enabled we have 2 allocators: colored and buddy.
The amount of memory for buddy allocator comes from the config (64MB by default).
So what about the first block of code at the beginning of end_boot_allocator
that calls init_heap_pages for the first free boot memory region?
There are two issues:
1. Buddy will end up having the buddy_pages + pages from the first free bootmem region.
   This is already incorrect as buddy should have the amount of memory set by the user.
2. Allowing the first free memory bank to go to buddy without imposing any restrictions
   on the size, can significantly lower the amount of memory available to colored allocator.
   If we load the images near the end of memory bank, the first free region can actually
   occupy most of the system memory and lead to issues with not enough colored memory for domains allocations.

I cannot see a reason for you to use that block of code. Before your series there was a split
to prefer allocations from higher memory with the exception of inserting one region residing on
the boot CPU node first (4280d3ee4cb1). Because your series modifies this behavior to prefer allocations
from lower memory in ascending order (and also allowing user to set a buddy size) I think this block
of code should not be executed when cache coloring is enabled.


Apart from that, the memory coming from the buddy is of any color. Shouldn't it be that the memory
allocated for domains comes from colored memory of the colors assigned to them and anything else
should come from colors given to Xen? At the moment, the memory for e.g. allocating P2M tables comes
from the buddy which means it can be of any color and might cause some cache interference.


~Michal


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-10-17  7:06   ` Michal Orzel
@ 2022-10-17  8:44     ` Julien Grall
  2022-10-17  9:16       ` Michal Orzel
  0 siblings, 1 reply; 60+ messages in thread
From: Julien Grall @ 2022-10-17  8:44 UTC (permalink / raw)
  To: Michal Orzel, Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi,

On 17/10/2022 08:06, Michal Orzel wrote:
> On 26/08/2022 14:51, Carlo Nonato wrote:
> Apart from that, the memory coming from the buddy is of any color. Shouldn't it be that the memory
> allocated for domains comes from colored memory of the colors assigned to them and anything else
> should come from colors given to Xen? At the moment, the memory for e.g. allocating P2M tables comes
> from the buddy which means it can be of any color and might cause some cache interference.

Somewhat related. IIUC what you are saying, the P2M pool will still be 
allocated from the buddy. I would expect we want to instead allocate the 
P2M pool from the same color as the domain to prevent interference when 
the TLBs are loaded. Or is the interference negligible?

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 06/12] xen/common: add cache coloring allocator for domains
  2022-10-17  8:44     ` Julien Grall
@ 2022-10-17  9:16       ` Michal Orzel
  0 siblings, 0 replies; 60+ messages in thread
From: Michal Orzel @ 2022-10-17  9:16 UTC (permalink / raw)
  To: Julien Grall, Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Julien,

On 17/10/2022 10:44, Julien Grall wrote:
> 
> 
> Hi,
> 
> On 17/10/2022 08:06, Michal Orzel wrote:
>> On 26/08/2022 14:51, Carlo Nonato wrote:
>> Apart from that, the memory coming from the buddy is of any color. Shouldn't it be that the memory
>> allocated for domains comes from colored memory of the colors assigned to them and anything else
>> should come from colors given to Xen? At the moment, the memory for e.g. allocating P2M tables comes
>> from the buddy which means it can be of any color and might cause some cache interference.
> 
> Somewhat related. IIUC what you are saying, the P2M pool will still be
> allocated from the buddy. I would expect we want to instead allocate the
> P2M pool from the same color as the domain to prevent interference when
> the TLBs are loaded. Or is the interference negligible?
> 
Good point and I agree. I do not think it is negligible.
All in all, allocating this memory from buddy which is of any color is incorrect.
When cache coloring is enabled, it should not be possible to allocate memory of any color.
If we can do this so that this memory comes from either Xen or domain colors, the
intereference will be reduced. When it comes to P2M tables, if the memory comes from
the colors assigned to a domain, there will be even less interference.


> Cheers,
> 
> --
> Julien Grall
> 

~Michal


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

* Re: [PATCH 08/12] Revert "xen/arm: setup: Add Xen as boot module before printing all boot modules"
  2022-09-12 13:54     ` Carlo Nonato
@ 2022-10-21 16:52       ` Julien Grall
  0 siblings, 0 replies; 60+ messages in thread
From: Julien Grall @ 2022-10-21 16:52 UTC (permalink / raw)
  To: Carlo Nonato
  Cc: xen-devel, andrew.cooper3, george.dunlap, jbeulich,
	stefano.stabellini, wl, marco.solieri, andrea.bastoni, lucmiccio,
	Marco Solieri

On 12/09/2022 14:54, Carlo Nonato wrote:
> Hi Julien,

Hi Carlo,

> On Sat, Sep 10, 2022 at 4:01 PM Julien Grall <julien@xen.org> wrote: > Do you have any suggestions? Is it ok to add the print to this very patch
> explaining why I added that (since it would edit the clean revert)?

I would consider to the call to early_print_info() after the Xen module 
is created.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 01/12] xen/arm: add cache coloring initialization
  2022-08-26 12:51 ` [PATCH 01/12] xen/arm: add cache coloring initialization Carlo Nonato
  2022-09-26  6:20   ` Wei Chen
@ 2022-10-21 17:14   ` Julien Grall
  1 sibling, 0 replies; 60+ messages in thread
From: Julien Grall @ 2022-10-21 17:14 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Carlo,

On 26/08/2022 13:51, Carlo Nonato wrote:
> This commit adds the cache coloring support initialization, Kconfig options,
> command line parameters and the initial documentation.
> The initialization consists of an auto probing of the cache layout
> necessary to retrieve the LLC way size which is used to compute the
> number of available colors. The Dom0 colors are then initialized with default
> colors (all available ones) if not provided from the command line, and
> they are checked for bad configuration.
> 
> It also adds a debug-key to dump general cache coloring info.
> This includes LLC way size, total available colors and the mask used to
> extract colors from physical addresses.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
>   docs/misc/arm/cache-coloring.rst     | 112 ++++++++++++++
>   docs/misc/xen-command-line.pandoc    |  22 +++
>   xen/arch/arm/Kconfig                 |  16 ++
>   xen/arch/arm/Makefile                |   1 +
>   xen/arch/arm/coloring.c              | 222 +++++++++++++++++++++++++++
>   xen/arch/arm/include/asm/coloring.h  |  31 ++++
>   xen/arch/arm/include/asm/processor.h |  16 ++
>   xen/arch/arm/setup.c                 |   8 +
>   8 files changed, 428 insertions(+)
>   create mode 100644 docs/misc/arm/cache-coloring.rst
>   create mode 100644 xen/arch/arm/coloring.c
>   create mode 100644 xen/arch/arm/include/asm/coloring.h
> 
> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> new file mode 100644
> index 0000000000..c7adcb0f1f
> --- /dev/null
> +++ b/docs/misc/arm/cache-coloring.rst
> @@ -0,0 +1,112 @@
> +Xen cache coloring user guide
> +=============================
> +
> +The cache coloring support in Xen allows to reserve Last Level Cache (LLC)
> +partition for Dom0, DomUs and Xen itself. Currently only ARM64 is supported.
> +
> +In order to enable and use it, few steps are needed.
> +
> +- Enable cache coloring in Xen configuration file.
> +
> +        CONFIG_CACHE_COLORING=y
> +- If needed, change the maximum number of colors in Xen configuration file
> +  (refer to menuconfig help for value meaning and when it should be changed).
> +
> +        CONFIG_MAX_CACHE_COLORS=<n>
> +- Assign colors to Dom0 using the `Color selection format`_ (see
> +  `Coloring parameters`_ for more documentation pointers).
> +
> +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.
> +
> +.. raw:: html
> +
> +    <pre>
> +                            Region j            Region j+1
> +                .....................   ............
> +                .                     . .
> +                .                       .
> +            _ _ _______________ _ _____________________ _ _
> +                |     |     |     |     |     |     |
> +                | c_0 | c_1 |     | c_n | c_0 | c_1 |
> +           _ _ _|_____|_____|_ _ _|_____|_____|_____|_ _ _
> +                    :                       :
> +                    :                       :...         ... .
> +                    :                            color 0
> +                    :...........................         ... .
> +                                                :
> +          . . ..................................:
> +    </pre>
> +
> +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
> +a 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 to the user to overcome failing situations
> +or for debugging/testing purposes. See `Coloring parameters`_ section for more
> +information on that.
> +
> +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]                               |
> ++---------------------+-----------------------------------+
> +
> +Coloring parameters
> +*******************
> +
> +LLC way size (as previously discussed) and Dom0 colors can be set using the
> +appropriate command line parameters. See the relevant documentation in
> +"docs/misc/xen-command-line.pandoc".
> \ No newline at end of file
> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> index 9a79385a37..910ebeb2eb 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -889,6 +889,14 @@ Controls for the dom0 IOMMU setup.
>   
>       Incorrect use of this option may result in a malfunctioning system.
>   
> +### dom0-colors (arm64)
> +> `= List of [ <integer> | <integer>-<integer> ]`
> +
> +> Default: `All available colors`
> +
> +Specify dom0 color configuration. If the parameter is not set, all available
> +colors are chosen and the user is warned on Xen's serial console.
> +
>   ### dom0_ioports_disable (x86)
>   > `= List of <hex>-<hex>`
>   
> @@ -1631,6 +1639,20 @@ 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-way-size (arm64)
> +> `= <size>`
> +
> +> Default: `Obtained from the hardware`
> +
> +Specify the way size of the Last Level Cache. This parameter is only useful with
> +cache coloring support enabled. It is an optional, expert-only parameter and it
> +is used to calculate the number of available 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.
> +
>   ### loglvl
>   > `= <level>[/<rate-limited level>]` where level is `none | error | warning | info | debug | all`
>   
> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> index 33e004d702..8acff9682c 100644
> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -131,6 +131,22 @@ config ARM64_BTI
>   	  Branch Target Identification support.
>   	  This feature is not supported in Xen.
>   
> +config CACHE_COLORING
> +	bool "Last Level Cache (LLC) coloring" if EXPERT
> +	default n
> +	depends on ARM_64
> +
> +config MAX_CACHE_COLORS
> +	int "Maximum number of cache colors"
> +	default 128
> +	range 0 65536
> +	depends on CACHE_COLORING
> +	help
> +	  This config value is an upper bound for the actual number of cache colors
> +	  supported by the architecture. Xen preallocates this amount of cache
> +	  colors at boot. Note that if, at any time, a color configuration with more
> +	  colors than the maximum will be employed an error will be produced.
> +
>   config TEE
>   	bool "Enable TEE mediators support (UNSUPPORTED)" if UNSUPPORTED
>   	default n
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 4d076b278b..12940ba761 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -67,6 +67,7 @@ obj-$(CONFIG_SBSA_VUART_CONSOLE) += vpl011.o
>   obj-y += vsmc.o
>   obj-y += vpsci.o
>   obj-y += vuart.o
> +obj-$(CONFIG_CACHE_COLORING) += coloring.o

The Makefile should be ordered alphabetically based on the filename. So 
please move this to correct position.

>   
>   extra-y += xen.lds
>   
> diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
> new file mode 100644
> index 0000000000..c010ebc01b
> --- /dev/null
> +++ b/xen/arch/arm/coloring.c
> @@ -0,0 +1,222 @@
> +/*
> + * xen/arch/arm/coloring.c
> + *
> + * Coloring support for ARM
> + *
> + * Copyright (C) 2019 Xilinx Inc.
> + *
> + * Authors:
> + *    Luca Miccio <lucmiccio@gmail.com>
> + *    Carlo Nonato <carlo.nonato@minervasys.tech>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <xen/errno.h>
> +#include <xen/keyhandler.h>
> +#include <xen/param.h>
> +#include <xen/types.h>
> +
> +#include <asm/coloring.h>
> +#include <asm/processor.h>
> +#include <asm/sysregs.h>
> +
> +/* Size of a LLC way */
> +static unsigned int llc_way_size;
> +/* Number of colors available in the LLC */
> +static unsigned int max_colors;
> +/* Mask to retrieve coloring relevant bits */
> +static uint64_t addr_col_mask;

IIUC, this is meant to be applied on a host physical address. If so, 
please use 'paddr_t' rather than uint64_t. Same below.

> +
> +#define addr_to_color(addr) (((addr) & addr_col_mask) >> PAGE_SHIFT)
> +#define addr_set_color(addr, color) (((addr) & ~addr_col_mask) \
> +                                     | ((color) << PAGE_SHIFT))

I don't see any use of addr_to_color() and addr_set_color() below. So it 
is not clear to me what is the type of 'color'. This may need to be 
casted to (paddr_t).

But as the helpers are quite small, it would be better to introduce the 
macros where they are used.

> +
> +static unsigned int dom0_colors[CONFIG_MAX_CACHE_COLORS];
> +static unsigned int 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;
> +
> +    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 ||
> +                 *num_colors + end - start >= CONFIG_MAX_CACHE_COLORS )

In theory, *num_colors + end - start could overflow. I would also check 
that given you are sanity checking the values.

Lastly, may I ask to surround *num_colors + end - start with ()? This 
would make easier to read.

> +                return -EINVAL;
> +            for ( color = start; color <= end; color++ )
> +                colors[(*num_colors)++] = color;
> +        }
> +        else
> +            s++;
> +    }
> +
> +    return *s ? -EINVAL : 0;
> +}
> +
> +size_param("llc-way-size", llc_way_size);
> +
> +static int __init parse_dom0_colors(const char *s)
> +{
> +    return parse_color_config(s, dom0_colors, &dom0_num_colors);
> +}
> +custom_param("dom0-colors", parse_dom0_colors);
> +
> +/* Return the LLC way size by probing the hardware */
> +static unsigned int 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 bool check_colors(unsigned int *colors, unsigned int num_colors)
> +{
> +    int i;

i should not be signed. So please use "unsigned int".

> +
> +    if ( num_colors > max_colors )
> +        return false;
> +
> +    for ( i = 0; i < num_colors; i++ )
> +        if ( colors[i] >= max_colors )
> +            return false;
> +
> +    return true;
> +}
> +
> +static unsigned int set_default_domain_colors(unsigned int *colors)
> +{
> +    unsigned int i;
> +
> +    if ( !colors )
> +        return 0;
I find a bit odd that we return 0 if 'colors' is NULL. In what situation 
do you expect 'colors' to be NULL? Is this a programming error?

> + > +    for ( i = 0; i < max_colors; i++ )
> +        colors[i] = i;

Coding style: Newline please.

> +    return max_colors;
> +}
> +
> +static void dump_coloring_info(unsigned char key)
> +{
> +    printk("'%c' pressed -> dumping coloring general info\n", key);
> +    printk("LLC way size: %u KiB\n", llc_way_size >> 10);
> +    printk("Number of LLC colors supported: %u\n", max_colors);
> +    printk("Address color mask: 0x%lx\n", addr_col_mask);
> +}
> +
> +bool __init 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;
> +    }
> +
> +    max_colors = llc_way_size / PAGE_SIZE;
> +    /* The maximum number of colors must be a power of 2 in order to correctly
> +       map colors to bits of an address. */
> +    ASSERT((max_colors & (max_colors - 1)) == 0);
> +    addr_col_mask = (max_colors - 1) << PAGE_SHIFT;
> +
> +    if ( !dom0_num_colors )
> +    {
> +        printk(XENLOG_WARNING
> +               "Dom0 color config not found. Using default (all colors)\n");
> +        dom0_num_colors = set_default_domain_colors(dom0_colors);
> +    }
> +
> +    if ( !check_colors(dom0_colors, dom0_num_colors) )
> +    {
> +        printk(XENLOG_ERR "Bad color config for Dom0\n");
> +        return false;
> +    }
> +
> +    register_keyhandler('K', dump_coloring_info, "dump coloring info", 1);
> +
> +    return true;
> +}
> +
> +/*
> + * 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/coloring.h b/xen/arch/arm/include/asm/coloring.h
> new file mode 100644
> index 0000000000..dd7eff5f07
> --- /dev/null
> +++ b/xen/arch/arm/include/asm/coloring.h
> @@ -0,0 +1,31 @@
> +/*
> + * xen/arm/include/asm/coloring.h
> + *
> + * Coloring support for ARM
> + *
> + * Copyright (C) 2019 Xilinx Inc.
> + *
> + * Authors:
> + *    Luca Miccio <lucmiccio@gmail.com>
> + *    Carlo Nonato <carlo.nonato@minervasys.tech>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __ASM_ARM_COLORING_H__
> +#define __ASM_ARM_COLORING_H__
> +
> +#include <xen/init.h>
> +
> +bool __init coloring_init(void);
> +
> +#endif /* !__ASM_ARM_COLORING_H__ */

Missing emags magic as you added in coloring.c.

> diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h
> index 1dd81d7d52..85ff0caf1e 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            0x7
> +#define CCSIDR_NUMSETS_SHIFT            13
> +#define CCSIDR_NUMSETS_MASK             0x3FFF
> +#define CCSIDR_NUMSETS_SHIFT_FEAT_CCIDX 32
> +#define CCSIDR_NUMSETS_MASK_FEAT_CCIDX  0xFFFFFF

Please use ULL here otherwise someone using MASK << SHIFT will have the 
expected result.

My preference would be that all the MASK should have the same type. So 
this is easier to spot any mistake.

> +
> +/* CCSELR Cache Size Selection Register */
> +#define CCSELR_LEVEL_MASK  0x7
> +#define CCSELR_LEVEL_SHIFT 1
> +
> +/* CLIDR Cache Level ID Register */
> +#define CLIDR_CTYPEn_SHIFT(n) (3 * (n - 1))
> +#define CLIDR_CTYPEn_MASK     0x7
> +#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/setup.c b/xen/arch/arm/setup.c
> index 500307edc0..c02f21c0e6 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -53,6 +53,9 @@
>   #include <asm/setup.h>
>   #include <xsm/xsm.h>
>   #include <asm/acpi.h>
> +#ifdef CONFIG_CACHE_COLORING
> +#include <asm/coloring.h>
> +#endif

I would rather prefer if the #ifdef are moved in the header. So...

>   
>   struct bootinfo __initdata bootinfo;
>   
> @@ -930,6 +933,11 @@ void __init start_xen(unsigned long boot_phys_offset,
>       printk("Command line: %s\n", cmdline);
>       cmdline_parse(cmdline);
>   
> +#ifdef CONFIG_CACHE_COLORING
> +    if ( !coloring_init() )

... a stub for coloring_init() is provided and we avoid sprinkling the 
common code with #ifdef.

> +        panic("Xen Coloring support: setup failed\n");
> +#endif
> +
>       setup_mm();
>   
>       /* Parse the ACPI tables for possible boot-time configuration */

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-09-26  6:39   ` Wei Chen
  2022-09-27 14:31     ` Carlo Nonato
@ 2022-10-21 17:25     ` Julien Grall
  1 sibling, 0 replies; 60+ messages in thread
From: Julien Grall @ 2022-10-21 17:25 UTC (permalink / raw)
  To: Wei Chen, Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri



On 26/09/2022 07:39, Wei Chen wrote:
> 
> 
> On 2022/8/26 20:51, Carlo Nonato wrote:
>> This commit adds array pointers to domains as well as to the hypercall
>> and configuration structure employed in domain creation. The latter is 
>> used
>> both by the toolstack and by Xen itself to pass configuration data to the
>> domain creation function, so the XEN_GUEST_HANDLE macro must be 
>> adopted to be
>> able to access guest memory in the first case. This implies special 
>> care for
>> the copy of the configuration data into the domain data, meaning that a
>> discrimination variable for the two possible code paths (coming from 
>> Xen or
>> from the toolstack) is needed.
>>
>> The initialization and free functions for colored domains are also added.
>> The former is responsible for allocating and populating the color array
>> of the domain and it also checks for configuration issues. One of those
>> issues is enabling both coloring and directmap for the domain because 
>> they
>> contradicts one another. Since that, Dom0 must not be created with the
>> directmap flag.
>> The latter instead frees allocated memory.
>>
>> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
>> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
>> ---
>>   docs/misc/arm/cache-coloring.rst    |  7 ++--
>>   xen/arch/arm/coloring.c             | 56 +++++++++++++++++++++++++++++
>>   xen/arch/arm/domain.c               | 11 ++++++
>>   xen/arch/arm/domain_build.c         | 13 +++++--
>>   xen/arch/arm/include/asm/coloring.h |  7 ++++
>>   xen/arch/arm/include/asm/domain.h   |  4 +++
>>   xen/include/public/arch-arm.h       |  8 +++++
>>   7 files changed, 102 insertions(+), 4 deletions(-)
>>
>> diff --git a/docs/misc/arm/cache-coloring.rst 
>> b/docs/misc/arm/cache-coloring.rst
>> index c7adcb0f1f..345d97cb56 100644
>> --- a/docs/misc/arm/cache-coloring.rst
>> +++ b/docs/misc/arm/cache-coloring.rst
>> @@ -13,7 +13,7 @@ In order to enable and use it, few steps are needed.
>>     (refer to menuconfig help for value meaning and when it should be 
>> changed).
>>           CONFIG_MAX_CACHE_COLORS=<n>
>> -- Assign colors to Dom0 using the `Color selection format`_ (see
>> +- Assign colors to domains using the `Color selection format`_ (see
>>     `Coloring parameters`_ for more documentation pointers).
>>   Background
>> @@ -109,4 +109,7 @@ Coloring parameters
>>   LLC way size (as previously discussed) and Dom0 colors can be set 
>> using the
>>   appropriate command line parameters. See the relevant documentation in
>> -"docs/misc/xen-command-line.pandoc".
>> \ No newline at end of file
>> +"docs/misc/xen-command-line.pandoc".
>> +
>> +Note that if no color configuration is provided for domains, they 
>> fallback to
>> +the default one, which corresponds simply to all available colors.
>> \ No newline at end of file
>> diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
>> index c010ebc01b..2b37cda067 100644
>> --- a/xen/arch/arm/coloring.c
>> +++ b/xen/arch/arm/coloring.c
>> @@ -22,6 +22,7 @@
>>    * along with this program.  If not, see 
>> <http://www.gnu.org/licenses/>.
>>    */
>>   #include <xen/errno.h>
>> +#include <xen/guest_access.h>
>>   #include <xen/keyhandler.h>
>>   #include <xen/param.h>
>>   #include <xen/types.h>
>> @@ -211,6 +212,61 @@ bool __init coloring_init(void)
>>       return true;
>>   }
>> +int domain_coloring_init(struct domain *d,
>> +                         const struct xen_arch_domainconfig *config)
>> +{
>> +    if ( is_domain_direct_mapped(d) )
>> +    {
>> +        printk(XENLOG_ERR
>> +               "Can't enable coloring and directmap at the same time 
>> for %pd\n",
>> +               d);
>> +        return -EINVAL;
>> +    }
>> +
>> +    if ( is_hardware_domain(d) )
>> +    {
>> +        d->arch.colors = dom0_colors;
>> +        d->arch.num_colors = dom0_num_colors;
>> +    }
>> +    else if ( config->num_colors == 0 )
>> +    {
>> +        printk(XENLOG_WARNING
>> +               "Color config not found for %pd. Using default\n", d);
>> +        d->arch.colors = xzalloc_array(unsigned int, max_colors);
>> +        d->arch.num_colors = set_default_domain_colors(d->arch.colors);
>> +    }
>> +    else
>> +    {
>> +        d->arch.colors = xzalloc_array(unsigned int, 
>> config->num_colors);
>> +        d->arch.num_colors = config->num_colors;
>> +        if ( config->from_guest )
>> +            copy_from_guest(d->arch.colors, config->colors, 
>> config->num_colors);
>> +        else
>> +            memcpy(d->arch.colors, config->colors.p,
>> +                   sizeof(unsigned int) * config->num_colors);
>> +    }
>> +
>> +    if ( !d->arch.colors )
>> +    {
>> +        printk(XENLOG_ERR "Colors allocation failed for %pd\n", d);
>> +        return -ENOMEM;
>> +    }
>> +
>> +    if ( !check_colors(d->arch.colors, d->arch.num_colors) )
>> +    {
> 
> If we add xfree(d->arch.colors) here for non-hw domains, is it possible 
> to make this function have a complete fallback process? And I know 
> currently, this is handled in domain_coloring_free.

arch_domain_destroy() (and therefore domain_coloring_free()) will always 
be called by arch_domain_create(). So here you will want to use XFREE() 
to avoid a double free.

However, I would just rely on the free() in domain_coloring_free().

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-08-26 12:51 ` [PATCH 02/12] xen/arm: add cache coloring initialization for domains Carlo Nonato
  2022-09-26  6:39   ` Wei Chen
@ 2022-10-21 18:02   ` Julien Grall
  2022-10-25 10:53     ` Carlo Nonato
                       ` (2 more replies)
  2022-10-21 18:04   ` Julien Grall
  2 siblings, 3 replies; 60+ messages in thread
From: Julien Grall @ 2022-10-21 18:02 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Carlo,

On 26/08/2022 13:51, Carlo Nonato wrote:
> This commit adds array pointers to domains as well as to the hypercall
> and configuration structure employed in domain creation. The latter is used
> both by the toolstack and by Xen itself to pass configuration data to the
> domain creation function, so the XEN_GUEST_HANDLE macro must be adopted to be
> able to access guest memory in the first case. This implies special care for
> the copy of the configuration data into the domain data, meaning that a
> discrimination variable for the two possible code paths (coming from Xen or
> from the toolstack) is needed.

So this means that a toolstack could set from_guest. I know the 
toolstack is trusted... However, we should try to limit when the trust 
when this is possible.

In this case, I would consider to modify the prototype of 
domain_create() to pass internal information.

> 
> The initialization and free functions for colored domains are also added.
> The former is responsible for allocating and populating the color array
> of the domain and it also checks for configuration issues. One of those
> issues is enabling both coloring and directmap for the domain because they
> contradicts one another. Since that, Dom0 must not be created with the
> directmap flag.
> The latter instead frees allocated memory.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
>   docs/misc/arm/cache-coloring.rst    |  7 ++--
>   xen/arch/arm/coloring.c             | 56 +++++++++++++++++++++++++++++
>   xen/arch/arm/domain.c               | 11 ++++++
>   xen/arch/arm/domain_build.c         | 13 +++++--
>   xen/arch/arm/include/asm/coloring.h |  7 ++++
>   xen/arch/arm/include/asm/domain.h   |  4 +++
>   xen/include/public/arch-arm.h       |  8 +++++
>   7 files changed, 102 insertions(+), 4 deletions(-)
> 
> diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> index c7adcb0f1f..345d97cb56 100644
> --- a/docs/misc/arm/cache-coloring.rst
> +++ b/docs/misc/arm/cache-coloring.rst
> @@ -13,7 +13,7 @@ In order to enable and use it, few steps are needed.
>     (refer to menuconfig help for value meaning and when it should be changed).
>   
>           CONFIG_MAX_CACHE_COLORS=<n>
> -- Assign colors to Dom0 using the `Color selection format`_ (see
> +- Assign colors to domains using the `Color selection format`_ (see
>     `Coloring parameters`_ for more documentation pointers).
>   
>   Background
> @@ -109,4 +109,7 @@ Coloring parameters
>   
>   LLC way size (as previously discussed) and Dom0 colors can be set using the
>   appropriate command line parameters. See the relevant documentation in
> -"docs/misc/xen-command-line.pandoc".
> \ No newline at end of file
> +"docs/misc/xen-command-line.pandoc".
> +
> +Note that if no color configuration is provided for domains, they fallback to
> +the default one, which corresponds simply to all available colors.
> \ No newline at end of file
> diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
> index c010ebc01b..2b37cda067 100644
> --- a/xen/arch/arm/coloring.c
> +++ b/xen/arch/arm/coloring.c
> @@ -22,6 +22,7 @@
>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>    */
>   #include <xen/errno.h>
> +#include <xen/guest_access.h>
>   #include <xen/keyhandler.h>
>   #include <xen/param.h>
>   #include <xen/types.h>
> @@ -211,6 +212,61 @@ bool __init coloring_init(void)
>       return true;
>   }
>   
> +int domain_coloring_init(struct domain *d,
> +                         const struct xen_arch_domainconfig *config)
> +{
> +    if ( is_domain_direct_mapped(d) )
> +    {
> +        printk(XENLOG_ERR
> +               "Can't enable coloring and directmap at the same time for %pd\n",
> +               d);
> +        return -EINVAL;
> +    }
> +
> +    if ( is_hardware_domain(d) )
> +    {
> +        d->arch.colors = dom0_colors;
> +        d->arch.num_colors = dom0_num_colors;
> +    }

I think it would be better if we allocate an array also for the HW 
domain. This is not going to require too much extra memory and will help 
the code to be simpler.

I would also pass the color to domain_create(). So there is no logic 
specific to the HW domain here.

> +    else if ( config->num_colors == 0 )
> +    {
> +        printk(XENLOG_WARNING
> +               "Color config not found for %pd. Using default\n", d);
> +        d->arch.colors = xzalloc_array(unsigned int, max_colors);
> +        d->arch.num_colors = set_default_domain_colors(d->arch.colors);
Ah, so your check in set_default_domain_colors() is here to cater this 
case? I would prefer if we check the allocation before using it. This 
will make it more obvious compare to expecting 
set_default_domain_colors() checking for NULL.

> +    }
> +    else
> +    {
> +        d->arch.colors = xzalloc_array(unsigned int, config->num_colors);
> +        d->arch.num_colors = config->num_colors;
> +        if ( config->from_guest )
> +            copy_from_guest(d->arch.colors, config->colors, config->num_colors);
> +        else
> +            memcpy(d->arch.colors, config->colors.p,
> +                   sizeof(unsigned int) * config->num_colors);

See my remark above.

> +    }
> +
> +    if ( !d->arch.colors )
> +    {
> +        printk(XENLOG_ERR "Colors allocation failed for %pd\n", d);
> +        return -ENOMEM;
> +    }
> +
> +    if ( !check_colors(d->arch.colors, d->arch.num_colors) )
> +    {
> +        printk(XENLOG_ERR "Bad color config for %pd\n", d);
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +void domain_coloring_free(struct domain *d)
> +{
> +    if ( !is_hardware_domain(d) )
> +        xfree(d->arch.colors);
> +}
> +
>   /*
>    * Local variables:
>    * mode: C
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 2d6253181a..c6fa8adc99 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -23,6 +23,9 @@
>   #include <xen/wait.h>
>   
>   #include <asm/alternative.h>
> +#ifdef CONFIG_CACHE_COLORING
> +#include <asm/coloring.h>
> +#endif
>   #include <asm/cpuerrata.h>
>   #include <asm/cpufeature.h>
>   #include <asm/current.h>
> @@ -712,6 +715,11 @@ int arch_domain_create(struct domain *d,
>       ioreq_domain_init(d);
>   #endif
>   
> +#ifdef CONFIG_CACHE_COLORING

When !CONFIG_CACHE_COLORING, we should check that the color is not 
specified.

> +    if ( (rc = domain_coloring_init(d, &config->arch)) )
> +        goto fail;
> +#endif
> +
>       /* p2m_init relies on some value initialized by the IOMMU subsystem */
>       if ( (rc = iommu_domain_init(d, config->iommu_opts)) != 0 )
>           goto fail;
> @@ -807,6 +815,9 @@ void arch_domain_destroy(struct domain *d)
>                          get_order_from_bytes(d->arch.efi_acpi_len));
>   #endif
>       domain_io_free(d);
> +#ifdef CONFIG_CACHE_COLORING
> +    domain_coloring_free(d);
> +#endif

See my remark in patch #1 about the #ifdef.

>   }
>   
>   void arch_domain_shutdown(struct domain *d)
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 3fd1186b53..4d4cb692fc 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -33,6 +33,12 @@
>   #include <xen/grant_table.h>
>   #include <xen/serial.h>
>   
> +#ifdef CONFIG_CACHE_COLORING
> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged
> +#else
> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged | CDF_directmap
> +#endif

I can't remember if I asked it before and it doesn't seem to written 
everywhere. This check suggest that it is not possible to use the same 
Xen binary for coloring and non-coloring.

At the moment, we have been able to have all the features in the same 
Xen binary. So what are the reasons for this restriction?

> +
>   static unsigned int __initdata opt_dom0_max_vcpus;
>   integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
>   
> @@ -3399,7 +3405,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_ENABLED(CONFIG_CACHE_COLORING) )

Even if we can't have a single Xen binary yet, I would prefer if we 
avoid using directly IS_ENABLED(CONFIG_CACHE_COLORING). Instead it would 
be better to provide an helper that check whether the domain has cache 
coloring is enabled.

That helper could use IS_ENABLED(CONFIG_CACHE_COLORING) if that still 
wanted. The advantage is we make it easier to modify the code.

> +        allocate_memory(d, &kinfo);
> +    else
> +        allocate_memory_11(d, &kinfo);
>       find_gnttab_region(d, &kinfo);
>   
>       /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
> @@ -3455,7 +3464,7 @@ void __init create_dom0(void)
>       if ( iommu_enabled )
>           dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu;
>   
> -    dom0 = domain_create(0, &dom0_cfg, CDF_privileged | CDF_directmap);
> +    dom0 = domain_create(0, &dom0_cfg, XEN_DOM0_CREATE_FLAGS);
>       if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
>           panic("Error creating domain 0\n");
>   
> diff --git a/xen/arch/arm/include/asm/coloring.h b/xen/arch/arm/include/asm/coloring.h
> index dd7eff5f07..60c8b1f079 100644
> --- a/xen/arch/arm/include/asm/coloring.h
> +++ b/xen/arch/arm/include/asm/coloring.h
> @@ -25,7 +25,14 @@
>   #define __ASM_ARM_COLORING_H__
>   
>   #include <xen/init.h>
> +#include <xen/sched.h>
> +
> +#include <public/arch-arm.h>
>   
>   bool __init coloring_init(void);
>   
> +int domain_coloring_init(struct domain *d,
> +                         const struct xen_arch_domainconfig *config);
> +void domain_coloring_free(struct domain *d);
> +
>   #endif /* !__ASM_ARM_COLORING_H__ */
> diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
> index 26a8348eed..291f7c375d 100644
> --- a/xen/arch/arm/include/asm/domain.h
> +++ b/xen/arch/arm/include/asm/domain.h
> @@ -58,6 +58,10 @@ struct arch_domain
>   #ifdef CONFIG_ARM_64
>       enum domain_type type;
>   #endif

NIT: Newline here please. So we keep each feature in their own block.

> +#ifdef CONFIG_CACHE_COLORING
> +    unsigned int *colors;
> +    unsigned int num_colors;
> +#endif >
>       /* Virtual MMU */
>       struct p2m_domain p2m;
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index c8b6058d3a..adf843a7a1 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -314,6 +314,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
>   #define XEN_DOMCTL_CONFIG_TEE_NONE      0
>   #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
>   
> +__DEFINE_XEN_GUEST_HANDLE(color_t, unsigned int);

You don't seem to use "color_t" outside of arch-arm.h and we already 
define guest handle for "unsigned int". So can they be used?

> +
>   struct xen_arch_domainconfig {
>       /* IN/OUT */
>       uint8_t gic_version;
> @@ -335,6 +337,12 @@ struct xen_arch_domainconfig {
>        *
>        */
>       uint32_t clock_frequency;
> +    /* IN */
> +    uint8_t from_guest;

There is an implicit padding here and ...
> +    /* IN */
> +    uint16_t num_colors;

... here. For the ABI, we are trying to have all the padding explicit. 
So the layout of the structure is clear.

Also, DOMCTL is an unstable ABI, so I think it would not be necessary to 
check the padding are zeroed. If it were a stable ABI, then we would 
need to check so they can be re-used in the future.

> +    /* IN */
> +    XEN_GUEST_HANDLE(color_t) colors;
>   };

Lastly, assuming this is the first patch touching the domctl for next 
release, you will want to bump the XEN_DOMCTL_INTERFACE_VERSION.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-08-26 12:51 ` [PATCH 02/12] xen/arm: add cache coloring initialization for domains Carlo Nonato
  2022-09-26  6:39   ` Wei Chen
  2022-10-21 18:02   ` Julien Grall
@ 2022-10-21 18:04   ` Julien Grall
  2 siblings, 0 replies; 60+ messages in thread
From: Julien Grall @ 2022-10-21 18:04 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel, Andrew Cooper, Anthony PERARD
  Cc: george.dunlap, jbeulich, stefano.stabellini, wl, marco.solieri,
	andrea.bastoni, lucmiccio, Marco Solieri

Hi,

On 26/08/2022 13:51, Carlo Nonato wrote:
>   #endif /* !__ASM_ARM_COLORING_H__ */
> diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
> index 26a8348eed..291f7c375d 100644
> --- a/xen/arch/arm/include/asm/domain.h
> +++ b/xen/arch/arm/include/asm/domain.h
> @@ -58,6 +58,10 @@ struct arch_domain
>   #ifdef CONFIG_ARM_64
>       enum domain_type type;
>   #endif
> +#ifdef CONFIG_CACHE_COLORING
> +    unsigned int *colors;
> +    unsigned int num_colors;
> +#endif
>   
>       /* Virtual MMU */
>       struct p2m_domain p2m;
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index c8b6058d3a..adf843a7a1 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -314,6 +314,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
>   #define XEN_DOMCTL_CONFIG_TEE_NONE      0
>   #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
>   
> +__DEFINE_XEN_GUEST_HANDLE(color_t, unsigned int);
> +
>   struct xen_arch_domainconfig {
>       /* IN/OUT */
>       uint8_t gic_version;
> @@ -335,6 +337,12 @@ struct xen_arch_domainconfig {
>        *
>        */
>       uint32_t clock_frequency;
> +    /* IN */
> +    uint8_t from_guest;
> +    /* IN */
> +    uint16_t num_colors;
> +    /* IN */
> +    XEN_GUEST_HANDLE(color_t) colors;
>   };
>   #endif /* __XEN__ || __XEN_TOOLS__ */


I forgot to mention. I think the golang and OCaml bindings will also 
need to be re-generated. Andrew, Anthony, can you confirm?

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 04/12] tools/xl: add support for cache coloring configuration
  2022-08-26 12:51 ` [PATCH 04/12] tools/xl: add support for cache coloring configuration Carlo Nonato
@ 2022-10-21 18:09   ` Julien Grall
  0 siblings, 0 replies; 60+ messages in thread
From: Julien Grall @ 2022-10-21 18:09 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	Anthony PERARD, Juergen Gross

Hi Carlo,

This patch seems to be missing the tools maintainers/reviewers. I have 
added them now.

I am not sure what you are to generate the CCs. If you are not aware, we 
have a script that will add the correct maintainers/reviewers for each 
patch. The script is called "scripts/add_maintainers.pl" and can be used 
after generating the patches.

Cheers,

On 26/08/2022 13:51, Carlo Nonato wrote:
> Add a new "colors" parameter that defines the 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.
> Also documentation is added.
> 
> Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> ---
>   docs/man/xl.cfg.5.pod.in         | 10 ++++++
>   tools/libs/light/libxl_create.c  | 12 ++++++++
>   tools/libs/light/libxl_types.idl |  1 +
>   tools/xl/xl_parse.c              | 52 ++++++++++++++++++++++++++++++--
>   4 files changed, 73 insertions(+), 2 deletions(-)
> 
> diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
> index b2901e04cf..5f53cec8bf 100644
> --- a/docs/man/xl.cfg.5.pod.in
> +++ b/docs/man/xl.cfg.5.pod.in
> @@ -2880,6 +2880,16 @@ Currently, only the "sbsa_uart" model is supported for ARM.
>   
>   =back
>   
> +=over 4
> +
> +=item B<colors=[ "COLORS_RANGE", "COLORS_RANGE", ...]>
> +
> +Specify the LLC color configuration for the guest. B<COLORS_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/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c
> index b9dd2deedf..94c511912c 100644
> --- a/tools/libs/light/libxl_create.c
> +++ b/tools/libs/light/libxl_create.c
> @@ -615,6 +615,7 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
>       struct xs_permissions rwperm[1];
>       struct xs_permissions noperm[1];
>       xs_transaction_t t = 0;
> +    DECLARE_HYPERCALL_BUFFER(unsigned int, colors);
>   
>       /* convenience aliases */
>       libxl_domain_create_info *info = &d_config->c_info;
> @@ -676,6 +677,16 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
>               goto out;
>           }
>   
> +        if (d_config->b_info.num_colors) {
> +            size_t bytes = sizeof(unsigned int) * d_config->b_info.num_colors;
> +            colors = xc_hypercall_buffer_alloc(ctx->xch, colors, bytes);
> +            memcpy(colors, d_config->b_info.colors, bytes);
> +            set_xen_guest_handle(create.arch.colors, colors);
> +            create.arch.num_colors = d_config->b_info.num_colors;
> +            create.arch.from_guest = 1;
> +            LOG(DEBUG, "Setup %u domain colors", d_config->b_info.num_colors);
> +        }
> +
>           for (;;) {
>               uint32_t local_domid;
>               bool recent;
> @@ -922,6 +933,7 @@ retry_transaction:
>       rc = 0;
>    out:
>       if (t) xs_transaction_end(ctx->xsh, t, 1);
> +    if (colors) xc_hypercall_buffer_free(ctx->xch, colors);
>       return rc;
>   }
>   
> diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
> index d634f304cd..642173af1a 100644
> --- a/tools/libs/light/libxl_types.idl
> +++ b/tools/libs/light/libxl_types.idl
> @@ -557,6 +557,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")),
> +    ("colors",           Array(uint32, "num_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 1b5381cef0..7f8fbbfb4c 100644
> --- a/tools/xl/xl_parse.c
> +++ b/tools/xl/xl_parse.c
> @@ -1220,8 +1220,9 @@ 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;
> -    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian, num_mca_caps;
> +                   *mca_caps, *colors;
> +    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian, num_mca_caps,
> +        num_colors;
>       int pci_power_mgmt = 0;
>       int pci_msitranslate = 0;
>       int pci_permissive = 0;
> @@ -1370,6 +1371,53 @@ 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, "colors", &colors, &num_colors, 0)) {
> +        int k, p, cur_index;
> +
> +        b_info->num_colors = 0;
> +        /* Get number of colors based on ranges */
> +        for (i = 0; i < num_colors; i++) {
> +            uint32_t start = 0, end = 0;
> +
> +            buf = xlu_cfg_get_listitem(colors, i);
> +            if (!buf) {
> +                fprintf(stderr,
> +                    "xl: Unable to get element %d in colors range list\n", i);
> +                exit(1);
> +            }
> +
> +            if (sscanf(buf, "%u-%u", &start, &end) != 2) {
> +                if (sscanf(buf, "%u", &start) != 1) {
> +                    fprintf(stderr, "xl: Invalid color range: %s\n", buf);
> +                    exit(1);
> +                }
> +                end = start;
> +            }
> +            else if (start > end) {
> +                fprintf(stderr,
> +                        "xl: Start color is greater than end color: %s\n", buf);
> +                exit(1);
> +            }
> +
> +            /* Check for overlaps */
> +            for (k = start; k <= end; k++) {
> +                for (p = 0; p < b_info->num_colors; p++)
> +                    if (b_info->colors[p] == k) {
> +                        fprintf(stderr, "xl: Overlapped ranges not allowed\n");
> +                        exit(1);
> +                    }
> +            }
> +
> +            cur_index = b_info->num_colors;
> +            b_info->num_colors += (end - start) + 1;
> +            b_info->colors = (uint32_t *)realloc(b_info->colors,
> +                                sizeof(*b_info->colors) * b_info->num_colors);
> +
> +            for (k = start; k <= end; k++)
> +                b_info->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)) {

-- 
Julien Grall


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

* Re: [PATCH 00/12] Arm cache coloring
  2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
                   ` (13 preceding siblings ...)
  2022-09-15 13:29 ` Jan Beulich
@ 2022-10-22 15:13 ` Julien Grall
  14 siblings, 0 replies; 60+ messages in thread
From: Julien Grall @ 2022-10-22 15:13 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio

Hi Carlo,

On 26/08/2022 13:50, Carlo Nonato wrote:
> - The way xl passes user space memory to Xen it's adapted from various
>    points of the xl code itself (e.g. xc_domain_node_setaffinity) and it
>    works, but it really needs attention from expert maintainers since
>    I'm not completely sure this is the correct way of doing things.
> - We still need to bring back the relocation feature (part of) in order
>    to move Xen memory to a colored space where the hypervisor could be
>    isolated from VMs interference (see the revert commit #10 and the
>    get_xen_paddr function in #12).
> - Revert commits #8 and #9 are needed because coloring has the command
>    line parsing as a prerequisite for its initialization and
>    setup_pagetables must be called after it in order to color the Xen
>    mapping. The DTB mapping is then added to the boot page tables instead
>    of the Xen ones. Probably the way this is done is a bit simplistic.
>    Looking forward for comments on the subject.
> - A temporary mapping of the old Xen code (old here means non-colored)
>    is used to reach variables in the old physical space so that secondary
>    CPUs can boot. There were some comments in the previous version on that
>    because the mapping is available for all the CPUs while only CPU0 is
>    the one supposed to access it. I'm not sure how to temporarily mapping
>    things only for the master CPU.

On Arm64, Xen will only use one set of page-tables for all the CPUs. So 
it will not be possible to have a temporary mapping for a single CPU. 
But what you can do is mapping the region and unmapping it when you are 
done.

That said, I would rather prefer if we can get rid of the old copy of 
Xen. This would means secondary CPUs will directly jump to the new Xen.

> - A lot of #ifdef for cache coloring are introduced because I prefer to
>    define functions only if they are actually needed. Let me know if you
>    prefer a different approach.

The preferred approach in Xen is to provide stub helpers in the #else part.

> - Julien posted an RFC to address a problem with the switch_ttbr function.
>    For the moment I haven't considered it since it's still a work in progress.

I have posted a new version for this:

https://lore.kernel.org/xen-devel/20221022150422.17707-1-julien@xen.org/

There are a couple of open questions about the interaction with cache 
coloring. Please have a look there.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-10-21 18:02   ` Julien Grall
@ 2022-10-25 10:53     ` Carlo Nonato
  2022-10-25 11:15       ` Julien Grall
  2023-01-26 12:05     ` Jan Beulich
  2023-01-26 12:07     ` Jan Beulich
  2 siblings, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-10-25 10:53 UTC (permalink / raw)
  To: Julien Grall, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Julien,

On Fri, Oct 21, 2022 at 8:02 PM Julien Grall <julien@xen.org> wrote:
>
> Hi Carlo,
>
> On 26/08/2022 13:51, Carlo Nonato wrote:
> > This commit adds array pointers to domains as well as to the hypercall
> > and configuration structure employed in domain creation. The latter is used
> > both by the toolstack and by Xen itself to pass configuration data to the
> > domain creation function, so the XEN_GUEST_HANDLE macro must be adopted to be
> > able to access guest memory in the first case. This implies special care for
> > the copy of the configuration data into the domain data, meaning that a
> > discrimination variable for the two possible code paths (coming from Xen or
> > from the toolstack) is needed.
>
> So this means that a toolstack could set from_guest. I know the
> toolstack is trusted... However, we should try to limit when the trust
> when this is possible.
>
> In this case, I would consider to modify the prototype of
> domain_create() to pass internal information.

Doing as you said isn't a bit too invasive? I should also change all the call
sites of domain_create() and this means x86 too.
Isn't there an easier way to spot a guest address? Maybe just looking at the
address value... Or maybe adding an internal flag to the do_domctl() path.

> > The initialization and free functions for colored domains are also added.
> > The former is responsible for allocating and populating the color array
> > of the domain and it also checks for configuration issues. One of those
> > issues is enabling both coloring and directmap for the domain because they
> > contradicts one another. Since that, Dom0 must not be created with the
> > directmap flag.
> > The latter instead frees allocated memory.
> >
> > Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
> > Signed-off-by: Marco Solieri <marco.solieri@minervasys.tech>
> > ---
> >   docs/misc/arm/cache-coloring.rst    |  7 ++--
> >   xen/arch/arm/coloring.c             | 56 +++++++++++++++++++++++++++++
> >   xen/arch/arm/domain.c               | 11 ++++++
> >   xen/arch/arm/domain_build.c         | 13 +++++--
> >   xen/arch/arm/include/asm/coloring.h |  7 ++++
> >   xen/arch/arm/include/asm/domain.h   |  4 +++
> >   xen/include/public/arch-arm.h       |  8 +++++
> >   7 files changed, 102 insertions(+), 4 deletions(-)
> >
> > diff --git a/docs/misc/arm/cache-coloring.rst b/docs/misc/arm/cache-coloring.rst
> > index c7adcb0f1f..345d97cb56 100644
> > --- a/docs/misc/arm/cache-coloring.rst
> > +++ b/docs/misc/arm/cache-coloring.rst
> > @@ -13,7 +13,7 @@ In order to enable and use it, few steps are needed.
> >     (refer to menuconfig help for value meaning and when it should be changed).
> >
> >           CONFIG_MAX_CACHE_COLORS=<n>
> > -- Assign colors to Dom0 using the `Color selection format`_ (see
> > +- Assign colors to domains using the `Color selection format`_ (see
> >     `Coloring parameters`_ for more documentation pointers).
> >
> >   Background
> > @@ -109,4 +109,7 @@ Coloring parameters
> >
> >   LLC way size (as previously discussed) and Dom0 colors can be set using the
> >   appropriate command line parameters. See the relevant documentation in
> > -"docs/misc/xen-command-line.pandoc".
> > \ No newline at end of file
> > +"docs/misc/xen-command-line.pandoc".
> > +
> > +Note that if no color configuration is provided for domains, they fallback to
> > +the default one, which corresponds simply to all available colors.
> > \ No newline at end of file
> > diff --git a/xen/arch/arm/coloring.c b/xen/arch/arm/coloring.c
> > index c010ebc01b..2b37cda067 100644
> > --- a/xen/arch/arm/coloring.c
> > +++ b/xen/arch/arm/coloring.c
> > @@ -22,6 +22,7 @@
> >    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >    */
> >   #include <xen/errno.h>
> > +#include <xen/guest_access.h>
> >   #include <xen/keyhandler.h>
> >   #include <xen/param.h>
> >   #include <xen/types.h>
> > @@ -211,6 +212,61 @@ bool __init coloring_init(void)
> >       return true;
> >   }
> >
> > +int domain_coloring_init(struct domain *d,
> > +                         const struct xen_arch_domainconfig *config)
> > +{
> > +    if ( is_domain_direct_mapped(d) )
> > +    {
> > +        printk(XENLOG_ERR
> > +               "Can't enable coloring and directmap at the same time for %pd\n",
> > +               d);
> > +        return -EINVAL;
> > +    }
> > +
> > +    if ( is_hardware_domain(d) )
> > +    {
> > +        d->arch.colors = dom0_colors;
> > +        d->arch.num_colors = dom0_num_colors;
> > +    }
>
> I think it would be better if we allocate an array also for the HW
> domain. This is not going to require too much extra memory and will help
> the code to be simpler.

Yep.

> I would also pass the color to domain_create(). So there is no logic
> specific to the HW domain here.

If we can avoid changing domain_create(), I can simply use
struct xen_domctl_createdomain to pass this data.

> > +    else if ( config->num_colors == 0 )
> > +    {
> > +        printk(XENLOG_WARNING
> > +               "Color config not found for %pd. Using default\n", d);
> > +        d->arch.colors = xzalloc_array(unsigned int, max_colors);
> > +        d->arch.num_colors = set_default_domain_colors(d->arch.colors);
> Ah, so your check in set_default_domain_colors() is here to cater this
> case? I would prefer if we check the allocation before using it. This
> will make it more obvious compare to expecting
> set_default_domain_colors() checking for NULL.
>
> > +    }
> > +    else
> > +    {
> > +        d->arch.colors = xzalloc_array(unsigned int, config->num_colors);
> > +        d->arch.num_colors = config->num_colors;
> > +        if ( config->from_guest )
> > +            copy_from_guest(d->arch.colors, config->colors, config->num_colors);
> > +        else
> > +            memcpy(d->arch.colors, config->colors.p,
> > +                   sizeof(unsigned int) * config->num_colors);
>
> See my remark above.
>
> > +    }
> > +
> > +    if ( !d->arch.colors )
> > +    {
> > +        printk(XENLOG_ERR "Colors allocation failed for %pd\n", d);
> > +        return -ENOMEM;
> > +    }
> > +
> > +    if ( !check_colors(d->arch.colors, d->arch.num_colors) )
> > +    {
> > +        printk(XENLOG_ERR "Bad color config for %pd\n", d);
> > +        return -EINVAL;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +void domain_coloring_free(struct domain *d)
> > +{
> > +    if ( !is_hardware_domain(d) )
> > +        xfree(d->arch.colors);
> > +}
> > +
> >   /*
> >    * Local variables:
> >    * mode: C
> > diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> > index 2d6253181a..c6fa8adc99 100644
> > --- a/xen/arch/arm/domain.c
> > +++ b/xen/arch/arm/domain.c
> > @@ -23,6 +23,9 @@
> >   #include <xen/wait.h>
> >
> >   #include <asm/alternative.h>
> > +#ifdef CONFIG_CACHE_COLORING
> > +#include <asm/coloring.h>
> > +#endif
> >   #include <asm/cpuerrata.h>
> >   #include <asm/cpufeature.h>
> >   #include <asm/current.h>
> > @@ -712,6 +715,11 @@ int arch_domain_create(struct domain *d,
> >       ioreq_domain_init(d);
> >   #endif
> >
> > +#ifdef CONFIG_CACHE_COLORING
>
> When !CONFIG_CACHE_COLORING, we should check that the color is not
> specified.
>
> > +    if ( (rc = domain_coloring_init(d, &config->arch)) )
> > +        goto fail;
> > +#endif
> > +
> >       /* p2m_init relies on some value initialized by the IOMMU subsystem */
> >       if ( (rc = iommu_domain_init(d, config->iommu_opts)) != 0 )
> >           goto fail;
> > @@ -807,6 +815,9 @@ void arch_domain_destroy(struct domain *d)
> >                          get_order_from_bytes(d->arch.efi_acpi_len));
> >   #endif
> >       domain_io_free(d);
> > +#ifdef CONFIG_CACHE_COLORING
> > +    domain_coloring_free(d);
> > +#endif
>
> See my remark in patch #1 about the #ifdef.
>
> >   }
> >
> >   void arch_domain_shutdown(struct domain *d)
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 3fd1186b53..4d4cb692fc 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -33,6 +33,12 @@
> >   #include <xen/grant_table.h>
> >   #include <xen/serial.h>
> >
> > +#ifdef CONFIG_CACHE_COLORING
> > +#define XEN_DOM0_CREATE_FLAGS CDF_privileged
> > +#else
> > +#define XEN_DOM0_CREATE_FLAGS CDF_privileged | CDF_directmap
> > +#endif
>
> I can't remember if I asked it before and it doesn't seem to written
> everywhere. This check suggest that it is not possible to use the same
> Xen binary for coloring and non-coloring.

If coloring is enabled, all the domains are colored (even if they use
zero colors
because of the default selection). This means that they are going to use
the colored allocator. Since this all-or-nothing design, if coloring is
enabled, dom0 is assumed to be colored, which implies removing the directmap
flag. So if what you mean with "same Xen binary for coloring and non-coloring"
is to have a way to select at runtime if a domain is colored, or if Xen
itself is colored, the answer is no, we don't have this right now.

> At the moment, we have been able to have all the features in the same
> Xen binary. So what are the reasons for this restriction?

Not sure about the first sentence (you mean, until this patch?), but the
restriction is just because it's simpler. For example if we have to support
colored and non-colored domains at the same time, we probably need to
change something in the allocator (at least reserving more memory for the
buddy).

> > +
> >   static unsigned int __initdata opt_dom0_max_vcpus;
> >   integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
> >
> > @@ -3399,7 +3405,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_ENABLED(CONFIG_CACHE_COLORING) )
>
> Even if we can't have a single Xen binary yet, I would prefer if we
> avoid using directly IS_ENABLED(CONFIG_CACHE_COLORING). Instead it would
> be better to provide an helper that check whether the domain has cache
> coloring is enabled.
>
> That helper could use IS_ENABLED(CONFIG_CACHE_COLORING) if that still
> wanted. The advantage is we make it easier to modify the code.

Ok.

> > +        allocate_memory(d, &kinfo);
> > +    else
> > +        allocate_memory_11(d, &kinfo);
> >       find_gnttab_region(d, &kinfo);
> >
> >       /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
> > @@ -3455,7 +3464,7 @@ void __init create_dom0(void)
> >       if ( iommu_enabled )
> >           dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu;
> >
> > -    dom0 = domain_create(0, &dom0_cfg, CDF_privileged | CDF_directmap);
> > +    dom0 = domain_create(0, &dom0_cfg, XEN_DOM0_CREATE_FLAGS);
> >       if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
> >           panic("Error creating domain 0\n");
> >
> > diff --git a/xen/arch/arm/include/asm/coloring.h b/xen/arch/arm/include/asm/coloring.h
> > index dd7eff5f07..60c8b1f079 100644
> > --- a/xen/arch/arm/include/asm/coloring.h
> > +++ b/xen/arch/arm/include/asm/coloring.h
> > @@ -25,7 +25,14 @@
> >   #define __ASM_ARM_COLORING_H__
> >
> >   #include <xen/init.h>
> > +#include <xen/sched.h>
> > +
> > +#include <public/arch-arm.h>
> >
> >   bool __init coloring_init(void);
> >
> > +int domain_coloring_init(struct domain *d,
> > +                         const struct xen_arch_domainconfig *config);
> > +void domain_coloring_free(struct domain *d);
> > +
> >   #endif /* !__ASM_ARM_COLORING_H__ */
> > diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
> > index 26a8348eed..291f7c375d 100644
> > --- a/xen/arch/arm/include/asm/domain.h
> > +++ b/xen/arch/arm/include/asm/domain.h
> > @@ -58,6 +58,10 @@ struct arch_domain
> >   #ifdef CONFIG_ARM_64
> >       enum domain_type type;
> >   #endif
>
> NIT: Newline here please. So we keep each feature in their own block.
>
> > +#ifdef CONFIG_CACHE_COLORING
> > +    unsigned int *colors;
> > +    unsigned int num_colors;
> > +#endif >
> >       /* Virtual MMU */
> >       struct p2m_domain p2m;
> > diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> > index c8b6058d3a..adf843a7a1 100644
> > --- a/xen/include/public/arch-arm.h
> > +++ b/xen/include/public/arch-arm.h
> > @@ -314,6 +314,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
> >   #define XEN_DOMCTL_CONFIG_TEE_NONE      0
> >   #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
> >
> > +__DEFINE_XEN_GUEST_HANDLE(color_t, unsigned int);
>
> You don't seem to use "color_t" outside of arch-arm.h and we already
> define guest handle for "unsigned int". So can they be used?

That's because the guest handle for "unsigned int" is defined later
(in public/xen.h). We can also think of moving the coloring fields from this
struct to the common one (xen_domctl_createdomain) protecting them with
the proper #ifdef (but we are targeting only arm64...).

> > +
> >   struct xen_arch_domainconfig {
> >       /* IN/OUT */
> >       uint8_t gic_version;
> > @@ -335,6 +337,12 @@ struct xen_arch_domainconfig {
> >        *
> >        */
> >       uint32_t clock_frequency;
> > +    /* IN */
> > +    uint8_t from_guest;
>
> There is an implicit padding here and ...
> > +    /* IN */
> > +    uint16_t num_colors;
>
> ... here. For the ABI, we are trying to have all the padding explicit.
> So the layout of the structure is clear.

Isn't it true also for other fields like gic_version and tee_type?

> Also, DOMCTL is an unstable ABI, so I think it would not be necessary to
> check the padding are zeroed. If it were a stable ABI, then we would
> need to check so they can be re-used in the future.
>
> > +    /* IN */
> > +    XEN_GUEST_HANDLE(color_t) colors;
> >   };
>
> Lastly, assuming this is the first patch touching the domctl for next
> release, you will want to bump the XEN_DOMCTL_INTERFACE_VERSION.

Ok.

> Cheers,
>
> --
> Julien Grall

Thanks.

-- Carlo Nonato


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-10-25 10:53     ` Carlo Nonato
@ 2022-10-25 11:15       ` Julien Grall
  2022-10-25 11:51         ` Andrea Bastoni
  2022-11-07 13:44         ` Carlo Nonato
  0 siblings, 2 replies; 60+ messages in thread
From: Julien Grall @ 2022-10-25 11:15 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri



On 25/10/2022 11:53, Carlo Nonato wrote:
> Hi Julien,
> 
> On Fri, Oct 21, 2022 at 8:02 PM Julien Grall <julien@xen.org> wrote:
>>
>> Hi Carlo,
>>
>> On 26/08/2022 13:51, Carlo Nonato wrote:
>>> This commit adds array pointers to domains as well as to the hypercall
>>> and configuration structure employed in domain creation. The latter is used
>>> both by the toolstack and by Xen itself to pass configuration data to the
>>> domain creation function, so the XEN_GUEST_HANDLE macro must be adopted to be
>>> able to access guest memory in the first case. This implies special care for
>>> the copy of the configuration data into the domain data, meaning that a
>>> discrimination variable for the two possible code paths (coming from Xen or
>>> from the toolstack) is needed.
>>
>> So this means that a toolstack could set from_guest. I know the
>> toolstack is trusted... However, we should try to limit when the trust
>> when this is possible.
>>
>> In this case, I would consider to modify the prototype of
>> domain_create() to pass internal information.
> 
> Doing as you said isn't a bit too invasive? I should also change all the call
> sites of domain_create() and this means x86 too.

Yes there will be a few calls to modify. But this is better than hacking 
the hypercall interface to cater for internal use.

> Isn't there an easier way to spot a guest address? Maybe just looking at the
> address value... 

HVM/Arm guest have a separate address space. So it is not possible to 
differentiate between guest vs hypervisor address.

> Or maybe adding an internal flag to the do_domctl() path.
IIUC, this flag would indicate whether the XEN_GUEST_HANDLE() is an 
hypervisor or guest address. Is that correct?

If so, I dislike it. I am not sure what the other maintainers think, but 
personally updating domain_create() is my preferred way.

[...]

>>>    void arch_domain_shutdown(struct domain *d)
>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>> index 3fd1186b53..4d4cb692fc 100644
>>> --- a/xen/arch/arm/domain_build.c
>>> +++ b/xen/arch/arm/domain_build.c
>>> @@ -33,6 +33,12 @@
>>>    #include <xen/grant_table.h>
>>>    #include <xen/serial.h>
>>>
>>> +#ifdef CONFIG_CACHE_COLORING
>>> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged
>>> +#else
>>> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged | CDF_directmap
>>> +#endif
>>
>> I can't remember if I asked it before and it doesn't seem to written
>> everywhere. This check suggest that it is not possible to use the same
>> Xen binary for coloring and non-coloring.
> 
> If coloring is enabled, all the domains are colored (even if they use
> zero colors
> because of the default selection). This means that they are going to use
> the colored allocator. Since this all-or-nothing design, if coloring is
> enabled, dom0 is assumed to be colored, which implies removing the directmap
> flag. So if what you mean with "same Xen binary for coloring and non-coloring"
> is to have a way to select at runtime if a domain is colored, or if Xen
> itself is colored, the answer is no, we don't have this right now.

[...]

> 
>> At the moment, we have been able to have all the features in the same
>> Xen binary. So what are the reasons for this restriction?
> 
> Not sure about the first sentence (you mean, until this patch?),

Yes.

> but the
> restriction is just because it's simpler. For example if we have to support
> colored and non-colored domains at the same time,

I am not asking for supporting a mix of colored and non-colored domains. 
What I am asking is to have a runtime switch (rather than compile time) 
to decide whether the system is colored or not.

IOW, why can't system-wide coloring be selected at runtime?

> we probably need to
> change something in the allocator (at least reserving more memory for the
> buddy).

This sentence picked my interesting. How do you decide the size of the 
buddy today?

[...]

>>> +#ifdef CONFIG_CACHE_COLORING
>>> +    unsigned int *colors;
>>> +    unsigned int num_colors;
>>> +#endif >
>>>        /* Virtual MMU */
>>>        struct p2m_domain p2m;
>>> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
>>> index c8b6058d3a..adf843a7a1 100644
>>> --- a/xen/include/public/arch-arm.h
>>> +++ b/xen/include/public/arch-arm.h
>>> @@ -314,6 +314,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
>>>    #define XEN_DOMCTL_CONFIG_TEE_NONE      0
>>>    #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
>>>
>>> +__DEFINE_XEN_GUEST_HANDLE(color_t, unsigned int);
>>
>> You don't seem to use "color_t" outside of arch-arm.h and we already
>> define guest handle for "unsigned int". So can they be used?
> 
> That's because the guest handle for "unsigned int" is defined later
> (in public/xen.h).

Hmmm... And I guess we can't define "unsigned int" earlier because they 
rely on macro defined in arch-arm.h?

> We can also think of moving the coloring fields from this
> struct to the common one (xen_domctl_createdomain) protecting them with
> the proper #ifdef (but we are targeting only arm64...).

Your code is targeting arm64 but fundamentally this is an arm64 specific 
feature. IOW, this could be used in the future on other arch. So I think 
it would make sense to define it in common without the #ifdef.

@x86 maintainers, what do you think?

> 
>>> +
>>>    struct xen_arch_domainconfig {
>>>        /* IN/OUT */
>>>        uint8_t gic_version;
>>> @@ -335,6 +337,12 @@ struct xen_arch_domainconfig {
>>>         *
>>>         */
>>>        uint32_t clock_frequency;
>>> +    /* IN */
>>> +    uint8_t from_guest;
>>
>> There is an implicit padding here and ...
>>> +    /* IN */
>>> +    uint16_t num_colors;
>>
>> ... here. For the ABI, we are trying to have all the padding explicit.
>> So the layout of the structure is clear.
> 
> Isn't it true also for other fields like gic_version and tee_type?

Indeed, there is missing explicit padding after gic_version. There is no 
padding necessary after 'tee_type'.

I am not asking you to fix the existing missing padding, however we 
should avoid to introduce new ones.

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-10-25 11:15       ` Julien Grall
@ 2022-10-25 11:51         ` Andrea Bastoni
  2022-11-07 13:44         ` Carlo Nonato
  1 sibling, 0 replies; 60+ messages in thread
From: Andrea Bastoni @ 2022-10-25 11:51 UTC (permalink / raw)
  To: Julien Grall, Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, lucmiccio, Marco Solieri, Jan Kiszka

Hi Julien,

On 25/10/2022 13:15, Julien Grall wrote:
> 
> 
> On 25/10/2022 11:53, Carlo Nonato wrote:
>> Hi Julien,
>>
>> On Fri, Oct 21, 2022 at 8:02 PM Julien Grall <julien@xen.org> wrote:
>>>
>>> Hi Carlo,
>>>
>>> On 26/08/2022 13:51, Carlo Nonato wrote:
>>>> This commit adds array pointers to domains as well as to the hypercall
>>>> and configuration structure employed in domain creation. The latter is used
>>>> both by the toolstack and by Xen itself to pass configuration data to the
>>>> domain creation function, so the XEN_GUEST_HANDLE macro must be adopted to be
>>>> able to access guest memory in the first case. This implies special care for
>>>> the copy of the configuration data into the domain data, meaning that a
>>>> discrimination variable for the two possible code paths (coming from Xen or
>>>> from the toolstack) is needed.
>>>
>>> So this means that a toolstack could set from_guest. I know the
>>> toolstack is trusted... However, we should try to limit when the trust
>>> when this is possible.
>>>
>>> In this case, I would consider to modify the prototype of
>>> domain_create() to pass internal information.
>>
>> Doing as you said isn't a bit too invasive? I should also change all the call
>> sites of domain_create() and this means x86 too.
> 
> Yes there will be a few calls to modify. But this is better than hacking the 
> hypercall interface to cater for internal use.
> 
>> Isn't there an easier way to spot a guest address? Maybe just looking at the
>> address value... 
> 
> HVM/Arm guest have a separate address space. So it is not possible to 
> differentiate between guest vs hypervisor address.
> 
>> Or maybe adding an internal flag to the do_domctl() path.
> IIUC, this flag would indicate whether the XEN_GUEST_HANDLE() is an hypervisor 
> or guest address. Is that correct?
> 
> If so, I dislike it. I am not sure what the other maintainers think, but 
> personally updating domain_create() is my preferred way.
> 
> [...]
> 
>>>>    void arch_domain_shutdown(struct domain *d)
>>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>>> index 3fd1186b53..4d4cb692fc 100644
>>>> --- a/xen/arch/arm/domain_build.c
>>>> +++ b/xen/arch/arm/domain_build.c
>>>> @@ -33,6 +33,12 @@
>>>>    #include <xen/grant_table.h>
>>>>    #include <xen/serial.h>
>>>>
>>>> +#ifdef CONFIG_CACHE_COLORING
>>>> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged
>>>> +#else
>>>> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged | CDF_directmap
>>>> +#endif
>>>
>>> I can't remember if I asked it before and it doesn't seem to written
>>> everywhere. This check suggest that it is not possible to use the same
>>> Xen binary for coloring and non-coloring.
>>
>> If coloring is enabled, all the domains are colored (even if they use
>> zero colors
>> because of the default selection). This means that they are going to use
>> the colored allocator. Since this all-or-nothing design, if coloring is
>> enabled, dom0 is assumed to be colored, which implies removing the directmap
>> flag. So if what you mean with "same Xen binary for coloring and non-coloring"
>> is to have a way to select at runtime if a domain is colored, or if Xen
>> itself is colored, the answer is no, we don't have this right now.
> 
> [...]
> 
>>
>>> At the moment, we have been able to have all the features in the same
>>> Xen binary. So what are the reasons for this restriction?
>>
>> Not sure about the first sentence (you mean, until this patch?),
> 
> Yes.
> 
>> but the
>> restriction is just because it's simpler. For example if we have to support
>> colored and non-colored domains at the same time,
> 
> I am not asking for supporting a mix of colored and non-colored domains. What I 
> am asking is to have a runtime switch (rather than compile time) to decide 
> whether the system is colored or not.
> 
> IOW, why can't system-wide coloring be selected at runtime?
> 
>> we probably need to
>> change something in the allocator (at least reserving more memory for the
>> buddy).
> 
> This sentence picked my interesting. How do you decide the size of the buddy today?
> 
> [...]
> 
>>>> +#ifdef CONFIG_CACHE_COLORING
>>>> +    unsigned int *colors;
>>>> +    unsigned int num_colors;
>>>> +#endif >
>>>>        /* Virtual MMU */
>>>>        struct p2m_domain p2m;
>>>> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
>>>> index c8b6058d3a..adf843a7a1 100644
>>>> --- a/xen/include/public/arch-arm.h
>>>> +++ b/xen/include/public/arch-arm.h
>>>> @@ -314,6 +314,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
>>>>    #define XEN_DOMCTL_CONFIG_TEE_NONE      0
>>>>    #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
>>>>
>>>> +__DEFINE_XEN_GUEST_HANDLE(color_t, unsigned int);
>>>
>>> You don't seem to use "color_t" outside of arch-arm.h and we already
>>> define guest handle for "unsigned int". So can they be used?
>>
>> That's because the guest handle for "unsigned int" is defined later
>> (in public/xen.h).
> 
> Hmmm... And I guess we can't define "unsigned int" earlier because they rely on 
> macro defined in arch-arm.h?
> 
>> We can also think of moving the coloring fields from this
>> struct to the common one (xen_domctl_createdomain) protecting them with
>> the proper #ifdef (but we are targeting only arm64...).
> 
> Your code is targeting arm64 but fundamentally this is an arm64 specific 
> feature. IOW, this could be used in the future on other arch. So I think it 
> would make sense to define it in common without the #ifdef.

As additional information on this point, we had in the past some discussion in 
the context of cache-coloring and Jailhouse (+CC Jan):

https://groups.google.com/g/jailhouse-dev/c/K4rqZxpxa0U/m/lsvy5HXcAAAJ

x86 has CAT and RDT, and supporting software coloring was not in scope for 
Jailhouse. The discussion was more on perspective support for RISC-V.

Best,

> @x86 maintainers, what do you think?
> 
>>
>>>> +
>>>>    struct xen_arch_domainconfig {
>>>>        /* IN/OUT */
>>>>        uint8_t gic_version;
>>>> @@ -335,6 +337,12 @@ struct xen_arch_domainconfig {
>>>>         *
>>>>         */
>>>>        uint32_t clock_frequency;
>>>> +    /* IN */
>>>> +    uint8_t from_guest;
>>>
>>> There is an implicit padding here and ...
>>>> +    /* IN */
>>>> +    uint16_t num_colors;
>>>
>>> ... here. For the ABI, we are trying to have all the padding explicit.
>>> So the layout of the structure is clear.
>>
>> Isn't it true also for other fields like gic_version and tee_type?
> 
> Indeed, there is missing explicit padding after gic_version. There is no padding 
> necessary after 'tee_type'.
> 
> I am not asking you to fix the existing missing padding, however we should avoid 
> to introduce new ones.
> 
> Cheers,
> 
-- 
Thanks,
Andrea Bastoni



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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-10-25 11:15       ` Julien Grall
  2022-10-25 11:51         ` Andrea Bastoni
@ 2022-11-07 13:44         ` Carlo Nonato
  2022-11-07 18:24           ` Julien Grall
  1 sibling, 1 reply; 60+ messages in thread
From: Carlo Nonato @ 2022-11-07 13:44 UTC (permalink / raw)
  To: Julien Grall, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri

Hi Julien,

On Tue, Oct 25, 2022 at 1:15 PM Julien Grall <julien@xen.org> wrote:
> On 25/10/2022 11:53, Carlo Nonato wrote:
> > Hi Julien,
> >
> > On Fri, Oct 21, 2022 at 8:02 PM Julien Grall <julien@xen.org> wrote:
> >>
> >> Hi Carlo,
> >>
> >> On 26/08/2022 13:51, Carlo Nonato wrote:
> >>> This commit adds array pointers to domains as well as to the hypercall
> >>> and configuration structure employed in domain creation. The latter is used
> >>> both by the toolstack and by Xen itself to pass configuration data to the
> >>> domain creation function, so the XEN_GUEST_HANDLE macro must be adopted to be
> >>> able to access guest memory in the first case. This implies special care for
> >>> the copy of the configuration data into the domain data, meaning that a
> >>> discrimination variable for the two possible code paths (coming from Xen or
> >>> from the toolstack) is needed.
> >>
> >> So this means that a toolstack could set from_guest. I know the
> >> toolstack is trusted... However, we should try to limit when the trust
> >> when this is possible.
> >>
> >> In this case, I would consider to modify the prototype of
> >> domain_create() to pass internal information.
> >
> > Doing as you said isn't a bit too invasive? I should also change all the call
> > sites of domain_create() and this means x86 too.
>
> Yes there will be a few calls to modify. But this is better than hacking
> the hypercall interface to cater for internal use.
>
> > Isn't there an easier way to spot a guest address? Maybe just looking at the
> > address value...
>
> HVM/Arm guest have a separate address space. So it is not possible to
> differentiate between guest vs hypervisor address.
>
> > Or maybe adding an internal flag to the do_domctl() path.
> IIUC, this flag would indicate whether the XEN_GUEST_HANDLE() is an
> hypervisor or guest address. Is that correct?
>
> If so, I dislike it. I am not sure what the other maintainers think, but
> personally updating domain_create() is my preferred way.

Sorry to bother you again on this topic, but I thought of a way to get rid of
the "from_guest" field which I hope is simple enough to convince you.
I can call copy_from_guest() *only* in domctl.c, overwriting the colors
pointer with a new, Xen allocated, array.
This lets me simplify the logic in domain_coloring_init() since all the arrays
coming to it via the domainconfig struct are allocated in Xen memory only.
It's still a bit of a hack since I'm using the XEN_GUEST_HANDLE as a normal
Xen pointer, but it's by far less hacky than before and doesn't have the trust
problem.

> [...]
>
> >>>    void arch_domain_shutdown(struct domain *d)
> >>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> >>> index 3fd1186b53..4d4cb692fc 100644
> >>> --- a/xen/arch/arm/domain_build.c
> >>> +++ b/xen/arch/arm/domain_build.c
> >>> @@ -33,6 +33,12 @@
> >>>    #include <xen/grant_table.h>
> >>>    #include <xen/serial.h>
> >>>
> >>> +#ifdef CONFIG_CACHE_COLORING
> >>> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged
> >>> +#else
> >>> +#define XEN_DOM0_CREATE_FLAGS CDF_privileged | CDF_directmap
> >>> +#endif
> >>
> >> I can't remember if I asked it before and it doesn't seem to written
> >> everywhere. This check suggest that it is not possible to use the same
> >> Xen binary for coloring and non-coloring.
> >
> > If coloring is enabled, all the domains are colored (even if they use
> > zero colors
> > because of the default selection). This means that they are going to use
> > the colored allocator. Since this all-or-nothing design, if coloring is
> > enabled, dom0 is assumed to be colored, which implies removing the directmap
> > flag. So if what you mean with "same Xen binary for coloring and non-coloring"
> > is to have a way to select at runtime if a domain is colored, or if Xen
> > itself is colored, the answer is no, we don't have this right now.
>
> [...]
>
> >
> >> At the moment, we have been able to have all the features in the same
> >> Xen binary. So what are the reasons for this restriction?
> >
> > Not sure about the first sentence (you mean, until this patch?),
>
> Yes.
>
> > but the
> > restriction is just because it's simpler. For example if we have to support
> > colored and non-colored domains at the same time,
>
> I am not asking for supporting a mix of colored and non-colored domains.
> What I am asking is to have a runtime switch (rather than compile time)
> to decide whether the system is colored or not.
>
> IOW, why can't system-wide coloring be selected at runtime?

This is definitely doable. Do you also think the compile time switch is
useless? Should we get rid of that?

> > we probably need to
> > change something in the allocator (at least reserving more memory for the
> > buddy).
>
> This sentence picked my interesting. How do you decide the size of the
> buddy today?

The user can actually choose it arbitrarily and there is no particular
calculation behind the default value (64M): it's just a reasonable sounding
value.

> [...]
>
> >>> +#ifdef CONFIG_CACHE_COLORING
> >>> +    unsigned int *colors;
> >>> +    unsigned int num_colors;
> >>> +#endif >
> >>>        /* Virtual MMU */
> >>>        struct p2m_domain p2m;
> >>> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> >>> index c8b6058d3a..adf843a7a1 100644
> >>> --- a/xen/include/public/arch-arm.h
> >>> +++ b/xen/include/public/arch-arm.h
> >>> @@ -314,6 +314,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
> >>>    #define XEN_DOMCTL_CONFIG_TEE_NONE      0
> >>>    #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
> >>>
> >>> +__DEFINE_XEN_GUEST_HANDLE(color_t, unsigned int);
> >>
> >> You don't seem to use "color_t" outside of arch-arm.h and we already
> >> define guest handle for "unsigned int". So can they be used?
> >
> > That's because the guest handle for "unsigned int" is defined later
> > (in public/xen.h).
>
> Hmmm... And I guess we can't define "unsigned int" earlier because they
> rely on macro defined in arch-arm.h?

Exactly.

> > We can also think of moving the coloring fields from this
> > struct to the common one (xen_domctl_createdomain) protecting them with
> > the proper #ifdef (but we are targeting only arm64...).
>
> Your code is targeting arm64 but fundamentally this is an arm64 specific
> feature. IOW, this could be used in the future on other arch. So I think
> it would make sense to define it in common without the #ifdef.
>
> @x86 maintainers, what do you think?
>
> >
> >>> +
> >>>    struct xen_arch_domainconfig {
> >>>        /* IN/OUT */
> >>>        uint8_t gic_version;
> >>> @@ -335,6 +337,12 @@ struct xen_arch_domainconfig {
> >>>         *
> >>>         */
> >>>        uint32_t clock_frequency;
> >>> +    /* IN */
> >>> +    uint8_t from_guest;
> >>
> >> There is an implicit padding here and ...
> >>> +    /* IN */
> >>> +    uint16_t num_colors;
> >>
> >> ... here. For the ABI, we are trying to have all the padding explicit.
> >> So the layout of the structure is clear.
> >
> > Isn't it true also for other fields like gic_version and tee_type?
>
> Indeed, there is missing explicit padding after gic_version. There is no
> padding necessary after 'tee_type'.
>
> I am not asking you to fix the existing missing padding, however we
> should avoid to introduce new ones.

Understood.

> Cheers,
>
> --
> Julien Grall

Thanks.

- Carlo Nonato


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-11-07 13:44         ` Carlo Nonato
@ 2022-11-07 18:24           ` Julien Grall
  0 siblings, 0 replies; 60+ messages in thread
From: Julien Grall @ 2022-11-07 18:24 UTC (permalink / raw)
  To: Carlo Nonato, xen-devel
  Cc: andrew.cooper3, george.dunlap, jbeulich, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri



On 07/11/2022 13:44, Carlo Nonato wrote:
> Hi Julien,

Hi Carlo,

> On Tue, Oct 25, 2022 at 1:15 PM Julien Grall <julien@xen.org> wrote:
>> On 25/10/2022 11:53, Carlo Nonato wrote:
>>> Hi Julien,
>>>
>>> On Fri, Oct 21, 2022 at 8:02 PM Julien Grall <julien@xen.org> wrote:
>>>>
>>>> Hi Carlo,
>>>>
>>>> On 26/08/2022 13:51, Carlo Nonato wrote:
>>>>> This commit adds array pointers to domains as well as to the hypercall
>>>>> and configuration structure employed in domain creation. The latter is used
>>>>> both by the toolstack and by Xen itself to pass configuration data to the
>>>>> domain creation function, so the XEN_GUEST_HANDLE macro must be adopted to be
>>>>> able to access guest memory in the first case. This implies special care for
>>>>> the copy of the configuration data into the domain data, meaning that a
>>>>> discrimination variable for the two possible code paths (coming from Xen or
>>>>> from the toolstack) is needed.
>>>>
>>>> So this means that a toolstack could set from_guest. I know the
>>>> toolstack is trusted... However, we should try to limit when the trust
>>>> when this is possible.
>>>>
>>>> In this case, I would consider to modify the prototype of
>>>> domain_create() to pass internal information.
>>>
>>> Doing as you said isn't a bit too invasive? I should also change all the call
>>> sites of domain_create() and this means x86 too.
>>
>> Yes there will be a few calls to modify. But this is better than hacking
>> the hypercall interface to cater for internal use.
>>
>>> Isn't there an easier way to spot a guest address? Maybe just looking at the
>>> address value...
>>
>> HVM/Arm guest have a separate address space. So it is not possible to
>> differentiate between guest vs hypervisor address.
>>
>>> Or maybe adding an internal flag to the do_domctl() path.
>> IIUC, this flag would indicate whether the XEN_GUEST_HANDLE() is an
>> hypervisor or guest address. Is that correct?
>>
>> If so, I dislike it. I am not sure what the other maintainers think, but
>> personally updating domain_create() is my preferred way.
> 
> Sorry to bother you again on this topic, but I thought of a way to get rid of
> the "from_guest" field which I hope is simple enough to convince you.
> I can call copy_from_guest() *only* in domctl.c, overwriting the colors
> pointer with a new, Xen allocated, array.
> This lets me simplify the logic in domain_coloring_init() since all the arrays
> coming to it via the domainconfig struct are allocated in Xen memory only.
> It's still a bit of a hack since I'm using the XEN_GUEST_HANDLE as a normal
> Xen pointer, but it's by far less hacky than before and doesn't have the trust
> problem.

You don't have the trust problem but you are still mixing guest handle 
and xen pointer. I continue dislike this because this a gross hack that 
may save you some effort today but will be a nightmare to 
review/use/maintain (the developer will have to remember whether the 
field contain a guest address or xen address).

Cheers,

-- 
Julien Grall


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-10-21 18:02   ` Julien Grall
  2022-10-25 10:53     ` Carlo Nonato
@ 2023-01-26 12:05     ` Jan Beulich
  2023-01-26 12:07     ` Jan Beulich
  2 siblings, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2023-01-26 12:05 UTC (permalink / raw)
  To: Julien Grall, Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 21.10.2022 20:02, Julien Grall wrote:
> On 26/08/2022 13:51, Carlo Nonato wrote:
>> This commit adds array pointers to domains as well as to the hypercall
>> and configuration structure employed in domain creation. The latter is used
>> both by the toolstack and by Xen itself to pass configuration data to the
>> domain creation function, so the XEN_GUEST_HANDLE macro must be adopted to be
>> able to access guest memory in the first case. This implies special care for
>> the copy of the configuration data into the domain data, meaning that a
>> discrimination variable for the two possible code paths (coming from Xen or
>> from the toolstack) is needed.
> 
> So this means that a toolstack could set from_guest. I know the 
> toolstack is trusted... However, we should try to limit when the trust 
> when this is possible.
> 
> In this case, I would consider to modify the prototype of 
> domain_create() to pass internal information.

Since I was pointed at this in the context of reviewing v4: The way a
clone of domain_create() was introduced there is, as pointed out there,
not scalable. Imo the prototype shouldn't change unless really needed
(i.e. benefiting at least a fair share of callers), and clones like
this one also shouldn't be introduced.

Hopefully this is all moot now anyway, with - as it looks - there being
agreement that this won't need to be part of domain_create() anymore.

Jan


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

* Re: [PATCH 02/12] xen/arm: add cache coloring initialization for domains
  2022-10-21 18:02   ` Julien Grall
  2022-10-25 10:53     ` Carlo Nonato
  2023-01-26 12:05     ` Jan Beulich
@ 2023-01-26 12:07     ` Jan Beulich
  2 siblings, 0 replies; 60+ messages in thread
From: Jan Beulich @ 2023-01-26 12:07 UTC (permalink / raw)
  To: Julien Grall, Carlo Nonato
  Cc: andrew.cooper3, george.dunlap, stefano.stabellini, wl,
	marco.solieri, andrea.bastoni, lucmiccio, Marco Solieri,
	xen-devel

On 21.10.2022 20:02, Julien Grall wrote:
> On 26/08/2022 13:51, Carlo Nonato wrote:
>> @@ -335,6 +337,12 @@ struct xen_arch_domainconfig {
>>        *
>>        */
>>       uint32_t clock_frequency;
>> +    /* IN */
>> +    uint8_t from_guest;
> 
> There is an implicit padding here and ...
>> +    /* IN */
>> +    uint16_t num_colors;
> 
> ... here. For the ABI, we are trying to have all the padding explicit. 
> So the layout of the structure is clear.
> 
> Also, DOMCTL is an unstable ABI, so I think it would not be necessary to 
> check the padding are zeroed. If it were a stable ABI, then we would 
> need to check so they can be re-used in the future.

Independently of the other reply, a comment here as well: While domctl
being unstable does permit to omit zero checks, I think we're well
advised to still have them. The we can re-use such fields without
needing to bump the interface version.

Jan


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

end of thread, other threads:[~2023-01-26 12:08 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-26 12:50 [PATCH 00/12] Arm cache coloring Carlo Nonato
2022-08-26 12:51 ` [PATCH 01/12] xen/arm: add cache coloring initialization Carlo Nonato
2022-09-26  6:20   ` Wei Chen
2022-09-26  7:42     ` Jan Beulich
2022-09-27 14:31       ` Carlo Nonato
2022-10-21 17:14   ` Julien Grall
2022-08-26 12:51 ` [PATCH 02/12] xen/arm: add cache coloring initialization for domains Carlo Nonato
2022-09-26  6:39   ` Wei Chen
2022-09-27 14:31     ` Carlo Nonato
2022-10-21 17:25     ` Julien Grall
2022-10-21 18:02   ` Julien Grall
2022-10-25 10:53     ` Carlo Nonato
2022-10-25 11:15       ` Julien Grall
2022-10-25 11:51         ` Andrea Bastoni
2022-11-07 13:44         ` Carlo Nonato
2022-11-07 18:24           ` Julien Grall
2023-01-26 12:05     ` Jan Beulich
2023-01-26 12:07     ` Jan Beulich
2022-10-21 18:04   ` Julien Grall
2022-08-26 12:51 ` [PATCH 03/12] xen/arm: dump cache colors in domain info debug-key Carlo Nonato
2022-08-26 12:51 ` [PATCH 04/12] tools/xl: add support for cache coloring configuration Carlo Nonato
2022-10-21 18:09   ` Julien Grall
2022-08-26 12:51 ` [PATCH 05/12] xen/arm: add support for cache coloring configuration via device-tree Carlo Nonato
2022-08-26 12:51 ` [PATCH 06/12] xen/common: add cache coloring allocator for domains Carlo Nonato
2022-09-15 13:13   ` Jan Beulich
2022-09-16 16:05     ` Carlo Nonato
2022-09-19  6:26       ` Jan Beulich
2022-09-19 22:42         ` Stefano Stabellini
2022-09-20  7:54           ` Jan Beulich
2022-10-13  9:47         ` Carlo Nonato
2022-10-13 10:44           ` Jan Beulich
2022-10-17  7:06   ` Michal Orzel
2022-10-17  8:44     ` Julien Grall
2022-10-17  9:16       ` Michal Orzel
2022-08-26 12:51 ` [PATCH 07/12] xen/common: add colored heap info debug-key Carlo Nonato
2022-08-26 14:13   ` Jan Beulich
2022-08-26 16:04     ` Carlo Nonato
2022-08-26 12:51 ` [PATCH 08/12] Revert "xen/arm: setup: Add Xen as boot module before printing all boot modules" Carlo Nonato
2022-09-10 14:01   ` Julien Grall
2022-09-12 13:54     ` Carlo Nonato
2022-10-21 16:52       ` Julien Grall
2022-08-26 12:51 ` [PATCH 09/12] Revert "xen/arm: mm: Initialize page-tables earlier" Carlo Nonato
2022-09-10 14:28   ` Julien Grall
2022-09-12 13:59     ` Carlo Nonato
2022-08-26 12:51 ` [PATCH 10/12] Revert "xen/arm: Remove unused BOOT_RELOC_VIRT_START" Carlo Nonato
2022-08-26 12:51 ` [PATCH 11/12] xen/arm: add Xen cache colors command line parameter Carlo Nonato
2022-08-26 12:51 ` [PATCH 12/12] xen/arm: add cache coloring support for Xen Carlo Nonato
2022-09-10 15:22   ` Julien Grall
2022-09-10 15:23     ` Julien Grall
2022-09-15 13:25   ` Jan Beulich
2022-09-16 16:07     ` Carlo Nonato
2022-09-19  8:38       ` Jan Beulich
2022-09-27 14:31         ` Carlo Nonato
2022-09-27 15:28           ` Jan Beulich
2022-09-10 15:12 ` [PATCH 00/12] Arm cache coloring Julien Grall
2022-09-12 13:24   ` Carlo Nonato
2022-09-15 13:29 ` Jan Beulich
2022-09-15 14:52   ` Marco Solieri
2022-09-15 18:15   ` Stefano Stabellini
2022-10-22 15:13 ` Julien Grall

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.