xen/arm: its: initialize host LPI state before activating ITSes

The boot CPU pending table must use the memory attributes selected by
ITS quirks. gicv3_lpi_init_host_lpis() is therefore called after
gicv3_its_init(). However, gicv3_its_init() also programs and enables
each ITS before host LPI state is allocated. No ITS commands are
submitted at that point, but this ordering relies on that implementation
detail.

Split per-ITS initialization into preparation and activation phases.
First map and disable every ITS and collect its quirks. Then initialize
host LPI state. Only after that, allocate and program the ITS tables and
command queue, and enable each ITS.

The subsequent gicv3_cpu_init() sequence remains unchanged: it programs
the Redistributor LPI tables, enables LPIs, and then submits the first
MAPC and SYNC commands.

Drop the now unreachable stub for gicv3_lpi_init_host_lpis().

Suggested-by: Julien Grall <julien@xen.org>
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Volodymyr Babchuk <volodymyr_babchuk@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
This commit is contained in:
Mykola Kvach authored and Michal Orzel committed 2026-10-26 09:01:40 +01:00
1 parent 4e3c0eeac5
commit b5c1b94155
3 files changed
+32 -26

No files matched your search

+28 -6
View File
@@ -11,6 +11,7 @@
#include <xen/lib.h> #include <xen/lib.h>
#include <xen/delay.h> #include <xen/delay.h>
#include <xen/iocap.h> #include <xen/iocap.h>
#include <xen/init.h>
#include <xen/libfdt/libfdt.h> #include <xen/libfdt/libfdt.h>
#include <xen/mm.h> #include <xen/mm.h>
#include <xen/rbtree.h> #include <xen/rbtree.h>
@@ -549,10 +550,9 @@ static int gicv3_disable_its(struct host_its *hw_its)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
static int gicv3_its_init_single_its(struct host_its *hw_its) static int __init gicv3_its_prepare_single_its(struct host_its *hw_its)
{ {
uint64_t reg; int ret;
int i, ret;
hw_its->its_base = ioremap_nocache(hw_its->addr, hw_its->size); hw_its->its_base = ioremap_nocache(hw_its->addr, hw_its->size);
if ( !hw_its->its_base ) if ( !hw_its->its_base )
@@ -564,6 +564,14 @@ static int gicv3_its_init_single_its(struct host_its *hw_its)
gicv3_its_enable_quirks(hw_its); gicv3_its_enable_quirks(hw_its);
return 0;
}
static int __init gicv3_its_init_single_its(struct host_its *hw_its)
{
uint64_t reg;
int i, ret;
reg = readq_relaxed(hw_its->its_base + GITS_TYPER); reg = readq_relaxed(hw_its->its_base + GITS_TYPER);
hw_its->devid_bits = GITS_TYPER_DEVICE_ID_BITS(reg); hw_its->devid_bits = GITS_TYPER_DEVICE_ID_BITS(reg);
hw_its->evid_bits = GITS_TYPER_EVENT_ID_BITS(reg); hw_its->evid_bits = GITS_TYPER_EVENT_ID_BITS(reg);
@@ -1189,7 +1197,7 @@ static void gicv3_its_acpi_init(void)
#endif #endif
int gicv3_its_init(void) int __init gicv3_its_init(unsigned int host_lpi_bits)
{ {
struct host_its *hw_its; struct host_its *hw_its;
int ret; int ret;
@@ -1199,6 +1207,22 @@ int gicv3_its_init(void)
else else
gicv3_its_acpi_init(); gicv3_its_acpi_init();
if ( list_empty(&host_its_list) )
return 0;
list_for_each_entry(hw_its, &host_its_list, entry)
{
ret = gicv3_its_prepare_single_its(hw_its);
if ( ret )
return ret;
}
gicv3_its_validate_quirks();
ret = gicv3_lpi_init_host_lpis(host_lpi_bits);
if ( ret )
return ret;
list_for_each_entry(hw_its, &host_its_list, entry) list_for_each_entry(hw_its, &host_its_list, entry)
{ {
ret = gicv3_its_init_single_its(hw_its); ret = gicv3_its_init_single_its(hw_its);
@@ -1206,8 +1230,6 @@ int gicv3_its_init(void)
return ret; return ret;
} }
gicv3_its_validate_quirks();
return 0; return 0;
} }
+2 -13
View File
@@ -2037,20 +2037,9 @@ static int __init gicv3_init(void)
if ( gic_dist_supports_lpis() ) if ( gic_dist_supports_lpis() )
{ {
res = gicv3_its_init(); res = gicv3_its_init(intid_bits);
if ( res ) if ( res )
panic("GICv3: ITS: initialization failed: %d\n", res); panic("GICv3: ITS/LPI initialization failed: %d\n", res);
/*
* Host LPI allocation uses ITS-derived memory attributes, so defer it
* until after gicv3_its_init() has discovered ITS workarounds.
*/
if ( gicv3_its_host_has_its() )
{
res = gicv3_lpi_init_host_lpis(intid_bits);
if ( res )
panic("GICv3: LPI initialization failed: %d\n", res);
}
} }
res = gicv3_cpu_init(); res = gicv3_cpu_init();
+2 -7
View File
@@ -156,7 +156,7 @@ int gicv3_lpi_init_rdist(void __iomem * rdist_base);
/* Initialize the host structures for LPIs and the host ITSes. */ /* Initialize the host structures for LPIs and the host ITSes. */
int gicv3_lpi_init_host_lpis(unsigned int host_lpi_bits); int gicv3_lpi_init_host_lpis(unsigned int host_lpi_bits);
int gicv3_its_init(void); int gicv3_its_init(unsigned int host_lpi_bits);
/* Store the physical address and ID for each redistributor as read from DT. */ /* Store the physical address and ID for each redistributor as read from DT. */
void gicv3_set_redist_address(paddr_t address, unsigned int redist_id); void gicv3_set_redist_address(paddr_t address, unsigned int redist_id);
@@ -240,12 +240,7 @@ static inline int gicv3_lpi_init_rdist(void __iomem * rdist_base)
return -ENODEV; return -ENODEV;
} }
static inline int gicv3_lpi_init_host_lpis(unsigned int host_lpi_bits) static inline int gicv3_its_init(unsigned int host_lpi_bits)
{
return 0;
}
static inline int gicv3_its_init(void)
{ {
return 0; return 0;
} }
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.