[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH v2 3/4] tests: ibm, configure-connector RTAS call
From: |
Michael Roth |
Subject: |
Re: [Qemu-ppc] [PATCH v2 3/4] tests: ibm, configure-connector RTAS call implementation |
Date: |
Tue, 28 Nov 2017 18:02:16 -0600 |
User-agent: |
alot/0.6 |
Quoting Daniel Henrique Barboza (2017-11-09 06:35:30)
>
>
> On 11/06/2017 03:46 PM, Laurent Vivier wrote:
> > On 31/10/2017 21:43, Daniel Henrique Barboza wrote:
> >> 'ibm,configure-connector' hypercall is used by the guest OS
> >> to start the configuration of a given device, where the
> >> machine configures the said device and all its sub-devices,
> >> giving back FDTs to the caller for each sub-device.
> >>
> >> This hypercall is supposed to be called multiple times by the
> >> guest OS until it returns RTAS_OUT_SUCESS (code 0), indicating
> >> that the device is now properly configured and ready
> >> to be used, or a return value < 0 when an error occurs.
> >>
> >> This patch implements the 'ibm,configure-connector' RTAS
> >> hypercall in tests/libqos/rtas.c, with an extra test
> >> case for it inside tests/rtas-tests.c.
> >>
> >> Signed-off-by: Daniel Henrique Barboza <address@hidden>
> >> ---
> >> tests/libqos/rtas.c | 35 +++++++++++++++++++++++++++
> >> tests/libqos/rtas.h | 1 +
> >> tests/rtas-test.c | 68
> >> +++++++++++++++++++++++++++++++++++++++++++++++++++++
> >> 3 files changed, 104 insertions(+)
> >>
> >> diff --git a/tests/libqos/rtas.c b/tests/libqos/rtas.c
> >> index ade572a84f..1cb9e2b495 100644
> >> --- a/tests/libqos/rtas.c
> >> +++ b/tests/libqos/rtas.c
> >> @@ -184,3 +184,38 @@ int qrtas_set_indicator(QGuestAllocator *alloc,
> >> uint32_t type, uint32_t idx,
> >>
> >> return ret[0];
> >> }
> >> +
> >> +/*
> >> + * ibm,configure-connector as defined by PAPR 2.7+, 13.5.3.5
> >> + *
> >> + * nargs = 2
> >> + * nrets = 1
> >> + *
> >> + * args[0] and args[1] compose the 64 bit Work Area address.
> >> + *
> >> + * This call will configure not only the device reported in the first
> >> + * offset of the Work Area but all of its siblingis as well, returning
> >> + * the FDT of each configured sub-device as well as a return code
> >> + * 'Next child', 'Next property' or 'Previous parent'. When the whole
> >> + * configuration is done, 'Configuration completed' (0) is returned.
> >> + *
> >> + * configure-connector will always reply with status code 'Next child'(2)
> >> + * on the first successful call. The DRC configuration will be
> >> + * completed when configure-connector returns status 0. Any return
> >> + * status < 0 indicates an error.
> >> + */
> >> +int qrtas_ibm_configure_connector(QGuestAllocator *alloc, uintptr_t
> >> wa_addr)
> >> +{
> >> + uint32_t args[2], ret[1];
> >> + int res;
> >> +
> >> + args[0] = (uint32_t)(wa_addr);
> >> + args[1] = (uint32_t)(wa_addr >> 32);
> > This part looks strange to me. I agree it's what qemu does, but
> > according to spec args[0] is "Address of work area" and args[1] "0 or
> > address of additional page":
> >
> > Linux on Power Architecture Platform Reference
> > Version 1.1
> > 24 March 2016
> >
> > 13.5.3.5 ibm,configure-connector RTAS Call
> > The “need more memory” status code, is similar in semantics to the “call
> > again” status. However, on the next ibm,configure-connector call, the OS
> > will supply, via the Memory extent parameter, the address of another
> > page of memory for RTAS to add to the work area in order for
> > configuration to continue. On all other calls to ibm,configure-connector
> > the contents of the Memory extent parameter should be 0.
>
> Hmmmmm thinking about it, the reason why it works in QEMU is because
> wa_addr >> 32 will always be zero, perhaps?
It looks that way. At least with linux guests the "need more memory"
handling remains unimplemented, so we only ever end up dealing with:
rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL);
which effectively sets args[1] to 0. Still worth fixing though of
course.
>
> At any rate, In this test, makes sense to leave args[1] to be set by the
> caller,
> setting it to 0 in the non "need more memory" scenario.
>
>
> >
> >> + res = qrtas_call(alloc, "ibm,configure-connector", 2, args, 1, ret);
> >> + if (res != 0) {
> >> + return -1;
> >> + }
> >> +
> >> + return ret[0];
> >> +}
> >> diff --git a/tests/libqos/rtas.h b/tests/libqos/rtas.h
> >> index 9dfa18f32b..35c44fb967 100644
> >> --- a/tests/libqos/rtas.h
> >> +++ b/tests/libqos/rtas.h
> >> @@ -16,4 +16,5 @@ int qrtas_check_exception(QGuestAllocator *alloc,
> >> uint32_t mask,
> >> uint32_t buf_addr, uint32_t buf_len);
> >> int qrtas_set_indicator(QGuestAllocator *alloc, uint32_t type, uint32_t
> >> idx,
> >> uint32_t new_state);
> >> +int qrtas_ibm_configure_connector(QGuestAllocator *alloc, uintptr_t
> >> wa_addr);
> >> #endif /* LIBQOS_RTAS_H */
> >> diff --git a/tests/rtas-test.c b/tests/rtas-test.c
> >> index 2c34b6e83c..b3538bf878 100644
> >> --- a/tests/rtas-test.c
> >> +++ b/tests/rtas-test.c
> >> @@ -15,6 +15,8 @@
> >> #define SPAPR_DR_ALLOCATION_STATE_USABLE 1
> >> #define SPAPR_DR_ISOLATION_STATE_UNISOLATED 1
> >>
> >> +#define CC_WA_LEN 4096
> >> +
> >> static void test_rtas_get_time_of_day(void)
> >> {
> >> QOSState *qs;
> >> @@ -169,6 +171,70 @@ static void test_rtas_set_indicator(void)
> >> qtest_shutdown(qs);
> >> }
> >>
> >> +static void test_rtas_ibm_configure_connector(void)
> >> +{
> >> + QOSState *qs;
> >> + uint64_t ret;
> >> + uintptr_t guest_buf_addr, guest_drc_addr;
> >> + uint32_t drc_index;
> >> + uint8_t *buf = g_malloc0(EVENT_LOG_LEN);
> >> +
> >> + qs = qtest_spapr_boot("-machine pseries -cpu POWER8_v2.0 "
> >> + "-smp 1,sockets=4,cores=1,threads=1,maxcpus=4");
> >> +
> >> + guest_buf_addr = guest_alloc(qs->alloc, EVENT_LOG_LEN *
> >> sizeof(uint8_t));
> >> + qtest_qmp_device_add("power8_v2.0-spapr-cpu-core", "id-1",
> >> + "'core-id':'1'");
> >> +
> >> + ret = qrtas_check_exception(qs->alloc, EVENT_MASK_EPOW,
> >> + guest_buf_addr, EVENT_LOG_LEN);
> >> +
> >> + memread(guest_buf_addr, buf, EVENT_LOG_LEN);
> >> + guest_free(qs->alloc, guest_buf_addr);
> >> +
> >> + g_assert_cmpint(ret, ==, 0);
> >> +
> >> + /*
> >> + * Same 108 bytes offset magic used and explained in
> >> + * test_rtas_set_indicator.
> >> + */
> >> + drc_index = be32toh(*((uint32_t *)(buf + 108)));
> >> + g_free(buf);
> >> +
> >> + ret = qrtas_set_indicator(qs->alloc,
> >> RTAS_SENSOR_TYPE_ALLOCATION_STATE,
> >> + drc_index,
> >> SPAPR_DR_ALLOCATION_STATE_USABLE);
> >> + g_assert_cmpint(ret, ==, 0);
> >> +
> >> + ret = qrtas_set_indicator(qs->alloc, RTAS_SENSOR_TYPE_ISOLATION_STATE,
> >> + drc_index,
> >> SPAPR_DR_ISOLATION_STATE_UNISOLATED);
> >> + g_assert_cmpint(ret, ==, 0);
> >> +
> >> + /*
> >> + * Call ibm,configure-connector to finish the hotplugged device
> >> + * configuration, putting its DRC into 'ready' state.
> >> + *
> >> + * We're not interested in the generated FDTs during the config
> >> + * process, thus we simply keep calling configure-connector
> >> + * until it returns SUCCESS(0) or an error.
> >> + *
> >> + * The full explanation logic behind this process can be found
> >> + * at PAPR 2.7+, 13.5.3.5.
> >> + */
> >> + guest_drc_addr = guest_alloc(qs->alloc, CC_WA_LEN * sizeof(uint32_t));
> > CC_WA_LEN is already 4096, why "* sizeof(uint32_t"?
> > It must be aligned to a 4096 bytes boundaries.
>
> Good catch. I'll fix it.
>
> >
> >> + writel(guest_drc_addr, drc_index);
> >> + writel(guest_drc_addr + sizeof(uint32_t), 0)> +
> >> + do {
> >> + ret = qrtas_ibm_configure_connector(qs->alloc, guest_drc_addr);
> >> + } while (ret > 0);
> > I think it would be interesting to check the result of the call (return
> > value, node name, property name,...)
> >
> > And you should also exit with error in the case of ret == 5 (need more
> > memory).
> >
> >> + guest_free(qs->alloc, guest_drc_addr);
> >> +
> >> + g_assert_cmpint(ret, ==, 0);
> >> +
> >> + qtest_shutdown(qs);
> >> +}
> >> +
> >> int main(int argc, char *argv[])
> >> {
> >> const char *arch = qtest_get_arch();
> >> @@ -185,6 +251,8 @@ int main(int argc, char *argv[])
> >> qtest_add_func("rtas/rtas-check-exception-hotplug-event",
> >> test_rtas_check_exception_hotplug_event);
> >> qtest_add_func("rtas/test_rtas_set_indicator",
> >> test_rtas_set_indicator);
> >> + qtest_add_func("rtas/test_rtas_ibm_configure_connector",
> >> + test_rtas_ibm_configure_connector);
> >>
> >> return g_test_run();
> >> }
> >>
> > Thanks,
> > Laurent
> >
>