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

Configure Feed

Select the types of activity you want to include in your feed.

s390/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>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Link: https://lore.kernel.org/all/20250204-vdso-store-rng-v3-12-13a4669dfc8c@linutronix.de

authored by

Thomas Weißschuh and committed by
Thomas Gleixner
9bf39a65 31e9fa2b

+17 -153
+1
arch/s390/Kconfig
··· 166 166 select GENERIC_PTDUMP 167 167 select GENERIC_SMP_IDLE_THREAD 168 168 select GENERIC_TIME_VSYSCALL 169 + select GENERIC_VDSO_DATA_STORE 169 170 select GENERIC_VDSO_TIME_NS 170 171 select GENERIC_IOREMAP if PCI 171 172 select HAVE_ALIGNED_STRUCT_PAGE
+1 -3
arch/s390/include/asm/vdso.h
··· 6 6 7 7 #ifndef __ASSEMBLY__ 8 8 9 - extern struct vdso_data *vdso_data; 10 - 11 9 int vdso_getcpu_init(void); 12 10 13 11 #endif /* __ASSEMBLY__ */ 14 12 15 - #define __VVAR_PAGES 2 13 + #define __VDSO_PAGES 4 16 14 17 15 #define VDSO_VERSION_STRING LINUX_2.6.29 18 16
-12
arch/s390/include/asm/vdso/getrandom.h
··· 23 23 return syscall3(__NR_getrandom, (long)buffer, (long)len, (long)flags); 24 24 } 25 25 26 - static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void) 27 - { 28 - /* 29 - * The RNG data is in the real VVAR data page, but if a task belongs to a time namespace 30 - * then VVAR_DATA_PAGE_OFFSET points to the namespace-specific VVAR page and VVAR_TIMENS_ 31 - * PAGE_OFFSET points to the real VVAR page. 32 - */ 33 - if (IS_ENABLED(CONFIG_TIME_NS) && _vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS) 34 - return (void *)&_vdso_rng_data + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE; 35 - return &_vdso_rng_data; 36 - } 37 - 38 26 #endif /* !__ASSEMBLY__ */ 39 27 40 28 #endif /* __ASM_VDSO_GETRANDOM_H */
+1 -14
arch/s390/include/asm/vdso/gettimeofday.h
··· 14 14 #include <linux/compiler.h> 15 15 16 16 17 - static __always_inline const struct vdso_data *__arch_get_vdso_data(void) 18 - { 19 - return _vdso_data; 20 - } 21 - 22 - static inline u64 __arch_get_hw_counter(s32 clock_mode, const struct vdso_data *vd) 17 + static inline u64 __arch_get_hw_counter(s32 clock_mode, const struct vdso_time_data *vd) 23 18 { 24 19 u64 adj, now; 25 20 ··· 43 48 { 44 49 return syscall2(__NR_clock_getres, (long)clkid, (long)ts); 45 50 } 46 - 47 - #ifdef CONFIG_TIME_NS 48 - static __always_inline 49 - const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) 50 - { 51 - return _timens_data; 52 - } 53 - #endif 54 51 55 52 #endif
-20
arch/s390/include/asm/vdso/vsyscall.h
··· 2 2 #ifndef __ASM_VDSO_VSYSCALL_H 3 3 #define __ASM_VDSO_VSYSCALL_H 4 4 5 - #define __VDSO_RND_DATA_OFFSET 768 6 - 7 5 #ifndef __ASSEMBLY__ 8 6 9 7 #include <linux/hrtimer.h> 10 8 #include <vdso/datapage.h> 11 9 #include <asm/vdso.h> 12 - 13 - enum vvar_pages { 14 - VVAR_DATA_PAGE_OFFSET, 15 - VVAR_TIMENS_PAGE_OFFSET, 16 - VVAR_NR_PAGES 17 - }; 18 - 19 - static __always_inline struct vdso_data *__s390_get_k_vdso_data(void) 20 - { 21 - return vdso_data; 22 - } 23 - #define __arch_get_k_vdso_data __s390_get_k_vdso_data 24 - 25 - static __always_inline struct vdso_rng_data *__s390_get_k_vdso_rnd_data(void) 26 - { 27 - return (void *)vdso_data + __VDSO_RND_DATA_OFFSET; 28 - } 29 - #define __arch_get_k_vdso_rng_data __s390_get_k_vdso_rnd_data 30 10 31 11 /* The asm-generic header needs to be included after the definitions above */ 32 12 #include <asm-generic/vdso/vsyscall.h>
+3 -3
arch/s390/kernel/time.c
··· 84 84 /* Initialize TOD steering parameters */ 85 85 tod_steering_end = tod_clock_base.tod; 86 86 for (cs = 0; cs < CS_BASES; cs++) 87 - vdso_data[cs].arch_data.tod_steering_end = tod_steering_end; 87 + vdso_k_time_data[cs].arch_data.tod_steering_end = tod_steering_end; 88 88 89 89 if (!test_facility(28)) 90 90 return; ··· 390 390 tod_steering_delta); 391 391 tod_steering_end = now + (abs(tod_steering_delta) << 15); 392 392 for (cs = 0; cs < CS_BASES; cs++) { 393 - vdso_data[cs].arch_data.tod_steering_end = tod_steering_end; 394 - vdso_data[cs].arch_data.tod_steering_delta = tod_steering_delta; 393 + vdso_k_time_data[cs].arch_data.tod_steering_end = tod_steering_end; 394 + vdso_k_time_data[cs].arch_data.tod_steering_delta = tod_steering_delta; 395 395 } 396 396 397 397 /* Update LPAR offset. */
+5 -92
arch/s390/kernel/vdso.c
··· 16 16 #include <linux/mm.h> 17 17 #include <linux/slab.h> 18 18 #include <linux/smp.h> 19 - #include <linux/time_namespace.h> 20 19 #include <linux/random.h> 20 + #include <linux/vdso_datastore.h> 21 21 #include <vdso/datapage.h> 22 22 #include <asm/vdso/vsyscall.h> 23 23 #include <asm/alternative.h> ··· 26 26 extern char vdso64_start[], vdso64_end[]; 27 27 extern char vdso32_start[], vdso32_end[]; 28 28 29 - static struct vm_special_mapping vvar_mapping; 30 - 31 - static union vdso_data_store vdso_data_store __page_aligned_data; 32 - 33 - struct vdso_data *vdso_data = vdso_data_store.data; 34 - 35 - #ifdef CONFIG_TIME_NS 36 - struct vdso_data *arch_get_vdso_data(void *vvar_page) 37 - { 38 - return (struct vdso_data *)(vvar_page); 39 - } 40 - 41 - /* 42 - * The VVAR page layout depends on whether a task belongs to the root or 43 - * non-root time namespace. Whenever a task changes its namespace, the VVAR 44 - * page tables are cleared and then they will be re-faulted with a 45 - * corresponding layout. 46 - * See also the comment near timens_setup_vdso_data() for details. 47 - */ 48 - int vdso_join_timens(struct task_struct *task, struct time_namespace *ns) 49 - { 50 - struct mm_struct *mm = task->mm; 51 - VMA_ITERATOR(vmi, mm, 0); 52 - struct vm_area_struct *vma; 53 - 54 - mmap_read_lock(mm); 55 - for_each_vma(vmi, vma) { 56 - if (!vma_is_special_mapping(vma, &vvar_mapping)) 57 - continue; 58 - zap_vma_pages(vma); 59 - break; 60 - } 61 - mmap_read_unlock(mm); 62 - return 0; 63 - } 64 - #endif 65 - 66 - static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, 67 - struct vm_area_struct *vma, struct vm_fault *vmf) 68 - { 69 - struct page *timens_page = find_timens_vvar_page(vma); 70 - unsigned long addr, pfn; 71 - vm_fault_t err; 72 - 73 - switch (vmf->pgoff) { 74 - case VVAR_DATA_PAGE_OFFSET: 75 - pfn = virt_to_pfn(vdso_data); 76 - if (timens_page) { 77 - /* 78 - * Fault in VVAR page too, since it will be accessed 79 - * to get clock data anyway. 80 - */ 81 - addr = vmf->address + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE; 82 - err = vmf_insert_pfn(vma, addr, pfn); 83 - if (unlikely(err & VM_FAULT_ERROR)) 84 - return err; 85 - pfn = page_to_pfn(timens_page); 86 - } 87 - break; 88 - #ifdef CONFIG_TIME_NS 89 - case VVAR_TIMENS_PAGE_OFFSET: 90 - /* 91 - * If a task belongs to a time namespace then a namespace 92 - * specific VVAR is mapped with the VVAR_DATA_PAGE_OFFSET and 93 - * the real VVAR page is mapped with the VVAR_TIMENS_PAGE_OFFSET 94 - * offset. 95 - * See also the comment near timens_setup_vdso_data(). 96 - */ 97 - if (!timens_page) 98 - return VM_FAULT_SIGBUS; 99 - pfn = virt_to_pfn(vdso_data); 100 - break; 101 - #endif /* CONFIG_TIME_NS */ 102 - default: 103 - return VM_FAULT_SIGBUS; 104 - } 105 - return vmf_insert_pfn(vma, vmf->address, pfn); 106 - } 107 - 108 29 static int vdso_mremap(const struct vm_special_mapping *sm, 109 30 struct vm_area_struct *vma) 110 31 { 111 32 current->mm->context.vdso_base = vma->vm_start; 112 33 return 0; 113 34 } 114 - 115 - static struct vm_special_mapping vvar_mapping = { 116 - .name = "[vvar]", 117 - .fault = vvar_fault, 118 - }; 119 35 120 36 static struct vm_special_mapping vdso64_mapping = { 121 37 .name = "[vdso]", ··· 58 142 struct vm_area_struct *vma; 59 143 int rc; 60 144 61 - BUILD_BUG_ON(VVAR_NR_PAGES != __VVAR_PAGES); 145 + BUILD_BUG_ON(VDSO_NR_PAGES != __VDSO_PAGES); 62 146 if (mmap_write_lock_killable(mm)) 63 147 return -EINTR; 64 148 ··· 73 157 rc = vvar_start; 74 158 if (IS_ERR_VALUE(vvar_start)) 75 159 goto out; 76 - vma = _install_special_mapping(mm, vvar_start, VVAR_NR_PAGES*PAGE_SIZE, 77 - VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP| 78 - VM_PFNMAP, 79 - &vvar_mapping); 160 + vma = vdso_install_vvar_mapping(mm, vvar_start); 80 161 rc = PTR_ERR(vma); 81 162 if (IS_ERR(vma)) 82 163 goto out; 83 - vdso_text_start = vvar_start + VVAR_NR_PAGES * PAGE_SIZE; 164 + vdso_text_start = vvar_start + VDSO_NR_PAGES * PAGE_SIZE; 84 165 /* VM_MAYWRITE for COW so gdb can set breakpoints */ 85 166 vma = _install_special_mapping(mm, vdso_text_start, vdso_text_len, 86 167 VM_READ|VM_EXEC| ··· 133 220 134 221 unsigned long vdso_size(void) 135 222 { 136 - return vdso_text_size() + VVAR_NR_PAGES * PAGE_SIZE; 223 + return vdso_text_size() + VDSO_NR_PAGES * PAGE_SIZE; 137 224 } 138 225 139 226 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+3 -4
arch/s390/kernel/vdso32/vdso32.lds.S
··· 6 6 7 7 #include <asm/page.h> 8 8 #include <asm/vdso.h> 9 + #include <vdso/datapage.h> 9 10 10 11 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") 11 12 OUTPUT_ARCH(s390:31-bit) 12 13 13 14 SECTIONS 14 15 { 15 - PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE); 16 - #ifdef CONFIG_TIME_NS 17 - PROVIDE(_timens_data = _vdso_data + PAGE_SIZE); 18 - #endif 16 + VDSO_VVAR_SYMS 17 + 19 18 . = SIZEOF_HEADERS; 20 19 21 20 .hash : { *(.hash) } :text
+3 -5
arch/s390/kernel/vdso64/vdso64.lds.S
··· 7 7 #include <asm/vdso/vsyscall.h> 8 8 #include <asm/page.h> 9 9 #include <asm/vdso.h> 10 + #include <vdso/datapage.h> 10 11 11 12 OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") 12 13 OUTPUT_ARCH(s390:64-bit) 13 14 14 15 SECTIONS 15 16 { 16 - PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE); 17 - PROVIDE(_vdso_rng_data = _vdso_data + __VDSO_RND_DATA_OFFSET); 18 - #ifdef CONFIG_TIME_NS 19 - PROVIDE(_timens_data = _vdso_data + PAGE_SIZE); 20 - #endif 17 + VDSO_VVAR_SYMS 18 + 21 19 . = SIZEOF_HEADERS; 22 20 23 21 .hash : { *(.hash) } :text