Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm: vdso: Switch to generic storage implementation

The generic storage implementation provides the same features as the
custom one. However it can be shared between architectures, making
maintenance easier.

Co-developed-by: Nam Cao <namcao@linutronix.de>
Signed-off-by: Nam Cao <namcao@linutronix.de>
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250204-vdso-store-rng-v3-11-13a4669dfc8c@linutronix.de

authored by

Thomas Weißschuh and committed by
Thomas Gleixner
31e9fa2b d2862bb9

+15 -49
+2
arch/arm/include/asm/vdso.h
··· 4 4 5 5 #ifdef __KERNEL__ 6 6 7 + #define __VDSO_PAGES 4 8 + 7 9 #ifndef __ASSEMBLY__ 8 10 9 11 struct mm_struct;
+1 -6
arch/arm/include/asm/vdso/gettimeofday.h
··· 112 112 #define __arch_vdso_hres_capable arm_vdso_hres_capable 113 113 114 114 static __always_inline u64 __arch_get_hw_counter(int clock_mode, 115 - const struct vdso_data *vd) 115 + const struct vdso_time_data *vd) 116 116 { 117 117 #ifdef CONFIG_ARM_ARCH_TIMER 118 118 u64 cycle_now; ··· 133 133 /* Make GCC happy. This is compiled out anyway */ 134 134 return 0; 135 135 #endif 136 - } 137 - 138 - static __always_inline const struct vdso_data *__arch_get_vdso_data(void) 139 - { 140 - return _vdso_data; 141 136 } 142 137 143 138 #endif /* !__ASSEMBLY__ */
+2 -10
arch/arm/include/asm/vdso/vsyscall.h
··· 7 7 #include <vdso/datapage.h> 8 8 #include <asm/cacheflush.h> 9 9 10 - extern struct vdso_data *vdso_data; 11 10 extern bool cntvct_ok; 12 11 13 12 static __always_inline 14 - struct vdso_data *__arm_get_k_vdso_data(void) 15 - { 16 - return vdso_data; 17 - } 18 - #define __arch_get_k_vdso_data __arm_get_k_vdso_data 19 - 20 - static __always_inline 21 - void __arm_sync_vdso_data(struct vdso_data *vdata) 13 + void __arch_sync_vdso_time_data(struct vdso_time_data *vdata) 22 14 { 23 15 flush_dcache_page(virt_to_page(vdata)); 24 16 } 25 - #define __arch_sync_vdso_data __arm_sync_vdso_data 17 + #define __arch_sync_vdso_time_data __arch_sync_vdso_time_data 26 18 27 19 /* The asm-generic header needs to be included after the definitions above */ 28 20 #include <asm-generic/vdso/vsyscall.h>
-4
arch/arm/kernel/asm-offsets.c
··· 153 153 DEFINE(CACHE_WRITEBACK_ORDER, __CACHE_WRITEBACK_ORDER); 154 154 DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE); 155 155 BLANK(); 156 - #ifdef CONFIG_VDSO 157 - DEFINE(VDSO_DATA_SIZE, sizeof(union vdso_data_store)); 158 - #endif 159 - BLANK(); 160 156 #ifdef CONFIG_ARM_MPU 161 157 DEFINE(MPU_RNG_INFO_RNGS, offsetof(struct mpu_rgn_info, rgns)); 162 158 DEFINE(MPU_RNG_INFO_USED, offsetof(struct mpu_rgn_info, used));
+7 -27
arch/arm/kernel/vdso.c
··· 7 7 */ 8 8 9 9 #include <linux/cache.h> 10 + #include <linux/vdso_datastore.h> 10 11 #include <linux/elf.h> 11 12 #include <linux/err.h> 12 13 #include <linux/kernel.h> ··· 33 32 34 33 /* Total number of pages needed for the data and text portions of the VDSO. */ 35 34 unsigned int vdso_total_pages __ro_after_init; 36 - 37 - static union vdso_data_store vdso_data_store __page_aligned_data; 38 - struct vdso_data *vdso_data = vdso_data_store.data; 39 - 40 - static struct page *vdso_data_page __ro_after_init; 41 - static const struct vm_special_mapping vdso_data_mapping = { 42 - .name = "[vvar]", 43 - .pages = &vdso_data_page, 44 - }; 45 35 46 36 static int vdso_mremap(const struct vm_special_mapping *sm, 47 37 struct vm_area_struct *new_vma) ··· 184 192 if (vdso_text_pagelist == NULL) 185 193 return -ENOMEM; 186 194 187 - /* Grab the VDSO data page. */ 188 - vdso_data_page = virt_to_page(vdso_data); 189 - 190 195 /* Grab the VDSO text pages. */ 191 196 for (i = 0; i < text_pages; i++) { 192 197 struct page *page; ··· 194 205 195 206 vdso_text_mapping.pages = vdso_text_pagelist; 196 207 197 - vdso_total_pages = 1; /* for the data/vvar page */ 208 + vdso_total_pages = VDSO_NR_PAGES; /* for the data/vvar pages */ 198 209 vdso_total_pages += text_pages; 199 210 200 211 cntvct_ok = cntvct_functional(); ··· 205 216 } 206 217 arch_initcall(vdso_init); 207 218 208 - static int install_vvar(struct mm_struct *mm, unsigned long addr) 209 - { 210 - struct vm_area_struct *vma; 211 - 212 - vma = _install_special_mapping(mm, addr, PAGE_SIZE, 213 - VM_READ | VM_MAYREAD, 214 - &vdso_data_mapping); 215 - 216 - return PTR_ERR_OR_ZERO(vma); 217 - } 219 + static_assert(__VDSO_PAGES == VDSO_NR_PAGES); 218 220 219 221 /* assumes mmap_lock is write-locked */ 220 222 void arm_install_vdso(struct mm_struct *mm, unsigned long addr) ··· 218 238 if (vdso_text_pagelist == NULL) 219 239 return; 220 240 221 - if (install_vvar(mm, addr)) 241 + if (IS_ERR(vdso_install_vvar_mapping(mm, addr))) 222 242 return; 223 243 224 - /* Account for vvar page. */ 225 - addr += PAGE_SIZE; 226 - len = (vdso_total_pages - 1) << PAGE_SHIFT; 244 + /* Account for vvar pages. */ 245 + addr += VDSO_NR_PAGES * PAGE_SIZE; 246 + len = (vdso_total_pages - VDSO_NR_PAGES) << PAGE_SHIFT; 227 247 228 248 vma = _install_special_mapping(mm, addr, len, 229 249 VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+1
arch/arm/mm/Kconfig
··· 928 928 select GENERIC_TIME_VSYSCALL 929 929 select GENERIC_VDSO_32 930 930 select GENERIC_GETTIMEOFDAY 931 + select GENERIC_VDSO_DATA_STORE 931 932 help 932 933 Place in the process address space an ELF shared object 933 934 providing fast implementations of gettimeofday and
+2 -2
arch/arm/vdso/vdso.lds.S
··· 11 11 */ 12 12 13 13 #include <linux/const.h> 14 - #include <asm/asm-offsets.h> 15 14 #include <asm/page.h> 16 15 #include <asm/vdso.h> 16 + #include <vdso/datapage.h> 17 17 18 18 OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 19 19 OUTPUT_ARCH(arm) 20 20 21 21 SECTIONS 22 22 { 23 - PROVIDE(_vdso_data = . - VDSO_DATA_SIZE); 23 + VDSO_VVAR_SYMS 24 24 25 25 . = SIZEOF_HEADERS; 26 26