diff --git a/zlib-1.2.11-IBM-Z-hw-accelrated-inflate-small-window.patch b/zlib-1.2.11-IBM-Z-hw-accelrated-inflate-small-window.patch new file mode 100644 index 0000000..b39d839 --- /dev/null +++ b/zlib-1.2.11-IBM-Z-hw-accelrated-inflate-small-window.patch @@ -0,0 +1,299 @@ +--- a/contrib/s390/dfltcc.c ++++ b/contrib/s390/dfltcc.c +@@ -539,10 +539,6 @@ int ZLIB_INTERNAL dfltcc_can_inflate(strm) + struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state; + struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state); + +- /* Unsupported compression settings */ +- if (state->wbits != HB_BITS) +- return 0; +- + /* Unsupported hardware */ + return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) && + is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0); +@@ -606,8 +602,6 @@ dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(strm, flush, ret) + /* Translate stream to parameter block */ + param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32; + param->sbb = state->bits; +- param->hl = state->whave; /* Software and hardware history formats match */ +- param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1); + if (param->hl) + param->nt = 0; /* Honor history for the first block */ + param->cv = state->flags ? ZSWAP32(state->check) : state->check; +@@ -621,8 +615,6 @@ dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(strm, flush, ret) + strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); + state->last = cc == DFLTCC_CC_OK; + state->bits = param->sbb; +- state->whave = param->hl; +- state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1); + strm->adler = state->check = state->flags ? ZSWAP32(param->cv) : param->cv; + if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) { + /* Report an error if stream is corrupted */ +@@ -644,11 +636,52 @@ int ZLIB_INTERNAL dfltcc_was_inflate_used(strm) + return !param->nt; + } + ++/* ++ Rotates a circular buffer. ++ The implementation is based on https://cplusplus.com/reference/algorithm/rotate/ ++ */ ++local void rotate OF((Bytef *start, Bytef *pivot, Bytef *end)); ++local void rotate(start, pivot, end) ++ Bytef *start; ++ Bytef *pivot; ++ Bytef *end; ++{ ++ Bytef *p = pivot; ++ Bytef tmp; ++ ++ while (p != start) { ++ tmp = *start; ++ *start = *p; ++ *p = tmp; ++ ++ start++; ++ p++; ++ ++ if (p == end) ++ p = pivot; ++ else if (start == pivot) ++ pivot = p; ++ } ++} ++ ++#define MIN(x, y) ({ \ ++ typeof(x) _x = (x); \ ++ typeof(y) _y = (y); \ ++ _x < _y ? _x : _y; \ ++}) ++ ++#define MAX(x, y) ({ \ ++ typeof(x) _x = (x); \ ++ typeof(y) _y = (y); \ ++ _x > _y ? _x : _y; \ ++}) ++ + int ZLIB_INTERNAL dfltcc_inflate_disable(strm) + z_streamp strm; + { + struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state; + struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state); ++ struct dfltcc_param_v0 *param = &dfltcc_state->param; + + if (!dfltcc_can_inflate(strm)) + return 0; +@@ -660,6 +693,9 @@ int ZLIB_INTERNAL dfltcc_inflate_disable(strm) + return 1; + /* DFLTCC was not used yet - decompress in software */ + memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); ++ /* Convert the window from the hardware to the software format */ ++ rotate(state->window, state->window + param->ho, state->window + HB_SIZE); ++ state->whave = state->wnext = MIN(param->hl, state->wsize); + return 0; + } + +@@ -830,9 +866,9 @@ voidpf ZLIB_INTERNAL dfltcc_alloc_window(strm, items, size) + voidpf p, w; + + /* To simplify freeing, we store the pointer to the allocated buffer right +- * before the window. ++ * before the window. Note that DFLTCC always uses HB_SIZE bytes. + */ +- p = ZALLOC(strm, sizeof(voidpf) + items * size + PAGE_ALIGN, ++ p = ZALLOC(strm, sizeof(voidpf) + MAX(items * size, HB_SIZE) + PAGE_ALIGN, + sizeof(unsigned char)); + if (p == NULL) + return NULL; +@@ -841,6 +877,14 @@ voidpf ZLIB_INTERNAL dfltcc_alloc_window(strm, items, size) + return w; + } + ++void ZLIB_INTERNAL dfltcc_copy_window(dest, src, n) ++ void *dest; ++ const void *src; ++ size_t n; ++{ ++ memcpy(dest, src, MAX(n, HB_SIZE)); ++} ++ + void ZLIB_INTERNAL dfltcc_free_window(strm, w) + z_streamp strm; + voidpf w; +@@ -951,6 +995,24 @@ local void append_history(param, history, buf, count) + } + } + ++local void get_history OF((struct dfltcc_param_v0 FAR *param, ++ const Bytef *history, ++ Bytef *buf)); ++local void get_history(param, history, buf) ++ struct dfltcc_param_v0 FAR *param; ++ const Bytef *history; ++ Bytef *buf; ++{ ++ if (param->ho + param->hl <= HB_SIZE) ++ /* Circular history buffer does not wrap - copy one chunk */ ++ memcpy(buf, history + param->ho, param->hl); ++ else { ++ /* Circular history buffer wraps - copy two chunks */ ++ memcpy(buf, history + param->ho, HB_SIZE - param->ho); ++ memcpy(buf + HB_SIZE - param->ho, history, param->ho + param->hl - HB_SIZE); ++ } ++} ++ + int ZLIB_INTERNAL dfltcc_deflate_set_dictionary(strm, dictionary, dict_length) + z_streamp strm; + const Bytef *dictionary; +@@ -975,20 +1037,43 @@ int ZLIB_INTERNAL dfltcc_deflate_get_dictionary(strm, dictionary, dict_length) + struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state); + struct dfltcc_param_v0 FAR *param = &dfltcc_state->param; + +- if (dictionary) { +- if (param->ho + param->hl <= HB_SIZE) +- /* Circular history buffer does not wrap - copy one chunk */ +- zmemcpy(dictionary, state->window + param->ho, param->hl); +- else { +- /* Circular history buffer wraps - copy two chunks */ +- zmemcpy(dictionary, +- state->window + param->ho, +- HB_SIZE - param->ho); +- zmemcpy(dictionary + HB_SIZE - param->ho, +- state->window, +- param->ho + param->hl - HB_SIZE); +- } ++ if (dictionary) ++ get_history(param, state->window, dictionary); ++ if (dict_length) ++ *dict_length = param->hl; ++ return Z_OK; ++} ++ ++int ZLIB_INTERNAL dfltcc_inflate_set_dictionary(strm, dictionary, dict_length) ++ z_streamp strm; ++ const Bytef *dictionary; ++ uInt dict_length; ++{ ++ struct inflate_state *state = (struct inflate_state *)strm->state; ++ struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); ++ struct dfltcc_param_v0 *param = &dfltcc_state->param; ++ ++ if (inflate_ensure_window(state)) { ++ state->mode = MEM; ++ return Z_MEM_ERROR; + } ++ ++ append_history(param, state->window, dictionary, dict_length); ++ state->havedict = 1; ++ return Z_OK; ++} ++ ++int ZLIB_INTERNAL dfltcc_inflate_get_dictionary(strm, dictionary, dict_length) ++ z_streamp strm; ++ Bytef *dictionary; ++ uInt *dict_length; ++{ ++ struct inflate_state *state = (struct inflate_state *)strm->state; ++ struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); ++ struct dfltcc_param_v0 *param = &dfltcc_state->param; ++ ++ if (dictionary && state->window) ++ get_history(param, state->window, dictionary); + if (dict_length) + *dict_length = param->hl; + return Z_OK; +--- a/contrib/s390/dfltcc.h ++++ b/contrib/s390/dfltcc.h +@@ -11,6 +11,8 @@ void ZLIB_INTERNAL dfltcc_copy_state OF((voidpf dst, const voidpf src, + void ZLIB_INTERNAL dfltcc_reset OF((z_streamp strm, uInt size)); + voidpf ZLIB_INTERNAL dfltcc_alloc_window OF((z_streamp strm, uInt items, + uInt size)); ++void ZLIB_INTERNAL dfltcc_copy_window OF((void *dest, const void *src, ++ size_t n)); + void ZLIB_INTERNAL dfltcc_free_window OF((z_streamp strm, voidpf w)); + #define DFLTCC_BLOCK_HEADER_BITS 3 + #define DFLTCC_HLITS_COUNT_BITS 5 +@@ -44,11 +46,18 @@ dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate OF((z_streamp strm, + int flush, int *ret)); + int ZLIB_INTERNAL dfltcc_was_inflate_used OF((z_streamp strm)); + int ZLIB_INTERNAL dfltcc_inflate_disable OF((z_streamp strm)); ++int ZLIB_INTERNAL dfltcc_inflate_set_dictionary OF((z_streamp strm, ++ const Bytef *dictionary, ++ uInt dict_length)); ++int ZLIB_INTERNAL dfltcc_inflate_get_dictionary OF((z_streamp strm, ++ Bytef *dictionary, ++ uInt* dict_length)); + + #define ZALLOC_STATE dfltcc_alloc_state + #define ZFREE_STATE ZFREE + #define ZCOPY_STATE dfltcc_copy_state + #define ZALLOC_WINDOW dfltcc_alloc_window ++#define ZCOPY_WINDOW dfltcc_copy_window + #define ZFREE_WINDOW dfltcc_free_window + #define TRY_FREE_WINDOW dfltcc_free_window + #define INFLATE_RESET_KEEP_HOOK(strm) \ +@@ -77,5 +86,15 @@ int ZLIB_INTERNAL dfltcc_inflate_disable OF((z_streamp strm)); + do { \ + if (dfltcc_was_inflate_used((strm))) return Z_STREAM_ERROR; \ + } while (0) ++#define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \ ++ do { \ ++ if (dfltcc_can_inflate(strm)) \ ++ return dfltcc_inflate_set_dictionary(strm, dict, dict_len); \ ++ } while (0) ++#define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \ ++ do { \ ++ if (dfltcc_can_inflate(strm)) \ ++ return dfltcc_inflate_get_dictionary(strm, dict, dict_len); \ ++ } while (0) + + #endif +\ No newline at end of file +diff --git a/inflate.c b/inflate.c +index 3750152..a0e2169 100644 +--- a/inflate.c ++++ b/inflate.c +@@ -93,6 +93,7 @@ + #define ZFREE_STATE ZFREE + #define ZCOPY_STATE zmemcpy + #define ZALLOC_WINDOW ZALLOC ++#define ZCOPY_WINDOW zmemcpy + #define ZFREE_WINDOW ZFREE + #define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0) + #define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0) +@@ -101,6 +102,8 @@ + #define INFLATE_NEED_UPDATEWINDOW(strm) 1 + #define INFLATE_MARK_HOOK(strm) do {} while (0) + #define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) ++#define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) ++#define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) + #endif + + #ifdef MAKEFIXED +@@ -1330,6 +1333,8 @@ uInt *dictLength; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + ++ INFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength); ++ + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, +@@ -1365,6 +1370,8 @@ uInt dictLength; + return Z_DATA_ERROR; + } + ++ INFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength); ++ + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); +@@ -1529,8 +1536,7 @@ z_streamp source; + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { +- wsize = 1U << state->wbits; +- zmemcpy(window, state->window, wsize); ++ ZCOPY_WINDOW(window, state->window, 1U << state->wbits); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; diff --git a/zlib.spec b/zlib.spec index 12825b3..94a8a71 100644 --- a/zlib.spec +++ b/zlib.spec @@ -2,7 +2,7 @@ Name: zlib Version: 1.2.11 -Release: 35%{?dist} +Release: 36%{?dist} Summary: Compression and decompression library # /contrib/dotzlib/ have Boost license License: zlib and Boost @@ -46,6 +46,8 @@ Patch20: zlib-1.2.11-cve-2022-37434_2.patch # Fix setting strm.adler on z15 Patch21: zlib-1.2.11-IBM-Z-hw-accelrated-deflate-strm-adler-fix.patch +# Optimization for z15 +Patch22: zlib-1.2.11-IBM-Z-hw-accelrated-inflate-small-window.patch BuildRequires: make BuildRequires: automake, autoconf, libtool @@ -119,6 +121,7 @@ developing applications which use minizip. %patch19 -p1 %patch20 -p1 %patch21 -p1 +%patch22 -p1 iconv -f iso-8859-2 -t utf-8 < ChangeLog > ChangeLog.tmp @@ -196,6 +199,9 @@ find $RPM_BUILD_ROOT -name '*.la' -delete %changelog +* Mon Dec 19 2022 Ilya Leoshkevich - 1.2.11-36 +- Inflate small window optimization for IBM z15 rhbz#2154775 + * Wed Oct 12 2022 Ilya Leoshkevich - 1.2.11-35 - Fix for IBM strm.adler rhbz#2134074