All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Leizhen (ThunderTown)" <thunder.leizhen@huawei.com>
To: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>,
	Robin Murphy <robin.murphy@arm.com>,
	Will Deacon <will.deacon@arm.com>, Joerg Roedel <joro@8bytes.org>,
	linux-arm-kernel <linux-arm-kernel@lists.infradead.org>,
	iommu <iommu@lists.linux-foundation.org>,
	linux-kernel <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 2/5] iommu/arm-smmu-v3: make smmu can be enabled in kdump kernel
Date: Fri, 1 Mar 2019 17:18:57 +0800	[thread overview]
Message-ID: <5C78F901.703@huawei.com> (raw)
In-Reply-To: <5C78F535.4030105@huawei.com>

[-- Attachment #1: Type: text/plain, Size: 6110 bytes --]

It seems that the picture is too big, I change it from jpg to png.


On 2019/3/1 17:02, Leizhen (ThunderTown) wrote:
> Hi All,
>     I drew a flowchart, hope this can help you to understand my method.
> 
> On 2019/2/19 15:54, Zhen Lei wrote:
>> To reduce the risk of further crash, the device_shutdown() was not called
>> by the first kernel. That means some devices may still working in the
>> secondary kernel. For example, a netcard may still using ring buffer to
>> receive the broadcast messages in the kdump kernel. No events are reported
>> utill the related smmu reinitialized by the kdump kernel.
>>
>> commit b63b3439b856 ("iommu/arm-smmu-v3: Abort all transactions if SMMU is
>> enabled in kdump kernel") set SMMU_GBPA.ABORT to prevent the unexpected
>> devices accessing, but it also prevent the devices accessing which we
>> needed, like hard disk, netcard.
>>
>> In fact, we can use STE.config=0b000 to abort the unexpected devices
>> accessing only. As below:
>> 1. In the first kernel, all buffers used by the "unexpected" devices are
>>    correctly mapped, and it will not be used by the secondary kernel
>>    because the latter has its dedicated reserved memory.
>> 2. In the secondary kernel, set SMMU_GBPA.ABORT=1 before "disable smmu".
>> 3. In the secondary kernel, after the smmu was disabled, preset all
>>    STE.config=0b000. For 2-level Stream Table, make all L1STD.l2ptr
>>    pointer to a dummy L2ST. The dummy L2ST is shared by all L1STDs.
>> 4. In the secondary kernel, enable smmu. For the needed devices, allocate
>>    new L2STs accordingly.
>>
>> For phase 1 and 2, the unexpected devices base the old mapping access
>> memory, it will not corrupt others. For phase 3, SMMU_GBPA abort it. For
>> phase 4 STE abort it.
>>
>> Fixes: commit b63b3439b856 ("iommu/arm-smmu-v3: Abort all transactions ...")
>> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
>> ---
>>  drivers/iommu/arm-smmu-v3.c | 72 ++++++++++++++++++++++++++++++++-------------
>>  1 file changed, 51 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
>> index 2072897..c3c4ff2 100644
>> --- a/drivers/iommu/arm-smmu-v3.c
>> +++ b/drivers/iommu/arm-smmu-v3.c
>> @@ -1219,35 +1219,57 @@ static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent)
>>  	}
>>  }
>>
>> -static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
>> +static int __arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid,
>> +				     struct arm_smmu_strtab_l1_desc *desc)
>>  {
>> -	size_t size;
>>  	void *strtab;
>>  	struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
>> -	struct arm_smmu_strtab_l1_desc *desc = &cfg->l1_desc[sid >> STRTAB_SPLIT];
>>
>> -	if (desc->l2ptr)
>> -		return 0;
>> -
>> -	size = 1 << (STRTAB_SPLIT + ilog2(STRTAB_STE_DWORDS) + 3);
>>  	strtab = &cfg->strtab[(sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS];
>>
>> -	desc->span = STRTAB_SPLIT + 1;
>> -	desc->l2ptr = dmam_alloc_coherent(smmu->dev, size, &desc->l2ptr_dma,
>> -					  GFP_KERNEL | __GFP_ZERO);
>>  	if (!desc->l2ptr) {
>> -		dev_err(smmu->dev,
>> -			"failed to allocate l2 stream table for SID %u\n",
>> -			sid);
>> -		return -ENOMEM;
>> +		size_t size;
>> +
>> +		size = 1 << (STRTAB_SPLIT + ilog2(STRTAB_STE_DWORDS) + 3);
>> +		desc->l2ptr = dmam_alloc_coherent(smmu->dev, size,
>> +						  &desc->l2ptr_dma,
>> +						  GFP_KERNEL | __GFP_ZERO);
>> +		if (!desc->l2ptr) {
>> +			dev_err(smmu->dev,
>> +				"failed to allocate l2 stream table for SID %u\n",
>> +				sid);
>> +			return -ENOMEM;
>> +		}
>> +
>> +		desc->span = STRTAB_SPLIT + 1;
>> +		arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
>>  	}
>>
>> -	arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
>>  	arm_smmu_write_strtab_l1_desc(strtab, desc);
>> +	return 0;
>> +}
>> +
>> +static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
>> +{
>> +	int ret;
>> +	struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
>> +	struct arm_smmu_strtab_l1_desc *desc = &cfg->l1_desc[sid >> STRTAB_SPLIT];
>> +
>> +	ret = __arm_smmu_init_l2_strtab(smmu, sid, desc);
>> +	if (ret)
>> +		return ret;
>> +
>>  	arm_smmu_sync_std_for_sid(smmu, sid);
>>  	return 0;
>>  }
>>
>> +static int arm_smmu_init_dummy_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
>> +{
>> +	static struct arm_smmu_strtab_l1_desc dummy_desc;
>> +
>> +	return __arm_smmu_init_l2_strtab(smmu, sid, &dummy_desc);
>> +}
>> +
>>  /* IRQ and event handlers */
>>  static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
>>  {
>> @@ -2150,8 +2172,12 @@ static int arm_smmu_init_l1_strtab(struct arm_smmu_device *smmu)
>>  	}
>>
>>  	for (i = 0; i < cfg->num_l1_ents; ++i) {
>> -		arm_smmu_write_strtab_l1_desc(strtab, &cfg->l1_desc[i]);
>> -		strtab += STRTAB_L1_DESC_DWORDS << 3;
>> +		if (is_kdump_kernel()) {
>> +			arm_smmu_init_dummy_l2_strtab(smmu, i << STRTAB_SPLIT);
>> +		} else {
>> +			arm_smmu_write_strtab_l1_desc(strtab, &cfg->l1_desc[i]);
>> +			strtab += STRTAB_L1_DESC_DWORDS << 3;
>> +		}
>>  	}
>>
>>  	return 0;
>> @@ -2467,11 +2493,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
>>  	/* Clear CR0 and sync (disables SMMU and queue processing) */
>>  	reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
>>  	if (reg & CR0_SMMUEN) {
>> -		if (is_kdump_kernel()) {
>> +		if (is_kdump_kernel())
>>  			arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0);
>> -			arm_smmu_device_disable(smmu);
>> -			return -EBUSY;
>> -		}
>>
>>  		dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n");
>>  	}
>> @@ -2859,6 +2882,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>>  	struct device *dev = &pdev->dev;
>>  	bool bypass;
>>
>> +	/*
>> +	 * Force to disable bypass for the kdump kernel, abort all incoming
>> +	 * transactions from the unknown devices.
>> +	 */
>> +	if (is_kdump_kernel())
>> +		disable_bypass = 1;
>> +
>>  	smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
>>  	if (!smmu) {
>>  		dev_err(dev, "failed to allocate arm_smmu_device\n");
>> --
>> 1.8.3
>>
>>
>>
>> .
>>
> 

-- 
Thanks!
BestRegards

[-- Attachment #2: kdump_smmu.png --]
[-- Type: image/png, Size: 47852 bytes --]

WARNING: multiple messages have this Message-ID (diff)
From: "Leizhen (ThunderTown)" <thunder.leizhen@huawei.com>
To: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>,
	Robin Murphy <robin.murphy@arm.com>,
	Will Deacon <will.deacon@arm.com>, Joerg Roedel <joro@8bytes.org>,
	linux-arm-kernel <linux-arm-kernel@lists.infradead.org>,
	iommu <iommu@lists.linux-foundation.org>,
	linux-kernel <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 2/5] iommu/arm-smmu-v3: make smmu can be enabled in kdump kernel
Date: Fri, 1 Mar 2019 17:18:57 +0800	[thread overview]
Message-ID: <5C78F901.703@huawei.com> (raw)
In-Reply-To: <5C78F535.4030105@huawei.com>

[-- Attachment #1: Type: text/plain, Size: 6110 bytes --]

It seems that the picture is too big, I change it from jpg to png.


On 2019/3/1 17:02, Leizhen (ThunderTown) wrote:
> Hi All,
>     I drew a flowchart, hope this can help you to understand my method.
> 
> On 2019/2/19 15:54, Zhen Lei wrote:
>> To reduce the risk of further crash, the device_shutdown() was not called
>> by the first kernel. That means some devices may still working in the
>> secondary kernel. For example, a netcard may still using ring buffer to
>> receive the broadcast messages in the kdump kernel. No events are reported
>> utill the related smmu reinitialized by the kdump kernel.
>>
>> commit b63b3439b856 ("iommu/arm-smmu-v3: Abort all transactions if SMMU is
>> enabled in kdump kernel") set SMMU_GBPA.ABORT to prevent the unexpected
>> devices accessing, but it also prevent the devices accessing which we
>> needed, like hard disk, netcard.
>>
>> In fact, we can use STE.config=0b000 to abort the unexpected devices
>> accessing only. As below:
>> 1. In the first kernel, all buffers used by the "unexpected" devices are
>>    correctly mapped, and it will not be used by the secondary kernel
>>    because the latter has its dedicated reserved memory.
>> 2. In the secondary kernel, set SMMU_GBPA.ABORT=1 before "disable smmu".
>> 3. In the secondary kernel, after the smmu was disabled, preset all
>>    STE.config=0b000. For 2-level Stream Table, make all L1STD.l2ptr
>>    pointer to a dummy L2ST. The dummy L2ST is shared by all L1STDs.
>> 4. In the secondary kernel, enable smmu. For the needed devices, allocate
>>    new L2STs accordingly.
>>
>> For phase 1 and 2, the unexpected devices base the old mapping access
>> memory, it will not corrupt others. For phase 3, SMMU_GBPA abort it. For
>> phase 4 STE abort it.
>>
>> Fixes: commit b63b3439b856 ("iommu/arm-smmu-v3: Abort all transactions ...")
>> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
>> ---
>>  drivers/iommu/arm-smmu-v3.c | 72 ++++++++++++++++++++++++++++++++-------------
>>  1 file changed, 51 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
>> index 2072897..c3c4ff2 100644
>> --- a/drivers/iommu/arm-smmu-v3.c
>> +++ b/drivers/iommu/arm-smmu-v3.c
>> @@ -1219,35 +1219,57 @@ static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent)
>>  	}
>>  }
>>
>> -static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
>> +static int __arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid,
>> +				     struct arm_smmu_strtab_l1_desc *desc)
>>  {
>> -	size_t size;
>>  	void *strtab;
>>  	struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
>> -	struct arm_smmu_strtab_l1_desc *desc = &cfg->l1_desc[sid >> STRTAB_SPLIT];
>>
>> -	if (desc->l2ptr)
>> -		return 0;
>> -
>> -	size = 1 << (STRTAB_SPLIT + ilog2(STRTAB_STE_DWORDS) + 3);
>>  	strtab = &cfg->strtab[(sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS];
>>
>> -	desc->span = STRTAB_SPLIT + 1;
>> -	desc->l2ptr = dmam_alloc_coherent(smmu->dev, size, &desc->l2ptr_dma,
>> -					  GFP_KERNEL | __GFP_ZERO);
>>  	if (!desc->l2ptr) {
>> -		dev_err(smmu->dev,
>> -			"failed to allocate l2 stream table for SID %u\n",
>> -			sid);
>> -		return -ENOMEM;
>> +		size_t size;
>> +
>> +		size = 1 << (STRTAB_SPLIT + ilog2(STRTAB_STE_DWORDS) + 3);
>> +		desc->l2ptr = dmam_alloc_coherent(smmu->dev, size,
>> +						  &desc->l2ptr_dma,
>> +						  GFP_KERNEL | __GFP_ZERO);
>> +		if (!desc->l2ptr) {
>> +			dev_err(smmu->dev,
>> +				"failed to allocate l2 stream table for SID %u\n",
>> +				sid);
>> +			return -ENOMEM;
>> +		}
>> +
>> +		desc->span = STRTAB_SPLIT + 1;
>> +		arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
>>  	}
>>
>> -	arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
>>  	arm_smmu_write_strtab_l1_desc(strtab, desc);
>> +	return 0;
>> +}
>> +
>> +static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
>> +{
>> +	int ret;
>> +	struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
>> +	struct arm_smmu_strtab_l1_desc *desc = &cfg->l1_desc[sid >> STRTAB_SPLIT];
>> +
>> +	ret = __arm_smmu_init_l2_strtab(smmu, sid, desc);
>> +	if (ret)
>> +		return ret;
>> +
>>  	arm_smmu_sync_std_for_sid(smmu, sid);
>>  	return 0;
>>  }
>>
>> +static int arm_smmu_init_dummy_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
>> +{
>> +	static struct arm_smmu_strtab_l1_desc dummy_desc;
>> +
>> +	return __arm_smmu_init_l2_strtab(smmu, sid, &dummy_desc);
>> +}
>> +
>>  /* IRQ and event handlers */
>>  static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
>>  {
>> @@ -2150,8 +2172,12 @@ static int arm_smmu_init_l1_strtab(struct arm_smmu_device *smmu)
>>  	}
>>
>>  	for (i = 0; i < cfg->num_l1_ents; ++i) {
>> -		arm_smmu_write_strtab_l1_desc(strtab, &cfg->l1_desc[i]);
>> -		strtab += STRTAB_L1_DESC_DWORDS << 3;
>> +		if (is_kdump_kernel()) {
>> +			arm_smmu_init_dummy_l2_strtab(smmu, i << STRTAB_SPLIT);
>> +		} else {
>> +			arm_smmu_write_strtab_l1_desc(strtab, &cfg->l1_desc[i]);
>> +			strtab += STRTAB_L1_DESC_DWORDS << 3;
>> +		}
>>  	}
>>
>>  	return 0;
>> @@ -2467,11 +2493,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
>>  	/* Clear CR0 and sync (disables SMMU and queue processing) */
>>  	reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
>>  	if (reg & CR0_SMMUEN) {
>> -		if (is_kdump_kernel()) {
>> +		if (is_kdump_kernel())
>>  			arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0);
>> -			arm_smmu_device_disable(smmu);
>> -			return -EBUSY;
>> -		}
>>
>>  		dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n");
>>  	}
>> @@ -2859,6 +2882,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>>  	struct device *dev = &pdev->dev;
>>  	bool bypass;
>>
>> +	/*
>> +	 * Force to disable bypass for the kdump kernel, abort all incoming
>> +	 * transactions from the unknown devices.
>> +	 */
>> +	if (is_kdump_kernel())
>> +		disable_bypass = 1;
>> +
>>  	smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
>>  	if (!smmu) {
>>  		dev_err(dev, "failed to allocate arm_smmu_device\n");
>> --
>> 1.8.3
>>
>>
>>
>> .
>>
> 

-- 
Thanks!
BestRegards

[-- Attachment #2: kdump_smmu.png --]
[-- Type: image/png, Size: 47852 bytes --]

[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2019-03-01  9:19 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-19  7:54 [PATCH 0/5] iommu/arm-smmu-v3: make smmu can be enabled in kdump kernel Zhen Lei
2019-02-19  7:54 ` Zhen Lei
2019-02-19  7:54 ` [PATCH 1/5] iommu/arm-smmu-v3: make sure the stale caching of L1STD are invalid Zhen Lei
2019-02-19  7:54   ` Zhen Lei
2019-02-19  7:54   ` Zhen Lei
2019-02-19  7:54 ` [PATCH 2/5] iommu/arm-smmu-v3: make smmu can be enabled in kdump kernel Zhen Lei
2019-02-19  7:54   ` Zhen Lei
2019-03-01  9:02   ` Leizhen (ThunderTown)
2019-03-01  9:18     ` Leizhen (ThunderTown) [this message]
2019-03-01  9:18       ` Leizhen (ThunderTown)
2019-02-19  7:54 ` [PATCH 3/5] iommu/arm-smmu-v3: add macro xxx_SIZE to replace xxx_DWORDS shift Zhen Lei
2019-02-19  7:54   ` Zhen Lei
2019-02-19  7:54 ` [PATCH 4/5] iommu/arm-smmu-v3: move arm_smmu_get_step_for_sid() a little ahead Zhen Lei
2019-02-19  7:54   ` Zhen Lei
2019-02-19  7:54 ` [PATCH 5/5] iommu/arm-smmu-v3: workaround for STE abort in kdump kernel Zhen Lei
2019-02-19  7:54   ` Zhen Lei
2019-02-27  3:25 ` [PATCH 0/5] iommu/arm-smmu-v3: make smmu can be enabled " Leizhen (ThunderTown)
2019-02-27  3:25   ` Leizhen (ThunderTown)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5C78F901.703@huawei.com \
    --to=thunder.leizhen@huawei.com \
    --cc=iommu@lists.linux-foundation.org \
    --cc=jean-philippe.brucker@arm.com \
    --cc=joro@8bytes.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=will.deacon@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.