|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 03/24] ARM: GICv3 ITS: allocate device and collection table
Hi,
On 24/10/16 15:30, Vijay Kilari wrote:
> On Wed, Sep 28, 2016 at 11:54 PM, Andre Przywara <andre.przywara@xxxxxxx>
> wrote:
>> Each ITS maps a pair of a DeviceID (usually the 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 the ITS.
>> We limit the number of devices to cover 4 PCI busses for now.
>
> Thunderx has more than 4 PCI busses
Yeah, I am thinking about a proper solution for that hack.
We may use a default of 4 buses and allow platform to override this.
Or make this a configuration value.
Or copy the Linux behaviour by limiting the number of pages to some
sensible value (16MB, if I got this correctly).
Anyway I think we need indirect table support to save Thunder from
allocating too much memory for this.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>
>> ---
>> xen/arch/arm/gic-its.c | 114
>> ++++++++++++++++++++++++++++++++++++++++++
>> xen/arch/arm/gic-v3.c | 5 ++
>> xen/include/asm-arm/gic-its.h | 49 +++++++++++++++++-
>> 3 files changed, 167 insertions(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/arm/gic-its.c b/xen/arch/arm/gic-its.c
>> index b52dff3..40238a2 100644
>> --- a/xen/arch/arm/gic-its.c
>> +++ b/xen/arch/arm/gic-its.c
>> @@ -21,6 +21,7 @@
>> #include <xen/device_tree.h>
>> #include <xen/libfdt/libfdt.h>
>> #include <asm/p2m.h>
>> +#include <asm/io.h>
>> #include <asm/gic.h>
>> #include <asm/gic_v3_defs.h>
>> #include <asm/gic-its.h>
>> @@ -38,6 +39,119 @@ static DEFINE_PER_CPU(void *, pending_table);
>> min_t(unsigned int, lpi_data.host_lpi_bits, CONFIG_HOST_LPI_BITS)
>> #define MAX_HOST_LPIS (BIT(MAX_HOST_LPI_BITS) - 8192)
>>
>> +#define BASER_ATTR_MASK \
>> + ((0x3UL << GITS_BASER_SHAREABILITY_SHIFT) | \
>> + (0x7UL << GITS_BASER_OUTER_CACHEABILITY_SHIFT) | \
>> + (0x7UL << GITS_BASER_INNER_CACHEABILITY_SHIFT))
>> +#define BASER_RO_MASK (GENMASK(52, 48) | GENMASK(58, 56))
>> +
>> +static uint64_t encode_phys_addr(paddr_t addr, int page_bits)
>> +{
>> + uint64_t ret;
>> +
>> + if ( page_bits < 16)
>> + return (uint64_t)addr & GENMASK(47, page_bits);
>> +
>> + ret = addr & GENMASK(47, 16);
>> + return ret | (addr & GENMASK(51, 48)) >> (48 - 12);
>
> why this mask and shift for?.
According to the (current issue of the) spec bits 48-51 of the address
are stored in bits 12-15 of the register.
>> +}
>> +
>> +static int gicv3_map_baser(void __iomem *basereg, uint64_t regc, int
>> nr_items)
>> +{
>> + uint64_t attr;
>> + int entry_size = (regc >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f;
>> + int pagesz;
>> + int order;
>> + void *buffer = NULL;
>> +
>> + 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;
>> +
>> + /*
>> + * Loop over the page sizes (4K, 16K, 64K) to find out what the host
>> + * supports.
>> + */
>> + for (pagesz = 0; pagesz < 3; pagesz++)
>> + {
>> + uint64_t reg;
>> + int nr_bytes;
>> +
>> + nr_bytes = ROUNDUP(nr_items * entry_size, BIT(pagesz * 2 + 12));
>> + order = get_order_from_bytes(nr_bytes);
>> +
>> + if ( !buffer )
>> + buffer = alloc_xenheap_pages(order, 0);
> Don't we need to reset to zero all the pages before handing
> memory to ITS hw?
True. Will fix it.
>> + if ( !buffer )
>> + return -ENOMEM;
>> +
>> + reg = attr;
>> + reg |= (pagesz << GITS_BASER_PAGE_SIZE_SHIFT);
>> + reg |= nr_bytes >> (pagesz * 2 + 12);
>> + reg |= regc & BASER_RO_MASK;
>> + reg |= GITS_BASER_VALID;
>> + reg |= encode_phys_addr(virt_to_maddr(buffer), pagesz * 2 + 12);
>> +
>> + writeq_relaxed(reg, basereg);
>> + regc = readl_relaxed(basereg);
>> +
>> + /* The host didn't like our attributes, just use what it returned.
>> */
>> + if ( (regc & BASER_ATTR_MASK) != attr )
>> + attr = regc & BASER_ATTR_MASK;
>> +
>> + /* If the host accepted our page size, we are done. */
>> + if ( (reg & (3UL << GITS_BASER_PAGE_SIZE_SHIFT)) == pagesz )
>> + return 0;
>> +
>> + /* Check whether our buffer is aligned to the next page size
>> already. */
>> + if ( !(virt_to_maddr(buffer) & (BIT(pagesz * 2 + 12 + 2) - 1)) )
>> + {
>> + free_xenheap_pages(buffer, order);
>> + buffer = NULL;
>> + }
>> + }
>> +
>> + if ( buffer )
>> + free_xenheap_pages(buffer, order);
>> +
>> + return -EINVAL;
>> +}
>> +
>> +int gicv3_its_init(struct host_its *hw_its)
>> +{
>> + uint64_t reg;
>> + int i;
>> +
>> + hw_its->its_base = ioremap_nocache(hw_its->addr, hw_its->size);
>> + if ( !hw_its->its_base )
>> + return -ENOMEM;
>> +
>> + for (i = 0; i < 8; i++)
>> + {
>> + void __iomem *basereg = hw_its->its_base + GITS_BASER0 + i * 8;
>> + int type;
>> +
>> + reg = readq_relaxed(basereg);
>> + type = (reg >> 56) & 0x7;
>
> define a macro for these constants
Sure.
Cheers,
Andre.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |