[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH RFC 2/2] AMD IOMMU: allow command line overrides for broken IVRS tables



Tuesday, August 27, 2013, 11:52:36 AM, you wrote:


> Tuesday, August 27, 2013, 10:05:41 AM, you wrote:

>> With there being so many systems with broken ACPI tables, and with it
>> generally being known what's wrong with those tables, give people a
>> handle to overcome the resulting disabling of their IOMMUs.

>> Inspired by Linux side patches providing similar functionality.

>> TODO: documentation

> Hi Jan,

> Would the syntax be the same as linux ?
> f.e. ivrs_ioapic[6]=00:14.0 for my case ?

> I'm asking because using it on the command line seems to enable the iommu 
> fine (which it shouldn't without the override), but i don't seem to see the
> "IVHD: Command line override present for IO-APIC %#x" in my xl dmesg... 

Hrrrmm could it be due to the fact that in my case it actually shouldn't 
override a present IVRS entry, but add a extra one ?


> --
> Sander


>> Suggested-by: Sander Eikelenboom <linux@xxxxxxxxxxxxxx>
>> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

>> --- a/xen/common/kernel.c
>> +++ b/xen/common/kernel.c
>> @@ -81,9 +81,15 @@ void __init cmdline_parse(const char *cm
>>          /* Search for value part of a key=value option. */
>>          optval = strchr(opt, '=');
>>          if ( optval != NULL )
>> +        {
>>              *optval++ = '\0'; /* nul-terminate the option value */
>> +            q = strpbrk(opt, "([{<");
>> +        }
>>          else
>> +        {
>>              optval = q;       /* default option value is empty string */
>> +            q = NULL;
>> +        }
>>  
>>          /* Boolean parameters can be inverted with 'no-' prefix. */
>>          bool_assert = !!strncmp("no-", optkey, 3);
>> @@ -93,7 +99,17 @@ void __init cmdline_parse(const char *cm
>>          for ( param = &__setup_start; param < &__setup_end; param++ )
>>          {
>>              if ( strcmp(param->name, optkey) )
>> +            {
>> +                if ( param->type == OPT_CUSTOM && q &&
>> +                     strlen(param->name) == q + 1 - opt &&
>> +                     !strncmp(param->name, opt, q + 1 - opt) )
>> +                {
>> +                    optval[-1] = '=';
>> +                    ((void (*)(const char *))param->var)(q);
>> +                    optval[-1] = '\0';
>> +                }
>>                  continue;
>> +            }
>>  
>>              switch ( param->type )
>>              {
>> --- a/xen/drivers/passthrough/amd/iommu_acpi.c
>> +++ b/xen/drivers/passthrough/amd/iommu_acpi.c
>> @@ -633,6 +633,50 @@ static u16 __init parse_ivhd_device_exte
>>      return dev_length;
>>  }
>>  
>> +static __initdata DECLARE_BITMAP(ioapic_cmdline, ARRAY_SIZE(ioapic_sbdf));
>> +
>> +static void __init parse_ivrs_ioapic(char *str)
>> +{
>> +    const char *s = str;
>> +    unsigned long id;
>> +    unsigned int seg, bus, dev, func;
>> +
>> +    ASSERT(*s == '[');
>> +    id = simple_strtoul(s + 1, &s, 0);
+    if ( id >>>= ARRAY_SIZE(ioapic_sbdf) || *s != ']' || *++s != '=' )
>> +        return;
>> +
>> +    s = parse_pci(s + 1, &seg, &bus, &dev, &func);
>> +    if ( !s || *s )
>> +        return;
>> +
>> +    ioapic_sbdf[id].bdf = PCI_BDF(bus, dev, func);
>> +    ioapic_sbdf[id].seg = seg;
>> +    __set_bit(id, ioapic_cmdline);
>> +}
>> +custom_param("ivrs_ioapic[", parse_ivrs_ioapic);
>> +
>> +static void __init parse_ivrs_hpet(char *str)
>> +{
>> +    const char *s = str;
>> +    unsigned long id;
>> +    unsigned int seg, bus, dev, func;
>> +
>> +    ASSERT(*s == '[');
>> +    id = simple_strtoul(s + 1, &s, 0);
>> +    if ( id != (typeof(hpet_sbdf.id))id || *s != ']' || *++s != '=' )
>> +        return;
>> +
>> +    s = parse_pci(s + 1, &seg, &bus, &dev, &func);
>> +    if ( !s || *s )
>> +        return;
>> +
>> +    hpet_sbdf.bdf = PCI_BDF(bus, dev, func);
>> +    hpet_sbdf.seg = seg;
>> +    hpet_sbdf.cmdline = 1;
>> +}
>> +custom_param("ivrs_hpet[", parse_ivrs_hpet);
>> +
>>  static u16 __init parse_ivhd_device_special(
>>      const struct acpi_ivrs_device8c *special, u16 seg,
>>      u16 header_length, u16 block_length, struct amd_iommu *iommu)
>> @@ -674,7 +718,17 @@ static u16 __init parse_ivhd_device_spec
>>              if ( IO_APIC_ID(apic) != special->handle )
>>                  continue;
>>  
>> -            if ( ioapic_sbdf[special->handle].pin_2_idx )
>> +            if ( special->handle >= ARRAY_SIZE(ioapic_sbdf) )
>> +            {
>> +                printk(XENLOG_ERR "IVHD Error: IO-APIC %#x entry beyond 
>> bounds\n",
>> +                       special->handle);
>> +                return 0;
>> +            }
>> +
>> +            if ( test_bit(special->handle, ioapic_cmdline) )
>> +                AMD_IOMMU_DEBUG("IVHD: Command line override present for 
>> IO-APIC %#x\n",
>> +                                special->handle);
>> +            else if ( ioapic_sbdf[special->handle].pin_2_idx )
>>              {
>>                  if ( ioapic_sbdf[special->handle].bdf == bdf &&
>>                       ioapic_sbdf[special->handle].seg == seg )
>> @@ -717,14 +771,18 @@ static u16 __init parse_ivhd_device_spec
>>          break;
>>      case ACPI_IVHD_HPET:
>>          /* set device id of hpet */
>> -        if ( hpet_sbdf.iommu )
>> +        if ( hpet_sbdf.iommu ||
>> +             (hpet_sbdf.cmdline && hpet_sbdf.id != special->handle) )
>>          {
>>              printk(XENLOG_WARNING "Only one IVHD HPET entry is 
>> supported\n");
>>              break;
>>          }
>>          hpet_sbdf.id = special->handle;
>> -        hpet_sbdf.bdf = bdf;
>> -        hpet_sbdf.seg = seg;
>> +        if ( !hpet_sbdf.cmdline )
>> +        {
>> +            hpet_sbdf.bdf = bdf;
>> +            hpet_sbdf.seg = seg;
>> +        }
>>          hpet_sbdf.iommu = iommu;
>>          break;
>>      default:
>> @@ -935,21 +993,23 @@ static int __init parse_ivrs_table(struc
>>               ioapic_sbdf[IO_APIC_ID(apic)].pin_2_idx )
>>              continue;
>>  
>> -        printk(XENLOG_ERR "IVHD Error: no information for IO-APIC %#x\n",
>> -               IO_APIC_ID(apic));
>> -        if ( amd_iommu_perdev_intremap )
>> -            error = -ENXIO;
>> -        else
>> +        if ( !test_bit(IO_APIC_ID(apic), ioapic_cmdline) )
>>          {
>> -            ioapic_sbdf[IO_APIC_ID(apic)].pin_2_idx = xmalloc_array(
>> -                u16, nr_ioapic_entries[apic]);
>> -            if ( !ioapic_sbdf[IO_APIC_ID(apic)].pin_2_idx )
>> -            {
>> -                printk(XENLOG_ERR "IVHD Error: Out of memory\n");
>> -                error = -ENOMEM;
>> -            }
>> +            printk(XENLOG_ERR "IVHD Error: no information for IO-APIC 
>> %#x\n",
>> +                   IO_APIC_ID(apic));
>> +            if ( amd_iommu_perdev_intremap )
>> +                return -ENXIO;
>> +        }
>> +
>> +        ioapic_sbdf[IO_APIC_ID(apic)].pin_2_idx = xmalloc_array(
>> +            u16, nr_ioapic_entries[apic]);
>> +        if ( ioapic_sbdf[IO_APIC_ID(apic)].pin_2_idx )
>>              memset(ioapic_sbdf[IO_APIC_ID(apic)].pin_2_idx, -1,
>>                     nr_ioapic_entries[apic] * 
>> sizeof(*ioapic_sbdf->pin_2_idx));
>> +        else
>> +        {
>> +            printk(XENLOG_ERR "IVHD Error: Out of memory\n");
>> +            error = -ENOMEM;
>>          }
>>      }
>>  
>> --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
>> +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
>> @@ -108,6 +108,7 @@ extern struct ioapic_sbdf {
>>  
>>  extern struct hpet_sbdf {
>>      u16 bdf, seg, id;
>> +    bool_t cmdline;
>>      struct amd_iommu *iommu;
>>  } hpet_sbdf;
>>  







_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.