hulk inclusion category: bugfix bugzilla: 26326 CVE: NA
-------------------------------------------------
Currently, when we test hibernation, it will fail at the ITS. [11384.327419] Call trace: [11384.329854] dump_backtrace+0x0/0x180 [11384.333503] show_stack+0x14/0x20 [11384.336805] dump_stack+0x8c/0xac [11384.340107] dequeue_task_idle+0x2c/0x68 [11384.344016] do_set_cpus_allowed+0x5c/0x148 [11384.348186] cpuset_cpus_allowed_fallback+0x1c/0x48 [11384.353050] select_fallback_rq+0x17c/0x220 [11384.355310] ITS queue not draining [11384.357219] sched_cpu_dying+0x328/0x368 [11384.364513] cpuhp_invoke_callback+0xc0/0x1f0 [11384.368856] _cpu_up+0x164/0x1e0 [11384.372070] enable_nonboot_cpus+0x7c/0xf8 [11384.376153] hibernation_snapshot+0x1c0/0x348 [11384.380496] hibernate+0xf4/0x290 [11384.383797] state_store+0x70/0xa0 [11384.387185] kobj_attr_store+0x14/0x28 [11384.390921] sysfs_kf_write+0x4c/0x60 [11384.394569] kernfs_fop_write+0x11c/0x1d0 [11384.398566] __vfs_write+0x1c/0x138 [11384.402041] vfs_write+0xb4/0x190 [11384.405342] ksys_write+0x50/0xa0 [11384.408643] __arm64_sys_write+0x14/0x20 [11384.412552] el0_svc_common+0x100/0x168 [11384.416374] el0_svc_handler+0x4c/0x68 [11384.420109] el0_svc+0x8/0xc [11384.422984] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
The its doesn't support hibernate, when hibernate() calls, the its doesn't suspend() and resume() successfully.
Add its herbinate state to support its suspend and resume correctly.
https://lkml.org/lkml/2019/12/2/270
Signed-off-by: Hongbo Yao yaohongbo@huawei.com Reviewed-by: Hanjun Guo guohanjun@huawei.com --- drivers/irqchip/irq-gic-v3-its.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 21dfe2266b31..f75f6d788567 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -38,6 +38,7 @@ #include <linux/of_platform.h> #include <linux/percpu.h> #include <linux/slab.h> +#include <linux/suspend.h> #include <linux/syscore_ops.h>
#include <linux/irqchip.h> @@ -53,6 +54,7 @@ #define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) #define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) #define ITS_FLAGS_SAVE_SUSPEND_STATE (1ULL << 3) +#define ITS_FLAGS_SAVE_HIBERNATE_STATE (1ULL << 4)
#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) #define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1) @@ -3365,8 +3367,16 @@ static int its_save_disable(void) raw_spin_lock(&its_lock); list_for_each_entry(its, &its_nodes, entry) { void __iomem *base; + u64 flags;
- if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE)) + if (system_in_hibernation()) + its->flags |= ITS_FLAGS_SAVE_HIBERNATE_STATE; + + flags = its->flags; + flags &= (ITS_FLAGS_SAVE_SUSPEND_STATE | + ITS_FLAGS_SAVE_HIBERNATE_STATE); + + if (!flags) continue;
base = its->base; @@ -3407,11 +3417,16 @@ static void its_restore_enable(void) raw_spin_lock(&its_lock); list_for_each_entry(its, &its_nodes, entry) { void __iomem *base; + u64 flags; int i;
- if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE)) + flags = its->flags; + flags &= (ITS_FLAGS_SAVE_SUSPEND_STATE | + ITS_FLAGS_SAVE_HIBERNATE_STATE); + if (!flags) continue;
+ its->flags &= ~ITS_FLAGS_SAVE_HIBERNATE_STATE; base = its->base;
/*