xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Oleksandr <olekstysh@gmail.com>
To: Julien Grall <julien.grall@arm.com>, xen-devel@lists.xenproject.org
Cc: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>,
	sstabellini@kernel.org, Volodymyr_Babchuk@epam.com
Subject: Re: [Xen-devel] [PATCH] [RFC V2] xen/arm: Restrict "p2m_ipa_bits" according to the IOMMU requirements
Date: Tue, 10 Sep 2019 19:24:50 +0300	[thread overview]
Message-ID: <e7520ee5-2a31-d129-d736-7ce56589cb3e@gmail.com> (raw)
In-Reply-To: <d844f8b1-380d-0aed-785c-d889050b62c5@arm.com>


On 10.09.19 18:11, Julien Grall wrote:
> Hi Oleksandr,

Hi, Julien


>
> On 8/23/19 8:34 PM, Oleksandr Tyshchenko wrote:
>> From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
>>
>> There is a strict requirement for the IOMMU which wants to share
>> the P2M table with the CPU. The IOMMU's Stage-2 input size must be equal
>> to the P2M IPA size. It is not a problem when the IOMMU can support
>> all values the CPU supports. In that case, the IOMMU driver would just
>> use any "p2m_ipa_bits" value as is. But, there are cases when not.
>>
>> In order to make P2M sharing possible on the platforms which
>> IPMMUs have a limitation in maximum Stage-2 input size introduce
>> the following logic.
>>
>> First initialize the IOMMU subsystem and gather requirements regarding
>> the maximum IPA bits supported by each IOMMU device to figure out
>> the minimum value among them. In the P2M code, take into the account
>> the IOMMU requirements and choose suitable "pa_range" according
>> to the restricted "p2m_ipa_bits".
>
> As I pointed in the previous version, all the code you modify is arm64 
> specific. For arm32, the number of IPA bits is
> hardcoded. So if you modify p2m_ipa_bits, you would end up to 
> misconfigure VTCR.
> In other words, for Arm32, you need to check p2m_ipa_bits is at least 
> 40-bits before overriding it.

But, all modifications with p2m_ipa_bits are done before 
setup_virt_paging(), where, actually, the p2m_ipa_bits is hard-coded to 
40 bits. How can we end up misconfiguring VTCR for ARM32? Or I really 
missed something?


>
>
>>
>> Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
>> CC: Julien Grall <julien.grall@arm.com>
>>
>> ---
>> Still RFC:
>>
>> 1. Patch assumes that IPMMU support is already in.
>> 2. Not checked for the SMMU.
>>
>> Changes since RFC V1 [1]:
>>     - Don't update p2m_ipa_bits by the IOMMU drivers directly,
>>       introduce p2m_restrict_ipa_bits()
>>     - Clarify patch subject/description
>>     - Add more comments to code
>>     - Check for equivalent "pabits" in setup_virt_paging()
>>     - Remove ASSERTs from the SMMU and IPMMU drivers
>>
>> [1] 
>> https://lists.xenproject.org/archives/html/xen-devel/2019-08/msg02078.html
>> ---
>>   xen/arch/arm/p2m.c                       | 33 
>> ++++++++++++++++++++++++++++++--
>>   xen/arch/arm/setup.c                     | 11 +++++++++--
>>   xen/drivers/passthrough/arm/ipmmu-vmsa.c | 19 ++++--------------
>>   xen/drivers/passthrough/arm/smmu.c       | 16 ++++++++--------
>>   xen/include/asm-arm/p2m.h                |  8 ++++++++
>>   5 files changed, 60 insertions(+), 27 deletions(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index 2374e92..f742d9c 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -34,7 +34,8 @@ static unsigned int __read_mostly max_vmid = 
>> MAX_VMID_8_BIT;
>>     #define P2M_ROOT_PAGES    (1<<P2M_ROOT_ORDER)
>>   -unsigned int __read_mostly p2m_ipa_bits;
>> +/* Larger than any possible value */
>
> I think it would be worth explaining that this is required so the 
> number of P2M bits can be restricted by external entity (e.g IOMMU).

ok, will add explanation


>
>
>> +unsigned int __read_mostly p2m_ipa_bits = 64;
>>     /* Helpers to lookup the properties of each level */
>>   static const paddr_t level_masks[] =
>> @@ -1912,6 +1913,16 @@ struct page_info *get_page_from_gva(struct 
>> vcpu *v, vaddr_t va,
>>       return page;
>>   }
>>   +void __init p2m_restrict_ipa_bits(unsigned int iommu_ipa_bits)
>
> The name of the function is quite generic as most of the code in it. 
> So can we avoid use the term IOMMU in it?

yes, will do


>
>
>> +{
>> +    /*
>> +     * Calculate the minimum of the maximum IPA bits that any IOMMU
>> +     * can support.
>> +     */
>> +    if ( iommu_ipa_bits < p2m_ipa_bits )
>> +        p2m_ipa_bits = iommu_ipa_bits;
>> +}
>> +
>>   /* VTCR value to be configured by all CPUs. Set only once by the 
>> boot CPU */
>>   static uint32_t __read_mostly vtcr;
>>   @@ -1966,10 +1977,28 @@ void __init setup_virt_paging(void)
>>           [7] = { 0 }  /* Invalid */
>>       };
>>   -    unsigned int cpu;
>> +    unsigned int i, cpu;
>>       unsigned int pa_range = 0x10; /* Larger than any possible value */
>>       bool vmid_8_bit = false;
>>   +    if ( iommu_enabled )
>
> Could we make this IOMMU-agnostic? The main reason to convert from 
> p2m_ipa_bits to pa_range is to cater the rest of the code.
>
> But we could rework the code to do the computation with p2m_ipa_bits 
> and then look-up for the pa_range. 

I am afraid, I don't completely understand your idea of making this 
IOMMU-agnostic and what I should do...


>> +    {
>> +        /*
>> +         * Choose suitable "pa_range" according to the IOMMU 
>> requirements
>> +         * (restricted "p2m_ipa_bits" value).
>> +         * As P2M table is always configured with IPA bits == PA bits,
>> +         * check for equivalent "pabits" and store it's index.
>> +         */
>> +        for ( i = 0; i < ARRAY_SIZE(pa_range_info); i++ )
>> +        {
>> +            if ( p2m_ipa_bits == pa_range_info[i].pabits )
>> +            {
>> +                pa_range = i;
>> +                break;
>> +            }
>> +        }
>> +    }
>> +
>>       for_each_online_cpu ( cpu )
>>       {
>>           const struct cpuinfo_arm *info = &cpu_data[cpu];
>> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
>> index 51a6677..413f3e6 100644
>> --- a/xen/arch/arm/setup.c
>> +++ b/xen/arch/arm/setup.c
>> @@ -936,12 +936,19 @@ void __init start_xen(unsigned long 
>> boot_phys_offset,
>>       printk("Brought up %ld CPUs\n", (long)num_online_cpus());
>>       /* TODO: smp_cpus_done(); */
>>   -    setup_virt_paging();
>> -
>> +    /*
>> +     * The IOMMU subsystem must be initialized before P2M as we need 
>> to gather
>> +     * requirements regarding the maximum IPA bits supported by each 
>> IOMMU
>> +     * device to figure out the minimum value among them. The P2M 
>> code will
>> +     * choose suitable "pa_range" according to the restricted 
>> "p2m_ipa_bits"
>> +     * value.
>> +     */
>
> This is a bit too verbose, implementation details are not necessary 
> here and increasing the risk to have bit rot comment. So how about:
>
> "The IOMMU subsystem must be initialized before the P2M as we need to 
> gather requirements regarding the maximum IPA bit supported by each 
> IOMMU."?

you are right, will update a comment


>
>
>>       rc = iommu_setup();
>>       if ( !iommu_enabled && rc != -ENODEV )
>>           panic("Couldn't configure correctly all the IOMMUs.");
>>   +    setup_virt_paging();
>> +
>>       do_initcalls();
>>         /*
>> diff --git a/xen/drivers/passthrough/arm/ipmmu-vmsa.c 
>> b/xen/drivers/passthrough/arm/ipmmu-vmsa.c
>> index ec543c3..d2e36a4 100644
>> --- a/xen/drivers/passthrough/arm/ipmmu-vmsa.c
>> +++ b/xen/drivers/passthrough/arm/ipmmu-vmsa.c
>> @@ -1314,23 +1314,12 @@ static __init int ipmmu_init(struct 
>> dt_device_node *node, const void *data)
>>           return -ENODEV;
>>       }
>>       else
>> -    {
>>           /*
>> -         * As 4-level translation table is not supported in IPMMU, 
>> we need
>> -         * to check IPA size used for P2M table beforehand to be 
>> sure it is
>> -         * 3-level and the IPMMU will be able to use it.
>> -         *
>> -         * TODO: First initialize the IOMMU and gather the 
>> requirements and
>> -         * then initialize the P2M. In the P2M code, take into the 
>> account
>> -         * the IOMMU requirements and restrict "pa_range" if necessary.
>> +         * Set maximum Stage-2 input size supported by the IPMMU. We 
>> expect
>> +         * the P2M code will take into the account the IOMMU 
>> requirements and
>> +         * choose suitable "pa_range".
>
> I would drop the last sentence.

ok. will do


>
>
>>            */
>> -        if ( IPMMU_MAX_P2M_IPA_BITS < p2m_ipa_bits )
>> -        {
>> -            printk_once(XENLOG_ERR "ipmmu: P2M IPA size is not 
>> supported (P2M=%u IPMMU=%u)!\n",
>> -                        p2m_ipa_bits, IPMMU_MAX_P2M_IPA_BITS);
>> -            return -ENODEV;
>> -        }
>> -    }
>> +        p2m_restrict_ipa_bits(IPMMU_MAX_P2M_IPA_BITS);
>>         ret = ipmmu_probe(node);
>>       if ( ret )
>> diff --git a/xen/drivers/passthrough/arm/smmu.c 
>> b/xen/drivers/passthrough/arm/smmu.c
>> index 8ae986a..2b10c6e 100644
>> --- a/xen/drivers/passthrough/arm/smmu.c
>> +++ b/xen/drivers/passthrough/arm/smmu.c
>> @@ -2198,14 +2198,14 @@ static int arm_smmu_device_cfg_probe(struct 
>> arm_smmu_device *smmu)
>>       size = arm_smmu_id_size_to_bits((id >> ID2_IAS_SHIFT) & 
>> ID2_IAS_MASK);
>>       smmu->s1_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, 
>> size);
>>   -    /* Xen: Stage-2 input size has to match p2m_ipa_bits.  */
>> -    if (size < p2m_ipa_bits) {
>> -        dev_err(smmu->dev,
>> -            "P2M IPA size not supported (P2M=%u SMMU=%lu)!\n",
>> -            p2m_ipa_bits, size);
>> -        return -ENODEV;
>> -    }
>> -    smmu->s2_input_size = p2m_ipa_bits;
>> +    /*
>> +     * Xen:
>> +     * Set maximum Stage-2 input size supported by the SMMU. We expect
>> +     * the P2M code will take into the account the IOMMU 
>> requirements and
>> +     * choose suitable "pa_range".
>
> Same here.

ok


-- 
Regards,

Oleksandr Tyshchenko


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  reply	other threads:[~2019-09-10 16:25 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-23 19:34 [Xen-devel] [PATCH] [RFC V2] xen/arm: Restrict "p2m_ipa_bits" according to the IOMMU requirements Oleksandr Tyshchenko
2019-09-10 15:11 ` Julien Grall
2019-09-10 16:24   ` Oleksandr [this message]
2019-09-10 18:55     ` Julien Grall
2019-09-11 16:34       ` Oleksandr
2019-09-11 16:44         ` Julien Grall

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e7520ee5-2a31-d129-d736-7ce56589cb3e@gmail.com \
    --to=olekstysh@gmail.com \
    --cc=Volodymyr_Babchuk@epam.com \
    --cc=julien.grall@arm.com \
    --cc=oleksandr_tyshchenko@epam.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).