On 8/15/2024 12:58 AM, Paul Menzel wrote:
> Dear Paul,
>
>
> Thank you for the patch.
>
> Am 13.08.24 um 00:15 schrieb Paul Greenwalt:
>> E830 adds hardware support to prevent the VF from overflowing the PF
>> mailbox with VIRTCHNL messages. E830 will use the hardware feature
>> (ICE_F_MBX_LIMIT) instead of the software solution ice_is_malicious_vf().
>
> What is the benefit? Less CPU cycles used? Any measurements, how much
> CPU it uses?
>
The hardware solution reduces complexity in the driver, and it’s more
robust than the software solution. The software solution will detect and
log when the VFs outstanding messages to a PF exceeds the threshold. The
hardware solution blocks the messages from the VF to the PF when the
threshold is exceeded.
>> To prevent a VF from overflowing the PF, the PF sets the number of
>> messages per VF that can be in the PF's mailbox queue
>> (ICE_MBX_OVERFLOW_WATERMARK). When the PF process a message from a VF,
>
> process*es*?
>
I will make this change in the commit message.
>> the PF decrements the per VF message count using the E830_MBX_VF_DEC_TRIG
>> register.
>
> Is there an error shown, once such a malicious situation occurs?
>
There is no PF error message when the hardware blocks the VF messages,
but the VF will generate messages related to the failed communication
with the PF.
> It’d be great, if you could documents ways how to test this.
>
It’s difficult to reproduce this issue since this is unlikely to occur
under normal circumstances.
Thanks,
Paul
>
> Kind regards,
>
> Paul
>
>
>> Signed-off-by: Paul Greenwalt <[email protected]>
>> ---
>> v1 -> v2:
>> - Update ice_mbx_vf_dec_trig_e830 and ice_mbx_vf_clear_cnt_e830 onstack
>> variables to const
>> v2 -> v3:
>> - Fix indentation and remove unnessary paranthes in macro
>> - Replace ice_init_feature_support() E830 device id check with MAC
>> check
>> - Remove use of const for scalars
>> ---
>> drivers/net/ethernet/intel/ice/ice.h | 1 +
>> .../net/ethernet/intel/ice/ice_hw_autogen.h | 3 ++
>> drivers/net/ethernet/intel/ice/ice_lib.c | 15 +++++++++
>> drivers/net/ethernet/intel/ice/ice_main.c | 24 ++++++++++----
>> drivers/net/ethernet/intel/ice/ice_sriov.c | 3 +-
>> drivers/net/ethernet/intel/ice/ice_vf_lib.c | 26 +++++++++++++--
>> drivers/net/ethernet/intel/ice/ice_vf_mbx.c | 32 +++++++++++++++++++
>> drivers/net/ethernet/intel/ice/ice_vf_mbx.h | 3 ++
>> drivers/net/ethernet/intel/ice/ice_virtchnl.c | 8 +++--
>> 9 files changed, 102 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/ice/ice.h
>> b/drivers/net/ethernet/intel/ice/ice.h
>> index d6f80da30dec..53082b619fc3 100644
>> --- a/drivers/net/ethernet/intel/ice/ice.h
>> +++ b/drivers/net/ethernet/intel/ice/ice.h
>> @@ -207,6 +207,7 @@ enum ice_feature {
>> ICE_F_GNSS,
>> ICE_F_ROCE_LAG,
>> ICE_F_SRIOV_LAG,
>> + ICE_F_MBX_LIMIT,
>> ICE_F_MAX
>> };
>> diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
>> b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
>> index 91cbae1eec89..8d31bfe28cc8 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
>> +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
>> @@ -539,5 +539,8 @@
>> #define E830_PRTMAC_CL01_QNT_THR_CL0_M GENMASK(15, 0)
>> #define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4))
>> #define VFINT_DYN_CTLN_CLEARPBA_M BIT(1)
>> +#define E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH 0x00234000
>> +#define E830_MBX_VF_DEC_TRIG(_VF) (0x00233800 + (_VF) * 4)
>> +#define E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(_VF) (0x00233000 +
>> (_VF) * 4)
>> #endif /* _ICE_HW_AUTOGEN_H_ */
>> diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c
>> b/drivers/net/ethernet/intel/ice/ice_lib.c
>> index d9c34d28c9cd..2c55209d3ce2 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_lib.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_lib.c
>> @@ -3877,9 +3877,24 @@ void ice_init_feature_support(struct ice_pf *pf)
>> if (ice_gnss_is_gps_present(&pf->hw))
>> ice_set_feature_support(pf, ICE_F_GNSS);
>> break;
>> + case ICE_DEV_ID_E830CC_BACKPLANE:
>> + case ICE_DEV_ID_E830CC_QSFP56:
>> + case ICE_DEV_ID_E830CC_SFP:
>> + case ICE_DEV_ID_E830CC_SFP_DD:
>> + case ICE_DEV_ID_E830C_BACKPLANE:
>> + case ICE_DEV_ID_E830C_QSFP:
>> + case ICE_DEV_ID_E830C_SFP:
>> + case ICE_DEV_ID_E830_XXV_BACKPLANE:
>> + case ICE_DEV_ID_E830_XXV_QSFP:
>> + case ICE_DEV_ID_E830_XXV_SFP:
>> + ice_set_feature_support(pf, ICE_F_MBX_LIMIT);
>> + break;
>> default:
>> break;
>> }
>> +
>> + if (pf->hw.mac_type == ICE_MAC_E830)
>> + ice_set_feature_support(pf, ICE_F_MBX_LIMIT);
>> }
>> /**
>> diff --git a/drivers/net/ethernet/intel/ice/ice_main.c
>> b/drivers/net/ethernet/intel/ice/ice_main.c
>> index fd27c7995d60..12ce5d2283d3 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_main.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_main.c
>> @@ -1542,12 +1542,20 @@ static int __ice_clean_ctrlq(struct ice_pf
>> *pf, enum ice_ctl_q q_type)
>> ice_vf_lan_overflow_event(pf, &event);
>> break;
>> case ice_mbx_opc_send_msg_to_pf:
>> - data.num_msg_proc = i;
>> - data.num_pending_arq = pending;
>> - data.max_num_msgs_mbx = hw->mailboxq.num_rq_entries;
>> - data.async_watermark_val = ICE_MBX_OVERFLOW_WATERMARK;
>> + if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) {
>> + ice_vc_process_vf_msg(pf, &event, NULL);
>> + ice_mbx_vf_dec_trig_e830(hw, &event);
>> + } else {
>> + u16 val = hw->mailboxq.num_rq_entries;
>> +
>> + data.max_num_msgs_mbx = val;
>> + val = ICE_MBX_OVERFLOW_WATERMARK;
>> + data.async_watermark_val = val;
>> + data.num_msg_proc = i;
>> + data.num_pending_arq = pending;
>> - ice_vc_process_vf_msg(pf, &event, &data);
>> + ice_vc_process_vf_msg(pf, &event, &data);
>> + }
>> break;
>> case ice_aqc_opc_fw_logs_event:
>> ice_get_fwlog_data(pf, &event);
>> @@ -4078,7 +4086,11 @@ static int ice_init_pf(struct ice_pf *pf)
>> mutex_init(&pf->vfs.table_lock);
>> hash_init(pf->vfs.table);
>> - ice_mbx_init_snapshot(&pf->hw);
>> + if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
>> + wr32(&pf->hw, E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH,
>> + ICE_MBX_OVERFLOW_WATERMARK);
>> + else
>> + ice_mbx_init_snapshot(&pf->hw);
>> xa_init(&pf->dyn_ports);
>> xa_init(&pf->sf_nums);
>> diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c
>> b/drivers/net/ethernet/intel/ice/ice_sriov.c
>> index e34fe2516ccc..e7b5fe553d1f 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_sriov.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
>> @@ -194,7 +194,8 @@ void ice_free_vfs(struct ice_pf *pf)
>> }
>> /* clear malicious info since the VF is getting released */
>> - list_del(&vf->mbx_info.list_entry);
>> + if (!ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
>> + list_del(&vf->mbx_info.list_entry);
>> mutex_unlock(&vf->cfg_lock);
>> }
>> diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
>> b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
>> index a69e91f88d81..d618292dfe27 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
>> @@ -709,6 +709,23 @@ ice_vf_clear_vsi_promisc(struct ice_vf *vf,
>> struct ice_vsi *vsi, u8 promisc_m)
>> return 0;
>> }
>> +/**
>> + * ice_reset_vf_mbx_cnt - reset VF mailbox message count
>> + * @vf: pointer to the VF structure
>> + *
>> + * This function clears the VF mailbox message count, and should be
>> called on
>> + * VF reset.
>> + */
>> +static void ice_reset_vf_mbx_cnt(struct ice_vf *vf)
>> +{
>> + struct ice_pf *pf = vf->pf;
>> +
>> + if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
>> + ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id);
>> + else
>> + ice_mbx_clear_malvf(&vf->mbx_info);
>> +}
>> +
>> /**
>> * ice_reset_all_vfs - reset all allocated VFs in one go
>> * @pf: pointer to the PF structure
>> @@ -735,7 +752,7 @@ void ice_reset_all_vfs(struct ice_pf *pf)
>> /* clear all malicious info if the VFs are getting reset */
>> ice_for_each_vf(pf, bkt, vf)
>> - ice_mbx_clear_malvf(&vf->mbx_info);
>> + ice_reset_vf_mbx_cnt(vf);
>> /* If VFs have been disabled, there is no need to reset */
>> if (test_and_set_bit(ICE_VF_DIS, pf->state)) {
>> @@ -951,7 +968,7 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
>> ice_eswitch_update_repr(&vf->repr_id, vsi);
>> /* if the VF has been reset allow it to come up again */
>> - ice_mbx_clear_malvf(&vf->mbx_info);
>> + ice_reset_vf_mbx_cnt(vf);
>> out_unlock:
>> if (lag && lag->bonded && lag->primary &&
>> @@ -1004,7 +1021,10 @@ void ice_initialize_vf_entry(struct ice_vf *vf)
>> ice_vf_fdir_init(vf);
>> /* Initialize mailbox info for this VF */
>> - ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info);
>> + if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
>> + ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id);
>> + else
>> + ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info);
>> mutex_init(&vf->cfg_lock);
>> }
>> diff --git a/drivers/net/ethernet/intel/ice/ice_vf_mbx.c
>> b/drivers/net/ethernet/intel/ice/ice_vf_mbx.c
>> index 40cb4ba0789c..75c8113e58ee 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_vf_mbx.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_vf_mbx.c
>> @@ -210,6 +210,38 @@ ice_mbx_detect_malvf(struct ice_hw *hw, struct
>> ice_mbx_vf_info *vf_info,
>> return 0;
>> }
>> +/**
>> + * ice_mbx_vf_dec_trig_e830 - Decrements the VF mailbox queue counter
>> + * @hw: pointer to the HW struct
>> + * @event: pointer to the control queue receive event
>> + *
>> + * This function triggers to decrement the counter
>> + * MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT when the driver replenishes
>> + * the buffers at the PF mailbox queue.
>> + */
>> +void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
>> + const struct ice_rq_event_info *event)
>> +{
>> + u16 vfid = le16_to_cpu(event->desc.retval);
>> +
>> + wr32(hw, E830_MBX_VF_DEC_TRIG(vfid), 1);
>> +}
>> +
>> +/**
>> + * ice_mbx_vf_clear_cnt_e830 - Clear the VF mailbox queue count
>> + * @hw: pointer to the HW struct
>> + * @vf_id: VF ID in the PF space
>> + *
>> + * This function clears the counter MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT,
>> and should
>> + * be called when a VF is created and on VF reset.
>> + */
>> +void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id)
>> +{
>> + u32 reg = rd32(hw, E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(vf_id));
>> +
>> + wr32(hw, E830_MBX_VF_DEC_TRIG(vf_id), reg);
>> +}
>> +
>> /**
>> * ice_mbx_vf_state_handler - Handle states of the overflow algorithm
>> * @hw: pointer to the HW struct
>> diff --git a/drivers/net/ethernet/intel/ice/ice_vf_mbx.h
>> b/drivers/net/ethernet/intel/ice/ice_vf_mbx.h
>> index 44bc030d17e0..edcd9332368c 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_vf_mbx.h
>> +++ b/drivers/net/ethernet/intel/ice/ice_vf_mbx.h
>> @@ -19,6 +19,9 @@ ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid,
>> u32 v_opcode, u32 v_retval,
>> u8 *msg, u16 msglen, struct ice_sq_cd *cd);
>> u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16
>> link_speed);
>> +void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
>> + const struct ice_rq_event_info *event);
>> +void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id);
>> int
>> ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data
>> *mbx_data,
>> struct ice_mbx_vf_info *vf_info, bool *report_malvf);
>> diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
>> b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
>> index 59f62306b9cb..3c86d0c2fe1f 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
>> @@ -4009,8 +4009,10 @@ ice_is_malicious_vf(struct ice_vf *vf, struct
>> ice_mbx_data *mbxdata)
>> * @event: pointer to the AQ event
>> * @mbxdata: information used to detect VF attempting mailbox overflow
>> *
>> - * called from the common asq/arq handler to
>> - * process request from VF
>> + * Called from the common asq/arq handler to process request from VF.
>> When this
>> + * flow is used for devices with hardware VF to PF message queue
>> overflow
>> + * support (ICE_F_MBX_LIMIT) mbxdata is set to NULL and
>> ice_is_malicious_vf
>> + * check is skipped.
>> */
>> void ice_vc_process_vf_msg(struct ice_pf *pf, struct
>> ice_rq_event_info *event,
>> struct ice_mbx_data *mbxdata)
>> @@ -4036,7 +4038,7 @@ void ice_vc_process_vf_msg(struct ice_pf *pf,
>> struct ice_rq_event_info *event,
>> mutex_lock(&vf->cfg_lock);
>> /* Check if the VF is trying to overflow the mailbox */
>> - if (ice_is_malicious_vf(vf, mbxdata))
>> + if (mbxdata && ice_is_malicious_vf(vf, mbxdata))
>> goto finish;
>> /* Check if VF is disabled. */