[PATCH] xen/mm: Introduce per-arch pte_attr_t type for PTE flags

Shawn Anastasio posted 1 patch 10 months ago
Patches applied successfully (tree, apply log)
git fetch https://gitlab.com/xen-project/patchew/xen tags/patchew/47babd3f9ec00c15738a81aa57926e8a1f08cbe6.1735669493.git.sanastasio@raptorengineering.com
There is a newer version of this series
xen/arch/ppc/Kconfig             | 1 +
xen/arch/ppc/include/asm/types.h | 2 ++
xen/arch/ppc/mm-radix.c          | 2 +-
xen/common/Kconfig               | 3 +++
xen/common/efi/boot.c            | 4 ++--
xen/common/vmap.c                | 2 +-
xen/include/xen/mm.h             | 8 ++++++--
xen/include/xen/vmap.h           | 3 ++-
8 files changed, 18 insertions(+), 7 deletions(-)
[PATCH] xen/mm: Introduce per-arch pte_attr_t type for PTE flags
Posted by Shawn Anastasio 10 months ago
Xen's memory management APIs map_pages_to_xen, modify_xen_mappings,
set_fixmap, ioremap_attr, and __vmap all use an unsigned int to
represent architecture-dependent page table entry flags. This assumption
does not work on PPC/radix where some flags go past 32-bits, so
introduce the pte_attr_t type to allow architectures to opt in to larger
types to store PTE flags.

Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Shawn Anastasio <sanastasio@raptorengineering.com>
---
 xen/arch/ppc/Kconfig             | 1 +
 xen/arch/ppc/include/asm/types.h | 2 ++
 xen/arch/ppc/mm-radix.c          | 2 +-
 xen/common/Kconfig               | 3 +++
 xen/common/efi/boot.c            | 4 ++--
 xen/common/vmap.c                | 2 +-
 xen/include/xen/mm.h             | 8 ++++++--
 xen/include/xen/vmap.h           | 3 ++-
 8 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/xen/arch/ppc/Kconfig b/xen/arch/ppc/Kconfig
index 6db575a48d..3fae481117 100644
--- a/xen/arch/ppc/Kconfig
+++ b/xen/arch/ppc/Kconfig
@@ -3,6 +3,7 @@ config PPC
 	select FUNCTION_ALIGNMENT_4B
 	select HAS_DEVICE_TREE
 	select HAS_VMAP
+	select HAS_PTE_ATTR_T
 
 config PPC64
 	def_bool y
diff --git a/xen/arch/ppc/include/asm/types.h b/xen/arch/ppc/include/asm/types.h
index ffaf378a4d..a0b12f816a 100644
--- a/xen/arch/ppc/include/asm/types.h
+++ b/xen/arch/ppc/include/asm/types.h
@@ -8,4 +8,6 @@ typedef unsigned long vaddr_t;
 #define INVALID_PADDR (~0UL)
 #define PRIpaddr "016lx"
 
+typedef unsigned long pte_attr_t;
+
 #endif /* _ASM_PPC_TYPES_H */
diff --git a/xen/arch/ppc/mm-radix.c b/xen/arch/ppc/mm-radix.c
index 24232f3907..e02dffa7c5 100644
--- a/xen/arch/ppc/mm-radix.c
+++ b/xen/arch/ppc/mm-radix.c
@@ -265,7 +265,7 @@ int destroy_xen_mappings(unsigned long s, unsigned long e)
 int map_pages_to_xen(unsigned long virt,
                      mfn_t mfn,
                      unsigned long nr_mfns,
-                     unsigned int flags)
+                     pte_attr_t flags)
 {
     BUG_ON("unimplemented");
 }
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 6166327f4d..017075d667 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -80,6 +80,9 @@ config HAS_PIRQ
 config HAS_PMAP
 	bool
 
+config HAS_PTE_ATTR_T
+	bool
+
 config HAS_SCHED_GRANULARITY
 	bool
 
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index efbec00af9..c200a27523 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -1656,7 +1656,7 @@ void __init efi_init_memory(void)
     struct rt_extra {
         struct rt_extra *next;
         unsigned long smfn, emfn;
-        unsigned int prot;
+        pte_attr_t prot;
     } *extra, *extra_head = NULL;
 
     free_ebmalloc_unused_mem();
@@ -1671,7 +1671,7 @@ void __init efi_init_memory(void)
         EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
         u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
         unsigned long smfn, emfn;
-        unsigned int prot = PAGE_HYPERVISOR_RWX;
+        pte_attr_t prot = PAGE_HYPERVISOR_RWX;
         paddr_t mem_base;
         unsigned long mem_npages;
 
diff --git a/xen/common/vmap.c b/xen/common/vmap.c
index 47225fecc0..d6991421f3 100644
--- a/xen/common/vmap.c
+++ b/xen/common/vmap.c
@@ -222,7 +222,7 @@ static void vm_free(const void *va)
 }
 
 void *__vmap(const mfn_t *mfn, unsigned int granularity,
-             unsigned int nr, unsigned int align, unsigned int flags,
+             unsigned int nr, unsigned int align, pte_attr_t flags,
              enum vmap_region type)
 {
     void *va = vm_alloc(nr * granularity, align, type);
diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h
index 16f733281a..5386f931e7 100644
--- a/xen/include/xen/mm.h
+++ b/xen/include/xen/mm.h
@@ -70,6 +70,10 @@
 #include <xen/perfc.h>
 #include <public/memory.h>
 
+#ifndef CONFIG_HAS_PTE_ATTR_T
+typedef unsigned int pte_attr_t;
+#endif
+
 struct page_info;
 
 extern bool using_static_heap;
@@ -113,9 +117,9 @@ int map_pages_to_xen(
     unsigned long virt,
     mfn_t mfn,
     unsigned long nr_mfns,
-    unsigned int flags);
+    pte_attr_t flags);
 /* Alter the permissions of a range of Xen virtual address space. */
-int modify_xen_mappings(unsigned long s, unsigned long e, unsigned int nf);
+int modify_xen_mappings(unsigned long s, unsigned long e, pte_attr_t nf);
 void modify_xen_mappings_lite(unsigned long s, unsigned long e,
                               unsigned int nf);
 int destroy_xen_mappings(unsigned long s, unsigned long e);
diff --git a/xen/include/xen/vmap.h b/xen/include/xen/vmap.h
index 26c831757a..9e2edd1252 100644
--- a/xen/include/xen/vmap.h
+++ b/xen/include/xen/vmap.h
@@ -8,6 +8,7 @@
 #ifndef __XEN_VMAP_H__
 #define __XEN_VMAP_H__
 
+#include <xen/mm.h>
 #include <xen/mm-frame.h>
 #include <xen/page-size.h>
 
@@ -57,7 +58,7 @@ void vm_init_type(enum vmap_region type, void *start, void *end);
  * @return Pointer to the mapped area on success; NULL otherwise.
  */
 void *__vmap(const mfn_t *mfn, unsigned int granularity, unsigned int nr,
-             unsigned int align, unsigned int flags, enum vmap_region type);
+             unsigned int align, pte_attr_t flags, enum vmap_region type);
 
 /*
  * Map an array of pages contiguously into the VMAP_DEFAULT vmap region
-- 
2.30.2
Re: [PATCH] xen/mm: Introduce per-arch pte_attr_t type for PTE flags
Posted by Jan Beulich 9 months, 3 weeks ago
On 31.12.2024 19:27, Shawn Anastasio wrote:
> Xen's memory management APIs map_pages_to_xen, modify_xen_mappings,
> set_fixmap, ioremap_attr, and __vmap all use an unsigned int to
> represent architecture-dependent page table entry flags. This assumption
> does not work on PPC/radix where some flags go past 32-bits, so
> introduce the pte_attr_t type to allow architectures to opt in to larger
> types to store PTE flags.
> 
> Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Signed-off-by: Shawn Anastasio <sanastasio@raptorengineering.com>

As iirc Andrew had indicated when suggesting this, what you say for PPC is
true for x86 as well. Yet still we get around with unsigned int. Hence I
think the change needs describing differently.

> --- a/xen/include/xen/mm.h
> +++ b/xen/include/xen/mm.h
> @@ -70,6 +70,10 @@
>  #include <xen/perfc.h>
>  #include <public/memory.h>
>  
> +#ifndef CONFIG_HAS_PTE_ATTR_T
> +typedef unsigned int pte_attr_t;
> +#endif

This imo makes the Kconfig control a misnomer: We'll always have pte_attr_t.
I wonder whether this actually needs a Kconfig setting in the first place:
It's hardly the end of the world for all architectures to specify the type
(later: the underlying type, for the real type to become type-safe)
explicitly.

Jan
Re: [PATCH] xen/mm: Introduce per-arch pte_attr_t type for PTE flags
Posted by Shawn Anastasio 9 months, 3 weeks ago
On 1/9/25 3:15 AM, Jan Beulich wrote:
> On 31.12.2024 19:27, Shawn Anastasio wrote:
>> Xen's memory management APIs map_pages_to_xen, modify_xen_mappings,
>> set_fixmap, ioremap_attr, and __vmap all use an unsigned int to
>> represent architecture-dependent page table entry flags. This assumption
>> does not work on PPC/radix where some flags go past 32-bits, so
>> introduce the pte_attr_t type to allow architectures to opt in to larger
>> types to store PTE flags.
>>
>> Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com>
>> Signed-off-by: Shawn Anastasio <sanastasio@raptorengineering.com>
> 
> As iirc Andrew had indicated when suggesting this, what you say for PPC is
> true for x86 as well. Yet still we get around with unsigned int. Hence I
> think the change needs describing differently.
> 

I see what you mean -- I'll reword this to correctly reflect that the
change is not strictly necessary to accomodate architectures with
greater than 32-bit pte flags.

> Jan

Thanks,
Shawn
Re: [PATCH] xen/mm: Introduce per-arch pte_attr_t type for PTE flags
Posted by Andrew Cooper 9 months, 3 weeks ago
On 09/01/2025 9:15 am, Jan Beulich wrote:
> On 31.12.2024 19:27, Shawn Anastasio wrote:
>> Xen's memory management APIs map_pages_to_xen, modify_xen_mappings,
>> set_fixmap, ioremap_attr, and __vmap all use an unsigned int to
>> represent architecture-dependent page table entry flags. This assumption
>> does not work on PPC/radix where some flags go past 32-bits, so
>> introduce the pte_attr_t type to allow architectures to opt in to larger
>> types to store PTE flags.
>>
>> Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com>
>> Signed-off-by: Shawn Anastasio <sanastasio@raptorengineering.com>
> As iirc Andrew had indicated when suggesting this, what you say for PPC is
> true for x86 as well. Yet still we get around with unsigned int. Hence I
> think the change needs describing differently.

x86 is currently unsigned int, and with some reasonably expensive
packing/unpacking under the hood.

x86 ought to become unsigned long, now we don't have the 32bit build to
worry about.  (back of the envelope calculation says up/down: 400/-3868
(-3468) but I've not checked that this boots).

>
>> --- a/xen/include/xen/mm.h
>> +++ b/xen/include/xen/mm.h
>> @@ -70,6 +70,10 @@
>>  #include <xen/perfc.h>
>>  #include <public/memory.h>
>>  
>> +#ifndef CONFIG_HAS_PTE_ATTR_T
>> +typedef unsigned int pte_attr_t;
>> +#endif
> This imo makes the Kconfig control a misnomer: We'll always have pte_attr_t.
> I wonder whether this actually needs a Kconfig setting in the first place:
> It's hardly the end of the world for all architectures to specify the type
> (later: the underlying type, for the real type to become type-safe)
> explicitly.

All architectures strictly need this.  It's not optional, so doesn't
warrant a Kconfig option.

Either, arch/mm.h is required to provide the typedef, or we could have a
common one as so:

#ifndef pte_attr_t
typedef unsigned int pte_attr_t;
#endif

which architectures can influence with:

typedef unsigned long pte_attr_t;
#define pte_attr_t pte_attr_t

in the usual way.


One thing however does occur to me.  ARM and RISC-V have systems with
MPU protections rather than MMU, with Xen already starting to support
this on ARM.

Therefore we might want to reconsider the name pte_attr_t to be
something slightly less pagetable specific.  Then again, I'm not sure
how much overlap there is between the map* functions and MPUs, where
mapping is of course not possible.


Finally, this wants to be at least 2 patches.  One introducing
pte_attr_t, and one changing PPC to be unsigned long.

~Andrew

Re: [PATCH] xen/mm: Introduce per-arch pte_attr_t type for PTE flags
Posted by Shawn Anastasio 9 months, 3 weeks ago
On 1/9/25 4:56 AM, Andrew Cooper wrote:
> Either, arch/mm.h is required to provide the typedef,

This approach seems fine to me. I wanted to avoid changes to other
architectures where possible, but if this is acceptable then this is
probably the route I'd want to go down (see below).

For the reason outlined below, this would also probably mean that the
typedef would go before other includes at the top of arch/mm.h, and I'm
not sure if that would be an issue from a style perspective.
Alternatively, I could have arch/type.h define it on every architecture
if that would be acceptable.

> or we could have a common one as so:
> 
> #ifndef pte_attr_t
> typedef unsigned int pte_attr_t;
> #endif
> 
> which architectures can influence with:
> 
> typedef unsigned long pte_attr_t;
> #define pte_attr_t pte_attr_t
> 
> in the usual way.
>

There seems to be a pretty messy header dependency tree with xen/mm.h
where it #includes arch/mm.h halfway through the file after defining
(among other things) the prototypes for the functions that would need
pte_attr_t. Defining pte_attr_t this late in the file won't work since
the definition also needs to be visible to xen/vmap.h which gets
transitively included by the arch headers.

The kconfig route I went with sidesteps this by allowing the common
definition to not depend on previous header inclusions in its #ifndef
guard, but I agree with yours and Jan's comments about it not being the
best approach.

> 
> One thing however does occur to me.  ARM and RISC-V have systems with
> MPU protections rather than MMU, with Xen already starting to support
> this on ARM.
> 
> Therefore we might want to reconsider the name pte_attr_t to be
> something slightly less pagetable specific.  Then again, I'm not sure
> how much overlap there is between the map* functions and MPUs, where
> mapping is of course not possible.
> 

Without too much familiarity with ARM/RISC-V's MPU situation, at first
glance it seems to me that it would warrant a separate type, even if it
happened to coincide with the flag type used by the MMU on those arches.

> 
> Finally, this wants to be at least 2 patches.  One introducing
> pte_attr_t, and one changing PPC to be unsigned long.
>

Gotcha -- not a problem.

> ~Andrew

Thanks,
Shawn