[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v9 10/25] x86: refactor psr: L3 CAT: set value: assemble features value array.
>>> On 16.03.17 at 12:08, <yi.y.sun@xxxxxxxxxxxxxxx> wrote: > --- a/xen/arch/x86/psr.c > +++ b/xen/arch/x86/psr.c > @@ -101,6 +101,28 @@ struct feat_node { > /* get_val is used to get feature COS register value. */ > void (*get_val)(const struct feat_node *feat, unsigned int cos, > enum cbm_type type, uint32_t *val); > + > + /* > + * get_old_val and set_new_val are a pair of functions called in > order. > + * The caller will traverse all features in the array and call > + * 'get_old_val' to get old_cos register value of all supported > + * features. Then, call 'set_new_val' to set the new value for the > + * designated feature. > + * > + * All the values are set into value array according to the traversal > + * order, meaning the same order of feature array members. > + * > + * The return value meaning of set_new_val: > + * 0 - success. > + * negative - error. > + */ > + void (*get_old_val)(uint32_t val[], > + const struct feat_node *feat, > + unsigned int old_cos); > + int (*set_new_val)(uint32_t val[], > + const struct feat_node *feat, > + enum cbm_type type, > + uint32_t new_val); Along the lines of an earlier comment - are "old" and "new" really meaningful here? > @@ -212,6 +234,29 @@ static enum psr_feat_type psr_cbm_type_to_feat_type(enum > cbm_type type) > } > > /* CAT common functions implementation. */ > +static bool psr_check_cbm(unsigned int cbm_len, uint32_t cbm) > +{ > + unsigned int first_bit, zero_bit; > + > + /* Set bits should only in the range of [0, cbm_len]. */ > + if ( cbm & (~0ul << cbm_len) ) Same question as elsewhere about the use of the ul suffix here: Can cbm_len really be any value in [0,32]? If not, I don't see why the calculation needs to be done as unsigned long. Otoh ... > + return false; > + > + /* At least one bit need to be set. */ > + if ( cbm == 0 ) > + return false; > + > + first_bit = find_first_bit((uint64_t *)&cbm, cbm_len); > + zero_bit = find_next_zero_bit((uint64_t *)&cbm, cbm_len, first_bit); ... these bogus casts suggest that the function would best have an "unsigned long" parameter. > @@ -285,11 +330,35 @@ static void cat_get_val(const struct feat_node *feat, > unsigned int cos, > *val = feat->cos_reg_val[cos]; > } > > +/* val[] len checking is done by caller. */ > +static void cat_get_old_val(uint32_t val[], > + const struct feat_node *feat, > + unsigned int old_cos) > +{ > + cat_get_val(feat, old_cos, 0, &val[0]); > +} > + > +/* val[] len checking is done by caller. */ > +static int cat_set_new_val(uint32_t val[], > + const struct feat_node *feat, > + enum cbm_type type, > + uint32_t new_val) > +{ > + if ( !psr_check_cbm(feat->info.cat_info.cbm_len, new_val) ) > + return -EINVAL; > + > + val[0] = new_val; > + > + return 0; > +} > + > /* L3 CAT ops */ > static const struct feat_ops l3_cat_ops = { > .get_cos_max = cat_get_cos_max, > .get_feat_info = cat_get_feat_info, > .get_val = cat_get_val, > + .get_old_val = cat_get_old_val, > + .set_new_val = cat_set_new_val, > }; > > static void __init parse_psr_bool(char *s, char *value, char *feature, > @@ -581,7 +650,21 @@ int psr_get_val(struct domain *d, unsigned int socket, > /* Set value functions */ > static unsigned int get_cos_num(const struct psr_socket_info *info) > { > - return 0; > + const struct feat_node *feat; > + unsigned int num = 0, i; > + > + /* Get all features total amount. */ > + for ( i = 0; i < PSR_SOCKET_MAX_FEAT; i++ ) > + { > + if ( !info->features[i] ) > + continue; > + > + feat = info->features[i]; > + > + num += feat->cos_num; > + } > + > + return num; > } > > static int gather_val_array(uint32_t val[], > @@ -589,7 +672,34 @@ static int gather_val_array(uint32_t val[], > const struct psr_socket_info *info, > unsigned int old_cos) > { > - return -EINVAL; > + const struct feat_node *feat; > + unsigned int i; > + > + if ( !val ) > + return -EINVAL; > + > + /* Get all features current values according to old_cos. */ > + for ( i = 0; i < PSR_SOCKET_MAX_FEAT; i++ ) > + { > + if ( !info->features[i] ) > + continue; > + > + feat = info->features[i]; > + > + if ( old_cos > feat->ops.get_cos_max(feat) ) > + old_cos = 0; > + > + /* value getting order is same as feature array */ > + feat->ops.get_old_val(val, feat, old_cos); > + > + array_len -= feat->cos_num; So this I should really have asked about on a much earlier patch, but I've recognize the oddity only now: Why is cos_num per-feature-node instead of per-feature? This should really be a field in struct feat_ops (albeit the name "ops" then will be slightly misleading, but I think that's tolerable if you can't think of a better name). > + if ( array_len < 0 ) > + return -ENOSPC; This check needs doing earlier - you need to make sure array_len >= ops.cos_num prior to calling ops.get_old_val(). (Doing the check after the subtraction even causes wrapping issues, which are even more visible in similar code further down.) > @@ -599,7 +709,43 @@ static int insert_new_val_to_array(uint32_t val[], > enum cbm_type type, > uint32_t new_val) > { > - return -EINVAL; > + const struct feat_node *feat; > + int ret; > + unsigned int i; > + > + ASSERT(feat_type < PSR_SOCKET_MAX_FEAT); > + > + /* Set new value into array according to feature's position in array. */ > + for ( i = 0; i < feat_type; i++ ) > + { > + if ( !info->features[i] ) > + continue; > + > + feat = info->features[i]; > + > + array_len -= feat->cos_num; > + if ( array_len <= 0 ) > + return -ENOSPC; > + > + val += feat->cos_num; > + } > + > + feat = info->features[feat_type]; > + > + array_len -= feat->cos_num; > + if ( array_len < 0 ) > + return -ENOSPC; > + > + /* > + * Value setting position is same as feature array. > + * Different features may have different setting behaviors, e.g. CDP > + * has two values (DATA/CODE) which need us to save input value to > + * different position in the array according to type, so we have to > + * maintain a callback function. > + */ > + ret = feat->ops.set_new_val(val, feat, type, new_val); > + > + return ret; Again a case of a pointless intermediate variable. Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |