On Tue, Feb 23, 2021 at 11:19:38PM +1100, Alexey Kardashevskiy wrote:
> 
> 
> On 23/02/2021 14:07, David Gibson wrote:
> > On Tue, Feb 09, 2021 at 10:02:52PM +1100, Alexey Kardashevskiy wrote:
> > > The PAPR platform which describes an OS environment that's presented by
> > > a combination of a hypervisor and firmware. The features it specifies
> > > require collaboration between the firmware and the hypervisor.
> > > 
> 
> [...]
> 
> > > +target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState 
> > > *spapr,
> > > +                                target_ulong opcode, target_ulong *args)
> > > +{
> > > +    target_ulong of_client_args = ppc64_phys_to_real(args[0]);
> > > +    struct prom_args pargs = { 0 };
> > > +    char service[64];
> > > +    unsigned nargs, nret, i;
> > > +
> > > +    cpu_physical_memory_read(of_client_args, &pargs, sizeof(pargs));
> > 
> > Need to check for read errors in case an out of bounds address is passed.
> 
> 
> cpu_physical_memory_read() returns void and so does
> cpu_physical_memory_rw()

Sorry, I'd forgotten that was the case.

> but eventually called address_space_rw() returns an error code, should I
> switch to it?

Yes, I think that would be best.

> > > +    nargs = be32_to_cpu(pargs.nargs);
> > > +    if (nargs >= ARRAY_SIZE(pargs.args)) {
> > > +        return H_PARAMETER;
> > > +    }
> > > +
> > > +    cpu_physical_memory_read(be32_to_cpu(pargs.service), service,
> > > +                             sizeof(service));
> > > +    if (strnlen(service, sizeof(service)) == sizeof(service)) {
> > > +        /* Too long service name */
> > > +        return H_PARAMETER;
> > > +    }
> > > +
> > > +    for (i = 0; i < nargs; ++i) {
> > > +        pargs.args[i] = be32_to_cpu(pargs.args[i]);
> > 
> > In general I dislike in-place endian conversion of structs, since I
> > think it's less confusing to think of the endianness as a property of
> > the type.
> 
> The type is uint32_t and there is no be32 in QEMU. I can have 2 copies of
> pargs if this makes reviewing easier, should I?

Even having 2 copies of the struct I don't really like.  Encoding the
endianness down to the individual field level is great when the tools
are available, but as you note qemu doesn't really have that.

But even without that, I like the endianness of structs to be fixed by
convention.  Otherwise when you see a struct instance it's not very
easy to tell if it's a pre-conversion or post-conversion version at
any point in the code.  That means later changes - even just simple
looking code motions can become very fragile, because they move things
to a point where the struct doesn't have the previously expected
endianness.

By preferred solution here when using a struct which needs to map
directly onto in-memory information with a specific endianness is to
*always* leave the struct in that endianness, and only convert when we
actually take things in or out of the struct to use them in
calculations.

-- 
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

Attachment: signature.asc
Description: PGP signature

Reply via email to