Messages in this thread | | | Subject | Re: [PATCH] perfcounters: fix type/event_id layout on big-endian systems | From | Peter Zijlstra <> | Date | Sat, 21 Mar 2009 11:24:30 +0100 |
| |
On Sat, 2009-03-21 at 15:53 +1100, Paul Mackerras wrote: > Impact: build fix for powerpc > > Commit db3a944aca35ae61 ("perf_counter: revamp syscall input ABI") > expanded the hw_event.type field into a union of structs containing > bitfields. In particular it introduced a type field and a raw_type > field, with the intention that the 1-bit raw_type field should > overlay the most-significant bit of the 8-bit type field, and in fact > perf_counter_alloc() now assumes that (or at least, assumes that > raw_type doesn't overlay any of the bits that are 1 in the values of > PERF_TYPE_{HARDWARE,SOFTWARE,TRACEPOINT}). > > Unfortunately this is not true on big-endian systems such as PowerPC, > where bitfields are laid out from left to right, i.e. from most > significant bit to least significant. This means that setting > hw_event.type = PERF_TYPE_SOFTWARE will set hw_event.raw_type to 1. > > This fixes it by making the layout depend on whether or not > __BIG_ENDIAN_BITFIELD is defined. It's a bit ugly, but that's what > we get for using bitfields in a user/kernel ABI.
Hmm, does userspace know about __BIG_ENDIAN_BITFIELD too? If not, we've got ourselves a problem here.
Sorry about missing those powerpc bits, I guess I should dust-off the cross-compiler.
> diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h > index a4b76c0..98f5990 100644 > --- a/include/linux/perf_counter.h > +++ b/include/linux/perf_counter.h > @@ -15,6 +15,7 @@ > > #include <linux/types.h> > #include <linux/ioctl.h> > +#include <asm/byteorder.h> > > /* > * User-space ABI bits: > @@ -86,6 +87,7 @@ enum perf_counter_record_type { > */ > struct perf_counter_hw_event { > union { > +#ifndef __BIG_ENDIAN_BITFIELD > struct { > __u64 event_id : 56, > type : 8; > @@ -94,6 +96,16 @@ struct perf_counter_hw_event { > __u64 raw_event_id : 63, > raw_type : 1; > }; > +#else > + struct { > + __u64 type : 8, > + event_id : 56; > + }; > + struct { > + __u64 raw_type : 1, > + raw_event_id : 63; > + }; > +#endif /* __BIT_ENDIAN_BITFIELD */ > __u64 event_config; > }; >
| |