Commit 83559b47 authored by Marc Zyngier's avatar Marc Zyngier Committed by Thomas Gleixner

irqchip/gic-v3-its: Only emit SYNC if targetting a valid collection

It is possible, under obscure circumstances, to convince the ITS driver to
emit a SYNC operation that targets a collection that is not bound to any
redistributor (and the target_address field is zero) because the
corresponding CPU has not been seen yet (the system has been booted with
max_cpus="something small").

If the ITS is using the linear CPU number as the target, this is not a big
deal, as we just end-up issuing a SYNC to CPU0. But if the ITS requires the
physical address of the redistributor (with GITS_TYPER.PTA==1), we end-up
asking the ITS to write to the physical address zero, which is not exactly
a good idea (there has been report of the ITS locking up). This should of
course never happen, but hey, this is SW...

In order to avoid the above disaster, let's track which collections have
been actually initialized, and let's not generate a SYNC if the collection
hasn't been properly bound to a redistributor.  Take this opportunity to
spit our a warning, in the hope that someone may report the issue if it
arrises again.
Reported-by: default avatarYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Sumit Garg <sumit.garg@linaro.org>
Link: https://lkml.kernel.org/r/20180622095254.5906-6-marc.zyngier@arm.com
parent c1797b11
...@@ -182,6 +182,14 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev, ...@@ -182,6 +182,14 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev,
return its->collections + its_dev->event_map.col_map[event]; return its->collections + its_dev->event_map.col_map[event];
} }
static struct its_collection *valid_col(struct its_collection *col)
{
if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(0, 15)))
return NULL;
return col;
}
/* /*
* ITS command descriptors - parameters to be encoded in a command * ITS command descriptors - parameters to be encoded in a command
* block. * block.
...@@ -439,7 +447,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its, ...@@ -439,7 +447,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_movi_cmd(struct its_node *its, static struct its_collection *its_build_movi_cmd(struct its_node *its,
...@@ -458,7 +466,7 @@ static struct its_collection *its_build_movi_cmd(struct its_node *its, ...@@ -458,7 +466,7 @@ static struct its_collection *its_build_movi_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_discard_cmd(struct its_node *its, static struct its_collection *its_build_discard_cmd(struct its_node *its,
...@@ -476,7 +484,7 @@ static struct its_collection *its_build_discard_cmd(struct its_node *its, ...@@ -476,7 +484,7 @@ static struct its_collection *its_build_discard_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_inv_cmd(struct its_node *its, static struct its_collection *its_build_inv_cmd(struct its_node *its,
...@@ -494,7 +502,7 @@ static struct its_collection *its_build_inv_cmd(struct its_node *its, ...@@ -494,7 +502,7 @@ static struct its_collection *its_build_inv_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_int_cmd(struct its_node *its, static struct its_collection *its_build_int_cmd(struct its_node *its,
...@@ -512,7 +520,7 @@ static struct its_collection *its_build_int_cmd(struct its_node *its, ...@@ -512,7 +520,7 @@ static struct its_collection *its_build_int_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_clear_cmd(struct its_node *its, static struct its_collection *its_build_clear_cmd(struct its_node *its,
...@@ -530,7 +538,7 @@ static struct its_collection *its_build_clear_cmd(struct its_node *its, ...@@ -530,7 +538,7 @@ static struct its_collection *its_build_clear_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_invall_cmd(struct its_node *its, static struct its_collection *its_build_invall_cmd(struct its_node *its,
...@@ -1824,11 +1832,16 @@ static int its_alloc_tables(struct its_node *its) ...@@ -1824,11 +1832,16 @@ static int its_alloc_tables(struct its_node *its)
static int its_alloc_collections(struct its_node *its) static int its_alloc_collections(struct its_node *its)
{ {
int i;
its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections), its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections),
GFP_KERNEL); GFP_KERNEL);
if (!its->collections) if (!its->collections)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < nr_cpu_ids; i++)
its->collections[i].target_address = ~0ULL;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment