• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* dfltcc_deflate.c - IBM Z DEFLATE CONVERSION CALL general support. */
2 
3 #include "../../zbuild.h"
4 #include "dfltcc_common.h"
5 #include "dfltcc_detail.h"
6 
7 /*
8    Memory management.
9 
10    DFLTCC requires parameter blocks and window to be aligned. zlib-ng allows
11    users to specify their own allocation functions, so using e.g.
12    `posix_memalign' is not an option. Thus, we overallocate and take the
13    aligned portion of the buffer.
14 */
is_dfltcc_enabled(void)15 static inline int is_dfltcc_enabled(void) {
16     uint64_t facilities[(DFLTCC_FACILITY / 64) + 1];
17     Z_REGISTER uint8_t r0 __asm__("r0");
18 
19     memset(facilities, 0, sizeof(facilities));
20     r0 = sizeof(facilities) / sizeof(facilities[0]) - 1;
21     /* STFLE is supported since z9-109 and only in z/Architecture mode. When
22      * compiling with -m31, gcc defaults to ESA mode, however, since the kernel
23      * is 64-bit, it's always z/Architecture mode at runtime.
24      */
25     __asm__ volatile(
26 #ifndef __clang__
27                      ".machinemode push\n"
28                      ".machinemode zarch\n"
29 #endif
30                      "stfle %[facilities]\n"
31 #ifndef __clang__
32                      ".machinemode pop\n"
33 #endif
34                      : [facilities] "=Q" (facilities), [r0] "+r" (r0) :: "cc");
35     return is_bit_set((const char *)facilities, DFLTCC_FACILITY);
36 }
37 
dfltcc_reset(PREFIX3 (streamp)strm,uInt size)38 void Z_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size) {
39     struct dfltcc_state *dfltcc_state = (struct dfltcc_state *)((char *)strm->state + ALIGN_UP(size, 8));
40     struct dfltcc_qaf_param *param = (struct dfltcc_qaf_param *)&dfltcc_state->param;
41 
42     /* Initialize available functions */
43     if (is_dfltcc_enabled()) {
44         dfltcc(DFLTCC_QAF, param, NULL, NULL, NULL, NULL, NULL);
45         memmove(&dfltcc_state->af, param, sizeof(dfltcc_state->af));
46     } else
47         memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
48 
49     /* Initialize parameter block */
50     memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param));
51     dfltcc_state->param.nt = 1;
52 
53     /* Initialize tuning parameters */
54     dfltcc_state->level_mask = DFLTCC_LEVEL_MASK;
55     dfltcc_state->block_size = DFLTCC_BLOCK_SIZE;
56     dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE;
57     dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE;
58     dfltcc_state->param.ribm = DFLTCC_RIBM;
59 }
60 
dfltcc_alloc_state(PREFIX3 (streamp)strm,uInt items,uInt size)61 void Z_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size) {
62     return ZALLOC(strm, ALIGN_UP(items * size, 8) + sizeof(struct dfltcc_state), sizeof(unsigned char));
63 }
64 
dfltcc_copy_state(void * dst,const void * src,uInt size)65 void Z_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size) {
66     memcpy(dst, src, ALIGN_UP(size, 8) + sizeof(struct dfltcc_state));
67 }
68 
69 static const int PAGE_ALIGN = 0x1000;
70 
dfltcc_alloc_window(PREFIX3 (streamp)strm,uInt items,uInt size)71 void Z_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt size) {
72     void *p;
73     void *w;
74 
75     /* To simplify freeing, we store the pointer to the allocated buffer right
76      * before the window.
77      */
78     p = ZALLOC(strm, sizeof(void *) + items * size + PAGE_ALIGN, sizeof(unsigned char));
79     if (p == NULL)
80         return NULL;
81     w = ALIGN_UP((char *)p + sizeof(void *), PAGE_ALIGN);
82     *(void **)((char *)w - sizeof(void *)) = p;
83     return w;
84 }
85 
dfltcc_free_window(PREFIX3 (streamp)strm,void * w)86 void Z_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w) {
87     if (w)
88         ZFREE(strm, *(void **)((unsigned char *)w - sizeof(void *)));
89 }
90