ARM: GICv3 ITS: map ITS command buffer

Instead of directly manipulating the tables in memory, an ITS driver
sends commands via a ring buffer in normal system memory to the ITS h/w
to create or alter the LPI mappings.
Allocate memory for that buffer and tell the ITS about it to be able
to send ITS commands.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Julien Grall <julien.grall@arm.com>
This commit is contained in:
Andre Przywara authored and Stefano Stabellini committed 2017-04-07 15:15:45 -07:00
1 parent 05238012b8
commit 8ed8d21373
2 files changed
+59

No files matched your search

+53
View File
@@ -20,10 +20,13 @@
#include <xen/lib.h>
#include <xen/mm.h>
#include <xen/sizes.h>
#include <asm/gic_v3_defs.h>
#include <asm/gic_v3_its.h>
#include <asm/io.h>
#define ITS_CMD_QUEUE_SZ SZ_1M
/*
* No lock here, as this list gets only populated upon boot while scanning
* firmware tables for all host ITSes, and only gets iterated afterwards.
@@ -60,6 +63,51 @@ static uint64_t encode_baser_phys_addr(paddr_t addr, unsigned int page_bits)
return ret | ((addr & GENMASK(51, 48)) >> (48 - 12));
}
static void *its_map_cbaser(struct host_its *its)
{
void __iomem *cbasereg = its->its_base + GITS_CBASER;
uint64_t reg;
void *buffer;
reg = GIC_BASER_InnerShareable << GITS_BASER_SHAREABILITY_SHIFT;
reg |= GIC_BASER_CACHE_SameAsInner << GITS_BASER_OUTER_CACHEABILITY_SHIFT;
reg |= GIC_BASER_CACHE_RaWaWb << GITS_BASER_INNER_CACHEABILITY_SHIFT;
buffer = _xzalloc(ITS_CMD_QUEUE_SZ, SZ_64K);
if ( !buffer )
return NULL;
if ( virt_to_maddr(buffer) & ~GENMASK(51, 12) )
{
xfree(buffer);
return NULL;
}
reg |= GITS_VALID_BIT | virt_to_maddr(buffer);
reg |= ((ITS_CMD_QUEUE_SZ / SZ_4K) - 1) & GITS_CBASER_SIZE_MASK;
writeq_relaxed(reg, cbasereg);
reg = readq_relaxed(cbasereg);
/* If the ITS dropped shareability, drop cacheability as well. */
if ( (reg & GITS_BASER_SHAREABILITY_MASK) == 0 )
{
reg &= ~GITS_BASER_INNER_CACHEABILITY_MASK;
writeq_relaxed(reg, cbasereg);
}
/*
* If the command queue memory is mapped as uncached, we need to flush
* it on every access.
*/
if ( !(reg & GITS_BASER_INNER_CACHEABILITY_MASK) )
{
its->flags |= HOST_ITS_FLUSH_CMD_QUEUE;
printk(XENLOG_WARNING "using non-cacheable ITS command queue\n");
}
return buffer;
}
/* The ITS BASE registers work with page sizes of 4K, 16K or 64K. */
#define BASER_PAGE_BITS(sz) ((sz) * 2 + 12)
@@ -180,6 +228,11 @@ static int gicv3_its_init_single_its(struct host_its *hw_its)
}
}
hw_its->cmd_buf = its_map_cbaser(hw_its);
if ( !hw_its->cmd_buf )
return -ENOMEM;
writeq_relaxed(0, hw_its->its_base + GITS_CWRITER);
return 0;
}
+6
View File
@@ -79,8 +79,12 @@
#define GITS_BASER_OUTER_CACHEABILITY_MASK (0x7ULL << GITS_BASER_OUTER_CACHEABILITY_SHIFT)
#define GITS_BASER_INNER_CACHEABILITY_MASK (0x7ULL << GITS_BASER_INNER_CACHEABILITY_SHIFT)
#define GITS_CBASER_SIZE_MASK 0xff
#include <xen/device_tree.h>
#define HOST_ITS_FLUSH_CMD_QUEUE (1U << 0)
/* data structure for each hardware ITS */
struct host_its {
struct list_head entry;
@@ -91,6 +95,8 @@ struct host_its {
unsigned int devid_bits;
unsigned int evid_bits;
unsigned int itte_size;
void *cmd_buf;
unsigned int flags;
};
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.