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