| From 5def0055823238892cca25c7c7500bda88d01fde Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 5 Jul 2021 02:03:54 +0200 |
| Subject: MIPS: vdso: Invalid GIC access through VDSO |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Martin Fäcknitz <faecknitz@hotsplots.de> |
| |
| [ 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> |
| --- |
| arch/mips/include/asm/vdso/vdso.h | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| 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 */ |
| -- |
| 2.30.2 |
| |