6.6.54-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 133/538 mtd: rawnand: mtk: Fix init error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miquel Raynal <[email protected]>
[ Upstream commit 2073ae37d550ea32e8545edaa94ef10b4fef7235 ]
Reviewing a series converting the for_each_chil_of_node() loops into their _scoped variants made me realize there was no cleanup of the already registered NAND devices upon error which may leak memory on systems with more than a chip when this error occurs. We should call the _nand_chips_cleanup() function when this happens.
--- drivers/mtd/nand/raw/mtk_nand.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/mtd/nand/raw/mtk_nand.c +3 -1
@@ -1453,8 +1453,10 @@ static int mtk_nfc_nand_chips_init(struct device *dev, struct mtk_nfc *nfc)for_each_child_of_node_scoped (np, nand_np) { ret =mtk_nfc_nand_chip_init (dev, nfc, nand_np); -if (ret) +if (ret) { +mtk_nfc_nand_chips_cleanup (nfc);return ret; + } }return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 134/538 iommu/arm-smmu-qcom: hide last LPASS SMMU context bank from linux
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Gonzalez <[email protected]>
[ Upstream commit 3a8990b8a778219327c5f8ecf10b5d81377b925a ]
On qcom msm8998, writing to the last context bank of lpass_q6_smmu (base address 0x05100000) produces a system freeze & reboot.
The hardware/hypervisor reports 13 context banks for the LPASS SMMU on msm8998, but only the first 12 are accessible... Override the number of context banks
[ 2.546101] arm-smmu 5100000.iommu: probing hardware configuration... [ 2.552439] arm-smmu 5100000.iommu: SMMUv2 with: [ 2.558945] arm-smmu 5100000.iommu: stage 1 translation [ 2.563627] arm-smmu 5100000.iommu: address translation ops [ 2.568923] arm-smmu 5100000.iommu: non-coherent table walk [ 2.574566] arm-smmu 5100000.iommu: (IDR0.CTTW overridden by FW configuration) [ 2.580220] arm-smmu 5100000.iommu: stream matching with 12 register groups [ 2.587263] arm-smmu 5100000.iommu: 13 context banks (0 stage-2 only) [ 2.614447] arm-smmu 5100000.iommu: Supported page sizes: 0x63315000 [ 2.621358] arm-smmu 5100000.iommu: Stage-1: 36-bit VA -> 36-bit IPA [ 2.627772] arm-smmu 5100000.iommu: preserved 0 boot mappings
Specifically, the crashes occur here:
qsmmu->bypass_cbndx = smmu->num_context_banks - 1; arm_smmu_cb_write(smmu, qsmmu->bypass_cbndx, ARM_SMMU_CB_SCTLR, 0);
and here:
arm_smmu_write_context_bank(smmu, i); arm_smmu_cb_write(smmu, i, ARM_SMMU_CB_FSR, ARM_SMMU_CB_FSR_FAULT);
It is likely that FW reserves the last context bank for its own use, thus a simple work-around is: DON'T USE IT in Linux.
If we decrease the number of context banks, last one will be "hidden".
Stable-dep-of: 19eb465c969f ("iommu/arm-smmu-qcom: apply num_context_bank fixes for SDM630 / SDM660")
--- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +7 -0
@@ -278,6 +278,13 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)u32 smr;int i; +/* +* MSM8998 LPASS SMMU reports 13 context banks, but accessing +* the last context bank crashes the system. +*/ +if (of_device_is_compatible (smmu->dev->of_node,"qcom,msm8998-smmu-v2" ) && smmu->num_context_banks ==13 ) + smmu->num_context_banks =12 ; +/* * Some platforms support more than the Arm SMMU architected maximum of * 128 stream matching groups. For unknown reasons, the additional
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 135/538 iommu/arm-smmu-qcom: Work around SDM845 Adreno SMMU w/ 16K pages
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit 2d42d3ba443706c9164fa0bef4e5fd1c36bc1bd9 ]
SDM845's Adreno SMMU is unique in that it actually advertizes support for 16K (and 32M) pages, which doesn't hold for newer SoCs.
This however, seems either broken in the hardware implementation, the hypervisor middleware that abstracts the SMMU, or there's a bug in the Linux kernel somewhere down the line that nobody managed to track down.
Booting SDM845 with 16K page sizes and drm/msm results in:
*** gpu fault: ttbr0=0000000000000000 iova=000100000000c000 dir=READ type=TRANSLATION source=CP (0,0,0,0)
right after loading the firmware. The GPU then starts spitting out illegal intstruction errors, as it's quite obvious that it got a bogus pointer.
Moreover, it seems like this issue also concerns other implementations of SMMUv2 on Qualcomm SoCs, such as the one on SC7180.
Hide 16K support on such instances to work around this.
Stable-dep-of: 19eb465c969f ("iommu/arm-smmu-qcom: apply num_context_bank fixes for SDM630 / SDM660")
--- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +9 -0
@@ -341,6 +341,14 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)return 0 ; } +static int qcom_adreno_smmuv2_cfg_probe (struct arm_smmu_device *smmu) +{ +/* Support for 16K pages is advertised on some SoCs, but it doesn't seem to work */ + smmu->features &= ~ARM_SMMU_FEAT_FMT_AARCH64_16K ; + +return 0 ; +} +static void qcom_smmu_write_s2cr (struct arm_smmu_device *smmu,int idx) {struct arm_smmu_s2cr *s2cr = smmu->s2crs + idx;
@@ -431,6 +439,7 @@ static const struct arm_smmu_impl sdm845_smmu_500_impl = {static const struct arm_smmu_impl qcom_adreno_smmu_v2_impl = { .init_context = qcom_adreno_smmu_init_context, + .cfg_probe = qcom_adreno_smmuv2_cfg_probe, .def_domain_type = qcom_smmu_def_domain_type, .alloc_context_bank = qcom_adreno_smmu_alloc_context_bank, .write_sctlr = qcom_adreno_smmu_write_sctlr,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 136/538 iommu/arm-smmu-qcom: apply num_context_bank fixes for SDM630 / SDM660
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 19eb465c969f3d6ed1b98506d3e470e863b41e16 ]
The Qualcomm SDM630 / SDM660 platform requires the same kind of workaround as MSM8998: some IOMMUs have context banks reserved by firmware / TZ, touching those banks resets the board.
Apply the num_context_bank workaround to those two SMMU devices in order to allow them to be used by Linux.
--- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +13 -1
@@ -282,8 +282,15 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)* MSM8998 LPASS SMMU reports 13 context banks, but accessing * the last context bank crashes the system. */ -if (of_device_is_compatible (smmu->dev->of_node,"qcom,msm8998-smmu-v2" ) && smmu->num_context_banks ==13 ) +if (of_device_is_compatible (smmu->dev->of_node,"qcom,msm8998-smmu-v2" ) && + smmu->num_context_banks ==13 ) { smmu->num_context_banks =12 ; + }else if (of_device_is_compatible (smmu->dev->of_node,"qcom,sdm630-smmu-v2" )) { +if (smmu->num_context_banks ==21 )/* SDM630 / SDM660 A2NOC SMMU */ + smmu->num_context_banks =7 ; +else if (smmu->num_context_banks ==14 )/* SDM630 / SDM660 LPASS SMMU */ + smmu->num_context_banks =13 ; + }/* * Some platforms support more than the Arm SMMU architected maximum of
@@ -346,6 +353,11 @@ static int qcom_adreno_smmuv2_cfg_probe(struct arm_smmu_device *smmu)/* Support for 16K pages is advertised on some SoCs, but it doesn't seem to work */ smmu->features &= ~ARM_SMMU_FEAT_FMT_AARCH64_16K ; +/* TZ protects several last context banks, hide them from Linux */ +if (of_device_is_compatible (smmu->dev->of_node,"qcom,sdm630-smmu-v2" ) && + smmu->num_context_banks ==5 ) + smmu->num_context_banks =2 ; +return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 137/538 pmdomain: core: Harden inter-column space in debug summary
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geert Uytterhoeven <[email protected]>
[ Upstream commit 692c20c4d075bd452acfbbc68200fc226c7c9496 ]
The inter-column space in the debug summary is two spaces. However, in one case, the extra space is handled implicitly in a field width specifier. Make inter-column space explicit to ease future maintenance.
--- drivers/base/power/domain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/power/domain.c +1 -1
@@ -3135,7 +3135,7 @@ static int genpd_summary_one(struct seq_file *s,else snprintf (state,sizeof (state),"%s" , status_lookup[genpd->status]); -seq_printf (s,"%-30s %-50s %u" , genpd->name, state, genpd->performance_state); +seq_printf (s,"%-30s %-49s %u" , genpd->name, state, genpd->performance_state);/* * Modifications on the list require holding locks on both
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 138/538 drm/stm: Fix an error handling path in stm_drm_platform_probe()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit ce7c90bfda2656418c69ba0dd8f8a7536b8928d4 ]
If drm_dev_register() fails, a call to drv_load() must be undone, as already done in the remove function.
--- drivers/gpu/drm/stm/drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/stm/drv.c +3 -1
@@ -203,12 +203,14 @@ static int stm_drm_platform_probe(struct platform_device *pdev) ret =drm_dev_register (ddev,0 );if (ret) - goto err_put; + goto err_unload;drm_fbdev_dma_setup (ddev,16 );return 0 ; +err_unload: +drv_unload (ddev); err_put:drm_dev_put (ddev);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 139/538 drm/stm: ltdc: check memory returned by devm_kzalloc()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Claudiu Beznea <[email protected]>
[ Upstream commit fd39730c58890cd7f0a594231e19bb357f28877c ]
devm_kzalloc() can fail and return NULL pointer. Check its return status. Identified with Coccinelle (kmerr.cocci script).
--- drivers/gpu/drm/stm/ltdc.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/stm/ltdc.c +2 -0
@@ -1580,6 +1580,8 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,ARRAY_SIZE (ltdc_drm_fmt_ycbcr_sp) + ARRAY_SIZE(ltdc_drm_fmt_ycbcr_fp)) * sizeof(*formats), GFP_KERNEL); +if (!formats) +return NULL ;for (i =0 ; i < ldev->caps.pix_fmt_nb; i++) { drm_fmt = ldev->caps.pix_fmt_drm[i];
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 140/538 drm/amd/display: Add null check for set_output_gamma in dcn30_set_output_transfer_func
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit 08ae395ea22fb3d9b318c8bde28c0dfd2f5fa4d2 ]
This commit adds a null check for the set_output_gamma function pointer in the dcn30_set_output_transfer_func function. Previously, set_output_gamma was being checked for nullity at line 386, but then it was being dereferenced without any nullity check at line 401. This could potentially lead to a null pointer dereference error if set_output_gamma is indeed null.
To fix this, we now ensure that set_output_gamma is not null before dereferencing it. We do this by adding a nullity check for set_output_gamma before the call to set_output_gamma at line 401. If set_output_gamma is null, we log an error message and do not call the function.
This fix prevents a potential null pointer dereference error.
drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c:401 dcn30_set_output_transfer_func()
error: we previously assumed 'mpc->funcs->set_output_gamma' could be null (see line 386)
drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c
373 bool dcn30_set_output_transfer_func(struct dc *dc,
374 struct pipe_ctx *pipe_ctx,
375 const struct dc_stream_state *stream)
376 {
377 int mpcc_id = pipe_ctx->plane_res.hubp->inst;
378 struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
379 const struct pwl_params *params = NULL;
380 bool ret = false;
381
382 /* program OGAM or 3DLUT only for the top pipe*/
383 if (pipe_ctx->top_pipe == NULL) {
384 /*program rmu shaper and 3dlut in MPC*/
385 ret = dcn30_set_mpc_shaper_3dlut(pipe_ctx, stream);
386 if (ret == false && mpc->funcs->set_output_gamma) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If this is NULL
387 if (stream->out_transfer_func.type == TF_TYPE_HWPWL)
388 params = &stream->out_transfer_func.pwl;
389 else if (pipe_ctx->stream->out_transfer_func.type ==
390 TF_TYPE_DISTRIBUTED_POINTS &&
391 cm3_helper_translate_curve_to_hw_format(
392 &stream->out_transfer_func,
393 &mpc->blender_params, false))
394 params = &mpc->blender_params;
395 /* there are no ROM LUTs in OUTGAM */
396 if (stream->out_transfer_func.type == TF_TYPE_PREDEFINED)
397 BREAK_TO_DEBUGGER();
398 }
399 }
400
--> 401 mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Then it will crash
402 return ret;
403 }--- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +5 -1
@@ -214,7 +214,11 @@ bool dcn30_set_output_transfer_func(struct dc *dc, } } - mpc->funcs->set_output_gamma (mpc, mpcc_id, params); +if (mpc->funcs->set_output_gamma) + mpc->funcs->set_output_gamma (mpc, mpcc_id, params); +else +DC_LOG_ERROR ("%s: set_output_gamma function pointer is NULL.\n" , __func__); +return ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 141/538 drm/amdgpu: properly handle vbios fake edid sizing
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 8155566a26b8d6c1dd914f06a0c652e4e2f2adf1 ]
The comment in the vbios structure says:
// = 128 means EDID length is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128
This fake edid struct has not been used in a long time, so I'm not sure if there were actually any boards out there with a non-128 byte EDID, but align the code with the comment.
--- .../gpu/drm/amd/amdgpu/atombios_encoders.c | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-)
drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +16 -13
@@ -2065,26 +2065,29 @@ amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder) fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;if (fake_edid_record->ucFakeEDIDLength) {struct edid *edid; -int edid_size = -max ((int )EDID_LENGTH , (int )fake_edid_record->ucFakeEDIDLength); - edid =kmalloc (edid_size,GFP_KERNEL ); +int edid_size; + +if (fake_edid_record->ucFakeEDIDLength ==128 ) + edid_size = fake_edid_record->ucFakeEDIDLength; +else + edid_size = fake_edid_record->ucFakeEDIDLength *128 ; + edid =kmemdup (&fake_edid_record->ucFakeEDIDString[0 ], + edid_size,GFP_KERNEL );if (edid) { -memcpy ((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0 ], - fake_edid_record->ucFakeEDIDLength); -if (drm_edid_is_valid (edid)) { adev->mode_info.bios_hardcoded_edid = edid; adev->mode_info.bios_hardcoded_edid_size = edid_size; - }else + }else {kfree (edid); + } } + record +=struct_size (fake_edid_record, + ucFakeEDIDString, + edid_size); + }else { +/* empty fake edid record must be 3 bytes long */ + record +=sizeof (ATOM_FAKE_EDID_PATCH_RECORD ) +1 ; } - record += fake_edid_record->ucFakeEDIDLength ? -struct_size (fake_edid_record, - ucFakeEDIDString, - fake_edid_record->ucFakeEDIDLength) : -/* empty fake edid record must be 3 bytes long */ -sizeof (ATOM_FAKE_EDID_PATCH_RECORD ) +1 ;break ;case LCD_PANEL_RESOLUTION_RECORD_TYPE : panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 142/538 drm/radeon: properly handle vbios fake edid sizing
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 17c6baff3d5f65c8da164137a58742541a060b2f ]
The comment in the vbios structure says:
// = 128 means EDID length is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128
This fake edid struct has not been used in a long time, so I'm not sure if there were actually any boards out there with a non-128 byte EDID, but align the code with the comment.
--- drivers/gpu/drm/radeon/radeon_atombios.c | 29 +++++++++++++----------- 1 file changed, 16 insertions(+), 13 deletions(-)
drivers/gpu/drm/radeon/radeon_atombios.c +16 -13
@@ -1716,26 +1716,29 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;if (fake_edid_record->ucFakeEDIDLength) {struct edid *edid; -int edid_size = -max ((int )EDID_LENGTH , (int )fake_edid_record->ucFakeEDIDLength); - edid =kmalloc (edid_size,GFP_KERNEL ); +int edid_size; + +if (fake_edid_record->ucFakeEDIDLength ==128 ) + edid_size = fake_edid_record->ucFakeEDIDLength; +else + edid_size = fake_edid_record->ucFakeEDIDLength *128 ; + edid =kmemdup (&fake_edid_record->ucFakeEDIDString[0 ], + edid_size,GFP_KERNEL );if (edid) { -memcpy ((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0 ], - fake_edid_record->ucFakeEDIDLength); -if (drm_edid_is_valid (edid)) { rdev->mode_info.bios_hardcoded_edid = edid; rdev->mode_info.bios_hardcoded_edid_size = edid_size; - }else + }else {kfree (edid); + } } + record +=struct_size (fake_edid_record, + ucFakeEDIDString, + edid_size); + }else { +/* empty fake edid record must be 3 bytes long */ + record +=sizeof (ATOM_FAKE_EDID_PATCH_RECORD ) +1 ; } - record += fake_edid_record->ucFakeEDIDLength ? -struct_size (fake_edid_record, - ucFakeEDIDString, - fake_edid_record->ucFakeEDIDLength) : -/* empty fake edid record must be 3 bytes long */ -sizeof (ATOM_FAKE_EDID_PATCH_RECORD ) +1 ;break ;case LCD_PANEL_RESOLUTION_RECORD_TYPE : panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 143/538 scsi: smartpqi: revert propagate-the-multipath-failure-to-SML-quickly
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gilbert Wu <[email protected]>
[ Upstream commit f1393d52e6cda9c20f12643cbecf1e1dc357e0e2 ]
Correct a rare multipath failure issue by reverting commit 94a68c814328 ("scsi: smartpqi: Quickly propagate path failures to SCSI midlayer") [1].
Reason for revert: The patch propagated the path failure to SML quickly when one of the path fails during IO and AIO path gets disabled for a multipath device.
But it created a new issue: when creating a volume on an encryption-enabled controller, the firmware reports the AIO path is disabled, which cause the driver to report a path failure to SML for a multipath device.
There will be a new fix to handle "Illegal request" and "Invalid field in parameter list" on RAID path when the AIO path is disabled on a multipath device.
[1] https://lore.kernel.org/all/[email protected]/
--- drivers/scsi/smartpqi/smartpqi_init.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-)
drivers/scsi/smartpqi/smartpqi_init.c +2 -18
@@ -2355,14 +2355,6 @@ static inline void pqi_mask_device(u8 *scsi3addr) scsi3addr[3 ] |=0xc0 ; } -static inline bool pqi_is_multipath_device (struct pqi_scsi_dev *device) -{ -if (pqi_is_logical_device (device)) -return false; - -return (device->path_map & (device->path_map -1 )) !=0 ; -} -static inline bool pqi_expose_device (struct pqi_scsi_dev *device) {return !device->is_physical_device || !pqi_skip_device (device->scsi3addr);
@@ -3259,14 +3251,12 @@ static void pqi_process_aio_io_error(struct pqi_io_request *io_request)int residual_count;int xfer_count;bool device_offline; -struct pqi_scsi_dev *device; scmd = io_request->scmd; error_info = io_request->error_info; host_byte =DID_OK ; sense_data_length =0 ; device_offline = false; - device = scmd->device->hostdata;switch (error_info->service_response) {case PQI_AIO_SERV_RESPONSE_COMPLETE :
@@ -3291,14 +3281,8 @@ static void pqi_process_aio_io_error(struct pqi_io_request *io_request)break ;case PQI_AIO_STATUS_AIO_PATH_DISABLED :pqi_aio_path_disabled (io_request); -if (pqi_is_multipath_device (device)) { -pqi_device_remove_start (device); - host_byte =DID_NO_CONNECT ; - scsi_status =SAM_STAT_CHECK_CONDITION ; - }else { - scsi_status =SAM_STAT_GOOD ; - io_request->status = -EAGAIN ; - } + scsi_status =SAM_STAT_GOOD ; + io_request->status = -EAGAIN ;break ;case PQI_AIO_STATUS_NO_PATH_TO_DEVICE :case PQI_AIO_STATUS_INVALID_DEVICE :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 144/538 scsi: NCR5380: Check for phase match during PDMA fixup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Finn Thain <[email protected]>
[ Upstream commit 5768718da9417331803fc4bc090544c2a93b88dc ]
It's not an error for a target to change the bus phase during a transfer. Unfortunately, the FLAG_DMA_FIXUP workaround does not allow for that -- a phase change produces a DRQ timeout error and the device borken flag will be set.
Check the phase match bit during FLAG_DMA_FIXUP processing. Don't forget to decrement the command residual. While we are here, change shost_printk() into scmd_printk() for better consistency with other DMA error messages.
--- drivers/scsi/NCR5380.c | 78 +++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 39 deletions(-)
drivers/scsi/NCR5380.c +39 -39
@@ -1485,6 +1485,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char **data) {struct NCR5380_hostdata *hostdata =shost_priv (instance); +struct NCR5380_cmd *ncmd =NCR5380_to_ncmd (hostdata->connected);int c = *count;unsigned char p = *phase;unsigned char *d = *data;
@@ -1496,7 +1497,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,return -1 ; } -NCR5380_to_ncmd (hostdata->connected)->phase = p; + ncmd->phase = p;if (p &SR_IO ) {if (hostdata->read_overruns)
@@ -1608,45 +1609,44 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,* request. */ -if (hostdata->flags &FLAG_DMA_FIXUP ) { -if (p &SR_IO ) { -/* -* The workaround was to transfer fewer bytes than we -* intended to with the pseudo-DMA read function, wait for -* the chip to latch the last byte, read it, and then disable -* pseudo-DMA mode. -* -* After REQ is asserted, the NCR5380 asserts DRQ and ACK. -* REQ is deasserted when ACK is asserted, and not reasserted -* until ACK goes false. Since the NCR5380 won't lower ACK -* until DACK is asserted, which won't happen unless we twiddle -* the DMA port or we take the NCR5380 out of DMA mode, we -* can guarantee that we won't handshake another extra -* byte. -*/ - -if (NCR5380_poll_politely (hostdata,BUS_AND_STATUS_REG , -BASR_DRQ ,BASR_DRQ ,0 ) <0 ) { - result =-1 ; -shost_printk (KERN_ERR , instance,"PDMA read: DRQ timeout\n" ); - } -if (NCR5380_poll_politely (hostdata,STATUS_REG , -SR_REQ ,0 ,0 ) <0 ) { - result =-1 ; -shost_printk (KERN_ERR , instance,"PDMA read: !REQ timeout\n" ); - } - d[*count -1 ] =NCR5380_read (INPUT_DATA_REG ); - }else { -/* -* Wait for the last byte to be sent. If REQ is being asserted for -* the byte we're interested, we'll ACK it and it will go false. -*/ -if (NCR5380_poll_politely2 (hostdata, -BUS_AND_STATUS_REG ,BASR_DRQ ,BASR_DRQ , -BUS_AND_STATUS_REG ,BASR_PHASE_MATCH ,0 ,0 ) <0 ) { - result =-1 ; -shost_printk (KERN_ERR , instance,"PDMA write: DRQ and phase timeout\n" ); +if ((hostdata->flags &FLAG_DMA_FIXUP ) && + (NCR5380_read (BUS_AND_STATUS_REG ) &BASR_PHASE_MATCH )) { +/* +* The workaround was to transfer fewer bytes than we +* intended to with the pseudo-DMA receive function, wait for +* the chip to latch the last byte, read it, and then disable +* DMA mode. +* +* After REQ is asserted, the NCR5380 asserts DRQ and ACK. +* REQ is deasserted when ACK is asserted, and not reasserted +* until ACK goes false. Since the NCR5380 won't lower ACK +* until DACK is asserted, which won't happen unless we twiddle +* the DMA port or we take the NCR5380 out of DMA mode, we +* can guarantee that we won't handshake another extra +* byte. +* +* If sending, wait for the last byte to be sent. If REQ is +* being asserted for the byte we're interested, we'll ACK it +* and it will go false. +*/ +if (!NCR5380_poll_politely (hostdata,BUS_AND_STATUS_REG , +BASR_DRQ ,BASR_DRQ ,0 )) { +if ((p &SR_IO ) && + (NCR5380_read (BUS_AND_STATUS_REG ) &BASR_PHASE_MATCH )) { +if (!NCR5380_poll_politely (hostdata,STATUS_REG , +SR_REQ ,0 ,0 )) { + d[c] =NCR5380_read (INPUT_DATA_REG ); + --ncmd->this_residual; + }else { + result =-1 ; +scmd_printk (KERN_ERR , hostdata->connected, +"PDMA fixup: !REQ timeout\n" ); + } } + }else if (NCR5380_read (BUS_AND_STATUS_REG ) &BASR_PHASE_MATCH ) { + result =-1 ; +scmd_printk (KERN_ERR , hostdata->connected, +"PDMA fixup: DRQ timeout\n" ); } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 145/538 drm/amd/amdgpu: Properly tune the size of struct
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: WangYuli <[email protected]>
[ Upstream commit 0cee47cde41e22712c034ae961076067d4ac13a0 ]
The struct assertion is failed because sparse cannot parse #pragma pack(push, 1) and #pragma pack(pop) correctly. GCC's output is still 1-byte-aligned. No harm to memory layout.
The error can be filtered out by sparse-diff, but sometimes multiple lines queezed into one, making the sparse-diff thinks its a new error. I'm trying to aviod this by fixing errors.
--- drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +2 -2
@@ -209,7 +209,7 @@ struct amd_sriov_msg_pf2vf_info {uint32_t pcie_atomic_ops_support_flags;/* reserved */ uint32_t reserved[256 -AMD_SRIOV_MSG_PF2VF_INFO_FILLED_SIZE ]; -}; +} __packed;struct amd_sriov_msg_vf2pf_info_header {/* the total structure size in byte */
@@ -267,7 +267,7 @@ struct amd_sriov_msg_vf2pf_info {/* reserved */ uint32_t reserved[256 -AMD_SRIOV_MSG_VF2PF_INFO_FILLED_SIZE ]; -}; +} __packed;/* mailbox message send from guest to host */ enum amd_sriov_mailbox_request_message {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 146/538 drm/rockchip: vop: Allow 4096px width scaling
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Bee <[email protected]>
[ Upstream commit 0ef968d91a20b5da581839f093f98f7a03a804f7 ]
There is no reason to limit VOP scaling to 3840px width, the limit of RK3288, when there are newer VOP versions that support 4096px width.
Change to enforce a maximum of 4096px width plane scaling, the maximum supported output width of the VOP versions supported by this driver.
--- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/rockchip_drm_vop.c +2 -2
@@ -381,8 +381,8 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,if (info->is_yuv) is_yuv = true; -if (dst_w >3840 ) { -DRM_DEV_ERROR (vop->dev,"Maximum dst width (3840) exceeded\n" ); +if (dst_w >4096 ) { +DRM_DEV_ERROR (vop->dev,"Maximum dst width (4096) exceeded\n" );return ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 147/538 drm/rockchip: dw_hdmi: Fix reading EDID when using a forced mode
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Karlman <[email protected]>
[ Upstream commit a5d024541ec466f428e6c514577d511a40779c7b ]
EDID cannot be read on RK3328 until after read_hpd has been called and correct io voltage has been configured based on connection status.
When a forced mode is used, e.g. video=1920x1080@60e, the connector detect ops, that in turn normally calls the read_hpd, never gets called.
This result in reading EDID to fail in connector get_modes ops.
Call dw_hdmi_rk3328_read_hpd at end of dw_hdmi_rk3328_setup_hpd to correct io voltage and allow reading EDID after setup_hpd.
--- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +2 -0
@@ -435,6 +435,8 @@ static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data)HIWORD_UPDATE (RK3328_HDMI_SDAIN_MSK |RK3328_HDMI_SCLIN_MSK ,RK3328_HDMI_SDAIN_MSK |RK3328_HDMI_SCLIN_MSK | RK3328_HDMI_HPD_IOE)); + +dw_hdmi_rk3328_read_hpd (dw_hdmi, data); }static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 148/538 drm/radeon/evergreen_cs: fix int overflow errors in cs track offsets
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikita Zhandarovich <[email protected]>
[ Upstream commit 3fbaf475a5b8361ebee7da18964db809e37518b7 ]
Several cs track offsets (such as 'track->db_s_read_offset') either are initialized with or plainly take big enough values that, once shifted 8 bits left, may be hit with integer overflow if the resulting values end up going over u32 limit.
Same goes for a few instances of 'surf.layer_size * mslice' multiplications that are added to 'offset' variable - they may potentially overflow as well and need to be validated properly.
While some debug prints in this code section take possible overflow issues into account, simply casting to (unsigned long) may be erroneous in its own way, as depending on CPU architecture one is liable to get different results.
Fix said problems by:
- casting 'offset' to fixed u64 data type instead of ambiguous unsigned long.
- casting one of the operands in vulnerable to integer overflow cases to u64.
- adjust format specifiers in debug prints to properly represent 'offset' values.
Found by Linux Verification Center (linuxtesting.org) with static analysis tool SVACE.
--- drivers/gpu/drm/radeon/evergreen_cs.c | 62 +++++++++++++-------------- 1 file changed, 31 insertions(+), 31 deletions(-)
drivers/gpu/drm/radeon/evergreen_cs.c +31 -31
@@ -395,7 +395,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned istruct evergreen_cs_track *track = p->track;struct eg_surface surf;unsigned pitch, slice, mslice; -unsigned long offset; +u64 offset;int r; mslice =G_028C6C_SLICE_MAX (track->cb_color_view[id]) +1 ;
@@ -433,14 +433,14 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned ireturn r; } - offset = track->cb_color_bo_offset[id] <<8 ; + offset = (u64 )track->cb_color_bo_offset[id] <<8 ;if (offset & (surf.base_align -1 )) { -dev_warn (p->dev,"%s:%d cb[%d] bo base %ld not aligned with %ld\n" , +dev_warn (p->dev,"%s:%d cb[%d] bo base %llu not aligned with %ld\n" , __func__, __LINE__, id, offset, surf.base_align);return -EINVAL ; } - offset += surf.layer_size * mslice; + offset += (u64 )surf.layer_size * mslice;if (offset >radeon_bo_size (track->cb_color_bo[id])) {/* old ddx are broken they allocate bo with w*h*bpp but * program slice with ALIGN(h, 8), catch this and patch
@@ -448,14 +448,14 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i*/ if (!surf.mode) {uint32_t *ib = p->ib.ptr; -unsigned long tmp, nby, bsize, size, min =0 ; +u64 tmp, nby, bsize, size, min =0 ;/* find the height the ddx wants */ if (surf.nby >8 ) { min = surf.nby -8 ; } bsize =radeon_bo_size (track->cb_color_bo[id]); - tmp = track->cb_color_bo_offset[id] <<8 ; + tmp = (u64 )track->cb_color_bo_offset[id] <<8 ;for (nby = surf.nby; nby > min; nby--) { size = nby * surf.nbx * surf.bpe * surf.nsamples;if ((tmp + size * mslice) <= bsize) {
@@ -467,7 +467,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i slice = ((nby * surf.nbx) /64 ) -1 ;if (!evergreen_surface_check (p, &surf,"cb" )) {/* check if this one works */ - tmp += surf.layer_size * mslice; + tmp += (u64 )surf.layer_size * mslice;if (tmp <= bsize) { ib[track->cb_color_slice_idx[id]] = slice; goto old_ddx_ok;
@@ -476,9 +476,9 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i } }dev_warn (p->dev,"%s:%d cb[%d] bo too small (layer size %d, " -"offset %d, max layer %d, bo size %ld, slice %d)\n" , +"offset %llu, max layer %d, bo size %ld, slice %d)\n" , __func__, __LINE__, id, surf.layer_size, - track->cb_color_bo_offset[id] <<8 , mslice, + (u64 )track->cb_color_bo_offset[id] <<8 , mslice,radeon_bo_size (track->cb_color_bo[id]), slice); dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", __func__, __LINE__, surf.nbx, surf.nby,
@@ -562,7 +562,7 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)struct evergreen_cs_track *track = p->track;struct eg_surface surf;unsigned pitch, slice, mslice; -unsigned long offset; +u64 offset;int r; mslice =G_028008_SLICE_MAX (track->db_depth_view) +1 ;
@@ -608,18 +608,18 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)return r; } - offset = track->db_s_read_offset <<8 ; + offset = (u64 )track->db_s_read_offset <<8 ;if (offset & (surf.base_align -1 )) { -dev_warn (p->dev,"%s:%d stencil read bo base %ld not aligned with %ld\n" , +dev_warn (p->dev,"%s:%d stencil read bo base %llu not aligned with %ld\n" , __func__, __LINE__, offset, surf.base_align);return -EINVAL ; } - offset += surf.layer_size * mslice; + offset += (u64 )surf.layer_size * mslice;if (offset >radeon_bo_size (track->db_s_read_bo)) {dev_warn (p->dev,"%s:%d stencil read bo too small (layer size %d, " -"offset %ld, max layer %d, bo size %ld)\n" , +"offset %llu, max layer %d, bo size %ld)\n" , __func__, __LINE__, surf.layer_size, - (unsigned long )track->db_s_read_offset <<8 , mslice, + (u64 )track->db_s_read_offset <<8 , mslice,radeon_bo_size (track->db_s_read_bo)); dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", __func__, __LINE__, track->db_depth_size,
@@ -627,18 +627,18 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)return -EINVAL ; } - offset = track->db_s_write_offset <<8 ; + offset = (u64 )track->db_s_write_offset <<8 ;if (offset & (surf.base_align -1 )) { -dev_warn (p->dev,"%s:%d stencil write bo base %ld not aligned with %ld\n" , +dev_warn (p->dev,"%s:%d stencil write bo base %llu not aligned with %ld\n" , __func__, __LINE__, offset, surf.base_align);return -EINVAL ; } - offset += surf.layer_size * mslice; + offset += (u64 )surf.layer_size * mslice;if (offset >radeon_bo_size (track->db_s_write_bo)) {dev_warn (p->dev,"%s:%d stencil write bo too small (layer size %d, " -"offset %ld, max layer %d, bo size %ld)\n" , +"offset %llu, max layer %d, bo size %ld)\n" , __func__, __LINE__, surf.layer_size, - (unsigned long )track->db_s_write_offset <<8 , mslice, + (u64 )track->db_s_write_offset <<8 , mslice,radeon_bo_size (track->db_s_write_bo));return -EINVAL ; }
@@ -659,7 +659,7 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p)struct evergreen_cs_track *track = p->track;struct eg_surface surf;unsigned pitch, slice, mslice; -unsigned long offset; +u64 offset;int r; mslice =G_028008_SLICE_MAX (track->db_depth_view) +1 ;
@@ -706,34 +706,34 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p)return r; } - offset = track->db_z_read_offset <<8 ; + offset = (u64 )track->db_z_read_offset <<8 ;if (offset & (surf.base_align -1 )) { -dev_warn (p->dev,"%s:%d stencil read bo base %ld not aligned with %ld\n" , +dev_warn (p->dev,"%s:%d stencil read bo base %llu not aligned with %ld\n" , __func__, __LINE__, offset, surf.base_align);return -EINVAL ; } - offset += surf.layer_size * mslice; + offset += (u64 )surf.layer_size * mslice;if (offset >radeon_bo_size (track->db_z_read_bo)) {dev_warn (p->dev,"%s:%d depth read bo too small (layer size %d, " -"offset %ld, max layer %d, bo size %ld)\n" , +"offset %llu, max layer %d, bo size %ld)\n" , __func__, __LINE__, surf.layer_size, - (unsigned long )track->db_z_read_offset <<8 , mslice, + (u64 )track->db_z_read_offset <<8 , mslice,radeon_bo_size (track->db_z_read_bo));return -EINVAL ; } - offset = track->db_z_write_offset <<8 ; + offset = (u64 )track->db_z_write_offset <<8 ;if (offset & (surf.base_align -1 )) { -dev_warn (p->dev,"%s:%d stencil write bo base %ld not aligned with %ld\n" , +dev_warn (p->dev,"%s:%d stencil write bo base %llu not aligned with %ld\n" , __func__, __LINE__, offset, surf.base_align);return -EINVAL ; } - offset += surf.layer_size * mslice; + offset += (u64 )surf.layer_size * mslice;if (offset >radeon_bo_size (track->db_z_write_bo)) {dev_warn (p->dev,"%s:%d depth write bo too small (layer size %d, " -"offset %ld, max layer %d, bo size %ld)\n" , +"offset %llu, max layer %d, bo size %ld)\n" , __func__, __LINE__, surf.layer_size, - (unsigned long )track->db_z_write_offset <<8 , mslice, + (u64 )track->db_z_write_offset <<8 , mslice,radeon_bo_size (track->db_z_write_bo));return -EINVAL ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 149/538 drm/bridge: lontium-lt8912b: Validate mode in drm_bridge_funcs::mode_valid()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liu Ying <[email protected]>
[ Upstream commit fe828fbd87786238b30f44cafd698d975d956c97 ]
If the bridge is attached with the DRM_BRIDGE_ATTACH_NO_CONNECTOR flag set, this driver won't initialize a connector and hence display mode won't be validated in drm_connector_helper_funcs::mode_valid(). So, move the mode validation from drm_connector_helper_funcs::mode_valid() to drm_bridge_funcs::mode_valid(), because the mode validation is always done for the bridge.
--- drivers/gpu/drm/bridge/lontium-lt8912b.c | 35 ++++++++++++------------ 1 file changed, 18 insertions(+), 17 deletions(-)
drivers/gpu/drm/bridge/lontium-lt8912b.c +18 -17
@@ -411,22 +411,6 @@ static const struct drm_connector_funcs lt8912_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static enum drm_mode_status -lt8912_connector_mode_valid (struct drm_connector *connector, -struct drm_display_mode *mode) -{ -if (mode->clock >150000 ) -return MODE_CLOCK_HIGH ; - -if (mode->hdisplay >1920 ) -return MODE_BAD_HVALUE ; - -if (mode->vdisplay >1080 ) -return MODE_BAD_VVALUE ; - -return MODE_OK ; -} -static int lt8912_connector_get_modes (struct drm_connector *connector) {const struct drm_edid *drm_edid;
@@ -452,7 +436,6 @@ static int lt8912_connector_get_modes(struct drm_connector *connector)static const struct drm_connector_helper_funcs lt8912_connector_helper_funcs = { .get_modes = lt8912_connector_get_modes, - .mode_valid = lt8912_connector_mode_valid, }; static void lt8912_bridge_mode_set(struct drm_bridge *bridge,
@@ -594,6 +577,23 @@ static void lt8912_bridge_detach(struct drm_bridge *bridge)drm_bridge_hpd_disable (lt->hdmi_port); } +static enum drm_mode_status +lt8912_bridge_mode_valid (struct drm_bridge *bridge, +const struct drm_display_info *info, +const struct drm_display_mode *mode) +{ +if (mode->clock >150000 ) +return MODE_CLOCK_HIGH ; + +if (mode->hdisplay >1920 ) +return MODE_BAD_HVALUE ; + +if (mode->vdisplay >1080 ) +return MODE_BAD_VVALUE ; + +return MODE_OK ; +} +static enum drm_connector_status lt8912_bridge_detect (struct drm_bridge *bridge) {
@@ -624,6 +624,7 @@ static struct edid *lt8912_bridge_get_edid(struct drm_bridge *bridge,static const struct drm_bridge_funcs lt8912_bridge_funcs = { .attach = lt8912_bridge_attach, .detach = lt8912_bridge_detach, + .mode_valid = lt8912_bridge_mode_valid, .mode_set = lt8912_bridge_mode_set, .enable = lt8912_bridge_enable, .detect = lt8912_bridge_detect,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 150/538 drm/vc4: hdmi: Handle error case of pm_runtime_resume_and_get
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Wahren <[email protected]>
[ Upstream commit f1a54e860b1bc8d824925b5a77f510913880e8d6 ]
The commit 0f5251339eda ("drm/vc4: hdmi: Make sure the controller is powered in detect") introduced the necessary power management handling to avoid register access while controller is powered down. Unfortunately it just print a warning if pm_runtime_resume_and_get() fails and proceed anyway.
This could happen during suspend to idle. So we must assume it is unsafe to access the HDMI register. So bail out properly.
--- drivers/gpu/drm/vc4/vc4_hdmi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/gpu/drm/vc4/vc4_hdmi.c +7 -1
@@ -458,6 +458,7 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector, {struct vc4_hdmi *vc4_hdmi =connector_to_vc4_hdmi (connector);enum drm_connector_status status = connector_status_disconnected; +int ret;/* * NOTE: This function should really take vc4_hdmi->mutex, but
@@ -470,7 +471,12 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector,* the lock for now. */ -WARN_ON (pm_runtime_resume_and_get (&vc4_hdmi->pdev->dev)); + ret =pm_runtime_resume_and_get (&vc4_hdmi->pdev->dev); +if (ret) { +drm_err_once (connector->dev,"Failed to retain HDMI power domain: %d\n" , + ret); +return connector_status_unknown; + }if (vc4_hdmi->hpd_gpio) {if (gpiod_get_value_cansleep (vc4_hdmi->hpd_gpio))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 151/538 scsi: elx: libefc: Fix potential use after free in efc_nport_vport_del()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 2e4b02fad094976763af08fec2c620f4f8edd9ae ]
The kref_put() function will call nport->release if the refcount drops to zero. The nport->release release function is _efc_nport_free() which frees "nport". But then we dereference "nport" on the next line which is a use after free. Re-order these lines to avoid the use after free.
--- drivers/scsi/elx/libefc/efc_nport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/elx/libefc/efc_nport.c +1 -1
@@ -705,9 +705,9 @@ efc_nport_vport_del(struct efc *efc, struct efc_domain *domain,spin_lock_irqsave (&efc->lock, flags);list_for_each_entry (nport, &domain->nport_list, list_entry) {if (nport->wwpn == wwpn && nport->wwnn == wwnn) { -kref_put (&nport->ref, nport->release);/* Shutdown this NPORT */ efc_sm_post_event (&nport->sm,EFC_EVT_SHUTDOWN ,NULL ); +kref_put (&nport->ref, nport->release);break ; } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 152/538 jfs: fix out-of-bounds in dbNextAG() and diAlloc()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeongjun Park <[email protected]>
[ Upstream commit e63866a475562810500ea7f784099bfe341e761a ]
In dbNextAG() , there is no check for the case where bmp->db_numag is greater or same than MAXAG due to a polluted image, which causes an out-of-bounds. Therefore, a bounds check should be added in dbMount().
And in dbNextAG(), a check for the case where agpref is greater than bmp->db_numag should be added, so an out-of-bounds exception should be prevented.
Additionally, a check for the case where agno is greater or same than MAXAG should be added in diAlloc() to prevent out-of-bounds.
--- fs/jfs/jfs_dmap.c | 4 ++-- fs/jfs/jfs_imap.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
fs/jfs/jfs_dmap.c +2 -2
@@ -187,7 +187,7 @@ int dbMount(struct inode *ipbmap) } bmp->db_numag =le32_to_cpu (dbmp_le->dn_numag); -if (!bmp->db_numag) { +if (!bmp->db_numag || bmp->db_numag >=MAXAG ) { err = -EINVAL ; goto err_release_metapage; }
@@ -652,7 +652,7 @@ int dbNextAG(struct inode *ipbmap)* average free space. */ for (i =0 ; i < bmp->db_numag; i++, agpref++) { -if (agpref == bmp->db_numag) +if (agpref >= bmp->db_numag) agpref =0 ;if (atomic_read (&bmp->db_active[agpref]))
fs/jfs/jfs_imap.c +1 -1
@@ -1360,7 +1360,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)/* get the ag number of this iag */ agno =BLKTOAG (JFS_IP (pip)->agstart,JFS_SBI (pip->i_sb)); dn_numag =JFS_SBI (pip->i_sb)->bmap->db_numag; -if (agno <0 || agno > dn_numag) +if (agno <0 || agno > dn_numag || agno >=MAXAG )return -EIO ;if (atomic_read (&JFS_SBI (pip->i_sb)->bmap->db_active[agno])) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 153/538 drm/mediatek: Fix missing configuration flags in mtk_crtc_ddp_config()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason-JH.Lin <[email protected]>
[ Upstream commit fe30bae552ce27b9fefe0b12db1544e73d07325f ]
In mtk_crtc_ddp_config(), mtk_crtc will use some configuration flags to generate instructions to cmdq_handle, such as:
state->pending_config
mtk_crtc->pending_planes
plane_state->pending.config
mtk_crtc->pending_async_planes plane_state->pending.async_config
These configuration flags may be set to false when a GCE IRQ comes calling ddp_cmdq_cb(). This may result in missing prepare instructions, especially if mtk_crtc_update_config() with the flase need_vblank (no need to wait for vblank) cases.
Therefore, the mtk_crtc->config_updating flag is set at the beginning of mtk_crtc_update_config() to ensure that these configuration flags won't be changed when the mtk_crtc_ddp_config() is preparing instructions. But somehow the ddp_cmdq_cb() didn't use the mtk_crtc->config_updating flag to prevent those pending config flags from being cleared.
To avoid missing the configuration when generating the config instruction, the config_updating flag should be added into ddp_cmdq_cb() and be protected with spin_lock.
--- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
drivers/gpu/drm/mediatek/mtk_drm_crtc.c +27 -0
@@ -67,6 +67,8 @@ struct mtk_drm_crtc {/* lock for display hardware access */ struct mutex hw_lock;bool config_updating; +/* lock for config_updating to cmd buffer */ +spinlock_t config_lock; };struct mtk_crtc_state {
@@ -104,11 +106,16 @@ static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)static void mtk_drm_finish_page_flip (struct mtk_drm_crtc *mtk_crtc) { +unsigned long flags; +drm_crtc_handle_vblank (&mtk_crtc->base); + +spin_lock_irqsave (&mtk_crtc->config_lock, flags);if (!mtk_crtc->config_updating && mtk_crtc->pending_needs_vblank) {mtk_drm_crtc_finish_page_flip (mtk_crtc); mtk_crtc->pending_needs_vblank = false; } +spin_unlock_irqrestore (&mtk_crtc->config_lock, flags); }#if IS_REACHABLE (CONFIG_MTK_CMDQ )
@@ -291,12 +298,19 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_drm_crtc, cmdq_client);struct mtk_crtc_state *state;unsigned int i; +unsigned long flags;if (data->sta <0 )return ; state =to_mtk_crtc_state (mtk_crtc->base.state); +spin_lock_irqsave (&mtk_crtc->config_lock, flags); +if (mtk_crtc->config_updating) { +spin_unlock_irqrestore (&mtk_crtc->config_lock, flags); + goto ddp_cmdq_cb_out; + } + state->pending_config = false;if (mtk_crtc->pending_planes) {
@@ -323,6 +337,10 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) mtk_crtc->pending_async_planes = false; } +spin_unlock_irqrestore (&mtk_crtc->config_lock, flags); + +ddp_cmdq_cb_out: + mtk_crtc->cmdq_vblank_cnt =0 ;wake_up (&mtk_crtc->cb_blocking_queue); }
@@ -555,9 +573,14 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,struct mtk_drm_private *priv = crtc->dev->dev_private;unsigned int pending_planes =0 , pending_async_planes =0 ;int i; +unsigned long flags;mutex_lock (&mtk_crtc->hw_lock); + +spin_lock_irqsave (&mtk_crtc->config_lock, flags); mtk_crtc->config_updating = true; +spin_unlock_irqrestore (&mtk_crtc->config_lock, flags); +if (needs_vblank) mtk_crtc->pending_needs_vblank = true;
@@ -611,7 +634,10 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0); }#endif +spin_lock_irqsave (&mtk_crtc->config_lock, flags); mtk_crtc->config_updating = false; +spin_unlock_irqrestore (&mtk_crtc->config_lock, flags); +mutex_unlock (&mtk_crtc->hw_lock); }
@@ -1014,6 +1040,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,drm_mode_crtc_set_gamma_size (&mtk_crtc->base, gamma_lut_size);drm_crtc_enable_color_mgmt (&mtk_crtc->base,0 , has_ctm, gamma_lut_size);mutex_init (&mtk_crtc->hw_lock); +spin_lock_init (&mtk_crtc->config_lock);#if IS_REACHABLE (CONFIG_MTK_CMDQ ) i = priv->mbox_index++;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 154/538 drm/mediatek: Use spin_lock_irqsave() for CRTC event lock
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fei Shao <[email protected]>
[ Upstream commit be03b30b7aa99aca876fbc7c1c1b73b2d0339321 ]
Use the state-aware spin_lock_irqsave() and spin_unlock_irqrestore() to avoid unconditionally re-enabling the local interrupts.
--- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/mediatek/mtk_drm_crtc.c +3 -2
@@ -450,6 +450,7 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) {struct drm_device *drm = mtk_crtc->base.dev;struct drm_crtc *crtc = &mtk_crtc->base; +unsigned long flags;int i;for (i =0 ; i < mtk_crtc->ddp_comp_nr; i++) {
@@ -481,10 +482,10 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)pm_runtime_put (drm->dev);if (crtc->state->event && !crtc->state->active) { -spin_lock_irq (&crtc->dev->event_lock); +spin_lock_irqsave (&crtc->dev->event_lock, flags);drm_crtc_send_vblank_event (crtc, crtc->state->event); crtc->state->event =NULL ; -spin_unlock_irq (&crtc->dev->event_lock); +spin_unlock_irqrestore (&crtc->dev->event_lock, flags); } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 155/538 powerpc/8xx: Fix initial memory mapping
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy <[email protected]>
[ Upstream commit f9f2bff64c2f0dbee57be3d8c2741357ad3d05e6 ]
Commit cf209951fa7f ("powerpc/8xx: Map linear memory with huge pages") introduced an initial mapping of kernel TEXT using PAGE_KERNEL_TEXT, but the pages that contain kernel TEXT may also contain kernel RODATA, and depending on selected debug options PAGE_KERNEL_TEXT may be either RWX or ROX. RODATA must be writable during init because it also contains ro_after_init data.
So use PAGE_KERNEL_X instead to be sure it is RWX.
--- arch/powerpc/mm/nohash/8xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/mm/nohash/8xx.c +2 -2
@@ -149,11 +149,11 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)mmu_mapin_immr (); -mmu_mapin_ram_chunk (0 , boundary,PAGE_KERNEL_TEXT , true); +mmu_mapin_ram_chunk (0 , boundary,PAGE_KERNEL_X , true);if (debug_pagealloc_enabled_or_kfence ()) { top = boundary; }else { -mmu_mapin_ram_chunk (boundary, einittext8,PAGE_KERNEL_TEXT , true); +mmu_mapin_ram_chunk (boundary, einittext8,PAGE_KERNEL_X , true);mmu_mapin_ram_chunk (einittext8, top,PAGE_KERNEL , true); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 156/538 powerpc/8xx: Fix kernel vs user address comparison
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy <[email protected]>
[ Upstream commit 65a82e117ffeeab0baf6f871a1cab11a28ace183 ]
Since commit 9132a2e82adc ("powerpc/8xx: Define a MODULE area below kernel text"), module exec space is below PAGE_OFFSET so not only space above PAGE_OFFSET, but space above TASK_SIZE need to be seen as kernel space.
Until now the problem went undetected because by default TASK_SIZE is 0x8000000 which means address space is determined by just checking upper address bit. But when TASK_SIZE is over 0x80000000, PAGE_OFFSET is used for comparison, leading to thinking module addresses are part of user space.
Fix it by using TASK_SIZE instead of PAGE_OFFSET for address comparison.
--- arch/powerpc/kernel/head_8xx.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/powerpc/kernel/head_8xx.S +3 -3
@@ -41,12 +41,12 @@ #include "head_32.h" .macro compare_to_kernel_boundary scratch, addr -#if CONFIG_TASK_SIZE <= 0x80000000 && CONFIG_PAGE_OFFSET >= 0x80000000 +#if CONFIG_TASK_SIZE <= 0x80000000 && MODULES_VADDR >= 0x80000000 /* By simply checking Address >= 0x80000000, we know if its a kernel address */ not. \scratch, \addr #else rlwinm \scratch, \addr, 16, 0xfff8 - cmpli cr0, \scratch, PAGE_OFFSET@h + cmpli cr0, \scratch, TASK_SIZE@h #endif .endm
@@ -404,7 +404,7 @@ FixupDAR:/* Entry point for dcbx workaround. */ mfspr r10, SPRN_SRR0 mtspr SPRN_MD_EPN, r10 rlwinm r11, r10, 16, 0xfff8 - cmpli cr1, r11, PAGE_OFFSET@h + cmpli cr1, r11, TASK_SIZE@h mfspr r11, SPRN_M_TWB /* Get level 1 table */ blt+ cr1, 3f
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 157/538 powerpc/vdso: Inconditionally use CFUNC macro
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy <[email protected]>
[ Upstream commit 65948b0e716a47382731889ee6bbb18642b8b003 ]
During merge of commit 4e991e3c16a3 ("powerpc: add CFUNC assembly label annotation") a fallback version of CFUNC macro was added at the last minute, so it can be used inconditionally.
--- arch/powerpc/kernel/vdso/gettimeofday.S | 4 ---- 1 file changed, 4 deletions(-)
arch/powerpc/kernel/vdso/gettimeofday.S +0 -4
@@ -38,11 +38,7 @@ .else addi r4, r5, VDSO_DATA_OFFSET .endif -#ifdef __powerpc64__ bl CFUNC(DOTSYM(\funct)) -#else - bl \funct -#endif PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) #ifdef __powerpc64__ PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 158/538 drm/msm: Fix incorrect file name output in adreno_request_fw()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Mishin <[email protected]>
[ Upstream commit e19366911340c2313a1abbb09c54eaf9bdea4f58 ]
In adreno_request_fw() when debugging information is printed to the log after firmware load, an incorrect filename is printed. 'newname' is used instead of 'fwname', so prefix "qcom/" is being added to filename. Looks like "copy-paste" mistake.
Fix this mistake by replacing 'newname' with 'fwname'.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Patchwork: https://patchwork.freedesktop.org/patch/602382/
--- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/adreno/adreno_gpu.c +1 -1
@@ -468,7 +468,7 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const char *fwname) ret =request_firmware_direct (&fw, fwname, drm->dev);if (!ret) {DRM_DEV_INFO (drm->dev,"loaded %s from legacy location\n" , - newname); + fwname); adreno_gpu->fwloc =FW_LOCATION_LEGACY ; goto out; }else if (adreno_gpu->fwloc !=FW_LOCATION_UNKNOWN ) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 159/538 drm/msm/a5xx: disable preemption in submits by default
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Lypak <[email protected]>
[ Upstream commit db9dec2db76146d65e1cfbb6afb2e2bd5dab67f8 ]
Fine grain preemption (switching from/to points within submits) requires extra handling in command stream of those submits, especially when rendering with tiling (using GMEM). However this handling is missing at this point in mesa (and always was). For this reason we get random GPU faults and hangs if more than one priority level is used because local preemption is enabled prior to executing command stream from submit.
With that said it was ahead of time to enable local preemption by default considering the fact that even on downstream kernel it is only enabled if requested via UAPI.
Patchwork: https://patchwork.freedesktop.org/patch/612041/
--- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/adreno/a5xx_gpu.c +6 -2
@@ -150,9 +150,13 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)OUT_PKT7 (ring,CP_SET_PROTECTED_MODE ,1 );OUT_RING (ring,1 ); -/* Enable local preemption for finegrain preemption */ +/* +* Disable local preemption by default because it requires +* user-space to be aware of it and provide additional handling +* to restore rendering state or do various flushes on switch. +*/ OUT_PKT7 (ring,CP_PREEMPT_ENABLE_LOCAL ,1 ); -OUT_RING (ring,0x1 ); +OUT_RING (ring,0x0 );/* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */ OUT_PKT7 (ring,CP_YIELD_ENABLE ,1 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 160/538 drm/msm/a5xx: properly clear preemption records on resume
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Lypak <[email protected]>
[ Upstream commit 64fd6d01a52904bdbda0ce810a45a428c995a4ca ]
Two fields of preempt_record which are used by CP aren't reset on
resume: "data" and "info". This is the reason behind faults which happen when we try to switch to the ring that was active last before suspend. In addition those faults can't be recovered from because we use suspend and resume to do so (keeping values of those fields again).
Patchwork: https://patchwork.freedesktop.org/patch/612043/
--- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/msm/adreno/a5xx_preempt.c +2 -0
@@ -204,6 +204,8 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu)return ;for (i =0 ; i < gpu->nr_rings; i++) { + a5xx_gpu->preempt[i]->data =0 ; + a5xx_gpu->preempt[i]->info =0 ; a5xx_gpu->preempt[i]->wptr =0 ; a5xx_gpu->preempt[i]->rptr =0 ; a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 161/538 drm/msm/a5xx: fix races in preemption evaluation stage
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Lypak <[email protected]>
[ Upstream commit ce050f307ad93bcc5958d0dd35fc276fd394d274 ]
On A5XX GPUs when preemption is used it's invietable to enter a soft lock-up state in which GPU is stuck at empty ring-buffer doing nothing. This appears as full UI lockup and not detected as GPU hang (because it's not). This happens due to not triggering preemption when it was needed. Sometimes this state can be recovered by some new submit but generally it won't happen because applications are waiting for old submits to retire.
One of the reasons why this happens is a race between a5xx_submit and a5xx_preempt_trigger called from IRQ during submit retire. Former thread updates ring->cur of previously empty and not current ring right after latter checks it for emptiness. Then both threads can just exit because for first one preempt_state wasn't NONE yet and for second one all rings appeared to be empty.
To prevent such situations from happening we need to establish guarantee for preempt_trigger to make decision after each submit or retire. To implement this we serialize preemption initiation using spinlock. If switch is already in progress we need to re-trigger preemption when it finishes.
Patchwork: https://patchwork.freedesktop.org/patch/612045/
--- drivers/gpu/drm/msm/adreno/a5xx_gpu.h | 1 + drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 24 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/adreno/a5xx_gpu.h +1 -0
@@ -36,6 +36,7 @@ struct a5xx_gpu {uint64_t preempt_iova[MSM_GPU_MAX_RINGS ];atomic_t preempt_state; +spinlock_t preempt_start_lock;struct timer_list preempt_timer;struct drm_gem_object *shadow_bo;
drivers/gpu/drm/msm/adreno/a5xx_preempt.c +22 -2
@@ -97,12 +97,19 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)if (gpu->nr_rings ==1 )return ; +/* +* Serialize preemption start to ensure that we always make +* decision on latest state. Otherwise we can get stuck in +* lower priority or empty ring. +*/ +spin_lock_irqsave (&a5xx_gpu->preempt_start_lock, flags); +/* * Try to start preemption by moving from NONE to START. If * unsuccessful, a preemption is already in flight */ if (!try_preempt_state (a5xx_gpu,PREEMPT_NONE ,PREEMPT_START )) -return ; + goto out;/* Get the next ring to preempt to */ ring =get_next_ring (gpu);
@@ -127,9 +134,11 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)set_preempt_state (a5xx_gpu,PREEMPT_ABORT );update_wptr (gpu, a5xx_gpu->cur_ring);set_preempt_state (a5xx_gpu,PREEMPT_NONE ); -return ; + goto out; } +spin_unlock_irqrestore (&a5xx_gpu->preempt_start_lock, flags); +/* Make sure the wptr doesn't update while we're in motion */ spin_lock_irqsave (&ring->preempt_lock, flags); a5xx_gpu->preempt[ring->id]->wptr =get_wptr (ring);
@@ -152,6 +161,10 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)/* And actually start the preemption */ gpu_write (gpu,REG_A5XX_CP_CONTEXT_SWITCH_CNTL ,1 ); +return ; + +out: +spin_unlock_irqrestore (&a5xx_gpu->preempt_start_lock, flags); }void a5xx_preempt_irq (struct msm_gpu *gpu)
@@ -188,6 +201,12 @@ void a5xx_preempt_irq(struct msm_gpu *gpu)update_wptr (gpu, a5xx_gpu->cur_ring);set_preempt_state (a5xx_gpu,PREEMPT_NONE ); + +/* +* Try to trigger preemption again in case there was a submit or +* retire during ring switch +*/ +a5xx_preempt_trigger (gpu); }void a5xx_preempt_hw_init (struct msm_gpu *gpu)
@@ -300,5 +319,6 @@ void a5xx_preempt_init(struct msm_gpu *gpu) } } +spin_lock_init (&a5xx_gpu->preempt_start_lock);timer_setup (&a5xx_gpu->preempt_timer, a5xx_preempt_timer,0 ); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 162/538 drm/msm/a5xx: workaround early ring-buffer emptiness check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Lypak <[email protected]>
[ Upstream commit a30f9f65b5ac82d4390548c32ed9c7f05de7ddf5 ]
There is another cause for soft lock-up of GPU in empty ring-buffer:
race between GPU executing last commands and CPU checking ring for emptiness. On GPU side IRQ for retire is triggered by CACHE_FLUSH_TS event and RPTR shadow (which is used to check ring emptiness) is updated a bit later from CP_CONTEXT_SWITCH_YIELD. Thus if GPU is executing its last commands slow enough or we check that ring too fast we will miss a chance to trigger switch to lower priority ring because current ring isn't empty just yet. This can escalate to lock-up situation described in previous patch.
To work-around this issue we keep track of last submit sequence number for each ring and compare it with one written to memptrs from GPU during execution of CACHE_FLUSH_TS event.
Patchwork: https://patchwork.freedesktop.org/patch/612047/
--- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 4 ++++ drivers/gpu/drm/msm/adreno/a5xx_gpu.h | 1 + drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 4 ++++ 3 files changed, 9 insertions(+)
drivers/gpu/drm/msm/adreno/a5xx_gpu.c +4 -0
@@ -65,6 +65,8 @@ void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring,static void a5xx_submit_in_rb (struct msm_gpu *gpu,struct msm_gem_submit *submit) { +struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu); +struct a5xx_gpu *a5xx_gpu =to_a5xx_gpu (adreno_gpu);struct msm_ringbuffer *ring = submit->ring;struct drm_gem_object *obj;uint32_t *ptr, dwords;
@@ -109,6 +111,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit } } + a5xx_gpu->last_seqno[ring->id] = submit->seqno;a5xx_flush (gpu, ring, true);a5xx_preempt_trigger (gpu);
@@ -210,6 +213,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)/* Write the fence to the scratch register */ OUT_PKT4 (ring,REG_A5XX_CP_SCRATCH_REG (2 ),1 );OUT_RING (ring, submit->seqno); + a5xx_gpu->last_seqno[ring->id] = submit->seqno;/* * Execute a CACHE_FLUSH_TS event. This will ensure that the
drivers/gpu/drm/msm/adreno/a5xx_gpu.h +1 -0
@@ -34,6 +34,7 @@ struct a5xx_gpu {struct drm_gem_object *preempt_counters_bo[MSM_GPU_MAX_RINGS ];struct a5xx_preempt_record *preempt[MSM_GPU_MAX_RINGS ];uint64_t preempt_iova[MSM_GPU_MAX_RINGS ]; +uint32_t last_seqno[MSM_GPU_MAX_RINGS ];atomic_t preempt_state;spinlock_t preempt_start_lock;
drivers/gpu/drm/msm/adreno/a5xx_preempt.c +4 -0
@@ -55,6 +55,8 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)/* Return the highest priority ringbuffer with something in it */ static struct msm_ringbuffer *get_next_ring (struct msm_gpu *gpu) { +struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu); +struct a5xx_gpu *a5xx_gpu =to_a5xx_gpu (adreno_gpu);unsigned long flags;int i;
@@ -64,6 +66,8 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu)spin_lock_irqsave (&ring->preempt_lock, flags); empty = (get_wptr (ring) == gpu->funcs->get_rptr (gpu, ring)); +if (!empty && ring == a5xx_gpu->cur_ring) + empty = ring->memptrs->fence == a5xx_gpu->last_seqno[i];spin_unlock_irqrestore (&ring->preempt_lock, flags);if (!empty)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 163/538 ipmi: docs: dont advertise deprecated sysfs entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit 64dce81f8c373c681e62d5ffe0397c45a35d48a2 ]
"i2c-adapter" class entries are deprecated since 2009. Switch to the proper location.
Message-Id: <[email protected]>
--- Documentation/driver-api/ipmi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/driver-api/ipmi.rst +1 -1
@@ -540,7 +540,7 @@ at module load time (for a module) with:: alerts_broken The addresses are normal I2C addresses. The adapter is the string -name of the adapter, as shown in /sys/class/i2c-adapter/i2c-<n>/name. +name of the adapter, as shown in /sys/bus/i2c/devices/i2c-<n>/name. It is *NOT* i2c-<n> itself. Also, the comparison is done ignoring spaces, so if the name is "This is an I2C chip" you can say adapter_name=ThisisanI2cchip. This is because it's hard to pass in
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 164/538 drm/msm/dsi: correct programming sequence for SM8350 / SM8450
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 1328cb7c34bf6d056df9ff694ee5194537548258 ]
According to the display-drivers, 5nm DSI PLL (v4.2, v4.3) have different boundaries for pll_clock_inverters programming. Follow the vendor code and use correct values.
Patchwork: https://patchwork.freedesktop.org/patch/606947/
--- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +11 -1
@@ -135,7 +135,7 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config config->pll_clock_inverters =0x00 ; else config->pll_clock_inverters = 0x40; - }else { + }else if (pll->phy->cfg->quirks &DSI_PHY_7NM_QUIRK_V4_1 ) {if (pll_freq <=1000000000ULL ) config->pll_clock_inverters =0xa0 ;else if (pll_freq <=2500000000ULL )
@@ -144,6 +144,16 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config config->pll_clock_inverters =0x00 ; else config->pll_clock_inverters = 0x40; + }else { +/* 4.2, 4.3 */ +if (pll_freq <=1000000000ULL ) + config->pll_clock_inverters =0xa0 ; +else if (pll_freq <=2500000000ULL ) + config->pll_clock_inverters =0x20 ; +else if (pll_freq <=3500000000ULL ) + config->pll_clock_inverters =0x00 ; +else + config->pll_clock_inverters =0x40 ; } config->decimal_div_start = dec;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 165/538 drm/msm: fix %s null argument error
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sherry Yang <[email protected]>
[ Upstream commit 25b85075150fe8adddb096db8a4b950353045ee1 ]
The following build error was triggered because of NULL string argument:
BUILDSTDERR: drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c: In function 'mdp5_smp_dump': BUILDSTDERR: drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c:352:51: error: '%s' directive argument is null [-Werror=format-overflow=] BUILDSTDERR: 352 | drm_printf(p, "%s:%d\t%d\t%s\n", BUILDSTDERR: | ^~ BUILDSTDERR: drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c:352:51: error: '%s' directive argument is null [-Werror=format-overflow=]
This happens from the commit a61ddb4393ad ("drm: enable (most) W=1 warnings by default across the subsystem"). Using "(null)" instead to fix it.
Patchwork: https://patchwork.freedesktop.org/patch/611071/
--- drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +1 -1
@@ -356,7 +356,7 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p)drm_printf (p,"%s:%d\t%d\t%s\n" ,pipe2name (pipe), j, inuse, - plane ? plane->name :NULL ); + plane ? plane->name :"(null)" ); total += inuse; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 166/538 drivers:drm:exynos_drm_gsc:Fix wrong assignment in gsc_bind()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuesong Li <[email protected]>
[ Upstream commit 94ebc3d3235c5c516f67315059ce657e5090e94b ]
cocci reported a double assignment problem. Upon reviewing previous commits, it appears this may actually be an incorrect assignment.
--- drivers/gpu/drm/exynos/exynos_drm_gsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/exynos/exynos_drm_gsc.c +1 -1
@@ -1173,7 +1173,7 @@ static int gsc_bind(struct device *dev, struct device *master, void *data)struct exynos_drm_ipp *ipp = &ctx->ipp; ctx->drm_dev = drm_dev; - ctx->drm_dev = drm_dev; + ipp->drm_dev = drm_dev;exynos_drm_register_dma (drm_dev, dev, &ctx->dma_priv); exynos_drm_ipp_register(dev, ipp, &ipp_funcs,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 167/538 xen: use correct end address of kernel for conflict checking
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juergen Gross <[email protected]>
[ Upstream commit fac1bceeeb04886fc2ee952672e6e6c85ce41dca ]
When running as a Xen PV dom0 the kernel is loaded by the hypervisor using a different memory map than that of the host. In order to minimize the required changes in the kernel, the kernel adapts its memory map to that of the host. In order to do that it is checking for conflicts of its load address with the host memory map.
Unfortunately the tested memory range does not include the .brk area, which might result in crashes or memory corruption when this area does conflict with the memory map of the host.
Fix the test by using the _end label instead of __bss_stop.
--- arch/x86/xen/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/xen/setup.c +1 -1
@@ -825,7 +825,7 @@ char * __init xen_memory_setup(void)* to relocating (and even reusing) pages with kernel text or data. */ if (xen_is_e820_reserved (__pa_symbol (_text), -__pa_symbol (__bss_stop) -__pa_symbol (_text))) { +__pa_symbol (_end) -__pa_symbol (_text))) {xen_raw_console_write ("Xen hypervisor allocated kernel memory conflicts with E820 map\n" );BUG (); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 168/538 HID: wacom: Support sequence numbers smaller than 16-bit
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gerecke <[email protected]>
[ Upstream commit 359673ea3a203611b4f6d0f28922a4b9d2cfbcc8 ]
The current dropped packet reporting assumes that all sequence numbers are 16 bits in length. This results in misleading "Dropped" messages if the hardware uses fewer bits. For example, if a tablet uses only 8 bits to store its sequence number, once it rolls over from 255 -> 0, the driver will still be expecting a packet "256". This patch adjusts the logic to reset the next expected packet to logical_minimum whenever it overflows beyond logical_maximum.
--- drivers/hid/wacom_wac.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/hid/wacom_wac.c +7 -2
@@ -2492,9 +2492,14 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field wacom_wac->hid_data.barrelswitch3 = value;return ;case WACOM_HID_WD_SEQUENCENUMBER : -if (wacom_wac->hid_data.sequence_number != value) -hid_warn (hdev,"Dropped %hu packets" , (unsigned short )(value - wacom_wac->hid_data.sequence_number)); +if (wacom_wac->hid_data.sequence_number != value) { +int sequence_size = field->logical_maximum - field->logical_minimum +1 ; +int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size; +hid_warn (hdev,"Dropped %d packets" , drop_count); + } wacom_wac->hid_data.sequence_number = value +1 ; +if (wacom_wac->hid_data.sequence_number > field->logical_maximum) + wacom_wac->hid_data.sequence_number = field->logical_minimum;return ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 169/538 HID: wacom: Do not warn about dropped packets for first packet
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gerecke <[email protected]>
[ Upstream commit 84aecf2d251a3359bc78b7c8e58f54b9fc966e89 ]
The driver currently assumes that the first sequence number it will see is going to be 0. This is not a realiable assumption and can break if, for example, the tablet has already been running for some time prior to the kernel driver connecting to the device. This commit initializes the expected sequence number to -1 and will only print the "Dropped" warning the it has been updated to a non-negative value.
--- drivers/hid/wacom_wac.c | 6 +++++- drivers/hid/wacom_wac.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-)
drivers/hid/wacom_wac.c +5 -1
@@ -2368,6 +2368,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,wacom_map_usage (input, usage, field,EV_KEY ,BTN_STYLUS3 ,0 ); features->quirks &= ~WACOM_QUIRK_PEN_BUTTON3 ;break ; +case WACOM_HID_WD_SEQUENCENUMBER : + wacom_wac->hid_data.sequence_number =-1 ; +break ; } }
@@ -2492,7 +2495,8 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field wacom_wac->hid_data.barrelswitch3 = value;return ;case WACOM_HID_WD_SEQUENCENUMBER : -if (wacom_wac->hid_data.sequence_number != value) { +if (wacom_wac->hid_data.sequence_number != value && + wacom_wac->hid_data.sequence_number >=0 ) {int sequence_size = field->logical_maximum - field->logical_minimum +1 ;int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;hid_warn (hdev,"Dropped %d packets" , drop_count);
drivers/hid/wacom_wac.h +1 -1
@@ -324,7 +324,7 @@ struct hid_data {int bat_connected;int ps_connected;bool pad_input_event_flag; -unsigned short sequence_number; +int sequence_number;ktime_t time_delayed; };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 170/538 ata: libata: Clear DID_TIME_OUT for ATA PT commands with sense data
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Cassel <[email protected]>
[ Upstream commit e5dd410acb34c7341a0a93b429dcf3dabf9e3323 ]
When ata_qc_complete() schedules a command for EH using ata_qc_schedule_eh(), blk_abort_request() will be called, which leads to req->q->mq_ops->timeout() / scsi_timeout() being called.
scsi_timeout(), if the LLDD has no abort handler (libata has no abort handler), will set host byte to DID_TIME_OUT, and then call scsi_eh_scmd_add() to add the command to EH.
Thus, when commands first enter libata's EH strategy_handler, all the commands that have been added to EH will have DID_TIME_OUT set.
libata has its own flag (AC_ERR_TIMEOUT), that it sets for commands that have not received a completion at the time of entering EH.
Thus, libata doesn't really care about DID_TIME_OUT at all, and currently clears the host byte at the end of EH, in ata_scsi_qc_complete(), before scsi_eh_finish_cmd() is called.
However, this clearing in ata_scsi_qc_complete() is currently only done for commands that are not ATA passthrough commands.
Since the host byte is visible in the completion that we return to user space for ATA passthrough commands, for ATA passthrough commands that got completed via EH (commands with sense data), the user will incorrectly see:
ATA pass-through(16): transport error: Host_status=0x03 [DID_TIME_OUT]
Fix this by moving the clearing of the host byte (which is currently only done for commands that are not ATA passthrough commands) from ata_scsi_qc_complete() to the start of EH (regardless if the command is ATA passthrough or not).
While at it, use the proper helper function to clear the host byte, rather than open coding the clearing.
This will make sure that we:
-Correctly clear DID_TIME_OUT for both ATA passthrough commands and
commands that are not ATA passthrough commands.
-Do not needlessly clear the host byte for commands that did not go via EH.
ata_scsi_qc_complete() is called both for commands that are completed normally (without going via EH), and for commands that went via EH, however, only commands that went via EH will have DID_TIME_OUT set.
--- drivers/ata/libata-eh.c | 8 ++++++++ drivers/ata/libata-scsi.c | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-)
drivers/ata/libata-eh.c +8 -0
@@ -618,6 +618,14 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,list_for_each_entry_safe (scmd, tmp, eh_work_q, eh_entry) {struct ata_queued_cmd *qc; +/* +* If the scmd was added to EH, via ata_qc_schedule_eh() -> +* scsi_timeout() -> scsi_eh_scmd_add(), scsi_timeout() will +* have set DID_TIME_OUT (since libata does not have an abort +* handler). Thus, to clear DID_TIME_OUT, clear the host byte. +*/ +set_host_byte (scmd,DID_OK ); +ata_qc_for_each_raw (ap, qc, i) {if (qc->flags &ATA_QCFLAG_ACTIVE && qc->scsicmd == scmd)
drivers/ata/libata-scsi.c +0 -3
@@ -1725,9 +1725,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)set_status_byte (qc->scsicmd,SAM_STAT_CHECK_CONDITION ); }else if (is_error && !have_sense) {ata_gen_ata_sense (qc); - }else { -/* Keep the SCSI ML and status byte, clear host byte. */ - cmd->result &=0x0000ffff ; }ata_qc_done (qc);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 171/538 minmax: avoid overly complex min()/max() macro arguments in xen
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
[ Upstream commit e8432ac802a028eaee6b1e86383d7cd8e9fb8431 ]
We have some very fancy min/max macros that have tons of sanity checking to warn about mixed signedness etc.
This is all things that a sane compiler should warn about, but there are no sane compiler interfaces for this, and '-Wsign-compare' is broken [1] and not useful.
So then we compensate (some would say over-compensate) by doing the checks manually with some truly horrid macro games.
And no, we can't just use __builtin_types_compatible_p(), because the whole question of "does it make sense to compare these two values" is a lot more complicated than that.
For example, it makes a ton of sense to compare unsigned values with simple constants like "5", even if that is indeed a signed type. So we have these very strange macros to try to make sensible type checking decisions on the arguments to 'min()' and 'max()'.
But that can cause enormous code expansion if the min()/max() macros are used with complicated expressions, and particularly if you nest these things so that you get the first big expansion then expanded again.
The xen setup.c file ended up ballooning to over 50MB of preprocessed noise that takes 15s to compile (obviously depending on the build host), largely due to one single line.
So let's split that one single line to just be simpler. I think it ends up being more legible to humans too at the same time. Now that single file compiles in under a second.
Stable-dep-of: be35d91c8880 ("xen: tolerate ACPI NVS memory overlapping with Xen allocated memory")
--- arch/x86/xen/setup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/xen/setup.c +3 -2
@@ -691,6 +691,7 @@ char * __init xen_memory_setup(void)struct xen_memory_map memmap;unsigned long max_pages;unsigned long extra_pages =0 ; +unsigned long maxmem_pages;int i;int op;
@@ -762,8 +763,8 @@ char * __init xen_memory_setup(void)* Make sure we have no memory above max_pages, as this area * isn't handled by the p2m management. */ - extra_pages =min3 (EXTRA_MEM_RATIO *min (max_pfn,PFN_DOWN (MAXMEM )), - extra_pages, max_pages - max_pfn); + maxmem_pages =EXTRA_MEM_RATIO *min (max_pfn,PFN_DOWN (MAXMEM )); + extra_pages =min3 (maxmem_pages, extra_pages, max_pages - max_pfn); i =0 ; addr = xen_e820_table.entries[0 ].addr; size = xen_e820_table.entries[0 ].size;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 172/538 xen: introduce generic helper checking for memory map conflicts
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juergen Gross <[email protected]>
[ Upstream commit ba88829706e2c5b7238638fc2b0713edf596495e ]
When booting as a Xen PV dom0 the memory layout of the dom0 is modified to match that of the host, as this requires less changes in the kernel for supporting Xen.
There are some cases, though, which are problematic, as it is the Xen hypervisor selecting the kernel's load address plus some other data, which might conflict with the host's memory map.
These conflicts are detected at boot time and result in a boot error. In order to support handling at least some of these conflicts in future, introduce a generic helper function which will later gain the ability to adapt the memory layout when possible.
Add the missing check for the xen_start_info area.
Note that possible p2m map and initrd memory conflicts are handled already by copying the data to memory areas not conflicting with the memory map. The initial stack allocated by Xen doesn't need to be checked, as early boot code is switching to the statically allocated initial kernel stack. Initial page tables and the kernel itself will be handled later.
Stable-dep-of: be35d91c8880 ("xen: tolerate ACPI NVS memory overlapping with Xen allocated memory")
--- arch/x86/xen/mmu_pv.c | 5 +---- arch/x86/xen/setup.c | 34 ++++++++++++++++++++++++++++------ arch/x86/xen/xen-ops.h | 3 ++- 3 files changed, 31 insertions(+), 11 deletions(-)
arch/x86/xen/mmu_pv.c +1 -4
@@ -2019,10 +2019,7 @@ void __init xen_reserve_special_pages(void)void __init xen_pt_check_e820 (void ) { -if (xen_is_e820_reserved (xen_pt_base, xen_pt_size)) { -xen_raw_console_write ("Xen hypervisor allocated page table memory conflicts with E820 map\n" ); -BUG (); - } +xen_chk_is_e820_usable (xen_pt_base, xen_pt_size,"page table" ); } static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss;
arch/x86/xen/setup.c +28 -6
@@ -568,7 +568,7 @@ static void __init xen_ignore_unusable(void) } } -bool __init xen_is_e820_reserved (phys_addr_t start,phys_addr_t size) +static bool __init xen_is_e820_reserved (phys_addr_t start,phys_addr_t size) {struct e820_entry *entry;unsigned mapcnt;
@@ -625,6 +625,23 @@ phys_addr_t __init xen_find_free_area(phys_addr_t size)return 0 ; } +/* +* Check for an area in physical memory to be usable for non-movable purposes. +* An area is considered to usable if the used E820 map lists it to be RAM. +* In case the area is not usable, crash the system with an error message. +*/ +void __init xen_chk_is_e820_usable (phys_addr_t start,phys_addr_t size, +const char *component) +{ +if (!xen_is_e820_reserved (start, size)) +return ; + +xen_raw_console_write ("Xen hypervisor allocated " ); +xen_raw_console_write (component); +xen_raw_console_write (" memory conflicts with E820 map\n" ); +BUG (); +} +/* * Like memcpy, but with physical addresses for dest and src. */
@@ -825,11 +842,16 @@ char * __init xen_memory_setup(void)* Failing now is better than running into weird problems later due * to relocating (and even reusing) pages with kernel text or data. */ -if (xen_is_e820_reserved (__pa_symbol (_text), -__pa_symbol (_end) -__pa_symbol (_text))) { -xen_raw_console_write ("Xen hypervisor allocated kernel memory conflicts with E820 map\n" ); -BUG (); - } +xen_chk_is_e820_usable (__pa_symbol (_text), +__pa_symbol (_end) -__pa_symbol (_text), +"kernel" ); + +/* +* Check for a conflict of the xen_start_info memory with the target +* E820 map. +*/ +xen_chk_is_e820_usable (__pa (xen_start_info),sizeof (*xen_start_info), +"xen_start_info" );/* * Check for a conflict of the hypervisor supplied page tables with
arch/x86/xen/xen-ops.h +2 -1
@@ -44,7 +44,8 @@ void xen_mm_unpin_all(void);void __init xen_relocate_p2m (void );#endif -bool __init xen_is_e820_reserved (phys_addr_t start,phys_addr_t size); +void __init xen_chk_is_e820_usable (phys_addr_t start,phys_addr_t size, +const char *component);unsigned long __ref xen_chk_extra_mem (unsigned long pfn);void __init xen_inv_extra_mem (void );void __init xen_remap_memory (void );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 173/538 xen: move max_pfn in xen_memory_setup() out of function scope
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juergen Gross <[email protected]>
[ Upstream commit 43dc2a0f479b9cd30f6674986d7a40517e999d31 ]
Instead of having max_pfn as a local variable of xen_memory_setup(), make it a static variable in setup.c instead. This avoids having to pass it to subfunctions, which will be needed in more cases in future.
Rename it to ini_nr_pages, as the value denotes the currently usable number of memory pages as passed from the hypervisor at boot time.
Stable-dep-of: be35d91c8880 ("xen: tolerate ACPI NVS memory overlapping with Xen allocated memory")
--- arch/x86/xen/setup.c | 52 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-)
arch/x86/xen/setup.c +26 -26
@@ -47,6 +47,9 @@ bool xen_pv_pci_possible;/* E820 map used during setting up memory. */ static struct e820_table xen_e820_table__initdata ; +/* Number of initially usable memory pages. */ +static unsigned long ini_nr_pages__initdata ; +/* * Buffer used to remap identity mapped pages. We only need the virtual space. * The physical page behind this address is remapped as needed to different
@@ -213,7 +216,7 @@ static int __init xen_free_mfn(unsigned long mfn)* as a fallback if the remapping fails. */ static void __init xen_set_identity_and_release_chunk (unsigned long start_pfn, -unsigned long end_pfn,unsigned long nr_pages) +unsigned long end_pfn) {unsigned long pfn, end;int ret;
@@ -221,7 +224,7 @@ static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn,WARN_ON (start_pfn > end_pfn);/* Release pages first. */ - end =min (end_pfn, nr_pages); + end =min (end_pfn, ini_nr_pages);for (pfn = start_pfn; pfn < end; pfn++) {unsigned long mfn =pfn_to_mfn (pfn);
@@ -342,15 +345,14 @@ static void __init xen_do_set_identity_and_remap_chunk(* to Xen and not remapped. */ static unsigned long __init xen_set_identity_and_remap_chunk ( -unsigned long start_pfn,unsigned long end_pfn,unsigned long nr_pages, -unsigned long remap_pfn) +unsigned long start_pfn,unsigned long end_pfn,unsigned long remap_pfn) {unsigned long pfn;unsigned long i =0 ;unsigned long n = end_pfn - start_pfn;if (remap_pfn ==0 ) - remap_pfn = nr_pages; + remap_pfn = ini_nr_pages;while (i < n) {unsigned long cur_pfn = start_pfn + i;
@@ -359,19 +361,19 @@ static unsigned long __init xen_set_identity_and_remap_chunk(unsigned long remap_range_size;/* Do not remap pages beyond the current allocation */ -if (cur_pfn >= nr_pages) { +if (cur_pfn >= ini_nr_pages) {/* Identity map remaining pages */ set_phys_range_identity (cur_pfn, cur_pfn + size);break ; } -if (cur_pfn + size > nr_pages) - size = nr_pages - cur_pfn; +if (cur_pfn + size > ini_nr_pages) + size = ini_nr_pages - cur_pfn; remap_range_size =xen_find_pfn_range (&remap_pfn);if (!remap_range_size) {pr_warn ("Unable to find available pfn range, not remapping identity pages\n" );xen_set_identity_and_release_chunk (cur_pfn, - cur_pfn + left, nr_pages); + cur_pfn + left);break ; }/* Adjust size to fit in current e820 RAM region */
@@ -398,18 +400,18 @@ static unsigned long __init xen_set_identity_and_remap_chunk( }static unsigned long __init xen_count_remap_pages ( -unsigned long start_pfn,unsigned long end_pfn,unsigned long nr_pages, +unsigned long start_pfn,unsigned long end_pfn,unsigned long remap_pages) { -if (start_pfn >= nr_pages) +if (start_pfn >= ini_nr_pages)return remap_pages; -return remap_pages +min (end_pfn, nr_pages) - start_pfn; +return remap_pages +min (end_pfn, ini_nr_pages) - start_pfn; } -static unsigned long __init xen_foreach_remap_area (unsigned long nr_pages, +static unsigned long __init xen_foreach_remap_area (unsigned long (*func)(unsigned long start_pfn,unsigned long end_pfn, -unsigned long nr_pages,unsigned long last_val)) +unsigned long last_val)) {phys_addr_t start =0 ;unsigned long ret_val =0 ;
@@ -437,8 +439,7 @@ static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, end_pfn =PFN_UP (entry->addr);if (start_pfn < end_pfn) - ret_val =func (start_pfn, end_pfn, nr_pages, - ret_val); + ret_val =func (start_pfn, end_pfn, ret_val); start = end; } }
@@ -701,7 +702,7 @@ static void __init xen_reserve_xen_mfnlist(void)**/ char *__init xen_memory_setup (void ) { -unsigned long max_pfn, pfn_s, n_pfns; +unsigned long pfn_s, n_pfns;phys_addr_t mem_end, addr, size, chunk_size;u32 type;int rc;
@@ -713,9 +714,8 @@ char * __init xen_memory_setup(void)int op;xen_parse_512gb (); - max_pfn =xen_get_pages_limit (); - max_pfn =min (max_pfn, xen_start_info->nr_pages); - mem_end =PFN_PHYS (max_pfn); + ini_nr_pages =min (xen_get_pages_limit (), xen_start_info->nr_pages); + mem_end =PFN_PHYS (ini_nr_pages); memmap.nr_entries =ARRAY_SIZE (xen_e820_table.entries);set_xen_guest_handle (memmap.buffer, xen_e820_table.entries);
@@ -768,10 +768,10 @@ char * __init xen_memory_setup(void) max_pages =xen_get_max_pages ();/* How many extra pages do we need due to remapping? */ - max_pages +=xen_foreach_remap_area (max_pfn, xen_count_remap_pages); + max_pages +=xen_foreach_remap_area (xen_count_remap_pages); -if (max_pages > max_pfn) - extra_pages += max_pages - max_pfn; +if (max_pages > ini_nr_pages) + extra_pages += max_pages - ini_nr_pages;/* * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
@@ -780,8 +780,8 @@ char * __init xen_memory_setup(void)* Make sure we have no memory above max_pages, as this area * isn't handled by the p2m management. */ - maxmem_pages =EXTRA_MEM_RATIO *min (max_pfn,PFN_DOWN (MAXMEM )); - extra_pages =min3 (maxmem_pages, extra_pages, max_pages - max_pfn); + maxmem_pages =EXTRA_MEM_RATIO *min (ini_nr_pages,PFN_DOWN (MAXMEM )); + extra_pages =min3 (maxmem_pages, extra_pages, max_pages - ini_nr_pages); i =0 ; addr = xen_e820_table.entries[0 ].addr; size = xen_e820_table.entries[0 ].size;
@@ -886,7 +886,7 @@ char * __init xen_memory_setup(void)* Set identity map on non-RAM pages and prepare remapping the * underlying RAM. */ -xen_foreach_remap_area (max_pfn, xen_set_identity_and_remap_chunk); +xen_foreach_remap_area (xen_set_identity_and_remap_chunk);pr_info ("Released %ld page(s)\n" , xen_released_pages);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 174/538 xen: add capability to remap non-RAM pages to different PFNs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juergen Gross <[email protected]>
[ Upstream commit d05208cf7f05420ad10cc7f9550f91d485523659 ]
When running as a Xen PV dom0 it can happen that the kernel is being loaded to a guest physical address conflicting with the host memory map.
In order to be able to resolve this conflict, add the capability to remap non-RAM areas to different guest PFNs. A function to use this remapping information for other purposes than doing the remap will be added when needed.
As the number of conflicts should be rather low (currently only machines with max. 1 conflict are known), save the remap data in a small statically allocated array.
Stable-dep-of: be35d91c8880 ("xen: tolerate ACPI NVS memory overlapping with Xen allocated memory")
--- arch/x86/xen/p2m.c | 63 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/xen/xen-ops.h | 3 ++ 2 files changed, 66 insertions(+)
arch/x86/xen/p2m.c +63 -0
@@ -80,6 +80,7 @@#include <asm/xen/hypervisor.h> #include <xen/balloon.h> #include <xen/grant_table.h> +#include <xen/hvc-console.h> #include "multicalls.h" #include "xen-ops.h"
@@ -794,6 +795,68 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,return ret; } +/* Remapped non-RAM areas */ +#define NR_NONRAM_REMAP 4 +static struct nonram_remap { +phys_addr_t maddr; +phys_addr_t paddr; +size_t size; +} xen_nonram_remap[NR_NONRAM_REMAP ]__ro_after_init ; +static unsigned int nr_nonram_remap__ro_after_init ; + +/* +* Do the real remapping of non-RAM regions as specified in the +* xen_nonram_remap[] array. +* In case of an error just crash the system. +*/ +void __init xen_do_remap_nonram (void ) +{ +unsigned int i; +unsigned int remapped =0 ; +const struct nonram_remap *remap = xen_nonram_remap; +unsigned long pfn, mfn, end_pfn; + +for (i =0 ; i < nr_nonram_remap; i++) { + end_pfn =PFN_UP (remap->paddr + remap->size); + pfn =PFN_DOWN (remap->paddr); + mfn =PFN_DOWN (remap->maddr); +while (pfn < end_pfn) { +if (!set_phys_to_machine (pfn, mfn)) +panic ("Failed to set p2m mapping for pfn=%lx mfn=%lx\n" , + pfn, mfn); + + pfn++; + mfn++; + remapped++; + } + + remap++; + } + +pr_info ("Remapped %u non-RAM page(s)\n" , remapped); +} + +/* +* Add a new non-RAM remap entry. +* In case of no free entry found, just crash the system. +*/ +void __init xen_add_remap_nonram (phys_addr_t maddr,phys_addr_t paddr, +unsigned long size) +{ +BUG_ON ((maddr & ~PAGE_MASK ) != (paddr & ~PAGE_MASK )); + +if (nr_nonram_remap ==NR_NONRAM_REMAP ) { +xen_raw_console_write ("Number of required E820 entry remapping actions exceed maximum value\n" ); +BUG (); + } + + xen_nonram_remap[nr_nonram_remap].maddr = maddr; + xen_nonram_remap[nr_nonram_remap].paddr = paddr; + xen_nonram_remap[nr_nonram_remap].size = size; + + nr_nonram_remap++; +} +#ifdef CONFIG_XEN_DEBUG_FS #include <linux/debugfs.h> #include "debugfs.h"
arch/x86/xen/xen-ops.h +3 -0
@@ -43,6 +43,9 @@ void xen_mm_unpin_all(void);#ifdef CONFIG_X86_64 void __init xen_relocate_p2m (void );#endif +void __init xen_do_remap_nonram (void ); +void __init xen_add_remap_nonram (phys_addr_t maddr,phys_addr_t paddr, +unsigned long size);void __init xen_chk_is_e820_usable (phys_addr_t start,phys_addr_t size,const char *component);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 175/538 xen: tolerate ACPI NVS memory overlapping with Xen allocated memory
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juergen Gross <[email protected]>
[ Upstream commit be35d91c8880650404f3bf813573222dfb106935 ]
In order to minimize required special handling for running as Xen PV dom0, the memory layout is modified to match that of the host. This requires to have only RAM at the locations where Xen allocated memory is living. Unfortunately there seem to be some machines, where ACPI NVS is located at 64 MB, resulting in a conflict with the loaded kernel or the initial page tables built by Xen.
Avoid this conflict by swapping the ACPI NVS area in the memory map with unused RAM. This is possible via modification of the dom0 P2M map. Accesses to the ACPI NVS area are done either for saving and restoring it across suspend operations (this will work the same way as before), or by ACPI code when NVS memory is referenced from other ACPI tables. The latter case is handled by a Xen specific indirection of acpi_os_ioremap().
While the E820 map can (and should) be modified right away, the P2M map can be updated only after memory allocation is working, as the P2M map might need to be extended.
--- arch/x86/xen/setup.c | 92 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-)
arch/x86/xen/setup.c +91 -1
@@ -496,6 +496,8 @@ void __init xen_remap_memory(void)set_pte_mfn (buf, mfn_save,PAGE_KERNEL );pr_info ("Remapped %ld page(s)\n" , remapped); + +xen_do_remap_nonram (); }static unsigned long __init xen_get_pages_limit (void )
@@ -626,14 +628,102 @@ phys_addr_t __init xen_find_free_area(phys_addr_t size)return 0 ; } +/* +* Swap a non-RAM E820 map entry with RAM above ini_nr_pages. +* Note that the E820 map is modified accordingly, but the P2M map isn't yet. +* The adaption of the P2M must be deferred until page allocation is possible. +*/ +static void __init xen_e820_swap_entry_with_ram (struct e820_entry *swap_entry) +{ +struct e820_entry *entry; +unsigned int mapcnt; +phys_addr_t mem_end =PFN_PHYS (ini_nr_pages); +phys_addr_t swap_addr, swap_size, entry_end; + + swap_addr =PAGE_ALIGN_DOWN (swap_entry->addr); + swap_size =PAGE_ALIGN (swap_entry->addr - swap_addr + swap_entry->size); + entry = xen_e820_table.entries; + +for (mapcnt =0 ; mapcnt < xen_e820_table.nr_entries; mapcnt++) { + entry_end = entry->addr + entry->size; +if (entry->type ==E820_TYPE_RAM && entry->size >= swap_size && + entry_end - swap_size >= mem_end) { +/* Reduce RAM entry by needed space (whole pages). */ + entry->size -= swap_size; + +/* Add new entry at the end of E820 map. */ + entry = xen_e820_table.entries + + xen_e820_table.nr_entries; + xen_e820_table.nr_entries++; + +/* Fill new entry (keep size and page offset). */ + entry->type = swap_entry->type; + entry->addr = entry_end - swap_size + + swap_addr - swap_entry->addr; + entry->size = swap_entry->size; + +/* Convert old entry to RAM, align to pages. */ + swap_entry->type =E820_TYPE_RAM ; + swap_entry->addr = swap_addr; + swap_entry->size = swap_size; + +/* Remember PFN<->MFN relation for P2M update. */ +xen_add_remap_nonram (swap_addr, entry_end - swap_size, + swap_size); + +/* Order E820 table and merge entries. */ +e820__update_table (&xen_e820_table); + +return ; + } + + entry++; + } + +xen_raw_console_write ("No suitable area found for required E820 entry remapping action\n" ); +BUG (); +} + +/* +* Look for non-RAM memory types in a specific guest physical area and move +* those away if possible (ACPI NVS only for now). +*/ +static void __init xen_e820_resolve_conflicts (phys_addr_t start, +phys_addr_t size) +{ +struct e820_entry *entry; +unsigned int mapcnt; +phys_addr_t end; + +if (!size) +return ; + + end = start + size; + entry = xen_e820_table.entries; + +for (mapcnt =0 ; mapcnt < xen_e820_table.nr_entries; mapcnt++) { +if (entry->addr >= end) +return ; + +if (entry->addr + entry->size > start && + entry->type ==E820_TYPE_NVS ) +xen_e820_swap_entry_with_ram (entry); + + entry++; + } +} +/* * Check for an area in physical memory to be usable for non-movable purposes. -* An area is considered to usable if the used E820 map lists it to be RAM. +* An area is considered to usable if the used E820 map lists it to be RAM or +* some other type which can be moved to higher PFNs while keeping the MFNs. * In case the area is not usable, crash the system with an error message. */ void __init xen_chk_is_e820_usable (phys_addr_t start,phys_addr_t size,const char *component) { +xen_e820_resolve_conflicts (start, size); +if (!xen_is_e820_reserved (start, size))return ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 176/538 xen/swiotlb: add alignment check for dma buffers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juergen Gross <[email protected]>
[ Upstream commit 9f40ec84a7976d95c34e7cc070939deb103652b0 ]
When checking a memory buffer to be consecutive in machine memory, the alignment needs to be checked, too. Failing to do so might result in DMA memory not being aligned according to its requested size, leading to error messages like:
4xxx 0000:2b:00.0: enabling device (0140 -> 0142) 4xxx 0000:2b:00.0: Ring address not aligned
4xxx 0000:2b:00.0: Failed to initialise service qat_crypto 4xxx 0000:2b:00.0: Resetting device qat_dev0 4xxx: probe of 0000:2b:00.0 failed with error -14
--- drivers/xen/swiotlb-xen.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/xen/swiotlb-xen.c +6 -0
@@ -78,9 +78,15 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) {unsigned long next_bfn, xen_pfn =XEN_PFN_DOWN (p);unsigned int i, nr_pages =XEN_PFN_UP (xen_offset_in_page (p) + size); +phys_addr_t algn =1ULL << (get_order (size) +PAGE_SHIFT ); next_bfn =pfn_to_bfn (xen_pfn); +/* If buffer is physically aligned, ensure DMA alignment. */ +if (IS_ALIGNED (p, algn) && + !IS_ALIGNED ((phys_addr_t )next_bfn <<XEN_PAGE_SHIFT , algn)) +return 1 ; +for (i =1 ; i < nr_pages; i++)if (pfn_to_bfn (++xen_pfn) != ++next_bfn)return 1 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 177/538 xen/swiotlb: fix allocated size
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juergen Gross <[email protected]>
[ Upstream commit c3dea3d54f4d399f8044547f0f1abdccbdfb0fee ]
The allocated size in xen_swiotlb_alloc_coherent() and xen_swiotlb_free_coherent() is calculated wrong for the case of XEN_PAGE_SIZE not matching PAGE_SIZE. Fix that.
--- drivers/xen/swiotlb-xen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/xen/swiotlb-xen.c +2 -2
@@ -146,7 +146,7 @@ xen_swiotlb_alloc_coherent(struct device *dev, size_t size,void *ret;/* Align the allocation to the Xen page size */ - size =1UL << (order +XEN_PAGE_SHIFT ); + size =ALIGN (size,XEN_PAGE_SIZE ); ret = (void *)__get_free_pages (flags,get_order (size));if (!ret)
@@ -178,7 +178,7 @@ xen_swiotlb_free_coherent(struct device *dev, size_t size, void *vaddr,int order =get_order (size);/* Convert the size to actually allocated. */ - size =1UL << (order +XEN_PAGE_SHIFT ); + size =ALIGN (size,XEN_PAGE_SIZE );if (WARN_ON_ONCE (dma_handle + size -1 > dev->coherent_dma_mask) ||WARN_ON_ONCE (range_straddles_page_boundary (phys, size)))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 178/538 tpm: Clean up TPM space after command failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonathan McDowell <[email protected]>
[ Upstream commit e3aaebcbb7c6b403416f442d1de70d437ce313a7 ]
tpm_dev_transmit prepares the TPM space before attempting command transmission. However if the command fails no rollback of this preparation is done. This can result in transient handles being leaked if the device is subsequently closed with no further commands performed.
Fix this by flushing the space in the event of command transmission failure.
--- drivers/char/tpm/tpm-dev-common.c | 2 ++ drivers/char/tpm/tpm2-space.c | 3 +++ 2 files changed, 5 insertions(+)
drivers/char/tpm/tpm-dev-common.c +2 -0
@@ -47,6 +47,8 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space,if (!ret) ret =tpm2_commit_space (chip, space, buf, &len); +else +tpm2_flush_space (chip); out_rc:return ret ? ret : len;
drivers/char/tpm/tpm2-space.c +3 -0
@@ -166,6 +166,9 @@ void tpm2_flush_space(struct tpm_chip *chip)struct tpm_space *space = &chip->work_space;int i; +if (!space) +return ; +for (i =0 ; i <ARRAY_SIZE (space->context_tbl); i++)if (space->context_tbl[i] && ~space->context_tbl[i])tpm2_flush_context (chip, space->context_tbl[i]);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 179/538 sched/fair: Make SCHED_IDLE entity be preempted in strict hierarchy
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tianchen Ding <[email protected]>
[ Upstream commit faa42d29419def58d3c3e5b14ad4037f0af3b496 ]
Consider the following cgroup:
root
|
------------------------
| |
normal_cgroup idle_cgroup
| | SCHED_IDLE task_A SCHED_NORMAL task_B
According to the cgroup hierarchy, A should preempt B. But current check_preempt_wakeup_fair() treats cgroup se and task separately, so B will preempt A unexpectedly.
Unify the wakeup logic by {c,p}se_is_idle only. This makes SCHED_IDLE of a task a relative policy that is effective only within its own cgroup, similar to the behavior of NICE.
Also fix se_is_idle() definition when !CONFIG_FAIR_GROUP_SCHED.
--- kernel/sched/fair.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
kernel/sched/fair.c +9 -13
@@ -533,7 +533,7 @@ static int cfs_rq_is_idle(struct cfs_rq *cfs_rq)static int se_is_idle (struct sched_entity *se) { -return 0 ; +return task_has_idle_policy (task_of (se)); }#endif /* CONFIG_FAIR_GROUP_SCHED */
@@ -8209,16 +8209,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_if (test_tsk_need_resched (curr))return ; -/* Idle tasks are by definition preempted by non-idle tasks. */ -if (unlikely (task_has_idle_policy (curr)) && -likely (!task_has_idle_policy (p))) - goto preempt; - -/* -* Batch and idle tasks do not preempt non-idle tasks (their preemption -* is driven by the tick): -*/ -if (unlikely (p->policy !=SCHED_NORMAL ) || !sched_feat (WAKEUP_PREEMPTION )) +if (!sched_feat (WAKEUP_PREEMPTION ))return ;find_matching_se (&se, &pse);
@@ -8228,7 +8219,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ pse_is_idle =se_is_idle (pse);/* -* Preempt an idle group in favor of a non-idle group (and don't preempt +* Preempt an idle entity in favor of a non-idle entity (and don't preempt * in the inverse case). */ if (cse_is_idle && !pse_is_idle)
@@ -8236,9 +8227,14 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_if (cse_is_idle != pse_is_idle)return ; +/* +* BATCH and IDLE tasks do not preempt others. +*/ +if (unlikely (p->policy !=SCHED_NORMAL )) +return ; + cfs_rq =cfs_rq_of (se);update_curr (cfs_rq); -/* * XXX pick_eevdf(cfs_rq) != se ? */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 180/538 selftests/bpf: Workaround strict bpf_lsm return value check.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Starovoitov <[email protected]>
[ Upstream commit aa8ebb270c66cea1f56a25d0f938036e91ad085a ]
test_progs-no_alu32 -t libbpf_get_fd_by_id_opts is being rejected by the verifier with the following error due to compiler optimization:
6: (67) r0 <<= 62 ; R0_w=scalar(smax=0x4000000000000000,umax=0xc000000000000000,smin32=0,smax32=umax32=0,var_off=(0x0; 0xc000000000000000))
7: (c7) r0 s>>= 63 ; R0_w=scalar(smin=smin32=-1,smax=smax32=0)
; @ test_libbpf_get_fd_by_id_opts.c:0
8: (57) r0 &= -13 ; R0_w=scalar(smax=0x7ffffffffffffff3,umax=0xfffffffffffffff3,smax32=0x7ffffff3,umax32=0xfffffff3,var_off=(0x0; 0xfffffffffffffff3))
; int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode) @ test_libbpf_get_fd_by_id_opts.c:27 9: (95) exit
At program exit the register R0 has smax=9223372036854775795 should have been in [-4095, 0]
Workaround by adding barrier().
Eventually the verifier will be able to recognize it.
--- .../testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c +1 -0
@@ -31,6 +31,7 @@ int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode)if (fmode &FMODE_WRITE )return -EACCES ; +barrier ();return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 181/538 selftests/bpf: Fix error linking uprobe_multi on mips
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit a5f40d596bff182b4b47547712f540885e8fb17b ]
Linking uprobe_multi.c on mips64el fails due to relocation overflows, when the GOT entries required exceeds the default maximum. Add a specific CFLAGS (-mxgot) for uprobe_multi.c on MIPS that allows using a larger GOT and avoids errors such as:
/tmp/ccBTNQzv.o: in function `bench':
uprobe_multi.c:49:(.text+0x1d7720): relocation truncated to fit: R_MIPS_GOT_DISP against uprobe_multi_func_08188' uprobe_multi.c:49:(.text+0x1d7730): relocation truncated to fit: R_MIPS_GOT_DISP against uprobe_multi_func_08189'
...
collect2: error: ld returned 1 exit status
--- tools/testing/selftests/bpf/Makefile | 2 ++ 1 file changed, 2 insertions(+)
tools/testing/selftests/bpf/Makefile +2 -0
@@ -702,6 +702,8 @@ $(OUTPUT)/veristat: $(OUTPUT)/veristat.o $(call msg,BINARY,,$@) $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ +# Linking uprobe_multi can fail due to relocation overflows on mips. +$(OUTPUT)/uprobe_multi: CFLAGS += $(if $(filter mips, $(ARCH)),-mxgot) $(OUTPUT)/uprobe_multi: uprobe_multi.c $(call msg,BINARY,,$@) $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 182/538 bpf: Use -Wno-error in certain tests when building with GCC
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jose E. Marchesi <[email protected]>
[ Upstream commit 646751d523587cfd7ebcf1733298ecd470879eda ]
Certain BPF selftests contain code that, albeit being legal C, trigger warnings in GCC that cannot be disabled. This is the case for example for the tests
progs/btf_dump_test_case_bitfields.c
progs/btf_dump_test_case_namespacing.c
progs/btf_dump_test_case_packing.c
progs/btf_dump_test_case_padding.c
progs/btf_dump_test_case_syntax.c
which contain struct type declarations inside function parameter lists. This is problematic, because:
- The BPF selftests are built with -Werror.
- The Clang and GCC compilers sometimes differ when it comes to handle warnings. in the handling of warnings. One compiler may emit warnings for code that the other compiles compiles silently, and one compiler may offer the possibility to disable certain warnings, while the other doesn't.
In order to overcome this problem, this patch modifies the tools/testing/selftests/bpf/Makefile in order to:
1. Enable the possibility of specifing per-source-file extra CFLAGS. This is done by defining a make variable like:
<source-filename>-CFLAGS := <whateverflags>
And then modifying the proper Make rule in order to use these flags when compiling <source-filename>.
2. Use the mechanism above to add -Wno-error to CFLAGS for the following selftests:
progs/btf_dump_test_case_bitfields.c
progs/btf_dump_test_case_namespacing.c
progs/btf_dump_test_case_packing.c
progs/btf_dump_test_case_padding.c
progs/btf_dump_test_case_syntax.c
Note the corresponding -CFLAGS variables for these files are defined only if the selftests are being built with GCC.
Note that, while compiler pragmas can generally be used to disable particular warnings per file, this 1) is only possible for warning that actually can be disabled in the command line, i.e. that have -Wno-FOO options, and 2) doesn't apply to -Wno-error.
Tested in bpf-next master branch.
No regressions.
Stable-dep-of: 3ece93a4087b ("selftests/bpf: Fix wrong binary in Makefile log output")
--- tools/testing/selftests/bpf/Makefile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
tools/testing/selftests/bpf/Makefile +11 -1
@@ -56,6 +56,15 @@ TEST_INST_SUBDIRS := no_alu32 ifneq ($(BPF_GCC),) TEST_GEN_PROGS += test_progs-bpf_gcc TEST_INST_SUBDIRS += bpf_gcc + +# The following tests contain C code that, although technically legal, +# triggers GCC warnings that cannot be disabled: declaration of +# anonymous struct types in function parameter lists. +progs/btf_dump_test_case_bitfields.c-CFLAGS := -Wno-error +progs/btf_dump_test_case_namespacing.c-CFLAGS := -Wno-error +progs/btf_dump_test_case_packing.c-CFLAGS := -Wno-error +progs/btf_dump_test_case_padding.c-CFLAGS := -Wno-error +progs/btf_dump_test_case_syntax.c-CFLAGS := -Wno-error endif ifneq ($(CLANG_CPUV4),)
@@ -492,7 +501,8 @@ $(TRUNNER_BPF_OBJS): $(TRUNNER_OUTPUT)/%.bpf.o: \ $(wildcard $(BPFDIR)/*.bpf.h) \ | $(TRUNNER_OUTPUT) $$(BPFOBJ) $$(call $(TRUNNER_BPF_BUILD_RULE),$$<,$$@, \ - $(TRUNNER_BPF_CFLAGS)) + $(TRUNNER_BPF_CFLAGS) \ + $$($$<-CFLAGS)) $(TRUNNER_BPF_SKELS): %.skel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT) $$(call msg,GEN-SKEL,$(TRUNNER_BINARY),$$@)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 183/538 bpf: Disable some `attribute ignored warnings in GCC
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jose E. Marchesi <[email protected]>
[ Upstream commit b0fbdf759da05a35b67fd27b8859738b79af25d6 ]
This patch modifies selftests/bpf/Makefile to pass -Wno-attributes to GCC. This is because of the following attributes which are ignored:
- btf_decl_tag
- btf_type_tag
There are many of these. At the moment none of these are recognized/handled by gcc-bpf.
We are aware that btf_decl_tag is necessary for some of the selftest harness to communicate test failure/success. Support for it is in progress in GCC upstream:
https://gcc.gnu.org/pipermail/gcc-patches/2024-May/650482.html
However, the GCC master branch is not yet open, so the series above (currently under review upstream) wont be able to make it there until 14.1 gets released, probably mid next week.
As for btf_type_tag, more extensive work will be needed in GCC upstream to support it in both BTF and DWARF. We have a WIP big patch for that, but that is not needed to compile/build the selftests.
- used
There are SEC macros defined in the selftests as:
#define SEC(N) __attribute__((section(N),used))
The SEC macro is used for both functions and global variables. According to the GCC documentation `used' attribute is really only meaningful for functions, and it warns when the attribute is used for other global objects, like for example ctl_array in test_xdp_noinline.c.
Ignoring this is benign.
- align_value
In progs/test_cls_redirect.c:127 there is:
typedef uint8_t *net_ptr __attribute__((align_value(8)));
GCC warns that it is ignoring this attribute, because it is not implemented by GCC.
I think ignoring this attribute in GCC is benign, because according to the clang documentation [1] its purpose seems to be merely declarative and doesn't seem to translate into extra checks at run-time, only to perhaps better optimized code ("runtime behavior is undefined if the pointed memory object is not aligned to the specified alignment").
[1] https://clang.llvm.org/docs/AttributeReference.html#align-value
Tested in bpf-next master.
Stable-dep-of: 3ece93a4087b ("selftests/bpf: Fix wrong binary in Makefile log output")
--- tools/testing/selftests/bpf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/Makefile +1 -1
@@ -412,7 +412,7 @@ endef # Build BPF object using GCC define GCC_BPF_BUILD_RULE $(call msg,GCC-BPF,$(TRUNNER_BINARY),$2) - $(Q)$(BPF_GCC) $3 -O2 -c $1 -o $2 + $(Q)$(BPF_GCC) $3 -Wno-attributes -O2 -c $1 -o $2 endef SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 184/538 bpf: Temporarily define BPF_NO_PRESEVE_ACCESS_INDEX for GCC
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jose E. Marchesi <[email protected]>
[ Upstream commit 675b4e24bc50f4600b6bf3527fdbaa1f73498334 ]
The vmlinux.h file generated by bpftool makes use of compiler pragmas in order to install the CO-RE preserve_access_index in all the struct types derived from the BTF info:
#ifndef __VMLINUX_H__ #define __VMLINUX_H__ #ifndef BPF_NO_PRESERVE_ACCESS_INDEX #pragma clang attribute push (__attribute__((preserve_access_index)), apply_t = record #endif
[... type definitions generated from kernel BTF ... ]
#ifndef BPF_NO_PRESERVE_ACCESS_INDEX #pragma clang attribute pop #endif
The `clang attribute push/pop' pragmas are specific to clang/llvm and are not supported by GCC.
At the moment the BTF dumping services in libbpf do not support dicriminating between types dumped because they are directly referred and types dumped because they are dependencies. A suitable API is being worked now. See [1] and [2].
In the interim, this patch changes the selftests/bpf Makefile so it passes -DBPF_NO_PRESERVE_ACCESS_INDEX to GCC when it builds the selftests. This workaround is temporary, and may have an impact on the results of the GCC-built tests.
[1] https://lore.kernel.org/bpf/[email protected]/T/#u
[2] https://lore.kernel.org/bpf/[email protected]/T/#u
Tested in bpf-next master.
No regressions.
Stable-dep-of: 3ece93a4087b ("selftests/bpf: Fix wrong binary in Makefile log output")
--- tools/testing/selftests/bpf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/Makefile +1 -1
@@ -412,7 +412,7 @@ endef # Build BPF object using GCC define GCC_BPF_BUILD_RULE $(call msg,GCC-BPF,$(TRUNNER_BINARY),$2) - $(Q)$(BPF_GCC) $3 -Wno-attributes -O2 -c $1 -o $2 + $(Q)$(BPF_GCC) $3 -DBPF_NO_PRESERVE_ACCESS_INDEX -Wno-attributes -O2 -c $1 -o $2 endef SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 185/538 selftests/bpf: Add CFLAGS per source file and runner
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cupertino Miranda <[email protected]>
[ Upstream commit 207cf6e649ee551ab3bdb1cfe1b2848e6a4337a5 ]
This patch adds support to specify CFLAGS per source file and per test runner.
Stable-dep-of: 3ece93a4087b ("selftests/bpf: Fix wrong binary in Makefile log output")
--- tools/testing/selftests/bpf/Makefile | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
tools/testing/selftests/bpf/Makefile +9 -8
@@ -60,11 +60,11 @@ TEST_INST_SUBDIRS += bpf_gcc # The following tests contain C code that, although technically legal, # triggers GCC warnings that cannot be disabled: declaration of # anonymous struct types in function parameter lists. -progs/btf_dump_test_case_bitfields.c-CFLAGS := -Wno-error -progs/btf_dump_test_case_namespacing.c-CFLAGS := -Wno-error -progs/btf_dump_test_case_packing.c-CFLAGS := -Wno-error -progs/btf_dump_test_case_padding.c-CFLAGS := -Wno-error -progs/btf_dump_test_case_syntax.c-CFLAGS := -Wno-error +progs/btf_dump_test_case_bitfields.c-bpf_gcc-CFLAGS := -Wno-error +progs/btf_dump_test_case_namespacing.c-bpf_gcc-CFLAGS := -Wno-error +progs/btf_dump_test_case_packing.c-bpf_gcc-CFLAGS := -Wno-error +progs/btf_dump_test_case_padding.c-bpf_gcc-CFLAGS := -Wno-error +progs/btf_dump_test_case_syntax.c-bpf_gcc-CFLAGS := -Wno-error endif ifneq ($(CLANG_CPUV4),)
@@ -451,7 +451,7 @@ LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.c,$(foreach skel,$(LINKED_SKELS),$($(ske # $eval()) and pass control to DEFINE_TEST_RUNNER_RULES. # Parameters: # $1 - test runner base binary name (e.g., test_progs) -# $2 - test runner extra "flavor" (e.g., no_alu32, cpuv4, gcc-bpf, etc) +# $2 - test runner extra "flavor" (e.g., no_alu32, cpuv4, bpf_gcc, etc) define DEFINE_TEST_RUNNER TRUNNER_OUTPUT := $(OUTPUT)$(if $2,/)$2
@@ -479,7 +479,7 @@ endef # Using TRUNNER_XXX variables, provided by callers of DEFINE_TEST_RUNNER and # set up by DEFINE_TEST_RUNNER itself, create test runner build rules with: # $1 - test runner base binary name (e.g., test_progs) -# $2 - test runner extra "flavor" (e.g., no_alu32, cpuv4, gcc-bpf, etc) +# $2 - test runner extra "flavor" (e.g., no_alu32, cpuv4, bpf_gcc, etc) define DEFINE_TEST_RUNNER_RULES ifeq ($($(TRUNNER_OUTPUT)-dir),)
@@ -502,7 +502,8 @@ $(TRUNNER_BPF_OBJS): $(TRUNNER_OUTPUT)/%.bpf.o: \ | $(TRUNNER_OUTPUT) $$(BPFOBJ) $$(call $(TRUNNER_BPF_BUILD_RULE),$$<,$$@, \ $(TRUNNER_BPF_CFLAGS) \ - $$($$<-CFLAGS)) + $$($$<-CFLAGS) \ + $$($$<-$2-CFLAGS)) $(TRUNNER_BPF_SKELS): %.skel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT) $$(call msg,GEN-SKEL,$(TRUNNER_BINARY),$$@)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 186/538 selftests/bpf: Fix wrong binary in Makefile log output
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 3ece93a4087b2db7b99ebb2412bd60cf26bbbb51 ]
Make log output incorrectly shows 'test_maps' as the binary name for every 'CLNG-BPF' build step, apparently picking up the last value defined for the $(TRUNNER_BINARY) variable. Update the 'CLANG_BPF_BUILD_RULE' variants to fix this confusing output.
Current output:
CLNG-BPF [test_maps] access_map_in_map.bpf.o GEN-SKEL [test_progs] access_map_in_map.skel.h
...
CLNG-BPF [test_maps] access_map_in_map.bpf.o GEN-SKEL [test_progs-no_alu32] access_map_in_map.skel.h
...
CLNG-BPF [test_maps] access_map_in_map.bpf.o GEN-SKEL [test_progs-cpuv4] access_map_in_map.skel.h
After fix:
CLNG-BPF [test_progs] access_map_in_map.bpf.o GEN-SKEL [test_progs] access_map_in_map.skel.h
...
CLNG-BPF [test_progs-no_alu32] access_map_in_map.bpf.o GEN-SKEL [test_progs-no_alu32] access_map_in_map.skel.h
...
CLNG-BPF [test_progs-cpuv4] access_map_in_map.bpf.o GEN-SKEL [test_progs-cpuv4] access_map_in_map.skel.h
--- tools/testing/selftests/bpf/Makefile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
tools/testing/selftests/bpf/Makefile +6 -5
@@ -395,23 +395,24 @@ $(OUTPUT)/cgroup_getset_retval_hooks.o: cgroup_getset_retval_hooks.h # $1 - input .c file # $2 - output .o file # $3 - CFLAGS +# $4 - binary name define CLANG_BPF_BUILD_RULE - $(call msg,CLNG-BPF,$(TRUNNER_BINARY),$2) + $(call msg,CLNG-BPF,$4,$2) $(Q)$(CLANG) $3 -O2 --target=bpf -c $1 -mcpu=v3 -o $2 endef # Similar to CLANG_BPF_BUILD_RULE, but with disabled alu32 define CLANG_NOALU32_BPF_BUILD_RULE - $(call msg,CLNG-BPF,$(TRUNNER_BINARY),$2) + $(call msg,CLNG-BPF,$4,$2) $(Q)$(CLANG) $3 -O2 --target=bpf -c $1 -mcpu=v2 -o $2 endef # Similar to CLANG_BPF_BUILD_RULE, but with cpu-v4 define CLANG_CPUV4_BPF_BUILD_RULE - $(call msg,CLNG-BPF,$(TRUNNER_BINARY),$2) + $(call msg,CLNG-BPF,$4,$2) $(Q)$(CLANG) $3 -O2 --target=bpf -c $1 -mcpu=v4 -o $2 endef # Build BPF object using GCC define GCC_BPF_BUILD_RULE - $(call msg,GCC-BPF,$(TRUNNER_BINARY),$2) + $(call msg,GCC-BPF,$4,$2) $(Q)$(BPF_GCC) $3 -DBPF_NO_PRESERVE_ACCESS_INDEX -Wno-attributes -O2 -c $1 -o $2 endef
@@ -503,7 +504,7 @@ $(TRUNNER_BPF_OBJS): $(TRUNNER_OUTPUT)/%.bpf.o: \ $$(call $(TRUNNER_BPF_BUILD_RULE),$$<,$$@, \ $(TRUNNER_BPF_CFLAGS) \ $$($$<-CFLAGS) \ - $$($$<-$2-CFLAGS)) + $$($$<-$2-CFLAGS),$(TRUNNER_BINARY)) $(TRUNNER_BPF_SKELS): %.skel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT) $$(call msg,GEN-SKEL,$(TRUNNER_BINARY),$$@)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 187/538 tools/runqslower: Fix LDFLAGS and add LDLIBS support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit f86601c3661946721e8f260bdd812b759854ac22 ]
Actually use previously defined LDFLAGS during build and add support for LDLIBS to link extra standalone libraries e.g. 'argp' which is not provided by musl libc.
--- tools/bpf/runqslower/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/bpf/runqslower/Makefile +2 -1
@@ -15,6 +15,7 @@ INCLUDES := -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../include/uapi) CFLAGS := -g -Wall $(CLANG_CROSS_FLAGS) CFLAGS += $(EXTRA_CFLAGS) LDFLAGS += $(EXTRA_LDFLAGS) +LDLIBS += -lelf -lz # Try to detect best kernel BTF source KERNEL_REL := $(shell uname -r)
@@ -51,7 +52,7 @@ clean: libbpf_hdrs: $(BPFOBJ) $(OUTPUT)/runqslower: $(OUTPUT)/runqslower.o $(BPFOBJ) - $(QUIET_LINK)$(CC) $(CFLAGS) $^ -lelf -lz -o $@ + $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ $(OUTPUT)/runqslower.o: runqslower.h $(OUTPUT)/runqslower.skel.h \ $(OUTPUT)/runqslower.bpf.o | libbpf_hdrs
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 188/538 selftests/bpf: Use pid_t consistently in test_progs.c
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit ec4fe2f0fa12fd2d0115df7e58414dc26899cc5e ]
Use pid_t rather than __pid_t when allocating memory for 'worker_pids' in 'struct test_env', as this is its declared type and also avoids compile errors seen building against musl libc on mipsel64:
test_progs.c:1738:49: error: '__pid_t' undeclared (first use in this function); did you mean 'pid_t'?
1738 | env.worker_pids = calloc(sizeof(__pid_t), env.workers);
| ^~~~~~~
| pid_ttest_progs.c:1738:49: note: each undeclared identifier is reported only once for each function it appears in
--- tools/testing/selftests/bpf/test_progs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/test_progs.c +1 -1
@@ -1690,7 +1690,7 @@ int main(int argc, char **argv)/* launch workers if requested */ env.worker_id =-1 ;/* main process */ if (env.workers) { - env.worker_pids =calloc (sizeof (__pid_t), env.workers); + env.worker_pids =calloc (sizeof (pid_t), env.workers); env.worker_socks =calloc (sizeof (int ), env.workers);if (env.debug)fprintf (stdout,"Launching %d workers.\n" , env.workers);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 189/538 selftests/bpf: Fix compile error from rlim_t in sk_storage_map.c
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit d393f9479d4aaab0fa4c3caf513f28685e831f13 ]
Cast 'rlim_t' argument to match expected type of printf() format and avoid compile errors seen building for mips64el/musl-libc:
In file included from map_tests/sk_storage_map.c:20:
map_tests/sk_storage_map.c: In function 'test_sk_storage_map_stress_free':
map_tests/sk_storage_map.c:414:56: error: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'rlim_t' {aka 'long long unsigned int'} [-Werror=format=]
414 | CHECK(err, "setrlimit(RLIMIT_NOFILE)", "rlim_new:%lu errno:%d",
| ^~~~~~~~~~~~~~~~~~~~~~~
415 | rlim_new.rlim_cur, errno);
| ~~~~~~~~~~~~~~~~~
| |
| rlim_t {aka long long unsigned int}
./test_maps.h:12:24: note: in definition of macro 'CHECK'
12 | printf(format); \
| ^~~~~~
map_tests/sk_storage_map.c:414:68: note: format string is defined here
414 | CHECK(err, "setrlimit(RLIMIT_NOFILE)", "rlim_new:%lu errno:%d",
| ~~^
| |
| long unsigned int
| %llucc1: all warnings being treated as errors
--- tools/testing/selftests/bpf/map_tests/sk_storage_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/map_tests/sk_storage_map.c +1 -1
@@ -412,7 +412,7 @@ static void test_sk_storage_map_stress_free(void) rlim_new.rlim_max = rlim_new.rlim_cur +128 ; err =setrlimit (RLIMIT_NOFILE , &rlim_new);CHECK (err,"setrlimit(RLIMIT_NOFILE)" ,"rlim_new:%lu errno:%d" , - rlim_new.rlim_cur, errno); + (unsigned long ) rlim_new.rlim_cur, errno); } err =do_sk_storage_map_stress_free ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 190/538 selftests/bpf: Fix error compiling bpf_iter_setsockopt.c with musl libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 7b10f0c227ce3fa055d601f058dc411092a62a78 ]
Existing code calls getsockname() with a 'struct sockaddr_in6 *' argument where a 'struct sockaddr *' argument is declared, yielding compile errors when building for mips64el/musl-libc:
bpf_iter_setsockopt.c: In function 'get_local_port':
bpf_iter_setsockopt.c:98:30: error: passing argument 2 of 'getsockname' from incompatible pointer type [-Werror=incompatible-pointer-types]
98 | if (!getsockname(fd, &addr, &addrlen))
| ^~~~~
| |
| struct sockaddr_in6 *
In file included from .../netinet/in.h:10,
from .../arpa/inet.h:9,
from ./test_progs.h:17,
from bpf_iter_setsockopt.c:5:
.../sys/socket.h:391:23: note: expected 'struct sockaddr * restrict' but argument is of type 'struct sockaddr_in6 *'
391 | int getsockname (int, struct sockaddr *__restrict, socklen_t *__restrict);
| ^cc1: all warnings being treated as errors
This compiled under glibc only because the argument is declared to be a "funky" transparent union which includes both types above. Explicitly cast the argument to allow compiling for both musl and glibc.
--- tools/testing/selftests/bpf/prog_tests/bpf_iter_setsockopt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/prog_tests/bpf_iter_setsockopt.c +1 -1
@@ -95,7 +95,7 @@ static unsigned short get_local_port(int fd)struct sockaddr_in6 addr;socklen_t addrlen =sizeof (addr); -if (!getsockname (fd, &addr, &addrlen)) +if (!getsockname (fd, (struct sockaddr *)&addr, &addrlen))return ntohs (addr.sin6_port);return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 191/538 selftests/bpf: Implement get_hw_ring_size function to retrieve current and max interface size
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tushar Vyavahare <[email protected]>
[ Upstream commit 90a695c3d31e1c9f0adb8c4c80028ed4ea7ed5ab ]
Introduce a new function called get_hw_size that retrieves both the current and maximum size of the interface and stores this information in the 'ethtool_ringparam' structure.
Remove ethtool_channels struct from xdp_hw_metadata.c due to redefinition error. Remove unused linux/if.h include from flow_dissector BPF test to address CI pipeline failure.
Stable-dep-of: 69f409469c9b ("selftests/bpf: Drop unneeded error.h includes")
--- tools/testing/selftests/bpf/network_helpers.c | 24 +++++++++++++++++++ tools/testing/selftests/bpf/network_helpers.h | 4 ++++ .../selftests/bpf/prog_tests/flow_dissector.c | 1 - tools/testing/selftests/bpf/xdp_hw_metadata.c | 14 ----------- 4 files changed, 28 insertions(+), 15 deletions(-)
tools/testing/selftests/bpf/network_helpers.c +24 -0
@@ -465,3 +465,27 @@ int get_socket_local_port(int sock_fd)return -1 ; } + +int get_hw_ring_size (char *ifname,struct ethtool_ringparam *ring_param) +{ +struct ifreq ifr = {0 }; +int sockfd, err; + + sockfd =socket (AF_INET ,SOCK_DGRAM ,0 ); +if (sockfd <0 ) +return -errno; + +memcpy (ifr.ifr_name, ifname,sizeof (ifr.ifr_name)); + + ring_param->cmd =ETHTOOL_GRINGPARAM ; + ifr.ifr_data = (char *)ring_param; + +if (ioctl (sockfd,SIOCETHTOOL , &ifr) <0 ) { + err = errno; +close (sockfd); +return -err; + } + +close (sockfd); +return 0 ; +}
tools/testing/selftests/bpf/network_helpers.h +4 -0
@@ -9,8 +9,11 @@ typedef __u16 __sum16;#include <linux/if_packet.h> #include <linux/ip.h> #include <linux/ipv6.h> +#include <linux/ethtool.h> +#include <linux/sockios.h> #include <netinet/tcp.h> #include <bpf/bpf_endian.h> +#include <net/if.h> #define MAGIC_VAL 0x1234#define NUM_ITER 100000
@@ -60,6 +63,7 @@ int make_sockaddr(int family, const char *addr_str, __u16 port, struct sockaddr_storage *addr, socklen_t *len);char *ping_command (int family);int get_socket_local_port (int sock_fd); +int get_hw_ring_size (char *ifname,struct ethtool_ringparam *ring_param);struct nstoken ;/**
tools/testing/selftests/bpf/prog_tests/flow_dissector.c +0 -1
@@ -2,7 +2,6 @@#include <test_progs.h> #include <network_helpers.h> #include <error.h> -#include <linux/if.h> #include <linux/if_tun.h> #include <sys/uio.h>
tools/testing/selftests/bpf/xdp_hw_metadata.c +0 -14
@@ -288,20 +288,6 @@ static int verify_metadata(struct xsk *rx_xsk, int rxq, int server_fd, clockid_treturn 0 ; } -struct ethtool_channels { -__u32 cmd; -__u32 max_rx; -__u32 max_tx; -__u32 max_other; -__u32 max_combined; -__u32 rx_count; -__u32 tx_count; -__u32 other_count; -__u32 combined_count; -}; - -#define ETHTOOL_GCHANNELS 0x0000003c/* Get no of channels */ -static int rxq_num (const char *ifname) {struct ethtool_channels ch = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 192/538 selftests/bpf: Drop unneeded error.h includes
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 69f409469c9b1515a5db40d5a36fda372376fa2d ]
The addition of general support for unprivileged tests in test_loader.c breaks building test_verifier on non-glibc (e.g. musl) systems, due to the inclusion of glibc extension '<error.h>' in 'unpriv_helpers.c'. However, the header is actually not needed, so remove it to restore building.
Similarly for sk_lookup.c and flow_dissector.c, error.h is not necessary and causes problems, so drop them.
--- tools/testing/selftests/bpf/prog_tests/flow_dissector.c | 1 - tools/testing/selftests/bpf/prog_tests/sk_lookup.c | 1 - tools/testing/selftests/bpf/unpriv_helpers.c | 1 - 3 files changed, 3 deletions(-)
tools/testing/selftests/bpf/prog_tests/flow_dissector.c +0 -1
@@ -1,7 +1,6 @@// SPDX-License-Identifier: GPL-2.0 #include <test_progs.h> #include <network_helpers.h> -#include <error.h> #include <linux/if_tun.h> #include <sys/uio.h>
tools/testing/selftests/bpf/prog_tests/sk_lookup.c +0 -1
@@ -18,7 +18,6 @@#include <arpa/inet.h> #include <assert.h> #include <errno.h> -#include <error.h> #include <fcntl.h> #include <sched.h> #include <stdio.h>
tools/testing/selftests/bpf/unpriv_helpers.c +0 -1
@@ -2,7 +2,6 @@#include <stdbool.h> #include <stdlib.h> -#include <error.h> #include <stdio.h> #include "unpriv_helpers.h"
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 193/538 selftests/bpf: Fix missing ARRAY_SIZE() definition in bench.c
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit d44c93fc2f5a0c47b23fa03d374e45259abd92d2 ]
Add a "bpf_util.h" include to avoid the following error seen compiling for mips64el with musl libc:
bench.c: In function 'find_benchmark':
bench.c:590:25: error: implicit declaration of function 'ARRAY_SIZE' [-Werror=implicit-function-declaration]
590 | for (i = 0; i < ARRAY_SIZE(benchs); i++) {
| ^~~~~~~~~~cc1: all warnings being treated as errors
--- tools/testing/selftests/bpf/bench.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/bench.c +1 -0
@@ -10,6 +10,7 @@#include <sys/sysinfo.h> #include <signal.h> #include "bench.h" +#include "bpf_util.h" #include "testing_helpers.h" struct env env = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 194/538 selftests/bpf: Fix missing UINT_MAX definitions in benchmarks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit a2c155131b710959beb508ca6a54769b6b1bd488 ]
Include <limits.h> in 'bench.h' to provide a UINT_MAX definition and avoid multiple compile errors against mips64el/musl-libc like:
benchs/bench_local_storage.c: In function 'parse_arg':
benchs/bench_local_storage.c:40:38: error: 'UINT_MAX' undeclared (first use in this function)
40 | if (ret < 1 || ret > UINT_MAX) {
| ^~~~~~~~
benchs/bench_local_storage.c:11:1: note: 'UINT_MAX' is defined in header '<limits.h>'; did you forget to '#include <limits.h>'?
10 | #include <test_btf.h>
+++ |+#include <limits.h>
11 |seen with bench_local_storage.c, bench_local_storage_rcu_tasks_trace.c, and bench_bpf_hashmap_lookup.c.
--- tools/testing/selftests/bpf/bench.h | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/bench.h +1 -0
@@ -10,6 +10,7 @@#include <math.h> #include <time.h> #include <sys/syscall.h> +#include <limits.h> struct cpu_set {bool *cpus;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 195/538 selftests/bpf: Fix missing BUILD_BUG_ON() declaration
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 6495eb79ca7d15bd87c38d77307e8f9b6b7bf4ef ]
Explicitly include '<linux/build_bug.h>' to fix errors seen compiling with gcc targeting mips64el/musl-libc:
user_ringbuf.c: In function 'test_user_ringbuf_loop':
user_ringbuf.c:426:9: error: implicit declaration of function 'BUILD_BUG_ON' [-Werror=implicit-function-declaration]
426 | BUILD_BUG_ON(total_samples <= c_max_entries);
| ^~~~~~~~~~~~cc1: all warnings being treated as errors
--- tools/testing/selftests/bpf/prog_tests/user_ringbuf.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/prog_tests/user_ringbuf.c +1 -0
@@ -4,6 +4,7 @@#define _GNU_SOURCE#include <linux/compiler.h> #include <linux/ring_buffer.h> +#include <linux/build_bug.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h>
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 196/538 selftests/bpf: Replace CHECK with ASSERT_* in ns_current_pid_tgid test
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonghong Song <[email protected]>
[ Upstream commit 84239a24d10174fcfc7d6760cb120435a6ff69af ]
Replace CHECK in selftest ns_current_pid_tgid with recommended ASSERT_* style. I also shortened subtest name as the prefix of subtest name is covered by the test name already.
This patch does fix a testing issue. Currently even if bss->user_{pid,tgid} is not correct, the test still passed since the clone func returns 0. I fixed it to return a non-zero value if bss->user_{pid,tgid} is incorrect.
Stable-dep-of: 21f0b0af9772 ("selftests/bpf: Fix include of <sys/fcntl.h>")
--- .../bpf/prog_tests/ns_current_pid_tgid.c | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-)
tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c +19 -17
@@ -20,19 +20,19 @@ static int test_current_pid_tgid(void *args) {struct test_ns_current_pid_tgid__bss *bss;struct test_ns_current_pid_tgid *skel; -int err =-1 , duration =0 ; +int ret =-1 , err;pid_t tgid, pid;struct stat st; skel =test_ns_current_pid_tgid__open_and_load (); -if (CHECK (!skel,"skel_open_load" ,"failed to load skeleton\n" )) - goto cleanup; +if (!ASSERT_OK_PTR (skel,"test_ns_current_pid_tgid__open_and_load" )) + goto out; pid =syscall (SYS_gettid); tgid =getpid (); err =stat ("/proc/self/ns/pid" , &st); -if (CHECK (err,"stat" ,"failed /proc/self/ns/pid: %d\n" , err)) +if (!ASSERT_OK (err,"stat /proc/self/ns/pid" )) goto cleanup; bss = skel->bss;
@@ -42,24 +42,26 @@ static int test_current_pid_tgid(void *args) bss->user_tgid =0 ; err =test_ns_current_pid_tgid__attach (skel); -if (CHECK (err,"skel_attach" ,"skeleton attach failed: %d\n" , err)) +if (!ASSERT_OK (err,"test_ns_current_pid_tgid__attach" )) goto cleanup;/* trigger tracepoint */ usleep (1 ); -ASSERT_EQ (bss->user_pid, pid,"pid" ); -ASSERT_EQ (bss->user_tgid, tgid,"tgid" ); - err =0 ; +if (!ASSERT_EQ (bss->user_pid, pid,"pid" )) + goto cleanup; +if (!ASSERT_EQ (bss->user_tgid, tgid,"tgid" )) + goto cleanup; + ret =0 ; cleanup: -test_ns_current_pid_tgid__destroy (skel); - -return err; +test_ns_current_pid_tgid__destroy (skel); +out: +return ret; }static void test_ns_current_pid_tgid_new_ns (void ) { -int wstatus, duration =0 ; +int wstatus;pid_t cpid;/* Create a process in a new namespace, this process
@@ -68,21 +70,21 @@ static void test_ns_current_pid_tgid_new_ns(void) cpid =clone (test_current_pid_tgid, child_stack +STACK_SIZE ,CLONE_NEWPID |SIGCHLD ,NULL ); -if (CHECK (cpid ==-1 ,"clone" ,"%s\n" ,strerror (errno))) +if (!ASSERT_NEQ (cpid,-1 ,"clone" ))return ; -if (CHECK (waitpid (cpid, &wstatus,0 ) ==-1 ,"waitpid" ,"%s\n" ,strerror (errno))) +if (!ASSERT_NEQ (waitpid (cpid, &wstatus,0 ),-1 ,"waitpid" ))return ; -if (CHECK (WEXITSTATUS (wstatus) !=0 ,"newns_pidtgid" ,"failed" )) +if (!ASSERT_OK (WEXITSTATUS (wstatus),"newns_pidtgid" ))return ; }/* TODO: use a different tracepoint */ void serial_test_ns_current_pid_tgid (void ) { -if (test__start_subtest ("ns_current_pid_tgid_root_ns" )) +if (test__start_subtest ("root_ns_tp" ))test_current_pid_tgid (NULL ); -if (test__start_subtest ("ns_current_pid_tgid_new_ns" )) +if (test__start_subtest ("new_ns_tp" ))test_ns_current_pid_tgid_new_ns (); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 197/538 selftests/bpf: Refactor out some functions in ns_current_pid_tgid test
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonghong Song <[email protected]>
[ Upstream commit 4d4bd29e363c467752536f874a2cba10a5923c59 ]
Refactor some functions in both user space code and bpf program as these functions are used by later cgroup/sk_msg tests. Another change is to mark tp program optional loading as later patches will use optional loading as well since they have quite different attachment and testing logic.
There is no functionality change.
Stable-dep-of: 21f0b0af9772 ("selftests/bpf: Fix include of <sys/fcntl.h>")
--- .../bpf/prog_tests/ns_current_pid_tgid.c | 53 ++++++++++++------- .../bpf/progs/test_ns_current_pid_tgid.c | 10 ++-- 2 files changed, 41 insertions(+), 22 deletions(-)
tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c +34 -19
@@ -16,30 +16,46 @@#define STACK_SIZE (1024 * 1024)static char child_stack[STACK_SIZE ]; -static int test_current_pid_tgid (void *args) +static int get_pid_tgid (pid_t *pid,pid_t *tgid, +struct test_ns_current_pid_tgid__bss *bss) { -struct test_ns_current_pid_tgid__bss *bss; -struct test_ns_current_pid_tgid *skel; -int ret =-1 , err; -pid_t tgid, pid;struct stat st; +int err; - skel =test_ns_current_pid_tgid__open_and_load (); -if (!ASSERT_OK_PTR (skel,"test_ns_current_pid_tgid__open_and_load" )) - goto out; - - pid =syscall (SYS_gettid); - tgid =getpid (); + *pid =syscall (SYS_gettid); + *tgid =getpid (); err =stat ("/proc/self/ns/pid" , &st);if (!ASSERT_OK (err,"stat /proc/self/ns/pid" )) - goto cleanup; +return err; - bss = skel->bss; bss->dev = st.st_dev; bss->ino = st.st_ino; bss->user_pid =0 ; bss->user_tgid =0 ; +return 0 ; +} + +static int test_current_pid_tgid_tp (void *args) +{ +struct test_ns_current_pid_tgid__bss *bss; +struct test_ns_current_pid_tgid *skel; +int ret =-1 , err; +pid_t tgid, pid; + + skel =test_ns_current_pid_tgid__open (); +if (!ASSERT_OK_PTR (skel,"test_ns_current_pid_tgid__open" )) +return ret; + +bpf_program__set_autoload (skel->progs.tp_handler, true); + + err =test_ns_current_pid_tgid__load (skel); +if (!ASSERT_OK (err,"test_ns_current_pid_tgid__load" )) + goto cleanup; + + bss = skel->bss; +if (get_pid_tgid (&pid, &tgid, bss)) + goto cleanup; err =test_ns_current_pid_tgid__attach (skel);if (!ASSERT_OK (err,"test_ns_current_pid_tgid__attach" ))
@@ -55,11 +71,10 @@ static int test_current_pid_tgid(void *args) cleanup:test_ns_current_pid_tgid__destroy (skel); -out:return ret; } -static void test_ns_current_pid_tgid_new_ns (void ) +static void test_ns_current_pid_tgid_new_ns (int (*fn)(void *),void *arg) {int wstatus;pid_t cpid;
@@ -67,8 +82,8 @@ static void test_ns_current_pid_tgid_new_ns(void)/* Create a process in a new namespace, this process * will be the init process of this new namespace hence will be pid 1. */ - cpid =clone (test_current_pid_tgid, child_stack +STACK_SIZE , -CLONE_NEWPID |SIGCHLD ,NULL ); + cpid =clone (fn, child_stack +STACK_SIZE , +CLONE_NEWPID |SIGCHLD , arg);if (!ASSERT_NEQ (cpid,-1 ,"clone" ))return ;
@@ -84,7 +99,7 @@ static void test_ns_current_pid_tgid_new_ns(void)void serial_test_ns_current_pid_tgid (void ) {if (test__start_subtest ("root_ns_tp" )) -test_current_pid_tgid (NULL ); +test_current_pid_tgid_tp (NULL );if (test__start_subtest ("new_ns_tp" )) -test_ns_current_pid_tgid_new_ns (); +test_ns_current_pid_tgid_new_ns (test_current_pid_tgid_tp,NULL ); }
tools/testing/selftests/bpf/progs/test_ns_current_pid_tgid.c +7 -3
@@ -10,17 +10,21 @@ __u64 user_tgid = 0;__u64 dev =0 ;__u64 ino =0 ; -SEC("tracepoint/syscalls/sys_enter_nanosleep") -int handler (const void *ctx) +static void get_pid_tgid (void ) {struct bpf_pidns_info nsdata;if (bpf_get_ns_current_pid_tgid (dev, ino, &nsdata,sizeof (struct bpf_pidns_info ))) -return 0 ; +return ; user_pid = nsdata.pid; user_tgid = nsdata.tgid; +} +SEC("?tracepoint/syscalls/sys_enter_nanosleep") +int tp_handler (const void *ctx) +{ +get_pid_tgid ();return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 198/538 selftests/bpf: Add a cgroup prog bpf_get_ns_current_pid_tgid() test
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonghong Song <[email protected]>
[ Upstream commit 87ade6cd859ea9dbde6e80b3fcf717ed9a73b4a9 ]
Add a cgroup bpf program test where the bpf program is running in a pid namespace. The test is successfully:
#165/3 ns_current_pid_tgid/new_ns_cgrp:OK
Stable-dep-of: 21f0b0af9772 ("selftests/bpf: Fix include of <sys/fcntl.h>")
--- .../bpf/prog_tests/ns_current_pid_tgid.c | 73 +++++++++++++++++++ .../bpf/progs/test_ns_current_pid_tgid.c | 7 ++ 2 files changed, 80 insertions(+)
tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c +73 -0
@@ -12,6 +12,7 @@#include <sys/wait.h> #include <sys/mount.h> #include <sys/fcntl.h> +#include "network_helpers.h" #define STACK_SIZE (1024 * 1024)static char child_stack[STACK_SIZE ];
@@ -74,6 +75,50 @@ static int test_current_pid_tgid_tp(void *args)return ret; } +static int test_current_pid_tgid_cgrp (void *args) +{ +struct test_ns_current_pid_tgid__bss *bss; +struct test_ns_current_pid_tgid *skel; +int server_fd =-1 , ret =-1 , err; +int cgroup_fd = *(int *)args; +pid_t tgid, pid; + + skel =test_ns_current_pid_tgid__open (); +if (!ASSERT_OK_PTR (skel,"test_ns_current_pid_tgid__open" )) +return ret; + +bpf_program__set_autoload (skel->progs.cgroup_bind4, true); + + err =test_ns_current_pid_tgid__load (skel); +if (!ASSERT_OK (err,"test_ns_current_pid_tgid__load" )) + goto cleanup; + + bss = skel->bss; +if (get_pid_tgid (&pid, &tgid, bss)) + goto cleanup; + + skel->links.cgroup_bind4 =bpf_program__attach_cgroup ( + skel->progs.cgroup_bind4, cgroup_fd); +if (!ASSERT_OK_PTR (skel->links.cgroup_bind4,"bpf_program__attach_cgroup" )) + goto cleanup; + + server_fd =start_server (AF_INET ,SOCK_STREAM ,NULL ,0 ,0 ); +if (!ASSERT_GE (server_fd,0 ,"start_server" )) + goto cleanup; + +if (!ASSERT_EQ (bss->user_pid, pid,"pid" )) + goto cleanup; +if (!ASSERT_EQ (bss->user_tgid, tgid,"tgid" )) + goto cleanup; + ret =0 ; + +cleanup: +if (server_fd >=0 ) +close (server_fd); +test_ns_current_pid_tgid__destroy (skel); +return ret; +} +static void test_ns_current_pid_tgid_new_ns (int (*fn)(void *),void *arg) {int wstatus;
@@ -95,6 +140,25 @@ static void test_ns_current_pid_tgid_new_ns(int (*fn)(void *), void *arg)return ; } +static void test_in_netns (int (*fn)(void *),void *arg) +{ +struct nstoken *nstoken =NULL ; + +SYS (cleanup,"ip netns add ns_current_pid_tgid" ); +SYS (cleanup,"ip -net ns_current_pid_tgid link set dev lo up" ); + + nstoken =open_netns ("ns_current_pid_tgid" ); +if (!ASSERT_OK_PTR (nstoken,"open_netns" )) + goto cleanup; + +test_ns_current_pid_tgid_new_ns (fn, arg); + +cleanup: +if (nstoken) +close_netns (nstoken); +SYS_NOFAIL ("ip netns del ns_current_pid_tgid" ); +} +/* TODO: use a different tracepoint */ void serial_test_ns_current_pid_tgid (void ) {
@@ -102,4 +166,13 @@ void serial_test_ns_current_pid_tgid(void)test_current_pid_tgid_tp (NULL );if (test__start_subtest ("new_ns_tp" ))test_ns_current_pid_tgid_new_ns (test_current_pid_tgid_tp,NULL ); +if (test__start_subtest ("new_ns_cgrp" )) { +int cgroup_fd =-1 ; + + cgroup_fd =test__join_cgroup ("/sock_addr" ); +if (ASSERT_GE (cgroup_fd,0 ,"join_cgroup" )) { +test_in_netns (test_current_pid_tgid_cgrp, &cgroup_fd); +close (cgroup_fd); + } + } }
tools/testing/selftests/bpf/progs/test_ns_current_pid_tgid.c +7 -0
@@ -28,4 +28,11 @@ int tp_handler(const void *ctx)return 0 ; } +SEC("?cgroup/bind4") +int cgroup_bind4 (struct bpf_sock_addr *ctx) +{ +get_pid_tgid (); +return 1 ; +} + char _license[] SEC("license") = "GPL";
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 199/538 selftests/bpf: Fix include of <sys/fcntl.h>
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 21f0b0af977203220ad58aff95e372151288ec47 ]
Update ns_current_pid_tgid.c to use '#include <fcntl.h>' and avoid compile error against mips64el/musl libc:
In file included from .../prog_tests/ns_current_pid_tgid.c:14:
.../include/sys/fcntl.h:1:2: error: #warning redirecting incorrect #include <sys/fcntl.h> to <fcntl.h> [-Werror=cpp]
1 | #warning redirecting incorrect #include <sys/fcntl.h> to <fcntl.h>
| ^~~~~~~
cc1: all warnings being treated as errors
--- tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c +1 -1
@@ -11,7 +11,7 @@#include <sched.h> #include <sys/wait.h> #include <sys/mount.h> -#include <sys/fcntl.h> +#include <fcntl.h> #include "network_helpers.h" #define STACK_SIZE (1024 * 1024)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 200/538 selftests/bpf: Fix compiling parse_tcp_hdr_opt.c with musl-libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 4c329b99ef9c118343379bde9f97e8ce5cac9fc9 ]
The GNU version of 'struct tcphdr', with members 'doff' and 'urg_ptr', is not exposed by musl headers unless _GNU_SOURCE is defined.
Add this definition to fix errors seen compiling for mips64el/musl-libc:
parse_tcp_hdr_opt.c:18:21: error: 'struct tcphdr' has no member named 'urg_ptr'
18 | .pk6_v6.tcp.urg_ptr = 123,
| ^~~~~~~
parse_tcp_hdr_opt.c:19:21: error: 'struct tcphdr' has no member named 'doff'
19 | .pk6_v6.tcp.doff = 9, /* 16 bytes of options */
| ^~~~--- tools/testing/selftests/bpf/prog_tests/parse_tcp_hdr_opt.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/prog_tests/parse_tcp_hdr_opt.c +1 -0
@@ -1,5 +1,6 @@// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE#include <test_progs.h> #include <network_helpers.h> #include "test_parse_tcp_hdr_opt.skel.h"
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 201/538 selftests/bpf: Fix compiling kfree_skb.c with musl-libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit bae9a5ce7d3a9b3a9e07b31ab9e9c58450e3e9fd ]
The GNU version of 'struct tcphdr' with member 'doff' is not exposed by musl headers unless _GNU_SOURCE is defined. Add this definition to fix errors seen compiling for mips64el/musl-libc:
In file included from kfree_skb.c:2:
kfree_skb.c: In function 'on_sample':
kfree_skb.c:45:30: error: 'struct tcphdr' has no member named 'doff'
45 | if (CHECK(pkt_v6->tcp.doff != 5, "check_tcp",
| ^--- tools/testing/selftests/bpf/prog_tests/kfree_skb.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/prog_tests/kfree_skb.c +1 -0
@@ -1,4 +1,5 @@// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE#include <test_progs.h> #include <network_helpers.h> #include "kfree_skb.skel.h"
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 202/538 selftests/bpf: Fix compiling flow_dissector.c with musl-libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 5e4c43bcb85973243d7274e0058b6e8f5810e4f7 ]
The GNU version of 'struct tcphdr' has members 'doff', 'source' and 'dest', which are not exposed by musl libc headers unless _GNU_SOURCE is defined.
Add this definition to fix errors seen compiling for mips64el/musl-libc:
flow_dissector.c:118:30: error: 'struct tcphdr' has no member named 'doff'
118 | .tcp.doff = 5,
| ^~~~
flow_dissector.c:119:30: error: 'struct tcphdr' has no member named 'source'
119 | .tcp.source = 80,
| ^~~~~~
flow_dissector.c:120:30: error: 'struct tcphdr' has no member named 'dest'
120 | .tcp.dest = 8080,
| ^~~~--- tools/testing/selftests/bpf/prog_tests/flow_dissector.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/prog_tests/flow_dissector.c +1 -0
@@ -1,4 +1,5 @@// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE#include <test_progs.h> #include <network_helpers.h> #include <linux/if_tun.h>
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 203/538 selftests/bpf: Fix compiling tcp_rtt.c with musl-libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 18826fb0b79c3c3cd1fe765d85f9c6f1a902c722 ]
The GNU version of 'struct tcp_info' in 'netinet/tcp.h' is not exposed by musl headers unless _GNU_SOURCE is defined.
Add this definition to fix errors seen compiling for mips64el/musl-libc:
tcp_rtt.c: In function 'wait_for_ack':
tcp_rtt.c:24:25: error: storage size of 'info' isn't known
24 | struct tcp_info info;
| ^~~~ tcp_rtt.c:24:25: error: unused variable 'info' [-Werror=unused-variable]
cc1: all warnings being treated as errors
--- tools/testing/selftests/bpf/prog_tests/tcp_rtt.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/prog_tests/tcp_rtt.c +1 -0
@@ -1,4 +1,5 @@// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE#include <test_progs.h> #include "cgroup_helpers.h" #include "network_helpers.h"
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 204/538 selftests/bpf: Fix compiling core_reloc.c with musl-libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit debfa4f628f271f72933bf38d581cc53cfe1def5 ]
The type 'loff_t' is a GNU extension and not exposed by the musl 'fcntl.h' header unless _GNU_SOURCE is defined. Add this definition to fix errors seen compiling for mips64el/musl-libc:
In file included from tools/testing/selftests/bpf/prog_tests/core_reloc.c:4:
./bpf_testmod/bpf_testmod.h:10:9: error: unknown type name 'loff_t'
10 | loff_t off;
| ^~~~~~
./bpf_testmod/bpf_testmod.h:16:9: error: unknown type name 'loff_t'
16 | loff_t off;
| ^~~~~~--- tools/testing/selftests/bpf/prog_tests/core_reloc.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/prog_tests/core_reloc.c +1 -0
@@ -1,4 +1,5 @@// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE#include <test_progs.h> #include "progs/core_reloc_types.h" #include "bpf_testmod/bpf_testmod.h"
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 205/538 selftests/bpf: Fix errors compiling lwt_redirect.c with musl libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 27c4797ce51c8dd51e35e68e9024a892f62d78b2 ]
Remove a redundant include of '<linux/icmp.h>' which is already provided in 'lwt_helpers.h'. This avoids errors seen compiling for mips64el/musl-libc:
In file included from .../arpa/inet.h:9,
from lwt_redirect.c:51:
.../netinet/in.h:23:8: error: redefinition of 'struct in6_addr'
23 | struct in6_addr {
| ^~~~~~~~
In file included from .../linux/icmp.h:24,
from lwt_redirect.c:50:
.../linux/in6.h:33:8: note: originally defined here
33 | struct in6_addr {
| ^~~~~~~~
.../netinet/in.h:34:8: error: redefinition of 'struct sockaddr_in6'
34 | struct sockaddr_in6 {
| ^~~~~~~~~~~~
.../linux/in6.h:50:8: note: originally defined here
50 | struct sockaddr_in6 {
| ^~~~~~~~~~~~
.../netinet/in.h:42:8: error: redefinition of 'struct ipv6_mreq'
42 | struct ipv6_mreq {
| ^~~~~~~~~
.../linux/in6.h:60:8: note: originally defined here
60 | struct ipv6_mreq {
| ^~~~~~~~~--- tools/testing/selftests/bpf/prog_tests/lwt_redirect.c | 1 - 1 file changed, 1 deletion(-)
tools/testing/selftests/bpf/prog_tests/lwt_redirect.c +0 -1
@@ -47,7 +47,6 @@#include <linux/if_ether.h> #include <linux/if_packet.h> #include <linux/if_tun.h> -#include <linux/icmp.h> #include <arpa/inet.h> #include <unistd.h> #include <errno.h>
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 206/538 selftests/bpf: Fix errors compiling decap_sanity.c with musl libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 1b00f355130a5dfc38a01ad02458ae2cb2ebe609 ]
Remove a redundant include of '<linux/in6.h>', whose needed definitions are already provided by 'test_progs.h'. This avoids errors seen compiling for mips64el/musl-libc:
In file included from .../arpa/inet.h:9,
from ./test_progs.h:17,
from prog_tests/decap_sanity.c:9:
.../netinet/in.h:23:8: error: redefinition of 'struct in6_addr'
23 | struct in6_addr {
| ^~~~~~~~
In file included from decap_sanity.c:7:
.../linux/in6.h:33:8: note: originally defined here
33 | struct in6_addr {
| ^~~~~~~~
.../netinet/in.h:34:8: error: redefinition of 'struct sockaddr_in6'
34 | struct sockaddr_in6 {
| ^~~~~~~~~~~~
.../linux/in6.h:50:8: note: originally defined here
50 | struct sockaddr_in6 {
| ^~~~~~~~~~~~
.../netinet/in.h:42:8: error: redefinition of 'struct ipv6_mreq'
42 | struct ipv6_mreq {
| ^~~~~~~~~
.../linux/in6.h:60:8: note: originally defined here
60 | struct ipv6_mreq {
| ^~~~~~~~~--- tools/testing/selftests/bpf/prog_tests/decap_sanity.c | 1 - 1 file changed, 1 deletion(-)
tools/testing/selftests/bpf/prog_tests/decap_sanity.c +0 -1
@@ -4,7 +4,6 @@#include <sys/types.h> #include <sys/socket.h> #include <net/if.h> -#include <linux/in6.h> #include "test_progs.h" #include "network_helpers.h"
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 207/538 selftests/bpf: Fix errors compiling cg_storage_multi.h with musl libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 730561d3c08d4a327cceaabf11365958a1c00cec ]
Remove a redundant include of '<asm/types.h>', whose needed definitions are already included (via '<linux/types.h>') in cg_storage_multi_egress_only.c, cg_storage_multi_isolated.c, and cg_storage_multi_shared.c. This avoids redefinition errors seen compiling for mips64el/musl-libc like:
In file included from progs/cg_storage_multi_egress_only.c:13:
In file included from progs/cg_storage_multi.h:6:
In file included from /usr/mips64el-linux-gnuabi64/include/asm/types.h:23:
/usr/include/asm-generic/int-l64.h:29:25: error: typedef redefinition with different types ('long' vs 'long long')
29 | typedef __signed__ long __s64;
| ^
/usr/include/asm-generic/int-ll64.h:30:44: note: previous definition is here
30 | __extension__ typedef __signed__ long long __s64;
| ^--- tools/testing/selftests/bpf/progs/cg_storage_multi.h | 2 -- 1 file changed, 2 deletions(-)
tools/testing/selftests/bpf/progs/cg_storage_multi.h +0 -2
@@ -3,8 +3,6 @@ #ifndef __PROGS_CG_STORAGE_MULTI_H #define __PROGS_CG_STORAGE_MULTI_H -#include <asm/types.h> - struct cgroup_value { __u32 egress_pkts; __u32 ingress_pkts;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 208/538 libbpf: use stable map placeholder FDs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrii Nakryiko <[email protected]>
[ Upstream commit dac645b950ea4fc0896fe46a645365cb8d9ab92b ]
Move map creation to later during BPF object loading by pre-creating stable placeholder FDs (utilizing memfd_create()). Use dup2() syscall to then atomically make those placeholder FDs point to real kernel BPF map objects.
This change allows to delay BPF map creation to after all the BPF program relocations. That, in turn, allows to delay BTF finalization and loading into kernel to after all the relocations as well. We'll take advantage of the latter in subsequent patches to allow libbpf to adjust BTF in a way that helps with BPF global function usage.
Clean up a few places where we close map->fd, which now shouldn't happen, because map->fd should be a valid FD regardless of whether map was created or not. Surprisingly and nicely it simplifies a bunch of error handling code. If this change doesn't backfire, I'm tempted to pre-create such stable FDs for other entities (progs, maybe even BTF). We previously did some manipulations to make gen_loader work with fake map FDs, with stable map FDs this hack is not necessary for maps (we still have it for BTF, but I left it as is for now).
Stable-dep-of: 04a94133f1b3 ("libbpf: Don't take direct pointers into BTF data from st_ops")
--- tools/lib/bpf/libbpf.c | 101 ++++++++++++++++++++------------ tools/lib/bpf/libbpf_internal.h | 14 +++++ 2 files changed, 77 insertions(+), 38 deletions(-)
tools/lib/bpf/libbpf.c +63 -38
@@ -1491,6 +1491,16 @@ static Elf64_Sym *find_elf_var_sym(const struct bpf_object *obj, const char *namreturn ERR_PTR (-ENOENT ); } +static int create_placeholder_fd (void ) +{ +int fd; + + fd =ensure_good_fd (memfd_create ("libbpf-placeholder-fd" ,MFD_CLOEXEC )); +if (fd <0 ) +return -errno; +return fd; +} +static struct bpf_map *bpf_object__add_map (struct bpf_object *obj) {struct bpf_map *map;
@@ -1503,7 +1513,21 @@ static struct bpf_map *bpf_object__add_map(struct bpf_object *obj) map = &obj->maps[obj->nr_maps++]; map->obj = obj; - map->fd =-1 ; +/* Preallocate map FD without actually creating BPF map just yet. +* These map FD "placeholders" will be reused later without changing +* FD value when map is actually created in the kernel. +* +* This is useful to be able to perform BPF program relocations +* without having to create BPF maps before that step. This allows us +* to finalize and load BTF very late in BPF object's loading phase, +* right before BPF maps have to be created and BPF programs have to +* be loaded. By having these map FD placeholders we can perform all +* the sanitizations, relocations, and any other adjustments before we +* start creating actual BPF kernel objects (BTF, maps, progs). +*/ + map->fd =create_placeholder_fd (); +if (map->fd <0 ) +return ERR_PTR (map->fd); map->inner_map_fd =-1 ; map->autocreate = true;
@@ -2595,7 +2619,9 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj, map->inner_map =calloc (1 ,sizeof (*map->inner_map));if (!map->inner_map)return -ENOMEM ; - map->inner_map->fd =-1 ; + map->inner_map->fd =create_placeholder_fd (); +if (map->inner_map->fd <0 ) +return map->inner_map->fd; map->inner_map->sec_idx = sec_idx; map->inner_map->name =malloc (strlen (map_name) +sizeof (".inner" ) +1 );if (!map->inner_map->name)
@@ -4446,14 +4472,12 @@ int bpf_map__reuse_fd(struct bpf_map *map, int fd) goto err_free_new_name; } - err =zclose (map->fd); -if (err) { - err = -errno; - goto err_close_new_fd; - } + err =reuse_fd (map->fd, new_fd); +if (err) + goto err_free_new_name; +free (map->name); - map->fd = new_fd; map->name = new_name; map->def.type = info.type; map->def.key_size = info.key_size;
@@ -4467,8 +4491,6 @@ int bpf_map__reuse_fd(struct bpf_map *map, int fd)return 0 ; -err_close_new_fd: -close (new_fd); err_free_new_name:free (new_name);return libbpf_err (err);
@@ -5102,7 +5124,7 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, bLIBBPF_OPTS (bpf_map_create_opts, create_attr);struct bpf_map_def *def = &map->def;const char *map_name =NULL ; -int err =0 ; +int err =0 , map_fd;if (kernel_supports (obj,FEAT_PROG_NAME )) map_name = map->name;
@@ -5164,17 +5186,19 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, bbpf_gen__map_create (obj->gen_loader, def->type, map_name, def->key_size, def->value_size, def->max_entries, &create_attr, is_inner ?-1 : map - obj->maps); -/* Pretend to have valid FD to pass various fd >= 0 checks. -* This fd == 0 will not be used with any syscall and will be reset to -1 eventually. +/* We keep pretenting we have valid FD to pass various fd >= 0 +* checks by just keeping original placeholder FDs in place. +* See bpf_object__add_map() comment. +* This placeholder fd will not be used with any syscall and +* will be reset to -1 eventually. */ - map->fd =0 ; + map_fd = map->fd; }else { - map->fd =bpf_map_create (def->type, map_name, - def->key_size, def->value_size, - def->max_entries, &create_attr); + map_fd =bpf_map_create (def->type, map_name, + def->key_size, def->value_size, + def->max_entries, &create_attr); } -if (map->fd <0 && (create_attr.btf_key_type_id || - create_attr.btf_value_type_id)) { +if (map_fd <0 && (create_attr.btf_key_type_id || create_attr.btf_value_type_id)) {char *cp, errmsg[STRERR_BUFSIZE ]; err = -errno;
@@ -5186,13 +5210,11 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b create_attr.btf_value_type_id =0 ; map->btf_key_type_id =0 ; map->btf_value_type_id =0 ; - map->fd =bpf_map_create (def->type, map_name, - def->key_size, def->value_size, - def->max_entries, &create_attr); + map_fd =bpf_map_create (def->type, map_name, + def->key_size, def->value_size, + def->max_entries, &create_attr); } - err = map->fd <0 ? -errno :0 ; -if (bpf_map_type__is_map_in_map (def->type) && map->inner_map) {if (obj->gen_loader) map->inner_map->fd =-1 ;
@@ -5200,7 +5222,19 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, bzfree (&map->inner_map); } -return err; +if (map_fd <0 ) +return map_fd; + +/* obj->gen_loader case, prevent reuse_fd() from closing map_fd */ +if (map->fd == map_fd) +return 0 ; + +/* Keep placeholder FD value but now point it to the BPF map object. +* This way everything that relied on this map's FD (e.g., relocated +* ldimm64 instructions) will stay valid and won't need adjustments. +* map->fd stays valid but now point to what map_fd points to. +*/ +return reuse_fd (map->fd, map_fd); }static int init_map_in_map_slots (struct bpf_object *obj,struct bpf_map *map)
@@ -5284,10 +5318,8 @@ static int bpf_object_init_prog_arrays(struct bpf_object *obj)continue ; err =init_prog_array_slots (obj, map); -if (err <0 ) { -zclose (map->fd); +if (err <0 )return err; - } }return 0 ; }
@@ -5378,25 +5410,20 @@ bpf_object__create_maps(struct bpf_object *obj)if (bpf_map__is_internal (map)) { err =bpf_object__populate_internal_map (obj, map); -if (err <0 ) { -zclose (map->fd); +if (err <0 ) goto err_out; - } }if (map->init_slots_sz && map->def.type !=BPF_MAP_TYPE_PROG_ARRAY ) { err =init_map_in_map_slots (obj, map); -if (err <0 ) { -zclose (map->fd); +if (err <0 ) goto err_out; - } } }if (map->pin_path && !map->pinned) { err =bpf_map__pin (map,NULL );if (err) { -zclose (map->fd);if (!retried && err == -EEXIST ) { retried = true; goto retry;
@@ -7937,8 +7964,8 @@ static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const ch err = err ? :bpf_object__sanitize_and_load_btf (obj); err = err ? :bpf_object__sanitize_maps (obj); err = err ? :bpf_object__init_kern_struct_ops_maps (obj); - err = err ? :bpf_object__create_maps (obj); err = err ? :bpf_object__relocate (obj, obj->btf_custom_path ? : target_btf_path); + err = err ? :bpf_object__create_maps (obj); err = err ? :bpf_object__load_progs (obj, extra_log_level); err = err ? :bpf_object_init_prog_arrays (obj); err = err ? :bpf_object_prepare_struct_ops (obj);
@@ -7947,8 +7974,6 @@ static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const ch/* reset FDs */ if (obj->btf)btf__set_fd (obj->btf,-1 ); -for (i =0 ; i < obj->nr_maps; i++) - obj->maps[i].fd =-1 ;if (!err) err =bpf_gen__finish (obj->gen_loader, obj->nr_programs, obj->nr_maps); }
tools/lib/bpf/libbpf_internal.h +14 -0
@@ -569,6 +569,20 @@ static inline int ensure_good_fd(int fd)return fd; } +/* Point *fixed_fd* to the same file that *tmp_fd* points to. +* Regardless of success, *tmp_fd* is closed. +* Whatever *fixed_fd* pointed to is closed silently. +*/ +static inline int reuse_fd (int fixed_fd,int tmp_fd) +{ +int err; + + err =dup2 (tmp_fd, fixed_fd); + err = err <0 ? -errno :0 ; +close (tmp_fd);/* clean up temporary FD */ +return err; +} +/* The following two functions are exposed to bpftool */ int bpf_core_add_cands(struct bpf_core_cand *local_cand, size_t local_essent_len,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 209/538 libbpf: Find correct module BTFs for struct_ops maps and progs.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kui-Feng Lee <[email protected]>
[ Upstream commit 9e926acda0c2e21bca431a1818665ddcd6939755 ]
Locate the module BTFs for struct_ops maps and progs and pass them to the kernel. This ensures that the kernel correctly resolves type IDs from the appropriate module BTFs.
For the map of a struct_ops object, the FD of the module BTF is set to bpf_map to keep a reference to the module BTF. The FD is passed to the kernel as value_type_btf_obj_fd when the struct_ops object is loaded.
For a bpf_struct_ops prog, attach_btf_obj_fd of bpf_prog is the FD of a module BTF in the kernel.
Stable-dep-of: 04a94133f1b3 ("libbpf: Don't take direct pointers into BTF data from st_ops")
--- tools/lib/bpf/bpf.c | 4 +++- tools/lib/bpf/bpf.h | 4 +++- tools/lib/bpf/libbpf.c | 41 ++++++++++++++++++++++++++--------- tools/lib/bpf/libbpf_probes.c | 1 + 4 files changed, 38 insertions(+), 12 deletions(-)
tools/lib/bpf/bpf.c +3 -1
@@ -169,7 +169,8 @@ int bpf_map_create(enum bpf_map_type map_type,__u32 max_entries, const struct bpf_map_create_opts *opts) { - const size_t attr_sz = offsetofend(union bpf_attr, map_extra); + const size_t attr_sz = offsetofend(union bpf_attr, + value_type_btf_obj_fd);union bpf_attr attr;int fd;
@@ -191,6 +192,7 @@ int bpf_map_create(enum bpf_map_type map_type, attr.btf_key_type_id =OPTS_GET (opts, btf_key_type_id,0 ); attr.btf_value_type_id =OPTS_GET (opts, btf_value_type_id,0 ); attr.btf_vmlinux_value_type_id =OPTS_GET (opts, btf_vmlinux_value_type_id,0 ); + attr.value_type_btf_obj_fd =OPTS_GET (opts, value_type_btf_obj_fd,-1 ); attr.inner_map_fd =OPTS_GET (opts, inner_map_fd,0 ); attr.map_flags =OPTS_GET (opts, map_flags,0 );
tools/lib/bpf/bpf.h +3 -1
@@ -51,8 +51,10 @@ struct bpf_map_create_opts {__u32 numa_node;__u32 map_ifindex; +__s32 value_type_btf_obj_fd; + size_t:0; }; -#define bpf_map_create_opts__last_field map_ifindex +#define bpf_map_create_opts__last_field value_type_btf_obj_fd LIBBPF_API int bpf_map_create(enum bpf_map_type map_type, const char *map_name,
tools/lib/bpf/libbpf.c +31 -10
118 lines not on this page · raw message
tools/lib/bpf/libbpf_probes.c +1 -0
@@ -326,6 +326,7 @@ static int probe_map_create(enum bpf_map_type map_type)case BPF_MAP_TYPE_STRUCT_OPS :/* we'll get -ENOTSUPP for invalid BTF type ID for struct_ops */ opts.btf_vmlinux_value_type_id =1 ; + opts.value_type_btf_obj_fd =-1 ; exp_err =-524 ;/* -ENOTSUPP */ break ;case BPF_MAP_TYPE_BLOOM_FILTER :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 210/538 libbpf: Convert st_ops->data to shadow type.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kui-Feng Lee <[email protected]>
[ Upstream commit 69e4a9d2b3f5adf5af4feeab0a9f505da971265a ]
Convert st_ops->data to the shadow type of the struct_ops map. The shadow type of a struct_ops type is a variant of the original struct type providing a way to access/change the values in the maps of the struct_ops type.
bpf_map__initial_value() will return st_ops->data for struct_ops types. The skeleton is going to use it as the pointer to the shadow type of the original struct type.
One of the main differences between the original struct type and the shadow type is that all function pointers of the shadow type are converted to pointers of struct bpf_program. Users can replace these bpf_program pointers with other BPF programs. The st_ops->progs[] will be updated before updating the value of a map to reflect the changes made by users.
Stable-dep-of: 04a94133f1b3 ("libbpf: Don't take direct pointers into BTF data from st_ops")
--- tools/lib/bpf/libbpf.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-)
tools/lib/bpf/libbpf.c +38 -2
@@ -994,6 +994,19 @@ static bool bpf_map__is_struct_ops(const struct bpf_map *map)return map->def.type ==BPF_MAP_TYPE_STRUCT_OPS ; } +static bool is_valid_st_ops_program (struct bpf_object *obj, +const struct bpf_program *prog) +{ +int i; + +for (i =0 ; i < obj->nr_programs; i++) { +if (&obj->programs[i] == prog) +return prog->type ==BPF_PROG_TYPE_STRUCT_OPS ; + } + +return false; +} +/* Init the map's fields that depend on kern_btf */ static int bpf_map__init_kern_struct_ops (struct bpf_map *map) {
@@ -1082,9 +1095,16 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)if (btf_is_ptr (mtype)) {struct bpf_program *prog; - prog = st_ops->progs[i]; +/* Update the value from the shadow type */ + prog = *(void **)mdata; + st_ops->progs[i] = prog;if (!prog)continue ; +if (!is_valid_st_ops_program (obj, prog)) { +pr_warn ("struct_ops init_kern %s: member %s is not a struct_ops program\n" , + map->name, mname); +return -ENOTSUP ; + } kern_mtype = skip_mods_and_typedefs(kern_btf, kern_mtype->type,
@@ -9165,7 +9185,9 @@ static struct bpf_map *find_struct_ops_map_by_offset(struct bpf_object *obj,return NULL ; } -/* Collect the reloc from ELF and populate the st_ops->progs[] */ +/* Collect the reloc from ELF, populate the st_ops->progs[], and update +* st_ops->data for shadow type. +*/ static int bpf_object__collect_st_ops_relos (struct bpf_object *obj,Elf64_Shdr *shdr,Elf_Data *data) {
@@ -9279,6 +9301,14 @@ static int bpf_object__collect_st_ops_relos(struct bpf_object *obj, } st_ops->progs[member_idx] = prog; + +/* st_ops->data will be exposed to users, being returned by +* bpf_map__initial_value() as a pointer to the shadow +* type. All function pointers in the original struct type +* should be converted to a pointer to struct bpf_program +* in the shadow type. +*/ + *((struct bpf_program **)(st_ops->data + moff)) = prog; }return 0 ;
@@ -9730,6 +9760,12 @@ int bpf_map__set_initial_value(struct bpf_map *map,void *bpf_map__initial_value (struct bpf_map *map,size_t *psize) { +if (bpf_map__is_struct_ops (map)) { +if (psize) + *psize = map->def.value_size; +return map->st_ops->data; + } +if (!map->mmaped)return NULL ; *psize = map->def.value_size;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 211/538 libbpf: Sync progs autoload with maps autocreate for struct_ops maps
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eduard Zingerman <[email protected]>
[ Upstream commit fe9d049c3da06373a1a35914b7f695509e4cb1fe ]
Automatically select which struct_ops programs to load depending on which struct_ops maps are selected for automatic creation. E.g. for the BPF code below:
SEC("struct_ops/test_1") int BPF_PROG(foo) { ... }
SEC("struct_ops/test_2") int BPF_PROG(bar) { ... }
SEC(".struct_ops.link")
struct test_ops___v1 A = {
.foo = (void *)foo
};
SEC(".struct_ops.link")
struct test_ops___v2 B = {
.foo = (void *)foo,
.bar = (void *)bar,
};And the following libbpf API calls:
bpf_map__set_autocreate(skel->maps.A, true);
bpf_map__set_autocreate(skel->maps.B, false);The autoload would be enabled for program 'foo' and disabled for program 'bar'.
During load, for each struct_ops program P, referenced from some struct_ops map M:
- set P.autoload = true if M.autocreate is true for some M;
- set P.autoload = false if M.autocreate is false for all M;
- don't change P.autoload, if P is not referenced from any map.
Do this after bpf_object__init_kern_struct_ops_maps() to make sure that shadow vars assignment is done.
Stable-dep-of: 04a94133f1b3 ("libbpf: Don't take direct pointers into BTF data from st_ops")
--- tools/lib/bpf/libbpf.c | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
tools/lib/bpf/libbpf.c +43 -0
@@ -1007,6 +1007,48 @@ static bool is_valid_st_ops_program(struct bpf_object *obj,return false; } +/* For each struct_ops program P, referenced from some struct_ops map M, +* enable P.autoload if there are Ms for which M.autocreate is true, +* disable P.autoload if for all Ms M.autocreate is false. +* Don't change P.autoload for programs that are not referenced from any maps. +*/ +static int bpf_object_adjust_struct_ops_autoload (struct bpf_object *obj) +{ +struct bpf_program *prog, *slot_prog; +struct bpf_map *map; +int i, j, k, vlen; + +for (i =0 ; i < obj->nr_programs; ++i) { +int should_load = false; +int use_cnt =0 ; + + prog = &obj->programs[i]; +if (prog->type !=BPF_PROG_TYPE_STRUCT_OPS ) +continue ; + +for (j =0 ; j < obj->nr_maps; ++j) { + map = &obj->maps[j]; +if (!bpf_map__is_struct_ops (map)) +continue ; + + vlen =btf_vlen (map->st_ops->type); +for (k =0 ; k < vlen; ++k) { + slot_prog = map->st_ops->progs[k]; +if (prog != slot_prog) +continue ; + + use_cnt++; +if (map->autocreate) + should_load = true; + } + } +if (use_cnt) + prog->autoload = should_load; + } + +return 0 ; +} +/* Init the map's fields that depend on kern_btf */ static int bpf_map__init_kern_struct_ops (struct bpf_map *map) {
@@ -8003,6 +8045,7 @@ static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const ch err = err ? :bpf_object__sanitize_and_load_btf (obj); err = err ? :bpf_object__sanitize_maps (obj); err = err ? :bpf_object__init_kern_struct_ops_maps (obj); + err = err ? :bpf_object_adjust_struct_ops_autoload (obj); err = err ? :bpf_object__relocate (obj, obj->btf_custom_path ? : target_btf_path); err = err ? :bpf_object__create_maps (obj); err = err ? :bpf_object__load_progs (obj, extra_log_level);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 212/538 libbpf: Dont take direct pointers into BTF data from st_ops
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Vernet <[email protected]>
[ Upstream commit 04a94133f1b3cccb19e056c26f056c50b4e5b3b1 ]
In struct bpf_struct_ops, we have take a pointer to a BTF type name, and a struct btf_type. This was presumably done for convenience, but can actually result in subtle and confusing bugs given that BTF data can be invalidated before a program is loaded. For example, in sched_ext, we may sometimes resize a data section after a skeleton has been opened, but before the struct_ops scheduler map has been loaded. This may cause the BTF data to be realloc'd, which can then cause a UAF when loading the program because the struct_ops map has pointers directly into the BTF data.
We're already storing the BTF type_id in struct bpf_struct_ops. Because type_id is stable, we can therefore just update the places where we were looking at those pointers to instead do the lookups we need from the type_id.
--- tools/lib/bpf/libbpf.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
tools/lib/bpf/libbpf.c +13 -10
@@ -457,8 +457,6 @@ struct bpf_program { };struct bpf_struct_ops { -const char *tname; -const struct btf_type *type;struct bpf_program **progs;__u32 *kern_func_off;/* e.g. struct tcp_congestion_ops in bpf_prog's btf format */
@@ -1027,11 +1025,14 @@ static int bpf_object_adjust_struct_ops_autoload(struct bpf_object *obj)continue ;for (j =0 ; j < obj->nr_maps; ++j) { +const struct btf_type *type; + map = &obj->maps[j];if (!bpf_map__is_struct_ops (map))continue ; - vlen =btf_vlen (map->st_ops->type); + type =btf__type_by_id (obj->btf, map->st_ops->type_id); + vlen =btf_vlen (type);for (k =0 ; k < vlen; ++k) { slot_prog = map->st_ops->progs[k];if (prog != slot_prog)
@@ -1065,8 +1066,8 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)int err; st_ops = map->st_ops; - type = st_ops->type; - tname = st_ops->tname; + type =btf__type_by_id (btf, st_ops->type_id); + tname =btf__name_by_offset (btf, type->name_off); err = find_struct_ops_kern_types(obj, tname, &mod_btf, &kern_type, &kern_type_id, &kern_vtype, &kern_vtype_id,
@@ -1298,8 +1299,6 @@ static int init_struct_ops_maps(struct bpf_object *obj, const char *sec_name,memcpy (st_ops->data, data->d_buf + vsi->offset, type->size); - st_ops->tname = tname; - st_ops->type = type; st_ops->type_id = type_id; pr_debug("struct_ops init: struct %s(type_id=%u) %s found at offset %u\n",
@@ -7995,11 +7994,13 @@ static int bpf_object__resolve_externs(struct bpf_object *obj,static void bpf_map_prepare_vdata (const struct bpf_map *map) { +const struct btf_type *type;struct bpf_struct_ops *st_ops;__u32 i; st_ops = map->st_ops; -for (i =0 ; i <btf_vlen (st_ops->type); i++) { + type =btf__type_by_id (map->obj->btf, st_ops->type_id); +for (i =0 ; i <btf_vlen (type); i++) {struct bpf_program *prog = st_ops->progs[i];void *kern_data;int prog_fd;
@@ -9234,6 +9235,7 @@ static struct bpf_map *find_struct_ops_map_by_offset(struct bpf_object *obj,static int bpf_object__collect_st_ops_relos (struct bpf_object *obj,Elf64_Shdr *shdr,Elf_Data *data) { +const struct btf_type *type;const struct btf_member *member;struct bpf_struct_ops *st_ops;struct bpf_program *prog;
@@ -9293,13 +9295,14 @@ static int bpf_object__collect_st_ops_relos(struct bpf_object *obj, } insn_idx = sym->st_value /BPF_INSN_SZ ; - member =find_member_by_offset (st_ops->type, moff *8 ); + type =btf__type_by_id (btf, st_ops->type_id); + member =find_member_by_offset (type, moff *8 );if (!member) {pr_warn ("struct_ops reloc %s: cannot find member at moff %u\n" , map->name, moff);return -EINVAL ; } - member_idx = member -btf_members (st_ops->type); + member_idx = member -btf_members (type); name =btf__name_by_offset (btf, member->name_off);if (!resolve_func_ptr (btf, member->type,NULL )) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 213/538 selftests/bpf: Fix arg parsing in veristat, test_progs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 03bfcda1fbc37ef34aa21d2b9e09138335afc6ee ]
Current code parses arguments with strtok_r() using a construct like
char *state = NULL;
while ((next = strtok_r(state ? NULL : input, ",", &state))) {
...
}where logic assumes the 'state' var can distinguish between first and subsequent strtok_r() calls, and adjusts parameters accordingly. However, 'state' is strictly internal context for strtok_r() and no such assumptions are supported in the man page. Moreover, the exact behaviour of 'state' depends on the libc implementation, making the above code fragile.
Indeed, invoking "./test_progs -t <test_name>" on mips64el/musl will hang, with the above code in an infinite loop.
Similarly, we see strange behaviour running 'veristat' on mips64el/musl:
$ ./veristat -e file,prog,verdict,insns -C two-ok add-failure
Can't specify more than 9 statsRewrite code using a counter to distinguish between strtok_r() calls.
--- tools/testing/selftests/bpf/testing_helpers.c | 4 ++-- tools/testing/selftests/bpf/veristat.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)
tools/testing/selftests/bpf/testing_helpers.c +2 -2
@@ -220,13 +220,13 @@ int parse_test_list(const char *s, bool is_glob_pattern) {char *input, *state =NULL , *test_spec; -int err =0 ; +int err =0 , cnt =0 ; input =strdup (s);if (!input)return -ENOMEM ; -while ((test_spec =strtok_r (state ?NULL : input,"," , &state))) { +while ((test_spec =strtok_r (cnt++ ?NULL : input,"," , &state))) { err =insert_test (set, test_spec, is_glob_pattern);if (err)break ;
tools/testing/selftests/bpf/veristat.c +4 -4
@@ -753,13 +753,13 @@ static int parse_stat(const char *stat_name, struct stat_specs *specs)static int parse_stats (const char *stats_str,struct stat_specs *specs) {char *input, *state =NULL , *next; -int err; +int err, cnt =0 ; input =strdup (stats_str);if (!input)return -ENOMEM ; -while ((next =strtok_r (state ?NULL : input,"," , &state))) { +while ((next =strtok_r (cnt++ ?NULL : input,"," , &state))) { err =parse_stat (next, specs);if (err)return err;
@@ -1444,7 +1444,7 @@ static int parse_stats_csv(const char *filename, struct stat_specs *specs,while (fgets (line,sizeof (line), f)) {char *input = line, *state =NULL , *next;struct verif_stats *st =NULL ; -int col =0 ; +int col =0 , cnt =0 ;if (!header) {void *tmp;
@@ -1462,7 +1462,7 @@ static int parse_stats_csv(const char *filename, struct stat_specs *specs, *stat_cntp +=1 ; } -while ((next =strtok_r (state ?NULL : input,",\n" , &state))) { +while ((next =strtok_r (cnt++ ?NULL : input,",\n" , &state))) {if (header) {/* for the first line, set up spec stats */ err =parse_stat (next, specs);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 214/538 selftests/bpf: Fix error compiling test_lru_map.c
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit cacf2a5a78cd1f5f616eae043ebc6f024104b721 ]
Although the post-increment in macro 'CPU_SET(next++, &cpuset)' seems safe, the sequencing can raise compile errors, so move the increment outside the macro. This avoids an error seen using gcc 12.3.0 for mips64el/musl-libc:
In file included from test_lru_map.c:11:
test_lru_map.c: In function 'sched_next_online':
test_lru_map.c:129:29: error: operation on 'next' may be undefined [-Werror=sequence-point]
129 | CPU_SET(next++, &cpuset);
| ^cc1: all warnings being treated as errors
--- tools/testing/selftests/bpf/test_lru_map.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/testing/selftests/bpf/test_lru_map.c +2 -1
@@ -126,7 +126,8 @@ static int sched_next_online(int pid, int *next_to_try)while (next < nr_cpus) {CPU_ZERO (&cpuset); -CPU_SET (next++, &cpuset); +CPU_SET (next, &cpuset); + next++;if (!sched_setaffinity (pid,sizeof (cpuset), &cpuset)) { ret =0 ;break ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 215/538 selftests/bpf: Fix C++ compile error from missing _Bool type
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit aa95073fd290b5b3e45f067fa22bb25e59e1ff7c ]
While building, bpftool makes a skeleton from test_core_extern.c, which itself includes <stdbool.h> and uses the 'bool' type. However, the skeleton test_core_extern.skel.h generated *does not* include <stdbool.h> or use the 'bool' type, instead using the C-only '_Bool' type. Compiling test_cpp.cpp with g++ 12.3 for mips64el/musl-libc then fails with error:
In file included from test_cpp.cpp:9:
test_core_extern.skel.h:45:17: error: '_Bool' does not name a type
45 | _Bool CONFIG_BOOL;
| ^~~~~This was likely missed previously because glibc uses a GNU extension for <stdbool.h> with C++ (#define _Bool bool), not supported by musl libc.
Normally, a C fragment would include <stdbool.h> and use the 'bool' type, and thus cleanly work after import by C++. The ideal fix would be for 'bpftool gen skeleton' to output the correct type/include supporting C++, but in the meantime add a conditional define as above.
--- tools/testing/selftests/bpf/test_cpp.cpp | 4 ++++ 1 file changed, 4 insertions(+)
tools/testing/selftests/bpf/test_cpp.cpp +4 -0
@@ -6,6 +6,10 @@ #include <bpf/libbpf.h> #include <bpf/bpf.h> #include <bpf/btf.h> + +#ifndef _Bool +#define _Bool bool +#endif #include "test_core_extern.skel.h" template <typename T>
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 216/538 selftests/bpf: Fix flaky selftest lwt_redirect/lwt_reroute
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonghong Song <[email protected]>
[ Upstream commit e7f31873176a345d72ca77c7b4da48493ccd9efd ]
Recently, when running './test_progs -j', I occasionally hit the following errors:
test_lwt_redirect:PASS:pthread_create 0 nsec test_lwt_redirect_run:FAIL:netns_create unexpected error: 256 (errno 0)
#142/2 lwt_redirect/lwt_redirect_normal_nomac:FAIL
#142 lwt_redirect:FAIL
test_lwt_reroute:PASS:pthread_create 0 nsec test_lwt_reroute_run:FAIL:netns_create unexpected error: 256 (errno 0) test_lwt_reroute:PASS:pthread_join 0 nsec
#143/2 lwt_reroute/lwt_reroute_qdisc_dropped:FAIL
#143 lwt_reroute:FAIL
The netns_create() definition looks like below:
#define NETNS "ns_lwt"
static inline int netns_create(void)
{
return system("ip netns add " NETNS);
}One possibility is that both lwt_redirect and lwt_reroute create netns with the same name "ns_lwt" which may cause conflict. I tried the following example:
$ sudo ip netns add abc $ echo $? 0 $ sudo ip netns add abc Cannot create namespace file "/var/run/netns/abc": File exists $ echo $? 1 $
The return code for above netns_create() is 256. The internet search suggests that the return value for 'ip netns add ns_lwt' is 1, which matches the above 'sudo ip netns add abc' example.
This patch tried to use different netns names for two tests to avoid 'ip netns add <name>' failure.
I ran './test_progs -j' 10 times and all succeeded with lwt_redirect/lwt_reroute tests.
Stable-dep-of: 16b795cc5952 ("selftests/bpf: Fix redefinition errors compiling lwt_reroute.c")
--- tools/testing/selftests/bpf/prog_tests/lwt_helpers.h | 2 -- tools/testing/selftests/bpf/prog_tests/lwt_redirect.c | 1 + tools/testing/selftests/bpf/prog_tests/lwt_reroute.c | 1 + 3 files changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/bpf/prog_tests/lwt_helpers.h +0 -2
@@ -27,8 +27,6 @@ } \ }) -#define NETNS "ns_lwt" -static inline int netns_create (void ) {return system ("ip netns add " NETNS );
tools/testing/selftests/bpf/prog_tests/lwt_redirect.c +1 -0
@@ -53,6 +53,7 @@#include <stdbool.h> #include <stdlib.h> +#define NETNS "ns_lwt_redirect"#include "lwt_helpers.h" #include "test_progs.h" #include "network_helpers.h"
tools/testing/selftests/bpf/prog_tests/lwt_reroute.c +1 -0
@@ -48,6 +48,7 @@* For case 2, force UDP packets to overflow fq limit. As long as kernel * is not crashed, it is considered successful. */ +#define NETNS "ns_lwt_reroute"#include "lwt_helpers.h" #include "network_helpers.h" #include <linux/net_tstamp.h>
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 217/538 selftests/bpf: Fix redefinition errors compiling lwt_reroute.c
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 16b795cc59528cf280abc79af3c70bda42f715b9 ]
Compiling lwt_reroute.c with GCC 12.3 for mips64el/musl-libc yields errors:
In file included from .../include/arpa/inet.h:9,
from ./test_progs.h:18,
from tools/testing/selftests/bpf/prog_tests/lwt_helpers.h:11,
from tools/testing/selftests/bpf/prog_tests/lwt_reroute.c:52:
.../include/netinet/in.h:23:8: error: redefinition of 'struct in6_addr'
23 | struct in6_addr {
| ^~~~~~~~
In file included from .../include/linux/icmp.h:24,
from tools/testing/selftests/bpf/prog_tests/lwt_helpers.h:9:
.../include/linux/in6.h:33:8: note: originally defined here
33 | struct in6_addr {
| ^~~~~~~~
.../include/netinet/in.h:34:8: error: redefinition of 'struct sockaddr_in6'
34 | struct sockaddr_in6 {
| ^~~~~~~~~~~~
.../include/linux/in6.h:50:8: note: originally defined here
50 | struct sockaddr_in6 {
| ^~~~~~~~~~~~
.../include/netinet/in.h:42:8: error: redefinition of 'struct ipv6_mreq'
42 | struct ipv6_mreq {
| ^~~~~~~~~
.../include/linux/in6.h:60:8: note: originally defined here
60 | struct ipv6_mreq {
| ^~~~~~~~~These errors occur because <linux/in6.h> is included before <netinet/in.h>, bypassing the Linux uapi/libc compat mechanism's partial musl support. As described in [1] and [2], fix these errors by including <netinet/in.h> in lwt_reroute.c before any uapi headers.
[1]: commit c0bace798436 ("uapi libc compat: add fallback for unsupported libcs") [2]: https://git.musl-libc.org/cgit/musl/commit/?id=04983f227238
--- tools/testing/selftests/bpf/prog_tests/lwt_reroute.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/prog_tests/lwt_reroute.c +1 -0
@@ -49,6 +49,7 @@* is not crashed, it is considered successful. */ #define NETNS "ns_lwt_reroute" +#include <netinet/in.h> #include "lwt_helpers.h" #include "network_helpers.h" #include <linux/net_tstamp.h>
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 218/538 selftests/bpf: Fix compile if backtrace support missing in libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit c9a83e76b5a96801a2c7ea0a79ca77c356d8b38d ]
Include GNU <execinfo.h> header only with glibc and provide weak, stubbed backtrace functions as a fallback in test_progs.c. This allows for non-GNU replacements while avoiding compile errors (e.g. with musl libc) like:
test_progs.c:13:10: fatal error: execinfo.h: No such file or directory
13 | #include <execinfo.h> /* backtrace */
| ^~~~~~~~~~~~
test_progs.c: In function 'crash_handler':
test_progs.c:1034:14: error: implicit declaration of function 'backtrace' [-Werror=implicit-function-declaration]
1034 | sz = backtrace(bt, ARRAY_SIZE(bt));
| ^~~~~~~~~
test_progs.c:1045:9: error: implicit declaration of function 'backtrace_symbols_fd' [-Werror=implicit-function-declaration]
1045 | backtrace_symbols_fd(bt, sz, STDERR_FILENO);
| ^~~~~~~~~~~~~~~~~~~~--- tools/testing/selftests/bpf/test_progs.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
tools/testing/selftests/bpf/test_progs.c +15 -1
@@ -10,7 +10,6 @@#include <sched.h> #include <signal.h> #include <string.h> -#include <execinfo.h> /* backtrace */ #include <sys/sysinfo.h> /* get_nprocs */ #include <netinet/in.h> #include <sys/select.h>
@@ -19,6 +18,21 @@#include <bpf/btf.h> #include "json_writer.h" +#ifdef __GLIBC__ +#include <execinfo.h> /* backtrace */ +#endif + +/* Default backtrace funcs if missing at link */ +__weak int backtrace (void **buffer,int size) +{ +return 0 ; +} + +__weak void backtrace_symbols_fd (void *const *buffer,int size,int fd) +{ +dprintf (fd,"<backtrace not supported>\n" ); +} +static bool verbose (void ) {return env.verbosity >VERBOSE_NONE ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 219/538 selftests/bpf: Fix error compiling tc_redirect.c with musl libc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony Ambardar <[email protected]>
[ Upstream commit 21c5f4f55da759c7444a1ef13e90b6e6f674eeeb ]
Linux 5.1 implemented 64-bit time types and related syscalls to address the Y2038 problem generally across archs. Userspace handling of Y2038 varies with the libc however. While musl libc uses 64-bit time across all 32-bit and 64-bit platforms, GNU glibc uses 64-bit time on 64-bit platforms but defaults to 32-bit time on 32-bit platforms unless they "opt-in" to 64-bit time or explicitly use 64-bit syscalls and time structures.
One specific area is the standard setsockopt() call, SO_TIMESTAMPNS option used for timestamping, and the related output 'struct timespec'. GNU glibc defaults as above, also exposing the SO_TIMESTAMPNS_NEW flag to explicitly use a 64-bit call and 'struct __kernel_timespec'. Since these are not exposed or needed with musl libc, their use in tc_redirect.c leads to compile errors building for mips64el/musl:
tc_redirect.c: In function 'rcv_tstamp':
tc_redirect.c:425:32: error: 'SO_TIMESTAMPNS_NEW' undeclared (first use in this function); did you mean 'SO_TIMESTAMPNS'?
425 | cmsg->cmsg_type == SO_TIMESTAMPNS_NEW)
| ^~~~~~~~~~~~~~~~~~
| SO_TIMESTAMPNS
tc_redirect.c:425:32: note: each undeclared identifier is reported only once for each function it appears in
tc_redirect.c: In function 'test_inet_dtime':
tc_redirect.c:491:49: error: 'SO_TIMESTAMPNS_NEW' undeclared (first use in this function); did you mean 'SO_TIMESTAMPNS'?
491 | err = setsockopt(listen_fd, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
| ^~~~~~~~~~~~~~~~~~
| SO_TIMESTAMPNSHowever, using SO_TIMESTAMPNS_NEW isn't strictly needed, nor is Y2038 being explicitly tested. The timestamp checks in tc_redirect.c are simple: the packet receive timestamp is non-zero and processed/handled in less than 5 seconds.
Switch to using the standard setsockopt() call and SO_TIMESTAMPNS option to ensure compatibility across glibc and musl libc. In the worst-case, there is a 5-second window 14 years from now where tc_redirect tests may fail on 32-bit systems. However, we should reasonably expect glibc to adopt a 64-bit mandate rather than the current "opt-in" policy before the Y2038 roll-over.
--- tools/testing/selftests/bpf/prog_tests/tc_redirect.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
tools/testing/selftests/bpf/prog_tests/tc_redirect.c +6 -6
@@ -421,7 +421,7 @@ static int set_forwarding(bool enable)static int __rcv_tstamp (int fd,const char *expected,size_t s,__u64 *tstamp) { -struct __kernel_timespec pkt_ts = {}; +struct timespec pkt_ts = {};char ctl[CMSG_SPACE (sizeof (pkt_ts))];struct timespec now_ts;struct msghdr msg = {};
@@ -445,7 +445,7 @@ static int __rcv_tstamp(int fd, const char *expected, size_t s, __u64 *tstamp) cmsg =CMSG_FIRSTHDR (&msg);if (cmsg && cmsg->cmsg_level ==SOL_SOCKET && - cmsg->cmsg_type ==SO_TIMESTAMPNS_NEW ) + cmsg->cmsg_type ==SO_TIMESTAMPNS )memcpy (&pkt_ts,CMSG_DATA (cmsg),sizeof (pkt_ts)); pkt_ns = pkt_ts.tv_sec *NSEC_PER_SEC + pkt_ts.tv_nsec;
@@ -487,9 +487,9 @@ static int wait_netstamp_needed_key(void)if (!ASSERT_GE (srv_fd,0 ,"start_server" )) goto done; - err =setsockopt (srv_fd,SOL_SOCKET ,SO_TIMESTAMPNS_NEW , + err =setsockopt (srv_fd,SOL_SOCKET ,SO_TIMESTAMPNS , &opt,sizeof (opt)); -if (!ASSERT_OK (err,"setsockopt(SO_TIMESTAMPNS_NEW)" )) +if (!ASSERT_OK (err,"setsockopt(SO_TIMESTAMPNS)" )) goto done; cli_fd =connect_to_fd (srv_fd,TIMEOUT_MILLIS );
@@ -571,9 +571,9 @@ static void test_inet_dtime(int family, int type, const char *addr, __u16 port)return ;/* Ensure the kernel puts the (rcv) timestamp for all skb */ - err =setsockopt (listen_fd,SOL_SOCKET ,SO_TIMESTAMPNS_NEW , + err =setsockopt (listen_fd,SOL_SOCKET ,SO_TIMESTAMPNS , &opt,sizeof (opt)); -if (!ASSERT_OK (err,"setsockopt(SO_TIMESTAMPNS_NEW)" )) +if (!ASSERT_OK (err,"setsockopt(SO_TIMESTAMPNS)" )) goto done;if (type ==SOCK_STREAM ) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 220/538 samples/bpf: Fix compilation errors with cf-protection option
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiangshan Yi <[email protected]>
[ Upstream commit fdf1c728fac541891ef1aa773bfd42728626769c ]
Currently, compiling the bpf programs will result the compilation errors with the cf-protection option as follows in arm64 and loongarch64 machine when using gcc 12.3.1 and clang 17.0.6. This commit fixes the compilation errors by limited the cf-protection option only used in x86 platform.
[root@localhost linux]# make M=samples/bpf
......
CLANG-bpf samples/bpf/xdp2skb_meta_kern.o
error: option 'cf-protection=return' cannot be specified on this target
error: option 'cf-protection=branch' cannot be specified on this target 2 errors generated.
CLANG-bpf samples/bpf/syscall_tp_kern.o
error: option 'cf-protection=return' cannot be specified on this target
error: option 'cf-protection=branch' cannot be specified on this target 2 errors generated.
......
--- samples/bpf/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
samples/bpf/Makefile +5 -1
@@ -166,6 +166,10 @@ BPF_EXTRA_CFLAGS += -I$(srctree)/arch/mips/include/asm/mach-generic endif endif +ifeq ($(ARCH), x86) +BPF_EXTRA_CFLAGS += -fcf-protection +endif + TPROGS_CFLAGS += -Wall -O2 TPROGS_CFLAGS += -Wmissing-prototypes TPROGS_CFLAGS += -Wstrict-prototypes
@@ -394,7 +398,7 @@ $(obj)/%.o: $(src)/%.c -Wno-gnu-variable-sized-type-not-at-end \ -Wno-address-of-packed-member -Wno-tautological-compare \ -Wno-unknown-warning-option $(CLANG_ARCH_ARGS) \ - -fno-asynchronous-unwind-tables -fcf-protection \ + -fno-asynchronous-unwind-tables \ -I$(srctree)/samples/bpf/ -include asm_goto_workaround.h \ -O2 -emit-llvm -Xclang -disable-llvm-passes -c $< -o - | \ $(OPT) -O2 -mtriple=bpf-pc-linux | $(LLVM_DIS) | \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 221/538 bpf: correctly handle malformed BPF_CORE_TYPE_ID_LOCAL relos
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eduard Zingerman <[email protected]>
[ Upstream commit 3d2786d65aaa954ebd3fcc033ada433e10da21c4 ]
In case of malformed relocation record of kind BPF_CORE_TYPE_ID_LOCAL referencing a non-existing BTF type, function bpf_core_calc_relo_insn would cause a null pointer deference.
Fix this by adding a proper check upper in call stack, as malformed relocation records could be passed from user space.
Simplest reproducer is a program:
r0 = 0
exitWith a single relocation record:
.insn_off = 0, /* patch first instruction */
.type_id = 100500, /* this type id does not exist */
.access_str_off = 6, /* offset of string "0" */ .kind = BPF_CORE_TYPE_ID_LOCAL,
See the link for original reproducer or next commit for a test case.
--- kernel/bpf/btf.c | 8 ++++++++ 1 file changed, 8 insertions(+)
kernel/bpf/btf.c +8 -0
@@ -8421,6 +8421,7 @@ int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo,struct bpf_core_cand_list cands = {};struct bpf_core_relo_res targ_res;struct bpf_core_spec *specs; +const struct btf_type *type;int err;/* ~4k of temp memory necessary to convert LLVM spec like "0:1:0:5"
@@ -8430,6 +8431,13 @@ int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo,if (!specs)return -ENOMEM ; + type =btf_type_by_id (ctx->btf, relo->type_id); +if (!type) { +bpf_log (ctx->log,"relo #%u: bad type id %u\n" , + relo_idx, relo->type_id); +return -EINVAL ; + } +if (need_cands) {struct bpf_cand_cache *cc;int i;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 222/538 xz: cleanup CRC32 edits from 2018
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lasse Collin <[email protected]>
[ Upstream commit 2ee96abef214550d9e92f5143ee3ac1fd1323e67 ]
In 2018, a dependency on <linux/crc32poly.h> was added to avoid duplicating the same constant in multiple files. Two months later it was found to be a bad idea and the definition of CRC32_POLY_LE macro was moved into xz_private.h to avoid including <linux/crc32poly.h>.
xz_private.h is a wrong place for it too. Revert back to the upstream version which has the poly in xz_crc32_init() in xz_crc32.c.
--- lib/xz/xz_crc32.c | 2 +- lib/xz/xz_private.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-)
lib/xz/xz_crc32.c +1 -1
@@ -29,7 +29,7 @@ STATIC_RW_DATA uint32_t xz_crc32_table[256]; XZ_EXTERN void xz_crc32_init(void) { -const uint32_t poly =CRC32_POLY_LE ; +const uint32_t poly =0xEDB88320 ;uint32_t i;uint32_t j;
lib/xz/xz_private.h +0 -4
@@ -105,10 +105,6 @@# endif #endif -#ifndef CRC32_POLY_LE -#define CRC32_POLY_LE 0xedb88320 -#endif -/* * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used * before calling xz_dec_lzma2_run().
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 223/538 kthread: fix task state in kthread worker if being frozen
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Yu <[email protected]>
[ Upstream commit e16c7b07784f3fb03025939c4590b9a7c64970a7 ]
When analyzing a kernel waring message, Peter pointed out that there is a race condition when the kworker is being frozen and falls into try_to_freeze() with TASK_INTERRUPTIBLE, which could trigger a might_sleep() warning in try_to_freeze(). Although the root cause is not related to freeze()[1], it is still worthy to fix this issue ahead.
One possible race scenario:
CPU 0 CPU 1
----- -----
// kthread_worker_fn
set_current_state(TASK_INTERRUPTIBLE);
suspend_freeze_processes()
freeze_processes
static_branch_inc(&freezer_active);
freeze_kernel_threads
pm_nosig_freezing = true;
if (work) { //false
__set_current_state(TASK_RUNNING);
} else if (!freezing(current)) //false, been frozen
freezing():
if (static_branch_unlikely(&freezer_active))
if (pm_nosig_freezing)
return true;
schedule()
}
// state is still TASK_INTERRUPTIBLE
try_to_freeze()
might_sleep() <--- warningFix this by explicitly set the TASK_RUNNING before entering try_to_freeze().
--- kernel/kthread.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
kernel/kthread.c +9 -1
@@ -844,8 +844,16 @@ int kthread_worker_fn(void *worker_ptr)* event only cares about the address. */ trace_sched_kthread_work_execute_end (work, func); - }else if (!freezing (current)) + }else if (!freezing (current)) {schedule (); + }else { +/* +* Handle the case where the current remains +* TASK_INTERRUPTIBLE. try_to_freeze() expects +* the current to be TASK_RUNNING. +*/ +__set_current_state (TASK_RUNNING ); + }try_to_freeze ();cond_resched ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 224/538 ext4: clear EXT4_GROUP_INFO_WAS_TRIMMED_BIT even mount with discard
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: yangerkun <[email protected]>
[ Upstream commit 20cee68f5b44fdc2942d20f3172a262ec247b117 ]
Commit 3d56b8d2c74c ("ext4: Speed up FITRIM by recording flags in ext4_group_info") speed up fstrim by skipping trim trimmed group. We also has the chance to clear trimmed once there exists some block free for this group(mount without discard), and the next trim for this group will work well too.
For mount with discard, we will issue dicard when we free blocks, so leave trimmed flag keep alive to skip useless trim trigger from userspace seems reasonable. But for some case like ext4 build on dm-thinpool(ext4 blocksize 4K, pool blocksize 128K), discard from ext4 maybe unaligned for dm thinpool, and thinpool will just finish this discard(see process_discard_bio when begein equals to end) without actually process discard. For this case, trim from userspace can really help us to free some thinpool block.
So convert to clear trimmed flag for all case no matter mounted with discard or not.
--- fs/ext4/mballoc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
fs/ext4/mballoc.c +4 -6
@@ -3886,11 +3886,8 @@ static void ext4_free_data_in_buddy(struct super_block *sb,/* * Clear the trimmed flag for the group so that the next * ext4_trim_fs can trim it. -* If the volume is mounted with -o discard, online discard -* is supported and the free blocks will be trimmed online. */ -if (!test_opt (sb,DISCARD )) -EXT4_MB_GRP_CLEAR_TRIMMED (db); +EXT4_MB_GRP_CLEAR_TRIMMED (db);if (!db->bb_free_root.rb_node) {/* No more items in the per group rb tree
@@ -6586,8 +6583,9 @@ static void ext4_mb_clear_bb(handle_t *handle, struct inode *inode," group:%u block:%d count:%lu failed" " with %d" , block_group, bit, count, err); - }else -EXT4_MB_GRP_CLEAR_TRIMMED (e4b.bd_info); + } + +EXT4_MB_GRP_CLEAR_TRIMMED (e4b.bd_info);ext4_lock_group (sb, block_group);mb_clear_bits (bitmap_bh->b_data, bit, count_clusters);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 225/538 smackfs: Use rcu_assign_pointer() to ensure safe assignment in smk_set_cipso
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiawei Ye <[email protected]>
[ Upstream commit 2749749afa071f8a0e405605de9da615e771a7ce ]
In the smk_set_cipso function, the skp->smk_netlabel.attr.mls.cat field is directly assigned to a new value without using the appropriate RCU pointer assignment functions. According to RCU usage rules, this is illegal and can lead to unpredictable behavior, including data inconsistencies and impossible-to-diagnose memory corruption issues.
This possible bug was identified using a static analysis tool developed by myself, specifically designed to detect RCU-related issues.
To address this, the assignment is now done using rcu_assign_pointer(), which ensures that the pointer assignment is done safely, with the necessary memory barriers and synchronization. This change prevents potential RCU dereference issues by ensuring that the cat field is safely updated while still adhering to RCU's requirements.
--- security/smack/smackfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/smack/smackfs.c +1 -1
@@ -932,7 +932,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, }if (rc >=0 ) { old_cat = skp->smk_netlabel.attr.mls.cat; - skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat; +rcu_assign_pointer (skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;synchronize_rcu ();netlbl_catmap_free (old_cat);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 226/538 ext4: avoid buffer_head leak in ext4_mark_inode_used()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kemeng Shi <[email protected]>
[ Upstream commit 5e5b2a56c57def1b41efd49596621504d7bcc61c ]
Release inode_bitmap_bh from ext4_read_inode_bitmap() in ext4_mark_inode_used() to avoid buffer_head leak.
By the way, remove unneeded goto for invalid ino when inode_bitmap_bh is NULL.
--- fs/ext4/ialloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/ext4/ialloc.c +3 -2
@@ -755,10 +755,10 @@ int ext4_mark_inode_used(struct super_block *sb, int ino)struct ext4_group_desc *gdp;ext4_group_t group;int bit; -int err = -EFSCORRUPTED ; +int err;if (ino <EXT4_FIRST_INO (sb) || ino > max_ino) - goto out; +return -EFSCORRUPTED ; group = (ino -1 ) /EXT4_INODES_PER_GROUP (sb); bit = (ino -1 ) %EXT4_INODES_PER_GROUP (sb);
@@ -860,6 +860,7 @@ int ext4_mark_inode_used(struct super_block *sb, int ino) err =ext4_handle_dirty_metadata (NULL ,NULL , group_desc_bh);sync_dirty_buffer (group_desc_bh); out: +brelse (inode_bitmap_bh);return err; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 227/538 ext4: avoid potential buffer_head leak in __ext4_new_inode()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kemeng Shi <[email protected]>
[ Upstream commit 227d31b9214d1b9513383cf6c7180628d4b3b61f ]
If a group is marked EXT4_GROUP_INFO_IBITMAP_CORRUPT after it's inode bitmap buffer_head was successfully verified, then __ext4_new_inode() will get a valid inode_bitmap_bh of a corrupted group from ext4_read_inode_bitmap() in which case inode_bitmap_bh misses a release. Hnadle "IS_ERR(inode_bitmap_bh)" and group corruption separately like how ext4_free_inode() does to avoid buffer_head leak.
--- fs/ext4/ialloc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
fs/ext4/ialloc.c +4 -3
@@ -1054,12 +1054,13 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap,brelse (inode_bitmap_bh); inode_bitmap_bh =ext4_read_inode_bitmap (sb, group);/* Skip groups with suspicious inode tables */ -if (((!(sbi->s_mount_state &EXT4_FC_REPLAY )) - &&EXT4_MB_GRP_IBITMAP_CORRUPT (grp)) || -IS_ERR (inode_bitmap_bh)) { +if (IS_ERR (inode_bitmap_bh)) { inode_bitmap_bh =NULL ; goto next_group; } +if (!(sbi->s_mount_state &EXT4_FC_REPLAY ) && +EXT4_MB_GRP_IBITMAP_CORRUPT (grp)) + goto next_group; repeat_in_this_group: ret2 =find_inode_bit (sb, group, inode_bitmap_bh, &ino);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 228/538 ext4: avoid negative min_clusters in find_group_orlov()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kemeng Shi <[email protected]>
[ Upstream commit bb0a12c3439b10d88412fd3102df5b9a6e3cd6dc ]
min_clusters is signed integer and will be converted to unsigned integer when compared with unsigned number stats.free_clusters. If min_clusters is negative, it will be converted to a huge unsigned value in which case all groups may not meet the actual desired free clusters.
Set negative min_clusters to 0 to avoid unexpected behavior.
--- fs/ext4/ialloc.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ext4/ialloc.c +2 -0
@@ -514,6 +514,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,if (min_inodes <1 ) min_inodes =1 ; min_clusters = avefreec -EXT4_CLUSTERS_PER_GROUP (sb)*flex_size /4 ; +if (min_clusters <0 ) + min_clusters =0 ;/* * Start looking in the flex group where we last allocated an
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 229/538 ext4: return error on ext4_find_inline_entry
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thadeu Lima de Souza Cascardo <[email protected]>
[ Upstream commit 4d231b91a944f3cab355fce65af5871fb5d7735b ]
In case of errors when reading an inode from disk or traversing inline directory entries, return an error-encoded ERR_PTR instead of returning NULL. ext4_find_inline_entry only caller, __ext4_find_entry already returns such encoded errors.
Stable-dep-of: c6b72f5d82b1 ("ext4: avoid OOB when system.data xattr changes underneath the filesystem")
--- fs/ext4/inline.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
fs/ext4/inline.c +7 -3
@@ -1670,8 +1670,9 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,void *inline_start;int inline_size; -if (ext4_get_inode_loc (dir, &iloc)) -return NULL ; + ret =ext4_get_inode_loc (dir, &iloc); +if (ret) +return ERR_PTR (ret);down_read (&EXT4_I (dir)->xattr_sem);if (!ext4_has_inline_data (dir)) {
@@ -1702,7 +1703,10 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, out:brelse (iloc.bh); - iloc.bh =NULL ; +if (ret <0 ) + iloc.bh =ERR_PTR (ret); +else + iloc.bh =NULL ; out_find:up_read (&EXT4_I (dir)->xattr_sem);return iloc.bh;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 230/538 ext4: avoid OOB when system.data xattr changes underneath the filesystem
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thadeu Lima de Souza Cascardo <[email protected]>
[ Upstream commit c6b72f5d82b1017bad80f9ebf502832fc321d796 ]
When looking up for an entry in an inlined directory, if e_value_offs is changed underneath the filesystem by some change in the block device, it will lead to an out-of-bounds access that KASAN detects as an UAF.
EXT4-fs (loop0): mounted filesystem 00000000-0000-0000-0000-000000000000 r/w without journal. Quota mode: none.
loop0: detected capacity change from 2048 to 2047
==================================================================
BUG: KASAN: use-after-free in ext4_search_dir+0xf2/0x1c0 fs/ext4/namei.c:1500 Read of size 1 at addr ffff88803e91130f by task syz-executor269/5103 CPU: 0 UID: 0 PID: 5103 Comm: syz-executor269 Not tainted 6.11.0-rc4-syzkaller #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Call Trace: <TASK> __dump_stack lib/dump_stack.c:93 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119 print_address_description mm/kasan/report.c:377 [inline] print_report+0x169/0x550 mm/kasan/report.c:488 kasan_report+0x143/0x180 mm/kasan/report.c:601 ext4_search_dir+0xf2/0x1c0 fs/ext4/namei.c:1500 ext4_find_inline_entry+0x4be/0x5e0 fs/ext4/inline.c:1697 __ext4_find_entry+0x2b4/0x1b30 fs/ext4/namei.c:1573 ext4_lookup_entry fs/ext4/namei.c:1727 [inline] ext4_lookup+0x15f/0x750 fs/ext4/namei.c:1795 lookup_one_qstr_excl+0x11f/0x260 fs/namei.c:1633 filename_create+0x297/0x540 fs/namei.c:3980 do_symlinkat+0xf9/0x3a0 fs/namei.c:4587 __do_sys_symlinkat fs/namei.c:4610 [inline] __se_sys_symlinkat fs/namei.c:4607 [inline] __x64_sys_symlinkat+0x95/0xb0 fs/namei.c:4607 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f3e73ced469 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 21 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fff4d40c258 EFLAGS: 00000246 ORIG_RAX: 000000000000010a RAX: ffffffffffffffda RBX: 0032656c69662f2e RCX: 00007f3e73ced469 RDX: 0000000020000200 RSI: 00000000ffffff9c RDI: 00000000200001c0 RBP: 0000000000000000 R08: 00007fff4d40c290 R09: 00007fff4d40c290 R10: 0023706f6f6c2f76 R11: 0000000000000246 R12: 00007fff4d40c27c R13: 0000000000000003 R14: 431bde82d7b634db R15: 00007fff4d40c2b0 </TASK>
Calling ext4_xattr_ibody_find right after reading the inode with ext4_get_inode_loc will lead to a check of the validity of the xattrs, avoiding this problem.
--- fs/ext4/inline.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-)
fs/ext4/inline.c +21 -10
@@ -1665,25 +1665,36 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,struct ext4_dir_entry_2 **res_dir, int *has_inline_data) { + struct ext4_xattr_ibody_find is = { + .s = { .not_found = -ENODATA , }, + }; +struct ext4_xattr_info i = { + .name_index =EXT4_XATTR_INDEX_SYSTEM , + .name =EXT4_XATTR_SYSTEM_DATA , + };int ret; -struct ext4_iloc iloc;void *inline_start;int inline_size; - ret =ext4_get_inode_loc (dir, &iloc); + ret =ext4_get_inode_loc (dir, &is.iloc);if (ret)return ERR_PTR (ret);down_read (&EXT4_I (dir)->xattr_sem); + + ret =ext4_xattr_ibody_find (dir, &i, &is); +if (ret) + goto out; +if (!ext4_has_inline_data (dir)) { *has_inline_data =0 ; goto out; } - inline_start = (void *)ext4_raw_inode (&iloc)->i_block + + inline_start = (void *)ext4_raw_inode (&is.iloc)->i_block +EXT4_INLINE_DOTDOT_SIZE ; inline_size =EXT4_MIN_INLINE_DATA_SIZE -EXT4_INLINE_DOTDOT_SIZE ; - ret =ext4_search_dir (iloc.bh, inline_start, inline_size, + ret =ext4_search_dir (is.iloc.bh, inline_start, inline_size, dir, fname,0 , res_dir);if (ret ==1 ) goto out_find;
@@ -1693,23 +1704,23 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,if (ext4_get_inline_size (dir) ==EXT4_MIN_INLINE_DATA_SIZE ) goto out; - inline_start =ext4_get_inline_xattr_pos (dir, &iloc); + inline_start =ext4_get_inline_xattr_pos (dir, &is.iloc); inline_size =ext4_get_inline_size (dir) -EXT4_MIN_INLINE_DATA_SIZE ; - ret =ext4_search_dir (iloc.bh, inline_start, inline_size, + ret =ext4_search_dir (is.iloc.bh, inline_start, inline_size, dir, fname,0 , res_dir);if (ret ==1 ) goto out_find; out: -brelse (iloc.bh); +brelse (is.iloc.bh);if (ret <0 ) - iloc.bh =ERR_PTR (ret); + is.iloc.bh =ERR_PTR (ret);else - iloc.bh =NULL ; + is.iloc.bh =NULL ; out_find:up_read (&EXT4_I (dir)->xattr_sem); -return iloc.bh; +return is.iloc.bh; } int ext4_delete_inline_entry(handle_t *handle,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 231/538 ext4: check stripe size compatibility on remount as well
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ojaswin Mujoo <[email protected]>
[ Upstream commit ee85e0938aa8f9846d21e4d302c3cf6a2a75110d ]
We disable stripe size in __ext4_fill_super if it is not a multiple of the cluster ratio however this check is missed when trying to remount. This can leave us with cases where stripe < cluster_ratio after remount:set making EXT4_B2C(sbi->s_stripe) become 0 that can cause some unforeseen bugs like divide by 0.
Fix that by adding the check in remount path as well.
--- fs/ext4/super.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-)
fs/ext4/super.c +22 -7
@@ -5205,6 +5205,18 @@ static int ext4_block_group_meta_init(struct super_block *sb, int silent)return 0 ; } +/* +* It's hard to get stripe aligned blocks if stripe is not aligned with +* cluster, just disable stripe and alert user to simplify code and avoid +* stripe aligned allocation which will rarely succeed. +*/ +static bool ext4_is_stripe_incompatible (struct super_block *sb,unsigned long stripe) +{ +struct ext4_sb_info *sbi =EXT4_SB (sb); +return (stripe >0 && sbi->s_cluster_ratio >1 && + stripe % sbi->s_cluster_ratio !=0 ); +} +static int __ext4_fill_super (struct fs_context *fc,struct super_block *sb) {struct ext4_super_block *es =NULL ;
@@ -5312,13 +5324,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) goto failed_mount3; sbi->s_stripe =ext4_get_stripe_size (sbi); -/* -* It's hard to get stripe aligned blocks if stripe is not aligned with -* cluster, just disable stripe and alert user to simpfy code and avoid -* stripe aligned allocation which will rarely successes. -*/ -if (sbi->s_stripe >0 && sbi->s_cluster_ratio >1 && - sbi->s_stripe % sbi->s_cluster_ratio !=0 ) { +if (ext4_is_stripe_incompatible (sb, sbi->s_stripe)) { ext4_msg(sb, KERN_WARNING, "stripe (%lu) is not aligned with cluster size (%u), " "stripe is disabled",
@@ -6482,6 +6488,15 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb) } +if ((ctx->spec & EXT4_SPEC_s_stripe) && +ext4_is_stripe_incompatible (sb, ctx->s_stripe)) { +ext4_msg (sb,KERN_WARNING , +"stripe (%lu) is not aligned with cluster size (%u), " +"stripe is disabled" , + ctx->s_stripe, sbi->s_cluster_ratio); + ctx->s_stripe =0 ; + } +/* * Changing the DIOREAD_NOLOCK or DELALLOC mount options may cause * two calls to ext4_should_dioread_nolock() to return inconsistent
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 232/538 sched/numa: Document vma_numab_state fields
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mel Gorman <[email protected]>
[ Upstream commit 9ae5c00ea2e600a8b823f9b95606dd244f3096bf ]
Document the intended usage of the fields.
[ mingo: Reformatted to take less vertical space & tidied it up. ]
Stable-dep-of: f22cde4371f3 ("sched/numa: Fix the vma scan starving issue")
--- include/linux/mm_types.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
include/linux/mm_types.h +21 -0
@@ -551,8 +551,29 @@ struct vma_lock { };struct vma_numab_state { +/* +* Initialised as time in 'jiffies' after which VMA +* should be scanned. Delays first scan of new VMA by at +* least sysctl_numa_balancing_scan_delay: +*/ unsigned long next_scan; + +/* +* Time in jiffies when access_pids[] is reset to +* detect phase change behaviour: +*/ unsigned long next_pid_reset; + +/* +* Approximate tracking of PIDs that trapped a NUMA hinting +* fault. May produce false positives due to hash collisions. +* +* [0] Previous PID tracking +* [1] Current PID tracking +* +* Window moves after next_pid_reset has expired approximately +* every VMA_PID_RESET_PERIOD jiffies: +*/ unsigned long access_pids[2 ]; };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 233/538 sched/numa: Rename vma_numab_state::access_pids[] => ::pids_active[], ::next_pid_reset => ::pids_active_reset
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mel Gorman <[email protected]>
[ Upstream commit f3a6c97940fbd25d6c84c2d5642338fc99a9b35b ]
The access_pids[] field name is somewhat ambiguous as no PIDs are accessed. Similarly, it's not clear that next_pid_reset is related to access_pids[]. Rename the fields to more accurately reflect their purpose.
[ mingo: Rename in the comments too. ]
Stable-dep-of: f22cde4371f3 ("sched/numa: Fix the vma scan starving issue")
--- include/linux/mm.h | 4 ++-- include/linux/mm_types.h | 6 +++--- kernel/sched/fair.c | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-)
include/linux/mm.h +2 -2
@@ -1732,8 +1732,8 @@ static inline void vma_set_access_pid_bit(struct vm_area_struct *vma)unsigned int pid_bit; pid_bit =hash_32 (current->pid,ilog2 (BITS_PER_LONG )); -if (vma->numab_state && !test_bit (pid_bit, &vma->numab_state->access_pids[1 ])) { -__set_bit (pid_bit, &vma->numab_state->access_pids[1 ]); +if (vma->numab_state && !test_bit (pid_bit, &vma->numab_state->pids_active[1 ])) { +__set_bit (pid_bit, &vma->numab_state->pids_active[1 ]); } }#else /* !CONFIG_NUMA_BALANCING */
include/linux/mm_types.h +3 -3
@@ -559,10 +559,10 @@ struct vma_numab_state {unsigned long next_scan;/* -* Time in jiffies when access_pids[] is reset to +* Time in jiffies when pids_active[] is reset to * detect phase change behaviour: */ -unsigned long next_pid_reset; +unsigned long pids_active_reset;/* * Approximate tracking of PIDs that trapped a NUMA hinting
@@ -574,7 +574,7 @@ struct vma_numab_state {* Window moves after next_pid_reset has expired approximately * every VMA_PID_RESET_PERIOD jiffies: */ -unsigned long access_pids[2 ]; +unsigned long pids_active[2 ]; };/*
kernel/sched/fair.c +6 -6
@@ -3200,7 +3200,7 @@ static bool vma_is_accessed(struct vm_area_struct *vma)if (READ_ONCE (current->mm->numa_scan_seq) <2 )return true; - pids = vma->numab_state->access_pids[0 ] | vma->numab_state->access_pids[1 ]; + pids = vma->numab_state->pids_active[0 ] | vma->numab_state->pids_active[1 ];return test_bit (hash_32 (current->pid,ilog2 (BITS_PER_LONG )), &pids); }
@@ -3316,7 +3316,7 @@ static void task_numa_work(struct callback_head *work)msecs_to_jiffies (sysctl_numa_balancing_scan_delay);/* Reset happens after 4 times scan delay of scan start */ - vma->numab_state->next_pid_reset = vma->numab_state->next_scan + + vma->numab_state->pids_active_reset = vma->numab_state->next_scan +msecs_to_jiffies (VMA_PID_RESET_PERIOD ); }
@@ -3337,11 +3337,11 @@ static void task_numa_work(struct callback_head *work)* vma for recent access to avoid clearing PID info before access.. */ if (mm->numa_scan_seq && -time_after (jiffies, vma->numab_state->next_pid_reset)) { - vma->numab_state->next_pid_reset = vma->numab_state->next_pid_reset + +time_after (jiffies, vma->numab_state->pids_active_reset)) { + vma->numab_state->pids_active_reset = vma->numab_state->pids_active_reset +msecs_to_jiffies (VMA_PID_RESET_PERIOD ); - vma->numab_state->access_pids[0 ] =READ_ONCE (vma->numab_state->access_pids[1 ]); - vma->numab_state->access_pids[1 ] =0 ; + vma->numab_state->pids_active[0 ] =READ_ONCE (vma->numab_state->pids_active[1 ]); + vma->numab_state->pids_active[1 ] =0 ; } do {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 234/538 sched/numa: Trace decisions related to skipping VMAs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mel Gorman <[email protected]>
[ Upstream commit ed2da8b725b932b1e2b2f4835bb664d47ed03031 ]
NUMA balancing skips or scans VMAs for a variety of reasons. In preparation for completing scans of VMAs regardless of PID access, trace the reasons why a VMA was skipped. In a later patch, the tracing will be used to track if a VMA was forcibly scanned.
Stable-dep-of: f22cde4371f3 ("sched/numa: Fix the vma scan starving issue")
--- include/linux/sched/numa_balancing.h | 8 +++++ include/trace/events/sched.h | 50 ++++++++++++++++++++++++++++ kernel/sched/fair.c | 17 +++++++--- 3 files changed, 71 insertions(+), 4 deletions(-)
include/linux/sched/numa_balancing.h +8 -0
@@ -15,6 +15,14 @@#define TNF_FAULT_LOCAL 0x08#define TNF_MIGRATE_FAIL 0x10 +enum numa_vmaskip_reason { +NUMAB_SKIP_UNSUITABLE , +NUMAB_SKIP_SHARED_RO , +NUMAB_SKIP_INACCESSIBLE , +NUMAB_SKIP_SCAN_DELAY , +NUMAB_SKIP_PID_INACTIVE , +}; +#ifdef CONFIG_NUMA_BALANCING extern void task_numa_fault (int last_node,int node,int pages,int flags);extern pid_t task_numa_group_id (struct task_struct *p);
include/trace/events/sched.h +50 -0
56 lines not on this page · raw message
kernel/sched/fair.c +13 -4
@@ -3285,6 +3285,7 @@ static void task_numa_work(struct callback_head *work) do { if (!vma_migratable(vma) || !vma_policy_mof(vma) || is_vm_hugetlb_page(vma) || (vma->vm_flags & VM_MIXEDMAP)) { + trace_sched_skip_vma_numa(mm, vma, NUMAB_SKIP_UNSUITABLE); continue; }
@@ -3295,15 +3296,19 @@ static void task_numa_work(struct callback_head *work)* as migrating the pages will be of marginal benefit. */ if (!vma->vm_mm || - (vma->vm_file && (vma->vm_flags & (VM_READ |VM_WRITE )) == (VM_READ ))) + (vma->vm_file && (vma->vm_flags & (VM_READ |VM_WRITE )) == (VM_READ ))) { +trace_sched_skip_vma_numa (mm, vma,NUMAB_SKIP_SHARED_RO );continue ; + }/* * Skip inaccessible VMAs to avoid any confusion between * PROT_NONE and NUMA hinting ptes */ -if (!vma_is_accessible (vma)) +if (!vma_is_accessible (vma)) { +trace_sched_skip_vma_numa (mm, vma,NUMAB_SKIP_INACCESSIBLE );continue ; + }/* Initialise new per-VMA NUMAB state. */ if (!vma->numab_state) {
@@ -3325,12 +3330,16 @@ static void task_numa_work(struct callback_head *work)* delay the scan for new VMAs. */ if (mm->numa_scan_seq &&time_before (jiffies, - vma->numab_state->next_scan)) + vma->numab_state->next_scan)) { +trace_sched_skip_vma_numa (mm, vma,NUMAB_SKIP_SCAN_DELAY );continue ; + }/* Do not scan the VMA if task has not accessed */ -if (!vma_is_accessed (vma)) +if (!vma_is_accessed (vma)) { +trace_sched_skip_vma_numa (mm, vma,NUMAB_SKIP_PID_INACTIVE );continue ; + }/* * RESET access PIDs regularly for old VMAs. Resetting after checking
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 235/538 sched/numa: Move up the access pid reset logic
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raghavendra K T <[email protected]>
[ Upstream commit 2e2675db1906ac04809f5399bf1f5e30d56a6f3e ]
Recent NUMA hinting faulting activity is reset approximately every VMA_PID_RESET_PERIOD milliseconds. However, if the current task has not accessed a VMA then the reset check is missed and the reset is potentially deferred forever. Check if the PID activity information should be reset before checking if the current task recently trapped a NUMA hinting fault.
[ [email protected]: Rewrite changelog ]
Stable-dep-of: f22cde4371f3 ("sched/numa: Fix the vma scan starving issue")
--- kernel/sched/fair.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
kernel/sched/fair.c +7 -10
@@ -3335,16 +3335,7 @@ static void task_numa_work(struct callback_head *work)continue ; } -/* Do not scan the VMA if task has not accessed */ -if (!vma_is_accessed (vma)) { -trace_sched_skip_vma_numa (mm, vma,NUMAB_SKIP_PID_INACTIVE ); -continue ; - } - -/* -* RESET access PIDs regularly for old VMAs. Resetting after checking -* vma for recent access to avoid clearing PID info before access.. -*/ +/* RESET access PIDs regularly for old VMAs. */ if (mm->numa_scan_seq &&time_after (jiffies, vma->numab_state->pids_active_reset)) { vma->numab_state->pids_active_reset = vma->numab_state->pids_active_reset +
@@ -3353,6 +3344,12 @@ static void task_numa_work(struct callback_head *work) vma->numab_state->pids_active[1 ] =0 ; } +/* Do not scan the VMA if task has not accessed */ +if (!vma_is_accessed (vma)) { +trace_sched_skip_vma_numa (mm, vma,NUMAB_SKIP_PID_INACTIVE ); +continue ; + } + do { start = max(start, vma->vm_start); end = ALIGN(start + (pages << PAGE_SHIFT), HPAGE_SIZE);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 236/538 sched/numa: Complete scanning of partial VMAs regardless of PID activity
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mel Gorman <[email protected]>
[ Upstream commit b7a5b537c55c088d891ae554103d1b281abef781 ]
NUMA Balancing skips VMAs when the current task has not trapped a NUMA fault within the VMA. If the VMA is skipped then mm->numa_scan_offset advances and a task that is trapping faults within the VMA may never fully update PTEs within the VMA.
Force tasks to update PTEs for partially scanned PTEs. The VMA will be tagged for NUMA hints by some task but this removes some of the benefit of tracking PID activity within a VMA. A follow-on patch will mitigate this problem.
The test cases and machines evaluated did not trigger the corner case so the performance results are neutral with only small changes within the noise from normal test-to-test variance. However, the next patch makes the corner case easier to trigger.
Stable-dep-of: f22cde4371f3 ("sched/numa: Fix the vma scan starving issue")
--- include/linux/sched/numa_balancing.h | 1 + include/trace/events/sched.h | 3 ++- kernel/sched/fair.c | 18 +++++++++++++++--- 3 files changed, 18 insertions(+), 4 deletions(-)
include/linux/sched/numa_balancing.h +1 -0
@@ -21,6 +21,7 @@ enum numa_vmaskip_reason {NUMAB_SKIP_INACCESSIBLE ,NUMAB_SKIP_SCAN_DELAY ,NUMAB_SKIP_PID_INACTIVE , + NUMAB_SKIP_IGNORE_PID, };#ifdef CONFIG_NUMA_BALANCING
include/trace/events/sched.h +2 -1
@@ -670,7 +670,8 @@ DEFINE_EVENT(sched_numa_pair_template, sched_swap_numa, EM( NUMAB_SKIP_SHARED_RO, "shared_ro" ) \ EM( NUMAB_SKIP_INACCESSIBLE, "inaccessible" ) \ EM( NUMAB_SKIP_SCAN_DELAY, "scan_delay" ) \ -EMe (NUMAB_SKIP_PID_INACTIVE ,"pid_inactive" ) + EM( NUMAB_SKIP_PID_INACTIVE, "pid_inactive" ) \ +EMe (NUMAB_SKIP_IGNORE_PID ,"ignore_pid_inactive" ) /* Redefine for export. */#undef EM
kernel/sched/fair.c +15 -3
@@ -3188,7 +3188,7 @@ static void reset_ptenuma_scan(struct task_struct *p) p->mm->numa_scan_offset =0 ; } -static bool vma_is_accessed (struct vm_area_struct *vma) +static bool vma_is_accessed (struct mm_struct *mm,struct vm_area_struct *vma) {unsigned long pids;/*
@@ -3201,7 +3201,19 @@ static bool vma_is_accessed(struct vm_area_struct *vma)return true; pids = vma->numab_state->pids_active[0 ] | vma->numab_state->pids_active[1 ]; -return test_bit (hash_32 (current->pid,ilog2 (BITS_PER_LONG )), &pids); +if (test_bit (hash_32 (current->pid,ilog2 (BITS_PER_LONG )), &pids)) +return true; + +/* +* Complete a scan that has already started regardless of PID access, or +* some VMAs may never be scanned in multi-threaded applications: +*/ +if (mm->numa_scan_offset > vma->vm_start) { +trace_sched_skip_vma_numa (mm, vma,NUMAB_SKIP_IGNORE_PID ); +return true; + } + +return false; }#define VMA_PID_RESET_PERIOD (4 * sysctl_numa_balancing_scan_delay)
@@ -3345,7 +3357,7 @@ static void task_numa_work(struct callback_head *work) }/* Do not scan the VMA if task has not accessed */ -if (!vma_is_accessed (vma)) { +if (!vma_is_accessed (mm, vma)) {trace_sched_skip_vma_numa (mm, vma,NUMAB_SKIP_PID_INACTIVE );continue ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 237/538 sched/numa: Complete scanning of inactive VMAs when there is no alternative
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mel Gorman <[email protected]>
[ Upstream commit f169c62ff7cd1acf8bac8ae17bfeafa307d9e6fa ]
VMAs are skipped if there is no recent fault activity but this represents a chicken-and-egg problem as there may be no fault activity if the PTEs are never updated to trap NUMA hints. There is an indirect reliance on scanning to be forced early in the lifetime of a task but this may fail to detect changes in phase behaviour. Force inactive VMAs to be scanned when all other eligible VMAs have been updated within the same scan sequence.
Test results in general look good with some changes in performance, both negative and positive, depending on whether the additional scanning and faulting was beneficial or not to the workload. The autonuma benchmark workload NUMA01_THREADLOCAL was picked for closer examination. The workload creates two processes with numerous threads and thread-local storage that is zero-filled in a loop. It exercises the corner case where unrelated threads may skip VMAs that are thread-local to another thread and still has some VMAs that inactive while the workload executes.
The VMA skipping activity frequency with and without the patch:
6.6.0-rc2-sched-numabtrace-v1 ============================= 649 reason=scan_delay 9,094 reason=unsuitable 48,915 reason=shared_ro 143,919 reason=inaccessible 193,050 reason=pid_inactive 6.6.0-rc2-sched-numabselective-v1 ============================= 146 reason=seq_completed 622 reason=ignore_pid_inactive 624 reason=scan_delay 6,570 reason=unsuitable 16,101 reason=shared_ro 27,608 reason=inaccessible 41,939 reason=pid_inactive
Note that with the patch applied, the PID activity is ignored (ignore_pid_inactive) to ensure a VMA with some activity is completely scanned. In addition, a small number of VMAs are scanned when no other eligible VMA is available during a single scan window (seq_completed). The number of times a VMA is skipped due to no PID activity from the scanning task (pid_inactive) drops dramatically. It is expected that this will increase the number of PTEs updated for NUMA hinting faults as well as hinting faults but these represent PTEs that would otherwise have been missed. The tradeoff is scan+fault overhead versus improving locality due to migration.
On a 2-socket Cascade Lake test machine, the time to complete the workload is as follows;
6.6.0-rc2 6.6.0-rc2
sched-numabtrace-v1 sched-numabselective-v1
Min elsp-NUMA01_THREADLOCAL 174.22 ( 0.00%) 117.64 ( 32.48%)
Amean elsp-NUMA01_THREADLOCAL 175.68 ( 0.00%) 123.34 * 29.79%*
Stddev elsp-NUMA01_THREADLOCAL 1.20 ( 0.00%) 4.06 (-238.20%)
CoeffVar elsp-NUMA01_THREADLOCAL 0.68 ( 0.00%) 3.29 (-381.70%)
Max elsp-NUMA01_THREADLOCAL 177.18 ( 0.00%) 128.03 ( 27.74%)The time to complete the workload is reduced by almost 30%:
6.6.0-rc2 6.6.0-rc2
sched-numabtrace-v1 sched-numabselective-v1 /
Duration User 91201.80 63506.64
Duration System 2015.53 1819.78
Duration Elapsed 1234.77 868.37
In this specific case, system CPU time was not increased but it's not universally true.
Quoted 1 line
From vmstat, the NUMA scanning and fault activity is as follows;
6.6.0-rc2 6.6.0-rc2
sched-numabtrace-v1 sched-numabselective-v1
Ops NUMA base-page range updates 64272.00 26374386.00
Ops NUMA PTE updates 36624.00 55538.00
Ops NUMA PMD updates 54.00 51404.00
Ops NUMA hint faults 15504.00 75786.00
Ops NUMA hint local faults % 14860.00 56763.00 Ops NUMA hint local percent 95.85 74.90
Ops NUMA pages migrated 1629.00 6469222.00
Both the number of PTE updates and hint faults is dramatically increased. While this is superficially unfortunate, it represents ranges that were simply skipped without the patch. As a result of the scanning and hinting faults, many more pages were also migrated but as the time to completion is reduced, the overhead is offset by the gain.
Stable-dep-of: f22cde4371f3 ("sched/numa: Fix the vma scan starving issue")
--- include/linux/mm_types.h | 6 +++ include/linux/sched/numa_balancing.h | 1 + include/trace/events/sched.h | 3 +- kernel/sched/fair.c | 55 ++++++++++++++++++++++++++-- 4 files changed, 61 insertions(+), 4 deletions(-)
include/linux/mm_types.h +6 -0
@@ -575,6 +575,12 @@ struct vma_numab_state {* every VMA_PID_RESET_PERIOD jiffies: */ unsigned long pids_active[2 ]; + +/* +* MM scan sequence ID when the VMA was last completely scanned. +* A VMA is not eligible for scanning if prev_scan_seq == numa_scan_seq +*/ +int prev_scan_seq; };/*
include/linux/sched/numa_balancing.h +1 -0
@@ -22,6 +22,7 @@ enum numa_vmaskip_reason {NUMAB_SKIP_SCAN_DELAY ,NUMAB_SKIP_PID_INACTIVE ,NUMAB_SKIP_IGNORE_PID , + NUMAB_SKIP_SEQ_COMPLETED, };#ifdef CONFIG_NUMA_BALANCING
include/trace/events/sched.h +2 -1
@@ -671,7 +671,8 @@ DEFINE_EVENT(sched_numa_pair_template, sched_swap_numa, EM( NUMAB_SKIP_INACCESSIBLE, "inaccessible" ) \ EM( NUMAB_SKIP_SCAN_DELAY, "scan_delay" ) \ EM( NUMAB_SKIP_PID_INACTIVE, "pid_inactive" ) \ -EMe (NUMAB_SKIP_IGNORE_PID ,"ignore_pid_inactive" ) + EM( NUMAB_SKIP_IGNORE_PID, "ignore_pid_inactive" ) \ +EMe (NUMAB_SKIP_SEQ_COMPLETED ,"seq_completed" ) /* Redefine for export. */#undef EM
kernel/sched/fair.c +52 -3
93 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 238/538 sched/numa: Fix the vma scan starving issue
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yujie Liu <[email protected]>
[ Upstream commit f22cde4371f3c624e947a35b075c06c771442a43 ]
Problem statement:
Since commit fc137c0ddab2 ("sched/numa: enhance vma scanning logic"), the Numa vma scan overhead has been reduced a lot. Meanwhile, the reducing of the vma scan might create less Numa page fault information. The insufficient information makes it harder for the Numa balancer to make decision. Later, commit b7a5b537c55c08 ("sched/numa: Complete scanning of partial VMAs regardless of PID activity") and commit 84db47ca7146d7 ("sched/numa: Fix mm numa_scan_seq based unconditional scan") are found to bring back part of the performance.
Recently when running SPECcpu omnetpp_r on a 320 CPUs/2 Sockets system, a long duration of remote Numa node read was observed by PMU events: A few cores having ~500MB/s remote memory access for ~20 seconds. It causes high core-to-core variance and performance penalty. After the investigation, it is found that many vmas are skipped due to the active PID check. According to the trace events, in most cases, vma_is_accessed() returns false because the history access info stored in pids_active array has been cleared.
Proposal:
The main idea is to adjust vma_is_accessed() to let it return true easier. Thus compare the diff between mm->numa_scan_seq and vma->numab_state->prev_scan_seq. If the diff has exceeded the threshold, scan the vma.
This patch especially helps the cases where there are small number of threads, like the process-based SPECcpu. Without this patch, if the SPECcpu process access the vma at the beginning, then sleeps for a long time, the pid_active array will be cleared. A a result, if this process is woken up again, it never has a chance to set prot_none anymore. Because only the first 2 times of access is granted for vma scan:
(current->mm->numa_scan_seq) - vma->numab_state->start_scan_seq) < 2 to be worse, no other threads within the task can help set the prot_none. This causes information lost.
Raghavendra helped test current patch and got the positive result on the AMD platform:
autonumabench NUMA01
base patched Amean syst-NUMA01 194.05 ( 0.00%) 165.11 * 14.92%* Amean elsp-NUMA01 324.86 ( 0.00%) 315.58 * 2.86%*
Duration User 380345.36 368252.04
Duration System 1358.89 1156.23 Duration Elapsed 2277.45 2213.25
autonumabench NUMA02
Amean syst-NUMA02 1.12 ( 0.00%) 1.09 * 2.93%* Amean elsp-NUMA02 3.50 ( 0.00%) 3.56 * -1.84%*
Duration User 1513.23 1575.48
Duration System 8.33 8.13
Duration Elapsed 28.59 29.71
kernbench
Amean user-256 22935.42 ( 0.00%) 22535.19 * 1.75%* Amean syst-256 7284.16 ( 0.00%) 7608.72 * -4.46%* Amean elsp-256 159.01 ( 0.00%) 158.17 * 0.53%*
Duration User 68816.41 67615.74 Duration System 21873.94 22848.08
Duration Elapsed 506.66 504.55
Intel 256 CPUs/2 Sockets:
autonuma benchmark also shows improvements:
v6.10-rc5 v6.10-rc5
+patch
Amean syst-NUMA01 245.85 ( 0.00%) 230.84 * 6.11%*
Amean syst-NUMA01_THREADLOCAL 205.27 ( 0.00%) 191.86 * 6.53%*
Amean syst-NUMA02 18.57 ( 0.00%) 18.09 * 2.58%*
Amean syst-NUMA02_SMT 2.63 ( 0.00%) 2.54 * 3.47%*
Amean elsp-NUMA01 517.17 ( 0.00%) 526.34 * -1.77%*
Amean elsp-NUMA01_THREADLOCAL 99.92 ( 0.00%) 100.59 * -0.67%*
Amean elsp-NUMA02 15.81 ( 0.00%) 15.72 * 0.59%*
Amean elsp-NUMA02_SMT 13.23 ( 0.00%) 12.89 * 2.53%* v6.10-rc5 v6.10-rc5
+patch
Duration User 1064010.16 1075416.23
Duration System 3307.64 3104.66
Duration Elapsed 4537.54 4604.73The SPECcpu remote node access issue disappears with the patch applied.
--- kernel/sched/fair.c | 9 +++++++++ 1 file changed, 9 insertions(+)
kernel/sched/fair.c +9 -0
@@ -3213,6 +3213,15 @@ static bool vma_is_accessed(struct mm_struct *mm, struct vm_area_struct *vma)return true; } +/* +* This vma has not been accessed for a while, and if the number +* the threads in the same process is low, which means no other +* threads can help scan this vma, force a vma scan. +*/ +if (READ_ONCE (mm->numa_scan_seq) > + (vma->numab_state->prev_scan_seq +get_nr_threads (current))) +return true; +return false; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 239/538 nilfs2: fix potential null-ptr-deref in nilfs_btree_insert()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
[ Upstream commit 9403001ad65ae4f4c5de368bdda3a0636b51d51a ]
Patch series "nilfs2: fix potential issues with empty b-tree nodes".
This series addresses three potential issues with empty b-tree nodes that can occur with corrupted filesystem images, including one recently discovered by syzbot.
This patch (of 3):
If a b-tree is broken on the device, and the b-tree height is greater than 2 (the level of the root node is greater than 1) even if the number of child nodes of the b-tree root is 0, a NULL pointer dereference occurs in nilfs_btree_prepare_insert(), which is called from nilfs_btree_insert().
This is because, when the number of child nodes of the b-tree root is 0, nilfs_btree_do_lookup() does not set the block buffer head in any of path[x].bp_bh, leaving it as the initial value of NULL, but if the level of the b-tree root node is greater than 1, nilfs_btree_get_nonroot_node(), which accesses the buffer memory of path[x].bp_bh, is called.
Fix this issue by adding a check to nilfs_btree_root_broken(), which performs sanity checks when reading the root node from the device, to detect this inconsistency.
Thanks to Lizhi Xu for trying to solve the bug and clarifying the cause early on.
--- fs/nilfs2/btree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/nilfs2/btree.c +2 -1
@@ -381,7 +381,8 @@ static int nilfs_btree_root_broken(const struct nilfs_btree_node *node,if (unlikely (level <NILFS_BTREE_LEVEL_NODE_MIN || level >=NILFS_BTREE_LEVEL_MAX || nchildren <0 || - nchildren >NILFS_BTREE_ROOT_NCHILDREN_MAX )) { + nchildren >NILFS_BTREE_ROOT_NCHILDREN_MAX || + (nchildren ==0 && level >NILFS_BTREE_LEVEL_NODE_MIN ))) {nilfs_crit (inode->i_sb,"bad btree root (ino=%lu): level = %d, flags = 0x%x, nchildren = %d" , inode->i_ino, level, flags, nchildren);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 240/538 nilfs2: determine empty node blocks as corrupted
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
[ Upstream commit 111b812d3662f3a1b831d19208f83aa711583fe6 ]
Due to the nature of b-trees, nilfs2 itself and admin tools such as mkfs.nilfs2 will never create an intermediate b-tree node block with 0 child nodes, nor will they delete (key, pointer)-entries that would result in such a state. However, it is possible that a b-tree node block is corrupted on the backing device and is read with 0 child nodes.
Because operation is not guaranteed if the number of child nodes is 0 for intermediate node blocks other than the root node, modify nilfs_btree_node_broken(), which performs sanity checks when reading a b-tree node block, so that such cases will be judged as metadata corruption.
--- fs/nilfs2/btree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nilfs2/btree.c +1 -1
@@ -350,7 +350,7 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,if (unlikely (level <NILFS_BTREE_LEVEL_NODE_MIN || level >=NILFS_BTREE_LEVEL_MAX || (flags &NILFS_BTREE_NODE_ROOT ) || - nchildren <0 || + nchildren <=0 || nchildren >NILFS_BTREE_NODE_NCHILDREN_MAX (size))) { nilfs_crit(inode->i_sb, "bad btree node (ino=%lu, blocknr=%llu): level = %d, flags = 0x%x, nchildren = %d",
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 241/538 nilfs2: fix potential oob read in nilfs_btree_check_delete()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
[ Upstream commit f9c96351aa6718b42a9f42eaf7adce0356bdb5e8 ]
The function nilfs_btree_check_delete(), which checks whether degeneration to direct mapping occurs before deleting a b-tree entry, causes memory access outside the block buffer when retrieving the maximum key if the root node has no entries.
This does not usually happen because b-tree mappings with 0 child nodes are never created by mkfs.nilfs2 or nilfs2 itself. However, it can happen if the b-tree root node read from a device is configured that way, so fix this potential issue by adding a check for that case.
--- fs/nilfs2/btree.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
fs/nilfs2/btree.c +5 -2
@@ -1659,13 +1659,16 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key)int nchildren, ret; root =nilfs_btree_get_root (btree); + nchildren =nilfs_btree_node_get_nchildren (root); +if (unlikely (nchildren ==0 )) +return 0 ; +switch (nilfs_btree_height (btree)) {case 2 : bh =NULL ; node = root;break ;case 3 : - nchildren =nilfs_btree_node_get_nchildren (root);if (nchildren >1 )return 0 ; ptr = nilfs_btree_node_get_ptr(root, nchildren - 1,
@@ -1674,12 +1677,12 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key)if (ret <0 )return ret; node = (struct nilfs_btree_node *)bh->b_data; + nchildren =nilfs_btree_node_get_nchildren (node);break ;default :return 0 ; } - nchildren =nilfs_btree_node_get_nchildren (node); maxkey =nilfs_btree_node_get_key (node, nchildren -1 ); nextmaxkey = (nchildren >1 ) ?nilfs_btree_node_get_key (node, nchildren -2 ) :0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 242/538 bpf: Fix bpf_strtol and bpf_strtoul helpers for 32bit
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit cfe69c50b05510b24e26ccb427c7cc70beafd6c1 ]
The bpf_strtol() and bpf_strtoul() helpers are currently broken on 32bit:
The argument type ARG_PTR_TO_LONG is BPF-side "long", not kernel-side "long" and therefore always considered fixed 64bit no matter if 64 or 32bit underlying architecture.
This contract breaks in case of the two mentioned helpers since their BPF_CALL definition for the helpers was added with {unsigned,}long *res. Meaning, the transition from BPF-side "long" (BPF program) to kernel-side "long" (BPF helper) breaks here.
Both helpers call __bpf_strtoll() with "long long" correctly, but later assigning the result into 32-bit "*(long *)" on 32bit architectures. From a BPF program point of view, this means upper bits will be seen as uninitialised.
Therefore, fix both BPF_CALL signatures to {s,u}64 types to fix this situation.
Now, changing also uapi/bpf.h helper documentation which generates bpf_helper_defs.h for BPF programs is tricky: Changing signatures there to __{s,u}64 would trigger compiler warnings (incompatible pointer types passing 'long *' to parameter of type '__s64 *' (aka 'long long *')) for existing BPF programs.
Leaving the signatures as-is would be fine as from BPF program point of view it is still BPF-side "long" and thus equivalent to __{s,u}64 on 64 or 32bit underlying architectures.
Note that bpf_strtol() and bpf_strtoul() are the only helpers with this issue.
--- kernel/bpf/helpers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/bpf/helpers.c +2 -2
@@ -516,7 +516,7 @@ static int __bpf_strtoll(const char *buf, size_t buf_len, u64 flags, } BPF_CALL_4(bpf_strtol, const char *, buf, size_t, buf_len, u64, flags, - long *, res) + s64 *, res) {long long _res;int err;
@@ -541,7 +541,7 @@ const struct bpf_func_proto bpf_strtol_proto = { }; BPF_CALL_4(bpf_strtoul, const char *, buf, size_t, buf_len, u64, flags, - unsigned long *, res) + u64 *, res) {unsigned long long _res;bool is_negative;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 243/538 bpf: Fix helper writes to read-only maps
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 32556ce93bc45c730829083cb60f95a2728ea48b ]
Lonial found an issue that despite user- and BPF-side frozen BPF map (like in case of .rodata), it was still possible to write into it from a BPF program side through specific helpers having ARG_PTR_TO_{LONG,INT} as arguments.
In check_func_arg() when the argument is as mentioned, the meta->raw_mode is never set. Later, check_helper_mem_access(), under the case of PTR_TO_MAP_VALUE as register base type, it assumes BPF_READ for the subsequent call to check_map_access_type() and given the BPF map is read-only it succeeds.
The helpers really need to be annotated as ARG_PTR_TO_{LONG,INT} | MEM_UNINIT when results are written into them as opposed to read out of them. The latter indicates that it's okay to pass a pointer to uninitialized memory as the memory is written to anyway.
However, ARG_PTR_TO_{LONG,INT} is a special case of ARG_PTR_TO_FIXED_SIZE_MEM just with additional alignment requirement. So it is better to just get rid of the ARG_PTR_TO_{LONG,INT} special cases altogether and reuse the fixed size memory types. For this, add MEM_ALIGNED to additionally ensure alignment given these helpers write directly into the args via *<ptr> = val. The .arg*_size has been initialized reflecting the actual sizeof(*<ptr>).
MEM_ALIGNED can only be used in combination with MEM_FIXED_SIZE annotated argument types, since in !MEM_FIXED_SIZE cases the verifier does not know the buffer size a priori and therefore cannot blindly write *<ptr> = val.
--- include/linux/bpf.h | 7 +++++-- kernel/bpf/helpers.c | 6 ++++-- kernel/bpf/syscall.c | 3 ++- kernel/bpf/verifier.c | 41 +++++----------------------------------- kernel/trace/bpf_trace.c | 6 ++++-- net/core/filter.c | 6 ++++-- 6 files changed, 24 insertions(+), 45 deletions(-)
include/linux/bpf.h +5 -2
@@ -675,6 +675,11 @@ enum bpf_type_flag {/* DYNPTR points to xdp_buff */ DYNPTR_TYPE_XDP =BIT (16 +BPF_BASE_TYPE_BITS ), +/* Memory must be aligned on some architectures, used in combination with +* MEM_FIXED_SIZE. +*/ +MEM_ALIGNED =BIT (17 +BPF_BASE_TYPE_BITS ), + __BPF_TYPE_FLAG_MAX, __BPF_TYPE_LAST_FLAG = __BPF_TYPE_FLAG_MAX - 1, };
@@ -711,8 +716,6 @@ enum bpf_arg_type {ARG_ANYTHING ,/* any (initialized) argument is ok */ ARG_PTR_TO_SPIN_LOCK ,/* pointer to bpf_spin_lock */ ARG_PTR_TO_SOCK_COMMON ,/* pointer to sock_common */ -ARG_PTR_TO_INT ,/* pointer to int */ -ARG_PTR_TO_LONG ,/* pointer to long */ ARG_PTR_TO_SOCKET ,/* pointer to bpf_sock (fullsock) */ ARG_PTR_TO_BTF_ID ,/* pointer to in-kernel struct */ ARG_PTR_TO_RINGBUF_MEM, /* pointer to dynamically reserved ringbuf memory */
kernel/bpf/helpers.c +4 -2
@@ -537,7 +537,8 @@ const struct bpf_func_proto bpf_strtol_proto = { .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_LONG, + .arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, + .arg4_size = sizeof(s64), }; BPF_CALL_4(bpf_strtoul, const char *, buf, size_t, buf_len, u64, flags,
@@ -565,7 +566,8 @@ const struct bpf_func_proto bpf_strtoul_proto = { .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_LONG, + .arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, + .arg4_size = sizeof(u64), }; BPF_CALL_3(bpf_strncmp, const char *, s1, u32, s1_sz, const char *, s2)
kernel/bpf/syscall.c +2 -1
@@ -5667,7 +5667,8 @@ static const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = { .arg1_type = ARG_PTR_TO_MEM, .arg2_type = ARG_CONST_SIZE_OR_ZERO, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_LONG, + .arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, + .arg4_size = sizeof(u64), }; static const struct bpf_func_proto *
kernel/bpf/verifier.c +5 -36
71 lines not on this page · raw message
kernel/trace/bpf_trace.c +4 -2
@@ -1220,7 +1220,8 @@ static const struct bpf_func_proto bpf_get_func_arg_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_LONG, + .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, + .arg3_size = sizeof(u64), }; BPF_CALL_2(get_func_ret, void *, ctx, u64 *, value)
@@ -1236,7 +1237,8 @@ static const struct bpf_func_proto bpf_get_func_ret_proto = { .func = get_func_ret, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_LONG, + .arg2_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, + .arg2_size = sizeof(u64), }; BPF_CALL_1(get_func_arg_cnt, void *, ctx)
net/core/filter.c +4 -2
@@ -6306,7 +6306,8 @@ static const struct bpf_func_proto bpf_skb_check_mtu_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_INT, + .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, + .arg3_size = sizeof(u32), .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, };
@@ -6317,7 +6318,8 @@ static const struct bpf_func_proto bpf_xdp_check_mtu_proto = { .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_INT, + .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, + .arg3_size = sizeof(u32), .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 244/538 bpf: Improve check_raw_mode_ok test for MEM_UNINIT-tagged types
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 18752d73c1898fd001569195ba4b0b8c43255f4a ]
When checking malformed helper function signatures, also take other argument types into account aside from just ARG_PTR_TO_UNINIT_MEM.
This concerns (formerly) ARG_PTR_TO_{INT,LONG} given uninitialized memory can be passed there, too.
The func proto sanity check goes back to commit 435faee1aae9 ("bpf, verifier:
add ARG_PTR_TO_RAW_STACK type"), and its purpose was to detect wrong func protos which had more than just one MEM_UNINIT-tagged type as arguments.
The reason more than one is currently not supported is as we mark stack slots with STACK_MISC in check_helper_call() in case of raw mode based on meta.access_size to allow uninitialized stack memory to be passed to helpers when they just write into the buffer.
Probing for base type as well as MEM_UNINIT tagging ensures that other types do not get missed (as it used to be the case for ARG_PTR_TO_{INT,LONG}).
--- kernel/bpf/verifier.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
kernel/bpf/verifier.c +11 -5
@@ -7987,6 +7987,12 @@ static bool arg_type_is_mem_size(enum bpf_arg_type type) type ==ARG_CONST_SIZE_OR_ZERO ; } +static bool arg_type_is_raw_mem (enum bpf_arg_type type) +{ +return base_type (type) ==ARG_PTR_TO_MEM && + type &MEM_UNINIT ; +} +static bool arg_type_is_release (enum bpf_arg_type type) {return type &OBJ_RELEASE ;
@@ -9009,15 +9015,15 @@ static bool check_raw_mode_ok(const struct bpf_func_proto *fn) {int count =0 ; -if (fn->arg1_type ==ARG_PTR_TO_UNINIT_MEM ) +if (arg_type_is_raw_mem (fn->arg1_type)) count++; -if (fn->arg2_type ==ARG_PTR_TO_UNINIT_MEM ) +if (arg_type_is_raw_mem (fn->arg2_type)) count++; -if (fn->arg3_type ==ARG_PTR_TO_UNINIT_MEM ) +if (arg_type_is_raw_mem (fn->arg3_type)) count++; -if (fn->arg4_type ==ARG_PTR_TO_UNINIT_MEM ) +if (arg_type_is_raw_mem (fn->arg4_type)) count++; -if (fn->arg5_type ==ARG_PTR_TO_UNINIT_MEM ) +if (arg_type_is_raw_mem (fn->arg5_type)) count++;/* We only support one arg being in raw mode at the moment,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 245/538 bpf: Zero former ARG_PTR_TO_{LONG,INT} args in case of error
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 4b3786a6c5397dc220b1483d8e2f4867743e966f ]
For all non-tracing helpers which formerly had ARG_PTR_TO_{LONG,INT} as input arguments, zero the value for the case of an error as otherwise it could leak memory. For tracing, it is not needed given CAP_PERFMON can already read all kernel memory anyway hence bpf_get_func_arg() and bpf_get_func_ret() is skipped in here.
Also, the MTU helpers mtu_len pointer value is being written but also read. Technically, the MEM_UNINIT should not be there in order to always force init. Removing MEM_UNINIT needs more verifier rework though: MEM_UNINIT right now implies two things actually: i) write into memory, ii) memory does not have to be initialized. If we lift MEM_UNINIT, it then becomes: i) read into memory, ii) memory must be initialized. This means that for bpf_*_check_mtu() we're readding the issue we're trying to fix, that is, it would then be able to write back into things like .rodata BPF maps. Follow-up work will rework the MEM_UNINIT semantics such that the intent can be better expressed. For now just clear the *mtu_len on error path which can be lifted later again.
--- kernel/bpf/helpers.c | 2 ++ kernel/bpf/syscall.c | 1 + net/core/filter.c | 44 +++++++++++++++++++++++--------------------- 3 files changed, 26 insertions(+), 21 deletions(-)
kernel/bpf/helpers.c +2 -0
@@ -521,6 +521,7 @@ BPF_CALL_4(bpf_strtol, const char *, buf, size_t, buf_len, u64, flags,long long _res;int err; + *res =0 ; err =__bpf_strtoll (buf, buf_len, flags, &_res);if (err <0 )return err;
@@ -548,6 +549,7 @@ BPF_CALL_4(bpf_strtoul, const char *, buf, size_t, buf_len, u64, flags,bool is_negative;int err; + *res =0 ; err =__bpf_strtoull (buf, buf_len, flags, &_res, &is_negative);if (err <0 )return err;
kernel/bpf/syscall.c +1 -0
@@ -5647,6 +5647,7 @@ static const struct bpf_func_proto bpf_sys_close_proto = { BPF_CALL_4(bpf_kallsyms_lookup_name, const char *, name, int, name_sz, int, flags, u64 *, res) { + *res =0 ;if (flags)return -EINVAL ;
net/core/filter.c +23 -21
87 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 246/538 perf mem: Free the allocated sort string, fixing a leak
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namhyung Kim <[email protected]>
[ Upstream commit 3da209bb1177462b6fe8e3021a5527a5a49a9336 ]
The get_sort_order() returns either a new string (from strdup) or NULL but it never gets freed.
--- tools/perf/builtin-mem.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/builtin-mem.c +1 -0
@@ -372,6 +372,7 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem) rep_argv[i] = argv[j]; ret =cmd_report (i, rep_argv); +free (new_sort_order);free (rep_argv);return ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 247/538 perf callchain: Fix stitch LBR memory leaks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Rogers <[email protected]>
[ Upstream commit 599c19397b17d197fc1184bbc950f163a292efc9 ]
The 'struct callchain_cursor_node' has a 'struct map_symbol' whose maps and map members are reference counted. Ensure these values use a _get routine to increment the reference counts and use map_symbol__exit() to release the reference counts.
Do similar for 'struct thread's prev_lbr_cursor, but save the size of the prev_lbr_cursor array so that it may be iterated.
Ensure that when stitch_nodes are placed on the free list the map_symbols are exited.
Fix resolve_lbr_callchain_sample() by replacing list_replace_init() to list_splice_init(), so the whole list is moved and nodes aren't leaked.
A reproduction of the memory leaks is possible with a leak sanitizer build in the perf report command of:
``` $ perf record -e cycles --call-graph lbr perf test -w thloop $ perf report --stitch-lbr ```
--- tools/perf/util/machine.c | 17 +++++++++++++++-- tools/perf/util/thread.c | 4 ++++ tools/perf/util/thread.h | 1 + 3 files changed, 20 insertions(+), 2 deletions(-)
tools/perf/util/machine.c +15 -2
@@ -2536,8 +2536,12 @@ static void save_lbr_cursor_node(struct thread *thread, cursor->curr = cursor->first; else cursor->curr = cursor->curr->next; + +map_symbol__exit (&lbr_stitch->prev_lbr_cursor[idx].ms);memcpy (&lbr_stitch->prev_lbr_cursor[idx], cursor->curr,sizeof (struct callchain_cursor_node )); + lbr_stitch->prev_lbr_cursor[idx].ms.maps =maps__get (cursor->curr->ms.maps); + lbr_stitch->prev_lbr_cursor[idx].ms.map =map__get (cursor->curr->ms.map); lbr_stitch->prev_lbr_cursor[idx].valid = true; cursor->pos++;
@@ -2748,6 +2752,9 @@ static bool has_stitched_lbr(struct thread *thread,memcpy (&stitch_node->cursor, &lbr_stitch->prev_lbr_cursor[i],sizeof (struct callchain_cursor_node )); + stitch_node->cursor.ms.maps =maps__get (lbr_stitch->prev_lbr_cursor[i].ms.maps); + stitch_node->cursor.ms.map =map__get (lbr_stitch->prev_lbr_cursor[i].ms.map); +if (callee)list_add (&stitch_node->node, &lbr_stitch->lists);else
@@ -2771,6 +2778,8 @@ static bool alloc_lbr_stitch(struct thread *thread, unsigned int max_lbr)if (!thread__lbr_stitch (thread)->prev_lbr_cursor) goto free_lbr_stitch; +thread__lbr_stitch (thread)->prev_lbr_cursor_size = max_lbr +1 ; +INIT_LIST_HEAD (&thread__lbr_stitch (thread)->lists);INIT_LIST_HEAD (&thread__lbr_stitch (thread)->free_lists);
@@ -2826,8 +2835,12 @@ static int resolve_lbr_callchain_sample(struct thread *thread, max_lbr, callee);if (!stitched_lbr && !list_empty (&lbr_stitch->lists)) { -list_replace_init (&lbr_stitch->lists, - &lbr_stitch->free_lists); +struct stitch_list *stitch_node; + +list_for_each_entry (stitch_node, &lbr_stitch->lists, node) +map_symbol__exit (&stitch_node->cursor.ms); + +list_splice_init (&lbr_stitch->lists, &lbr_stitch->free_lists); }memcpy (&lbr_stitch->prev_sample, sample,sizeof (*sample)); }
tools/perf/util/thread.c +4 -0
@@ -478,6 +478,7 @@ void thread__free_stitch_list(struct thread *thread)return ;list_for_each_entry_safe (pos, tmp, &lbr_stitch->lists, node) { +map_symbol__exit (&pos->cursor.ms);list_del_init (&pos->node);free (pos); }
@@ -487,6 +488,9 @@ void thread__free_stitch_list(struct thread *thread)free (pos); } +for (unsigned int i =0 ; i < lbr_stitch->prev_lbr_cursor_size; i++) +map_symbol__exit (&lbr_stitch->prev_lbr_cursor[i].ms); +zfree (&lbr_stitch->prev_lbr_cursor);free (thread__lbr_stitch (thread));thread__set_lbr_stitch (thread,NULL );
tools/perf/util/thread.h +1 -0
@@ -28,6 +28,7 @@ struct lbr_stitch {struct list_head free_lists;struct perf_sample prev_sample;struct callchain_cursor_node *prev_lbr_cursor; +unsigned int prev_lbr_cursor_size; };struct thread_rb_node {
Signature · 1 line
2.43.0
Re: [PATCH 6.6 247/538] perf callchain: Fix stitch LBR memory leaks
Quoted 16 lines · Greg Kroah-Hartman
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Rogers <[email protected]>
[ Upstream commit
599c19397b17d197fc1184bbc950f163a292efc9]The 'struct
callchain_cursor_node' has a 'structmap_symbol' whose maps and map members are reference counted. Ensure these values use a_getroutine to increment the reference counts and usemap_symbol__exit()to release the reference counts.Do similar for 'struct thread's
prev_lbr_cursor, but save the size of theprev_lbr_cursorarray so that it may be iterated.
Quoted 8 lines
Ensure that when
stitch_nodesare placed on the free list themap_symbolsare exited.Fix
resolve_lbr_callchain_sample()by replacinglist_replace_init()tolist_splice_init(), so the whole list is moved and nodes aren't leaked.A reproduction of the memory leaks is possible with a leak sanitizer build in the perf report command of:
IMHO this doesn't meet stable criteria. It's a theoretical problem that only causes noise in leak checker outputs, but doesn't actually affect any real user. The memory is always freed on exit anyways.
-Andi
Greg Kroah-Hartman
maintainerRe: [PATCH 6.6 247/538] perf callchain: Fix stitch LBR memory leaks
Quoted 23 lines · Andi Kleen
Quoted 22 lines · Greg Kroah-Hartman
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Rogers <[email protected]>
[ Upstream commit
599c19397b17d197fc1184bbc950f163a292efc9]The 'struct
callchain_cursor_node' has a 'structmap_symbol' whose maps and map members are reference counted. Ensure these values use a_getroutine to increment the reference counts and usemap_symbol__exit()to release the reference counts.Do similar for 'struct thread's
prev_lbr_cursor, but save the size of theprev_lbr_cursorarray so that it may be iterated.Ensure that when
stitch_nodesare placed on the free list themap_symbolsare exited.Fix
resolve_lbr_callchain_sample()by replacinglist_replace_init()tolist_splice_init(), so the whole list is moved and nodes aren't leaked.
Quoted 6 lines
Quoted 2 lines
A reproduction of the memory leaks is possible with a leak sanitizer build in the perf report command of:
IMHO this doesn't meet stable criteria. It's a theoretical problem that only causes noise in leak checker outputs, but doesn't actually affect any real user. The memory is always freed on exit anyways.
Ok, now dropped from all queues, thanks for the review.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 248/538 perf inject: Fix leader sampling inserting additional samples
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Rogers <[email protected]>
[ Upstream commit 79bcd34e0f3da39fda841406ccc957405e724852 ]
The processing of leader samples would turn an individual sample with a group of read values into multiple samples. 'perf inject' would pass through the additional samples increasing the output data file size:
$ perf record -g -e "{instructions,cycles}:S" -o perf.orig.data true
$ perf script -D -i perf.orig.data | sed -e 's/perf.orig.data/perf.data/g' > orig.txt
$ perf inject -i perf.orig.data -o perf.new.data
$ perf script -D -i perf.new.data | sed -e 's/perf.new.data/perf.data/g' > new.txt
$ diff -u orig.txt new.txt
--- orig.txt 2024-07-29 14:29:40.606576769 -0700
+++ new.txt 2024-07-29 14:30:04.142737434 -0700
...
[email protected] [0x30]: event: 3
[email protected] [0xd0]: event: 9
+.
+. ... raw event: size 208 bytes
+. 0000: 09 00 00 00 01 00 d0 00 fc 72 01 86 ff ff ff ff .........r......
+. 0010: 74 7d 2c 00 74 7d 2c 00 fb c3 79 f9 ba d5 05 00 t},.t},...y.....
+. 0020: e6 cb 1a 00 00 00 00 00 01 00 00 00 00 00 00 00 ................
+. 0030: 02 00 00 00 00 00 00 00 76 01 00 00 00 00 00 00 ........v.......
+. 0040: e6 cb 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+. 0050: 62 18 00 00 00 00 00 00 f6 cb 1a 00 00 00 00 00 b...............
+. 0060: 00 00 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 ................
+. 0070: 80 ff ff ff ff ff ff ff fc 72 01 86 ff ff ff ff .........r......
+. 0080: f3 0e 6e 85 ff ff ff ff 0c cb 7f 85 ff ff ff ff ..n.............
+. 0090: bc f2 87 85 ff ff ff ff 44 af 7f 85 ff ff ff ff ........D.......
+. 00a0: bd be 7f 85 ff ff ff ff 26 d0 7f 85 ff ff ff ff ........&.......
+. 00b0: 6d a4 ff 85 ff ff ff ff ea 00 20 86 ff ff ff ff m......... .....
+. 00c0: 00 fe ff ff ff ff ff ff 57 14 4f 43 fc 7e 00 00 ........W.OC.~..
+
+1642373909693435 0xc550 [0xd0]: PERF_RECORD_SAMPLE(IP, 0x1): 2915700/2915700: 0xffffffff860172fc period: 1 addr: 0
+... FP chain: nr:12
+..... 0: ffffffffffffff80
+..... 1: ffffffff860172fc
+..... 2: ffffffff856e0ef3
+..... 3: ffffffff857fcb0c
+..... 4: ffffffff8587f2bc
+..... 5: ffffffff857faf44
+..... 6: ffffffff857fbebd
+..... 7: ffffffff857fd026
+..... 8: ffffffff85ffa46d
+..... 9: ffffffff862000ea
+..... 10: fffffffffffffe00
+..... 11: 00007efc434f1457
+... sample_read:
+.... group nr 2
+..... id 00000000001acbe6, value 0000000000000176, lost 0
+..... id 00000000001acbf6, value 0000000000001862, lost 0
+
[email protected] [0x30]: event: 3
...This behavior is incorrect as in the case above 'perf inject' should have done nothing. Fix this behavior by disabling separating samples for a tool that requests it. Only request this for perf inject so as to not affect other perf tools. With the patch and the test above there are no differences between the orig.txt and new.txt.
--- tools/perf/builtin-inject.c | 1 + tools/perf/util/session.c | 3 +++ tools/perf/util/tool.h | 1 + 3 files changed, 5 insertions(+)
tools/perf/builtin-inject.c +1 -0
@@ -2200,6 +2200,7 @@ int cmd_inject(int argc, const char **argv) .finished_init = perf_event__repipe_op2_synth, .compressed = perf_event__repipe_op4_synth, .auxtrace = perf_event__repipe_auxtrace, + .dont_split_sample_group = true, }, .input_name = "-", .samples = LIST_HEAD_INIT(inject.samples),
tools/perf/util/session.c +3 -0
@@ -1500,6 +1500,9 @@ static int deliver_sample_group(struct evlist *evlist,int ret = -EINVAL ;struct sample_read_value *v = sample->read.group.values; +if (tool->dont_split_sample_group) +return deliver_sample_value (evlist, tool, event, sample, v, machine); +sample_read_group__for_each (v, sample->read.group.nr, read_format) { ret =deliver_sample_value (evlist, tool, event, sample, v, machine);
tools/perf/util/tool.h +1 -0
@@ -85,6 +85,7 @@ struct perf_tool {bool namespace_events;bool cgroup_events;bool no_warn; +bool dont_split_sample_group;enum show_feature_header show_feat_hdr; };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 249/538 perf annotate: Split branch stack cycles info from struct annotation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namhyung Kim <[email protected]>
[ Upstream commit b7f87e32590bf48eca84f729d3422be7b8dc22d3 ]
The cycles info is only meaningful when sample has branch stacks. To save the memory for normal cases, move those fields to a new 'struct annotated_branch' and dynamically allocate it when needed. Also move cycles_hist from annotated_source as it's related here.
Stable-dep-of: 3ef44458071a ("perf report: Fix --total-cycles --stdio output error")
--- tools/perf/util/annotate.c | 99 ++++++++++++++++++++---------------- tools/perf/util/annotate.h | 17 ++++--- tools/perf/util/block-info.c | 4 +- tools/perf/util/sort.c | 14 ++--- 4 files changed, 73 insertions(+), 61 deletions(-)
tools/perf/util/annotate.c +54 -45
@@ -813,7 +813,6 @@ static __maybe_unused void annotated_source__delete(struct annotated_source *srcif (src ==NULL )return ;zfree (&src->histograms); -zfree (&src->cycles_hist);free (src); }
@@ -848,18 +847,6 @@ static int annotated_source__alloc_histograms(struct annotated_source *src,return src->histograms ?0 :-1 ; } -/* The cycles histogram is lazily allocated. */ -static int symbol__alloc_hist_cycles (struct symbol *sym) -{ -struct annotation *notes =symbol__annotation (sym); -const size_t size =symbol__size (sym); - - notes->src->cycles_hist =calloc (size,sizeof (struct cyc_hist )); -if (notes->src->cycles_hist ==NULL ) -return -1 ; -return 0 ; -} -void symbol__annotate_zero_histograms (struct symbol *sym) {struct annotation *notes =symbol__annotation (sym);
@@ -868,9 +855,10 @@ void symbol__annotate_zero_histograms(struct symbol *sym)if (notes->src !=NULL ) {memset (notes->src->histograms,0 , notes->src->nr_histograms * notes->src->sizeof_sym_hist); -if (notes->src->cycles_hist) -memset (notes->src->cycles_hist,0 , -symbol__size (sym) *sizeof (struct cyc_hist )); + } +if (notes->branch && notes->branch->cycles_hist) { +memset (notes->branch->cycles_hist,0 , +symbol__size (sym) *sizeof (struct cyc_hist )); }annotation__unlock (notes); }
@@ -961,23 +949,33 @@ static int __symbol__inc_addr_samples(struct map_symbol *ms,return 0 ; } +static struct annotated_branch *annotation__get_branch (struct annotation *notes) +{ +if (notes ==NULL ) +return NULL ; + +if (notes->branch ==NULL ) + notes->branch =zalloc (sizeof (*notes->branch)); + +return notes->branch; +} +static struct cyc_hist *symbol__cycles_hist (struct symbol *sym) {struct annotation *notes =symbol__annotation (sym); +struct annotated_branch *branch; -if (notes->src ==NULL ) { - notes->src =annotated_source__new (); -if (notes->src ==NULL ) -return NULL ; - goto alloc_cycles_hist; - } + branch =annotation__get_branch (notes); +if (branch ==NULL ) +return NULL ; + +if (branch->cycles_hist ==NULL ) { +const size_t size =symbol__size (sym); -if (!notes->src->cycles_hist) { -alloc_cycles_hist: -symbol__alloc_hist_cycles (sym); + branch->cycles_hist =calloc (size,sizeof (struct cyc_hist )); } -return notes->src->cycles_hist; +return branch->cycles_hist; }struct annotated_source *symbol__hists (struct symbol *sym,int nr_hists)
@@ -1086,6 +1084,14 @@ static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64return n_insn; } +static void annotated_branch__delete (struct annotated_branch *branch) +{ +if (branch) { +zfree (&branch->cycles_hist); +free (branch); + } +} +static void annotation__count_and_fill (struct annotation *notes,u64 start,u64 end,struct cyc_hist *ch) {unsigned n_insn;
@@ -1094,6 +1100,7 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 n_insn =annotation__count_insn (notes, start, end);if (n_insn && ch->num && ch->cycles) { +struct annotated_branch *branch;float ipc = n_insn / ((double )ch->cycles / (double )ch->num);/* Hide data when there are too many overlaps. */
@@ -1109,10 +1116,11 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 } } -if (cover_insn) { - notes->hit_cycles += ch->cycles; - notes->hit_insn += n_insn * ch->num; - notes->cover_insn += cover_insn; + branch =annotation__get_branch (notes); +if (cover_insn && branch) { + branch->hit_cycles += ch->cycles; + branch->hit_insn += n_insn * ch->num; + branch->cover_insn += cover_insn; } } }
@@ -1122,19 +1130,19 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size)int err =0 ;s64 offset; -if (!notes->src || !notes->src->cycles_hist) +if (!notes->branch || !notes->branch->cycles_hist)return 0 ; - notes->total_insn =annotation__count_insn (notes,0 , size -1 ); - notes->hit_cycles =0 ; - notes->hit_insn =0 ; - notes->cover_insn =0 ; + notes->branch->total_insn =annotation__count_insn (notes,0 , size -1 ); + notes->branch->hit_cycles =0 ; + notes->branch->hit_insn =0 ; + notes->branch->cover_insn =0 ;annotation__lock (notes);for (offset = size -1 ; offset >=0 ; --offset) {struct cyc_hist *ch; - ch = ¬es->src->cycles_hist[offset]; + ch = ¬es->branch->cycles_hist[offset];if (ch && ch->cycles) {struct annotation_line *al;
@@ -1153,13 +1161,12 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size) al->cycles->max = ch->cycles_max; al->cycles->min = ch->cycles_min; } - notes->have_cycles = true; } }if (err) {while (++offset < (s64 )size) { -struct cyc_hist *ch = ¬es->src->cycles_hist[offset]; +struct cyc_hist *ch = ¬es->branch->cycles_hist[offset];if (ch && ch->cycles) {struct annotation_line *al = notes->offsets[offset];
@@ -1325,6 +1332,7 @@ int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool rvoid annotation__exit (struct annotation *notes) {annotated_source__delete (notes->src); +annotated_branch__delete (notes->branch); }static struct sharded_mutex *sharded_mutex;
@@ -3074,13 +3082,14 @@ static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,static void ipc_coverage_string (char *bf,int size,struct annotation *notes) {double ipc =0.0 , coverage =0.0 ; +struct annotated_branch *branch =annotation__get_branch (notes); -if (notes->hit_cycles) - ipc = notes->hit_insn / ((double )notes->hit_cycles); +if (branch && branch->hit_cycles) + ipc = branch->hit_insn / ((double )branch->hit_cycles); -if (notes->total_insn) { - coverage = notes->cover_insn *100.0 / - ((double )notes->total_insn); +if (branch && branch->total_insn) { + coverage = branch->cover_insn *100.0 / + ((double )branch->total_insn); } scnprintf(bf, size, "(Average IPC: %.2f, IPC Coverage: %.1f%%)",
@@ -3105,7 +3114,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotatiint printed;if (first_line && (al->offset ==-1 || percent_max ==0.0 )) { -if (notes->have_cycles && al->cycles) { +if (notes->branch && al->cycles) {if (al->cycles->ipc ==0.0 && al->cycles->avg ==0 ) show_title = true; }else
@@ -3142,7 +3151,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati } } -if (notes->have_cycles) { +if (notes->branch) {if (al->cycles && al->cycles->ipc)obj__printf (obj,"%*.2f " ,ANNOTATION__IPC_WIDTH -1 , al->cycles->ipc);else if (!show_title)
tools/perf/util/annotate.h +10 -7
@@ -272,17 +272,20 @@ struct annotated_source {struct list_head source;int nr_histograms;size_t sizeof_sym_hist; -struct cyc_hist *cycles_hist;struct sym_hist *histograms; }; -struct LOCKABLE annotation { -u64 max_coverage; -u64 start; +struct annotated_branch {u64 hit_cycles;u64 hit_insn;unsigned int total_insn;unsigned int cover_insn; +struct cyc_hist *cycles_hist; +}; + +struct LOCKABLE annotation { +u64 max_coverage; +u64 start;struct annotation_options *options;struct annotation_line **offsets;int nr_events;
@@ -298,8 +301,8 @@ struct LOCKABLE annotation {u8 max_addr;u8 max_ins_name; } widths; -bool have_cycles;struct annotated_source *src; +struct annotated_branch *branch; };static inline void annotation__init (struct annotation *notes__maybe_unused )
@@ -313,10 +316,10 @@ bool annotation__trylock(struct annotation *notes) EXCLUSIVE_TRYLOCK_FUNCTION(trstatic inline int annotation__cycles_width (struct annotation *notes) { -if (notes->have_cycles && notes->options->show_minmax_cycle) +if (notes->branch && notes->options->show_minmax_cycle)return ANNOTATION__IPC_WIDTH +ANNOTATION__MINMAX_CYCLES_WIDTH ; -return notes->have_cycles ?ANNOTATION__IPC_WIDTH +ANNOTATION__CYCLES_WIDTH :0 ; +return notes->branch ?ANNOTATION__IPC_WIDTH +ANNOTATION__CYCLES_WIDTH :0 ; }static inline int annotation__pcnt_width (struct annotation *notes)
tools/perf/util/block-info.c +2 -2
@@ -129,9 +129,9 @@ int block_info__process_sym(struct hist_entry *he, struct block_hist *bh, al.sym = he->ms.sym; notes =symbol__annotation (he->ms.sym); -if (!notes || !notes->src || !notes->src->cycles_hist) +if (!notes || !notes->branch || !notes->branch->cycles_hist)return 0 ; - ch = notes->src->cycles_hist; + ch = notes->branch->cycles_hist;for (unsigned int i =0 ; i <symbol__size (he->ms.sym); i++) {if (ch[i].num_aggr) {struct block_info *bi;
tools/perf/util/sort.c +7 -7
@@ -583,21 +583,21 @@ static int hist_entry__sym_ipc_snprintf(struct hist_entry *he, char *bf, {struct symbol *sym = he->ms.sym; -struct annotation *notes; +struct annotated_branch *branch;double ipc =0.0 , coverage =0.0 ;char tmp[64 ];if (!sym)return repsep_snprintf (bf, size,"%-*s" , width,"-" ); - notes =symbol__annotation (sym); + branch =symbol__annotation (sym)->branch; -if (notes->hit_cycles) - ipc = notes->hit_insn / ((double )notes->hit_cycles); +if (branch && branch->hit_cycles) + ipc = branch->hit_insn / ((double )branch->hit_cycles); -if (notes->total_insn) { - coverage = notes->cover_insn *100.0 / - ((double )notes->total_insn); +if (branch && branch->total_insn) { + coverage = branch->cover_insn *100.0 / + ((double )branch->total_insn); }snprintf (tmp,sizeof (tmp),"%-5.2f [%5.1f%%]" , ipc, coverage);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 250/538 perf annotate: Move some source code related fields from struct annotation to struct annotated_source
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namhyung Kim <[email protected]>
[ Upstream commit 0aae4c99c5f8f748c6cb5ca03bb3b3ae8cfb10df ]
Some fields in the 'struct annotation' are only used with 'struct annotated_source' so better to be moved there in order to reduce memory consumption for other symbols.
Stable-dep-of: 3ef44458071a ("perf report: Fix --total-cycles --stdio output error")
--- tools/perf/ui/browsers/annotate.c | 12 ++++++------ tools/perf/util/annotate.c | 17 +++++++++-------- tools/perf/util/annotate.h | 14 +++++++------- 3 files changed, 22 insertions(+), 21 deletions(-)
tools/perf/ui/browsers/annotate.c +6 -6
@@ -384,7 +384,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)if (al->idx_asm < offset) offset = al->idx; - browser->b.nr_entries = notes->nr_entries; + browser->b.nr_entries = notes->src->nr_entries; notes->options->hide_src_code = false; browser->b.seek (&browser->b, -offset,SEEK_CUR ); browser->b.top_idx = al->idx - offset;
@@ -402,7 +402,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)if (al->idx_asm < offset) offset = al->idx_asm; - browser->b.nr_entries = notes->nr_asm_entries; + browser->b.nr_entries = notes->src->nr_asm_entries; notes->options->hide_src_code = true; browser->b.seek (&browser->b, -offset,SEEK_CUR ); browser->b.top_idx = al->idx_asm - offset;
@@ -435,7 +435,7 @@ static void ui_browser__init_asm_mode(struct ui_browser *browser) {struct annotation *notes =browser__annotation (browser);ui_browser__reset_index (browser); - browser->nr_entries = notes->nr_asm_entries; + browser->nr_entries = notes->src->nr_asm_entries; } static int sym_title(struct symbol *sym, struct map *map, char *title,
@@ -860,7 +860,7 @@ static int annotate_browser__run(struct annotate_browser *browser, browser->b.height, browser->b.index, browser->b.top_idx, - notes->nr_asm_entries); + notes->src->nr_asm_entries); }continue ;case K_ENTER :
@@ -991,8 +991,8 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,ui_helpline__push ("Press ESC to exit" ); - browser.b.width = notes->max_line_len; - browser.b.nr_entries = notes->nr_entries; + browser.b.width = notes->src->max_line_len; + browser.b.nr_entries = notes->src->nr_entries; browser.b.entries = ¬es->src->source, browser.b.width +=18 ;/* Percentage */
tools/perf/util/annotate.c +9 -8
@@ -2825,19 +2825,20 @@ void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)void annotation__set_offsets (struct annotation *notes,s64 size) {struct annotation_line *al; +struct annotated_source *src = notes->src; - notes->max_line_len =0 ; - notes->nr_entries =0 ; - notes->nr_asm_entries =0 ; + src->max_line_len =0 ; + src->nr_entries =0 ; + src->nr_asm_entries =0 ; -list_for_each_entry (al, ¬es->src->source, node) { +list_for_each_entry (al, &src->source, node) {size_t line_len =strlen (al->line); -if (notes->max_line_len < line_len) - notes->max_line_len = line_len; - al->idx = notes->nr_entries++; +if (src->max_line_len < line_len) + src->max_line_len = line_len; + al->idx = src->nr_entries++;if (al->offset !=-1 ) { - al->idx_asm = notes->nr_asm_entries++; + al->idx_asm = src->nr_asm_entries++;/* * FIXME: short term bandaid to cope with assembly * routines that comes with labels in the same column
tools/perf/util/annotate.h +7 -7
@@ -269,10 +269,13 @@ struct cyc_hist {* returns. */ struct annotated_source { -struct list_head source; -int nr_histograms; -size_t sizeof_sym_hist; -struct sym_hist *histograms; +struct list_head source; +size_t sizeof_sym_hist; +struct sym_hist *histograms; +int nr_histograms; +int nr_entries; +int nr_asm_entries; +u16 max_line_len; };struct annotated_branch {
@@ -290,9 +293,6 @@ struct LOCKABLE annotation {struct annotation_line **offsets;int nr_events;int max_jump_sources; -int nr_entries; -int nr_asm_entries; -u16 max_line_len;struct {u8 addr;u8 jumps;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 251/538 perf ui/browser/annotate: Use global annotation_options
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namhyung Kim <[email protected]>
[ Upstream commit 22197fb296913f83c7182befd2a8b23bf042f279 ]
Now it can use the global options and no need save local browser options separately.
Stable-dep-of: 3ef44458071a ("perf report: Fix --total-cycles --stdio output error")
--- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-report.c | 8 ++-- tools/perf/builtin-top.c | 3 +- tools/perf/ui/browsers/annotate.c | 65 ++++++++++++++----------------- tools/perf/ui/browsers/hists.c | 34 ++++++---------- tools/perf/ui/browsers/hists.h | 2 - tools/perf/util/annotate.h | 6 +-- tools/perf/util/block-info.c | 6 +-- tools/perf/util/block-info.h | 3 +- tools/perf/util/hist.h | 25 ++++-------- 10 files changed, 59 insertions(+), 95 deletions(-)
tools/perf/builtin-annotate.c +1 -1
@@ -378,7 +378,7 @@ static void hists__find_annotations(struct hists *hists,/* skip missing symbols */ nd =rb_next (nd); }else if (use_browser ==1 ) { - key =hist_entry__tui_annotate (he, evsel,NULL , &annotate_opts); + key =hist_entry__tui_annotate (he, evsel,NULL );switch (key) {case -1 :
tools/perf/builtin-report.c +3 -5
@@ -540,8 +540,7 @@ static int evlist__tui_block_hists_browse(struct evlist *evlist, struct report *evlist__for_each_entry (evlist, pos) { ret =report__browse_block_hists (&rep->block_reports[i++].hist, rep->min_percent, pos, - &rep->session->header.env, - &annotate_opts); + &rep->session->header.env);if (ret !=0 )return ret; }
@@ -573,8 +572,7 @@ static int evlist__tty_browse_hists(struct evlist *evlist, struct report *rep, cif (rep->total_cycles_mode) {report__browse_block_hists (&rep->block_reports[i++].hist, - rep->min_percent, pos, -NULL ,NULL ); + rep->min_percent, pos,NULL );continue ; }
@@ -669,7 +667,7 @@ static int report__browse_hists(struct report *rep) } ret =evlist__tui_browse_hists (evlist, help,NULL , rep->min_percent, - &session->header.env, true, &annotate_opts); + &session->header.env, true);/* * Usually "ret" is the last pressed key, and we only * care if the key notifies us to switch data file.
tools/perf/builtin-top.c +1 -2
@@ -646,8 +646,7 @@ static void *display_thread_tui(void *arg) } ret =evlist__tui_browse_hists (top->evlist, help, &hbt, top->min_percent, - &top->session->header.env, !top->record_opts.overwrite, - &annotate_opts); + &top->session->header.env, !top->record_opts.overwrite);if (ret ==K_RELOAD ) { top->zero = true; goto repeat;
tools/perf/ui/browsers/annotate.c +29 -36
210 lines not on this page · raw message
tools/perf/ui/browsers/hists.c +12 -22
@@ -2250,8 +2250,7 @@ struct hist_browser *hist_browser__new(struct hists *hists)static struct hist_browser *perf_evsel_browser__new (struct evsel *evsel,struct hist_browser_timer *hbt, -struct perf_env *env, -struct annotation_options *annotation_opts) +struct perf_env *env) {struct hist_browser *browser =hist_browser__new (evsel__hists (evsel));
@@ -2259,7 +2258,6 @@ perf_evsel_browser__new(struct evsel *evsel, browser->hbt = hbt; browser->env = env; browser->title = hists_browser__scnprintf_title; - browser->annotation_opts = annotation_opts; }return browser; }
@@ -2432,8 +2430,8 @@ do_annotate(struct hist_browser *browser, struct popup_action *act)struct hist_entry *he;int err; -if (!browser->annotation_opts->objdump_path && -perf_env__lookup_objdump (browser->env, &browser->annotation_opts->objdump_path)) +if (!annotate_opts.objdump_path && +perf_env__lookup_objdump (browser->env, &annotate_opts.objdump_path))return 0 ; notes =symbol__annotation (act->ms.sym);
@@ -2445,8 +2443,7 @@ do_annotate(struct hist_browser *browser, struct popup_action *act)else evsel =hists_to_evsel (browser->hists); - err =map_symbol__tui_annotate (&act->ms, evsel, browser->hbt, - browser->annotation_opts); + err =map_symbol__tui_annotate (&act->ms, evsel, browser->hbt); he =hist_browser__selected_entry (browser);/* * offer option to annotate the other branch source or target
@@ -2943,11 +2940,10 @@ static void hist_browser__update_percent_limit(struct hist_browser *hb,static int evsel__hists_browse (struct evsel *evsel,int nr_events,const char *helpline,bool left_exits,struct hist_browser_timer *hbt,float min_pcnt, -struct perf_env *env,bool warn_lost_event, -struct annotation_options *annotation_opts) +struct perf_env *env,bool warn_lost_event) {struct hists *hists =evsel__hists (evsel); -struct hist_browser *browser =perf_evsel_browser__new (evsel, hbt, env, annotation_opts); +struct hist_browser *browser =perf_evsel_browser__new (evsel, hbt, env);struct branch_info *bi =NULL ;#define MAX_OPTIONS 16char *options[MAX_OPTIONS ];
@@ -3398,7 +3394,6 @@ static int evsel__hists_browse(struct evsel *evsel, int nr_events, const char *hstruct evsel_menu {struct ui_browser b;struct evsel *selection; -struct annotation_options *annotation_opts;bool lost_events, lost_events_warned;float min_pcnt;struct perf_env *env;
@@ -3499,8 +3494,7 @@ static int perf_evsel_menu__run(struct evsel_menu *menu, hbt->timer (hbt->arg); key =evsel__hists_browse (pos, nr_events, help, true, hbt, menu->min_pcnt, menu->env, - warn_lost_event, - menu->annotation_opts); + warn_lost_event);ui_browser__show_title (&menu->b, title);switch (key) {case K_TAB :
@@ -3557,7 +3551,7 @@ static bool filter_group_entries(struct ui_browser *browser __maybe_unused,static int __evlist__tui_browse_hists (struct evlist *evlist,int nr_entries,const char *help,struct hist_browser_timer *hbt,float min_pcnt,struct perf_env *env, -bool warn_lost_event,struct annotation_options *annotation_opts) +bool warn_lost_event) {struct evsel *pos;struct evsel_menu menu = {
@@ -3572,7 +3566,6 @@ static int __evlist__tui_browse_hists(struct evlist *evlist, int nr_entries, con }, .min_pcnt = min_pcnt, .env = env, - .annotation_opts = annotation_opts, };ui_helpline__push ("Press ESC to exit" );
@@ -3607,8 +3600,7 @@ static bool evlist__single_entry(struct evlist *evlist) }int evlist__tui_browse_hists (struct evlist *evlist,const char *help,struct hist_browser_timer *hbt, -float min_pcnt,struct perf_env *env,bool warn_lost_event, -struct annotation_options *annotation_opts) +float min_pcnt,struct perf_env *env,bool warn_lost_event) {int nr_entries = evlist->core.nr_entries;
@@ -3617,7 +3609,7 @@ single_entry: {struct evsel *first =evlist__first (evlist);return evsel__hists_browse (first, nr_entries, help, false, hbt, min_pcnt, - env, warn_lost_event, annotation_opts); + env, warn_lost_event); } }
@@ -3635,7 +3627,7 @@ single_entry: { }return __evlist__tui_browse_hists (evlist, nr_entries, help, hbt, min_pcnt, env, - warn_lost_event, annotation_opts); + warn_lost_event); } static int block_hists_browser__title(struct hist_browser *browser, char *bf,
@@ -3654,8 +3646,7 @@ static int block_hists_browser__title(struct hist_browser *browser, char *bf, }int block_hists_tui_browse (struct block_hist *bh,struct evsel *evsel, -float min_percent,struct perf_env *env, -struct annotation_options *annotation_opts) +float min_percent,struct perf_env *env) {struct hists *hists = &bh->block_hists;struct hist_browser *browser;
@@ -3672,7 +3663,6 @@ int block_hists_tui_browse(struct block_hist *bh, struct evsel *evsel, browser->title = block_hists_browser__title; browser->min_pcnt = min_percent; browser->env = env; - browser->annotation_opts = annotation_opts;/* reset abort key so that it can get Ctrl-C as a key */ SLang_reset_tty ();
tools/perf/ui/browsers/hists.h +0 -2
@@ -4,7 +4,6 @@#include "ui/browser.h" -struct annotation_options ;struct evsel ;struct hist_browser {
@@ -15,7 +14,6 @@ struct hist_browser {struct hist_browser_timer *hbt;struct pstack *pstack;struct perf_env *env; -struct annotation_options *annotation_opts;struct evsel *block_evsel;int print_seq;bool show_dso;
tools/perf/util/annotate.h +2 -4
@@ -412,13 +412,11 @@ int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel);#ifdef HAVE_SLANG_SUPPORT int symbol__tui_annotate (struct map_symbol *ms,struct evsel *evsel, -struct hist_browser_timer *hbt, -struct annotation_options *opts); +struct hist_browser_timer *hbt);#else static inline int symbol__tui_annotate (struct map_symbol *ms__maybe_unused ,struct evsel *evsel__maybe_unused , -struct hist_browser_timer *hbt__maybe_unused , -struct annotation_options *opts__maybe_unused ) +struct hist_browser_timer *hbt__maybe_unused ) {return 0 ; }
tools/perf/util/block-info.c +2 -4
@@ -464,8 +464,7 @@ void block_info__free_report(struct block_report *reps, int nr_reps) }int report__browse_block_hists (struct block_hist *bh,float min_percent, -struct evsel *evsel,struct perf_env *env, -struct annotation_options *annotation_opts) +struct evsel *evsel,struct perf_env *env) {int ret;
@@ -477,8 +476,7 @@ int report__browse_block_hists(struct block_hist *bh, float min_percent,return 0 ;case 1 : symbol_conf.report_individual_block = true; - ret =block_hists_tui_browse (bh, evsel, min_percent, - env, annotation_opts); + ret =block_hists_tui_browse (bh, evsel, min_percent, env);return ret;default :return -1 ;
tools/perf/util/block-info.h +1 -2
@@ -78,8 +78,7 @@ struct block_report *block_info__create_report(struct evlist *evlist,void block_info__free_report (struct block_report *reps,int nr_reps);int report__browse_block_hists (struct block_hist *bh,float min_percent, -struct evsel *evsel,struct perf_env *env, -struct annotation_options *annotation_opts); +struct evsel *evsel,struct perf_env *env);float block_info__total_cycles_percent (struct hist_entry *he);
tools/perf/util/hist.h +8 -17
@@ -457,7 +457,6 @@ struct hist_browser_timer {int refresh; }; -struct annotation_options ;struct res_sample ;enum rstype {
@@ -473,16 +472,13 @@ struct block_hist;void attr_to_script (char *buf,struct perf_event_attr *attr);int map_symbol__tui_annotate (struct map_symbol *ms,struct evsel *evsel, -struct hist_browser_timer *hbt, -struct annotation_options *annotation_opts); +struct hist_browser_timer *hbt);int hist_entry__tui_annotate (struct hist_entry *he,struct evsel *evsel, -struct hist_browser_timer *hbt, -struct annotation_options *annotation_opts); +struct hist_browser_timer *hbt);int evlist__tui_browse_hists (struct evlist *evlist,const char *help,struct hist_browser_timer *hbt, -float min_pcnt,struct perf_env *env,bool warn_lost_event, -struct annotation_options *annotation_options); +float min_pcnt,struct perf_env *env,bool warn_lost_event);int script_browse (const char *script_opt,struct evsel *evsel);
@@ -492,8 +488,7 @@ int res_sample_browse(struct res_sample *res_samples, int num_res,void res_sample_init (void );int block_hists_tui_browse (struct block_hist *bh,struct evsel *evsel, -float min_percent,struct perf_env *env, -struct annotation_options *annotation_opts); +float min_percent,struct perf_env *env);#else static inline int evlist__tui_browse_hists(struct evlist *evlist __maybe_unused,
@@ -501,23 +496,20 @@ int evlist__tui_browse_hists(struct evlist *evlist __maybe_unused,struct hist_browser_timer *hbt__maybe_unused , float min_pcnt __maybe_unused, struct perf_env *env __maybe_unused, - bool warn_lost_event __maybe_unused, - struct annotation_options *annotation_options __maybe_unused) + bool warn_lost_event __maybe_unused) { return 0; }static inline int map_symbol__tui_annotate (struct map_symbol *ms__maybe_unused ,struct evsel *evsel__maybe_unused , -struct hist_browser_timer *hbt__maybe_unused , -struct annotation_options *annotation_options__maybe_unused ) +struct hist_browser_timer *hbt__maybe_unused ) {return 0 ; }static inline int hist_entry__tui_annotate (struct hist_entry *he__maybe_unused ,struct evsel *evsel__maybe_unused , -struct hist_browser_timer *hbt__maybe_unused , -struct annotation_options *annotation_opts__maybe_unused ) +struct hist_browser_timer *hbt__maybe_unused ) {return 0 ; }
@@ -541,8 +533,7 @@ static inline void res_sample_init(void) {}static inline int block_hists_tui_browse (struct block_hist *bh__maybe_unused ,struct evsel *evsel__maybe_unused ,float min_percent__maybe_unused , -struct perf_env *env__maybe_unused , -struct annotation_options *annotation_opts__maybe_unused ) +struct perf_env *env__maybe_unused ) {return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 252/538 perf report: Fix --total-cycles --stdio output error
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kan Liang <[email protected]>
[ Upstream commit 3ef44458071a19e5b5832cdfe6f75273aa521b6e ]
The --total-cycles may output wrong information with the --stdio.
For example:
# perf record -e "{cycles,instructions}",cache-misses -b sleep 1
# perf report --total-cycles --stdioThe total cycles output of {cycles,instructions} and cache-misses are almost the same.
# Samples: 938 of events 'anon group { cycles, instructions }' # Event count (approx.): 938
#
# Sampled Cycles% Sampled Cycles Avg Cycles% Avg Cycles [Program Block Range]
# ............... .............. ........... .......... ..................................................>
#
11.19% 2.6K 0.10% 21 [perf_iterate_ctx+48 -> >
5.79% 1.4K 0.45% 97 [__intel_pmu_enable_all.constprop.0+80 -> __intel_>
5.11% 1.2K 0.33% 71 [native_write_msr+0 ->> # Samples: 293 of event 'cache-misses'
# Event count (approx.): 293
#
# Sampled Cycles% Sampled Cycles Avg Cycles% Avg Cycles [Program Block Range]
# ............... .............. ........... .......... ..................................................>
#
11.19% 2.6K 0.13% 21 [perf_iterate_ctx+48 -> >
5.79% 1.4K 0.59% 97 [__intel_pmu_enable_all.constprop.0+80 -> __intel_>
5.11% 1.2K 0.43% 71 [native_write_msr+0 ->>With the symbol_conf.event_group, the 'perf report' should only report the block information of the leader event in a group.
However, the current implementation retrieves the next event's block information, rather than the next group leader's block information.
Make sure the index is updated even if the event is skipped.
With the patch,
# Samples: 293 of event 'cache-misses'
# Event count (approx.): 293
#
# Sampled Cycles% Sampled Cycles Avg Cycles% Avg Cycles [Program Block Range]
# ............... .............. ........... .......... ..................................................>
#
37.98% 9.0K 4.05% 299 [perf_event_addr_filters_exec+0 -> perf_event_a>
11.19% 2.6K 0.28% 21 [perf_iterate_ctx+48 -> >
5.79% 1.4K 1.32% 97 [__intel_pmu_enable_all.constprop.0+80 -> __intel_>--- tools/perf/builtin-report.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/builtin-report.c +2 -1
@@ -562,6 +562,7 @@ static int evlist__tty_browse_hists(struct evlist *evlist, struct report *rep, cstruct hists *hists =evsel__hists (pos);const char *evname =evsel__name (pos); + i++;if (symbol_conf.event_group && !evsel__is_group_leader (pos))continue ;
@@ -571,7 +572,7 @@ static int evlist__tty_browse_hists(struct evlist *evlist, struct report *rep, chists__fprintf_nr_sample_events (hists, rep, evname, stdout);if (rep->total_cycles_mode) { -report__browse_block_hists (&rep->block_reports[i++].hist, +report__browse_block_hists (&rep->block_reports[i -1 ].hist, rep->min_percent, pos,NULL );continue ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 253/538 perf sched timehist: Fix missing free of session in perf_sched__timehist()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Jihong <[email protected]>
[ Upstream commit 6bdf5168b6fb19541b0c1862bdaa596d116c7bfb ]
When perf_time__parse_str() fails in perf_sched__timehist(), need to free session that was previously created, fix it.
--- tools/perf/builtin-sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/builtin-sched.c +2 -1
@@ -3068,7 +3068,8 @@ static int perf_sched__timehist(struct perf_sched *sched)if (perf_time__parse_str (&sched->ptime, sched->time_str) !=0 ) {pr_err ("Invalid time string\n" ); -return -EINVAL ; + err = -EINVAL ; + goto out; }if (timehist_check_attr (sched, evlist) !=0 )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 254/538 perf stat: Display iostat headers correctly
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yicong Yang <[email protected]>
[ Upstream commit 2615639352420e6e3115952c5b8f46846e1c6d0e ]
Currently we'll only print metric headers for metric leader in aggregration mode. This will make perf iostat header not shown since it'll aggregrated globally but don't have metric events:
root@ubuntu204:/home/yang/linux/tools/perf# ./perf stat --iostat --timeout 1000
Performance counter stats for 'system wide':
port
0000:00 0 0 0 0
0000:80 0 0 0 0
[...]Fix this by excluding the iostat in the check of printing metric headers. Then we can see the headers:
root@ubuntu204:/home/yang/linux/tools/perf# ./perf stat --iostat --timeout 1000
Performance counter stats for 'system wide':
port Inbound Read(MB) Inbound Write(MB) Outbound Read(MB) Outbound Write(MB)
0000:00 0 0 0 0
0000:80 0 0 0 0
[...]--- tools/perf/util/stat-display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/stat-display.c +2 -1
@@ -1207,7 +1207,8 @@ static void print_metric_headers(struct perf_stat_config *config,/* Print metrics headers only */ evlist__for_each_entry (evlist, counter) { -if (config->aggr_mode !=AGGR_NONE && counter->metric_leader != counter) +if (!config->iostat_run && + config->aggr_mode !=AGGR_NONE && counter->metric_leader != counter)continue ; os.evsel = counter;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 255/538 perf sched timehist: Fixed timestamp error when unable to confirm event sched_in time
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Jihong <[email protected]>
[ Upstream commit 39c243411bdb8fb35777adf49ee32549633c4e12 ]
If sched_in event for current task is not recorded, sched_in timestamp will be set to end_time of time window interest, causing an error in timestamp show. In this case, we choose to ignore this event.
Test scenario:
perf[1229608] does not record the first sched_in event, run time and sch delay are both 0
# perf sched timehist
Samples of sched_switch event do not have callchains.
time cpu task name wait time sch delay run time
[tid/pid] (msec) (msec) (msec)
--------------- ------ ------------------------------ --------- --------- ---------
2090450.763231 [0000] perf[1229608] 0.000 0.000 0.000
2090450.763235 [0000] migration/0[15] 0.000 0.001 0.003
2090450.763263 [0001] perf[1229608] 0.000 0.000 0.000
2090450.763268 [0001] migration/1[21] 0.000 0.001 0.004
2090450.763302 [0002] perf[1229608] 0.000 0.000 0.000
2090450.763309 [0002] migration/2[27] 0.000 0.001 0.007
2090450.763338 [0003] perf[1229608] 0.000 0.000 0.000
2090450.763343 [0003] migration/3[33] 0.000 0.001 0.004Before:
arbitrarily specify a time window of interest, timestamp will be set to an incorrect value
# perf sched timehist --time 100,200
Samples of sched_switch event do not have callchains.
time cpu task name wait time sch delay run time
[tid/pid] (msec) (msec) (msec)
--------------- ------ ------------------------------ --------- --------- ---------
200.000000 [0000] perf[1229608] 0.000 0.000 0.000
200.000000 [0001] perf[1229608] 0.000 0.000 0.000
200.000000 [0002] perf[1229608] 0.000 0.000 0.000
200.000000 [0003] perf[1229608] 0.000 0.000 0.000
200.000000 [0004] perf[1229608] 0.000 0.000 0.000
200.000000 [0005] perf[1229608] 0.000 0.000 0.000
200.000000 [0006] perf[1229608] 0.000 0.000 0.000
200.000000 [0007] perf[1229608] 0.000 0.000 0.000After:
# perf sched timehist --time 100,200
Samples of sched_switch event do not have callchains.
time cpu task name wait time sch delay run time
[tid/pid] (msec) (msec) (msec)
--------------- ------ ------------------------------ --------- --------- ------------ tools/perf/builtin-sched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/perf/builtin-sched.c +4 -1
@@ -2633,9 +2633,12 @@ static int timehist_sched_change_event(struct perf_tool *tool,* - previous sched event is out of window - we are done * - sample time is beyond window user cares about - reset it * to close out stats for time window interest +* - If tprev is 0, that is, sched_in event for current task is +* not recorded, cannot determine whether sched_in event is +* within time window interest - ignore it */ if (ptime->end) { -if (tprev > ptime->end) +if (!tprev || tprev > ptime->end) goto out;if (t > ptime->end)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 256/538 perf time-utils: Fix 32-bit nsec parsing
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Rogers <[email protected]>
[ Upstream commit 38e2648a81204c9fc5b4c87a8ffce93a6ed91b65 ]
The "time utils" test fails in 32-bit builds:
...
parse_nsec_time("18446744073.709551615")
Failed. ptime 4294967295709551615 expected 18446744073709551615
...
Switch strtoul to strtoull as an unsigned long in 32-bit build isn't 64-bits.
--- tools/perf/util/time-utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/util/time-utils.c +2 -2
@@ -20,7 +20,7 @@ int parse_nsec_time(const char *str, u64 *ptime)u64 time_sec, time_nsec;char *end; - time_sec =strtoul (str, &end,10 ); + time_sec =strtoull (str, &end,10 );if (*end !='.' && *end !='\0' )return -1 ;
@@ -38,7 +38,7 @@ int parse_nsec_time(const char *str, u64 *ptime)for (i =strlen (nsec_buf); i <9 ; i++) nsec_buf[i] ='0' ; - time_nsec =strtoul (nsec_buf, &end,10 ); + time_nsec =strtoull (nsec_buf, &end,10 );if (*end !='\0' )return -1 ; }else
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 257/538 clk: imx: clk-audiomix: Correct parent clock for earc_phy and audpll
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shengjiu Wang <[email protected]>
[ Upstream commit d40371a1c963db688b37826adaf5ffdafb0862a1 ]
According to Reference Manual of i.MX8MP
The parent clock of "earc_phy" is "sai_pll_out_div2", The parent clock of "audpll" is "osc_24m".
Add CLK_GATE_PARENT() macro for usage of specifying parent clock.
--- drivers/clk/imx/clk-imx8mp-audiomix.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/clk/imx/clk-imx8mp-audiomix.c +11 -2
@@ -146,6 +146,15 @@ static const struct clk_parent_data clk_imx8mp_audiomix_pll_bypass_sels[] = { PDM_SEL, 2, 0 \ } +#define CLK_GATE_PARENT (gname, cname, pname) \ + { \ + gname"_cg", \ + IMX8MP_CLK_AUDIOMIX_##cname, \ + { .fw_name = pname, .name = pname }, NULL, 1, \ + CLKEN0 + 4 * !!(IMX8MP_CLK_AUDIOMIX_##cname / 32), \ + 1, IMX8MP_CLK_AUDIOMIX_##cname % 32 \ + } +struct clk_imx8mp_audiomix_sel {const char *name;int clkid;
@@ -163,14 +172,14 @@ static struct clk_imx8mp_audiomix_sel sels[] = {CLK_GATE ("earc" ,EARC_IPG ),CLK_GATE ("ocrama" ,OCRAMA_IPG ),CLK_GATE ("aud2htx" ,AUD2HTX_IPG ), -CLK_GATE ("earc_phy" ,EARC_PHY ), +CLK_GATE_PARENT ("earc_phy" ,EARC_PHY ,"sai_pll_out_div2" ),CLK_GATE ("sdma2" ,SDMA2_ROOT ),CLK_GATE ("sdma3" ,SDMA3_ROOT ),CLK_GATE ("spba2" ,SPBA2_ROOT ),CLK_GATE ("dsp" ,DSP_ROOT ),CLK_GATE ("dspdbg" ,DSPDBG_ROOT ),CLK_GATE ("edma" ,EDMA_ROOT ), -CLK_GATE ("audpll" ,AUDPLL_ROOT ), +CLK_GATE_PARENT ("audpll" ,AUDPLL_ROOT ,"osc_24m" ),CLK_GATE ("mu2" ,MU2_ROOT ),CLK_GATE ("mu3" ,MU3_ROOT ), CLK_PDM,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 258/538 clk: imx: imx6ul: fix default parent for enet*_ref_sel
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastien Laveze <[email protected]>
[ Upstream commit e52fd71333b4ed78fd5bb43094bdc46476614d25 ]
The clk_set_parent for "enet1_ref_sel" and "enet2_ref_sel" are incorrect, therefore the original requirements to have "enet_clk_ref" as output sourced by iMX ENET PLL as a default config is not met.
Only "enet[1,2]_ref_125m" "enet[1,2]_ref_pad" are possible parents for "enet1_ref_sel" and "enet2_ref_sel".
This was observed as a regression using a custom device tree which was expecting this default config.
This can be fixed at the device tree level but having a default config matching the original behavior (before refclock mux) will avoid breaking existing configs.
--- drivers/clk/imx/clk-imx6ul.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/imx/clk-imx6ul.c +2 -2
@@ -542,8 +542,8 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)clk_set_parent (hws[IMX6UL_CLK_ENFC_SEL ]->clk, hws[IMX6UL_CLK_PLL2_PFD2 ]->clk); -clk_set_parent (hws[IMX6UL_CLK_ENET1_REF_SEL ]->clk, hws[IMX6UL_CLK_ENET_REF ]->clk); -clk_set_parent (hws[IMX6UL_CLK_ENET2_REF_SEL ]->clk, hws[IMX6UL_CLK_ENET2_REF ]->clk); +clk_set_parent (hws[IMX6UL_CLK_ENET1_REF_SEL ]->clk, hws[IMX6UL_CLK_ENET1_REF_125M ]->clk); +clk_set_parent (hws[IMX6UL_CLK_ENET2_REF_SEL ]->clk, hws[IMX6UL_CLK_ENET2_REF_125M ]->clk);imx_register_uart_clocks (); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 259/538 clk: imx: composite-8m: Less function calls in __imx8m_clk_hw_composite() after error detection
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Markus Elfring <[email protected]>
[ Upstream commit fed6bf52c86df27ad4f39a72cdad8c27da9a50ba ]
The function “kfree” was called in up to three cases by the function “__imx8m_clk_hw_composite” during error handling even if the passed variables contained a null pointer.
Adjust jump targets according to the Linux coding style convention.
Stable-dep-of: 8f32e9dd0916 ("clk: imx: composite-8m: Enable gate clk with mcore_booted")
--- drivers/clk/imx/clk-composite-8m.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
drivers/clk/imx/clk-composite-8m.c +7 -5
@@ -220,7 +220,7 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name, mux =kzalloc (sizeof (*mux),GFP_KERNEL );if (!mux) - goto fail; +return ERR_CAST (hw); mux_hw = &mux->hw; mux->reg = reg;
@@ -230,7 +230,7 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name, div =kzalloc (sizeof (*div),GFP_KERNEL );if (!div) - goto fail; + goto free_mux; div_hw = &div->hw; div->reg = reg;
@@ -260,7 +260,7 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name,if (!mcore_booted) { gate =kzalloc (sizeof (*gate),GFP_KERNEL );if (!gate) - goto fail; + goto free_div; gate_hw = &gate->hw; gate->reg = reg;
@@ -272,13 +272,15 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name, mux_hw, mux_ops, div_hw, divider_ops, gate_hw, &clk_gate_ops, flags);if (IS_ERR (hw)) - goto fail; + goto free_gate;return hw; -fail: +free_gate:kfree (gate); +free_div:kfree (div); +free_mux:kfree (mux);return ERR_CAST (hw); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 260/538 clk: imx: composite-8m: Enable gate clk with mcore_booted
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peng Fan <[email protected]>
[ Upstream commit 8f32e9dd0916eb3fd4bcf550ed1d04542a65cb9e ]
Bootloader might disable some CCM ROOT Slices. So if mcore_booted set with display CCM ROOT disabled by Bootloader, kernel display BLK CTRL driver imx8m_blk_ctrl_driver_init may hang the system because the BUS clk is disabled.
Add back gate ops, but with disable doing nothing, then the CCM ROOT will be enabled when used.
--- drivers/clk/imx/clk-composite-8m.c | 53 +++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 11 deletions(-)
drivers/clk/imx/clk-composite-8m.c +42 -11
@@ -204,6 +204,34 @@ static const struct clk_ops imx8m_clk_composite_mux_ops = { .determine_rate = imx8m_clk_composite_mux_determine_rate, }; +static int imx8m_clk_composite_gate_enable (struct clk_hw *hw) +{ +struct clk_gate *gate =to_clk_gate (hw); +unsigned long flags; +u32 val; + +spin_lock_irqsave (gate->lock, flags); + + val =readl (gate->reg); + val |=BIT (gate->bit_idx); +writel (val, gate->reg); + +spin_unlock_irqrestore (gate->lock, flags); + +return 0 ; +} + +static void imx8m_clk_composite_gate_disable (struct clk_hw *hw) +{ +/* composite clk requires the disable hook */ +} + +static const struct clk_ops imx8m_clk_composite_gate_ops = { + .enable = imx8m_clk_composite_gate_enable, + .disable = imx8m_clk_composite_gate_disable, + .is_enabled = clk_gate_is_enabled, +}; + struct clk_hw *__imx8m_clk_hw_composite(const char *name, const char * const *parent_names, int num_parents, void __iomem *reg,
@@ -217,6 +245,7 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name,struct clk_mux *mux =NULL ;const struct clk_ops *divider_ops;const struct clk_ops *mux_ops; +const struct clk_ops *gate_ops; mux =kzalloc (sizeof (*mux),GFP_KERNEL );if (!mux)
@@ -257,20 +286,22 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name, div->flags =CLK_DIVIDER_ROUND_CLOSEST ;/* skip registering the gate ops if M4 is enabled */ -if (!mcore_booted) { - gate =kzalloc (sizeof (*gate),GFP_KERNEL ); -if (!gate) - goto free_div; - - gate_hw = &gate->hw; - gate->reg = reg; - gate->bit_idx =PCG_CGC_SHIFT ; - gate->lock = &imx_ccm_lock; - } + gate =kzalloc (sizeof (*gate),GFP_KERNEL ); +if (!gate) + goto free_div; + + gate_hw = &gate->hw; + gate->reg = reg; + gate->bit_idx =PCG_CGC_SHIFT ; + gate->lock = &imx_ccm_lock; +if (!mcore_booted) + gate_ops = &clk_gate_ops; +else + gate_ops = &imx8m_clk_composite_gate_ops; hw =clk_hw_register_composite (NULL , name, parent_names, num_parents, mux_hw, mux_ops, div_hw, - divider_ops, gate_hw, &clk_gate_ops, flags); + divider_ops, gate_hw, gate_ops, flags);if (IS_ERR (hw)) goto free_gate;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 261/538 clk: imx: composite-93: keep root clock on when mcore enabled
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacky Bai <[email protected]>
[ Upstream commit d342df11726bfac9c3a9d2037afa508ac0e9e44e ]
Previously we assumed that the root clock slice is enabled by default when kernel boot up. But the bootloader may disable the clocks before jump into kernel. The gate ops should be registered rather than NULL to make sure the disabled clock can be enabled when kernel boot up. Refine the code to skip disable the clock if mcore booted.
--- drivers/clk/imx/clk-composite-93.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
drivers/clk/imx/clk-composite-93.c +8 -7
@@ -76,6 +76,13 @@ static int imx93_clk_composite_gate_enable(struct clk_hw *hw)static void imx93_clk_composite_gate_disable (struct clk_hw *hw) { +/* +* Skip disable the root clock gate if mcore enabled. +* The root clock may be used by the mcore. +*/ +if (mcore_booted) +return ; +imx93_clk_composite_gate_endisable (hw,0 ); }
@@ -222,7 +229,7 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p hw =clk_hw_register_composite (NULL , name, parent_names, num_parents, mux_hw, &clk_mux_ro_ops, div_hw, &clk_divider_ro_ops,NULL ,NULL , flags); - }else if (!mcore_booted) { + }else { gate =kzalloc (sizeof (*gate),GFP_KERNEL );if (!gate) goto fail;
@@ -238,12 +245,6 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p &imx93_clk_composite_divider_ops, gate_hw, &imx93_clk_composite_gate_ops, flags | CLK_SET_RATE_NO_REPARENT); - }else { - hw =clk_hw_register_composite (NULL , name, parent_names, num_parents, - mux_hw, &imx93_clk_composite_mux_ops, div_hw, - &imx93_clk_composite_divider_ops,NULL , - &imx93_clk_composite_gate_ops, - flags |CLK_SET_RATE_NO_REPARENT ); }if (IS_ERR (hw))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 262/538 clk: imx: composite-7ulp: Check the PCC present bit
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ye Li <[email protected]>
[ Upstream commit 4717ccadb51e2630790dddd222830702de17f090 ]
When some module is disabled by fuse, its PCC PR bit is default 0 and PCC is not operational. Any write to this PCC will cause SError.
--- drivers/clk/imx/clk-composite-7ulp.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/clk/imx/clk-composite-7ulp.c +7 -0
@@ -14,6 +14,7 @@#include "../clk-fractional-divider.h" #include "clk.h" +#define PCG_PR_MASK BIT(31)#define PCG_PCS_SHIFT 24#define PCG_PCS_MASK 0x7#define PCG_CGC_SHIFT 30
@@ -78,6 +79,12 @@ static struct clk_hw *imx_ulp_clk_hw_composite(const char *name,struct clk_hw *hw;u32 val; + val =readl (reg); +if (!(val &PCG_PR_MASK )) { +pr_info ("PCC PR is 0 for clk:%s, bypass\n" , name); +return 0 ; + } +if (mux_present) { mux =kzalloc (sizeof (*mux),GFP_KERNEL );if (!mux)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 263/538 clk: imx: fracn-gppll: fix fractional part of PLL getting lost
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengfei Li <[email protected]>
[ Upstream commit 7622f888fca125ae46f695edf918798ebc0506c5 ]
Fractional part of PLL gets lost after re-enabling the PLL. the MFN can NOT be automatically loaded when doing frac PLL enable/disable, So when re-enable PLL, configure mfn explicitly.
--- drivers/clk/imx/clk-fracn-gppll.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/clk/imx/clk-fracn-gppll.c +4 -0
@@ -291,6 +291,10 @@ static int clk_fracn_gppll_prepare(struct clk_hw *hw)if (val &POWERUP_MASK )return 0 ; +if (pll->flags &CLK_FRACN_GPPLL_FRACN ) +writel_relaxed (readl_relaxed (pll->base +PLL_NUMERATOR ), + pll->base +PLL_NUMERATOR ); + val |=CLKMUX_BYPASS ;writel_relaxed (val, pll->base +PLL_CTRL );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 264/538 clk: imx: imx8mp: fix clock tree update of TF-A managed clocks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhipeng Wang <[email protected]>
[ Upstream commit 3d29036853b9cb07ac49e8261fca82a940be5c41 ]
On the i.MX8M*, the TF-A exposes a SiP (Silicon Provider) service for DDR frequency scaling. The imx8m-ddrc-devfreq driver calls the SiP and then does clk_set_parent on the DDR muxes to synchronize the clock tree.
since commit 936c383673b9 ("clk: imx: fix composite peripheral flags"), these TF-A managed muxes have SET_PARENT_GATE set, which results in imx8m-ddrc-devfreq's clk_set_parent after SiP failing with -EBUSY:
clk_set_parent(dram_apb_src, sys1_pll_40m);(busfreq-imx8mq.c)
commit 926bf91248dd
("clk: imx8m: fix clock tree update of TF-A managed clocks") adds this method and enables 8mm, 8mn and 8mq. i.MX8MP also needs it.
This is safe to do, because updating the Linux clock tree to reflect reality will always be glitch-free.
Another reason to this patch is that powersave image BT music requires dram to be 400MTS, so clk_set_parent(dram_alt_src, sys1_pll_800m); is required. Without this patch, it will not succeed.
--- drivers/clk/imx/clk-imx8mp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/imx/clk-imx8mp.c +2 -2
@@ -551,8 +551,8 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_IPG_ROOT ] =imx_clk_hw_divider2 ("ipg_root" ,"ahb_root" , ccm_base +0x9080 ,0 ,1 ); - hws[IMX8MP_CLK_DRAM_ALT ] =imx8m_clk_hw_composite ("dram_alt" , imx8mp_dram_alt_sels, ccm_base +0xa000 ); - hws[IMX8MP_CLK_DRAM_APB ] =imx8m_clk_hw_composite_critical ("dram_apb" , imx8mp_dram_apb_sels, ccm_base +0xa080 ); + hws[IMX8MP_CLK_DRAM_ALT ] =imx8m_clk_hw_fw_managed_composite ("dram_alt" , imx8mp_dram_alt_sels, ccm_base +0xa000 ); + hws[IMX8MP_CLK_DRAM_APB ] =imx8m_clk_hw_fw_managed_composite_critical ("dram_apb" , imx8mp_dram_apb_sels, ccm_base +0xa080 ); hws[IMX8MP_CLK_VPU_G1 ] =imx8m_clk_hw_composite ("vpu_g1" , imx8mp_vpu_g1_sels, ccm_base +0xa100 ); hws[IMX8MP_CLK_VPU_G2 ] =imx8m_clk_hw_composite ("vpu_g2" , imx8mp_vpu_g2_sels, ccm_base +0xa180 ); hws[IMX8MP_CLK_CAN1 ] =imx8m_clk_hw_composite ("can1" , imx8mp_can1_sels, ccm_base +0xa200 );
Signature · 1 line
2.43.0