On 6/11/25 7:16 PM, Roger Pau Monne wrote:
Allow controlling whether to attempt PDX compression, and which algorithm
to use to calculate the coefficients. Document the option and also add a
CHANGELOG entry for the newly added feature.
Note the work has been originally done to cope with the new Intel
Sapphire/Granite Rapids, however the compression is not explicitly tied to
Intel or x86, and hence could be helpful on other architectures.
Signed-off-by: Roger Pau Monné<roger....@citrix.com>
---
CHANGELOG.md | 3 +++
docs/misc/xen-command-line.pandoc | 22 ++++++++++++++++++
xen/common/pdx.c | 38 +++++++++++++++++++++++++++----
3 files changed, 59 insertions(+), 4 deletions(-)
LGTM: Reviewed-by: Oleksii Kurochko<oleksii.kuroc...@gmail.com>
Thanks.
~ Oleksii
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 23215a8cc1e6..48327f03078f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,9 @@ The format is based on [Keep a
Changelog](https://keepachangelog.com/en/1.0.0/)
table or foreign memory.
### Added
+ - Introduce new PDX compression algorithm to cope with Intel Sapphire and
+ Granite Rapids having sparse memory maps.
+
- On x86:
- Option to attempt to fixup p2m page-faults on PVH dom0.
- Resizable BARs is supported for PVH dom0.
diff --git a/docs/misc/xen-command-line.pandoc
b/docs/misc/xen-command-line.pandoc
index b0eadd2c5d58..06819576a06b 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -2072,6 +2072,28 @@ for all of them (`true`), only for those subject to XPTI
(`xpti`) or for
those not subject to XPTI (`no-xpti`). The feature is used only in case
INVPCID is supported and not disabled via `invpcid=false`.
+### pdx-compress
+> `= <boolean> | auto | fast | slow`
+
+> Default: `auto`
+
+Only relevant when hypervisor is build with PFN PDX offset compression
+`CONFIG_PDX_OFFSET_COMPRESSION`.
+
+Controls whether Xen will engage in PFN compression, and which algorithm will
+be used to calculate the compression coefficients:
+
+* `auto`: default choice, attempt fast calculation of compression
+ coefficients, if that's not successful fallback to slow calculation.
+
+* `fast`: only attempt fast calculation of coefficients, if it fails PFN PDX
+ compression will be disabled.
+
+* `slow`: only attempt slow calculation of coefficients, if it fails PFN PDX
+ compression will be disabled.
+
+Note `pdx-compress=true` is equivalent to `pdx-compress=auto`.
+
### ple_gap
> `= <integer>`
diff --git a/xen/common/pdx.c b/xen/common/pdx.c
index feabdcded804..5fd01305a7be 100644
--- a/xen/common/pdx.c
+++ b/xen/common/pdx.c
@@ -19,6 +19,7 @@
#include <xen/mm.h>
#include <xen/bitops.h>
#include <xen/nospec.h>
+#include <xen/param.h>
#include <xen/pfn.h>
#include <xen/sections.h>
#include <xen/sort.h>
@@ -468,11 +469,40 @@ STATIC void __init pfn_offset_sanitize_ranges(void)
}
#ifdef __XEN__
+static enum {
+ PDX_AUTO, /* Fast first, fallback to slow if fast is not successful. */
+ PDX_NO, /* Do not attempt compression. */
+ PDX_FAST, /* Only attempt fast calculation of compression parameters. */
+ PDX_SLOW, /* Only attempt slow calculation of compression parameters. */
+} compress_mode __initdata;
+
+static int __init cf_check parse_pdx_param(const char *arg)
+{
+ int val;
+
+ if ( !arg )
+ return -EINVAL;
+
+ if ( (val = parse_bool(arg, NULL)) != -1 )
+ compress_mode = val ? PDX_AUTO : PDX_NO;
+ else if ( !strcmp(arg, "auto") )
+ compress_mode = PDX_AUTO;
+ else if ( !strcmp(arg, "fast") )
+ compress_mode = PDX_FAST;
+ else if ( !strcmp(arg, "slow") )
+ compress_mode = PDX_SLOW;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+custom_param("pdx-compress", parse_pdx_param);
+
bool __init pfn_pdx_compression_setup(paddr_t base)
{
- bool use_slow = false;
+ bool use_slow = compress_mode == PDX_SLOW;
- if ( nr <= 1 )
+ if ( nr <= 1 || compress_mode == PDX_NO )
return false;
if ( nr > ARRAY_SIZE(ranges) )
@@ -507,11 +537,11 @@ bool __init pfn_pdx_compression_setup(paddr_t base)
dprintk(XENLOG_DEBUG,
"Find PFN compression coefficients using %s algorithm
failed\n",
use_slow ? "slow" : "fast");
- if ( use_slow )
+ if ( compress_mode == PDX_FAST || use_slow )
return false;
}
- if ( use_slow )
+ if ( compress_mode == PDX_FAST || use_slow )
break;
}