Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

arm_mpam: Probe the hardware features resctrl supports

Expand the probing support with the control and monitor types
we can use with resctrl.

CC: Dave Martin <Dave.Martin@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Fenghua Yu <fenghuay@nvidia.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>
Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Tested-by: Fenghua Yu <fenghuay@nvidia.com>
Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Tested-by: Peter Newman <peternewman@google.com>
Tested-by: Carl Worth <carl@os.amperecomputing.com>
Tested-by: Gavin Shan <gshan@redhat.com>
Tested-by: Zeng Heng <zengheng4@huawei.com>
Tested-by: Hanjun Guo <guohanjun@huawei.com>
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

James Morse and committed by
Catalin Marinas
8c90dc68 d02beb06

+182
+149
drivers/resctrl/mpam_devices.c
··· 170 170 171 171 #define mpam_write_partsel_reg(msc, reg, val) _mpam_write_partsel_reg(msc, MPAMCFG_##reg, val) 172 172 173 + static inline u32 _mpam_read_monsel_reg(struct mpam_msc *msc, u16 reg) 174 + { 175 + mpam_mon_sel_lock_held(msc); 176 + return __mpam_read_reg(msc, reg); 177 + } 178 + 179 + #define mpam_read_monsel_reg(msc, reg) _mpam_read_monsel_reg(msc, MSMON_##reg) 180 + 181 + static inline void _mpam_write_monsel_reg(struct mpam_msc *msc, u16 reg, u32 val) 182 + { 183 + mpam_mon_sel_lock_held(msc); 184 + __mpam_write_reg(msc, reg, val); 185 + } 186 + 187 + #define mpam_write_monsel_reg(msc, reg, val) _mpam_write_monsel_reg(msc, MSMON_##reg, val) 188 + 173 189 static u64 mpam_msc_read_idr(struct mpam_msc *msc) 174 190 { 175 191 u64 idr_high = 0, idr_low; ··· 564 548 return ERR_PTR(-ENOENT); 565 549 } 566 550 551 + /* 552 + * IHI009A.a has this nugget: "If a monitor does not support automatic behaviour 553 + * of NRDY, software can use this bit for any purpose" - so hardware might not 554 + * implement this - but it isn't RES0. 555 + * 556 + * Try and see what values stick in this bit. If we can write either value, 557 + * its probably not implemented by hardware. 558 + */ 559 + static bool _mpam_ris_hw_probe_hw_nrdy(struct mpam_msc_ris *ris, u32 mon_reg) 560 + { 561 + u32 now; 562 + u64 mon_sel; 563 + bool can_set, can_clear; 564 + struct mpam_msc *msc = ris->vmsc->msc; 565 + 566 + if (WARN_ON_ONCE(!mpam_mon_sel_lock(msc))) 567 + return false; 568 + 569 + mon_sel = FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, 0) | 570 + FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx); 571 + _mpam_write_monsel_reg(msc, mon_reg, mon_sel); 572 + 573 + _mpam_write_monsel_reg(msc, mon_reg, MSMON___NRDY); 574 + now = _mpam_read_monsel_reg(msc, mon_reg); 575 + can_set = now & MSMON___NRDY; 576 + 577 + _mpam_write_monsel_reg(msc, mon_reg, 0); 578 + now = _mpam_read_monsel_reg(msc, mon_reg); 579 + can_clear = !(now & MSMON___NRDY); 580 + mpam_mon_sel_unlock(msc); 581 + 582 + return (!can_set || !can_clear); 583 + } 584 + 585 + #define mpam_ris_hw_probe_hw_nrdy(_ris, _mon_reg) \ 586 + _mpam_ris_hw_probe_hw_nrdy(_ris, MSMON_##_mon_reg) 587 + 588 + static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) 589 + { 590 + int err; 591 + struct mpam_msc *msc = ris->vmsc->msc; 592 + struct device *dev = &msc->pdev->dev; 593 + struct mpam_props *props = &ris->props; 594 + 595 + lockdep_assert_held(&msc->probe_lock); 596 + lockdep_assert_held(&msc->part_sel_lock); 597 + 598 + /* Cache Portion partitioning */ 599 + if (FIELD_GET(MPAMF_IDR_HAS_CPOR_PART, ris->idr)) { 600 + u32 cpor_features = mpam_read_partsel_reg(msc, CPOR_IDR); 601 + 602 + props->cpbm_wd = FIELD_GET(MPAMF_CPOR_IDR_CPBM_WD, cpor_features); 603 + if (props->cpbm_wd) 604 + mpam_set_feature(mpam_feat_cpor_part, props); 605 + } 606 + 607 + /* Memory bandwidth partitioning */ 608 + if (FIELD_GET(MPAMF_IDR_HAS_MBW_PART, ris->idr)) { 609 + u32 mbw_features = mpam_read_partsel_reg(msc, MBW_IDR); 610 + 611 + /* portion bitmap resolution */ 612 + props->mbw_pbm_bits = FIELD_GET(MPAMF_MBW_IDR_BWPBM_WD, mbw_features); 613 + if (props->mbw_pbm_bits && 614 + FIELD_GET(MPAMF_MBW_IDR_HAS_PBM, mbw_features)) 615 + mpam_set_feature(mpam_feat_mbw_part, props); 616 + 617 + props->bwa_wd = FIELD_GET(MPAMF_MBW_IDR_BWA_WD, mbw_features); 618 + if (props->bwa_wd && FIELD_GET(MPAMF_MBW_IDR_HAS_MAX, mbw_features)) 619 + mpam_set_feature(mpam_feat_mbw_max, props); 620 + } 621 + 622 + /* Performance Monitoring */ 623 + if (FIELD_GET(MPAMF_IDR_HAS_MSMON, ris->idr)) { 624 + u32 msmon_features = mpam_read_partsel_reg(msc, MSMON_IDR); 625 + 626 + /* 627 + * If the firmware max-nrdy-us property is missing, the 628 + * CSU counters can't be used. Should we wait forever? 629 + */ 630 + err = device_property_read_u32(&msc->pdev->dev, 631 + "arm,not-ready-us", 632 + &msc->nrdy_usec); 633 + 634 + if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_CSU, msmon_features)) { 635 + u32 csumonidr; 636 + 637 + csumonidr = mpam_read_partsel_reg(msc, CSUMON_IDR); 638 + props->num_csu_mon = FIELD_GET(MPAMF_CSUMON_IDR_NUM_MON, csumonidr); 639 + if (props->num_csu_mon) { 640 + bool hw_managed; 641 + 642 + mpam_set_feature(mpam_feat_msmon_csu, props); 643 + 644 + /* Is NRDY hardware managed? */ 645 + hw_managed = mpam_ris_hw_probe_hw_nrdy(ris, CSU); 646 + if (hw_managed) 647 + mpam_set_feature(mpam_feat_msmon_csu_hw_nrdy, props); 648 + } 649 + 650 + /* 651 + * Accept the missing firmware property if NRDY appears 652 + * un-implemented. 653 + */ 654 + if (err && mpam_has_feature(mpam_feat_msmon_csu_hw_nrdy, props)) 655 + dev_err_once(dev, "Counters are not usable because not-ready timeout was not provided by firmware."); 656 + } 657 + if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_MBWU, msmon_features)) { 658 + bool hw_managed; 659 + u32 mbwumon_idr = mpam_read_partsel_reg(msc, MBWUMON_IDR); 660 + 661 + props->num_mbwu_mon = FIELD_GET(MPAMF_MBWUMON_IDR_NUM_MON, mbwumon_idr); 662 + if (props->num_mbwu_mon) 663 + mpam_set_feature(mpam_feat_msmon_mbwu, props); 664 + 665 + /* Is NRDY hardware managed? */ 666 + hw_managed = mpam_ris_hw_probe_hw_nrdy(ris, MBWU); 667 + if (hw_managed) 668 + mpam_set_feature(mpam_feat_msmon_mbwu_hw_nrdy, props); 669 + 670 + /* 671 + * Don't warn about any missing firmware property for 672 + * MBWU NRDY - it doesn't make any sense! 673 + */ 674 + } 675 + } 676 + } 677 + 567 678 static int mpam_msc_hw_probe(struct mpam_msc *msc) 568 679 { 569 680 u64 idr; ··· 734 591 mutex_unlock(&mpam_list_lock); 735 592 if (IS_ERR(ris)) 736 593 return PTR_ERR(ris); 594 + ris->idr = idr; 595 + 596 + mutex_lock(&msc->part_sel_lock); 597 + __mpam_part_sel(ris_idx, 0, msc); 598 + mpam_ris_hw_probe(ris); 599 + mutex_unlock(&msc->part_sel_lock); 737 600 } 738 601 739 602 spin_lock(&partid_max_lock);
+33
drivers/resctrl/mpam_internal.h
··· 5 5 #define MPAM_INTERNAL_H 6 6 7 7 #include <linux/arm_mpam.h> 8 + #include <linux/bitmap.h> 8 9 #include <linux/cpumask.h> 9 10 #include <linux/io.h> 10 11 #include <linux/llist.h> 11 12 #include <linux/mutex.h> 12 13 #include <linux/srcu.h> 13 14 #include <linux/spinlock.h> 15 + #include <linux/srcu.h> 14 16 #include <linux/types.h> 15 17 16 18 #define MPAM_MSC_MAX_NUM_RIS 16 ··· 114 112 raw_spin_lock_init(&msc->_mon_sel_lock); 115 113 } 116 114 115 + /* Bits for mpam features bitmaps */ 116 + enum mpam_device_features { 117 + mpam_feat_cpor_part, 118 + mpam_feat_mbw_part, 119 + mpam_feat_mbw_min, 120 + mpam_feat_mbw_max, 121 + mpam_feat_msmon, 122 + mpam_feat_msmon_csu, 123 + mpam_feat_msmon_csu_hw_nrdy, 124 + mpam_feat_msmon_mbwu, 125 + mpam_feat_msmon_mbwu_hw_nrdy, 126 + MPAM_FEATURE_LAST 127 + }; 128 + 129 + struct mpam_props { 130 + DECLARE_BITMAP(features, MPAM_FEATURE_LAST); 131 + 132 + u16 cpbm_wd; 133 + u16 mbw_pbm_bits; 134 + u16 bwa_wd; 135 + u16 num_csu_mon; 136 + u16 num_mbwu_mon; 137 + }; 138 + 139 + #define mpam_has_feature(_feat, x) test_bit(_feat, (x)->features) 140 + #define mpam_set_feature(_feat, x) set_bit(_feat, (x)->features) 141 + 117 142 struct mpam_class { 118 143 /* mpam_components in this class */ 119 144 struct list_head components; ··· 180 151 /* mpam_msc_ris in this vmsc */ 181 152 struct list_head ris; 182 153 154 + struct mpam_props props; 155 + 183 156 /* All RIS in this vMSC are members of this MSC */ 184 157 struct mpam_msc *msc; 185 158 ··· 193 162 194 163 struct mpam_msc_ris { 195 164 u8 ris_idx; 165 + u64 idr; 166 + struct mpam_props props; 196 167 197 168 cpumask_t affinity; 198 169