* [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable
@ 2025-07-16 20:15 Petr Beneš
2025-07-16 20:15 ` [PATCH v10 1/9] tools/xl: Add altp2m_count parameter Petr Beneš
` (8 more replies)
0 siblings, 9 replies; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel
Cc: Petr Beneš, Nick Rosbrook, George Dunlap, Anthony PERARD,
Juergen Gross, Jan Beulich, Andrew Cooper, Roger Pau Monné,
Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Shawn Anastasio, Alistair Francis,
Bob Eshleman, Connor Davis, Oleksii Kurochko, Tamas K Lengyel,
Alexandru Isaila, Petre Pircalabu, Christian Lindig, David Scott
From: Petr Beneš <w1benny@gmail.com>
This series introduces the ability to configure the maximum number of altp2m
tables during domain creation. Previously, the limits were hardcoded to a
maximum of 10. This change allows for greater flexibility in environments that
require more or fewer altp2m views.
This enhancement is particularly relevant for users leveraging Xen's features
for virtual machine introspection.
Changes since v9:
- Introduced 3 more patches:
- x86/p2m: Short-circuit p2m_is_altp2m() when CONFIG_ALTP2M=n
- Needed to optimize out `if ( p2m_is_altp2m(p2m) )` when CONFIG_ALTP2M=n.
- x86/altp2m: Remove p2m_altp2m_check stubs from unsupported architectures
- Removes p2m_altp2m_check stubs from archs that don't support altp2m.
- x86/altp2m: Wrap altp2m-specific code in #ifdef CONFIG_ALTP2M
- Self-explanatory - based on Jans review suggestion
- Small changes based on review:
- if ( v->domain->nr_altp2m == 0 ) -> if ( !v->domain->nr_altp2m )
- removed unnecessary condition in p2m_teardown_altp2m
- Added ASSERT(!config->altp2m.nr) when CONFIG_ALTP2M=n in domain_create
Changes since v8:
- Removed 1st patch, which was already applied.
- Removed Reviewed-by from "tools/xl: Add altp2m_count parameter" patch.
- (No code changes)
Changes since v7:
- Fix condition in libxl_create.c that caused assertions in CI.
- Removed incorrect mention of introduction of hvm_altp2m_supported() in commit
message of patch 0004.
- Adjust comments in altp2m_is_eptp_valid().
- Guard ALTP2M features with CONFIG_ALTP2M where appropriate. I made my best to
ensure that the following configurations compile correctly:
* CONFIG_HVM=n (CONFIG_ALTP2M=n implied)
* CONFIG_HVM=y CONFIG_ALTP2M=n
* CONFIG_HVM=y CONFIG_ALTP2M=y
* Note: Besides taking inspiration from CONFIG_MEM_SHARING &
CONFIG_MEM_PAGING, the reason for guards instead of wrapper methods is that
all ALTP2M features and fields became guarded by CONFIG_ALTP2M - therefore,
lots of code inside ALTP2M blocks would be touching inexisting fields.
This could be solved by introducing wrapped functions for each ALTP2M
field, but I believe that would be overkill.
Changes since v6:
- Rebased on top of staging
- Added missing Acks/Reviewed-bys where appropriate.
- No changes in patches since v6, with the exception of 0004: xen: Make the
maximum number of altp2m views configurable for x86... which was the only
patch that was left unacked/not reviewed
- In that patch, I made changes suggested by Jan - that is:
- Create altp2m_is_eptp_valid function and use it in places where
we don't control the index
- Fixed a nit: "Number of altp2ms to allocate." -> "... to permit."
- Cosmetic: moved altp2m_vcpu_idx() in altp2m.h up, so the order of
functions matches with the order in the #else block
Changes since v5:
- Reverted "Introduction of accessor functions for altp2m arrays and
refactoring the code to use them."
- Reason is minimizing the code changes, and save the code consistency.
- I've addressed (hopefully all) issues with long lines and mismatched
_nospec replacements mentioned in previous reviews.
- Removed "struct domain *d" from altp2m_vcpu_initialise/destroy.
Changes since v4:
- Rebased on top of staging (applying Roger's changes).
- Fix mixed tabs/spaces in xenctrl_stubs.c.
- Add missing OCaml bindings for altp2m_opts.
- Substitute altp2m_opts into an unnamed structure. (This is a preparation for
the next patch that will introduce the `nr` field.)
- altp2m.opts is then shortened to uint16_t and a new field altp2m.nr is added -
also uint16_t. This value is then verified by libxl to not exceed the maximum
uint16_t value.
This puts a hard limit to number of altp2m to 65535, which is enough, at least
for the time being. Also, altp2m.opts currently uses only 2 bits. Therefore
I believe this change is justified.
- Introduction of accessor functions for altp2m arrays and refactoring the code
to use them.
- Added a check to arm/arch_sanitise_domain_config() to disallow creating
domains with altp2m.nr != 0.
- Added dummy hvm_altp2m_supported() to avoid build errors when CONFIG_HVM is
disabled.
- Finally, expose altp2m_count to OCaml bindings (and verify both altp2m_opts
and altp2m_count fit uint16_t).
- I also removed Christian Lindig from the Acked-by, since I think this change
is significant enough to require a re-review.
Changes since v3:
- Rebased on top of staging (some functions were moved to altp2m.c).
- Re-added the array_index_nospec() where it was removed.
Changes since v2:
- Changed max_altp2m to nr_altp2m.
- Moved arch-dependent check from xen/common/domain.c to xen/arch/x86/domain.c.
- Replaced min(d->nr_altp2m, MAX_EPTP) occurences for just d->nr_altp2m.
- Replaced array_index_nospec(altp2m_idx, ...) for just altp2m_idx.
- Shortened long lines.
- Removed unnecessary comments in altp2m_vcpu_initialise/destroy.
- Moved nr_altp2m field after max_ fields in xen_domctl_createdomain.
- Removed the commit that adjusted the initial allocation of pages from 256
to 1024. This means that after these patches, technically, the nr_altp2m will
be capped to (256 - 1 - vcpus - MAX_NESTEDP2M) instead of MAX_EPTP (512).
Future work will be needed to fix this.
Petr Beneš (9):
tools/xl: Add altp2m_count parameter
docs/man: Add altp2m_count parameter to the xl.cfg manual
x86/p2m: Short-circuit p2m_is_altp2m() when CONFIG_ALTP2M=n
x86/altp2m: Remove p2m_altp2m_check stubs from unsupported
architectures
x86/altp2m: Wrap altp2m-specific code in #ifdef CONFIG_ALTP2M
xen: Make the maximum number of altp2m views configurable for x86
tools/libxl: Activate the altp2m_count feature
xen/x86: Disallow creating domains with altp2m enabled and altp2m.nr
== 0
tools/ocaml: Add altp2m_count parameter
docs/man/xl.cfg.5.pod.in | 14 ++++++
tools/golang/xenlight/helpers.gen.go | 2 +
tools/golang/xenlight/types.gen.go | 1 +
tools/include/libxl.h | 7 +++
tools/libs/light/libxl_create.c | 14 ++++++
tools/libs/light/libxl_internal.h | 1 +
tools/libs/light/libxl_types.idl | 1 +
tools/ocaml/libs/xc/xenctrl.ml | 1 +
tools/ocaml/libs/xc/xenctrl.mli | 1 +
tools/ocaml/libs/xc/xenctrl_stubs.c | 19 ++++++--
tools/xl/xl_parse.c | 9 ++++
xen/arch/arm/domain.c | 2 +-
xen/arch/arm/include/asm/p2m.h | 6 ---
xen/arch/ppc/include/asm/p2m.h | 5 --
xen/arch/riscv/include/asm/p2m.h | 5 --
xen/arch/x86/domain.c | 41 +++++++++++++---
xen/arch/x86/hvm/emulate.c | 10 +++-
xen/arch/x86/hvm/hvm.c | 18 ++++++-
xen/arch/x86/hvm/monitor.c | 2 +
xen/arch/x86/hvm/vmx/vmx.c | 10 +++-
xen/arch/x86/include/asm/altp2m.h | 28 +++++++++--
xen/arch/x86/include/asm/domain.h | 11 +++--
xen/arch/x86/include/asm/hvm/hvm.h | 8 ++++
xen/arch/x86/include/asm/hvm/vcpu.h | 4 ++
xen/arch/x86/include/asm/p2m.h | 30 ++++++++----
xen/arch/x86/mm/altp2m.c | 72 +++++++++++++++-------------
xen/arch/x86/mm/hap/hap.c | 12 +++--
xen/arch/x86/mm/mem_access.c | 30 +++++++-----
xen/arch/x86/mm/mem_sharing.c | 4 +-
xen/arch/x86/mm/p2m-ept.c | 11 +++--
xen/arch/x86/mm/p2m-pt.c | 2 +
xen/arch/x86/mm/p2m.c | 17 +++++--
xen/common/domain.c | 6 +++
xen/common/vm_event.c | 2 +
xen/include/public/domctl.h | 5 +-
xen/include/xen/sched.h | 4 ++
36 files changed, 307 insertions(+), 108 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v10 1/9] tools/xl: Add altp2m_count parameter
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
@ 2025-07-16 20:15 ` Petr Beneš
2025-07-17 13:42 ` Nick Rosbrook
2025-07-18 15:16 ` Anthony PERARD
2025-07-16 20:15 ` [PATCH v10 2/9] docs/man: Add altp2m_count parameter to the xl.cfg manual Petr Beneš
` (7 subsequent siblings)
8 siblings, 2 replies; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel
Cc: Petr Beneš, Nick Rosbrook, George Dunlap, Anthony PERARD,
Juergen Gross
From: Petr Beneš <w1benny@gmail.com>
Introduce a new altp2m_count parameter to control the maximum number of altp2m
views a domain can use. By default, if altp2m_count is unspecified and altp2m
is enabled, the value is set to 10, reflecting the legacy behavior.
This change is preparatory; it establishes the groundwork for the feature but
does not activate it.
Signed-off-by: Petr Beneš <w1benny@gmail.com>
---
tools/golang/xenlight/helpers.gen.go | 2 ++
tools/golang/xenlight/types.gen.go | 1 +
tools/include/libxl.h | 7 +++++++
tools/libs/light/libxl_create.c | 10 ++++++++++
tools/libs/light/libxl_internal.h | 1 +
tools/libs/light/libxl_types.idl | 1 +
tools/xl/xl_parse.c | 9 +++++++++
7 files changed, 31 insertions(+)
diff --git a/tools/golang/xenlight/helpers.gen.go b/tools/golang/xenlight/helpers.gen.go
index 191be87297..515a6ef10a 100644
--- a/tools/golang/xenlight/helpers.gen.go
+++ b/tools/golang/xenlight/helpers.gen.go
@@ -1167,6 +1167,7 @@ if err := x.ArchX86.MsrRelaxed.fromC(&xc.arch_x86.msr_relaxed);err != nil {
return fmt.Errorf("converting field ArchX86.MsrRelaxed: %v", err)
}
x.Altp2M = Altp2MMode(xc.altp2m)
+x.Altp2MCount = uint32(xc.altp2m_count)
x.VmtraceBufKb = int(xc.vmtrace_buf_kb)
if err := x.Vpmu.fromC(&xc.vpmu);err != nil {
return fmt.Errorf("converting field Vpmu: %v", err)
@@ -1695,6 +1696,7 @@ if err := x.ArchX86.MsrRelaxed.toC(&xc.arch_x86.msr_relaxed); err != nil {
return fmt.Errorf("converting field ArchX86.MsrRelaxed: %v", err)
}
xc.altp2m = C.libxl_altp2m_mode(x.Altp2M)
+xc.altp2m_count = C.uint32_t(x.Altp2MCount)
xc.vmtrace_buf_kb = C.int(x.VmtraceBufKb)
if err := x.Vpmu.toC(&xc.vpmu); err != nil {
return fmt.Errorf("converting field Vpmu: %v", err)
diff --git a/tools/golang/xenlight/types.gen.go b/tools/golang/xenlight/types.gen.go
index 656933c6c9..1a4f076bd2 100644
--- a/tools/golang/xenlight/types.gen.go
+++ b/tools/golang/xenlight/types.gen.go
@@ -604,6 +604,7 @@ ArchX86 struct {
MsrRelaxed Defbool
}
Altp2M Altp2MMode
+Altp2MCount uint32
VmtraceBufKb int
Vpmu Defbool
TrapUnmappedAccesses Defbool
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index a8704e0268..d6b6e5d2dd 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -1257,6 +1257,13 @@ typedef struct libxl__ctx libxl_ctx;
*/
#define LIBXL_HAVE_ALTP2M 1
+/*
+ * LIBXL_HAVE_ALTP2M_COUNT
+ * If this is defined, then libxl supports setting the maximum number of
+ * alternate p2m tables.
+ */
+#define LIBXL_HAVE_ALTP2M_COUNT 1
+
/*
* LIBXL_HAVE_REMUS
* If this is defined, then libxl supports remus.
diff --git a/tools/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c
index 8a85fba1cf..4301f17f90 100644
--- a/tools/libs/light/libxl_create.c
+++ b/tools/libs/light/libxl_create.c
@@ -421,6 +421,16 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
return -ERROR_INVAL;
}
+ if (b_info->altp2m_count == LIBXL_ALTP2M_COUNT_DEFAULT) {
+ if (b_info->type == LIBXL_DOMAIN_TYPE_HVM &&
+ (libxl_defbool_val(b_info->u.hvm.altp2m) ||
+ b_info->altp2m != LIBXL_ALTP2M_MODE_DISABLED))
+ /* Reflect the default legacy count */
+ b_info->altp2m_count = 10;
+ else
+ b_info->altp2m_count = 0;
+ }
+
/* Assume that providing a bootloader user implies enabling restrict. */
libxl_defbool_setdefault(&b_info->bootloader_restrict,
!!b_info->bootloader_user);
diff --git a/tools/libs/light/libxl_internal.h b/tools/libs/light/libxl_internal.h
index 75bb0b94cf..2a5b233caa 100644
--- a/tools/libs/light/libxl_internal.h
+++ b/tools/libs/light/libxl_internal.h
@@ -111,6 +111,7 @@
#define LIBXL_MIN_DOM0_MEM (128*1024)
#define LIBXL_INVALID_GFN (~(uint64_t)0)
#define LIBXL_VGA_HOLE_SIZE 0x20
+#define LIBXL_ALTP2M_COUNT_DEFAULT (~(uint32_t)0)
/* use 0 as the domid of the toolstack domain for now */
#define LIBXL_TOOLSTACK_DOMID 0
#define QEMU_SIGNATURE "DeviceModelRecord0002"
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index a3a79d12b2..fe251649f3 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -731,6 +731,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
# Alternate p2m is not bound to any architecture or guest type, as it is
# supported by x86 HVM and ARM support is planned.
("altp2m", libxl_altp2m_mode),
+ ("altp2m_count", uint32, {'init_val': 'LIBXL_ALTP2M_COUNT_DEFAULT'}),
# Size of preallocated vmtrace trace buffers (in KBYTES).
# Use zero value to disable this feature.
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index 7e11c62ba0..28cdbf07c2 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -2099,6 +2099,15 @@ void parse_config_data(const char *config_source,
}
}
+ if (!xlu_cfg_get_long(config, "altp2m_count", &l, 1)) {
+ if (l != (uint16_t)l) {
+ fprintf(stderr, "ERROR: invalid value %ld for \"altp2m_count\"\n", l);
+ exit (1);
+ }
+
+ b_info->altp2m_count = l;
+ }
+
if (!xlu_cfg_get_long(config, "vmtrace_buf_kb", &l, 1) && l) {
b_info->vmtrace_buf_kb = l;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v10 2/9] docs/man: Add altp2m_count parameter to the xl.cfg manual
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
2025-07-16 20:15 ` [PATCH v10 1/9] tools/xl: Add altp2m_count parameter Petr Beneš
@ 2025-07-16 20:15 ` Petr Beneš
2025-07-16 20:15 ` [PATCH v10 3/9] x86/p2m: Short-circuit p2m_is_altp2m() when CONFIG_ALTP2M=n Petr Beneš
` (6 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel; +Cc: Petr Beneš, Anthony PERARD
From: Petr Beneš <w1benny@gmail.com>
Update manual pages to include detailed information about the altp2m_count
configuration parameter.
Signed-off-by: Petr Beneš <w1benny@gmail.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
---
docs/man/xl.cfg.5.pod.in | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index 1d122982c6..5362fb0e9a 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -2023,6 +2023,20 @@ a single guest HVM domain. B<This option is deprecated, use the option
B<Note>: While the option "altp2mhvm" is deprecated, legacy applications for
x86 systems will continue to work using it.
+=item B<altp2m_count=NUMBER>
+
+Specifies the maximum number of alternate-p2m views available to the guest.
+This setting is crucial in domain introspection scenarios that require
+multiple physical-to-machine (p2m) memory mappings to be established
+simultaneously.
+
+Enabling multiple p2m views may increase memory usage. It is advisable to
+review and adjust the B<shadow_memory> setting as necessary to accommodate
+the additional memory requirements.
+
+B<Note>: This option is ignored if B<altp2m> is disabled. The default value
+is 10.
+
=item B<nestedhvm=BOOLEAN>
Enable or disables guest access to hardware virtualisation features,
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v10 3/9] x86/p2m: Short-circuit p2m_is_altp2m() when CONFIG_ALTP2M=n
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
2025-07-16 20:15 ` [PATCH v10 1/9] tools/xl: Add altp2m_count parameter Petr Beneš
2025-07-16 20:15 ` [PATCH v10 2/9] docs/man: Add altp2m_count parameter to the xl.cfg manual Petr Beneš
@ 2025-07-16 20:15 ` Petr Beneš
2025-07-22 14:50 ` Jan Beulich
2025-07-16 20:15 ` [PATCH v10 4/9] x86/altp2m: Remove p2m_altp2m_check stubs from unsupported architectures Petr Beneš
` (5 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel
Cc: Petr Beneš, Jan Beulich, Andrew Cooper, Roger Pau Monné
From: Petr Beneš <w1benny@gmail.com>
Wrap the p2m_is_altp2m() check with IS_ENABLED(CONFIG_ALTP2M) to allow the
compiler to short-circuit the condition at build time when ALTP2M is disabled.
Signed-off-by: Petr Beneš <w1benny@gmail.com>
---
xen/arch/x86/include/asm/p2m.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xen/arch/x86/include/asm/p2m.h b/xen/arch/x86/include/asm/p2m.h
index 4358cc15a2..58b56e575e 100644
--- a/xen/arch/x86/include/asm/p2m.h
+++ b/xen/arch/x86/include/asm/p2m.h
@@ -437,7 +437,7 @@ static inline bool p2m_is_nestedp2m(const struct p2m_domain *p2m)
static inline bool p2m_is_altp2m(const struct p2m_domain *p2m)
{
- return p2m->p2m_class == p2m_alternate;
+ return IS_ENABLED(CONFIG_ALTP2M) && p2m->p2m_class == p2m_alternate;
}
#ifdef CONFIG_HVM
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v10 4/9] x86/altp2m: Remove p2m_altp2m_check stubs from unsupported architectures
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
` (2 preceding siblings ...)
2025-07-16 20:15 ` [PATCH v10 3/9] x86/p2m: Short-circuit p2m_is_altp2m() when CONFIG_ALTP2M=n Petr Beneš
@ 2025-07-16 20:15 ` Petr Beneš
2025-07-22 14:56 ` Jan Beulich
2025-07-16 20:15 ` [PATCH v10 5/9] x86/altp2m: Wrap altp2m-specific code in #ifdef CONFIG_ALTP2M Petr Beneš
` (4 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel
Cc: Petr Beneš, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk,
Shawn Anastasio, Alistair Francis, Bob Eshleman, Connor Davis,
Oleksii Kurochko, Tamas K Lengyel, Alexandru Isaila,
Petre Pircalabu, Jan Beulich, Andrew Cooper, Roger Pau Monné
From: Petr Beneš <w1benny@gmail.com>
The p2m_altp2m_check() stub was previously declared on all architectures,
even though the altp2m feature is only supported on x86. This patch removes
the unused stub definitions from ARM, PPC, and RISC-V, and wraps the actual
usage sites in #ifdef CONFIG_ALTP2M instead.
Additionally, the declaration and definition of p2m_altp2m_check() are now
correctly nested under CONFIG_HVM, reflecting the fact that CONFIG_ALTP2M
always implies CONFIG_HVM.
Signed-off-by: Petr Beneš <w1benny@gmail.com>
---
xen/arch/arm/include/asm/p2m.h | 6 ------
xen/arch/ppc/include/asm/p2m.h | 5 -----
xen/arch/riscv/include/asm/p2m.h | 5 -----
xen/arch/x86/hvm/monitor.c | 2 ++
xen/arch/x86/include/asm/p2m.h | 9 ++++-----
xen/common/vm_event.c | 2 ++
6 files changed, 8 insertions(+), 21 deletions(-)
diff --git a/xen/arch/arm/include/asm/p2m.h b/xen/arch/arm/include/asm/p2m.h
index 2d53bf9b61..ef98bc5f4d 100644
--- a/xen/arch/arm/include/asm/p2m.h
+++ b/xen/arch/arm/include/asm/p2m.h
@@ -180,12 +180,6 @@ static inline bool arch_acquire_resource_check(struct domain *d)
return true;
}
-static inline
-void p2m_altp2m_check(struct vcpu *v, uint16_t idx)
-{
- /* Not supported on ARM. */
-}
-
/*
* Helper to restrict "p2m_ipa_bits" according the external entity
* (e.g. IOMMU) requirements.
diff --git a/xen/arch/ppc/include/asm/p2m.h b/xen/arch/ppc/include/asm/p2m.h
index f144ef8e1a..c96149ef74 100644
--- a/xen/arch/ppc/include/asm/p2m.h
+++ b/xen/arch/ppc/include/asm/p2m.h
@@ -88,9 +88,4 @@ static inline bool arch_acquire_resource_check(struct domain *d)
return false;
}
-static inline void p2m_altp2m_check(struct vcpu *v, uint16_t idx)
-{
- /* Not supported on PPC. */
-}
-
#endif /* __ASM_PPC_P2M_H__ */
diff --git a/xen/arch/riscv/include/asm/p2m.h b/xen/arch/riscv/include/asm/p2m.h
index 28f57a74f2..e43c559e0c 100644
--- a/xen/arch/riscv/include/asm/p2m.h
+++ b/xen/arch/riscv/include/asm/p2m.h
@@ -88,11 +88,6 @@ static inline bool arch_acquire_resource_check(struct domain *d)
return false;
}
-static inline void p2m_altp2m_check(struct vcpu *v, uint16_t idx)
-{
- /* Not supported on RISCV. */
-}
-
#endif /* ASM__RISCV__P2M_H */
/*
diff --git a/xen/arch/x86/hvm/monitor.c b/xen/arch/x86/hvm/monitor.c
index 523586ca98..d22a2e4644 100644
--- a/xen/arch/x86/hvm/monitor.c
+++ b/xen/arch/x86/hvm/monitor.c
@@ -178,6 +178,7 @@ int hvm_monitor_debug(unsigned long rip, enum hvm_monitor_debug_type type,
break;
case HVM_MONITOR_SINGLESTEP_BREAKPOINT:
+#ifdef CONFIG_ALTP2M
if ( curr->arch.hvm.fast_single_step.enabled )
{
p2m_altp2m_check(curr, curr->arch.hvm.fast_single_step.p2midx);
@@ -186,6 +187,7 @@ int hvm_monitor_debug(unsigned long rip, enum hvm_monitor_debug_type type,
curr->arch.hvm.fast_single_step.p2midx = 0;
return 0;
}
+#endif
if ( !ad->monitor.singlestep_enabled )
return 0;
req.reason = VM_EVENT_REASON_SINGLESTEP;
diff --git a/xen/arch/x86/include/asm/p2m.h b/xen/arch/x86/include/asm/p2m.h
index 58b56e575e..7375895836 100644
--- a/xen/arch/x86/include/asm/p2m.h
+++ b/xen/arch/x86/include/asm/p2m.h
@@ -962,17 +962,16 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
/* Set a specific p2m view visibility */
int p2m_set_altp2m_view_visibility(struct domain *d, unsigned int altp2m_idx,
uint8_t visible);
-#else /* !CONFIG_HVM */
-struct p2m_domain *p2m_get_altp2m(struct vcpu *v);
-#endif /* CONFIG_HVM */
#ifdef CONFIG_ALTP2M
/* Check to see if vcpu should be switched to a different p2m. */
void p2m_altp2m_check(struct vcpu *v, uint16_t idx);
-#else
-static inline void p2m_altp2m_check(struct vcpu *v, uint16_t idx) {}
#endif
+#else /* !CONFIG_HVM */
+struct p2m_domain *p2m_get_altp2m(struct vcpu *v);
+#endif /* CONFIG_HVM */
+
/* p2m access to IOMMU flags */
static inline unsigned int p2m_access_to_iommu_flags(p2m_access_t p2ma)
{
diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
index 1666ff615f..98204cbf43 100644
--- a/xen/common/vm_event.c
+++ b/xen/common/vm_event.c
@@ -430,9 +430,11 @@ static int vm_event_resume(struct domain *d, struct vm_event_domain *ved)
*/
vm_event_toggle_singlestep(d, v, &rsp);
+#ifdef CONFIG_ALTP2M
/* Check for altp2m switch */
if ( rsp.flags & VM_EVENT_FLAG_ALTERNATE_P2M )
p2m_altp2m_check(v, rsp.altp2m_idx);
+#endif
if ( rsp.flags & VM_EVENT_FLAG_SET_REGISTERS )
vm_event_set_registers(v, &rsp);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v10 5/9] x86/altp2m: Wrap altp2m-specific code in #ifdef CONFIG_ALTP2M
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
` (3 preceding siblings ...)
2025-07-16 20:15 ` [PATCH v10 4/9] x86/altp2m: Remove p2m_altp2m_check stubs from unsupported architectures Petr Beneš
@ 2025-07-16 20:15 ` Petr Beneš
2025-07-22 15:51 ` Jan Beulich
2025-07-16 20:15 ` [PATCH v10 6/9] xen: Make the maximum number of altp2m views configurable for x86 Petr Beneš
` (3 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel
Cc: Petr Beneš, Jan Beulich, Andrew Cooper, Roger Pau Monné,
Tamas K Lengyel, Alexandru Isaila, Petre Pircalabu
From: Petr Beneš <w1benny@gmail.com>
This change consistently guards all altp2m-related functionality
behind #ifdef CONFIG_ALTP2M, so that code and data structures related
to alternate p2m views are only included when the feature is enabled.
Apart from that:
- hvmemul_vmfunc() returns X86EMUL_UNHANDLEABLE when altp2m is disabled.
- do_altp2m_op() returns EOPNOTSUPP when altp2m is disabled.
- struct hvm_vcpu, arch_domain, and hvm_function_table only define altp2m
fields when the feature is enabled.
- Moved several declarations under #ifdef CONFIG_ALTP2M in p2m.h to avoid
polluting builds that don't require the feature.
Signed-off-by: Petr Beneš <w1benny@gmail.com>
---
xen/arch/x86/hvm/emulate.c | 10 ++++++++--
xen/arch/x86/hvm/hvm.c | 10 ++++++++++
xen/arch/x86/hvm/vmx/vmx.c | 8 ++++++++
xen/arch/x86/include/asm/domain.h | 2 ++
xen/arch/x86/include/asm/hvm/hvm.h | 8 ++++++++
xen/arch/x86/include/asm/hvm/vcpu.h | 4 ++++
xen/arch/x86/include/asm/p2m.h | 17 ++++++++++++++---
xen/arch/x86/mm/hap/hap.c | 6 ++++++
xen/arch/x86/mm/mem_access.c | 8 ++++++++
xen/arch/x86/mm/p2m-ept.c | 4 ++++
xen/arch/x86/mm/p2m.c | 9 +++++++++
11 files changed, 81 insertions(+), 5 deletions(-)
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 91f004d233..d933ed3bd3 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -2686,8 +2686,8 @@ static int cf_check hvmemul_tlb_op(
return rc;
}
-static int cf_check hvmemul_vmfunc(
- struct x86_emulate_ctxt *ctxt)
+#ifdef CONFIG_ALTP2M
+static int cf_check hvmemul_vmfunc(struct x86_emulate_ctxt *ctxt)
{
int rc;
@@ -2699,6 +2699,12 @@ static int cf_check hvmemul_vmfunc(
return rc;
}
+#else
+static int cf_check hvmemul_vmfunc(struct x86_emulate_ctxt *ctxt)
+{
+ return X86EMUL_UNHANDLEABLE;
+}
+#endif
static const struct x86_emulate_ops hvm_emulate_ops = {
.read = hvmemul_read,
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 56c7de3977..5183bfea3a 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -4608,6 +4608,7 @@ static int hvmop_get_param(
static int do_altp2m_op(
XEN_GUEST_HANDLE_PARAM(void) arg)
{
+#ifdef CONFIG_ALTP2M
struct xen_hvm_altp2m_op a;
struct domain *d = NULL;
int rc = 0;
@@ -4944,6 +4945,9 @@ static int do_altp2m_op(
rcu_unlock_domain(d);
return rc;
+#else /* !CONFIG_ALTP2M */
+ return -EOPNOTSUPP;
+#endif /* CONFIG_ALTP2M */
}
DEFINE_XEN_GUEST_HANDLE(compat_hvm_altp2m_op_t);
@@ -5235,8 +5239,12 @@ int hvm_debug_op(struct vcpu *v, int32_t op)
case XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF:
v->arch.hvm.single_step = false;
+
+#ifdef CONFIG_ALTP2M
v->arch.hvm.fast_single_step.enabled = false;
v->arch.hvm.fast_single_step.p2midx = 0;
+#endif
+
break;
default: /* Excluded above */
@@ -5261,6 +5269,7 @@ void hvm_toggle_singlestep(struct vcpu *v)
void hvm_fast_singlestep(struct vcpu *v, uint16_t p2midx)
{
+#ifdef CONFIG_ALTP2M
ASSERT(atomic_read(&v->pause_count));
if ( !hvm_is_singlestep_supported() )
@@ -5272,6 +5281,7 @@ void hvm_fast_singlestep(struct vcpu *v, uint16_t p2midx)
v->arch.hvm.single_step = true;
v->arch.hvm.fast_single_step.enabled = true;
v->arch.hvm.fast_single_step.p2midx = p2midx;
+#endif
}
/*
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 218cb2c1af..b136d89546 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2416,6 +2416,8 @@ static void cf_check vmx_enable_msr_interception(struct domain *d, uint32_t msr)
vmx_set_msr_intercept(v, msr, VMX_MSR_W);
}
+#ifdef CONFIG_ALTP2M
+
static void cf_check vmx_vcpu_update_eptp(struct vcpu *v)
{
struct domain *d = v->domain;
@@ -2535,6 +2537,8 @@ static bool cf_check vmx_vcpu_emulate_ve(struct vcpu *v)
return rc;
}
+#endif /* CONFIG_ALTP2M */
+
static bool cf_check vmx_get_pending_event(
struct vcpu *v, struct x86_event *info)
{
@@ -2863,10 +2867,12 @@ static struct hvm_function_table __initdata_cf_clobber vmx_function_table = {
.update_vlapic_mode = vmx_vlapic_msr_changed,
.nhvm_hap_walk_L1_p2m = nvmx_hap_walk_L1_p2m,
.enable_msr_interception = vmx_enable_msr_interception,
+#ifdef CONFIG_ALTP2M
.altp2m_vcpu_update_p2m = vmx_vcpu_update_eptp,
.altp2m_vcpu_update_vmfunc_ve = vmx_vcpu_update_vmfunc_ve,
.altp2m_vcpu_emulate_ve = vmx_vcpu_emulate_ve,
.altp2m_vcpu_emulate_vmfunc = vmx_vcpu_emulate_vmfunc,
+#endif
.vmtrace_control = vmtrace_control,
.vmtrace_output_position = vmtrace_output_position,
.vmtrace_set_option = vmtrace_set_option,
@@ -4963,6 +4969,7 @@ bool asmlinkage vmx_vmenter_helper(const struct cpu_user_regs *regs)
single = ept;
}
+#ifdef CONFIG_ALTP2M
if ( altp2m_active(currd) )
{
unsigned int i;
@@ -4981,6 +4988,7 @@ bool asmlinkage vmx_vmenter_helper(const struct cpu_user_regs *regs)
}
}
}
+#endif
if ( inv )
__invept(inv == 1 ? INVEPT_SINGLE_CONTEXT : INVEPT_ALL_CONTEXT,
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index 8c0dea12a5..8749c5eba0 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -351,12 +351,14 @@ struct arch_domain
struct p2m_domain *nested_p2m[MAX_NESTEDP2M];
mm_lock_t nested_p2m_lock;
+#ifdef CONFIG_ALTP2M
/* altp2m: allow multiple copies of host p2m */
bool altp2m_active;
struct p2m_domain *altp2m_p2m[MAX_ALTP2M];
mm_lock_t altp2m_list_lock;
uint64_t *altp2m_eptp;
uint64_t *altp2m_visible_eptp;
+#endif
#endif
/* NB. protected by d->event_lock and by irq_desc[irq].lock */
diff --git a/xen/arch/x86/include/asm/hvm/hvm.h b/xen/arch/x86/include/asm/hvm/hvm.h
index bf8bc2e100..af80acfdd8 100644
--- a/xen/arch/x86/include/asm/hvm/hvm.h
+++ b/xen/arch/x86/include/asm/hvm/hvm.h
@@ -225,11 +225,13 @@ struct hvm_function_table {
void (*enable_msr_interception)(struct domain *d, uint32_t msr);
+#ifdef CONFIG_ALTP2M
/* Alternate p2m */
void (*altp2m_vcpu_update_p2m)(struct vcpu *v);
void (*altp2m_vcpu_update_vmfunc_ve)(struct vcpu *v);
bool (*altp2m_vcpu_emulate_ve)(struct vcpu *v);
int (*altp2m_vcpu_emulate_vmfunc)(const struct cpu_user_regs *regs);
+#endif
/* vmtrace */
int (*vmtrace_control)(struct vcpu *v, bool enable, bool reset);
@@ -707,6 +709,7 @@ static inline bool hvm_nested_virt_supported(void)
return hvm_funcs.caps.nested_virt;
}
+#ifdef CONFIG_ALTP2M
/* updates the current hardware p2m */
static inline void altp2m_vcpu_update_p2m(struct vcpu *v)
{
@@ -731,6 +734,11 @@ static inline bool altp2m_vcpu_emulate_ve(struct vcpu *v)
}
return false;
}
+#else /* !CONFIG_ALTP2M */
+void altp2m_vcpu_update_p2m(struct vcpu *v);
+void altp2m_vcpu_update_vmfunc_ve(struct vcpu *v);
+bool altp2m_vcpu_emulate_ve(struct vcpu *v);
+#endif /* CONFIG_ALTP2M */
static inline int hvm_vmtrace_control(struct vcpu *v, bool enable, bool reset)
{
diff --git a/xen/arch/x86/include/asm/hvm/vcpu.h b/xen/arch/x86/include/asm/hvm/vcpu.h
index 196fed6d5d..924af890c5 100644
--- a/xen/arch/x86/include/asm/hvm/vcpu.h
+++ b/xen/arch/x86/include/asm/hvm/vcpu.h
@@ -133,10 +133,12 @@ struct hvm_vcpu {
bool flag_dr_dirty;
bool debug_state_latch;
bool single_step;
+#ifdef CONFIG_ALTP2M
struct {
bool enabled;
uint16_t p2midx;
} fast_single_step;
+#endif
/* (MFN) hypervisor page table */
pagetable_t monitor_table;
@@ -154,7 +156,9 @@ struct hvm_vcpu {
struct nestedvcpu nvcpu;
+#ifdef CONFIG_ALTP2M
struct altp2mvcpu avcpu;
+#endif
struct mtrr_state mtrr;
u64 pat_cr;
diff --git a/xen/arch/x86/include/asm/p2m.h b/xen/arch/x86/include/asm/p2m.h
index 7375895836..4ed93f3a46 100644
--- a/xen/arch/x86/include/asm/p2m.h
+++ b/xen/arch/x86/include/asm/p2m.h
@@ -889,6 +889,8 @@ void shadow_p2m_init(struct p2m_domain *p2m);
void cf_check nestedp2m_write_p2m_entry_post(
struct p2m_domain *p2m, unsigned int oflags);
+#ifdef CONFIG_ALTP2M
+
/*
* Alternate p2m: shadow p2m tables used for alternate memory views
*/
@@ -963,13 +965,22 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
int p2m_set_altp2m_view_visibility(struct domain *d, unsigned int altp2m_idx,
uint8_t visible);
-#ifdef CONFIG_ALTP2M
/* Check to see if vcpu should be switched to a different p2m. */
void p2m_altp2m_check(struct vcpu *v, uint16_t idx);
-#endif
-#else /* !CONFIG_HVM */
+#else /* !CONFIG_ALTP2M */
+
struct p2m_domain *p2m_get_altp2m(struct vcpu *v);
+bool p2m_set_altp2m(struct vcpu *v, unsigned int idx);
+bool p2m_altp2m_get_or_propagate(struct p2m_domain *ap2m, unsigned long gfn_l,
+ mfn_t *mfn, p2m_type_t *p2mt,
+ p2m_access_t *p2ma, unsigned int *page_order);
+int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
+ mfn_t mfn, unsigned int page_order,
+ p2m_type_t p2mt, p2m_access_t p2ma);
+
+#endif /* CONFIG_ALTP2M */
+
#endif /* CONFIG_HVM */
/* p2m access to IOMMU flags */
diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
index ec5043a8aa..384c24028f 100644
--- a/xen/arch/x86/mm/hap/hap.c
+++ b/xen/arch/x86/mm/hap/hap.c
@@ -494,6 +494,7 @@ int hap_enable(struct domain *d, u32 mode)
goto out;
}
+#ifdef CONFIG_ALTP2M
if ( hvm_altp2m_supported() )
{
/* Init alternate p2m data */
@@ -524,6 +525,7 @@ int hap_enable(struct domain *d, u32 mode)
d->arch.altp2m_active = false;
}
+#endif /* CONFIG_ALTP2M */
/* Now let other users see the new mode */
d->arch.paging.mode = mode | PG_HAP_enable;
@@ -537,9 +539,11 @@ void hap_final_teardown(struct domain *d)
{
unsigned int i;
+#ifdef CONFIG_ALTP2M
if ( hvm_altp2m_supported() )
for ( i = 0; i < MAX_ALTP2M; i++ )
p2m_teardown(d->arch.altp2m_p2m[i], true, NULL);
+#endif
/* Destroy nestedp2m's first */
for (i = 0; i < MAX_NESTEDP2M; i++) {
@@ -578,6 +582,7 @@ void hap_teardown(struct domain *d, bool *preempted)
for_each_vcpu ( d, v )
hap_vcpu_teardown(v);
+#ifdef CONFIG_ALTP2M
/* Leave the root pt in case we get further attempts to modify the p2m. */
if ( hvm_altp2m_supported() )
{
@@ -597,6 +602,7 @@ void hap_teardown(struct domain *d, bool *preempted)
return;
}
}
+#endif
/* Destroy nestedp2m's after altp2m. */
for ( i = 0; i < MAX_NESTEDP2M; i++ )
diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c
index 21b5b7ecda..0779c41161 100644
--- a/xen/arch/x86/mm/mem_access.c
+++ b/xen/arch/x86/mm/mem_access.c
@@ -347,6 +347,7 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
unsigned long gfn_l;
long rc = 0;
+#ifdef CONFIG_ALTP2M
/* altp2m view 0 is treated as the hostp2m */
if ( altp2m_idx )
{
@@ -357,6 +358,7 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
ap2m = array_access_nospec(d->arch.altp2m_p2m, altp2m_idx);
}
+#endif
if ( !xenmem_access_to_p2m_access(p2m, access, &a) )
return -EINVAL;
@@ -403,6 +405,7 @@ long p2m_set_mem_access_multi(struct domain *d,
struct p2m_domain *p2m = p2m_get_hostp2m(d), *ap2m = NULL;
long rc = 0;
+#ifdef CONFIG_ALTP2M
/* altp2m view 0 is treated as the hostp2m */
if ( altp2m_idx )
{
@@ -413,6 +416,7 @@ long p2m_set_mem_access_multi(struct domain *d,
ap2m = array_access_nospec(d->arch.altp2m_p2m, altp2m_idx);
}
+#endif
p2m_lock(p2m);
if ( ap2m )
@@ -462,6 +466,7 @@ int p2m_get_mem_access(struct domain *d, gfn_t gfn, xenmem_access_t *access,
{
struct p2m_domain *p2m = p2m_get_hostp2m(d);
+#ifdef CONFIG_ALTP2M
if ( !altp2m_active(d) )
{
if ( altp2m_idx )
@@ -476,6 +481,7 @@ int p2m_get_mem_access(struct domain *d, gfn_t gfn, xenmem_access_t *access,
p2m = array_access_nospec(d->arch.altp2m_p2m, altp2m_idx);
}
+#endif
return _p2m_get_mem_access(p2m, gfn, access);
}
@@ -486,6 +492,7 @@ void arch_p2m_set_access_required(struct domain *d, bool access_required)
p2m_get_hostp2m(d)->access_required = access_required;
+#ifdef CONFIG_ALTP2M
if ( altp2m_active(d) )
{
unsigned int i;
@@ -497,6 +504,7 @@ void arch_p2m_set_access_required(struct domain *d, bool access_required)
p2m->access_required = access_required;
}
}
+#endif
}
bool p2m_mem_access_sanity_check(const struct domain *d)
diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index 0cf6818c13..86dc538030 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -1297,6 +1297,7 @@ static void ept_set_ad_sync(struct domain *d, bool value)
hostp2m->ept.ad = value;
+#ifdef CONFIG_ALTP2M
if ( unlikely(altp2m_active(d)) )
{
unsigned int i;
@@ -1315,6 +1316,7 @@ static void ept_set_ad_sync(struct domain *d, bool value)
p2m_unlock(p2m);
}
}
+#endif
}
static void ept_enable_pml(struct p2m_domain *p2m)
@@ -1506,6 +1508,7 @@ void __init setup_ept_dump(void)
register_keyhandler('D', ept_dump_p2m_table, "dump VT-x EPT tables", 0);
}
+#ifdef CONFIG_ALTP2M
void p2m_init_altp2m_ept(struct domain *d, unsigned int i)
{
struct p2m_domain *p2m = array_access_nospec(d->arch.altp2m_p2m, i);
@@ -1545,6 +1548,7 @@ unsigned int p2m_find_altp2m_by_eptp(struct domain *d, uint64_t eptp)
altp2m_list_unlock(d);
return i;
}
+#endif /* CONFIG_ALTP2M */
/*
* Local variables:
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index b9a7c2dc53..5a3fda903e 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -101,6 +101,7 @@ void p2m_change_entry_type_global(struct domain *d,
change_entry_type_global(hostp2m, ot, nt);
+#ifdef CONFIG_ALTP2M
if ( unlikely(altp2m_active(d)) )
{
unsigned int i;
@@ -117,6 +118,7 @@ void p2m_change_entry_type_global(struct domain *d,
}
}
}
+#endif
p2m_unlock(hostp2m);
}
@@ -145,6 +147,7 @@ bool p2m_memory_type_changed(struct domain *d)
_memory_type_changed(hostp2m);
+#ifdef CONFIG_ALTP2M
if ( unlikely(altp2m_active(d)) )
{
unsigned int i;
@@ -161,6 +164,7 @@ bool p2m_memory_type_changed(struct domain *d)
}
}
}
+#endif
p2m_unlock(hostp2m);
@@ -930,6 +934,7 @@ void p2m_change_type_range(struct domain *d,
change_type_range(hostp2m, start, end, ot, nt);
+#ifdef CONFIG_ALTP2M
if ( unlikely(altp2m_active(d)) )
{
unsigned int i;
@@ -946,6 +951,8 @@ void p2m_change_type_range(struct domain *d,
}
}
}
+#endif
+
hostp2m->defer_nested_flush = false;
if ( nestedhvm_enabled(d) )
p2m_flush_nestedp2m(d);
@@ -1003,6 +1010,7 @@ int p2m_finish_type_change(struct domain *d,
if ( rc < 0 )
goto out;
+#ifdef CONFIG_ALTP2M
if ( unlikely(altp2m_active(d)) )
{
unsigned int i;
@@ -1022,6 +1030,7 @@ int p2m_finish_type_change(struct domain *d,
}
}
}
+#endif
out:
p2m_unlock(hostp2m);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v10 6/9] xen: Make the maximum number of altp2m views configurable for x86
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
` (4 preceding siblings ...)
2025-07-16 20:15 ` [PATCH v10 5/9] x86/altp2m: Wrap altp2m-specific code in #ifdef CONFIG_ALTP2M Petr Beneš
@ 2025-07-16 20:15 ` Petr Beneš
2025-07-23 15:26 ` Jan Beulich
2025-07-16 20:15 ` [PATCH v10 7/9] tools/libxl: Activate the altp2m_count feature Petr Beneš
` (2 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel
Cc: Petr Beneš, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné,
Tamas K Lengyel, Alexandru Isaila, Petre Pircalabu
From: Petr Beneš <w1benny@gmail.com>
This commit introduces the ability to configure the maximum number of altp2m
views for the domain during its creation. Previously, the limits were hardcoded
to a maximum of 10. This change allows for greater flexibility in environments
that require more or fewer altp2m views.
The maximum configurable limit for nr_altp2m on x86 is now set to
MAX_NR_ALTP2M (which currently holds the MAX_EPTP value - 512). This cap is
linked to the architectural limit of the EPTP-switching VMFUNC, which supports
up to 512 entries. Despite there being no inherent need for limiting nr_altp2m
in scenarios not utilizing VMFUNC, decoupling these components would necessitate
substantial code changes.
xen_domctl_createdomain::altp2m is extended for a new field `nr`, that will
configure this limit for a domain. Additionally, previous altp2m.opts value
has been reduced from uint32_t to uint16_t so that both of these fields occupy
as little space as possible.
Accesses to the altp2m_p2m array are modified to respect the new nr_altp2m
value. Accesses to the altp2m_(visible_)eptp arrays are unmodified, since
these arrays always have fixed size of MAX_EPTP.
Additional sanitization is introduced in the x86/arch_sanitise_domain_config
to fix the altp2m.nr value to 10 if it is previously set to 0. This behavior
is only temporary and immediately removed in the upcoming commit (which will
disallow creating a domain with enabled altp2m with zero nr_altp2m).
The reason for this temporary workaround is to retain the legacy behavior
until the feature is fully activated in libxl.
Also, arm/arch_sanitise_domain_config is extended to not allow requesting
non-zero altp2ms.
Signed-off-by: Petr Beneš <w1benny@gmail.com>
---
xen/arch/arm/domain.c | 2 +-
xen/arch/x86/domain.c | 40 ++++++++++++++---
xen/arch/x86/hvm/hvm.c | 8 +++-
xen/arch/x86/hvm/vmx/vmx.c | 2 +-
xen/arch/x86/include/asm/altp2m.h | 28 ++++++++++--
xen/arch/x86/include/asm/domain.h | 9 ++--
xen/arch/x86/include/asm/p2m.h | 4 +-
xen/arch/x86/mm/altp2m.c | 72 ++++++++++++++++---------------
xen/arch/x86/mm/hap/hap.c | 6 +--
xen/arch/x86/mm/mem_access.c | 22 ++++------
xen/arch/x86/mm/mem_sharing.c | 4 +-
xen/arch/x86/mm/p2m-ept.c | 7 +--
xen/arch/x86/mm/p2m-pt.c | 2 +
xen/arch/x86/mm/p2m.c | 8 ++--
xen/common/domain.c | 6 +++
xen/include/public/domctl.h | 5 ++-
xen/include/xen/sched.h | 4 ++
17 files changed, 151 insertions(+), 78 deletions(-)
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 79a144e61b..9a4f72c62b 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -693,7 +693,7 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
return -EINVAL;
}
- if ( config->altp2m.opts )
+ if ( config->altp2m.opts || config->altp2m.nr )
{
dprintk(XENLOG_INFO, "Altp2m not supported\n");
return -EINVAL;
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 56c3816187..155ea1f79f 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -716,16 +716,42 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
return -EINVAL;
}
- if ( altp2m_mode && nested_virt )
+ if ( altp2m_mode )
{
- dprintk(XENLOG_INFO,
- "Nested virt and altp2m are not supported together\n");
- return -EINVAL;
- }
+ if ( !hvm_altp2m_supported() )
+ {
+ dprintk(XENLOG_INFO, "altp2m is not supported\n");
+ return -EINVAL;
+ }
+
+ if ( !hap )
+ {
+ dprintk(XENLOG_INFO, "altp2m is only supported with HAP\n");
+ return -EINVAL;
+ }
+
+ if ( nested_virt )
+ {
+ dprintk(XENLOG_INFO,
+ "Nested virt and altp2m are not supported together\n");
+ return -EINVAL;
+ }
+
+ if ( !config->altp2m.nr )
+ {
+ /* Fix the value to the legacy default */
+ config->altp2m.nr = 10;
+ }
- if ( altp2m_mode && !hap )
+ if ( config->altp2m.nr > MAX_NR_ALTP2M )
+ {
+ dprintk(XENLOG_INFO, "altp2m.nr must be <= %lu\n", MAX_NR_ALTP2M);
+ return -EINVAL;
+ }
+ }
+ else if ( config->altp2m.nr )
{
- dprintk(XENLOG_INFO, "altp2m is only supported with HAP\n");
+ dprintk(XENLOG_INFO, "altp2m.nr must be zero when altp2m is off\n");
return -EINVAL;
}
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 5183bfea3a..e16850d1f8 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -4675,6 +4675,12 @@ static int do_altp2m_op(
goto out;
}
+ if ( d->nr_altp2m == 0 )
+ {
+ rc = -EINVAL;
+ goto out;
+ }
+
if ( (rc = xsm_hvm_altp2mhvm_op(XSM_OTHER, d, mode, a.cmd)) )
goto out;
@@ -5275,7 +5281,7 @@ void hvm_fast_singlestep(struct vcpu *v, uint16_t p2midx)
if ( !hvm_is_singlestep_supported() )
return;
- if ( p2midx >= MAX_ALTP2M )
+ if ( p2midx >= v->domain->nr_altp2m )
return;
v->arch.hvm.single_step = true;
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index b136d89546..0743177933 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -4974,7 +4974,7 @@ bool asmlinkage vmx_vmenter_helper(const struct cpu_user_regs *regs)
{
unsigned int i;
- for ( i = 0; i < MAX_ALTP2M; ++i )
+ for ( i = 0; i < currd->nr_altp2m; ++i )
{
if ( currd->arch.altp2m_eptp[i] == mfn_x(INVALID_MFN) )
continue;
diff --git a/xen/arch/x86/include/asm/altp2m.h b/xen/arch/x86/include/asm/altp2m.h
index c57a8c5588..8ecd74f363 100644
--- a/xen/arch/x86/include/asm/altp2m.h
+++ b/xen/arch/x86/include/asm/altp2m.h
@@ -13,12 +13,32 @@
#include <xen/sched.h> /* for struct vcpu, struct domain */
#include <asm/hvm/vcpu.h> /* for vcpu_altp2m */
+static inline bool altp2m_is_eptp_valid(const struct domain *d,
+ unsigned int idx)
+{
+ /* There must be enough EPTP entries to cover all altp2m indices */
+ BUILD_BUG_ON(MAX_EPTP < MAX_NR_ALTP2M);
+
+ /* Domain should not have more altp2m entries than MAX_NR_ALTP2M */
+ ASSERT(d->nr_altp2m <= MAX_NR_ALTP2M);
+
+ /* EPTP index is used as altp2m index */
+ return idx < d->nr_altp2m &&
+ d->arch.altp2m_eptp[array_index_nospec(idx, MAX_EPTP)] !=
+ mfn_x(INVALID_MFN);
+}
+
/* Alternate p2m HVM on/off per domain */
static inline bool altp2m_active(const struct domain *d)
{
return d->arch.altp2m_active;
}
+static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
+{
+ return vcpu_altp2m(v).p2midx;
+}
+
/* Alternate p2m VCPU */
void altp2m_vcpu_initialise(struct vcpu *v);
void altp2m_vcpu_destroy(struct vcpu *v);
@@ -26,11 +46,13 @@ void altp2m_vcpu_destroy(struct vcpu *v);
int altp2m_vcpu_enable_ve(struct vcpu *v, gfn_t gfn);
void altp2m_vcpu_disable_ve(struct vcpu *v);
-static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
+#else
+
+static inline bool altp2m_is_eptp_valid(const struct domain *d,
+ unsigned int idx)
{
- return vcpu_altp2m(v).p2midx;
+ return false;
}
-#else
static inline bool altp2m_active(const struct domain *d)
{
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index 8749c5eba0..02a00e1c07 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -258,11 +258,12 @@ struct paging_vcpu {
struct shadow_vcpu shadow;
};
-#define MAX_NESTEDP2M 10
+#define MAX_EPTP (PAGE_SIZE / sizeof(uint64_t))
+#define MAX_NR_ALTP2M MAX_EPTP
+#define MAX_NESTEDP2M 10
-#define MAX_ALTP2M 10 /* arbitrary */
#define INVALID_ALTP2M 0xffff
-#define MAX_EPTP (PAGE_SIZE / sizeof(uint64_t))
+
struct p2m_domain;
struct time_scale {
int shift;
@@ -354,7 +355,7 @@ struct arch_domain
#ifdef CONFIG_ALTP2M
/* altp2m: allow multiple copies of host p2m */
bool altp2m_active;
- struct p2m_domain *altp2m_p2m[MAX_ALTP2M];
+ struct p2m_domain **altp2m_p2m;
mm_lock_t altp2m_list_lock;
uint64_t *altp2m_eptp;
uint64_t *altp2m_visible_eptp;
diff --git a/xen/arch/x86/include/asm/p2m.h b/xen/arch/x86/include/asm/p2m.h
index 4ed93f3a46..738654590a 100644
--- a/xen/arch/x86/include/asm/p2m.h
+++ b/xen/arch/x86/include/asm/p2m.h
@@ -903,7 +903,7 @@ static inline struct p2m_domain *p2m_get_altp2m(struct vcpu *v)
if ( index == INVALID_ALTP2M )
return NULL;
- BUG_ON(index >= MAX_ALTP2M);
+ BUG_ON(index >= v->domain->nr_altp2m);
return v->domain->arch.altp2m_p2m[index];
}
@@ -913,7 +913,7 @@ static inline bool p2m_set_altp2m(struct vcpu *v, unsigned int idx)
{
struct p2m_domain *orig;
- BUG_ON(idx >= MAX_ALTP2M);
+ BUG_ON(idx >= v->domain->nr_altp2m);
if ( idx == vcpu_altp2m(v).p2midx )
return false;
diff --git a/xen/arch/x86/mm/altp2m.c b/xen/arch/x86/mm/altp2m.c
index 6fe1e9ed6b..0261360aae 100644
--- a/xen/arch/x86/mm/altp2m.c
+++ b/xen/arch/x86/mm/altp2m.c
@@ -9,12 +9,16 @@
#include <asm/altp2m.h>
#include <public/hvm/hvm_op.h>
#include <xen/event.h>
+#include <xen/xvmalloc.h>
#include "mm-locks.h"
#include "p2m.h"
void
altp2m_vcpu_initialise(struct vcpu *v)
{
+ if ( !v->domain->nr_altp2m )
+ return;
+
if ( v != current )
vcpu_pause(v);
@@ -32,6 +36,9 @@ altp2m_vcpu_destroy(struct vcpu *v)
{
struct p2m_domain *p2m;
+ if ( !v->domain->nr_altp2m )
+ return;
+
if ( v != current )
vcpu_pause(v);
@@ -122,7 +129,12 @@ int p2m_init_altp2m(struct domain *d)
struct p2m_domain *hostp2m = p2m_get_hostp2m(d);
mm_lock_init(&d->arch.altp2m_list_lock);
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ d->arch.altp2m_p2m = xvzalloc_array(struct p2m_domain *, d->nr_altp2m);
+
+ if ( !d->arch.altp2m_p2m )
+ return -ENOMEM;
+
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
d->arch.altp2m_p2m[i] = p2m = p2m_init_one(d);
if ( p2m == NULL )
@@ -143,7 +155,7 @@ void p2m_teardown_altp2m(struct domain *d)
unsigned int i;
struct p2m_domain *p2m;
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
if ( !d->arch.altp2m_p2m[i] )
continue;
@@ -151,6 +163,8 @@ void p2m_teardown_altp2m(struct domain *d)
d->arch.altp2m_p2m[i] = NULL;
p2m_free_one(p2m);
}
+
+ XVFREE(d->arch.altp2m_p2m);
}
int altp2m_get_effective_entry(struct p2m_domain *ap2m, gfn_t gfn, mfn_t *mfn,
@@ -200,7 +214,7 @@ bool p2m_switch_vcpu_altp2m_by_id(struct vcpu *v, unsigned int idx)
struct domain *d = v->domain;
bool rc = false;
- if ( idx >= MAX_ALTP2M )
+ if ( idx >= d->nr_altp2m )
return rc;
altp2m_list_lock(d);
@@ -306,8 +320,8 @@ static void p2m_reset_altp2m(struct domain *d, unsigned int idx,
{
struct p2m_domain *p2m;
- ASSERT(idx < MAX_ALTP2M);
- p2m = array_access_nospec(d->arch.altp2m_p2m, idx);
+ ASSERT(idx < d->nr_altp2m);
+ p2m = d->arch.altp2m_p2m[array_index_nospec(idx, d->nr_altp2m)];
p2m_lock(p2m);
@@ -332,7 +346,7 @@ void p2m_flush_altp2m(struct domain *d)
altp2m_list_lock(d);
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
p2m_reset_altp2m(d, i, ALTP2M_DEACTIVATE);
d->arch.altp2m_eptp[i] = mfn_x(INVALID_MFN);
@@ -348,9 +362,9 @@ static int p2m_activate_altp2m(struct domain *d, unsigned int idx,
struct p2m_domain *hostp2m, *p2m;
int rc;
- ASSERT(idx < MAX_ALTP2M);
+ ASSERT(idx < d->nr_altp2m);
- p2m = array_access_nospec(d->arch.altp2m_p2m, idx);
+ p2m = d->arch.altp2m_p2m[array_index_nospec(idx, d->nr_altp2m)];
hostp2m = p2m_get_hostp2m(d);
p2m_lock(p2m);
@@ -388,7 +402,7 @@ int p2m_init_altp2m_by_id(struct domain *d, unsigned int idx)
int rc = -EINVAL;
struct p2m_domain *hostp2m = p2m_get_hostp2m(d);
- if ( idx >= min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) )
+ if ( idx >= d->nr_altp2m )
return rc;
altp2m_list_lock(d);
@@ -415,7 +429,7 @@ int p2m_init_next_altp2m(struct domain *d, uint16_t *idx,
altp2m_list_lock(d);
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
if ( d->arch.altp2m_eptp[i] != mfn_x(INVALID_MFN) )
continue;
@@ -437,7 +451,7 @@ int p2m_destroy_altp2m_by_id(struct domain *d, unsigned int idx)
struct p2m_domain *p2m;
int rc = -EBUSY;
- if ( !idx || idx >= min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) )
+ if ( !idx || idx >= d->nr_altp2m )
return rc;
rc = domain_pause_except_self(d);
@@ -450,7 +464,7 @@ int p2m_destroy_altp2m_by_id(struct domain *d, unsigned int idx)
if ( d->arch.altp2m_eptp[array_index_nospec(idx, MAX_EPTP)] !=
mfn_x(INVALID_MFN) )
{
- p2m = array_access_nospec(d->arch.altp2m_p2m, idx);
+ p2m = d->arch.altp2m_p2m[array_index_nospec(idx, d->nr_altp2m)];
if ( !_atomic_read(p2m->active_vcpus) )
{
@@ -475,7 +489,7 @@ int p2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int idx)
struct vcpu *v;
int rc = -EINVAL;
- if ( idx >= MAX_ALTP2M )
+ if ( idx >= d->nr_altp2m )
return rc;
rc = domain_pause_except_self(d);
@@ -510,13 +524,11 @@ int p2m_change_altp2m_gfn(struct domain *d, unsigned int idx,
mfn_t mfn;
int rc = -EINVAL;
- if ( idx >= min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) ||
- d->arch.altp2m_eptp[array_index_nospec(idx, MAX_EPTP)] ==
- mfn_x(INVALID_MFN) )
+ if ( !altp2m_is_eptp_valid(d, idx) )
return rc;
hp2m = p2m_get_hostp2m(d);
- ap2m = array_access_nospec(d->arch.altp2m_p2m, idx);
+ ap2m = d->arch.altp2m_p2m[array_index_nospec(idx, d->nr_altp2m)];
p2m_lock(hp2m);
p2m_lock(ap2m);
@@ -572,7 +584,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
altp2m_list_lock(d);
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
p2m_type_t t;
p2m_access_t a;
@@ -595,7 +607,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
else
{
/* At least 2 altp2m's impacted, so reset everything */
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
if ( i == last_reset_idx ||
d->arch.altp2m_eptp[i] == mfn_x(INVALID_MFN) )
@@ -659,12 +671,11 @@ int p2m_set_suppress_ve_multi(struct domain *d,
if ( sve->view > 0 )
{
- if ( sve->view >= min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) ||
- d->arch.altp2m_eptp[array_index_nospec(sve->view, MAX_EPTP)] ==
- mfn_x(INVALID_MFN) )
+ if ( !altp2m_is_eptp_valid(d, sve->view) )
return -EINVAL;
- p2m = ap2m = array_access_nospec(d->arch.altp2m_p2m, sve->view);
+ p2m = ap2m =
+ d->arch.altp2m_p2m[array_index_nospec(sve->view, d->nr_altp2m)];
}
p2m_lock(host_p2m);
@@ -727,12 +738,11 @@ int p2m_get_suppress_ve(struct domain *d, gfn_t gfn, bool *suppress_ve,
if ( altp2m_idx > 0 )
{
- if ( altp2m_idx >= min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) ||
- d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)] ==
- mfn_x(INVALID_MFN) )
+ if ( !altp2m_is_eptp_valid(d, altp2m_idx) )
return -EINVAL;
- p2m = ap2m = array_access_nospec(d->arch.altp2m_p2m, altp2m_idx);
+ p2m = ap2m =
+ d->arch.altp2m_p2m[array_index_nospec(altp2m_idx, d->nr_altp2m)];
}
else
p2m = host_p2m;
@@ -761,13 +771,7 @@ int p2m_set_altp2m_view_visibility(struct domain *d, unsigned int altp2m_idx,
altp2m_list_lock(d);
- /*
- * Eptp index is correlated with altp2m index and should not exceed
- * min(MAX_ALTP2M, MAX_EPTP).
- */
- if ( altp2m_idx >= min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) ||
- d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)] ==
- mfn_x(INVALID_MFN) )
+ if ( !altp2m_is_eptp_valid(d, altp2m_idx) )
rc = -EINVAL;
else if ( visible )
d->arch.altp2m_visible_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)] =
diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
index 384c24028f..4aec98109d 100644
--- a/xen/arch/x86/mm/hap/hap.c
+++ b/xen/arch/x86/mm/hap/hap.c
@@ -516,7 +516,7 @@ int hap_enable(struct domain *d, u32 mode)
d->arch.altp2m_visible_eptp[i] = mfn_x(INVALID_MFN);
}
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
rv = p2m_alloc_table(d->arch.altp2m_p2m[i]);
if ( rv != 0 )
@@ -541,7 +541,7 @@ void hap_final_teardown(struct domain *d)
#ifdef CONFIG_ALTP2M
if ( hvm_altp2m_supported() )
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
p2m_teardown(d->arch.altp2m_p2m[i], true, NULL);
#endif
@@ -595,7 +595,7 @@ void hap_teardown(struct domain *d, bool *preempted)
FREE_XENHEAP_PAGE(d->arch.altp2m_eptp);
FREE_XENHEAP_PAGE(d->arch.altp2m_visible_eptp);
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
p2m_teardown(d->arch.altp2m_p2m[i], false, preempted);
if ( preempted && *preempted )
diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c
index 0779c41161..4538a63668 100644
--- a/xen/arch/x86/mm/mem_access.c
+++ b/xen/arch/x86/mm/mem_access.c
@@ -81,6 +81,7 @@ bool p2m_mem_access_emulate_check(struct vcpu *v,
if ( altp2m_active(d) )
p2m = p2m_get_altp2m(v);
+
if ( !p2m )
p2m = p2m_get_hostp2m(d);
@@ -145,6 +146,7 @@ bool p2m_mem_access_check(paddr_t gpa, unsigned long gla,
if ( altp2m_active(d) )
p2m = p2m_get_altp2m(v);
+
if ( !p2m )
p2m = p2m_get_hostp2m(d);
@@ -351,12 +353,10 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
/* altp2m view 0 is treated as the hostp2m */
if ( altp2m_idx )
{
- if ( altp2m_idx >= min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) ||
- d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)] ==
- mfn_x(INVALID_MFN) )
+ if ( !altp2m_is_eptp_valid(d, altp2m_idx) )
return -EINVAL;
- ap2m = array_access_nospec(d->arch.altp2m_p2m, altp2m_idx);
+ ap2m = d->arch.altp2m_p2m[array_index_nospec(altp2m_idx, d->nr_altp2m)];
}
#endif
@@ -409,12 +409,10 @@ long p2m_set_mem_access_multi(struct domain *d,
/* altp2m view 0 is treated as the hostp2m */
if ( altp2m_idx )
{
- if ( altp2m_idx >= min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) ||
- d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)] ==
- mfn_x(INVALID_MFN) )
+ if ( !altp2m_is_eptp_valid(d, altp2m_idx) )
return -EINVAL;
- ap2m = array_access_nospec(d->arch.altp2m_p2m, altp2m_idx);
+ ap2m = d->arch.altp2m_p2m[array_index_nospec(altp2m_idx, d->nr_altp2m)];
}
#endif
@@ -474,12 +472,10 @@ int p2m_get_mem_access(struct domain *d, gfn_t gfn, xenmem_access_t *access,
}
else if ( altp2m_idx ) /* altp2m view 0 is treated as the hostp2m */
{
- if ( altp2m_idx >= min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) ||
- d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)] ==
- mfn_x(INVALID_MFN) )
+ if ( !altp2m_is_eptp_valid(d, altp2m_idx) )
return -EINVAL;
- p2m = array_access_nospec(d->arch.altp2m_p2m, altp2m_idx);
+ p2m = d->arch.altp2m_p2m[array_index_nospec(altp2m_idx, d->nr_altp2m)];
}
#endif
@@ -496,7 +492,7 @@ void arch_p2m_set_access_required(struct domain *d, bool access_required)
if ( altp2m_active(d) )
{
unsigned int i;
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
struct p2m_domain *p2m = d->arch.altp2m_p2m[i];
diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
index da28266ef0..4787b27964 100644
--- a/xen/arch/x86/mm/mem_sharing.c
+++ b/xen/arch/x86/mm/mem_sharing.c
@@ -901,6 +901,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
if ( !page || is_special_page(page) )
goto out;
+#ifdef CONFIG_ALTP2M
/* Check if there are mem_access/remapped altp2m entries for this page */
if ( altp2m_active(d) )
{
@@ -912,7 +913,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
altp2m_list_lock(d);
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
ap2m = d->arch.altp2m_p2m[i];
if ( !ap2m )
@@ -929,6 +930,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
altp2m_list_unlock(d);
}
+#endif /* CONFIG_ALTP2M */
/* Try to convert the mfn to the sharable type */
ret = page_make_sharable(d, page, expected_refcnt, validate_only);
diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index 86dc538030..1c48e876fb 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -1302,7 +1302,7 @@ static void ept_set_ad_sync(struct domain *d, bool value)
{
unsigned int i;
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
struct p2m_domain *p2m;
@@ -1511,7 +1511,8 @@ void __init setup_ept_dump(void)
#ifdef CONFIG_ALTP2M
void p2m_init_altp2m_ept(struct domain *d, unsigned int i)
{
- struct p2m_domain *p2m = array_access_nospec(d->arch.altp2m_p2m, i);
+ struct p2m_domain *p2m =
+ d->arch.altp2m_p2m[array_index_nospec(i, d->nr_altp2m)];
struct p2m_domain *hostp2m = p2m_get_hostp2m(d);
struct ept_data *ept;
@@ -1530,7 +1531,7 @@ unsigned int p2m_find_altp2m_by_eptp(struct domain *d, uint64_t eptp)
altp2m_list_lock(d);
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
if ( d->arch.altp2m_eptp[i] == mfn_x(INVALID_MFN) )
continue;
diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c
index 666abd46be..5a6ce2f8bc 100644
--- a/xen/arch/x86/mm/p2m-pt.c
+++ b/xen/arch/x86/mm/p2m-pt.c
@@ -519,12 +519,14 @@ int p2m_pt_handle_deferred_changes(uint64_t gpa)
struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
int rc;
+#ifdef CONFIG_ALTP2M
/*
* Should altp2m ever be enabled for NPT / shadow use, this code
* should be updated to make use of the active altp2m, like
* ept_handle_misconfig().
*/
ASSERT(!altp2m_active(current->domain));
+#endif
p2m_lock(p2m);
rc = do_recalc(p2m, PFN_DOWN(gpa));
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 5a3fda903e..e802f2e4e6 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -106,7 +106,7 @@ void p2m_change_entry_type_global(struct domain *d,
{
unsigned int i;
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
if ( d->arch.altp2m_eptp[i] != mfn_x(INVALID_MFN) )
{
@@ -152,7 +152,7 @@ bool p2m_memory_type_changed(struct domain *d)
{
unsigned int i;
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
if ( d->arch.altp2m_eptp[i] != mfn_x(INVALID_MFN) )
{
@@ -939,7 +939,7 @@ void p2m_change_type_range(struct domain *d,
{
unsigned int i;
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
if ( d->arch.altp2m_eptp[i] != mfn_x(INVALID_MFN) )
{
@@ -1015,7 +1015,7 @@ int p2m_finish_type_change(struct domain *d,
{
unsigned int i;
- for ( i = 0; i < MAX_ALTP2M; i++ )
+ for ( i = 0; i < d->nr_altp2m; i++ )
{
if ( d->arch.altp2m_eptp[i] != mfn_x(INVALID_MFN) )
{
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 303c338ef2..b7c58e8e2b 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -811,6 +811,12 @@ struct domain *domain_create(domid_t domid,
if ( config )
{
d->options = config->flags;
+#ifdef CONFIG_ALTP2M
+ d->nr_altp2m = config->altp2m.nr;
+#else
+ ASSERT(!config->altp2m.nr);
+#endif
+
d->vmtrace_size = config->vmtrace_size;
}
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index a69dd96084..573d34f239 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -116,7 +116,10 @@ struct xen_domctl_createdomain {
/* Altp2m mode signaling uses bits [0, 1]. */
#define XEN_DOMCTL_ALTP2M_mode_mask (0x3U)
#define XEN_DOMCTL_ALTP2M_mode(m) ((m) & XEN_DOMCTL_ALTP2M_mode_mask)
- uint32_t opts;
+ uint16_t opts;
+
+ /* Number of altp2ms to permit. */
+ uint16_t nr;
} altp2m;
/* Per-vCPU buffer size in bytes. 0 to disable. */
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index fe53d4fab7..e46d10c0c3 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -619,6 +619,10 @@ struct domain
unsigned int guest_request_sync : 1;
} monitor;
+#ifdef CONFIG_ALTP2M
+ unsigned int nr_altp2m; /* Number of altp2m tables. */
+#endif
+
unsigned int vmtrace_size; /* Buffer size in bytes, or 0 to disable. */
#ifdef CONFIG_ARGO
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v10 7/9] tools/libxl: Activate the altp2m_count feature
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
` (5 preceding siblings ...)
2025-07-16 20:15 ` [PATCH v10 6/9] xen: Make the maximum number of altp2m views configurable for x86 Petr Beneš
@ 2025-07-16 20:15 ` Petr Beneš
2025-07-16 20:15 ` [PATCH v10 8/9] xen/x86: Disallow creating domains with altp2m enabled and altp2m.nr == 0 Petr Beneš
2025-07-16 20:15 ` [PATCH v10 9/9] tools/ocaml: Add altp2m_count parameter Petr Beneš
8 siblings, 0 replies; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel; +Cc: Petr Beneš, Anthony PERARD, Juergen Gross
From: Petr Beneš <w1benny@gmail.com>
This commit activates the previously introduced altp2m_count parameter,
establishing the connection between libxl and Xen.
Signed-off-by: Petr Beneš <w1benny@gmail.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
---
tools/libs/light/libxl_create.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c
index 4301f17f90..a796178050 100644
--- a/tools/libs/light/libxl_create.c
+++ b/tools/libs/light/libxl_create.c
@@ -596,6 +596,10 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
.max_grant_frames = b_info->max_grant_frames,
.max_maptrack_frames = b_info->max_maptrack_frames,
.grant_opts = XEN_DOMCTL_GRANT_version(b_info->max_grant_version),
+ .altp2m = {
+ .opts = 0, /* .opts will be set below */
+ .nr = b_info->altp2m_count,
+ },
.vmtrace_size = ROUNDUP(b_info->vmtrace_buf_kb << 10, XC_PAGE_SHIFT),
.cpupool_id = info->poolid,
};
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v10 8/9] xen/x86: Disallow creating domains with altp2m enabled and altp2m.nr == 0
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
` (6 preceding siblings ...)
2025-07-16 20:15 ` [PATCH v10 7/9] tools/libxl: Activate the altp2m_count feature Petr Beneš
@ 2025-07-16 20:15 ` Petr Beneš
2025-07-16 20:15 ` [PATCH v10 9/9] tools/ocaml: Add altp2m_count parameter Petr Beneš
8 siblings, 0 replies; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel
Cc: Petr Beneš, Jan Beulich, Andrew Cooper, Roger Pau Monné
From: Petr Beneš <w1benny@gmail.com>
Since libxl finally sends the altp2m.nr value, we can remove the previously
introduced temporary workaround.
Creating domain with enabled altp2m while setting altp2m.nr == 0 doesn't
make sense and it's probably not what user wants.
Signed-off-by: Petr Beneš <w1benny@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
xen/arch/x86/domain.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 155ea1f79f..872e97999c 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -739,8 +739,9 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
if ( !config->altp2m.nr )
{
- /* Fix the value to the legacy default */
- config->altp2m.nr = 10;
+ dprintk(XENLOG_INFO,
+ "altp2m must be requested with altp2m.nr > 0\n");
+ return -EINVAL;
}
if ( config->altp2m.nr > MAX_NR_ALTP2M )
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v10 9/9] tools/ocaml: Add altp2m_count parameter
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
` (7 preceding siblings ...)
2025-07-16 20:15 ` [PATCH v10 8/9] xen/x86: Disallow creating domains with altp2m enabled and altp2m.nr == 0 Petr Beneš
@ 2025-07-16 20:15 ` Petr Beneš
8 siblings, 0 replies; 18+ messages in thread
From: Petr Beneš @ 2025-07-16 20:15 UTC (permalink / raw)
To: xen-devel
Cc: Petr Beneš, Christian Lindig, David Scott, Anthony PERARD,
Christian Lindig
From: Petr Beneš <w1benny@gmail.com>
Allow developers using the OCaml bindings to set the altp2m_count parameter.
Signed-off-by: Petr Beneš <w1benny@gmail.com>
Acked-by: Christian Lindig <christian.lindig@cloud.com>
---
tools/ocaml/libs/xc/xenctrl.ml | 1 +
tools/ocaml/libs/xc/xenctrl.mli | 1 +
tools/ocaml/libs/xc/xenctrl_stubs.c | 19 +++++++++++++++----
3 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
index 7e1aabad6c..97108b9d86 100644
--- a/tools/ocaml/libs/xc/xenctrl.ml
+++ b/tools/ocaml/libs/xc/xenctrl.ml
@@ -87,6 +87,7 @@ type domctl_create_config =
max_maptrack_frames: int;
max_grant_version: int;
altp2m_opts: int32;
+ altp2m_count: int32;
vmtrace_buf_kb: int32;
cpupool_id: int32;
arch: arch_domainconfig;
diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
index f44dba61ae..9fccb2c2c2 100644
--- a/tools/ocaml/libs/xc/xenctrl.mli
+++ b/tools/ocaml/libs/xc/xenctrl.mli
@@ -79,6 +79,7 @@ type domctl_create_config = {
max_maptrack_frames: int;
max_grant_version: int;
altp2m_opts: int32;
+ altp2m_count: int32;
vmtrace_buf_kb: int32;
cpupool_id: int32;
arch: arch_domainconfig;
diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c
index b51fd66788..ac2a7537d6 100644
--- a/tools/ocaml/libs/xc/xenctrl_stubs.c
+++ b/tools/ocaml/libs/xc/xenctrl_stubs.c
@@ -205,13 +205,22 @@ CAMLprim value stub_xc_domain_create(value xch_val, value wanted_domid, value co
#define VAL_MAX_MAPTRACK_FRAMES Field(config, 7)
#define VAL_MAX_GRANT_VERSION Field(config, 8)
#define VAL_ALTP2M_OPTS Field(config, 9)
-#define VAL_VMTRACE_BUF_KB Field(config, 10)
-#define VAL_CPUPOOL_ID Field(config, 11)
-#define VAL_ARCH Field(config, 12)
+#define VAL_ALTP2M_COUNT Field(config, 10)
+#define VAL_VMTRACE_BUF_KB Field(config, 11)
+#define VAL_CPUPOOL_ID Field(config, 12)
+#define VAL_ARCH Field(config, 13)
uint32_t domid = Int_val(wanted_domid);
+ uint32_t altp2m_opts = Int32_val(VAL_ALTP2M_OPTS);
+ uint32_t altp2m_nr = Int32_val(VAL_ALTP2M_COUNT);
uint64_t vmtrace_size = Int32_val(VAL_VMTRACE_BUF_KB);
+ if ( altp2m_opts != (uint16_t)altp2m_opts )
+ caml_invalid_argument("altp2m_opts");
+
+ if ( altp2m_nr != (uint16_t)altp2m_nr )
+ caml_invalid_argument("altp2m_count");
+
vmtrace_size = ROUNDUP(vmtrace_size << 10, XC_PAGE_SHIFT);
if ( vmtrace_size != (uint32_t)vmtrace_size )
caml_invalid_argument("vmtrace_buf_kb");
@@ -226,7 +235,8 @@ CAMLprim value stub_xc_domain_create(value xch_val, value wanted_domid, value co
.grant_opts =
XEN_DOMCTL_GRANT_version(Int_val(VAL_MAX_GRANT_VERSION)),
.altp2m = {
- .opts = Int32_val(VAL_ALTP2M_OPTS),
+ .opts = altp2m_opts,
+ .nr = altp2m_nr,
},
.vmtrace_size = vmtrace_size,
.cpupool_id = Int32_val(VAL_CPUPOOL_ID),
@@ -286,6 +296,7 @@ CAMLprim value stub_xc_domain_create(value xch_val, value wanted_domid, value co
#undef VAL_ARCH
#undef VAL_CPUPOOL_ID
#undef VAL_VMTRACE_BUF_KB
+#undef VAL_ALTP2M_COUNT
#undef VAL_ALTP2M_OPTS
#undef VAL_MAX_GRANT_VERSION
#undef VAL_MAX_MAPTRACK_FRAMES
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v10 1/9] tools/xl: Add altp2m_count parameter
2025-07-16 20:15 ` [PATCH v10 1/9] tools/xl: Add altp2m_count parameter Petr Beneš
@ 2025-07-17 13:42 ` Nick Rosbrook
2025-07-18 15:16 ` Anthony PERARD
1 sibling, 0 replies; 18+ messages in thread
From: Nick Rosbrook @ 2025-07-17 13:42 UTC (permalink / raw)
To: Petr Beneš
Cc: xen-devel, Nick Rosbrook, George Dunlap, Anthony PERARD,
Juergen Gross
On Wed, Jul 16, 2025 at 4:19 PM Petr Beneš <w1benny@gmail.com> wrote:
>
> From: Petr Beneš <w1benny@gmail.com>
>
> Introduce a new altp2m_count parameter to control the maximum number of altp2m
> views a domain can use. By default, if altp2m_count is unspecified and altp2m
> is enabled, the value is set to 10, reflecting the legacy behavior.
>
> This change is preparatory; it establishes the groundwork for the feature but
> does not activate it.
>
> Signed-off-by: Petr Beneš <w1benny@gmail.com>
> ---
> tools/golang/xenlight/helpers.gen.go | 2 ++
> tools/golang/xenlight/types.gen.go | 1 +
> tools/include/libxl.h | 7 +++++++
> tools/libs/light/libxl_create.c | 10 ++++++++++
> tools/libs/light/libxl_internal.h | 1 +
> tools/libs/light/libxl_types.idl | 1 +
> tools/xl/xl_parse.c | 9 +++++++++
> 7 files changed, 31 insertions(+)
>
For the tools/golang changes,
Acked-by: Nick Rosbrook <enr0n@ubuntu.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v10 1/9] tools/xl: Add altp2m_count parameter
2025-07-16 20:15 ` [PATCH v10 1/9] tools/xl: Add altp2m_count parameter Petr Beneš
2025-07-17 13:42 ` Nick Rosbrook
@ 2025-07-18 15:16 ` Anthony PERARD
1 sibling, 0 replies; 18+ messages in thread
From: Anthony PERARD @ 2025-07-18 15:16 UTC (permalink / raw)
To: Petr Beneš
Cc: xen-devel, Nick Rosbrook, George Dunlap, Anthony PERARD,
Juergen Gross
On Wed, Jul 16, 2025 at 08:15:31PM +0000, Petr Beneš wrote:
> From: Petr Beneš <w1benny@gmail.com>
>
> Introduce a new altp2m_count parameter to control the maximum number of altp2m
> views a domain can use. By default, if altp2m_count is unspecified and altp2m
> is enabled, the value is set to 10, reflecting the legacy behavior.
>
> This change is preparatory; it establishes the groundwork for the feature but
> does not activate it.
>
> Signed-off-by: Petr Beneš <w1benny@gmail.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Thanks,
--
Anthony PERARD
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v10 3/9] x86/p2m: Short-circuit p2m_is_altp2m() when CONFIG_ALTP2M=n
2025-07-16 20:15 ` [PATCH v10 3/9] x86/p2m: Short-circuit p2m_is_altp2m() when CONFIG_ALTP2M=n Petr Beneš
@ 2025-07-22 14:50 ` Jan Beulich
0 siblings, 0 replies; 18+ messages in thread
From: Jan Beulich @ 2025-07-22 14:50 UTC (permalink / raw)
To: Petr Beneš; +Cc: Andrew Cooper, Roger Pau Monné, xen-devel
On 16.07.2025 22:15, Petr Beneš wrote:
> From: Petr Beneš <w1benny@gmail.com>
>
> Wrap the p2m_is_altp2m() check with IS_ENABLED(CONFIG_ALTP2M) to allow the
> compiler to short-circuit the condition at build time when ALTP2M is disabled.
>
> Signed-off-by: Petr Beneš <w1benny@gmail.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v10 4/9] x86/altp2m: Remove p2m_altp2m_check stubs from unsupported architectures
2025-07-16 20:15 ` [PATCH v10 4/9] x86/altp2m: Remove p2m_altp2m_check stubs from unsupported architectures Petr Beneš
@ 2025-07-22 14:56 ` Jan Beulich
2025-07-29 20:39 ` Petr Beneš
0 siblings, 1 reply; 18+ messages in thread
From: Jan Beulich @ 2025-07-22 14:56 UTC (permalink / raw)
To: Petr Beneš, Tamas K Lengyel
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Shawn Anastasio, Alistair Francis,
Bob Eshleman, Connor Davis, Oleksii Kurochko, Alexandru Isaila,
Petre Pircalabu, Andrew Cooper, Roger Pau Monné, xen-devel
On 16.07.2025 22:15, Petr Beneš wrote:
> From: Petr Beneš <w1benny@gmail.com>
>
> The p2m_altp2m_check() stub was previously declared on all architectures,
> even though the altp2m feature is only supported on x86. This patch removes
> the unused stub definitions from ARM, PPC, and RISC-V, and wraps the actual
> usage sites in #ifdef CONFIG_ALTP2M instead.
Hmm, using IS_ENABLED() would certainly be preferred. That would apparently
require ...
> --- a/xen/arch/x86/include/asm/p2m.h
> +++ b/xen/arch/x86/include/asm/p2m.h
> @@ -962,17 +962,16 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
> /* Set a specific p2m view visibility */
> int p2m_set_altp2m_view_visibility(struct domain *d, unsigned int altp2m_idx,
> uint8_t visible);
> -#else /* !CONFIG_HVM */
> -struct p2m_domain *p2m_get_altp2m(struct vcpu *v);
> -#endif /* CONFIG_HVM */
>
> #ifdef CONFIG_ALTP2M
> /* Check to see if vcpu should be switched to a different p2m. */
> void p2m_altp2m_check(struct vcpu *v, uint16_t idx);
... the declaration to be generally visible (likely also outside of x86).
> --- a/xen/common/vm_event.c
> +++ b/xen/common/vm_event.c
> @@ -430,9 +430,11 @@ static int vm_event_resume(struct domain *d, struct vm_event_domain *ved)
> */
> vm_event_toggle_singlestep(d, v, &rsp);
>
> +#ifdef CONFIG_ALTP2M
> /* Check for altp2m switch */
> if ( rsp.flags & VM_EVENT_FLAG_ALTERNATE_P2M )
> p2m_altp2m_check(v, rsp.altp2m_idx);
> +#endif
Is (and was) this actually correct? Shouldn't the caller be notified
somehow that its use of VM_EVENT_FLAG_ALTERNATE_P2M had no effect when
ALTP2M=n?
Jan
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v10 5/9] x86/altp2m: Wrap altp2m-specific code in #ifdef CONFIG_ALTP2M
2025-07-16 20:15 ` [PATCH v10 5/9] x86/altp2m: Wrap altp2m-specific code in #ifdef CONFIG_ALTP2M Petr Beneš
@ 2025-07-22 15:51 ` Jan Beulich
0 siblings, 0 replies; 18+ messages in thread
From: Jan Beulich @ 2025-07-22 15:51 UTC (permalink / raw)
To: Petr Beneš
Cc: Andrew Cooper, Roger Pau Monné, Tamas K Lengyel,
Alexandru Isaila, Petre Pircalabu, xen-devel
On 16.07.2025 22:15, Petr Beneš wrote:
> --- a/xen/arch/x86/hvm/emulate.c
> +++ b/xen/arch/x86/hvm/emulate.c
> @@ -2686,8 +2686,8 @@ static int cf_check hvmemul_tlb_op(
> return rc;
> }
>
> -static int cf_check hvmemul_vmfunc(
> - struct x86_emulate_ctxt *ctxt)
> +#ifdef CONFIG_ALTP2M
> +static int cf_check hvmemul_vmfunc(struct x86_emulate_ctxt *ctxt)
Please don't needlessly alter formatting, and ...
> {
> int rc;
>
> @@ -2699,6 +2699,12 @@ static int cf_check hvmemul_vmfunc(
>
> return rc;
> }
> +#else
> +static int cf_check hvmemul_vmfunc(struct x86_emulate_ctxt *ctxt)
> +{
> + return X86EMUL_UNHANDLEABLE;
> +}
> +#endif
... please don't duplicate function headers when such #ifdef-s can easily
be put inside the function body. Much like you do ...
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -4608,6 +4608,7 @@ static int hvmop_get_param(
> static int do_altp2m_op(
> XEN_GUEST_HANDLE_PARAM(void) arg)
> {
> +#ifdef CONFIG_ALTP2M
> struct xen_hvm_altp2m_op a;
> struct domain *d = NULL;
> int rc = 0;
> @@ -4944,6 +4945,9 @@ static int do_altp2m_op(
> rcu_unlock_domain(d);
>
> return rc;
> +#else /* !CONFIG_ALTP2M */
> + return -EOPNOTSUPP;
> +#endif /* CONFIG_ALTP2M */
> }
... here.
> @@ -5261,6 +5269,7 @@ void hvm_toggle_singlestep(struct vcpu *v)
>
> void hvm_fast_singlestep(struct vcpu *v, uint16_t p2midx)
> {
> +#ifdef CONFIG_ALTP2M
> ASSERT(atomic_read(&v->pause_count));
>
> if ( !hvm_is_singlestep_supported() )
> @@ -5272,6 +5281,7 @@ void hvm_fast_singlestep(struct vcpu *v, uint16_t p2midx)
> v->arch.hvm.single_step = true;
> v->arch.hvm.fast_single_step.enabled = true;
> v->arch.hvm.fast_single_step.p2midx = p2midx;
> +#endif
> }
This function would better be unreachable when ALTP2M=n, imo. Putting an #ifdef
in vm_event_toggle_singlestep() would be the simple solution, but maybe we could
to better.
> @@ -707,6 +709,7 @@ static inline bool hvm_nested_virt_supported(void)
> return hvm_funcs.caps.nested_virt;
> }
>
> +#ifdef CONFIG_ALTP2M
> /* updates the current hardware p2m */
> static inline void altp2m_vcpu_update_p2m(struct vcpu *v)
> {
> @@ -731,6 +734,11 @@ static inline bool altp2m_vcpu_emulate_ve(struct vcpu *v)
> }
> return false;
> }
> +#else /* !CONFIG_ALTP2M */
> +void altp2m_vcpu_update_p2m(struct vcpu *v);
> +void altp2m_vcpu_update_vmfunc_ve(struct vcpu *v);
> +bool altp2m_vcpu_emulate_ve(struct vcpu *v);
> +#endif /* CONFIG_ALTP2M */
Why would the altp2m_vcpu_update_{p2m,vmfunc_ve}() declarations be needed? All
uses are from altp2m.c.
Jan
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v10 6/9] xen: Make the maximum number of altp2m views configurable for x86
2025-07-16 20:15 ` [PATCH v10 6/9] xen: Make the maximum number of altp2m views configurable for x86 Petr Beneš
@ 2025-07-23 15:26 ` Jan Beulich
0 siblings, 0 replies; 18+ messages in thread
From: Jan Beulich @ 2025-07-23 15:26 UTC (permalink / raw)
To: Petr Beneš
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, Tamas K Lengyel, Alexandru Isaila,
Petre Pircalabu, xen-devel
On 16.07.2025 22:15, Petr Beneš wrote:
> From: Petr Beneš <w1benny@gmail.com>
>
> This commit introduces the ability to configure the maximum number of altp2m
> views for the domain during its creation. Previously, the limits were hardcoded
> to a maximum of 10. This change allows for greater flexibility in environments
> that require more or fewer altp2m views.
>
> The maximum configurable limit for nr_altp2m on x86 is now set to
> MAX_NR_ALTP2M (which currently holds the MAX_EPTP value - 512). This cap is
> linked to the architectural limit of the EPTP-switching VMFUNC, which supports
> up to 512 entries. Despite there being no inherent need for limiting nr_altp2m
> in scenarios not utilizing VMFUNC, decoupling these components would necessitate
> substantial code changes.
>
> xen_domctl_createdomain::altp2m is extended for a new field `nr`, that will
> configure this limit for a domain. Additionally, previous altp2m.opts value
> has been reduced from uint32_t to uint16_t so that both of these fields occupy
> as little space as possible.
>
> Accesses to the altp2m_p2m array are modified to respect the new nr_altp2m
> value. Accesses to the altp2m_(visible_)eptp arrays are unmodified, since
> these arrays always have fixed size of MAX_EPTP.
>
> Additional sanitization is introduced in the x86/arch_sanitise_domain_config
> to fix the altp2m.nr value to 10 if it is previously set to 0. This behavior
> is only temporary and immediately removed in the upcoming commit (which will
> disallow creating a domain with enabled altp2m with zero nr_altp2m).
>
> The reason for this temporary workaround is to retain the legacy behavior
> until the feature is fully activated in libxl.
>
> Also, arm/arch_sanitise_domain_config is extended to not allow requesting
> non-zero altp2ms.
>
> Signed-off-by: Petr Beneš <w1benny@gmail.com>
> ---
> xen/arch/arm/domain.c | 2 +-
> xen/arch/x86/domain.c | 40 ++++++++++++++---
> xen/arch/x86/hvm/hvm.c | 8 +++-
> xen/arch/x86/hvm/vmx/vmx.c | 2 +-
> xen/arch/x86/include/asm/altp2m.h | 28 ++++++++++--
> xen/arch/x86/include/asm/domain.h | 9 ++--
> xen/arch/x86/include/asm/p2m.h | 4 +-
> xen/arch/x86/mm/altp2m.c | 72 ++++++++++++++++---------------
> xen/arch/x86/mm/hap/hap.c | 6 +--
> xen/arch/x86/mm/mem_access.c | 22 ++++------
> xen/arch/x86/mm/mem_sharing.c | 4 +-
> xen/arch/x86/mm/p2m-ept.c | 7 +--
> xen/arch/x86/mm/p2m-pt.c | 2 +
> xen/arch/x86/mm/p2m.c | 8 ++--
> xen/common/domain.c | 6 +++
> xen/include/public/domctl.h | 5 ++-
> xen/include/xen/sched.h | 4 ++
> 17 files changed, 151 insertions(+), 78 deletions(-)
I understand the cover letter has some revlog, but may I please ask to have
such (also) per-patch?
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -4675,6 +4675,12 @@ static int do_altp2m_op(
> goto out;
> }
>
> + if ( d->nr_altp2m == 0 )
> + {
> + rc = -EINVAL;
> + goto out;
> + }
Besides disliking EINVAL here, I also question this general rejection. For
e.g. HVMOP_altp2m_get_domain_state it may well make sense to still get back
"disabled". Yet I understand this affects a few of the pre-existing checks
as well.
With the error code changed to EOPNOTSUPP (as every other similar path uses,
with the sole exception of the "if ( XEN_ALTP2M_disabled == mode )" one):
Acked-by: Jan Beulich <jbeulich@suse.com>
> --- a/xen/arch/x86/mm/mem_access.c
> +++ b/xen/arch/x86/mm/mem_access.c
> @@ -81,6 +81,7 @@ bool p2m_mem_access_emulate_check(struct vcpu *v,
>
> if ( altp2m_active(d) )
> p2m = p2m_get_altp2m(v);
> +
> if ( !p2m )
> p2m = p2m_get_hostp2m(d);
>
> @@ -145,6 +146,7 @@ bool p2m_mem_access_check(paddr_t gpa, unsigned long gla,
>
> if ( altp2m_active(d) )
> p2m = p2m_get_altp2m(v);
> +
> if ( !p2m )
> p2m = p2m_get_hostp2m(d);
I think such stray changes would better be omitted, especially from an already
large patch.
Jan
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v10 4/9] x86/altp2m: Remove p2m_altp2m_check stubs from unsupported architectures
2025-07-22 14:56 ` Jan Beulich
@ 2025-07-29 20:39 ` Petr Beneš
2025-07-30 5:33 ` Jan Beulich
0 siblings, 1 reply; 18+ messages in thread
From: Petr Beneš @ 2025-07-29 20:39 UTC (permalink / raw)
To: Jan Beulich
Cc: Tamas K Lengyel, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk,
Shawn Anastasio, Alistair Francis, Bob Eshleman, Connor Davis,
Oleksii Kurochko, Alexandru Isaila, Petre Pircalabu,
Andrew Cooper, Roger Pau Monné, xen-devel
On Tue, Jul 22, 2025 at 4:56 PM Jan Beulich <jbeulich@suse.com> wrote:
> Hmm, using IS_ENABLED() would certainly be preferred.
Why? Very similar usage is a few lines above, with #ifdef
CONFIG_MEM_PAGING and CONFIG_MEM_SHARING.
> That would apparently require ...
> ... the declaration to be generally visible (likely also outside of x86).
With all the other changes in this series, it seems like it only makes
sense to guard p2m_altp2m_check with CONFIG_ALTP2M.
"Having the declaration to be generally visible" is exactly what I was
trying to avoid.
P.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v10 4/9] x86/altp2m: Remove p2m_altp2m_check stubs from unsupported architectures
2025-07-29 20:39 ` Petr Beneš
@ 2025-07-30 5:33 ` Jan Beulich
0 siblings, 0 replies; 18+ messages in thread
From: Jan Beulich @ 2025-07-30 5:33 UTC (permalink / raw)
To: Petr Beneš
Cc: Tamas K Lengyel, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk,
Shawn Anastasio, Alistair Francis, Bob Eshleman, Connor Davis,
Oleksii Kurochko, Alexandru Isaila, Petre Pircalabu,
Andrew Cooper, Roger Pau Monné, xen-devel
On 29.07.2025 22:39, Petr Beneš wrote:
> On Tue, Jul 22, 2025 at 4:56 PM Jan Beulich <jbeulich@suse.com> wrote:
>> Hmm, using IS_ENABLED() would certainly be preferred.
>
> Why? Very similar usage is a few lines above, with #ifdef
> CONFIG_MEM_PAGING and CONFIG_MEM_SHARING.
Our preference towards IS_ENABLED() (where possible) likely post-dates
the addition of those #ifdef-s.
Jan
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2025-07-30 5:33 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-16 20:15 [PATCH v10 0/9] x86: Make MAX_ALTP2M configurable Petr Beneš
2025-07-16 20:15 ` [PATCH v10 1/9] tools/xl: Add altp2m_count parameter Petr Beneš
2025-07-17 13:42 ` Nick Rosbrook
2025-07-18 15:16 ` Anthony PERARD
2025-07-16 20:15 ` [PATCH v10 2/9] docs/man: Add altp2m_count parameter to the xl.cfg manual Petr Beneš
2025-07-16 20:15 ` [PATCH v10 3/9] x86/p2m: Short-circuit p2m_is_altp2m() when CONFIG_ALTP2M=n Petr Beneš
2025-07-22 14:50 ` Jan Beulich
2025-07-16 20:15 ` [PATCH v10 4/9] x86/altp2m: Remove p2m_altp2m_check stubs from unsupported architectures Petr Beneš
2025-07-22 14:56 ` Jan Beulich
2025-07-29 20:39 ` Petr Beneš
2025-07-30 5:33 ` Jan Beulich
2025-07-16 20:15 ` [PATCH v10 5/9] x86/altp2m: Wrap altp2m-specific code in #ifdef CONFIG_ALTP2M Petr Beneš
2025-07-22 15:51 ` Jan Beulich
2025-07-16 20:15 ` [PATCH v10 6/9] xen: Make the maximum number of altp2m views configurable for x86 Petr Beneš
2025-07-23 15:26 ` Jan Beulich
2025-07-16 20:15 ` [PATCH v10 7/9] tools/libxl: Activate the altp2m_count feature Petr Beneš
2025-07-16 20:15 ` [PATCH v10 8/9] xen/x86: Disallow creating domains with altp2m enabled and altp2m.nr == 0 Petr Beneš
2025-07-16 20:15 ` [PATCH v10 9/9] tools/ocaml: Add altp2m_count parameter Petr Beneš
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.