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

Re: [Xen-devel] [PATCH v2 03/27] ARM: GICv3 ITS: allocate device and collection table



Hi,

On 22/03/17 13:52, Julien Grall wrote:
> Hi Andre,
> 
> On 03/16/2017 11:20 AM, Andre Przywara wrote:
>> Each ITS maps a pair of a DeviceID (for instance derived from a PCI
>> b/d/f triplet) and an EventID (the MSI payload or interrupt ID) to a
>> pair of LPI number and collection ID, which points to the target CPU.
>> This mapping is stored in the device and collection tables, which
>> software
>> has to provide for the ITS to use.
>> Allocate the required memory and hand it to the ITS.
>> The maximum number of devices is limited to a compile-time constant
>> exposed in Kconfig.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>
>> ---
>>  docs/misc/xen-command-line.markdown |   8 ++
>>  xen/arch/arm/Kconfig                |  14 ++++
>>  xen/arch/arm/gic-v3-its.c           | 163
>> ++++++++++++++++++++++++++++++++++++
>>  xen/arch/arm/gic-v3.c               |   3 +
>>  xen/include/asm-arm/gic_v3_its.h    |  63 +++++++++++++-
>>  5 files changed, 250 insertions(+), 1 deletion(-)
>>
>> diff --git a/docs/misc/xen-command-line.markdown
>> b/docs/misc/xen-command-line.markdown
>> index 619016d..068d116 100644
>> --- a/docs/misc/xen-command-line.markdown
>> +++ b/docs/misc/xen-command-line.markdown
>> @@ -1158,6 +1158,14 @@ based interrupts. Any higher IRQs will be
>> available for use via PCI MSI.
>>  ### maxcpus
>>  > `= <integer>`
>>
>> +### max\_its\_device\_bits
>> +> `= <integer>`
>> +
>> +Specifies the maximum number of devices using MSIs on the ARM GICv3 ITS
>> +controller to allocate table entries for. Each table entry uses a
>> hardware
>> +specific size, typically 8 or 16 bytes.
>> +Defaults to 10 bits (to cover at most 1024 devices).
> 
> The description is misleading. Even if the platform has less than 1024
> devices, 10 may not be enough if the Device ID are not contiguous.

Right.

> However, I don't think this is useful. A user may not know the DevIDs in
> use of the platform and hence will not be able to choose a sensible value.
> 
> I still think that we should allocate what the hardware asked us and if
> it is necessary to limit this should be done per-platform.

I think you are right, a configurable limit does not make much sense. I
was wondering if we should have a hard coded *memory* limit instead, to
prevent ridiculously high allocations, say entry_size=8 and 32 bits of
device IDs, which would result in 32GB of memory for a flat device table.

Or if we don't want to arbitrarily limit this, we always print the
actual allocated size, maybe with a extra WARNING if it exceeds sane levels.

>> +
>>  ### max\_lpi\_bits
>>  > `= <integer>`
>>
>> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
>> index 86f7b53..0d50156 100644
>> --- a/xen/arch/arm/Kconfig
>> +++ b/xen/arch/arm/Kconfig
>> @@ -64,6 +64,20 @@ config MAX_PHYS_LPI_BITS
>>            This can be overridden on the command line with the
>> max_lpi_bits
>>            parameter.
>>
>> +config MAX_PHYS_ITS_DEVICE_BITS
>> +        depends on HAS_ITS
>> +        int "Number of device bits the ITS supports"
>> +        range 1 32
>> +        default "10"
>> +        help
>> +          Specifies the maximum number of devices which want to use
>> the ITS.
>> +          Xen needs to allocates memory for the whole range very early.
>> +          The allocation scheme may be sparse, so a much larger
>> number must
>> +          be supported to cover devices with a high bus number or
>> those on
>> +          separate bus segments.
>> +          This can be overridden on the command line with the
>> +          max_its_device_bits parameter.
> 
> From what I understand the default you suggested fit neither Cavium nor
> Qualcomm platform. It is also hard to see how a Distribution will be
> able to choose a sensible value here.

But it works for me (TM) ;-)
I was hoping that people would scream and suggest usable values instead
(because I don't know their limits). But indeed lets just remove that in
favor of something more future proof.

>> +
>>  endmenu
>>
>>  menu "ARM errata workaround via the alternative framework"
>> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
>> index 4056e5b..9982fe9 100644
>> --- a/xen/arch/arm/gic-v3-its.c
>> +++ b/xen/arch/arm/gic-v3-its.c
> 
> [...]
> 
>> +static int its_map_baser(void __iomem *basereg, uint64_t regc,
>> +                         unsigned int nr_items)
>> +{
>> +    uint64_t attr, reg;
>> +    unsigned int entry_size = GITS_BASER_ENTRY_SIZE(regc);
>> +    unsigned int pagesz = 2, order, table_size;
> 
> Please document what mean 2.
> 
>> +    void *buffer;
>> +
>> +    attr  = GIC_BASER_InnerShareable << GITS_BASER_SHAREABILITY_SHIFT;
>> +    attr |= GIC_BASER_CACHE_SameAsInner <<
>> GITS_BASER_OUTER_CACHEABILITY_SHIFT;
>> +    attr |= GIC_BASER_CACHE_RaWaWb <<
>> GITS_BASER_INNER_CACHEABILITY_SHIFT;
>> +
>> +    /*
>> +     * Setup the BASE register with the attributes that we like. Then
>> read
>> +     * it back and see what sticks (page size, cacheability and
>> shareability
>> +     * attributes), retrying if necessary.
>> +     */
>> +retry:
>> +    table_size = ROUNDUP(nr_items * entry_size,
>> BIT(BASER_PAGE_BITS(pagesz)));
>> +    /* The BASE registers support at most 256 pages. */
>> +    table_size = min(table_size, 256U << BASER_PAGE_BITS(pagesz));
>> +    /* The memory block must be aligned to the requested page size. */
>> +    order = max(get_order_from_bytes(table_size), pagesz * 2);
>> +
>> +    buffer = alloc_xenheap_pages(order, 0);
> 
> Why don't you use _zalloc(...)? This would avoid to compute the order
> and drop few lines.

Because they need to be physically contiguous.
Please correct me if I am wrong here, but the normal *alloc functions do
not guarantee this (from checking the implementation).

>> +    if ( !buffer )
>> +        return -ENOMEM;
>> +
>> +    if ( !check_propbaser_phys_addr(buffer, BASER_PAGE_BITS(pagesz)) )
> 
> The name of the function does not make sense. You check an address for
> the register BASER and not PROPBASER.

Indeed.

>> +    {
>> +        free_xenheap_pages(buffer, 0);
>> +        return -ERANGE;
>> +    }
>> +    memset(buffer, 0, table_size);
> 
> [...]
> 
>> +int gicv3_its_init(void)
>> +{
>> +    struct host_its *hw_its;
>> +    int ret;
>> +
>> +    list_for_each_entry(hw_its, &host_its_list, entry) {
> 
> Coding style:
> 
> list_for_each_entry(....)
> {

Yeah, I was looking at the Linux driver at the same time ;-)

>> +        ret = gicv3_its_init_single_its(hw_its);
>> +        if ( ret )
>> +            return ret;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>  /* Scan the DT for any ITS nodes and create a list of host ITSes out
>> of it. */
>>  void gicv3_its_dt_init(const struct dt_device_node *node)
>>  {
>> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
>> index ed78363..cc1e219 100644
>> --- a/xen/arch/arm/gic-v3.c
>> +++ b/xen/arch/arm/gic-v3.c
>> @@ -1590,6 +1590,9 @@ static int __init gicv3_init(void)
>>      spin_lock(&gicv3.lock);
>>
>>      gicv3_dist_init();
>> +    res = gicv3_its_init();
>> +    if ( res )
>> +        printk(XENLOG_WARNING "GICv3: ITS: initialization failed:
>> %d\n", res);
> 
> I would have expect a panic here because the ITS subsystem could be half
> initialized and it is not safe to continue.

OK, let me check what actually happens here if there is no ITS ;-)

Cheers,
Andre

> 
>>      res = gicv3_cpu_init();
>>      gicv3_hyp_init();
>>
> 
> Cheers,
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

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