• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stddef.h>
2 #include <stdint.h>
3 #include <stdio.h>
4 
5 #ifdef HAVE_SYS_SDT_H
6 #include <sys/sdt.h>
7 #endif
8 
9 /*
10    Tuning parameters.
11  */
12 #ifndef DFLTCC_LEVEL_MASK
13 #define DFLTCC_LEVEL_MASK 0x2
14 #endif
15 #ifndef DFLTCC_BLOCK_SIZE
16 #define DFLTCC_BLOCK_SIZE 1048576
17 #endif
18 #ifndef DFLTCC_FIRST_FHT_BLOCK_SIZE
19 #define DFLTCC_FIRST_FHT_BLOCK_SIZE 4096
20 #endif
21 #ifndef DFLTCC_DHT_MIN_SAMPLE_SIZE
22 #define DFLTCC_DHT_MIN_SAMPLE_SIZE 4096
23 #endif
24 #ifndef DFLTCC_RIBM
25 #define DFLTCC_RIBM 0
26 #endif
27 
28 /*
29    C wrapper for the DEFLATE CONVERSION CALL instruction.
30  */
31 typedef enum {
32     DFLTCC_CC_OK = 0,
33     DFLTCC_CC_OP1_TOO_SHORT = 1,
34     DFLTCC_CC_OP2_TOO_SHORT = 2,
35     DFLTCC_CC_OP2_CORRUPT = 2,
36     DFLTCC_CC_AGAIN = 3,
37 } dfltcc_cc;
38 
39 #define DFLTCC_QAF 0
40 #define DFLTCC_GDHT 1
41 #define DFLTCC_CMPR 2
42 #define DFLTCC_XPND 4
43 #define HBT_CIRCULAR (1 << 7)
44 #define HB_BITS 15
45 #define HB_SIZE (1 << HB_BITS)
46 #define DFLTCC_FACILITY 151
47 
dfltcc(int fn,void * param,unsigned char ** op1,size_t * len1,const unsigned char ** op2,size_t * len2,void * hist)48 static inline dfltcc_cc dfltcc(int fn, void *param,
49                                unsigned char **op1, size_t *len1, const unsigned char **op2, size_t *len2, void *hist) {
50     unsigned char *t2 = op1 ? *op1 : NULL;
51     size_t t3 = len1 ? *len1 : 0;
52     const unsigned char *t4 = op2 ? *op2 : NULL;
53     size_t t5 = len2 ? *len2 : 0;
54     Z_REGISTER int r0 __asm__("r0") = fn;
55     Z_REGISTER void *r1 __asm__("r1") = param;
56     Z_REGISTER unsigned char *r2 __asm__("r2") = t2;
57     Z_REGISTER size_t r3 __asm__("r3") = t3;
58     Z_REGISTER const unsigned char *r4 __asm__("r4") = t4;
59     Z_REGISTER size_t r5 __asm__("r5") = t5;
60     int cc;
61 
62     __asm__ volatile(
63 #ifdef HAVE_SYS_SDT_H
64                      STAP_PROBE_ASM(zlib, dfltcc_entry, STAP_PROBE_ASM_TEMPLATE(5))
65 #endif
66                      ".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n"
67 #ifdef HAVE_SYS_SDT_H
68                      STAP_PROBE_ASM(zlib, dfltcc_exit, STAP_PROBE_ASM_TEMPLATE(5))
69 #endif
70                      "ipm %[cc]\n"
71                      : [r2] "+r" (r2)
72                      , [r3] "+r" (r3)
73                      , [r4] "+r" (r4)
74                      , [r5] "+r" (r5)
75                      , [cc] "=r" (cc)
76                      : [r0] "r" (r0)
77                      , [r1] "r" (r1)
78                      , [hist] "r" (hist)
79 #ifdef HAVE_SYS_SDT_H
80                      , STAP_PROBE_ASM_OPERANDS(5, r2, r3, r4, r5, hist)
81 #endif
82                      : "cc", "memory");
83     t2 = r2; t3 = r3; t4 = r4; t5 = r5;
84 
85     if (op1)
86         *op1 = t2;
87     if (len1)
88         *len1 = t3;
89     if (op2)
90         *op2 = t4;
91     if (len2)
92         *len2 = t5;
93     return (cc >> 28) & 3;
94 }
95 
96 /*
97    Parameter Block for Query Available Functions.
98  */
99 #define static_assert(c, msg) __attribute__((unused)) static char static_assert_failed_ ## msg[c ? 1 : -1]
100 
101 struct dfltcc_qaf_param {
102     char fns[16];
103     char reserved1[8];
104     char fmts[2];
105     char reserved2[6];
106 };
107 
108 static_assert(sizeof(struct dfltcc_qaf_param) == 32, sizeof_struct_dfltcc_qaf_param_is_32);
109 
is_bit_set(const char * bits,int n)110 static inline int is_bit_set(const char *bits, int n) {
111     return bits[n / 8] & (1 << (7 - (n % 8)));
112 }
113 
clear_bit(char * bits,int n)114 static inline void clear_bit(char *bits, int n) {
115     bits[n / 8] &= ~(1 << (7 - (n % 8)));
116 }
117 
118 #define DFLTCC_FMT0 0
119 
120 /*
121    Parameter Block for Generate Dynamic-Huffman Table, Compress and Expand.
122  */
123 #define CVT_CRC32 0
124 #define CVT_ADLER32 1
125 #define HTT_FIXED 0
126 #define HTT_DYNAMIC 1
127 
128 struct dfltcc_param_v0 {
129     uint16_t pbvn;                     /* Parameter-Block-Version Number */
130     uint8_t mvn;                       /* Model-Version Number */
131     uint8_t ribm;                      /* Reserved for IBM use */
132     uint32_t reserved32 : 31;
133     uint32_t cf : 1;                   /* Continuation Flag */
134     uint8_t reserved64[8];
135     uint32_t nt : 1;                   /* New Task */
136     uint32_t reserved129 : 1;
137     uint32_t cvt : 1;                  /* Check Value Type */
138     uint32_t reserved131 : 1;
139     uint32_t htt : 1;                  /* Huffman-Table Type */
140     uint32_t bcf : 1;                  /* Block-Continuation Flag */
141     uint32_t bcc : 1;                  /* Block Closing Control */
142     uint32_t bhf : 1;                  /* Block Header Final */
143     uint32_t reserved136 : 1;
144     uint32_t reserved137 : 1;
145     uint32_t dhtgc : 1;                /* DHT Generation Control */
146     uint32_t reserved139 : 5;
147     uint32_t reserved144 : 5;
148     uint32_t sbb : 3;                  /* Sub-Byte Boundary */
149     uint8_t oesc;                      /* Operation-Ending-Supplemental Code */
150     uint32_t reserved160 : 12;
151     uint32_t ifs : 4;                  /* Incomplete-Function Status */
152     uint16_t ifl;                      /* Incomplete-Function Length */
153     uint8_t reserved192[8];
154     uint8_t reserved256[8];
155     uint8_t reserved320[4];
156     uint16_t hl;                       /* History Length */
157     uint32_t reserved368 : 1;
158     uint16_t ho : 15;                  /* History Offset */
159     uint32_t cv;                       /* Check Value */
160     uint32_t eobs : 15;                /* End-of-block Symbol */
161     uint32_t reserved431: 1;
162     uint8_t eobl : 4;                  /* End-of-block Length */
163     uint32_t reserved436 : 12;
164     uint32_t reserved448 : 4;
165     uint16_t cdhtl : 12;               /* Compressed-Dynamic-Huffman Table
166                                           Length */
167     uint8_t reserved464[6];
168     uint8_t cdht[288];
169     uint8_t reserved[32];
170     uint8_t csb[1152];
171 };
172 
173 static_assert(sizeof(struct dfltcc_param_v0) == 1536, sizeof_struct_dfltcc_param_v0_is_1536);
174 
oesc_msg(char * buf,int oesc)175 static inline const char *oesc_msg(char *buf, int oesc) {
176     if (oesc == 0x00)
177         return NULL; /* Successful completion */
178     else {
179         sprintf(buf, "Operation-Ending-Supplemental Code is 0x%.2X", oesc);
180         return buf;
181     }
182 }
183 
184 /*
185    Extension of inflate_state and deflate_state. Must be doubleword-aligned.
186 */
187 struct dfltcc_state {
188     struct dfltcc_param_v0 param;      /* Parameter block. */
189     struct dfltcc_qaf_param af;        /* Available functions. */
190     uint16_t level_mask;               /* Levels on which to use DFLTCC */
191     uint32_t block_size;               /* New block each X bytes */
192     size_t block_threshold;            /* New block after total_in > X */
193     uint32_t dht_threshold;            /* New block only if avail_in >= X */
194     char msg[64];                      /* Buffer for strm->msg */
195 };
196 
197 #define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1))
198 
199 #define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((char *)(state) + ALIGN_UP(sizeof(*state), 8)))
200