From 180a913d84c2c281b9e4df17e0b37c9c1194e70d Mon Sep 17 00:00:00 2001 From: Eugene Syromyatnikov Date: Fri, 12 Jan 2018 17:25:38 +0100 Subject: [PATCH] Introduce s390_guarded_storage system call decoder * linux/s390/syscallent.h ([378]): Change decoder to s390_guarded_storage. * linux/s390x/syscallent.h: Likewise. * s390.c (struct guard_storage_control_block, struct guard_storage_event_parameter_list): New structure type definition. (guard_storage_print_gsepl, guard_storage_print_gscb, SYS_FUNC(s390_guarded_storage)): New function. (DIV_ROUND_UP): New macro. * xlat/s390_guarded_storage_commands.in: New file. --- linux/s390/syscallent.h | 2 +- linux/s390x/syscallent.h | 2 +- s390.c | 180 ++++++++++++++++++++++++++ xlat/s390_guarded_storage_commands.in | 5 + 4 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 xlat/s390_guarded_storage_commands.in diff --git a/linux/s390/syscallent.h b/linux/s390/syscallent.h index dd1fbb10..522c6415 100644 --- a/linux/s390/syscallent.h +++ b/linux/s390/syscallent.h @@ -407,7 +407,7 @@ [375] = { 6, TD, SEN(copy_file_range), "copy_file_range" }, [376] = { 6, TD, SEN(preadv2), "preadv2" }, [377] = { 6, TD, SEN(pwritev2), "pwritev2" }, -[378] = { 2, 0, SEN(printargs), "s390_guarded_storage" }, +[378] = { 2, 0, SEN(s390_guarded_storage), "s390_guarded_storage" }, [379] = { 5, TD|TF|TSTA, SEN(statx), "statx" }, [380] = { 4, 0, SEN(s390_sthyi), "s390_sthyi" }, diff --git a/linux/s390x/syscallent.h b/linux/s390x/syscallent.h index fe5b252b..8e068c99 100644 --- a/linux/s390x/syscallent.h +++ b/linux/s390x/syscallent.h @@ -391,7 +391,7 @@ [375] = { 6, TD, SEN(copy_file_range), "copy_file_range" }, [376] = { 6, TD, SEN(preadv2), "preadv2" }, [377] = { 6, TD, SEN(pwritev2), "pwritev2" }, -[378] = { 2, 0, SEN(printargs), "s390_guarded_storage" }, +[378] = { 2, 0, SEN(s390_guarded_storage), "s390_guarded_storage" }, [379] = { 5, TD|TF|TSTA, SEN(statx), "statx" }, [380] = { 4, 0, SEN(s390_sthyi), "s390_sthyi" }, diff --git a/s390.c b/s390.c index 0f493698..2358adb4 100644 --- a/s390.c +++ b/s390.c @@ -35,6 +35,7 @@ #include "print_fields.h" +#include "xlat/s390_guarded_storage_commands.h" #include "xlat/s390_sthyi_function_codes.h" /* @@ -1030,4 +1031,183 @@ SYS_FUNC(s390_sthyi) return 0; } + +/* + * Structures are written based on + * https://www-304.ibm.com/support/docview.wss?uid=isg29c69415c1e82603c852576700058075a&aid=1#page=85 + */ + +struct guard_storage_control_block { + uint64_t reserved; + /** + * Guard Storage Designation + * - Bits 0..J, J == 64-GSC - Guard Storage Origin (GSO) + * - Bits 53..55 - Guard Load Shift (GLS) + * - Bits 58..63 - Guard Storage Characteristic (GSC), this is J from + * the first item, valud values are 25..56. + */ + uint64_t gsd; + uint64_t gssm; /**< Guard Storage Section Mask */ + uint64_t gs_epl_a; /**< Guard Storage Event Parameter List Address */ +}; + +struct guard_storage_event_parameter_list { + uint8_t pad1; + /** + * Guard Storage Event Addressing Mode + * - 0x40 - Extended addressing mode (E) + * - 0x80 - Basic addressing mode (B) + */ + uint8_t gs_eam; + /** + * Guard Storage Event Cause indication + * - 0x01 - CPU was in transaction execution mode (TX) + * - 0x02 - CPU was in constrained transaction execution mode (CX) + * - 0x80 - Instruction causing the event: 0 - LGG, 1 - LLGFGS + */ + uint8_t gs_eci; + /** + * Guard Storage Event Access Information + * - 0x01 - DAT mode + * - Bits 1..2 - Address space indication + * - Bits 4..7 - AR number + */ + uint8_t gs_eai; + uint32_t pad2; + uint64_t gs_eha; /**< Guard Storage Event Handler Address */ + uint64_t gs_eia; /**< Guard Storage Event Instruction Address */ + uint64_t gs_eoa; /**< Guard Storage Event Operation Address */ + uint64_t gs_eir; /**< Guard Storage Event Intermediate Result */ + uint64_t gs_era; /**< Guard Storage Event Return Address */ +}; + +static void +guard_storage_print_gsepl(struct tcb *tcp, uint64_t addr) +{ + struct guard_storage_event_parameter_list gsepl; + + /* Since it is 64-bit even on 31-bit s390... */ + if (sizeof(addr) > current_klongsize && + addr >= (1ULL << (current_klongsize * 8))) { + tprintf("%#" PRIx64, addr); + + return; + } + + if (umove_or_printaddr(tcp, addr, &gsepl)) + return; + + tprints("[{"); + + if (!abbrev(tcp)) { + if (gsepl.pad1) { + PRINT_FIELD_0X("", gsepl, pad1); + tprints(", "); + } + + PRINT_FIELD_0X("", gsepl, gs_eam); + tprintf_comment("extended addressing mode: %u, " + "basic addressing mode: %u", + !!(gsepl.gs_eam & 0x2), !!(gsepl.gs_eam & 0x1)); + + PRINT_FIELD_0X(", ", gsepl, gs_eci); + tprintf_comment("CPU in TX: %u, CPU in CX: %u, instruction: %s", + !!(gsepl.gs_eci & 0x80), + !!(gsepl.gs_eci & 0x40), + gsepl.gs_eci & 0x01 ? "LLGFGS" : "LGG"); + + PRINT_FIELD_0X(", ", gsepl, gs_eai); + tprintf_comment("DAT: %u, address space indication: %u, " + "AR number: %u", + !!(gsepl.gs_eai & 0x40), + (gsepl.gs_eai >> 4) & 0x3, + gsepl.gs_eai & 0xF); + + if (gsepl.pad2) + PRINT_FIELD_0X(", ", gsepl, pad2); + + tprints(", "); + } + + PRINT_FIELD_X("", gsepl, gs_eha); + + if (!abbrev(tcp)) { + PRINT_FIELD_X(", ", gsepl, gs_eia); + PRINT_FIELD_X(", ", gsepl, gs_eoa); + PRINT_FIELD_X(", ", gsepl, gs_eir); + PRINT_FIELD_X(", ", gsepl, gs_era); + } else { + tprints(", ..."); + } + + tprints("}]"); +} + +# define DIV_ROUND_UP(x,y) (((x) + ((y) - 1)) / (y)) + +static void +guard_storage_print_gscb(struct tcb *tcp, kernel_ulong_t addr) +{ + struct guard_storage_control_block gscb; + + if (umove_or_printaddr(tcp, addr, &gscb)) + return; + + tprints("{"); + + if (gscb.reserved) { + PRINT_FIELD_0X("", gscb, reserved); + tprints(", "); + } + + PRINT_FIELD_0X("", gscb, gsd); + + if (!abbrev(tcp)) { + unsigned int gsc = gscb.gsd & 0x3F; + bool gsc_valid = gsc >= 25 && gsc <= 56; + tprintf_comment("GS origin: %#*.*" PRIx64 "%s, " + "guard load shift: %" PRIu64 ", " + "GS characteristic: %u", + gsc_valid ? 2 + DIV_ROUND_UP(64 - gsc, 4) : 0, + gsc_valid ? DIV_ROUND_UP(64 - gsc, 4) : 0, + gsc_valid ? gscb.gsd >> gsc : 0, + gsc_valid ? "" : "[invalid]", + (gscb.gsd >> 8) & 0x7, gsc); + } + + PRINT_FIELD_0X(", ", gscb, gssm); + + tprints(", gs_epl_a="); + guard_storage_print_gsepl(tcp, gscb.gs_epl_a); + + tprints("}"); +} + +SYS_FUNC(s390_guarded_storage) +{ + int command = (int) tcp->u_arg[0]; + kernel_ulong_t gs_cb = tcp->u_arg[1]; + + printxval(s390_guarded_storage_commands, command, "GS_???"); + + switch (command) { + case GS_ENABLE: + case GS_DISABLE: + case GS_CLEAR_BC_CB: + case GS_BROADCAST: + break; + + case GS_SET_BC_CB: + tprints(", "); + guard_storage_print_gscb(tcp, gs_cb); + break; + + default: + tprints(", "); + printaddr(gs_cb); + } + + return RVAL_DECODED; +} + #endif /* defined S390 || defined S390X */ diff --git a/xlat/s390_guarded_storage_commands.in b/xlat/s390_guarded_storage_commands.in new file mode 100644 index 00000000..410e33e7 --- /dev/null +++ b/xlat/s390_guarded_storage_commands.in @@ -0,0 +1,5 @@ +GS_ENABLE 0 +GS_DISABLE 1 +GS_SET_BC_CB 2 +GS_CLEAR_BC_CB 3 +GS_BROADCAST 4 -- 2.40.0