linux/arch/mips/include/asm/vdso.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   2/*
   3 * Copyright (C) 2015 Imagination Technologies
   4 * Author: Alex Smith <alex.smith@imgtec.com>
   5 */
   6
   7#ifndef __ASM_VDSO_H
   8#define __ASM_VDSO_H
   9
  10#include <linux/mm_types.h>
  11
  12#include <asm/barrier.h>
  13
  14/**
  15 * struct mips_vdso_image - Details of a VDSO image.
  16 * @data: Pointer to VDSO image data (page-aligned).
  17 * @size: Size of the VDSO image data (page-aligned).
  18 * @off_sigreturn: Offset of the sigreturn() trampoline.
  19 * @off_rt_sigreturn: Offset of the rt_sigreturn() trampoline.
  20 * @mapping: Special mapping structure.
  21 *
  22 * This structure contains details of a VDSO image, including the image data
  23 * and offsets of certain symbols required by the kernel. It is generated as
  24 * part of the VDSO build process, aside from the mapping page array, which is
  25 * populated at runtime.
  26 */
  27struct mips_vdso_image {
  28        void *data;
  29        unsigned long size;
  30
  31        unsigned long off_sigreturn;
  32        unsigned long off_rt_sigreturn;
  33
  34        struct vm_special_mapping mapping;
  35};
  36
  37/*
  38 * The following structures are auto-generated as part of the build for each
  39 * ABI by genvdso, see arch/mips/vdso/Makefile.
  40 */
  41
  42extern struct mips_vdso_image vdso_image;
  43
  44#ifdef CONFIG_MIPS32_O32
  45extern struct mips_vdso_image vdso_image_o32;
  46#endif
  47
  48#ifdef CONFIG_MIPS32_N32
  49extern struct mips_vdso_image vdso_image_n32;
  50#endif
  51
  52/**
  53 * union mips_vdso_data - Data provided by the kernel for the VDSO.
  54 * @xtime_sec:          Current real time (seconds part).
  55 * @xtime_nsec:         Current real time (nanoseconds part, shifted).
  56 * @wall_to_mono_sec:   Wall-to-monotonic offset (seconds part).
  57 * @wall_to_mono_nsec:  Wall-to-monotonic offset (nanoseconds part).
  58 * @seq_count:          Counter to synchronise updates (odd = updating).
  59 * @cs_shift:           Clocksource shift value.
  60 * @clock_mode:         Clocksource to use for time functions.
  61 * @cs_mult:            Clocksource multiplier value.
  62 * @cs_cycle_last:      Clock cycle value at last update.
  63 * @cs_mask:            Clocksource mask value.
  64 * @tz_minuteswest:     Minutes west of Greenwich (from timezone).
  65 * @tz_dsttime:         Type of DST correction (from timezone).
  66 *
  67 * This structure contains data needed by functions within the VDSO. It is
  68 * populated by the kernel and mapped read-only into user memory. The time
  69 * fields are mirrors of internal data from the timekeeping infrastructure.
  70 *
  71 * Note: Care should be taken when modifying as the layout must remain the same
  72 * for both 64- and 32-bit (for 32-bit userland on 64-bit kernel).
  73 */
  74union mips_vdso_data {
  75        struct {
  76                u64 xtime_sec;
  77                u64 xtime_nsec;
  78                u64 wall_to_mono_sec;
  79                u64 wall_to_mono_nsec;
  80                u32 seq_count;
  81                u32 cs_shift;
  82                u8 clock_mode;
  83                u32 cs_mult;
  84                u64 cs_cycle_last;
  85                u64 cs_mask;
  86                s32 tz_minuteswest;
  87                s32 tz_dsttime;
  88        };
  89
  90        u8 page[PAGE_SIZE];
  91};
  92
  93static inline u32 vdso_data_read_begin(const union mips_vdso_data *data)
  94{
  95        u32 seq;
  96
  97        while (true) {
  98                seq = READ_ONCE(data->seq_count);
  99                if (likely(!(seq & 1))) {
 100                        /* Paired with smp_wmb() in vdso_data_write_*(). */
 101                        smp_rmb();
 102                        return seq;
 103                }
 104
 105                cpu_relax();
 106        }
 107}
 108
 109static inline bool vdso_data_read_retry(const union mips_vdso_data *data,
 110                                        u32 start_seq)
 111{
 112        /* Paired with smp_wmb() in vdso_data_write_*(). */
 113        smp_rmb();
 114        return unlikely(data->seq_count != start_seq);
 115}
 116
 117static inline void vdso_data_write_begin(union mips_vdso_data *data)
 118{
 119        ++data->seq_count;
 120
 121        /* Ensure sequence update is written before other data page values. */
 122        smp_wmb();
 123}
 124
 125static inline void vdso_data_write_end(union mips_vdso_data *data)
 126{
 127        /* Ensure data values are written before updating sequence again. */
 128        smp_wmb();
 129        ++data->seq_count;
 130}
 131
 132#endif /* __ASM_VDSO_H */
 133