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

zpvec.h (3761B)


      1/* SPDX-License-Identifier: GPL-2.0-only */
      2/*
      3 * Copyright (C) 2018 HUAWEI, Inc.
      4 *             https://www.huawei.com/
      5 */
      6#ifndef __EROFS_FS_ZPVEC_H
      7#define __EROFS_FS_ZPVEC_H
      8
      9#include "tagptr.h"
     10
     11/* page type in pagevec for decompress subsystem */
     12enum z_erofs_page_type {
     13	/* including Z_EROFS_VLE_PAGE_TAIL_EXCLUSIVE */
     14	Z_EROFS_PAGE_TYPE_EXCLUSIVE,
     15
     16	Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED,
     17
     18	Z_EROFS_VLE_PAGE_TYPE_HEAD,
     19	Z_EROFS_VLE_PAGE_TYPE_MAX
     20};
     21
     22extern void __compiletime_error("Z_EROFS_PAGE_TYPE_EXCLUSIVE != 0")
     23	__bad_page_type_exclusive(void);
     24
     25/* pagevec tagged pointer */
     26typedef tagptr2_t	erofs_vtptr_t;
     27
     28/* pagevec collector */
     29struct z_erofs_pagevec_ctor {
     30	struct page *curr, *next;
     31	erofs_vtptr_t *pages;
     32
     33	unsigned int nr, index;
     34};
     35
     36static inline void z_erofs_pagevec_ctor_exit(struct z_erofs_pagevec_ctor *ctor,
     37					     bool atomic)
     38{
     39	if (!ctor->curr)
     40		return;
     41
     42	if (atomic)
     43		kunmap_atomic(ctor->pages);
     44	else
     45		kunmap(ctor->curr);
     46}
     47
     48static inline struct page *
     49z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor,
     50			       unsigned int nr)
     51{
     52	unsigned int index;
     53
     54	/* keep away from occupied pages */
     55	if (ctor->next)
     56		return ctor->next;
     57
     58	for (index = 0; index < nr; ++index) {
     59		const erofs_vtptr_t t = ctor->pages[index];
     60		const unsigned int tags = tagptr_unfold_tags(t);
     61
     62		if (tags == Z_EROFS_PAGE_TYPE_EXCLUSIVE)
     63			return tagptr_unfold_ptr(t);
     64	}
     65	DBG_BUGON(nr >= ctor->nr);
     66	return NULL;
     67}
     68
     69static inline void
     70z_erofs_pagevec_ctor_pagedown(struct z_erofs_pagevec_ctor *ctor,
     71			      bool atomic)
     72{
     73	struct page *next = z_erofs_pagevec_ctor_next_page(ctor, ctor->nr);
     74
     75	z_erofs_pagevec_ctor_exit(ctor, atomic);
     76
     77	ctor->curr = next;
     78	ctor->next = NULL;
     79	ctor->pages = atomic ?
     80		kmap_atomic(ctor->curr) : kmap(ctor->curr);
     81
     82	ctor->nr = PAGE_SIZE / sizeof(struct page *);
     83	ctor->index = 0;
     84}
     85
     86static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor,
     87					     unsigned int nr,
     88					     erofs_vtptr_t *pages,
     89					     unsigned int i)
     90{
     91	ctor->nr = nr;
     92	ctor->curr = ctor->next = NULL;
     93	ctor->pages = pages;
     94
     95	if (i >= nr) {
     96		i -= nr;
     97		z_erofs_pagevec_ctor_pagedown(ctor, false);
     98		while (i > ctor->nr) {
     99			i -= ctor->nr;
    100			z_erofs_pagevec_ctor_pagedown(ctor, false);
    101		}
    102	}
    103	ctor->next = z_erofs_pagevec_ctor_next_page(ctor, i);
    104	ctor->index = i;
    105}
    106
    107static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor,
    108					   struct page *page,
    109					   enum z_erofs_page_type type,
    110					   bool pvec_safereuse)
    111{
    112	if (!ctor->next) {
    113		/* some pages cannot be reused as pvec safely without I/O */
    114		if (type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && !pvec_safereuse)
    115			type = Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED;
    116
    117		if (type != Z_EROFS_PAGE_TYPE_EXCLUSIVE &&
    118		    ctor->index + 1 == ctor->nr)
    119			return false;
    120	}
    121
    122	if (ctor->index >= ctor->nr)
    123		z_erofs_pagevec_ctor_pagedown(ctor, false);
    124
    125	/* exclusive page type must be 0 */
    126	if (Z_EROFS_PAGE_TYPE_EXCLUSIVE != (uintptr_t)NULL)
    127		__bad_page_type_exclusive();
    128
    129	/* should remind that collector->next never equal to 1, 2 */
    130	if (type == (uintptr_t)ctor->next) {
    131		ctor->next = page;
    132	}
    133	ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, page, type);
    134	return true;
    135}
    136
    137static inline struct page *
    138z_erofs_pagevec_dequeue(struct z_erofs_pagevec_ctor *ctor,
    139			enum z_erofs_page_type *type)
    140{
    141	erofs_vtptr_t t;
    142
    143	if (ctor->index >= ctor->nr) {
    144		DBG_BUGON(!ctor->next);
    145		z_erofs_pagevec_ctor_pagedown(ctor, true);
    146	}
    147
    148	t = ctor->pages[ctor->index];
    149
    150	*type = tagptr_unfold_tags(t);
    151
    152	/* should remind that collector->next never equal to 1, 2 */
    153	if (*type == (uintptr_t)ctor->next)
    154		ctor->next = tagptr_unfold_ptr(t);
    155
    156	ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, NULL, 0);
    157	return tagptr_unfold_ptr(t);
    158}
    159#endif