[PATCH 3/6] ppc/pegasos2: Implement get-time-of-day RTAS function with VOF

BALATON Zoltan posted 6 patches 4 years, 3 months ago
Maintainers: BALATON Zoltan <balaton@eik.bme.hu>
[PATCH 3/6] ppc/pegasos2: Implement get-time-of-day RTAS function with VOF
Posted by BALATON Zoltan 4 years, 3 months ago
This is needed for Linux to access RTC time.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/ppc/pegasos2.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index a1dd1f6752..a9e3625f56 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -31,6 +31,8 @@
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
 #include "exec/address-spaces.h"
+#include "qom/qom-qobject.h"
+#include "qapi/qmp/qdict.h"
 #include "trace.h"
 #include "qemu/datadir.h"
 #include "sysemu/device_tree.h"
@@ -369,6 +371,29 @@ static target_ulong pegasos2_rtas(PowerPCCPU *cpu, Pegasos2MachineState *pm,
         return H_PARAMETER;
     }
     switch (token) {
+    case RTAS_GET_TIME_OF_DAY:
+    {
+        QObject *qo = object_property_get_qobject(qdev_get_machine(),
+                                                  "rtc-time", &error_fatal);
+        QDict *qd = qobject_to(QDict, qo);
+
+        if (nargs != 0 || nrets != 8 || !qd) {
+            stl_be_phys(as, rets, -1);
+            qobject_unref(qo);
+            return H_PARAMETER;
+        }
+
+        stl_be_phys(as, rets, 0);
+        stl_be_phys(as, rets + 4, qdict_get_int(qd, "tm_year") + 1900);
+        stl_be_phys(as, rets + 8, qdict_get_int(qd, "tm_mon") + 1);
+        stl_be_phys(as, rets + 12, qdict_get_int(qd, "tm_mday"));
+        stl_be_phys(as, rets + 16, qdict_get_int(qd, "tm_hour"));
+        stl_be_phys(as, rets + 20, qdict_get_int(qd, "tm_min"));
+        stl_be_phys(as, rets + 24, qdict_get_int(qd, "tm_sec"));
+        stl_be_phys(as, rets + 28, 0);
+        qobject_unref(qo);
+        return H_SUCCESS;
+    }
     case RTAS_READ_PCI_CONFIG:
     {
         uint32_t addr, len, val;
-- 
2.21.4


Re: [PATCH 3/6] ppc/pegasos2: Implement get-time-of-day RTAS function with VOF
Posted by David Gibson 4 years, 3 months ago
On Thu, Oct 14, 2021 at 09:50:19PM +0200, BALATON Zoltan wrote:
> This is needed for Linux to access RTC time.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>  hw/ppc/pegasos2.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
> index a1dd1f6752..a9e3625f56 100644
> --- a/hw/ppc/pegasos2.c
> +++ b/hw/ppc/pegasos2.c
> @@ -31,6 +31,8 @@
>  #include "sysemu/kvm.h"
>  #include "kvm_ppc.h"
>  #include "exec/address-spaces.h"
> +#include "qom/qom-qobject.h"
> +#include "qapi/qmp/qdict.h"
>  #include "trace.h"
>  #include "qemu/datadir.h"
>  #include "sysemu/device_tree.h"
> @@ -369,6 +371,29 @@ static target_ulong pegasos2_rtas(PowerPCCPU *cpu, Pegasos2MachineState *pm,
>          return H_PARAMETER;
>      }
>      switch (token) {
> +    case RTAS_GET_TIME_OF_DAY:
> +    {
> +        QObject *qo = object_property_get_qobject(qdev_get_machine(),
> +                                                  "rtc-time", &error_fatal);
> +        QDict *qd = qobject_to(QDict, qo);
> +
> +        if (nargs != 0 || nrets != 8 || !qd) {
> +            stl_be_phys(as, rets, -1);
> +            qobject_unref(qo);
> +            return H_PARAMETER;
> +        }
> +
> +        stl_be_phys(as, rets, 0);
> +        stl_be_phys(as, rets + 4, qdict_get_int(qd, "tm_year") + 1900);
> +        stl_be_phys(as, rets + 8, qdict_get_int(qd, "tm_mon") + 1);
> +        stl_be_phys(as, rets + 12, qdict_get_int(qd, "tm_mday"));
> +        stl_be_phys(as, rets + 16, qdict_get_int(qd, "tm_hour"));
> +        stl_be_phys(as, rets + 20, qdict_get_int(qd, "tm_min"));
> +        stl_be_phys(as, rets + 24, qdict_get_int(qd, "tm_sec"));

Doing a separate dictionary lookup for every component seems like it
might be pretty expensive.  You might want to look at how spapr does
this.

However, you're maintainer for pegasos, so really it's your call -
applied, thanks.

> +        stl_be_phys(as, rets + 28, 0);
> +        qobject_unref(qo);
> +        return H_SUCCESS;
> +    }
>      case RTAS_READ_PCI_CONFIG:
>      {
>          uint32_t addr, len, val;

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
Re: [PATCH 3/6] ppc/pegasos2: Implement get-time-of-day RTAS function with VOF
Posted by BALATON Zoltan 4 years, 3 months ago
On Fri, 15 Oct 2021, David Gibson wrote:
> On Thu, Oct 14, 2021 at 09:50:19PM +0200, BALATON Zoltan wrote:
>> This is needed for Linux to access RTC time.
>>
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> ---
>>  hw/ppc/pegasos2.c | 25 +++++++++++++++++++++++++
>>  1 file changed, 25 insertions(+)
>>
>> diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
>> index a1dd1f6752..a9e3625f56 100644
>> --- a/hw/ppc/pegasos2.c
>> +++ b/hw/ppc/pegasos2.c
>> @@ -31,6 +31,8 @@
>>  #include "sysemu/kvm.h"
>>  #include "kvm_ppc.h"
>>  #include "exec/address-spaces.h"
>> +#include "qom/qom-qobject.h"
>> +#include "qapi/qmp/qdict.h"
>>  #include "trace.h"
>>  #include "qemu/datadir.h"
>>  #include "sysemu/device_tree.h"
>> @@ -369,6 +371,29 @@ static target_ulong pegasos2_rtas(PowerPCCPU *cpu, Pegasos2MachineState *pm,
>>          return H_PARAMETER;
>>      }
>>      switch (token) {
>> +    case RTAS_GET_TIME_OF_DAY:
>> +    {
>> +        QObject *qo = object_property_get_qobject(qdev_get_machine(),
>> +                                                  "rtc-time", &error_fatal);
>> +        QDict *qd = qobject_to(QDict, qo);
>> +
>> +        if (nargs != 0 || nrets != 8 || !qd) {
>> +            stl_be_phys(as, rets, -1);
>> +            qobject_unref(qo);
>> +            return H_PARAMETER;
>> +        }
>> +
>> +        stl_be_phys(as, rets, 0);
>> +        stl_be_phys(as, rets + 4, qdict_get_int(qd, "tm_year") + 1900);
>> +        stl_be_phys(as, rets + 8, qdict_get_int(qd, "tm_mon") + 1);
>> +        stl_be_phys(as, rets + 12, qdict_get_int(qd, "tm_mday"));
>> +        stl_be_phys(as, rets + 16, qdict_get_int(qd, "tm_hour"));
>> +        stl_be_phys(as, rets + 20, qdict_get_int(qd, "tm_min"));
>> +        stl_be_phys(as, rets + 24, qdict_get_int(qd, "tm_sec"));
>
> Doing a separate dictionary lookup for every component seems like it
> might be pretty expensive.  You might want to look at how spapr does
> this.

This is the only short way I could find to read the RTC the same way as 
the guest or firmware would. I wasn't sure because the rtc model has an 
update rtc function that it calls before reads to set the values but that 
looks like doing the same as spapr does so I'll send another patch 
replacing this with that then.

Thanks,
BALATON Zoltan

> However, you're maintainer for pegasos, so really it's your call -
> applied, thanks.
>
>> +        stl_be_phys(as, rets + 28, 0);
>> +        qobject_unref(qo);
>> +        return H_SUCCESS;
>> +    }
>>      case RTAS_READ_PCI_CONFIG:
>>      {
>>          uint32_t addr, len, val;
>
>

Re: [PATCH 3/6] ppc/pegasos2: Implement get-time-of-day RTAS function with VOF
Posted by BALATON Zoltan 4 years, 3 months ago
On Fri, 15 Oct 2021, BALATON Zoltan wrote:
> On Fri, 15 Oct 2021, David Gibson wrote:
>> On Thu, Oct 14, 2021 at 09:50:19PM +0200, BALATON Zoltan wrote:
>>> This is needed for Linux to access RTC time.
>>> 
>>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>>> ---
>>>  hw/ppc/pegasos2.c | 25 +++++++++++++++++++++++++
>>>  1 file changed, 25 insertions(+)
>>> 
>>> diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
>>> index a1dd1f6752..a9e3625f56 100644
>>> --- a/hw/ppc/pegasos2.c
>>> +++ b/hw/ppc/pegasos2.c
>>> @@ -31,6 +31,8 @@
>>>  #include "sysemu/kvm.h"
>>>  #include "kvm_ppc.h"
>>>  #include "exec/address-spaces.h"
>>> +#include "qom/qom-qobject.h"
>>> +#include "qapi/qmp/qdict.h"
>>>  #include "trace.h"
>>>  #include "qemu/datadir.h"
>>>  #include "sysemu/device_tree.h"
>>> @@ -369,6 +371,29 @@ static target_ulong pegasos2_rtas(PowerPCCPU *cpu, 
>>> Pegasos2MachineState *pm,
>>>          return H_PARAMETER;
>>>      }
>>>      switch (token) {
>>> +    case RTAS_GET_TIME_OF_DAY:
>>> +    {
>>> +        QObject *qo = object_property_get_qobject(qdev_get_machine(),
>>> +                                                  "rtc-time", 
>>> &error_fatal);
>>> +        QDict *qd = qobject_to(QDict, qo);
>>> +
>>> +        if (nargs != 0 || nrets != 8 || !qd) {
>>> +            stl_be_phys(as, rets, -1);
>>> +            qobject_unref(qo);
>>> +            return H_PARAMETER;
>>> +        }
>>> +
>>> +        stl_be_phys(as, rets, 0);
>>> +        stl_be_phys(as, rets + 4, qdict_get_int(qd, "tm_year") + 1900);
>>> +        stl_be_phys(as, rets + 8, qdict_get_int(qd, "tm_mon") + 1);
>>> +        stl_be_phys(as, rets + 12, qdict_get_int(qd, "tm_mday"));
>>> +        stl_be_phys(as, rets + 16, qdict_get_int(qd, "tm_hour"));
>>> +        stl_be_phys(as, rets + 20, qdict_get_int(qd, "tm_min"));
>>> +        stl_be_phys(as, rets + 24, qdict_get_int(qd, "tm_sec"));
>> 
>> Doing a separate dictionary lookup for every component seems like it
>> might be pretty expensive.  You might want to look at how spapr does
>> this.
>
> This is the only short way I could find to read the RTC the same way as the 
> guest or firmware would. I wasn't sure because the rtc model has an update 
> rtc function that it calls before reads to set the values but that looks like 
> doing the same as spapr does so I'll send another patch replacing this with 
> that then.

Forget it. I've looked at it and to get the time that way fitst we'd need 
the RTCState struct which we don't readily have as it's part of the vt8231 
device which creates it internally so the pegasos2 code does not see it 
directly but would need some qdev magic to find it. Then we would need to 
either export or duplicate the get_guest_rtc_ns() function from 
hw/rtc/mc146818rtc.c to get the guest clock. Since reading the rtc via 
RTAS is not a frequent operation and probably also slow on real hardware I 
can live with the above QObject solution so just keep this patch for now. 
It's only used by Linux to access hardware clock anyway.

Regards,
BALATON Zoltan

>> However, you're maintainer for pegasos, so really it's your call -
>> applied, thanks.
>> 
>>> +        stl_be_phys(as, rets + 28, 0);
>>> +        qobject_unref(qo);
>>> +        return H_SUCCESS;
>>> +    }
>>>      case RTAS_READ_PCI_CONFIG:
>>>      {
>>>          uint32_t addr, len, val;
>> 
>> 
>