[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v5 3/6] arm/mpu: Provide and populate MPU C data structures


  • To: Julien Grall <julien@xxxxxxx>
  • From: Luca Fancellu <Luca.Fancellu@xxxxxxx>
  • Date: Wed, 14 May 2025 14:27:38 +0000
  • Accept-language: en-GB, en-US
  • Arc-authentication-results: i=2; mx.microsoft.com 1; spf=pass (sender ip is 4.158.2.129) smtp.rcpttodomain=xen.org smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=pass (signature was verified) header.d=arm.com; arc=pass (0 oda=1 ltdi=1 spf=[1,1,smtp.mailfrom=arm.com] dkim=[1,1,header.d=arm.com] dmarc=[1,1,header.from=arm.com])
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none
  • Arc-message-signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=LTrrrbM77KNeqeVQJm2I0wmbQ8tBjHiWW/yCH0bPAJk=; b=w+14iVAC/9HyO5ZcfAKV+FYMBU2HyHjLfieZZY1pByZ9lEn994+7Zw0L3PrI21PL2Tz6Zm81wWOWPUjlDbtIL1pzxIb/NDK/IzMknFY/7pqp1pwefaglQtNpbR0GDzpFmrrwe8kamarP5PmLJQ81uSOYd5QQuuccu7ZCvoWlqtlXS4FpksH6Jd3Av+7vmX04sBuYwY3lisnN2k+OaNA5bu/R0+mdJm95cMEivjtva2lHAgcKgJnPRWR0qQBJA7VijoiOAhv2jKUafZXnIKmdLlmuUxKabO0C40MrAaXIY3f+2UzYFZiDm1HRwkaZdcN++Pvn8YEuxF7Q+0ZxL3Yq9A==
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=LTrrrbM77KNeqeVQJm2I0wmbQ8tBjHiWW/yCH0bPAJk=; b=v19uLf/O8Jk4PlB1E77xQHG5plwID7UvguzNnWiUvrPd0uHxhpcX0gp+LaGCdVGdix7rzrlI3NhOmSSWrmJD+A8iPqhNSIBhZFVipBK/otjIScBH4ii7VKKHwk5o/9zgKbcnwMmeb/QT4RliZKoncNi7cQCvpB+iC+1i51asiHGAtqkSS0YWAes5cxpE4e/Zw6PffI2QIBygNLVXSqL7vnTTlVMQ4YJ89QFMwMlOy1MEpONAJmzizcKkbD41jUwuyO7wjE0qDNqBGyU2K+kqDJEEZxzdRqi3hFmh0wqtrNYD+9sgOpNk72drx7QoZX9yFKeuDXUy5cm4VxWeEdGofQ==
  • Arc-seal: i=2; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=pass; b=vbTZp731xIQitgZlcdf7WvwxLfZBprQPV9GNorSBPkrO7XKsVdSiftLXusbPqwUQor0R5wuHCnLbaTsYtyBBd7iLm2lFY+QtMtur7xe3LF6GDo0Br2n7pC3nPUquHmBnCHIzqPsoEjM7E0Vi8dVNNU/37Xq3GryBJSS3ibAiLtErMCxHlTTD8qf4lA4YD5DUV9lNhnOxqlaFSugFmYiWzV4sIFFJ6Xm0qYqa4CJdRqDFfQdQJLJRcO5okF36ZEMRHZSX9YxhGqA2PhpjuquXr32mbtqHibPNSo9c9tqb6kX6JumSvbKciE8MJ3E9yvAoEFRxxM/GUAj80yZIe/i8UA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=XCvGZKKjcbT6a+IBDP7bOVaASjn+Dn+Nk2b1O6okNEAF47dBgnPjszRgcMP/DDRUL3P1XgwQo+DzrsU5arb3vcs8+7B+DRs7vPU6iPqViOD3T9ntbhMOTvUlRvAcdzHe2EhXrc7rHcjBtA2kLWJpR92Gu1k9rrLISK9fuf2giJ4WcMxaWegmgvDQUeD3ONDunr664SZE69xwm7KQM/dFDD6cuF4V6UJgN4sKnWO9gCSyjBhDfp4Cxd10lomIC6NdpwxZEYuUTETTYeo1vtDFy0QVOcHI997pSD69RJrCx+/4xL2ZabSRQqwRWhEdz0+M9R7wFVwIzmEM48IgKdc2YQ==
  • Authentication-results-original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com;
  • Cc: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Bertrand Marquis <Bertrand.Marquis@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Wed, 14 May 2025 14:28:36 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Nodisclaimer: true
  • Thread-index: AQHbw+N7OQ17lZ1szkalxBxuriXrX7PRz90AgABg5wA=
  • Thread-topic: [PATCH v5 3/6] arm/mpu: Provide and populate MPU C data structures

Hi Julien,

>> diff --git a/xen/arch/arm/arm64/mpu/head.S b/xen/arch/arm/arm64/mpu/head.S
>> index 6d336cafbbaf..59ddc46526eb 100644
>> --- a/xen/arch/arm/arm64/mpu/head.S
>> +++ b/xen/arch/arm/arm64/mpu/head.S
>> @@ -40,6 +40,9 @@ FUNC(enable_boot_cpu_mm)
>>      mrs   x5, MPUIR_EL2
>>      and   x5, x5, #NUM_MPU_REGIONS_MASK
>>  +    ldr   x0, =max_mpu_regions
>> +    strb  w5, [x0]
> 
> Below you are handling cache invalidation when writing to the bitmap. But you 
> don't do one here. Is this just an overlook?

oh yes, overlooked, thanks

>> 
>> diff --git a/xen/arch/arm/include/asm/bitmap-op.inc 
>> b/xen/arch/arm/include/asm/bitmap-op.inc
>> new file mode 100644
>> index 000000000000..ea7c8abbf6f0
>> --- /dev/null
>> +++ b/xen/arch/arm/include/asm/bitmap-op.inc
>> @@ -0,0 +1,67 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +
>> +/*
>> + * Sets a bit in a bitmap declared by DECLARE_BITMAP, symbol name passed 
>> through
>> + * bitmap_symbol.
>> + *
>> + * bitmap_set_bit:      symbol of the bitmap declared by DECLARE_BITMAP
>> + * bit:                 bit number to be set in the bitmap
>> + * tmp1-tmp4:           temporary registers used for the computation
>> + *
>> + * Preserves bit.
>> + * Output:
>> + *  tmp1: Address of the word containing the changed bit.
> 
> If the register is used for output, then I think it needs a better name.
> But looking at the code, it is not entirely clear how the output will be used.

So currently it will give the address of the word containing the bit, so that 
we will
pass it to the invalidate cache function.

> 
>> + * Clobbers: tmp1, tmp2, tmp3, tmp4.
>> + */
>> +.macro bitmap_set_bit bitmap_symbol, bit, tmp1, tmp2, tmp3, tmp4
> > +    adr_l   \tmp1, \bitmap_symbol> +    mov     \tmp2, #(BYTES_PER_LONG - 
> > 1)
>> +    mvn     \tmp2, \tmp2
>> +    lsr     \tmp3, \bit, #3
>> +    and     \tmp2, \tmp3, \tmp2
>> +    add     \tmp1, \tmp1, \tmp2                 /* bitmap_symbol + 
>> (bit/BITS_PER_LONG)*BYTES_PER_LONG */
> 
> Style: missing some spaces.
> 
> But is the comment explaining the logic above? If so, I think I would put it 
> right at the beginning to make easier to understand the logic. I would also 
> consider to split in smaller comments on each line e.g.:
> 
> * ... = ... + ...

Ok I’ll do a line by line explanation
>> 
>> diff --git a/xen/arch/arm/include/asm/mpu/regions.inc 
>> b/xen/arch/arm/include/asm/mpu/regions.inc
>> index 47868a152662..ba38213ffff1 100644
>> --- a/xen/arch/arm/include/asm/mpu/regions.inc
>> +++ b/xen/arch/arm/include/asm/mpu/regions.inc
>> @@ -1,14 +1,42 @@
>>  /* SPDX-License-Identifier: GPL-2.0-only */
>>  +#include <asm/bitmap-op.inc>
>>  #include <asm/mpu.h>
>>  #include <asm/sysregs.h>
>>    /* Backgroud region enable/disable */
>>  #define SCTLR_ELx_BR    BIT(17, UL)
>>  +#define REGION_DISABLED_PRLAR   0x00    /* NS=0 ATTR=000 EN=0 */
>>  #define REGION_NORMAL_PRLAR     0x0f    /* NS=0 ATTR=111 EN=1 */
>>  #define REGION_DEVICE_PRLAR     0x09    /* NS=0 ATTR=100 EN=1 */
>>  +#define PRLAR_ELx_EN            0x1
>> +
>> +#ifdef CONFIG_ARM_64
>> +#define XEN_MPUMAP_ENTRY_SHIFT  0x4     /* 16 byte structure */
>> +
>> +.macro store_pair reg1, reg2, dst
>> +    stp \reg1, \reg2, [\dst]
>> +.endm
>> +
>> +.macro invalidate_dcache_one reg
>> +    dc ivac, \reg
>> +.endm
>> +
>> +#else
>> +#define XEN_MPUMAP_ENTRY_SHIFT  0x3     /* 8 byte structure */
>> +
>> +.macro store_pair reg1, reg2, dst
>> +    nop
> 
> Can we use a function that will trigger a fault? So we will remember this 
> will needed to be updated. Maybe re-use the BUG_OPCODE?

Sure, I’ll look into it

> 
>> +.endm
>> +
>> +.macro invalidate_dcache_one reg
>> +    nop
> 
> Same here.
> 
>> +.endm
> > +> +#endif
>> +
>>  /*
>>   * Macro to prepare and set a EL2 MPU memory region.
>>   * We will also create an according MPU memory region entry, which
>> @@ -56,6 +84,27 @@
>>      isb
>>      WRITE_SYSREG_ASM(\prbar, PRBAR_EL2)
>>      WRITE_SYSREG_ASM(\prlar, PRLAR_EL2)
>> +
>> +    /* Load pair into xen_mpumap and invalidate cache */
> 
> To confirm my understanding, xen_mpumap is part of the loaded binary. So we 
> expect the bootloader to have clean the cache for us. Therefore, we
> only need to invalidate the entries afterwards. Is it correct?

yes xen_mpumap is part of the binary, are you suggesting we should use clean 
and invalidate here? So for example boot-wrapper-aarch64 is not
cleaning the cache.

> 
>> +    adr_l \base, xen_mpumap
>> +    add   \base, \base, \sel, LSL #XEN_MPUMAP_ENTRY_SHIFT
>> +    store_pair \prbar, \prlar, \base
> 
> I think you want a comment on top of pr_t to mention the structure
> will not changed and

can you explain better this part, what should I write on top of the typedef 
struct {...} pt_t?

> 
>> +    invalidate_dcache_one \base
> 
> This will invalidate a single line in the data cache. The size depends on the 
> HW, but typically it will be 64 - 128 bytes. Do we have any check
> that will confirm the data will fit in an cache line?

You are right, so we are gonna write 16 bytes at most for Arm64 and (for now) 8 
bytes for Arm32, so I think we will be way below 64 bytes,
shall we have a BUILD_BUG_ON inside build_assertions() in arm/mpu/mm.c to check 
sizeof(pr_t) <= 64?

> 
>> +
>> +    /* Set/clear xen_mpumap_mask bitmap */
>> +    tst   \prlar, #PRLAR_ELx_EN
>> +    bne   2f
>> +    /* Region is disabled, clear the bit in the bitmap */
>> +    bitmap_clear_bit xen_mpumap_mask, \sel, \base, \limit, \prbar, \prlar
>> +    b     3f
>> +
>> +2:
>> +    /* Region is enabled, set the bit in the bitmap */
>> +    bitmap_set_bit xen_mpumap_mask, \sel, \base, \limit, \prbar, \prlar
>> +
>> +3:
>> +    invalidate_dcache_one \base
> 
> You want to a comment to explain what this invalidate does. AFAICT, this is 
> for the bitmap. But given the bitmap will be typically small, wouldn't it 
> better to do it in one go at the end?

Yes this invalidate is a bit overkill because it will invalidate 64-128 bytes 
starting from the address of the last changed word where the bit was.

Should I invalidate everything outside this macro, inside enable_boot_cpu_mm in 
arm64/mpu/head.S instead?

> 
> Same comment here.
> 
>> +
>>      dsb   sy
>>      isb
>>  diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
>> index 07c8959f4ee9..ee035a54b942 100644
>> --- a/xen/arch/arm/mpu/mm.c
>> +++ b/xen/arch/arm/mpu/mm.c
>> @@ -7,9 +7,25 @@
>>  #include <xen/mm.h>
>>  #include <xen/sizes.h>
>>  #include <xen/types.h>
>> +#include <asm/mpu.h>
>>    struct page_info *frame_table;
>>  +/* Maximum number of supported MPU memory regions by the EL2 MPU. */
>> +uint8_t __ro_after_init max_mpu_regions;
>> +
>> +/*
>> + * Bitmap xen_mpumap_mask is to record the usage of EL2 MPU memory regions.
>> + * Bit 0 represents MPU memory region 0, bit 1 represents MPU memory
>> + * region 1, ..., and so on.
>> + * If a MPU memory region gets enabled, set the according bit to 1.
>> + */
>> +DECLARE_BITMAP(xen_mpumap_mask, MAX_MPU_REGION_NR) \
>> +    __section(".data.page_aligned");
> 
> Why does this need to be page_aligned?

I see from the linker file that this section is aligned to SMP_CACHE_BYTES, 
which is L1_CACHE_BYTES
for Arm, because we are using the invalidate cache I was under the impression 
that it’s better to have it
aligned on the cache line

> 
>> +
>> +/* EL2 Xen MPU memory region mapping table. */
>> +pr_t __section(".data.page_aligned") xen_mpumap[MAX_MPU_REGION_NR];
> 
> I guess for this one this is mandated by the HW?

same reason above, no other reason (I’m aware of).

Cheers,
Luca


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.