@@ -107,6 +107,7 @@ struct schib {
uint64_t mbo;
uint8_t md[4];
} __attribute__ ((aligned(4)));
+extern struct schib schib;
struct irb {
struct scsw scsw;
@@ -386,4 +387,18 @@ struct measurement_block_format0 {
uint32_t initial_cmd_resp_time;
};
+struct measurement_block_format1 {
+ uint32_t ssch_rsch_count;
+ uint32_t sample_count;
+ uint32_t device_connect_time;
+ uint32_t function_pending_time;
+ uint32_t device_disconnect_time;
+ uint32_t cu_queuing_time;
+ uint32_t device_active_only_time;
+ uint32_t device_busy_time;
+ uint32_t initial_cmd_resp_time;
+ uint32_t irq_delay_time;
+ uint32_t irq_prio_delay_time;
+};
+
#endif
@@ -19,7 +19,7 @@
#include <malloc_io.h>
#include <css.h>
-static struct schib schib;
+struct schib schib;
struct chsc_scsc *chsc_scsc;
static const char * const chsc_rsp_description[] = {
@@ -257,6 +257,80 @@ static void test_schm_fmt0(void)
free_io_mem(mb0, shared_mb_size);
}
+static void msch_with_wrong_fmt1_mbo(unsigned int schid, uint64_t mb)
+{
+ struct pmcw *pmcw = &schib.pmcw;
+ int cc;
+
+ /* Read the SCHIB for this subchannel */
+ cc = stsch(schid, &schib);
+ if (cc) {
+ report(0, "stsch: sch %08x failed with cc=%d", schid, cc);
+ return;
+ }
+
+ /* Update the SCHIB to enable the measurement block */
+ pmcw->flags |= PMCW_MBUE;
+ pmcw->flags2 |= PMCW_MBF1;
+ schib.mbo = mb;
+
+ /* Tell the CSS we want to modify the subchannel */
+ expect_pgm_int();
+ cc = msch(schid, &schib);
+ check_pgm_int_code(PGM_INT_CODE_OPERAND);
+}
+
+/*
+ * test_schm_fmt1:
+ * With measurement block format 1 the measurement block is
+ * dedicated to a subchannel.
+ */
+static void test_schm_fmt1(void)
+{
+ struct measurement_block_format1 *mb1;
+
+ if (!test_device_sid) {
+ report_skip("No device");
+ return;
+ }
+
+ if (!css_test_general_feature(CSSC_EXTENDED_MEASUREMENT_BLOCK)) {
+ report_skip("Extended measurement block not available");
+ return;
+ }
+
+ /* Allocate zeroed Measurement block */
+ mb1 = alloc_io_mem(sizeof(struct measurement_block_format1), 0);
+ if (!mb1) {
+ report_abort("measurement_block_format1 allocation failed");
+ return;
+ }
+
+ schm(NULL, 0); /* Stop any previous measurement */
+ schm(0, SCHM_MBU);
+
+ /* Expect error for non aligned MB */
+ report_prefix_push("Unaligned MB origin");
+ msch_with_wrong_fmt1_mbo(test_device_sid, (uint64_t)mb1 + 1);
+ report_prefix_pop();
+
+ /* Clear the measurement block for the next test */
+ memset(mb1, 0, sizeof(*mb1));
+
+ /* Expect success */
+ report_prefix_push("Valid MB origin");
+ if (start_measuring((u64)mb1, 0, true))
+ report(mb1->ssch_rsch_count == SCHM_UPDATE_CNT,
+ "SSCH measured %d", mb1->ssch_rsch_count);
+ report_prefix_pop();
+
+ /* Stop the measurement */
+ css_disable_mb(test_device_sid);
+ schm(NULL, 0);
+
+ free_io_mem(mb1, sizeof(struct measurement_block_format1));
+}
+
static struct {
const char *name;
void (*func)(void);
@@ -268,6 +342,7 @@ static struct {
{ "sense (ssch/tsch)", test_sense },
{ "measurement block (schm)", test_schm },
{ "measurement block format0", test_schm_fmt0 },
+ { "measurement block format1", test_schm_fmt1 },
{ NULL, NULL }
};