diff options
Diffstat (limited to 'src/zlib-ng/arch/s390/dfltcc_detail.h')
-rw-r--r-- | src/zlib-ng/arch/s390/dfltcc_detail.h | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/src/zlib-ng/arch/s390/dfltcc_detail.h b/src/zlib-ng/arch/s390/dfltcc_detail.h index 4ec03f8..8292423 100644 --- a/src/zlib-ng/arch/s390/dfltcc_detail.h +++ b/src/zlib-ng/arch/s390/dfltcc_detail.h @@ -1,6 +1,7 @@ #include <stddef.h> #include <stdint.h> #include <stdio.h> +#include <string.h> #ifdef HAVE_SYS_SDT_H #include <sys/sdt.h> @@ -115,6 +116,29 @@ static inline void clear_bit(char *bits, int n) { bits[n / 8] &= ~(1 << (7 - (n % 8))); } +static inline int is_dfltcc_enabled(void) { + uint64_t facilities[(DFLTCC_FACILITY / 64) + 1]; + Z_REGISTER uint8_t r0 __asm__("r0"); + + memset(facilities, 0, sizeof(facilities)); + r0 = sizeof(facilities) / sizeof(facilities[0]) - 1; + /* STFLE is supported since z9-109 and only in z/Architecture mode. When + * compiling with -m31, gcc defaults to ESA mode, however, since the kernel + * is 64-bit, it's always z/Architecture mode at runtime. + */ + __asm__ volatile( +#ifndef __clang__ + ".machinemode push\n" + ".machinemode zarch\n" +#endif + "stfle %[facilities]\n" +#ifndef __clang__ + ".machinemode pop\n" +#endif + : [facilities] "=Q" (facilities), [r0] "+r" (r0) :: "cc"); + return is_bit_set((const char *)facilities, DFLTCC_FACILITY); +} + #define DFLTCC_FMT0 0 /* @@ -187,13 +211,31 @@ static inline z_const char *oesc_msg(char *buf, int oesc) { struct dfltcc_state { struct dfltcc_param_v0 param; /* Parameter block. */ struct dfltcc_qaf_param af; /* Available functions. */ - uint16_t level_mask; /* Levels on which to use DFLTCC */ - uint32_t block_size; /* New block each X bytes */ - size_t block_threshold; /* New block after total_in > X */ - uint32_t dht_threshold; /* New block only if avail_in >= X */ char msg[64]; /* Buffer for strm->msg */ }; #define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1)) #define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((char *)(state) + ALIGN_UP(sizeof(*state), 8))) + +static inline void *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt size, uInt extension_size) { + return ZALLOC(strm, 1, ALIGN_UP(size, 8) + extension_size); +} + +static inline void dfltcc_reset_state(struct dfltcc_state *dfltcc_state) { + /* Initialize available functions */ + if (is_dfltcc_enabled()) { + dfltcc(DFLTCC_QAF, &dfltcc_state->param, NULL, NULL, NULL, NULL, NULL); + memmove(&dfltcc_state->af, &dfltcc_state->param, sizeof(dfltcc_state->af)); + } else + memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); + + /* Initialize parameter block */ + memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param)); + dfltcc_state->param.nt = 1; + dfltcc_state->param.ribm = DFLTCC_RIBM; +} + +static inline void dfltcc_copy_state(void *dst, const void *src, uInt size, uInt extension_size) { + memcpy(dst, src, ALIGN_UP(size, 8) + extension_size); +} |