Re: [PATCH v2 2/4] x86/split_lock: Align x86_capability to unsigned long to avoid split locked access

From: Thomas Gleixner
Date: Sat Jun 30 2018 - 02:24:57 EST


On Fri, 29 Jun 2018, Fenghua Yu wrote:
> On Fri, Jun 29, 2018 at 05:00:51PM -0700, Fenghua Yu wrote:

> diff --git a/arch/x86/boot/cpuflags.h b/arch/x86/boot/cpuflags.h
> index 2e20814d3ce3..29de0ff74351 100644
> --- a/arch/x86/boot/cpuflags.h
> +++ b/arch/x86/boot/cpuflags.h
> @@ -9,7 +9,7 @@ struct cpu_features {
> int level; /* Family, or 64 for x86-64 */
> int family; /* Family, always */
> int model;
> - u32 flags[NCAPINTS];
> + u32 flags[NCAPINTS] __aligned(sizeof(unsigned long));

Lacks a comment WHY this needs the aligned() as Dave already said.

> };
>
> extern struct cpu_features cpu;
> diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
> index 8c7b3e5a2d01..444a2275c1f8 100644
> --- a/arch/x86/include/asm/mce.h
> +++ b/arch/x86/include/asm/mce.h
> @@ -133,7 +133,7 @@ struct mce_log_buffer {
> char signature[12]; /* "MACHINECHECK" */
> unsigned len; /* = MCE_LOG_LEN */
> unsigned next;
> - unsigned flags;
> + unsigned flags __aligned(sizeof(unsigned long));

And whats wrong with just making that flags field unsigned long and move it
behind recordlen?

flags is at offset 20 so forcing alignement puts it at offset 24 creating a
4 byte hole. While reordering it and making it type unsigned long just
fills the already existing hole and just works w/o the stray aligned()

struct mce_log_buffer {
char signature[12]; /* 0 12 */
unsigned int len; /* 12 4 */
unsigned int next; /* 16 4 */
unsigned int flags; /* 20 4 */
unsigned int recordlen; /* 24 4 */

/* XXX 4 bytes hole, try to pack */

struct mce entry[32]; /* 32 3840 */

The point is, that there is no requirement that flags is unsigned int,
while the u32 type for the capability array has a reason.

So you need to analyse first whether the data type is required or can be
changed to unsigned long which is the right thing to do.

See?

Thanks,

tglx