|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 2/2] x86/spec-ctrl: add support for modifying SSBD VIA LS_CFG MSR
On Wed, Aug 15, 2018 at 10:00:48AM -0600, Jan Beulich wrote:
> >>> On 09.08.18 at 21:42, <brian.woods@xxxxxxx> wrote:
> > --- a/xen/arch/x86/cpu/amd.c
> > +++ b/xen/arch/x86/cpu/amd.c
> > @@ -611,14 +611,9 @@ static void init_amd(struct cpuinfo_x86 *c)
> > ssbd_amd_ls_cfg_mask = 1ull << bit;
> > }
> >
> > - if (ssbd_amd_ls_cfg_mask && !rdmsr_safe(MSR_AMD64_LS_CFG, value)) {
> > + if (ssbd_amd_ls_cfg_mask && !rdmsr_safe(MSR_AMD64_LS_CFG, value))
> > if (!boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG))
> > setup_force_cpu_cap(X86_FEATURE_SSBD_AMD_LS_CFG);
>
> If the inner if() was not to go away altogether in patch 1, please
> fold two successive if()-s like these.
>
> > --- a/xen/arch/x86/spec_ctrl.c
> > +++ b/xen/arch/x86/spec_ctrl.c
>
> First of all - I'm not convinced some of the AMD specific code here
> wouldn't better live in cpu/amd.c.
Well, by that logic, a lot of the other logic could go in cpu/intel.c.
It has to do with SSBD and when AMD's processors support it via the
SPEC_CTRL MSR, the support for SSBD will get merged together in
spec_ctrl.c and if that's the case, it makes sense to have all the SSBD
code together. IMO
> > @@ -50,7 +51,16 @@ bool __initdata bsp_delay_spec_ctrl;
> > uint8_t __read_mostly default_xen_spec_ctrl;
> > uint8_t __read_mostly default_spec_ctrl_flags;
> >
> > +/* for SSBD support for AMD via LS_CFG */
> > +#define SSBD_AMD_MAX_SOCKET 2
> > +struct ssbd_amd_ls_cfg_smt_status {
> > + spinlock_t lock;
> > + uint32_t mask;
> > +} __attribute__ ((aligned (64)));
>
> Where's this literal 64 coming from? Do you perhaps mean
> SMP_CACHE_BYTES? And if this is really needed (as said before,
> I think the array would better be dynamically allocated than having
> compile time determined fixed size), then please don't open-code
> __aligned().
It's the cache coherency size. The SMP_CACHE_BYTES is 128 bytes IIRC.
I was trying to save space since the struct is so small it would double
the size. That can be changed though.
> > +bool __read_mostly ssbd_amd_smt_en = false;
> > +bool __read_mostly default_xen_ssbd_amd_ls_cfg_en = false;
> > uint64_t __read_mostly ssbd_amd_ls_cfg_mask = 0ull;
> > +struct ssbd_amd_ls_cfg_smt_status
> > *ssbd_amd_smt_status[SSBD_AMD_MAX_SOCKET] = {NULL};
>
> Several further pointless initializers.
ssbd_amd_ls_cfg_mask -> needs to be initialized, due to how it gets set
ssbd_amd_ls_cfg_smt_status -> needs to be initialized, unless xalloc
sets it as NULL on failure to alloc
default_xen_ssbd_amd_ls_cfg_en -> needs to be initialized of an else
added to an if statement
ssbd_amd_smt_en -> like the above
If you want default_xen_ssbd_amd_ls_cfg_en and ssbd_amd_smt_en to be
not be initialized, I can add code to do that.
> > +static void ssbd_amd_ls_cfg_set_smt(bool enable_ssbd)
> > +{
> > + uint32_t socket, core, thread;
> > + uint64_t enable_mask;
> > + uint64_t ls_cfg;
> > + struct ssbd_amd_ls_cfg_smt_status *status;
> > + const struct cpuinfo_x86 *c = ¤t_cpu_data;
> > +
> > + socket = c->phys_proc_id;
> > + core = c->cpu_core_id;
> > + thread = c->apicid & (c->x86_num_siblings - 1);
> > + status = ssbd_amd_smt_status[socket] + core;
> > + enable_mask = (1ull << thread);
> > +
> > + spin_lock(&status->lock);
> > +
> > + if ( enable_ssbd )
> > + {
> > + if ( !(status->mask & enable_mask) )
>
> So with ->mask being uint32_t, why does enable_mask need to be
> uint64_t? Even uint32_t seems way more than needed, but there's
> certainly no point going below this. Just that, as expressed before,
> you should please use "unsigned int" in favor of uint32_t everywhere,
> unless you really need something that's exactly 32-bits wide.
Because when changing the variable types from __32 etc, I confused it
with the enable mask for the LS_CFG reg. I'll change them.
> > + {
> > + status->mask |= enable_mask;
> > + rdmsrl(MSR_AMD64_LS_CFG, ls_cfg);
> > + if ( !(ls_cfg & ssbd_amd_ls_cfg_mask) )
> > + {
> > + ls_cfg |= ssbd_amd_ls_cfg_mask;
> > + wrmsrl(MSR_AMD64_LS_CFG, ls_cfg);
> > + }
> > + }
> > + }
> > + else
> > + {
> > + if ( status->mask & enable_mask )
> > + {
> > + status->mask &= ~enable_mask;
> > + rdmsrl(MSR_AMD64_LS_CFG, ls_cfg);
> > + if ( (ls_cfg & ssbd_amd_ls_cfg_mask) && (status->mask == 0) )
>
> Please prefer the shorter ! over " == 0".
>
> > + {
> > + ls_cfg &= ~ssbd_amd_ls_cfg_mask;
> > + wrmsrl(MSR_AMD64_LS_CFG, ls_cfg);
> > + }
> > + }
> > + }
> > +
> > + spin_unlock(&status->lock);
> > +}
> > +
> > +void ssbd_amd_ls_cfg_set(bool enable_ssbd)
> > +{
> > + if ( !ssbd_amd_ls_cfg_mask ||
> > + !boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG) ) {
> > + dprintk(XENLOG_ERR, "SSBD AMD LS CFG: invalid mask or missing
> > feature\n");
>
> If the plan is for the function to also be called at runtime eventually,
> this dprintk() needs to go away.
>
> > + return;
> > + }
> > +
> > + if ( ssbd_amd_smt_en )
> > + ssbd_amd_ls_cfg_set_smt(enable_ssbd);
> > + else
> > + ssbd_amd_ls_cfg_set_nonsmt(enable_ssbd);
> > +}
> > +
> > +static int __init ssbd_amd_ls_cfg_init(void)
> > +{
> > + uint32_t cores_per_socket, threads_per_core;
> > + const struct cpuinfo_x86 *c = &boot_cpu_data;
> > + uint32_t core, socket;
> > +
> > + if ( !ssbd_amd_ls_cfg_mask ||
> > + !boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG) )
> > + goto ssbd_amd_ls_cfg_init_fail;
>
> Why not simply "return"?
Because it forces all the failed returns down one code path. I can
change it if you wish.
> > + switch ( c->x86 )
> > + {
> > + case 0x15:
> > + case 0x16:
> > + break;
> > +
> > + case 0x17:
> > + cores_per_socket = c->x86_max_cores;
> > + threads_per_core = c->x86_num_siblings;
> > +
> > + if ( threads_per_core > 1 )
> > + {
> > + ssbd_amd_smt_en = true;
> > + for ( socket = 0; socket < SSBD_AMD_MAX_SOCKET; socket++ )
> > + {
> > + ssbd_amd_smt_status[socket] =
> > + (struct ssbd_amd_ls_cfg_smt_status *)
> > + xmalloc_array(struct ssbd_amd_ls_cfg_smt_status,
> > + cores_per_socket);
>
> Pointless cast.
>
> > + if ( ssbd_amd_smt_status[socket] == NULL )
> > + {
> > + dprintk(XENLOG_ERR,
> > + "SSBD AMD LS CFG: error in status allocing\n");
> > + goto ssbd_amd_ls_cfg_init_fail;
> > + }
> > + }
> > +
> > + for ( socket = 0; socket < SSBD_AMD_MAX_SOCKET; socket++ )
> > + {
> > + for ( core = 0; core < cores_per_socket; core++ )
> > + {
> > +
> > spin_lock_init(&ssbd_amd_smt_status[socket][core].lock);
> > + ssbd_amd_smt_status[socket][core].mask = 0;
> > + }
> > + }
> > + }
> > + break;
> > +
> > + default:
> > + goto ssbd_amd_ls_cfg_init_fail;
> > + }
> > +
> > + if ( default_xen_ssbd_amd_ls_cfg_en )
> > + ssbd_amd_ls_cfg_set(true);
> > +
> > + return 0;
> > +
> > + ssbd_amd_ls_cfg_init_fail:
> > + for ( socket = 0; socket < SSBD_AMD_MAX_SOCKET; socket++ )
> > + if ( ssbd_amd_smt_status[socket] != NULL )
> > + xfree(ssbd_amd_smt_status[socket]);
>
> There's no need for the if() here.
>
> > + setup_clear_cpu_cap(X86_FEATURE_SSBD_AMD_LS_CFG);
>
> The same feature must not first be forced, and the cleared. Please
> take a look at the implementation of the functions.
Will do.
> > + default_xen_ssbd_amd_ls_cfg_en = false;
> > +
> > + dprintk(XENLOG_ERR, "SSBD AMD LS CFG: disalbing SSBD due to errors\n");
> > +
> > + return 1;
>
> If the function returns 0 and 1 only, it looks like you've meant to
> use bool, false, and true respectively.
>
> Jan
>
Because it's more of an error code than boolean logic value. I can
switch it over to bool if you want.
Noted about the things I didn't directly reply to.
--
Brian Woods
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |