lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:	Tue, 07 Apr 2015 22:53:49 +0800
From:	Jiang Liu <jiang.liu@...ux.intel.com>
To:	"Rafael J. Wysocki" <rjw@...ysocki.net>
CC:	Bjorn Helgaas <bhelgaas@...gle.com>,
	Thomas Gleixner <tglx@...utronix.de>,
	Ingo Molnar <mingo@...hat.com>,
	"H. Peter Anvin" <hpa@...or.com>, x86@...nel.org,
	Len Brown <lenb@...nel.org>, Lv Zheng <lv.zheng@...el.com>,
	LKML <linux-kernel@...r.kernel.org>, linux-pci@...r.kernel.org,
	linux-acpi@...r.kernel.org
Subject: Re: [Bugfix v4] x86/PCI/ACPI: Fix regression caused by commit 63f1789ec716

On 2015/4/7 19:47, Rafael J. Wysocki wrote:
> On Tuesday, April 07, 2015 12:30:18 PM Jiang Liu wrote:
>> Before commit 593669c2ac0f("Use common ACPI resource interfaces to
>> simplify implementation"), arch/x86/pci/acpi.c applies following
>> rules when parsing ACPI resources for PCI host bridge:
>> 1) Ignore IO port resources defined by acpi_resource_io and
>>    acpi_resource_fixed_io, which should be used to define resource
>>    for PCI device instead of PCI bridge.
>> 2) Accept IOMEM resource defined by acpi_resource_memory24,
>>    acpi_resource_memory32 and acpi_resource_fixed_memory32.
>>    These IOMEM resources are accepted to workaround some BIOS issue,
>>    though they should be ignored. For example, PC Engines APU.1C
>>    platform defines PCI host bridge IOMEM resources as:
>>                 Memory32Fixed (ReadOnly,
>>                     0x000A0000,         // Address Base
>>                     0x00020000,         // Address Length
>>                     )
>>                 Memory32Fixed (ReadOnly,
>>                     0x00000000,         // Address Base
>>                     0x00000000,         // Address Length
>>                     _Y00)
>> 3) Accept all IO port and IOMEM resources defined by
>>    acpi_resource_address{16,32,64,extended64}, no matter it's marked as
>>    ACPI_CONSUMER or ACPI_PRODUCER.
>>
>> Commit 593669c2ac0f("Use common ACPI resource interfaces to
>> simplify implementation") accept all IO port and IOMEM resources
>> defined by acpi_resource_io, acpi_resource_fixed_io,
>> acpi_resource_memory24, acpi_resource_memory32,
>> acpi_resource_fixed_memory32 and
>> acpi_resource_address{16,32,64,extended64}, which causes IO port
>> resources consumed by host bridge itself are listed in to host bridge
>> resource list.
>>
>> Then commit 63f1789ec716("Ignore resources consumed by host bridge
>> itself") ignores resources consumed by host bridge itself by checking
>> IORESOURCE_WINDOW flag, which accidently removed the workaround in 2)
>> above for BIOS bug .
>>
>> It's really costed us much time to figure out this whole picture.
>> So we refine interface acpi_dev_filter_resource_type as below,
>> which should be easier for maintence:
>> 1) Caller specifies IORESOURCE_WINDOW flag to explicitly query resource
>>    for bridge(PRODUCER), otherwise it's querying resource for
>>    device(CONSUMER).
>> 2) Ignore IO port resources defined by acpi_resource_io and
>>    acpi_resource_fixed_io if IORESOURCE_WINDOW is specified.
>> 3) Accpet IOMEM resource defined by acpi_resource_memory24,
>>    acpi_resource_memory32 and acpi_resource_fixed_memory32 if both
>>    IORESOURCE_WINDOW and IORESOURCE_MEM_8AND16BIT are specified to work
>>    around BIOS issues.
>> 4) Accept IO port and IOMEM defined by acpi_resource_addressxx if
>>    a) IORESOURCE_WINDOW is specified and ACPI_PRODUCER is true
>>    b) IORESOURCE_WINDOW is not specified and ACPI_PRODUCER is false
>>
>> Currently acpi_dev_filter_resource_type() is only used by ACPI pci
>> host bridge and IOAPIC driver, so it shouldn't affect other drivers.
>>
>> Another possible fix is to only ignore IO resource consumed by host
>> bridge and keep IOMEM resource consumed by host bridge, please refer to:
>> http://www.spinics.net/lists/linux-pci/msg39706.html
>>
>> Sample ACPI table are archived at:
>> https://bugzilla.kernel.org/show_bug.cgi?id=94221
>>
>> V3->V4:
>> 1) Improve comments
>> 2) Use flag IORESOURCE_MEM_8AND16BIT to work around BIOS issue
> 
> OK, so how does that address the comments in the previous thread?
> 
> It would *really* help if you responded there instead of starting a new
> thread by sending a new patch version.  This makes it really difficult to
> follow the entire discussion, which is part of why we keep forgetting things.
Hi Rafael,
	Apologize:) I miss understood previous mail. Please ignore
this version.
Regards!
Gerry

> 
>> Fixes: 63f1789ec716("Ignore resources consumed by host bridge itself")
>> Reported-and-Tested-by: Bernhard Thaler <bernhard.thaler@...et.at>
>> Signed-off-by: Jiang Liu <jiang.liu@...ux.intel.com>
>> ---
>>  arch/x86/pci/acpi.c     |    8 +++++---
>>  drivers/acpi/resource.c |   52 +++++++++++++++++++++++++++++++++++++++++------
>>  2 files changed, 51 insertions(+), 9 deletions(-)
>>
>> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
>> index e4695985f9de..150774be0f3f 100644
>> --- a/arch/x86/pci/acpi.c
>> +++ b/arch/x86/pci/acpi.c
>> @@ -332,12 +332,15 @@ static void probe_pci_root_info(struct pci_root_info *info,
>>  {
>>  	int ret;
>>  	struct resource_entry *entry, *tmp;
>> +	unsigned long res_flags;
>>  
>>  	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
>>  	info->bridge = device;
>> +	res_flags = IORESOURCE_IO | IORESOURCE_MEM |
>> +		    IORESOURCE_WINDOW | IORESOURCE_MEM_8AND16BIT;
>>  	ret = acpi_dev_get_resources(device, list,
>>  				     acpi_dev_filter_resource_type_cb,
>> -				     (void *)(IORESOURCE_IO | IORESOURCE_MEM));
>> +				     (void *)res_flags);
>>  	if (ret < 0)
>>  		dev_warn(&device->dev,
>>  			 "failed to parse _CRS method, error code %d\n", ret);
>> @@ -346,8 +349,7 @@ static void probe_pci_root_info(struct pci_root_info *info,
>>  			"no IO and memory resources present in _CRS\n");
>>  	else
>>  		resource_list_for_each_entry_safe(entry, tmp, list) {
>> -			if ((entry->res->flags & IORESOURCE_WINDOW) == 0 ||
>> -			    (entry->res->flags & IORESOURCE_DISABLED))
>> +			if (entry->res->flags & IORESOURCE_DISABLED)
>>  				resource_list_destroy_entry(entry);
>>  			else
>>  				entry->res->name = info->name;
>> diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
>> index 5589a6e2a023..0187e0e11bb8 100644
>> --- a/drivers/acpi/resource.c
>> +++ b/drivers/acpi/resource.c
>> @@ -567,6 +567,12 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
>>  }
>>  EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
>>  
>> +static bool acpi_dev_match_producer_consumer(unsigned long types, int producer)
>> +{
>> +	return ((types & IORESOURCE_WINDOW) && producer == ACPI_PRODUCER) ||
>> +		((types & IORESOURCE_WINDOW) == 0 && producer == ACPI_CONSUMER);
>> +}
>> +
>>  /**
>>   * acpi_dev_filter_resource_type - Filter ACPI resource according to resource
>>   *				   types
>> @@ -574,7 +580,19 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
>>   * @types: Valid resource types of IORESOURCE_XXX
>>   *
>>   * This is a hepler function to support acpi_dev_get_resources(), which filters
>> - * ACPI resource objects according to resource types.
>> + * ACPI resource objects according to resource types and flags as below:
>> + * 1) If flag IORESOURCE_WINDOW is not specified, it's querying resources
>> + *    consumed by device. That is to return:
>> + * 	a) ACPI resources without producer_consumer flag
>> + *	b) ACPI resources with producer_consumer flag setting to CONSUMER.
> 
> OK, so what if the resource is not of an "extended" type, say DWORD address space,
> but has a non-empty Resource Source field pointing to the device itself?
> 
> Shouldn't we treat that device as a "producer" too?
> 
>> + * 2) If flag IORESOURCE_WINDOW is specified, it's querying resources provided
>> + *    by device. That is to return:
>> + *	a) ACPI resources with producer_consumer flag setting to PRODUCER.
>> + * 3) But there's an exception. Some platforms, such as PC Engines APU.1C,
>> + *    report PCI host bridge resource provision by Memory32Fixed().
>> + *    Please refer to https://bugzilla.kernel.org/show_bug.cgi?id=94221
>> + *    So a special flag IORESOURCE_MEM_8AND16BIT is used to work around this
>> + *    BIOS issue.
> 
> This is a legitimate thing for the BIOS to do if my reading of the spec is
> correct, as the "producer" thing really is supposed to mean "this resource
> comes from the device itself".
> 
>>   */
>>  int acpi_dev_filter_resource_type(struct acpi_resource *ares,
>>  				  unsigned long types)
>> @@ -585,27 +603,49 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares,
>>  	case ACPI_RESOURCE_TYPE_MEMORY24:
>>  	case ACPI_RESOURCE_TYPE_MEMORY32:
>>  	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
>> -		type = IORESOURCE_MEM;
>> +		/*
>> +		 * These types of resource descriptor should be used to
>> +		 * describe resource consumption instead of resource provision.
>> +		 * But some platforms, such as PC Engines APU.1C, report
>> +		 * resource provision by Memory32Fixed(). Please refer to:
>> +		 * https://bugzilla.kernel.org/show_bug.cgi?id=94221
>> +		 * So a special rule to work around BIOS issues.
>> +		 */
>> +		if ((types & (IORESOURCE_WINDOW | IORESOURCE_MEM_8AND16BIT)) ==
>> +		    (IORESOURCE_WINDOW | IORESOURCE_MEM_8AND16BIT) ||
>> +		    acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +			type = IORESOURCE_MEM;
>>  		break;
>>  	case ACPI_RESOURCE_TYPE_IO:
>>  	case ACPI_RESOURCE_TYPE_FIXED_IO:
>> -		type = IORESOURCE_IO;
>> +		if (acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +			type = IORESOURCE_IO;
>>  		break;
>>  	case ACPI_RESOURCE_TYPE_IRQ:
>> +		if (acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +			type = IORESOURCE_IRQ;
>> +		break;
>>  	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
>> -		type = IORESOURCE_IRQ;
>> +		if (acpi_dev_match_producer_consumer(types,
>> +				ares->data.extended_irq.producer_consumer))
>> +			type = IORESOURCE_IRQ;
>>  		break;
>>  	case ACPI_RESOURCE_TYPE_DMA:
>>  	case ACPI_RESOURCE_TYPE_FIXED_DMA:
>> -		type = IORESOURCE_DMA;
>> +		if (acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +			type = IORESOURCE_DMA;
>>  		break;
>>  	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
>> -		type = IORESOURCE_REG;
>> +		if (acpi_dev_match_producer_consumer(types, ACPI_CONSUMER))
>> +			type = IORESOURCE_REG;
>>  		break;
>>  	case ACPI_RESOURCE_TYPE_ADDRESS16:
>>  	case ACPI_RESOURCE_TYPE_ADDRESS32:
>>  	case ACPI_RESOURCE_TYPE_ADDRESS64:
>>  	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
>> +		if (!acpi_dev_match_producer_consumer(types,
>> +				ares->data.address.producer_consumer))
>> +			break;
>>  		if (ares->data.address.resource_type == ACPI_MEMORY_RANGE)
>>  			type = IORESOURCE_MEM;
>>  		else if (ares->data.address.resource_type == ACPI_IO_RANGE)
>>
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ