Re: [PATCH 1/6] perf: Add new type PERF_TYPE_PROBE

From: Alexei Starovoitov
Date: Sat Nov 25 2017 - 21:01:25 EST


On 11/24/17 12:28 AM, Peter Zijlstra wrote:
On Thu, Nov 23, 2017 at 10:31:29PM -0800, Alexei Starovoitov wrote:
unfortunately 32-bit is more screwed than it seems:

$ cat align.c
#include <stdio.h>

struct S {
unsigned long long a;
} s;

struct U {
unsigned long long a;
} u;

int main()
{
printf("%d, %d\n", sizeof(unsigned long long),
__alignof__(unsigned long long));
printf("%d, %d\n", sizeof(s), __alignof__(s));
printf("%d, %d\n", sizeof(u), __alignof__(u));
}
$ gcc -m32 align.c
$ ./a.out
8, 8
8, 4
8, 4

*blink* how is that even correct? I understood the spec to say the
alignment of composite types should be the max alignment of any of its
member types (otherwise it cannot guarantee the alignment of its
members).

so we have to use __aligned_u64 in uapi.

Ideally yes, but effectively it most often doesn't matter.

Otherwise, yes, we could have used config1 and config2 to pass pointers
to the kernel, but since they're defined as __u64 already we cannot
change them and have to do this ugly dance around 'config' field.

I don't understand the reasoning why you cannot use them. Even if they
are not naturally aligned on x86_32, why would it matter?

x86_32 needs two loads in any case, but there is no concurrency, so
split loads is not a problem. Add to that that 'intptr_t' on ILP32
is in fact only a single u32 and thus the other u32 will always be 0.

So yes, alignment is screwy, but I really don't see who cares and why it
would matter in practise.

If we were poking into 'struct perf_event_attr __user *uptr'
directly like get|put_user(.., &uptr->config)
then 32-bit user space with 4-byte aligned u64s would cause
64-bit kernel to trap on archs like sparc.
But in this case you're right. We can use config[12] as-is, since these
u64 fields are passing the value one way only (into the kernel) and
we do full perf_copy_attr() first and all further accesses are from
copied structure and u64_to_user_ptr(event->attr.config) will be fine.

Do you mind we do
union {
__u64 file_path;
__u64 func_name;
__u64 config;
};
and similar with config1 ?
Or prefer that we use 'config/config1' to store string+offset there?
I think config/config1 is cleaner than config1/config2