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

dfltcc_inflate.c (4477B)


      1// SPDX-License-Identifier: Zlib
      2
      3#include "../zlib_inflate/inflate.h"
      4#include "dfltcc_util.h"
      5#include "dfltcc.h"
      6#include <asm/setup.h>
      7#include <linux/export.h>
      8#include <linux/zutil.h>
      9
     10/*
     11 * Expand.
     12 */
     13int dfltcc_can_inflate(
     14    z_streamp strm
     15)
     16{
     17    struct inflate_state *state = (struct inflate_state *)strm->state;
     18    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
     19
     20    /* Check for kernel dfltcc command line parameter */
     21    if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||
     22            zlib_dfltcc_support == ZLIB_DFLTCC_DEFLATE_ONLY)
     23        return 0;
     24
     25    /* Unsupported compression settings */
     26    if (state->wbits != HB_BITS)
     27        return 0;
     28
     29    /* Unsupported hardware */
     30    return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) &&
     31               is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
     32}
     33EXPORT_SYMBOL(dfltcc_can_inflate);
     34
     35static int dfltcc_was_inflate_used(
     36    z_streamp strm
     37)
     38{
     39    struct inflate_state *state = (struct inflate_state *)strm->state;
     40    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
     41
     42    return !param->nt;
     43}
     44
     45static int dfltcc_inflate_disable(
     46    z_streamp strm
     47)
     48{
     49    struct inflate_state *state = (struct inflate_state *)strm->state;
     50    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
     51
     52    if (!dfltcc_can_inflate(strm))
     53        return 0;
     54    if (dfltcc_was_inflate_used(strm))
     55        /* DFLTCC has already decompressed some data. Since there is not
     56         * enough information to resume decompression in software, the call
     57         * must fail.
     58         */
     59        return 1;
     60    /* DFLTCC was not used yet - decompress in software */
     61    memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
     62    return 0;
     63}
     64
     65static dfltcc_cc dfltcc_xpnd(
     66    z_streamp strm
     67)
     68{
     69    struct inflate_state *state = (struct inflate_state *)strm->state;
     70    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
     71    size_t avail_in = strm->avail_in;
     72    size_t avail_out = strm->avail_out;
     73    dfltcc_cc cc;
     74
     75    cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR,
     76                param, &strm->next_out, &avail_out,
     77                &strm->next_in, &avail_in, state->window);
     78    strm->avail_in = avail_in;
     79    strm->avail_out = avail_out;
     80    return cc;
     81}
     82
     83dfltcc_inflate_action dfltcc_inflate(
     84    z_streamp strm,
     85    int flush,
     86    int *ret
     87)
     88{
     89    struct inflate_state *state = (struct inflate_state *)strm->state;
     90    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
     91    struct dfltcc_param_v0 *param = &dfltcc_state->param;
     92    dfltcc_cc cc;
     93
     94    if (flush == Z_BLOCK) {
     95        /* DFLTCC does not support stopping on block boundaries */
     96        if (dfltcc_inflate_disable(strm)) {
     97            *ret = Z_STREAM_ERROR;
     98            return DFLTCC_INFLATE_BREAK;
     99        } else
    100            return DFLTCC_INFLATE_SOFTWARE;
    101    }
    102
    103    if (state->last) {
    104        if (state->bits != 0) {
    105            strm->next_in++;
    106            strm->avail_in--;
    107            state->bits = 0;
    108        }
    109        state->mode = CHECK;
    110        return DFLTCC_INFLATE_CONTINUE;
    111    }
    112
    113    if (strm->avail_in == 0 && !param->cf)
    114        return DFLTCC_INFLATE_BREAK;
    115
    116    if (!state->window || state->wsize == 0) {
    117        state->mode = MEM;
    118        return DFLTCC_INFLATE_CONTINUE;
    119    }
    120
    121    /* Translate stream to parameter block */
    122    param->cvt = CVT_ADLER32;
    123    param->sbb = state->bits;
    124    param->hl = state->whave; /* Software and hardware history formats match */
    125    param->ho = (state->write - state->whave) & ((1 << HB_BITS) - 1);
    126    if (param->hl)
    127        param->nt = 0; /* Honor history for the first block */
    128    param->cv = state->check;
    129
    130    /* Inflate */
    131    do {
    132        cc = dfltcc_xpnd(strm);
    133    } while (cc == DFLTCC_CC_AGAIN);
    134
    135    /* Translate parameter block to stream */
    136    strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
    137    state->last = cc == DFLTCC_CC_OK;
    138    state->bits = param->sbb;
    139    state->whave = param->hl;
    140    state->write = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
    141    state->check = param->cv;
    142    if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
    143        /* Report an error if stream is corrupted */
    144        state->mode = BAD;
    145        return DFLTCC_INFLATE_CONTINUE;
    146    }
    147    state->mode = TYPEDO;
    148    /* Break if operands are exhausted, otherwise continue looping */
    149    return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?
    150        DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;
    151}
    152EXPORT_SYMBOL(dfltcc_inflate);