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.

MIPS: 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-13-13a4669dfc8c@linutronix.de

authored by

Thomas Weißschuh and committed by
Thomas Gleixner
69896119 9bf39a65

+38 -57
+1
arch/mips/Kconfig
··· 51 51 select GENERIC_SMP_IDLE_THREAD 52 52 select GENERIC_IDLE_POLL_SETUP 53 53 select GENERIC_TIME_VSYSCALL 54 + select GENERIC_VDSO_DATA_STORE 54 55 select GUP_GET_PXX_LOW_HIGH if CPU_MIPS32 && PHYS_ADDR_T_64BIT 55 56 select HAS_IOPORT if !NO_IOPORT_MAP || ISA 56 57 select HAVE_ARCH_COMPILER_H
+5 -4
arch/mips/include/asm/vdso/gettimeofday.h
··· 167 167 168 168 #ifdef CONFIG_CLKSRC_MIPS_GIC 169 169 170 - static __always_inline u64 read_gic_count(const struct vdso_data *data) 170 + static __always_inline u64 read_gic_count(const struct vdso_time_data *data) 171 171 { 172 172 void __iomem *gic = get_gic(data); 173 173 u32 hi, hi2, lo; ··· 184 184 #endif 185 185 186 186 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, 187 - const struct vdso_data *vd) 187 + const struct vdso_time_data *vd) 188 188 { 189 189 #ifdef CONFIG_CSRC_R4K 190 190 if (clock_mode == VDSO_CLOCKMODE_R4K) ··· 209 209 } 210 210 #define __arch_vdso_hres_capable mips_vdso_hres_capable 211 211 212 - static __always_inline const struct vdso_data *__arch_get_vdso_data(void) 212 + static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(void) 213 213 { 214 - return get_vdso_data(); 214 + return get_vdso_time_data(); 215 215 } 216 + #define __arch_get_vdso_u_time_data __arch_get_vdso_u_time_data 216 217 217 218 #endif /* !__ASSEMBLY__ */ 218 219
+8 -11
arch/mips/include/asm/vdso/vdso.h
··· 5 5 */ 6 6 7 7 #include <asm/sgidefs.h> 8 + #include <vdso/page.h> 9 + 10 + #define __VDSO_PAGES 4 8 11 9 12 #ifndef __ASSEMBLY__ 10 13 11 14 #include <asm/asm.h> 12 - #include <asm/page.h> 13 15 #include <asm/vdso.h> 14 16 15 - static inline unsigned long get_vdso_base(void) 17 + static inline const struct vdso_time_data *get_vdso_time_data(void) 16 18 { 17 - unsigned long addr; 19 + const struct vdso_time_data *addr; 18 20 19 21 /* 20 22 * We can't use cpu_has_mips_r6 since it needs the cpu_data[] ··· 29 27 * We can't use addiupc because there is no label-label 30 28 * support for the addiupc reloc 31 29 */ 32 - __asm__("lapc %0, _start \n" 30 + __asm__("lapc %0, vdso_u_time_data \n" 33 31 : "=r" (addr) : :); 34 32 #else 35 33 /* ··· 48 46 " .set noreorder \n" 49 47 " bal 1f \n" 50 48 " nop \n" 51 - " .word _start - . \n" 49 + " .word vdso_u_time_data - . \n" 52 50 "1: lw %0, 0($31) \n" 53 51 " " STR(PTR_ADDU) " %0, $31, %0 \n" 54 52 " .set pop \n" ··· 60 58 return addr; 61 59 } 62 60 63 - static inline const struct vdso_data *get_vdso_data(void) 64 - { 65 - return (const struct vdso_data *)(get_vdso_base() - PAGE_SIZE); 66 - } 67 - 68 61 #ifdef CONFIG_CLKSRC_MIPS_GIC 69 62 70 - static inline void __iomem *get_gic(const struct vdso_data *data) 63 + static inline void __iomem *get_gic(const struct vdso_time_data *data) 71 64 { 72 65 return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE; 73 66 }
+2 -12
arch/mips/include/asm/vdso/vsyscall.h
··· 2 2 #ifndef __ASM_VDSO_VSYSCALL_H 3 3 #define __ASM_VDSO_VSYSCALL_H 4 4 5 + #include <asm/page.h> 6 + 5 7 #ifndef __ASSEMBLY__ 6 8 7 9 #include <vdso/datapage.h> 8 - 9 - extern struct vdso_data *vdso_data; 10 - 11 - /* 12 - * Update the vDSO data page to keep in sync with kernel timekeeping. 13 - */ 14 - static __always_inline 15 - struct vdso_data *__mips_get_k_vdso_data(void) 16 - { 17 - return vdso_data; 18 - } 19 - #define __arch_get_k_vdso_data __mips_get_k_vdso_data 20 10 21 11 /* The asm-generic header needs to be included after the definitions above */ 22 12 #include <asm-generic/vdso/vsyscall.h>
+18 -29
arch/mips/kernel/vdso.c
··· 15 15 #include <linux/random.h> 16 16 #include <linux/sched.h> 17 17 #include <linux/slab.h> 18 + #include <linux/vdso_datastore.h> 18 19 19 20 #include <asm/abi.h> 20 21 #include <asm/mips-cps.h> ··· 24 23 #include <vdso/helpers.h> 25 24 #include <vdso/vsyscall.h> 26 25 27 - /* Kernel-provided data used by the VDSO. */ 28 - static union vdso_data_store mips_vdso_data __page_aligned_data; 29 - struct vdso_data *vdso_data = mips_vdso_data.data; 30 - 31 - /* 32 - * Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as 33 - * what we map and where within the area they are mapped is determined at 34 - * runtime. 35 - */ 36 - static struct page *no_pages[] = { NULL }; 37 - static struct vm_special_mapping vdso_vvar_mapping = { 38 - .name = "[vvar]", 39 - .pages = no_pages, 40 - }; 26 + static_assert(VDSO_NR_PAGES == __VDSO_PAGES); 41 27 42 28 static void __init init_vdso_image(struct mips_vdso_image *image) 43 29 { ··· 78 90 { 79 91 struct mips_vdso_image *image = current->thread.abi->vdso; 80 92 struct mm_struct *mm = current->mm; 81 - unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr, gic_pfn, gic_base; 93 + unsigned long gic_size, size, base, data_addr, vdso_addr, gic_pfn, gic_base; 82 94 struct vm_area_struct *vma; 83 95 int ret; 84 96 ··· 107 119 * the counter registers at the start. 108 120 */ 109 121 gic_size = mips_gic_present() ? PAGE_SIZE : 0; 110 - vvar_size = gic_size + PAGE_SIZE; 111 - size = vvar_size + image->size; 122 + size = gic_size + VDSO_NR_PAGES * PAGE_SIZE + image->size; 112 123 113 124 /* 114 125 * Find a region that's large enough for us to perform the ··· 130 143 */ 131 144 if (cpu_has_dc_aliases) { 132 145 base = __ALIGN_MASK(base, shm_align_mask); 133 - base += ((unsigned long)vdso_data - gic_size) & shm_align_mask; 146 + base += ((unsigned long)vdso_k_time_data - gic_size) & shm_align_mask; 134 147 } 135 148 136 149 data_addr = base + gic_size; 137 - vdso_addr = data_addr + PAGE_SIZE; 150 + vdso_addr = data_addr + VDSO_NR_PAGES * PAGE_SIZE; 138 151 139 - vma = _install_special_mapping(mm, base, vvar_size, 140 - VM_READ | VM_MAYREAD, 141 - &vdso_vvar_mapping); 152 + vma = vdso_install_vvar_mapping(mm, data_addr); 142 153 if (IS_ERR(vma)) { 143 154 ret = PTR_ERR(vma); 144 155 goto out; ··· 146 161 if (gic_size) { 147 162 gic_base = (unsigned long)mips_gic_base + MIPS_GIC_USER_OFS; 148 163 gic_pfn = PFN_DOWN(__pa(gic_base)); 164 + static const struct vm_special_mapping gic_mapping = { 165 + .name = "[gic]", 166 + .pages = (struct page **) { NULL }, 167 + }; 168 + 169 + vma = _install_special_mapping(mm, base, gic_size, VM_READ | VM_MAYREAD, 170 + &gic_mapping); 171 + if (IS_ERR(vma)) { 172 + ret = PTR_ERR(vma); 173 + goto out; 174 + } 149 175 150 176 ret = io_remap_pfn_range(vma, base, gic_pfn, gic_size, 151 177 pgprot_noncached(vma->vm_page_prot)); 152 178 if (ret) 153 179 goto out; 154 180 } 155 - 156 - /* Map data page. */ 157 - ret = remap_pfn_range(vma, data_addr, 158 - virt_to_phys(vdso_data) >> PAGE_SHIFT, 159 - PAGE_SIZE, vma->vm_page_prot); 160 - if (ret) 161 - goto out; 162 181 163 182 /* Map VDSO image. */ 164 183 vma = _install_special_mapping(mm, vdso_addr, image->size,
+4 -1
arch/mips/vdso/vdso.lds.S
··· 5 5 */ 6 6 7 7 #include <asm/sgidefs.h> 8 + #include <asm/vdso/vdso.h> 9 + #include <vdso/datapage.h> 8 10 9 11 #if _MIPS_SIM == _MIPS_SIM_ABI64 10 12 OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips") ··· 20 18 21 19 SECTIONS 22 20 { 23 - PROVIDE(_start = .); 21 + VDSO_VVAR_SYMS 22 + 24 23 . = SIZEOF_HEADERS; 25 24 26 25 /*