aboutsummaryrefslogtreecommitdiff
path: root/src/zlib-ng/arch/s390/dfltcc_detail.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/zlib-ng/arch/s390/dfltcc_detail.h')
-rw-r--r--src/zlib-ng/arch/s390/dfltcc_detail.h50
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);
+}