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

page_actor.c (2545B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2013
      4 * Phillip Lougher <phillip@squashfs.org.uk>
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/slab.h>
      9#include <linux/pagemap.h>
     10#include "page_actor.h"
     11
     12/*
     13 * This file contains implementations of page_actor for decompressing into
     14 * an intermediate buffer, and for decompressing directly into the
     15 * page cache.
     16 *
     17 * Calling code should avoid sleeping between calls to squashfs_first_page()
     18 * and squashfs_finish_page().
     19 */
     20
     21/* Implementation of page_actor for decompressing into intermediate buffer */
     22static void *cache_first_page(struct squashfs_page_actor *actor)
     23{
     24	actor->next_page = 1;
     25	return actor->buffer[0];
     26}
     27
     28static void *cache_next_page(struct squashfs_page_actor *actor)
     29{
     30	if (actor->next_page == actor->pages)
     31		return NULL;
     32
     33	return actor->buffer[actor->next_page++];
     34}
     35
     36static void cache_finish_page(struct squashfs_page_actor *actor)
     37{
     38	/* empty */
     39}
     40
     41struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
     42	int pages, int length)
     43{
     44	struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
     45
     46	if (actor == NULL)
     47		return NULL;
     48
     49	actor->length = length ? : pages * PAGE_SIZE;
     50	actor->buffer = buffer;
     51	actor->pages = pages;
     52	actor->next_page = 0;
     53	actor->squashfs_first_page = cache_first_page;
     54	actor->squashfs_next_page = cache_next_page;
     55	actor->squashfs_finish_page = cache_finish_page;
     56	return actor;
     57}
     58
     59/* Implementation of page_actor for decompressing directly into page cache. */
     60static void *direct_first_page(struct squashfs_page_actor *actor)
     61{
     62	actor->next_page = 1;
     63	return actor->pageaddr = kmap_atomic(actor->page[0]);
     64}
     65
     66static void *direct_next_page(struct squashfs_page_actor *actor)
     67{
     68	if (actor->pageaddr)
     69		kunmap_atomic(actor->pageaddr);
     70
     71	return actor->pageaddr = actor->next_page == actor->pages ? NULL :
     72		kmap_atomic(actor->page[actor->next_page++]);
     73}
     74
     75static void direct_finish_page(struct squashfs_page_actor *actor)
     76{
     77	if (actor->pageaddr)
     78		kunmap_atomic(actor->pageaddr);
     79}
     80
     81struct squashfs_page_actor *squashfs_page_actor_init_special(struct page **page,
     82	int pages, int length)
     83{
     84	struct squashfs_page_actor *actor = kmalloc(sizeof(*actor), GFP_KERNEL);
     85
     86	if (actor == NULL)
     87		return NULL;
     88
     89	actor->length = length ? : pages * PAGE_SIZE;
     90	actor->page = page;
     91	actor->pages = pages;
     92	actor->next_page = 0;
     93	actor->pageaddr = NULL;
     94	actor->squashfs_first_page = direct_first_page;
     95	actor->squashfs_next_page = direct_next_page;
     96	actor->squashfs_finish_page = direct_finish_page;
     97	return actor;
     98}