1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#define _ISOC11_SOURCE
45#define _DEFAULT_SOURCE
46
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51#include <stdint.h>
52#include <sys/types.h>
53#include <sys/stat.h>
54#include <sys/time.h>
55#include <sys/fcntl.h>
56#include <sys/mman.h>
57#include <endian.h>
58#include <bits/endian.h>
59#include <sys/ioctl.h>
60#include <assert.h>
61#include <errno.h>
62#include <signal.h>
63#include "utils.h"
64#include "nxu.h"
65#include "nx.h"
66
67int nx_dbg;
68FILE *nx_gzip_log;
69
70#define NX_MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
71#define FNAME_MAX 1024
72#define FEXT ".nx.gz"
73
74#define SYSFS_MAX_REQ_BUF_PATH "devices/vio/ibm,compression-v1/nx_gzip_caps/req_max_processed_len"
75
76
77
78
79static int compress_fht_sample(char *src, uint32_t srclen, char *dst,
80 uint32_t dstlen, int with_count,
81 struct nx_gzip_crb_cpb_t *cmdp, void *handle)
82{
83 uint32_t fc;
84
85 assert(!!cmdp);
86
87 put32(cmdp->crb, gzip_fc, 0);
88 fc = (with_count) ? GZIP_FC_COMPRESS_RESUME_FHT_COUNT :
89 GZIP_FC_COMPRESS_RESUME_FHT;
90 putnn(cmdp->crb, gzip_fc, fc);
91 putnn(cmdp->cpb, in_histlen, 0);
92 memset((void *) &cmdp->crb.csb, 0, sizeof(cmdp->crb.csb));
93
94
95
96
97 if (!with_count)
98 put32(cmdp->cpb, out_spbc_comp, 0);
99 else
100 put32(cmdp->cpb, out_spbc_comp_with_count, 0);
101
102
103 put64(cmdp->crb, csb_address, 0);
104 put64(cmdp->crb, csb_address,
105 (uint64_t) &cmdp->crb.csb & csb_address_mask);
106
107
108 clear_dde(cmdp->crb.source_dde);
109 putnn(cmdp->crb.source_dde, dde_count, 0);
110 put32(cmdp->crb.source_dde, ddebc, srclen);
111 put64(cmdp->crb.source_dde, ddead, (uint64_t) src);
112
113
114 clear_dde(cmdp->crb.target_dde);
115 putnn(cmdp->crb.target_dde, dde_count, 0);
116 put32(cmdp->crb.target_dde, ddebc, dstlen);
117 put64(cmdp->crb.target_dde, ddead, (uint64_t) dst);
118
119
120 return nxu_submit_job(cmdp, handle);
121}
122
123
124
125
126
127
128int gzip_header_blank(char *buf)
129{
130 int i = 0;
131
132 buf[i++] = 0x1f;
133 buf[i++] = 0x8b;
134 buf[i++] = 0x08;
135 buf[i++] = 0x00;
136 buf[i++] = 0x00;
137 buf[i++] = 0x00;
138 buf[i++] = 0x00;
139 buf[i++] = 0x00;
140 buf[i++] = 0x04;
141 buf[i++] = 0x03;
142
143 return i;
144}
145
146
147int read_alloc_input_file(char *fname, char **buf, size_t *bufsize)
148{
149 struct stat statbuf;
150 FILE *fp;
151 char *p;
152 size_t num_bytes;
153
154 if (stat(fname, &statbuf)) {
155 perror(fname);
156 return(-1);
157 }
158 fp = fopen(fname, "r");
159 if (fp == NULL) {
160 perror(fname);
161 return(-1);
162 }
163 assert(NULL != (p = (char *) malloc(statbuf.st_size)));
164 num_bytes = fread(p, 1, statbuf.st_size, fp);
165 if (ferror(fp) || (num_bytes != statbuf.st_size)) {
166 perror(fname);
167 return(-1);
168 }
169 *buf = p;
170 *bufsize = num_bytes;
171 return 0;
172}
173
174
175int write_output_file(char *fname, char *buf, size_t bufsize)
176{
177 FILE *fp;
178 size_t num_bytes;
179
180 fp = fopen(fname, "w");
181 if (fp == NULL) {
182 perror(fname);
183 return(-1);
184 }
185 num_bytes = fwrite(buf, 1, bufsize, fp);
186 if (ferror(fp) || (num_bytes != bufsize)) {
187 perror(fname);
188 return(-1);
189 }
190 fclose(fp);
191 return 0;
192}
193
194
195
196
197
198int append_sync_flush(char *buf, int tebc, int final)
199{
200 uint64_t flush;
201 int shift = (tebc & 0x7);
202
203 if (tebc > 0) {
204
205 buf = buf - 1;
206 *buf = *buf & (unsigned char) ((1<<tebc)-1);
207 } else
208 *buf = 0;
209 flush = ((0x1ULL & final) << shift) | *buf;
210 shift = shift + 3;
211 shift = (shift <= 8) ? 8 : 16;
212 flush |= (0xFFFF0000ULL) << shift;
213 shift = shift + 32;
214 while (shift > 0) {
215 *buf++ = (unsigned char) (flush & 0xffULL);
216 flush = flush >> 8;
217 shift = shift - 8;
218 }
219 return(((tebc > 5) || (tebc == 0)) ? 5 : 4);
220}
221
222
223
224
225
226static void set_bfinal(void *buf, int bfinal)
227{
228 char *b = buf;
229
230 if (bfinal)
231 *b = *b | (unsigned char) 0x01;
232 else
233 *b = *b & (unsigned char) 0xfe;
234}
235
236int compress_file(int argc, char **argv, void *handle)
237{
238 char *inbuf, *outbuf, *srcbuf, *dstbuf;
239 char outname[FNAME_MAX];
240 uint32_t srclen, dstlen;
241 uint32_t flushlen, chunk;
242 size_t inlen, outlen, dsttotlen, srctotlen;
243 uint32_t crc, spbc, tpbc, tebc;
244 int lzcounts = 0;
245 int cc;
246 int num_hdr_bytes;
247 struct nx_gzip_crb_cpb_t *cmdp;
248 uint32_t pagelen = 65536;
249 int fault_tries = NX_MAX_FAULTS;
250 char buf[32];
251
252 cmdp = (void *)(uintptr_t)
253 aligned_alloc(sizeof(struct nx_gzip_crb_cpb_t),
254 sizeof(struct nx_gzip_crb_cpb_t));
255
256 if (argc != 2) {
257 fprintf(stderr, "usage: %s <fname>\n", argv[0]);
258 exit(-1);
259 }
260 if (read_alloc_input_file(argv[1], &inbuf, &inlen))
261 exit(-1);
262 fprintf(stderr, "file %s read, %ld bytes\n", argv[1], inlen);
263
264
265 outlen = 2 * inlen + 1024;
266
267 assert(NULL != (outbuf = (char *)malloc(outlen)));
268 nxu_touch_pages(outbuf, outlen, pagelen, 1);
269
270
271
272
273
274 if (!read_sysfs_file(SYSFS_MAX_REQ_BUF_PATH, buf, sizeof(buf))) {
275 chunk = atoi(buf);
276 } else {
277
278
279 chunk = 1<<22;
280 }
281
282
283 num_hdr_bytes = gzip_header_blank(outbuf);
284 dstbuf = outbuf + num_hdr_bytes;
285 outlen = outlen - num_hdr_bytes;
286 dsttotlen = num_hdr_bytes;
287
288 srcbuf = inbuf;
289 srctotlen = 0;
290
291
292 memset(&cmdp->crb, 0, sizeof(cmdp->crb));
293
294
295 put32(cmdp->cpb, in_crc, 0);
296
297 while (inlen > 0) {
298
299
300 srclen = NX_MIN(chunk, inlen);
301
302 dstlen = NX_MIN(2*srclen, outlen);
303
304
305
306
307
308
309
310
311 nxu_touch_pages(cmdp, sizeof(struct nx_gzip_crb_cpb_t), pagelen,
312 1);
313 nxu_touch_pages(srcbuf, srclen, pagelen, 0);
314 nxu_touch_pages(dstbuf, dstlen, pagelen, 1);
315
316 cc = compress_fht_sample(
317 srcbuf, srclen,
318 dstbuf, dstlen,
319 lzcounts, cmdp, handle);
320
321 if (cc != ERR_NX_OK && cc != ERR_NX_TPBC_GT_SPBC &&
322 cc != ERR_NX_AT_FAULT) {
323 fprintf(stderr, "nx error: cc= %d\n", cc);
324 exit(-1);
325 }
326
327
328 if (cc == ERR_NX_AT_FAULT) {
329 NXPRT(fprintf(stderr, "page fault: cc= %d, ", cc));
330 NXPRT(fprintf(stderr, "try= %d, fsa= %08llx\n",
331 fault_tries,
332 (unsigned long long) cmdp->crb.csb.fsaddr));
333 fault_tries--;
334 if (fault_tries > 0) {
335 continue;
336 } else {
337 fprintf(stderr, "error: cannot progress; ");
338 fprintf(stderr, "too many faults\n");
339 exit(-1);
340 }
341 }
342
343 fault_tries = NX_MAX_FAULTS;
344
345 inlen = inlen - srclen;
346 srcbuf = srcbuf + srclen;
347 srctotlen = srctotlen + srclen;
348
349
350
351
352 spbc = (!lzcounts) ? get32(cmdp->cpb, out_spbc_comp) :
353 get32(cmdp->cpb, out_spbc_comp_with_count);
354 assert(spbc == srclen);
355
356
357 tpbc = get32(cmdp->crb.csb, tpbc);
358
359 tebc = getnn(cmdp->cpb, out_tebc);
360 NXPRT(fprintf(stderr, "compressed chunk %d ", spbc));
361 NXPRT(fprintf(stderr, "to %d bytes, tebc= %d\n", tpbc, tebc));
362
363 if (inlen > 0) {
364 set_bfinal(dstbuf, 0);
365 dstbuf = dstbuf + tpbc;
366 dsttotlen = dsttotlen + tpbc;
367 outlen = outlen - tpbc;
368
369
370
371 flushlen = append_sync_flush(dstbuf, tebc, 0);
372 dsttotlen = dsttotlen + flushlen;
373 outlen = outlen - flushlen;
374 dstbuf = dstbuf + flushlen;
375 NXPRT(fprintf(stderr, "added sync_flush %d bytes\n",
376 flushlen));
377 } else {
378
379
380
381 set_bfinal(dstbuf, 1);
382 dstbuf = dstbuf + tpbc;
383 dsttotlen = dsttotlen + tpbc;
384 outlen = outlen - tpbc;
385 }
386
387
388 crc = get32(cmdp->cpb, out_crc);
389 put32(cmdp->cpb, in_crc, crc);
390 crc = be32toh(crc);
391 }
392
393
394 memcpy(dstbuf, &crc, 4);
395 memcpy(dstbuf+4, &srctotlen, 4);
396 dsttotlen = dsttotlen + 8;
397 outlen = outlen - 8;
398
399 assert(FNAME_MAX > (strlen(argv[1]) + strlen(FEXT)));
400 strcpy(outname, argv[1]);
401 strcat(outname, FEXT);
402 if (write_output_file(outname, outbuf, dsttotlen)) {
403 fprintf(stderr, "write error: %s\n", outname);
404 exit(-1);
405 }
406
407 fprintf(stderr, "compressed %ld to %ld bytes total, ", srctotlen,
408 dsttotlen);
409 fprintf(stderr, "crc32 checksum = %08x\n", crc);
410
411 if (inbuf != NULL)
412 free(inbuf);
413
414 if (outbuf != NULL)
415 free(outbuf);
416
417 return 0;
418}
419
420int main(int argc, char **argv)
421{
422 int rc;
423 struct sigaction act;
424 void *handle;
425
426 nx_dbg = 0;
427 nx_gzip_log = NULL;
428 act.sa_handler = 0;
429 act.sa_sigaction = nxu_sigsegv_handler;
430 act.sa_flags = SA_SIGINFO;
431 act.sa_restorer = 0;
432 sigemptyset(&act.sa_mask);
433 sigaction(SIGSEGV, &act, NULL);
434
435 handle = nx_function_begin(NX_FUNC_COMP_GZIP, 0);
436 if (!handle) {
437 fprintf(stderr, "Unable to init NX, errno %d\n", errno);
438 exit(-1);
439 }
440
441 rc = compress_file(argc, argv, handle);
442
443 nx_function_end(handle);
444
445 return rc;
446}
447