Update 'test-guest-state-buffer.c' to add two new KUNIT test cases for
validating correctness of changes to Guest-state-buffer management
infrastructure for adding support for Hostwide GSB elements.

The newly introduced test test_gs_hostwide_msg() checks if the Hostwide
elements can be set and parsed from a Guest-state-buffer. The second kunit
test test_gs_hostwide_counters() checks if the Hostwide GSB elements can be
send to the L0-PowerVM hypervisor via the H_GUEST_SET_STATE hcall and
ensures that the returned guest-state-buffer has all the 5 Hostwide stat
counters present.

Below is the KATP test report with the newly added KUNIT tests:

KTAP version 1
    # Subtest: guest_state_buffer_test
    # module: test_guest_state_buffer
    1..7
    ok 1 test_creating_buffer
    ok 2 test_adding_element
    ok 3 test_gs_bitmap
    ok 4 test_gs_parsing
    ok 5 test_gs_msg
    ok 6 test_gs_hostwide_msg
    # test_gs_hostwide_counters: Guest Heap Size=0 bytes
    # test_gs_hostwide_counters: Guest Heap Size Max=10995367936 bytes
    # test_gs_hostwide_counters: Guest Page-table Size=2178304 bytes
    # test_gs_hostwide_counters: Guest Page-table Size Max=2147483648 bytes
    # test_gs_hostwide_counters: Guest Page-table Reclaim Size=0 bytes
    ok 7 test_gs_hostwide_counters
 # guest_state_buffer_test: pass:7 fail:0 skip:0 total:7
 # Totals: pass:7 fail:0 skip:0 total:7
 ok 1 guest_state_buffer_test

Signed-off-by: Vaibhav Jain <vaib...@linux.ibm.com>
---
Changelog

v2->v3:
None

v1->v2:
None
---
 arch/powerpc/kvm/test-guest-state-buffer.c | 210 +++++++++++++++++++++
 1 file changed, 210 insertions(+)

diff --git a/arch/powerpc/kvm/test-guest-state-buffer.c 
b/arch/powerpc/kvm/test-guest-state-buffer.c
index bfd225329a18..99a3d4b12843 100644
--- a/arch/powerpc/kvm/test-guest-state-buffer.c
+++ b/arch/powerpc/kvm/test-guest-state-buffer.c
@@ -141,6 +141,16 @@ static void test_gs_bitmap(struct kunit *test)
                i++;
        }
 
+       for (u16 iden = KVMPPC_GSID_L0_GUEST_HEAP;
+            iden <= KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM; iden++) {
+               kvmppc_gsbm_set(&gsbm, iden);
+               kvmppc_gsbm_set(&gsbm1, iden);
+               KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
+               kvmppc_gsbm_clear(&gsbm, iden);
+               KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
+               i++;
+       }
+
        for (u16 iden = KVMPPC_GSID_RUN_INPUT; iden <= KVMPPC_GSID_VPA;
             iden++) {
                kvmppc_gsbm_set(&gsbm, iden);
@@ -309,12 +319,212 @@ static void test_gs_msg(struct kunit *test)
        kvmppc_gsm_free(gsm);
 }
 
+/* Test data struct for hostwide/L0 counters */
+struct kvmppc_gs_msg_test_hostwide_data {
+       u64 guest_heap;
+       u64 guest_heap_max;
+       u64 guest_pgtable_size;
+       u64 guest_pgtable_size_max;
+       u64 guest_pgtable_reclaim;
+};
+
+static size_t test_hostwide_get_size(struct kvmppc_gs_msg *gsm)
+
+{
+       size_t size = 0;
+       u16 ids[] = {
+               KVMPPC_GSID_L0_GUEST_HEAP,
+               KVMPPC_GSID_L0_GUEST_HEAP_MAX,
+               KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE,
+               KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE_MAX,
+               KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM
+       };
+
+       for (int i = 0; i < ARRAY_SIZE(ids); i++)
+               size += kvmppc_gse_total_size(kvmppc_gsid_size(ids[i]));
+       return size;
+}
+
+static int test_hostwide_fill_info(struct kvmppc_gs_buff *gsb,
+                                  struct kvmppc_gs_msg *gsm)
+{
+       struct kvmppc_gs_msg_test_hostwide_data *data = gsm->data;
+
+       if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_L0_GUEST_HEAP))
+               kvmppc_gse_put_u64(gsb, KVMPPC_GSID_L0_GUEST_HEAP,
+                                  data->guest_heap);
+       if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_L0_GUEST_HEAP_MAX))
+               kvmppc_gse_put_u64(gsb, KVMPPC_GSID_L0_GUEST_HEAP_MAX,
+                                  data->guest_heap_max);
+       if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE))
+               kvmppc_gse_put_u64(gsb, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE,
+                                  data->guest_pgtable_size);
+       if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE_MAX))
+               kvmppc_gse_put_u64(gsb, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE_MAX,
+                                  data->guest_pgtable_size_max);
+       if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM))
+               kvmppc_gse_put_u64(gsb, KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM,
+                                  data->guest_pgtable_reclaim);
+
+       return 0;
+}
+
+static int test_hostwide_refresh_info(struct kvmppc_gs_msg *gsm,
+                                     struct kvmppc_gs_buff *gsb)
+{
+       struct kvmppc_gs_parser gsp = { 0 };
+       struct kvmppc_gs_msg_test_hostwide_data *data = gsm->data;
+       struct kvmppc_gs_elem *gse;
+       int rc;
+
+       rc = kvmppc_gse_parse(&gsp, gsb);
+       if (rc < 0)
+               return rc;
+
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_HEAP);
+       if (gse)
+               data->guest_heap = kvmppc_gse_get_u64(gse);
+
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_HEAP_MAX);
+       if (gse)
+               data->guest_heap_max = kvmppc_gse_get_u64(gse);
+
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE);
+       if (gse)
+               data->guest_pgtable_size = kvmppc_gse_get_u64(gse);
+
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE_MAX);
+       if (gse)
+               data->guest_pgtable_size_max = kvmppc_gse_get_u64(gse);
+
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM);
+       if (gse)
+               data->guest_pgtable_reclaim = kvmppc_gse_get_u64(gse);
+
+       return 0;
+}
+
+static struct kvmppc_gs_msg_ops gs_msg_test_hostwide_ops = {
+       .get_size = test_hostwide_get_size,
+       .fill_info = test_hostwide_fill_info,
+       .refresh_info = test_hostwide_refresh_info,
+};
+
+static void test_gs_hostwide_msg(struct kunit *test)
+{
+       struct kvmppc_gs_msg_test_hostwide_data test_data = {
+               .guest_heap = 0xdeadbeef,
+               .guest_heap_max = ~0ULL,
+               .guest_pgtable_size = 0xff,
+               .guest_pgtable_size_max = 0xffffff,
+               .guest_pgtable_reclaim = 0xdeadbeef,
+       };
+       struct kvmppc_gs_msg *gsm;
+       struct kvmppc_gs_buff *gsb;
+
+       gsm = kvmppc_gsm_new(&gs_msg_test_hostwide_ops, &test_data, GSM_SEND,
+                            GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsm);
+
+       gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), 0, 0, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
+
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_HEAP);
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_HEAP_MAX);
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE);
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE_MAX);
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM);
+
+       kvmppc_gsm_fill_info(gsm, gsb);
+
+       memset(&test_data, 0, sizeof(test_data));
+
+       kvmppc_gsm_refresh_info(gsm, gsb);
+       KUNIT_EXPECT_EQ(test, test_data.guest_heap, 0xdeadbeef);
+       KUNIT_EXPECT_EQ(test, test_data.guest_heap_max, ~0ULL);
+       KUNIT_EXPECT_EQ(test, test_data.guest_pgtable_size, 0xff);
+       KUNIT_EXPECT_EQ(test, test_data.guest_pgtable_size_max, 0xffffff);
+       KUNIT_EXPECT_EQ(test, test_data.guest_pgtable_reclaim, 0xdeadbeef);
+
+       kvmppc_gsm_free(gsm);
+}
+
+/* Test if the H_GUEST_GET_STATE for hostwide counters works */
+static void test_gs_hostwide_counters(struct kunit *test)
+{
+       struct kvmppc_gs_msg_test_hostwide_data test_data;
+       struct kvmppc_gs_parser gsp = { 0 };
+
+       struct kvmppc_gs_msg *gsm;
+       struct kvmppc_gs_buff *gsb;
+       struct kvmppc_gs_elem *gse;
+       int rc;
+
+       gsm = kvmppc_gsm_new(&gs_msg_test_hostwide_ops, &test_data, GSM_SEND,
+                            GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsm);
+
+       gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), 0, 0, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
+
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_HEAP);
+
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_HEAP_MAX);
+
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE);
+
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE_MAX);
+
+       kvmppc_gsm_include(gsm, KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM);
+
+       kvmppc_gsm_fill_info(gsm, gsb);
+
+       /* With HOST_WIDE flags guestid and vcpuid will be ignored */
+       rc = kvmppc_gsb_recv(gsb, KVMPPC_GS_FLAGS_HOST_WIDE);
+       KUNIT_ASSERT_EQ(test, rc, 0);
+
+       /* Parse the guest state buffer is successful */
+       rc = kvmppc_gse_parse(&gsp, gsb);
+       KUNIT_ASSERT_EQ(test, rc, 0);
+
+       /* Parse the GSB and get the counters */
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_HEAP);
+       KUNIT_ASSERT_NOT_NULL_MSG(test, gse, "L0 Heap counter missing");
+       kunit_info(test, "Guest Heap Size=%llu bytes",
+                  kvmppc_gse_get_u64(gse));
+
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_HEAP_MAX);
+       KUNIT_ASSERT_NOT_NULL_MSG(test, gse, "L0 Heap counter max missing");
+       kunit_info(test, "Guest Heap Size Max=%llu bytes",
+                  kvmppc_gse_get_u64(gse));
+
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE);
+       KUNIT_ASSERT_NOT_NULL_MSG(test, gse, "L0 page-table size missing");
+       kunit_info(test, "Guest Page-table Size=%llu bytes",
+                  kvmppc_gse_get_u64(gse));
+
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_PGTABLE_SIZE_MAX);
+       KUNIT_ASSERT_NOT_NULL_MSG(test, gse, "L0 page-table size-max missing");
+       kunit_info(test, "Guest Page-table Size Max=%llu bytes",
+                  kvmppc_gse_get_u64(gse));
+
+       gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_L0_GUEST_PGTABLE_RECLAIM);
+       KUNIT_ASSERT_NOT_NULL_MSG(test, gse, "L0 page-table reclaim size 
missing");
+       kunit_info(test, "Guest Page-table Reclaim Size=%llu bytes",
+                  kvmppc_gse_get_u64(gse));
+
+       kvmppc_gsm_free(gsm);
+       kvmppc_gsb_free(gsb);
+}
+
 static struct kunit_case guest_state_buffer_testcases[] = {
        KUNIT_CASE(test_creating_buffer),
        KUNIT_CASE(test_adding_element),
        KUNIT_CASE(test_gs_bitmap),
        KUNIT_CASE(test_gs_parsing),
        KUNIT_CASE(test_gs_msg),
+       KUNIT_CASE(test_gs_hostwide_msg),
+       KUNIT_CASE(test_gs_hostwide_counters),
        {}
 };
 
-- 
2.48.1


Reply via email to