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

Re: [PATCH v2 2/7] arm/mpu: Provide access to the MPU region from the C code


  • To: Ayan Kumar Halder <ayankuma@xxxxxxx>
  • From: Luca Fancellu <Luca.Fancellu@xxxxxxx>
  • Date: Wed, 9 Apr 2025 10:21:12 +0000
  • Accept-language: en-GB, en-US
  • Arc-authentication-results: i=2; mx.microsoft.com 1; spf=permerror (sender ip is 4.158.2.129) smtp.rcpttodomain=amd.com 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=rS0KumpQdqhuu4el46q/s73I4WeH1UGavPN5jiivqSA=; b=sb+AYmoGRa9qh/1ql+I7YNUzTk9nvBRAf/twA7CudQsI6IFNimSpA8EeoOvZ3wXbuD+8Wjphho762L8E+uo180VKE1JPKpzYYKViIxbhmSwVT2rw//SWbl9IdCh14EBFWr4lX1YUZfy7uUZCjh03b9ji6DPiZM+EcI7Zcj4bE1p3UjIv8mfecKEb4RRI1jOQEDa27ZcBgsv2Me+Cte86NuTxRcQbh1W0c/uFDLXMbwhiDmSiuL/ZZlzggqwIIUZrp5c3T571vXbutCBEucheZFICwaJ8H11bq1UG1IgraWCpjI7azrfAWh3lElBb7PRceO17EYf2Ka2Ce63jVkn47g==
  • 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=rS0KumpQdqhuu4el46q/s73I4WeH1UGavPN5jiivqSA=; b=gmF0crxw8A8H5MnHEzK3DpjRJeMxZoQLzUHO6Mi9wL9113mxj6agwrbEMEPcGlhuRnQ+eYnvp91TneNkMADEvqE98w8CIfgSFpOBmlTE8MRE3MDbSD1J7QMCJ9BJRLvzQF+rIEiUv4DXIfeIRNc0OZ9vA58qUy4OmWpaME2FzMuAkmcSO2OkO/8J9w4NbBbFWPF6E6TpI6nmJyOmVq13UwLrNx/qYfMV2SpfHjoeXqGztq/6HMaa7bnex4Fkbh/dZhmmC2F5u2D10klMrEvQntCki9ZXk6L2zcGk1lNudDLdCuTS1jwo8w9a4jKBWz76kh8xmqaJrKLzk/RjFkNOpA==
  • Arc-seal: i=2; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=pass; b=kYSKN+0k27BRR3LfKG8mggVZKfJ/qFe1oqYVdAW6Jo50hk86wc2+GzrIlKUMU8jbVpVziwbT41WEcGHdxLjcjXIzTxEY0dftUDSqOgc5cEEddAmAzrM22X65AV7IJC20ESpwC/o35Upquc/np5OjWrxABjjuOqDGFLsQT6jEdcSpoM3o/571czvrWrcD8oTpycw/IU7BDNeSVH4DbeQ9YZwuoOP3ZPVwHROzt47EEijXsGL4J7wr5LghvJ85rXjHK5DnIKZL0G+RwGoZoZYg3UGMv6f64XSeTMrE451sRMnm64e35nsPtcIEMbiWSIVr7uIX1ti/51kiSP/UbpRCqw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=fq8UKzx16IghCCqrC2rxwNuDiunGAUqF8iEUP92G4HESknFCjCKnXZseZkvDFHqHxJrCTk/usmhRM3cN+4EdfT60kkiXpSjmjenpEyP2T1dh/rShtvp4I+wHwLoEsyd5exAcodRIV5rSuZ4Jx1iIjzRXbx7WKv8w6tvgMNAAqzFwNyOKWgOJRvDCSqZdCZHjhcmTexj6Zk1zy+GSD+CFOUaqlNEdmm0vW8Dr/BC7bZnPprngzoX0m797TTWIcJLVS6TZ1Z3AgrKqTIUQfsWtA821cZRc4t6cHGUtTP88GlocS9xDt31zcJYLK5hLBMY36rAgYOPXY6gYja3z+q+BJg==
  • 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>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <Bertrand.Marquis@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Wed, 09 Apr 2025 10:21:59 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Nodisclaimer: true
  • Thread-index: AQHbp52Ro+Yg+pQClU+WnJSxei+hH7OZzl8AgAAHm4CAACKVAIAABC6AgAAEEwCAAPj6AIAACQkAgAAcT4CAAAO6gA==
  • Thread-topic: [PATCH v2 2/7] arm/mpu: Provide access to the MPU region from the C code

Hi Ayan,

> On 9 Apr 2025, at 11:07, Ayan Kumar Halder <ayankuma@xxxxxxx> wrote:
> 
> 
> On 09/04/2025 09:26, Luca Fancellu wrote:
>> Hi Ayan,
> Hi Luca,
>> 
>>>>> The point of the code was to don’t issue an isb() every time we change 
>>>>> the selector,
>>>>> of course the code would be easier otherwise, but do we want to do that?
>>>> Not sure if it is beneficial as you would need to use isb() from region16 
>>>> onwards.
>>> The isb() is issued only when changing the selector, so when you go from 
>>> reading/writing regions
>>> from 0-15 to 16-31 for example, of course there is a case that if you 
>>> continuously write on region 15
>>> and 16 you would have to always change the selector, but it’s the less 
>>> impact we could have.
>>> 
>>> armv8-R is even better since it’s able to address regions from 0 to 23 
>>> without flushing the pipeline,
>>                  ^— aarch32 :)
> Can you point me to the document where you got this info ?

was referring to the r52, of course you are more knowledgeable on the armv8-r 
aarch32 part, so ...

>> 
>>> so I would say we should exploit this big advantage.
>>> 
>>> I’ll send shortly in this thread the code I would use and the code I was 
>>> thinking you could use.
>> Here the code I have in mind:
>> 
>> static void prepare_selector(uint8_t *sel)
>> {
>>     uint8_t cur_sel = *sel;
>>     /*
>>      * {read,write}_protection_region works using the direct access to the 
>> 0..15
>>      * regions, so in order to save the isb() overhead, change the PRSELR_EL2
>>      * only when needed, so when the upper 4 bits of the selector will 
>> change.
>>      */
>>     cur_sel &= 0xF0U;
>>     if ( READ_SYSREG(PRSELR_EL2) != cur_sel )
>>     {
>>         WRITE_SYSREG(cur_sel, PRSELR_EL2);
>>         isb();
>>     }
>>     *sel = *sel & 0xFU;
>> }
>> 
>> void read_protection_region(pr_t *pr_read, uint8_t sel)
>> {
>>     /*
>>      * Before accessing EL2 MPU region register PRBAR_EL2/PRLAR_EL2,
>>      * make sure PRSELR_EL2 is set, as it determines which MPU region
>>      * is selected.
>>      */
>>     prepare_selector(&sel);
>> 
>>     switch ( sel )
>>     {
>>         GENERATE_READ_PR_REG_CASE(0, pr_read);
>>         GENERATE_READ_PR_REG_CASE(1, pr_read);
>>         GENERATE_READ_PR_REG_CASE(2, pr_read);
>>         GENERATE_READ_PR_REG_CASE(3, pr_read);
>>         GENERATE_READ_PR_REG_CASE(4, pr_read);
>>         GENERATE_READ_PR_REG_CASE(5, pr_read);
>>         GENERATE_READ_PR_REG_CASE(6, pr_read);
>>         GENERATE_READ_PR_REG_CASE(7, pr_read);
>>         GENERATE_READ_PR_REG_CASE(8, pr_read);
>>         GENERATE_READ_PR_REG_CASE(9, pr_read);
>>         GENERATE_READ_PR_REG_CASE(10, pr_read);
>>         GENERATE_READ_PR_REG_CASE(11, pr_read);
>>         GENERATE_READ_PR_REG_CASE(12, pr_read);
>>         GENERATE_READ_PR_REG_CASE(13, pr_read);
>>         GENERATE_READ_PR_REG_CASE(14, pr_read);
>>         GENERATE_READ_PR_REG_CASE(15, pr_read);
>>     default:
>>         BUG(); /* Can't happen */
>>     }
>> }
>> 
>> void write_protection_region(const pr_t *pr_write, uint8_t sel)
>> {
>>     /*
>>      * Before accessing EL2 MPU region register PRBAR_EL2/PRLAR_EL2,
>>      * make sure PRSELR_EL2 is set, as it determines which MPU region
>>      * is selected.
>>      */
>>     prepare_selector(&sel);
>> 
>>     switch ( sel )
>>     {
>>         GENERATE_WRITE_PR_REG_CASE(0, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(1, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(2, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(3, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(4, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(5, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(6, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(7, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(8, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(9, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(10, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(11, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(12, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(13, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(14, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(15, pr_write);
>>     default:
>>         BUG(); /* Can't happen */
>>     }
>> }
> Till here I am fine if you think this is the correct approach for arm64.

Ok

>> 
>> Here the code I thought you could add for arm32:
>> 
>> static void prepare_selector(uint8_t *sel)
>> {
>>     uint8_t cur_sel = *sel;
>> 
>> #ifdef CONFIG_ARM_64
>>     /*
>>      * {read,write}_protection_region works using the direct access to the 
>> 0..15
>>      * regions, so in order to save the isb() overhead, change the PRSELR_EL2
>>      * only when needed, so when the upper 4 bits of the selector will 
>> change.
>>      */
>>     cur_sel &= 0xF0U;
>>     if ( READ_SYSREG(PRSELR_EL2) != cur_sel )
>>     {
>>         WRITE_SYSREG(cur_sel, PRSELR_EL2);
>>         isb();
>>     }
>>     *sel = *sel & 0xFU;
>> #else
>>     if ( cur_sel > 23 )
>>         panic("Armv8-R AArch32 region selector exceeds maximum allowed 
>> range!");
> I am not sure about this. See my question before. However ...
>> #endif
>> }
> 
> From ARM DDI 0568A.c ID110520
> 
> E2.2.3 HPRBAR<n> - Provides access to the base addresses for the first 32 
> defined EL2 MPU regions.
> 
> E2.2.6 HPRLAR<n> - Provides access to the limit addresses for the first 32 
> defined EL2 MPU regions.
> 
> I understand that HPRSELR is not used when directly accessing the above two 
> registers. Thus, this function will be a nop for Arm32. Please let me know if 
> I am mistaken.

yes you are right, you can decide if doing something or not in that function, 
you don’t need to change the selector.


> 
>> 
>> void read_protection_region(pr_t *pr_read, uint8_t sel)
>> {
>>     /*
>>      * Before accessing EL2 MPU region register PRBAR_EL2/PRLAR_EL2,
>>      * make sure PRSELR_EL2 is set, as it determines which MPU region
>>      * is selected.
>>      */
>>     prepare_selector(&sel);
>> 
>>     switch ( sel )
>>     {
>>         GENERATE_READ_PR_REG_CASE(0, pr_read);
>>         GENERATE_READ_PR_REG_CASE(1, pr_read);
>>         GENERATE_READ_PR_REG_CASE(2, pr_read);
>>         GENERATE_READ_PR_REG_CASE(3, pr_read);
>>         GENERATE_READ_PR_REG_CASE(4, pr_read);
>>         GENERATE_READ_PR_REG_CASE(5, pr_read);
>>         GENERATE_READ_PR_REG_CASE(6, pr_read);
>>         GENERATE_READ_PR_REG_CASE(7, pr_read);
>>         GENERATE_READ_PR_REG_CASE(8, pr_read);
>>         GENERATE_READ_PR_REG_CASE(9, pr_read);
>>         GENERATE_READ_PR_REG_CASE(10, pr_read);
>>         GENERATE_READ_PR_REG_CASE(11, pr_read);
>>         GENERATE_READ_PR_REG_CASE(12, pr_read);
>>         GENERATE_READ_PR_REG_CASE(13, pr_read);
>>         GENERATE_READ_PR_REG_CASE(14, pr_read);
>>         GENERATE_READ_PR_REG_CASE(15, pr_read);
>> #ifdef CONFIG_ARM_32
>>         GENERATE_READ_PR_REG_CASE(16, pr_read);
>>         GENERATE_READ_PR_REG_CASE(17, pr_read);
>>         GENERATE_READ_PR_REG_CASE(18, pr_read);
>>         GENERATE_READ_PR_REG_CASE(19, pr_read);
>>         GENERATE_READ_PR_REG_CASE(20, pr_read);
>>         GENERATE_READ_PR_REG_CASE(21, pr_read);
>>         GENERATE_READ_PR_REG_CASE(22, pr_read);
>>         GENERATE_READ_PR_REG_CASE(23, pr_read);
> At least 32 regions are directly accessible, thus thisn should go till 31 
> (0-31). Same ..

yeah you can add until the 31st here and ...

>> #endif
>>     default:
>>         BUG(); /* Can't happen */
>>     }
>> }
>> 
>> void write_protection_region(const pr_t *pr_write, uint8_t sel)
>> {
>>     /*
>>      * Before accessing EL2 MPU region register PRBAR_EL2/PRLAR_EL2,
>>      * make sure PRSELR_EL2 is set, as it determines which MPU region
>>      * is selected.
>>      */
>>     prepare_selector(&sel);
>> 
>>     switch ( sel )
>>     {
>>         GENERATE_WRITE_PR_REG_CASE(0, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(1, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(2, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(3, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(4, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(5, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(6, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(7, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(8, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(9, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(10, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(11, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(12, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(13, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(14, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(15, pr_write);
>> #ifdef CONFIG_ARM_32
>>         GENERATE_WRITE_PR_REG_CASE(16, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(17, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(18, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(19, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(20, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(21, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(22, pr_write);
>>         GENERATE_WRITE_PR_REG_CASE(23, pr_write);
> for here.

also here.

So I guess we are aligned for this patch right? I will update this patch as the 
code above and you
will modify the code for arm32 to support the direct access up to 32 region. Ok?

Cheers,
Luca



 


Rackspace

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