cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bvec.h (6328B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * bvec iterator
      4 *
      5 * Copyright (C) 2001 Ming Lei <ming.lei@canonical.com>
      6 */
      7#ifndef __LINUX_BVEC_H
      8#define __LINUX_BVEC_H
      9
     10#include <linux/highmem.h>
     11#include <linux/bug.h>
     12#include <linux/errno.h>
     13#include <linux/limits.h>
     14#include <linux/minmax.h>
     15#include <linux/mm.h>
     16#include <linux/types.h>
     17
     18struct page;
     19
     20/**
     21 * struct bio_vec - a contiguous range of physical memory addresses
     22 * @bv_page:   First page associated with the address range.
     23 * @bv_len:    Number of bytes in the address range.
     24 * @bv_offset: Start of the address range relative to the start of @bv_page.
     25 *
     26 * The following holds for a bvec if n * PAGE_SIZE < bv_offset + bv_len:
     27 *
     28 *   nth_page(@bv_page, n) == @bv_page + n
     29 *
     30 * This holds because page_is_mergeable() checks the above property.
     31 */
     32struct bio_vec {
     33	struct page	*bv_page;
     34	unsigned int	bv_len;
     35	unsigned int	bv_offset;
     36};
     37
     38struct bvec_iter {
     39	sector_t		bi_sector;	/* device address in 512 byte
     40						   sectors */
     41	unsigned int		bi_size;	/* residual I/O count */
     42
     43	unsigned int		bi_idx;		/* current index into bvl_vec */
     44
     45	unsigned int            bi_bvec_done;	/* number of bytes completed in
     46						   current bvec */
     47} __packed;
     48
     49struct bvec_iter_all {
     50	struct bio_vec	bv;
     51	int		idx;
     52	unsigned	done;
     53};
     54
     55/*
     56 * various member access, note that bio_data should of course not be used
     57 * on highmem page vectors
     58 */
     59#define __bvec_iter_bvec(bvec, iter)	(&(bvec)[(iter).bi_idx])
     60
     61/* multi-page (mp_bvec) helpers */
     62#define mp_bvec_iter_page(bvec, iter)				\
     63	(__bvec_iter_bvec((bvec), (iter))->bv_page)
     64
     65#define mp_bvec_iter_len(bvec, iter)				\
     66	min((iter).bi_size,					\
     67	    __bvec_iter_bvec((bvec), (iter))->bv_len - (iter).bi_bvec_done)
     68
     69#define mp_bvec_iter_offset(bvec, iter)				\
     70	(__bvec_iter_bvec((bvec), (iter))->bv_offset + (iter).bi_bvec_done)
     71
     72#define mp_bvec_iter_page_idx(bvec, iter)			\
     73	(mp_bvec_iter_offset((bvec), (iter)) / PAGE_SIZE)
     74
     75#define mp_bvec_iter_bvec(bvec, iter)				\
     76((struct bio_vec) {						\
     77	.bv_page	= mp_bvec_iter_page((bvec), (iter)),	\
     78	.bv_len		= mp_bvec_iter_len((bvec), (iter)),	\
     79	.bv_offset	= mp_bvec_iter_offset((bvec), (iter)),	\
     80})
     81
     82/* For building single-page bvec in flight */
     83 #define bvec_iter_offset(bvec, iter)				\
     84	(mp_bvec_iter_offset((bvec), (iter)) % PAGE_SIZE)
     85
     86#define bvec_iter_len(bvec, iter)				\
     87	min_t(unsigned, mp_bvec_iter_len((bvec), (iter)),		\
     88	      PAGE_SIZE - bvec_iter_offset((bvec), (iter)))
     89
     90#define bvec_iter_page(bvec, iter)				\
     91	(mp_bvec_iter_page((bvec), (iter)) +			\
     92	 mp_bvec_iter_page_idx((bvec), (iter)))
     93
     94#define bvec_iter_bvec(bvec, iter)				\
     95((struct bio_vec) {						\
     96	.bv_page	= bvec_iter_page((bvec), (iter)),	\
     97	.bv_len		= bvec_iter_len((bvec), (iter)),	\
     98	.bv_offset	= bvec_iter_offset((bvec), (iter)),	\
     99})
    100
    101static inline bool bvec_iter_advance(const struct bio_vec *bv,
    102		struct bvec_iter *iter, unsigned bytes)
    103{
    104	unsigned int idx = iter->bi_idx;
    105
    106	if (WARN_ONCE(bytes > iter->bi_size,
    107		     "Attempted to advance past end of bvec iter\n")) {
    108		iter->bi_size = 0;
    109		return false;
    110	}
    111
    112	iter->bi_size -= bytes;
    113	bytes += iter->bi_bvec_done;
    114
    115	while (bytes && bytes >= bv[idx].bv_len) {
    116		bytes -= bv[idx].bv_len;
    117		idx++;
    118	}
    119
    120	iter->bi_idx = idx;
    121	iter->bi_bvec_done = bytes;
    122	return true;
    123}
    124
    125/*
    126 * A simpler version of bvec_iter_advance(), @bytes should not span
    127 * across multiple bvec entries, i.e. bytes <= bv[i->bi_idx].bv_len
    128 */
    129static inline void bvec_iter_advance_single(const struct bio_vec *bv,
    130				struct bvec_iter *iter, unsigned int bytes)
    131{
    132	unsigned int done = iter->bi_bvec_done + bytes;
    133
    134	if (done == bv[iter->bi_idx].bv_len) {
    135		done = 0;
    136		iter->bi_idx++;
    137	}
    138	iter->bi_bvec_done = done;
    139	iter->bi_size -= bytes;
    140}
    141
    142#define for_each_bvec(bvl, bio_vec, iter, start)			\
    143	for (iter = (start);						\
    144	     (iter).bi_size &&						\
    145		((bvl = bvec_iter_bvec((bio_vec), (iter))), 1);	\
    146	     bvec_iter_advance_single((bio_vec), &(iter), (bvl).bv_len))
    147
    148/* for iterating one bio from start to end */
    149#define BVEC_ITER_ALL_INIT (struct bvec_iter)				\
    150{									\
    151	.bi_sector	= 0,						\
    152	.bi_size	= UINT_MAX,					\
    153	.bi_idx		= 0,						\
    154	.bi_bvec_done	= 0,						\
    155}
    156
    157static inline struct bio_vec *bvec_init_iter_all(struct bvec_iter_all *iter_all)
    158{
    159	iter_all->done = 0;
    160	iter_all->idx = 0;
    161
    162	return &iter_all->bv;
    163}
    164
    165static inline void bvec_advance(const struct bio_vec *bvec,
    166				struct bvec_iter_all *iter_all)
    167{
    168	struct bio_vec *bv = &iter_all->bv;
    169
    170	if (iter_all->done) {
    171		bv->bv_page++;
    172		bv->bv_offset = 0;
    173	} else {
    174		bv->bv_page = bvec->bv_page + (bvec->bv_offset >> PAGE_SHIFT);
    175		bv->bv_offset = bvec->bv_offset & ~PAGE_MASK;
    176	}
    177	bv->bv_len = min_t(unsigned int, PAGE_SIZE - bv->bv_offset,
    178			   bvec->bv_len - iter_all->done);
    179	iter_all->done += bv->bv_len;
    180
    181	if (iter_all->done == bvec->bv_len) {
    182		iter_all->idx++;
    183		iter_all->done = 0;
    184	}
    185}
    186
    187/**
    188 * bvec_kmap_local - map a bvec into the kernel virtual address space
    189 * @bvec: bvec to map
    190 *
    191 * Must be called on single-page bvecs only.  Call kunmap_local on the returned
    192 * address to unmap.
    193 */
    194static inline void *bvec_kmap_local(struct bio_vec *bvec)
    195{
    196	return kmap_local_page(bvec->bv_page) + bvec->bv_offset;
    197}
    198
    199/**
    200 * memcpy_from_bvec - copy data from a bvec
    201 * @bvec: bvec to copy from
    202 *
    203 * Must be called on single-page bvecs only.
    204 */
    205static inline void memcpy_from_bvec(char *to, struct bio_vec *bvec)
    206{
    207	memcpy_from_page(to, bvec->bv_page, bvec->bv_offset, bvec->bv_len);
    208}
    209
    210/**
    211 * memcpy_to_bvec - copy data to a bvec
    212 * @bvec: bvec to copy to
    213 *
    214 * Must be called on single-page bvecs only.
    215 */
    216static inline void memcpy_to_bvec(struct bio_vec *bvec, const char *from)
    217{
    218	memcpy_to_page(bvec->bv_page, bvec->bv_offset, from, bvec->bv_len);
    219}
    220
    221/**
    222 * memzero_bvec - zero all data in a bvec
    223 * @bvec: bvec to zero
    224 *
    225 * Must be called on single-page bvecs only.
    226 */
    227static inline void memzero_bvec(struct bio_vec *bvec)
    228{
    229	memzero_page(bvec->bv_page, bvec->bv_offset, bvec->bv_len);
    230}
    231
    232/**
    233 * bvec_virt - return the virtual address for a bvec
    234 * @bvec: bvec to return the virtual address for
    235 *
    236 * Note: the caller must ensure that @bvec->bv_page is not a highmem page.
    237 */
    238static inline void *bvec_virt(struct bio_vec *bvec)
    239{
    240	WARN_ON_ONCE(PageHighMem(bvec->bv_page));
    241	return page_address(bvec->bv_page) + bvec->bv_offset;
    242}
    243
    244#endif /* __LINUX_BVEC_H */