From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 81C7E2FDC34; Fri, 15 Aug 2025 10:41:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755254515; cv=none; b=TNpaok6pxsKdvlqEU9QTnvkjB+XxS9aQ5V0tuKe+5AQZnZTYd9FLcwziUMh3j6xY0Nw94z6Um6tFec+i04cbvUhojrKwHOje+nCNQCMZLRQrjKtJtpM1LNJIig6c9+p2VN6X5Ka2WMVK5HafHrx/ykgmkN76fcLJ6IqgvTefBxg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755254515; c=relaxed/simple; bh=0/g2GsyjS8KJIMqWUa/EP+pQi3Fle5PXvW2vOi9eawQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gFhoGbRDYfY5DVPDkDoMUsKf/s55PWvKLPqftfext+yv9iu6MMSz4f/nzXlCyk0vzPuiY6BL7WBGqn/qxJLPv9pWeKI1qt7SFV3YARq+EagNniPL9BWym3IiDlhklBoyO6KUeF03KKopj1JWu7w7NAjei40+HEvdSiIX2//lX6E= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=CRHVX62T; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=/SP0A1RH; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="CRHVX62T"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="/SP0A1RH" From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1755254511; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XU1YN5GY1NF9dXOEw6O1SSJX5jgdbpTOc/qjXs3cbg4=; b=CRHVX62Tsdqkcl31rrjNJRTZztqvk1EjVDLeAlPVK/0CU8AJjh0mi7qhWuW3HI8bmuErqR SSWzZTCzisCQXKzv/GlnAZ0NE8uqk055nO2rJeibnqpif32ta1ctNHzF0wIBAxyQbIUAZs lrYF22Wdn4VZBgNJIsy2rt1THWl53ydH7DSEkbl6TgB7tN9dtpOg4fuGHIxIJEaAiBNoH6 Q4t7Pm5svU+P/cvmBFyxNqCswSBBjzE0QOZgMGnFH3HzkBM9l7bv03f5QvsrmhBbDnRwDm 7oxYnRURdcMjlKg3cNXO7C29YJT/DH9MA5tEE7IBMhxmaxuJL44a1ZRvR2WLuQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1755254511; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XU1YN5GY1NF9dXOEw6O1SSJX5jgdbpTOc/qjXs3cbg4=; b=/SP0A1RHF/FV7SOLLzdWZ/y937QRn8r+//oIae3cCnDqasmFTS9oW14asrPyCP2vOOc7PJ v5w7ZlgiNvedjpAA== Date: Fri, 15 Aug 2025 12:41:13 +0200 Subject: [PATCH v2 04/13] sparc64: vdso: Replace code patching with runtime conditional Precedence: bulk X-Mailing-List: sparclinux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Message-Id: <20250815-vdso-sparc64-generic-2-v2-4-b5ff80672347@linutronix.de> References: <20250815-vdso-sparc64-generic-2-v2-0-b5ff80672347@linutronix.de> In-Reply-To: <20250815-vdso-sparc64-generic-2-v2-0-b5ff80672347@linutronix.de> To: Andy Lutomirski , Thomas Gleixner , Vincenzo Frascino , Arnd Bergmann , "David S. Miller" , Andreas Larsson , Nagarathnam Muthusamy , Nick Alcock , John Stultz , Stephen Boyd , John Paul Adrian Glaubitz Cc: linux-kernel@vger.kernel.org, sparclinux@vger.kernel.org, =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Developer-Signature: v=1; a=ed25519-sha256; t=1755254507; l=11901; i=thomas.weissschuh@linutronix.de; s=20240209; h=from:subject:message-id; bh=0/g2GsyjS8KJIMqWUa/EP+pQi3Fle5PXvW2vOi9eawQ=; b=TmPxQRla263hs1pXiP2pRUeMTloNUXslVyVngghGLJCJUi9xxocZk7096I/zGKichH5fcJw+u c2Sa9hyvgacARRFsd8j65iyLMdHElGmkKUg2ovAWLXcDcoxti6MfroU X-Developer-Key: i=thomas.weissschuh@linutronix.de; a=ed25519; pk=pfvxvpFUDJV2h2nY0FidLUml22uGLSjByFbM6aqQQws= The patching logic is unnecessarily complicated and stands in the way of the adoption of the generic vDSO framework. Replace it by a simple runtime switch, similar to other architectures. Suggested-by: Thomas Gleixner Link: https://lore.kernel.org/lkml/87ecu9tfhw.ffs@tglx/ Signed-off-by: Thomas Weißschuh --- arch/sparc/vdso/vclock_gettime.c | 112 +------------------- arch/sparc/vdso/vdso.lds.S | 2 - arch/sparc/vdso/vdso32/vdso32.lds.S | 2 - arch/sparc/vdso/vma.c | 204 ------------------------------------ 4 files changed, 4 insertions(+), 316 deletions(-) diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c index 79607804ea1b0f321215a9c4b5ead1edeb912e64..643608bffe13d904c5f77edd585b2e58277491fb 100644 --- a/arch/sparc/vdso/vclock_gettime.c +++ b/arch/sparc/vdso/vclock_gettime.c @@ -148,17 +148,11 @@ notrace static __always_inline u64 vgetsns(struct vvar_data *vvar) u64 v; u64 cycles; - cycles = vread_tick(); - v = (cycles - vvar->clock.cycle_last) & vvar->clock.mask; - return v * vvar->clock.mult; -} - -notrace static __always_inline u64 vgetsns_stick(struct vvar_data *vvar) -{ - u64 v; - u64 cycles; + if (likely(vvar->vclock_mode == VCLOCK_STICK)) + cycles = vread_tick_stick(); + else + cycles = vread_tick(); - cycles = vread_tick_stick(); v = (cycles - vvar->clock.cycle_last) & vvar->clock.mask; return v * vvar->clock.mult; } @@ -183,26 +177,6 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar, return 0; } -notrace static __always_inline int do_realtime_stick(struct vvar_data *vvar, - struct __kernel_old_timespec *ts) -{ - unsigned long seq; - u64 ns; - - do { - seq = vvar_read_begin(vvar); - ts->tv_sec = vvar->wall_time_sec; - ns = vvar->wall_time_snsec; - ns += vgetsns_stick(vvar); - ns = __shr64(ns, vvar->clock.shift); - } while (unlikely(vvar_read_retry(vvar, seq))); - - ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); - ts->tv_nsec = ns; - - return 0; -} - notrace static __always_inline int do_monotonic(struct vvar_data *vvar, struct __kernel_old_timespec *ts) { @@ -223,26 +197,6 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar, return 0; } -notrace static __always_inline int do_monotonic_stick(struct vvar_data *vvar, - struct __kernel_old_timespec *ts) -{ - unsigned long seq; - u64 ns; - - do { - seq = vvar_read_begin(vvar); - ts->tv_sec = vvar->monotonic_time_sec; - ns = vvar->monotonic_time_snsec; - ns += vgetsns_stick(vvar); - ns = __shr64(ns, vvar->clock.shift); - } while (unlikely(vvar_read_retry(vvar, seq))); - - ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); - ts->tv_nsec = ns; - - return 0; -} - notrace static int do_realtime_coarse(struct vvar_data *vvar, struct __kernel_old_timespec *ts) { @@ -298,31 +252,6 @@ int clock_gettime(clockid_t, struct __kernel_old_timespec *) __attribute__((weak, alias("__vdso_clock_gettime"))); -notrace int -__vdso_clock_gettime_stick(clockid_t clock, struct __kernel_old_timespec *ts) -{ - struct vvar_data *vvd = get_vvar_data(); - - switch (clock) { - case CLOCK_REALTIME: - if (unlikely(vvd->vclock_mode == VCLOCK_NONE)) - break; - return do_realtime_stick(vvd, ts); - case CLOCK_MONOTONIC: - if (unlikely(vvd->vclock_mode == VCLOCK_NONE)) - break; - return do_monotonic_stick(vvd, ts); - case CLOCK_REALTIME_COARSE: - return do_realtime_coarse(vvd, ts); - case CLOCK_MONOTONIC_COARSE: - return do_monotonic_coarse(vvd, ts); - } - /* - * Unknown clock ID ? Fall back to the syscall. - */ - return vdso_fallback_gettime(clock, ts); -} - notrace int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) { @@ -358,36 +287,3 @@ __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) int gettimeofday(struct __kernel_old_timeval *, struct timezone *) __attribute__((weak, alias("__vdso_gettimeofday"))); - -notrace int -__vdso_gettimeofday_stick(struct __kernel_old_timeval *tv, struct timezone *tz) -{ - struct vvar_data *vvd = get_vvar_data(); - - if (likely(vvd->vclock_mode != VCLOCK_NONE)) { - if (likely(tv != NULL)) { - union tstv_t { - struct __kernel_old_timespec ts; - struct __kernel_old_timeval tv; - } *tstv = (union tstv_t *) tv; - do_realtime_stick(vvd, &tstv->ts); - /* - * Assign before dividing to ensure that the division is - * done in the type of tv_usec, not tv_nsec. - * - * There cannot be > 1 billion usec in a second: - * do_realtime() has already distributed such overflow - * into tv_sec. So we can assign it to an int safely. - */ - tstv->tv.tv_usec = tstv->ts.tv_nsec; - tstv->tv.tv_usec /= 1000; - } - if (unlikely(tz != NULL)) { - /* Avoid memcpy. Some old compilers fail to inline it */ - tz->tz_minuteswest = vvd->tz_minuteswest; - tz->tz_dsttime = vvd->tz_dsttime; - } - return 0; - } - return vdso_fallback_gettimeofday(tv, tz); -} diff --git a/arch/sparc/vdso/vdso.lds.S b/arch/sparc/vdso/vdso.lds.S index 629ab6900df7156fc18b450dc3bbfba1bbd20e65..f3caa29a331c58175b67ea60d7ac15cd467fe5ff 100644 --- a/arch/sparc/vdso/vdso.lds.S +++ b/arch/sparc/vdso/vdso.lds.S @@ -18,10 +18,8 @@ VERSION { global: clock_gettime; __vdso_clock_gettime; - __vdso_clock_gettime_stick; gettimeofday; __vdso_gettimeofday; - __vdso_gettimeofday_stick; local: *; }; } diff --git a/arch/sparc/vdso/vdso32/vdso32.lds.S b/arch/sparc/vdso/vdso32/vdso32.lds.S index 218930fdff03d598d74a991657c109c3b15ce752..53575ee154c492f9503efdd8f995ac2a035203c7 100644 --- a/arch/sparc/vdso/vdso32/vdso32.lds.S +++ b/arch/sparc/vdso/vdso32/vdso32.lds.S @@ -17,10 +17,8 @@ VERSION { global: clock_gettime; __vdso_clock_gettime; - __vdso_clock_gettime_stick; gettimeofday; __vdso_gettimeofday; - __vdso_gettimeofday_stick; local: *; }; } diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c index bab7a59575e882d911c5d1b0903f45cec353aef0..582d84e2e5ba8932f39948bb0ca2678fc8f06a10 100644 --- a/arch/sparc/vdso/vma.c +++ b/arch/sparc/vdso/vma.c @@ -42,203 +42,6 @@ static struct vm_special_mapping vdso_mapping32 = { struct vvar_data *vvar_data; -struct vdso_elfinfo32 { - Elf32_Ehdr *hdr; - Elf32_Sym *dynsym; - unsigned long dynsymsize; - const char *dynstr; - unsigned long text; -}; - -struct vdso_elfinfo64 { - Elf64_Ehdr *hdr; - Elf64_Sym *dynsym; - unsigned long dynsymsize; - const char *dynstr; - unsigned long text; -}; - -struct vdso_elfinfo { - union { - struct vdso_elfinfo32 elf32; - struct vdso_elfinfo64 elf64; - } u; -}; - -static void *one_section64(struct vdso_elfinfo64 *e, const char *name, - unsigned long *size) -{ - const char *snames; - Elf64_Shdr *shdrs; - unsigned int i; - - shdrs = (void *)e->hdr + e->hdr->e_shoff; - snames = (void *)e->hdr + shdrs[e->hdr->e_shstrndx].sh_offset; - for (i = 1; i < e->hdr->e_shnum; i++) { - if (!strcmp(snames+shdrs[i].sh_name, name)) { - if (size) - *size = shdrs[i].sh_size; - return (void *)e->hdr + shdrs[i].sh_offset; - } - } - return NULL; -} - -static int find_sections64(const struct vdso_image *image, struct vdso_elfinfo *_e) -{ - struct vdso_elfinfo64 *e = &_e->u.elf64; - - e->hdr = image->data; - e->dynsym = one_section64(e, ".dynsym", &e->dynsymsize); - e->dynstr = one_section64(e, ".dynstr", NULL); - - if (!e->dynsym || !e->dynstr) { - pr_err("VDSO64: Missing symbol sections.\n"); - return -ENODEV; - } - return 0; -} - -static Elf64_Sym *find_sym64(const struct vdso_elfinfo64 *e, const char *name) -{ - unsigned int i; - - for (i = 0; i < (e->dynsymsize / sizeof(Elf64_Sym)); i++) { - Elf64_Sym *s = &e->dynsym[i]; - if (s->st_name == 0) - continue; - if (!strcmp(e->dynstr + s->st_name, name)) - return s; - } - return NULL; -} - -static int patchsym64(struct vdso_elfinfo *_e, const char *orig, - const char *new) -{ - struct vdso_elfinfo64 *e = &_e->u.elf64; - Elf64_Sym *osym = find_sym64(e, orig); - Elf64_Sym *nsym = find_sym64(e, new); - - if (!nsym || !osym) { - pr_err("VDSO64: Missing symbols.\n"); - return -ENODEV; - } - osym->st_value = nsym->st_value; - osym->st_size = nsym->st_size; - osym->st_info = nsym->st_info; - osym->st_other = nsym->st_other; - osym->st_shndx = nsym->st_shndx; - - return 0; -} - -static void *one_section32(struct vdso_elfinfo32 *e, const char *name, - unsigned long *size) -{ - const char *snames; - Elf32_Shdr *shdrs; - unsigned int i; - - shdrs = (void *)e->hdr + e->hdr->e_shoff; - snames = (void *)e->hdr + shdrs[e->hdr->e_shstrndx].sh_offset; - for (i = 1; i < e->hdr->e_shnum; i++) { - if (!strcmp(snames+shdrs[i].sh_name, name)) { - if (size) - *size = shdrs[i].sh_size; - return (void *)e->hdr + shdrs[i].sh_offset; - } - } - return NULL; -} - -static int find_sections32(const struct vdso_image *image, struct vdso_elfinfo *_e) -{ - struct vdso_elfinfo32 *e = &_e->u.elf32; - - e->hdr = image->data; - e->dynsym = one_section32(e, ".dynsym", &e->dynsymsize); - e->dynstr = one_section32(e, ".dynstr", NULL); - - if (!e->dynsym || !e->dynstr) { - pr_err("VDSO32: Missing symbol sections.\n"); - return -ENODEV; - } - return 0; -} - -static Elf32_Sym *find_sym32(const struct vdso_elfinfo32 *e, const char *name) -{ - unsigned int i; - - for (i = 0; i < (e->dynsymsize / sizeof(Elf32_Sym)); i++) { - Elf32_Sym *s = &e->dynsym[i]; - if (s->st_name == 0) - continue; - if (!strcmp(e->dynstr + s->st_name, name)) - return s; - } - return NULL; -} - -static int patchsym32(struct vdso_elfinfo *_e, const char *orig, - const char *new) -{ - struct vdso_elfinfo32 *e = &_e->u.elf32; - Elf32_Sym *osym = find_sym32(e, orig); - Elf32_Sym *nsym = find_sym32(e, new); - - if (!nsym || !osym) { - pr_err("VDSO32: Missing symbols.\n"); - return -ENODEV; - } - osym->st_value = nsym->st_value; - osym->st_size = nsym->st_size; - osym->st_info = nsym->st_info; - osym->st_other = nsym->st_other; - osym->st_shndx = nsym->st_shndx; - - return 0; -} - -static int find_sections(const struct vdso_image *image, struct vdso_elfinfo *e, - bool elf64) -{ - if (elf64) - return find_sections64(image, e); - else - return find_sections32(image, e); -} - -static int patch_one_symbol(struct vdso_elfinfo *e, const char *orig, - const char *new_target, bool elf64) -{ - if (elf64) - return patchsym64(e, orig, new_target); - else - return patchsym32(e, orig, new_target); -} - -static int stick_patch(const struct vdso_image *image, struct vdso_elfinfo *e, bool elf64) -{ - int err; - - err = find_sections(image, e, elf64); - if (err) - return err; - - err = patch_one_symbol(e, - "__vdso_gettimeofday", - "__vdso_gettimeofday_stick", elf64); - if (err) - return err; - - return patch_one_symbol(e, - "__vdso_clock_gettime", - "__vdso_clock_gettime_stick", elf64); - return 0; -} - /* * Allocate pages for the vdso and vvar, and copy in the vdso text from the * kernel image. @@ -250,15 +53,8 @@ static int __init init_vdso_image(const struct vdso_image *image, int cnpages = (image->size) / PAGE_SIZE; struct page *dp, **dpp = NULL; struct page *cp, **cpp = NULL; - struct vdso_elfinfo ei; int i, dnpages = 0; - if (tlb_type != spitfire) { - int err = stick_patch(image, &ei, elf64); - if (err) - return err; - } - /* * First, the vdso text. This is initialied data, an integral number of * pages long. -- 2.50.1