132 lines · c
1// SPDX-License-Identifier: Zlib2#ifndef DFLTCC_UTIL_H3#define DFLTCC_UTIL_H4 5#include "dfltcc.h"6#include <linux/kmsan-checks.h>7#include <linux/zutil.h>8 9/*10 * C wrapper for the DEFLATE CONVERSION CALL instruction.11 */12typedef enum {13 DFLTCC_CC_OK = 0,14 DFLTCC_CC_OP1_TOO_SHORT = 1,15 DFLTCC_CC_OP2_TOO_SHORT = 2,16 DFLTCC_CC_OP2_CORRUPT = 2,17 DFLTCC_CC_AGAIN = 3,18} dfltcc_cc;19 20#define DFLTCC_QAF 021#define DFLTCC_GDHT 122#define DFLTCC_CMPR 223#define DFLTCC_XPND 424#define HBT_CIRCULAR (1 << 7)25#define DFLTCC_FN_MASK ((1 << 7) - 1)26#define HB_BITS 1527#define HB_SIZE (1 << HB_BITS)28 29static inline dfltcc_cc dfltcc(30 int fn,31 void *param,32 Byte **op1,33 size_t *len1,34 const Byte **op2,35 size_t *len2,36 void *hist37)38{39 Byte *t2 = op1 ? *op1 : NULL;40 unsigned char *orig_t2 = t2;41 size_t t3 = len1 ? *len1 : 0;42 const Byte *t4 = op2 ? *op2 : NULL;43 size_t t5 = len2 ? *len2 : 0;44 register int r0 __asm__("r0") = fn;45 register void *r1 __asm__("r1") = param;46 register Byte *r2 __asm__("r2") = t2;47 register size_t r3 __asm__("r3") = t3;48 register const Byte *r4 __asm__("r4") = t4;49 register size_t r5 __asm__("r5") = t5;50 int cc;51 52 __asm__ volatile(53 ".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n"54 "ipm %[cc]\n"55 : [r2] "+r" (r2)56 , [r3] "+r" (r3)57 , [r4] "+r" (r4)58 , [r5] "+r" (r5)59 , [cc] "=r" (cc)60 : [r0] "r" (r0)61 , [r1] "r" (r1)62 , [hist] "r" (hist)63 : "cc", "memory");64 t2 = r2; t3 = r3; t4 = r4; t5 = r5;65 66 /*67 * Unpoison the parameter block and the output buffer.68 * This is a no-op in non-KMSAN builds.69 */70 switch (fn & DFLTCC_FN_MASK) {71 case DFLTCC_QAF:72 kmsan_unpoison_memory(param, sizeof(struct dfltcc_qaf_param));73 break;74 case DFLTCC_GDHT:75 kmsan_unpoison_memory(param, offsetof(struct dfltcc_param_v0, csb));76 break;77 case DFLTCC_CMPR:78 kmsan_unpoison_memory(param, sizeof(struct dfltcc_param_v0));79 kmsan_unpoison_memory(80 orig_t2,81 t2 - orig_t2 +82 (((struct dfltcc_param_v0 *)param)->sbb == 0 ? 0 : 1));83 break;84 case DFLTCC_XPND:85 kmsan_unpoison_memory(param, sizeof(struct dfltcc_param_v0));86 kmsan_unpoison_memory(orig_t2, t2 - orig_t2);87 break;88 }89 90 if (op1)91 *op1 = t2;92 if (len1)93 *len1 = t3;94 if (op2)95 *op2 = t4;96 if (len2)97 *len2 = t5;98 return (cc >> 28) & 3;99}100 101static inline int is_bit_set(102 const char *bits,103 int n104)105{106 return bits[n / 8] & (1 << (7 - (n % 8)));107}108 109static inline void turn_bit_off(110 char *bits,111 int n112)113{114 bits[n / 8] &= ~(1 << (7 - (n % 8)));115}116 117static inline int dfltcc_are_params_ok(118 int level,119 uInt window_bits,120 int strategy,121 uLong level_mask122)123{124 return (level_mask & (1 << level)) != 0 &&125 (window_bits == HB_BITS) &&126 (strategy == Z_DEFAULT_STRATEGY);127}128 129char *oesc_msg(char *buf, int oesc);130 131#endif /* DFLTCC_UTIL_H */132