summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Fäcknitz <faecknitz@hotsplots.de>2021-07-05 02:03:54 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-07-20 16:05:59 +0200
commite09c9b558436405407563472f41b0aff437b9c7d (patch)
treebd9856508a09c302533c1f5d27aa2bd438bcb17b
parent20f79ce2b1ab4ead8a5a8742adab962fa7f50143 (diff)
downloadlinux-stable-e09c9b558436405407563472f41b0aff437b9c7d.tar.gz
linux-stable-e09c9b558436405407563472f41b0aff437b9c7d.tar.bz2
linux-stable-e09c9b558436405407563472f41b0aff437b9c7d.zip
MIPS: vdso: Invalid GIC access through VDSO
[ Upstream commit 47ce8527fbba145a7723685bc9a27d9855e06491 ] Accessing raw timers (currently only CLOCK_MONOTONIC_RAW) through VDSO doesn't return the correct time when using the GIC as clock source. The address of the GIC mapped page is in this case not calculated correctly. The GIC mapped page is calculated from the VDSO data by subtracting PAGE_SIZE: void *get_gic(const struct vdso_data *data) { return (void __iomem *)data - PAGE_SIZE; } However, the data pointer is not page aligned for raw clock sources. This is because the VDSO data for raw clock sources (CS_RAW = 1) is stored after the VDSO data for coarse clock sources (CS_HRES_COARSE = 0). Therefore, only the VDSO data for CS_HRES_COARSE is page aligned: +--------------------+ | | | vd[CS_RAW] | ---+ | vd[CS_HRES_COARSE] | | +--------------------+ | -PAGE_SIZE | | | | GIC mapped page | <--+ | | +--------------------+ When __arch_get_hw_counter() is called with &vd[CS_RAW], get_gic returns the wrong address (somewhere inside the GIC mapped page). The GIC counter values are not returned which results in an invalid time. Fixes: a7f4df4e21dd ("MIPS: VDSO: Add implementations of gettimeofday() and clock_gettime()") Signed-off-by: Martin Fäcknitz <faecknitz@hotsplots.de> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--arch/mips/include/asm/vdso/vdso.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/mips/include/asm/vdso/vdso.h b/arch/mips/include/asm/vdso/vdso.h
index 737ddfc3411c..a327ca21270e 100644
--- a/arch/mips/include/asm/vdso/vdso.h
+++ b/arch/mips/include/asm/vdso/vdso.h
@@ -67,7 +67,7 @@ static inline const struct vdso_data *get_vdso_data(void)
static inline void __iomem *get_gic(const struct vdso_data *data)
{
- return (void __iomem *)data - PAGE_SIZE;
+ return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE;
}
#endif /* CONFIG_CLKSRC_MIPS_GIC */